diff --git a/lib/i18n/backend/base.rb b/lib/i18n/backend/base.rb index 974325b5..d9ad784c 100644 --- a/lib/i18n/backend/base.rb +++ b/lib/i18n/backend/base.rb @@ -114,11 +114,10 @@ def lookup(locale, key, scope = [], separator = nil) keys = I18n.send(:normalize_translation_keys, locale, key, scope, separator) keys.inject(translations) do |result, key| key = key.to_sym - if result.respond_to?(:has_key?) and result.has_key?(key) - result[key] - else - return nil - end + return nil unless result.is_a?(Hash) && result.has_key?(key) + result = result[key] + result = resolve(locale, key, result, :scope => scope, :separator => separator) if result.is_a?(Symbol) + result end end diff --git a/lib/i18n/backend/fast.rb b/lib/i18n/backend/fast.rb index f342c069..af8ef8d7 100644 --- a/lib/i18n/backend/fast.rb +++ b/lib/i18n/backend/fast.rb @@ -35,22 +35,8 @@ def init_translations protected # flatten_hash({:a=>'a', :b=>{:c=>'c', :d=>'d', :f=>{:x=>'x'}}}) # # => {:a=>'a', :b=>{:c=>'c', :d=>'d', :f=>{:x=>'x'}}, :"b.f" => {:x=>"x"}, :"b.c"=>"c", :"b.f.x"=>"x", :"b.d"=>"d"} - def flatten_hash(h, nested_stack = [], flattened_h = {}) - h.each_pair do |k, v| - new_nested_stack = nested_stack + [escape_default_separator(k)] - flattened_h[nested_stack_to_flat_key(new_nested_stack)] = v - flatten_hash(v, new_nested_stack, flattened_h) if v.kind_of?(Hash) - end - - flattened_h - end - - def escape_default_separator(key) - key.to_s.tr(I18n.default_separator, SEPARATOR_ESCAPE_CHAR) - end - - def nested_stack_to_flat_key(nested_stack) - nested_stack.join(I18n.default_separator).to_sym + def flatten_hash(h, nested_stack = [], flattened_h = {}, orig_h=h) + deep_symbolize_keys(wind_keys(h, nil, true)) end def flatten_translations(translations) diff --git a/lib/i18n/backend/helpers.rb b/lib/i18n/backend/helpers.rb index 873de085..d1e2fef9 100644 --- a/lib/i18n/backend/helpers.rb +++ b/lib/i18n/backend/helpers.rb @@ -1,6 +1,8 @@ module I18n module Backend module Helpers + SEPARATOR_ESCAPE_CHAR = "\001" + # Return a new hash with all keys and nested keys converted to symbols. def deep_symbolize_keys(hash) hash.inject({}) { |result, (key, value)| @@ -13,16 +15,41 @@ def deep_symbolize_keys(hash) # Flatten keys for nested Hashes by chaining up keys using the separator # >> { "a" => { "b" => { "c" => "d", "e" => "f" }, "g" => "h" }, "i" => "j"}.wind # => { "a.b.c" => "d", "a.b.e" => "f", "a.g" => "h", "i" => "j" } - def wind_keys(hash, separator = ".", prev_key = nil, result = {}) - hash.inject(result) do |result, pair| - key, value = *pair + def wind_keys(hash, separator = nil, subtree = false, prev_key = nil, result = {}, orig_hash=hash) + separator ||= I18n.default_separator + + hash.each_pair do |key, value| + key = escape_default_separator(key, separator) curr_key = [prev_key, key].compact.join(separator) + + if value.is_a?(Symbol) + value = hash_lookup(orig_hash, value, separator) || + hash_lookup(hash, value, separator) + end + if value.is_a?(Hash) - wind_keys(value, separator, curr_key, result) + result[curr_key] = value if subtree + wind_keys(value, separator, subtree, curr_key, result, orig_hash) else result[curr_key] = value end - result + end + + result + end + + def escape_default_separator(key, separator=nil) + key.to_s.tr(separator || I18n.default_separator, SEPARATOR_ESCAPE_CHAR) + end + + def hash_lookup(hash, keys, separator = ".") + keys.to_s.split(separator).inject(hash) do |result, key| + key = key.to_sym + if result.respond_to?(:has_key?) and result.has_key?(key) + result[key] + else + return nil + end end end diff --git a/test/api/link.rb b/test/api/link.rb index b5da5277..83b506f3 100644 --- a/test/api/link.rb +++ b/test/api/link.rb @@ -22,6 +22,11 @@ module Link setup_linked_translations assert_equal('baz', I18n.backend.translate('en', :link_to_baz, :scope => :bar)) end + + define_method "test linked lookup: given the first key resolves to a symbol it looks up the symbol with remaining keys" do + setup_linked_translations + assert_equal('baz', I18n.backend.translate('en', :"link_to_bar.baz")) + end protected diff --git a/test/test_helper.rb b/test/test_helper.rb index 2b970c1d..91abe67f 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,12 +1,13 @@ # encoding: utf-8 -$: << "lib" -$: << File.expand_path(File.dirname(__FILE__)) +$:.unshift File.expand_path("../lib", File.dirname(__FILE__)) +$:.unshift File.expand_path(File.dirname(__FILE__)) -require 'rubygems' -require 'test/unit' require 'i18n' require 'i18n/core_ext/object/meta_class' + +require 'rubygems' +require 'test/unit' require 'time' require 'yaml'