如何在Rails语言环境文件中更改插值变量的大小写?

时间:2012-03-10 00:46:46

标签: ruby-on-rails-3.1 internationalization

使用Rails 3.1.3和Ruby 1.9.3p0。

我发现默认情况下,Rails不会对表单按钮使用句子大小写。例如,它不是“更新用户”按钮,而是生成“更新用户”按钮。

按钮名称来自ActionView locale file。有没有办法创建一个下调模型名称的默认值?这不在Interpolation的Ruby on Rails Guides i18n部分中介绍,所以也许这是不可能的。以下不起作用:

en:
  helpers:
    submit:
      update: 'Update %{model}.downcase'

通常,我很乐意找到语言环境YAML文件语法的参考。 i18n指南涵盖了一些语法,但是查找所有感叹号,各种日期/时间格式等文档会很有帮助。或者我可能为此使用Ruby Hash而不是YAML文件? / p>

2 个答案:

答案 0 :(得分:9)

经过进一步的研究,我得出结论,这种对插值的操作是不可能的,至少使用YAML语言环境文件。

此处记录了YAML,不支持字符串操作:
http://www.yaml.org/spec/1.2/spec.html

Ruby本地化的主页在这里:
http://ruby-i18n.org/wiki

从那里,我们找到默认I18n gem的代码并深入到插值代码。它使用sprintf进行插值:
https://github.com/svenfuchs/i18n/blob/master/lib/i18n/interpolate/ruby.rb

该代码“严重基于Masao Mutoh的gettext字符串插值扩展”:
http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb

该扩展程序有一个格式化数字的示例:

For strings.
"%{firstname}, %{familyname}" % {:firstname => "Masao", :familyname => "Mutoh"}

With field type to specify format such as d(decimal), f(float),...
"%<age>d, %<weight>.1f" % {:age => 10, :weight => 43.4}

扩展名引用[Ruby]“Kernel::sprintf以获取格式字符串”的详细信息: http://www.ruby-doc.org/core-1.9.2/Kernel.html#method-i-sprintf

sprintf上的文档中,有很多方法可以格式化数字,但没有更改字符串大小写的操作。

答案 1 :(得分:1)

我通过更改I18n插值解决了这个问题。将以下代码放在初始化程序目录中:

module I18n
  # Implemented to support method call on translation keys
  INTERPOLATION_WITH_METHOD_PATTERN = Regexp.union(
    /%%/,
    /%\{(\w+)\}/,                               # matches placeholders like "%{foo}"
    /%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/, # matches placeholders like "%<foo>.d"
    /%\{(\w+)\.(\w+)\}/,                          # matches placeholders like "%{foo.upcase}"
  )

  class << self
    def interpolate_hash(string, values)
      string.gsub(INTERPOLATION_WITH_METHOD_PATTERN) do |match|
        if match == '%%'
          '%'
        else
          key = ($1 || $2 || $4).to_sym
          value = values.key?(key) ? values[key] : raise(MissingInterpolationArgument.new(values, string))
          value = value.call(values) if value.respond_to?(:call)
          $3 ? sprintf("%#{$3}", value) : ( $5 ? value.send($5) : value) 
        end
      end
    end
  end
end

现在,您可以在语言环境文件中执行此操作:

create: 'Opprett %{model.downcase}'

并测试它:

require 'test_helper'

class I18nTest < ActiveSupport::TestCase

  should 'interpolate as usual' do
    assert_equal 'Show Customer', I18n.interpolate("Show %{model}", model: 'Customer')
  end

  should 'interpolate with number formatting' do
    assert_equal 'Show many 100', I18n.interpolate("Show many %<kr>2d", kr: 100)
    assert_equal 'Show many abc', I18n.interpolate("Show many %<str>3.3s", str: 'abcde')
  end

  should 'support method execution' do
    assert_equal 'Show customer', I18n.interpolate("Show %{model.downcase}", model: 'Customer')
  end

end