2012-03-10 22 views
11

Sử dụng Rails 3.1.3 với Ruby 1.9.3p0.Làm thế nào để thay đổi trường hợp của các biến nội suy trong tệp miền địa phương Rails?

Tôi đã phát hiện ra rằng theo mặc định, Rails không sử dụng trường hợp câu cho các nút biểu mẫu. Ví dụ: thay vì nút "Cập nhật người dùng", nút này sẽ tạo nút "Người dùng cập nhật".

Tên nút đến từ ActionView locale file. Có cách nào để tạo ra một mặc định mà downcases tên model? Điều này không được đề cập trong phần i18n của Ruby on Rails trên Interpolation vì vậy có thể nó không thể thực hiện được. Các mục sau không hoạt động:

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

Nói chung, tôi rất vui khi tìm thấy tham chiếu cho cú pháp của tệp YAML miền địa phương. Hướng dẫn i18n bao gồm một số cú pháp, nhưng sẽ hữu ích khi tìm tài liệu trên tất cả các dấu chấm than, các định dạng ngày/giờ khác nhau, v.v. Hoặc có lẽ tôi nên sử dụng Ruby Hash thay vì tệp YAML cho mục đích này?

Trả lời

8

Sau khi nghiên cứu sâu hơn, tôi đã kết luận rằng loại thao tác này trên các giá trị nội suy là không thể, ít nhất là sử dụng một tệp miền địa phương YAML.

YAML được ghi chép lại ở đây và không hỗ trợ các hoạt động chuỗi:
http://www.yaml.org/spec/1.2/spec.html

Trang chính trên địa hóa của Ruby là ở đây:
http://ruby-i18n.org/wiki

Từ đó, chúng ta tìm thấy mã cho mặc định i18n đá quý và đi sâu vào mã nội suy. Nó sử dụng sprintf để làm suy:
https://github.com/svenfuchs/i18n/blob/master/lib/i18n/interpolate/ruby.rb

mã đó là "chủ yếu dựa vào mở rộng suy gettext Chuỗi Masao Mutoh của":
http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb

phần mở rộng đó có một ví dụ về định dạng số:

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} 

Phần mở rộng đề cập đến [Ruby] "Kernel::sprintf để biết chi tiết về chuỗi định dạng":
http://www.ruby-doc.org/core-1.9.2/Kernel.html#method-i-sprintf

Trong tài liệu đó trên sprintf, có nhiều cách để định dạng số, nhưng không có thao tác nào để thay đổi trường hợp chuỗi.

1

Tôi đã giải quyết vấn đề này bằng cách thay đổi nội suy I18n. Đặt đoạn mã sau trong thư mục initializers của bạn:

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 

Bây giờ, đây là những gì bạn có thể làm trong file locale của bạn:

create: 'Opprett %{model.downcase}' 

và thử nghiệm nó:

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 
Các vấn đề liên quan