I18n: 如何防止空的插值参数?

4
给定以下i18n键:
greeting: "Hi %{name}! Feeling %{adjective}?"

如果我调用I18n.t!("greeting", adjective: "strigine"),我会得到一个异常:I18n::MissingInterpolationArgument。这是好的。

但是,如果我根本不传递任何参数,我只会得到原始字符串。

I18n.t!("greeting") # => "Hi %{name}! Feeling %{adjective}?"

我希望确保这种情况不会发生。 是否有一种版本的该方法调用,如果没有参数,则会引发异常,或者我必须自己编写代码?

1个回答

3

I18n故意这样做

其原因在测试文档中进行了记录,如下:

如果没有提供插值参数,I18n就不应改变字符串。这种行为有三个原因:

  • 检查所有字符串中的插值键会影响性能,严重拖慢速度;
  • 这使我们可以通过I18n检索未被修改的值。例如,我可以编写一个中间件,将I18n查找结果以JSON格式返回,然后在JavaScript中进行处理。保留键不受影响允许插值在JavaScript层次进行;
  • 安全方面的考虑:如果允许用户翻译网站,他们可以在消息中插入%{},从而导致每个请求中的I18n查找失败。

如何绕过这个问题

如果您希望在这种情况下出现异常,可以定义一个像这样的方法:

  # Needed because I18n will happily return the raw template string if given
  # no interpolation arguments
  # https://github.com/svenfuchs/i18n/blob/v0.7.0/lib/i18n/tests/interpolation.rb#L6-L21
  def i18n_strict_t!(key, options = {})
    localized = I18n.t!(key, options)
    if missing = localized.match(I18n::INTERPOLATION_PATTERN)
      fail I18n::MissingInterpolationArgument.new(
        missing.captures.first, options, localized
      )
    end
    localized
  end

使用方法:

i18n_strict_t!("greeting")
# => I18n::MissingInterpolationArgument: missing
# interpolation argument "name" in
# "Hi %{name}! Feeling %{adjective}?" ({} given)
i18n_strict_t!("greeting", name: "Carla", adjective: "taciturn")
# => "Hi Carla! Feeling taciturn?"

如果要实现较慢但更简单的方法:

def i18n_strict_t!(key, options = {})
  options[:force_interpolation] = true if options.empty?
  I18n.t!(key, options)
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接