Как изменить регистр интерполированных переменных в Rails файле локали?

Использование Rails 3.1.3 с Ruby 1.9.3p0.

Я обнаружил, что по умолчанию Rails не использует случай предложения для кнопок формы. Например, вместо кнопки "Обновить пользователя" она генерирует кнопку "Обновить пользователя".

Имена кнопок взяты из файла локали ActionView. Есть ли способ создать значение по умолчанию, которое уменьшает имя модели? Это не описано в разделе i18n раздела "Рубины на рельсах" на Interpolation, поэтому, возможно, это невозможно. Не работает следующее:

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

В общем, я был бы рад найти ссылку на синтаксис локальных файлов YAML. Руководство i18n охватывает некоторые синтаксисы, но было бы полезно найти документацию обо всех восклицательных знаках, разных форматах даты и времени и т.д. Или, может быть, я должен использовать Ruby Hash вместо YAML файла для этой цели?

Ответ 1

После дальнейших исследований я пришел к выводу, что такая операция по интерполированным значениям невозможна, по крайней мере, с использованием файла локали 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

Этот код "в значительной степени основан на расширении интерполяции Масло Матуо Мутох" 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 существует множество способов форматирования чисел, но нет операций для изменения случая строк.

Ответ 2

Я решил эту проблему, изменив интерполяцию 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