I18n:我怎样才能防止空插值参数?

时间:2015-07-02 17:59:43

标签: ruby internationalization

给出以下i18n密钥:

greeting: "Hi %{name}! Feeling %{adjective}?"

如果我致电I18n.t!("greeting", adjective: "strigine"),我会收到例外:I18n::MissingInterpolationArgument。这很好。

但是,如果我根本没有传递任何参数,我只需要获取原始字符串。

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

我想确保不会发生这种情况。 如果没有给出参数,是否会引发此方法调用的版本,或者我是否必须自己编写代码?

1 个答案:

答案 0 :(得分:0)

I18n故意这样做

原因是documented in the tests如下:

  

如果没有给出插值参数,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