Permalink
Browse files

Decouple the external separator (used when storing translations) from…

… the internal separator in some backends (like Fast and ActiveRecord). This speed up and simplify both backends implementation (more refactoring coming next).
  • Loading branch information...
1 parent 4405bc2 commit 274cb4daa0ca5e3b2bd23b45eb7f9fc58f75a79d @josevalim josevalim committed Apr 27, 2010
View
15 lib/i18n/backend/active_record.rb
@@ -14,10 +14,9 @@ def reload!
end
def store_translations(locale, data, options = {})
- separator = options[:separator] || I18n.default_separator
- wind_keys(data, separator).each do |key, value|
+ wind_keys(data).each do |key, value|
store_link(locale, key, value) if value.is_a?(Symbol)
- Translation.locale(locale).lookup(expand_keys(key, separator), separator).delete_all
+ Translation.locale(locale).lookup(expand_keys(key, "."), ".").delete_all
Translation.create(:locale => locale.to_s, :key => key.to_s, :value => value)
end
end
@@ -34,19 +33,19 @@ def available_locales
def lookup(locale, key, scope = [], options = {})
return unless key
+ key = resolve_link(locale, key)
- separator = options[:separator] || I18n.default_separator
+ keys = I18n.normalize_keys(locale, key, scope, options[:separator])
+ key = keys[1..-1].map!{ |k| escape_default_separator(k) }.join(".")
- key = resolve_link(locale, key)
- key = (Array(scope) + Array(key)).join(separator)
- result = Translation.locale(locale).lookup(key, separator).all
+ result = Translation.locale(locale).lookup(key, ".").all
if result.empty?
return nil
elsif result.first.key == key
return result.first.value
else
- chop_range = (key.size + separator.size)..-1
+ chop_range = (key.size + 1)..-1
result = result.inject({}) do |hash, r|
hash[r.key.slice(chop_range)] = r.value
hash
View
61 lib/i18n/backend/fast.rb
@@ -14,29 +14,24 @@ module Backend
module Fast
include Links
- def reset_flattened_translations!
- @flattened_translations = nil
- end
-
- def flattened_translations
- @flattened_translations ||= flatten_translations(translations)
- end
-
- def merge_translations(locale, data, options = {})
- super
- reset_flattened_translations!
- end
-
- def init_translations
+ # Overwrite reload! to also clean up flattened translations.
+ def reload!
super
reset_flattened_translations!
end
protected
+
+ # Generate flattened translations after translations are initialized.
+ def init_translations
+ super
+ flattened_translations
+ end
+
def flatten_translations(translations)
# don't flatten locale roots
translations.inject({}) do |result, (locale, translations)|
- result[locale] = wind_keys(translations, nil, true)
+ result[locale] = wind_keys(translations, true)
result[locale].each do |key, value|
store_link(locale, key, value) if value.is_a?(Symbol)
end
@@ -48,22 +43,36 @@ def lookup(locale, key, scope = nil, options = {})
return unless key
init_translations unless initialized?
- return nil unless flattened_translations.has_key?(locale.to_sym)
+ locale = locale.to_sym
+ return nil unless flattened_translations[locale]
- separator = options[:separator]
- if separator && I18n.default_separator != separator
- key = cleanup_non_standard_separator(key, separator)
- scope = Array(scope).map{|k| cleanup_non_standard_separator(k, separator)} if scope
- end
-
+ # TODO Should link resolve locally or always globally?
key = resolve_link(locale, key)
- key = (Array(scope) + [key]).join(I18n.default_separator) if scope
- flattened_translations[locale.to_sym][key.to_sym]
+
+ keys = I18n.normalize_keys(locale, key, scope, options[:separator])
+ key = keys[1..-1].map!{ |k| escape_default_separator(k) }.join(".").to_sym
+
+ flattened_translations[locale][key]
end
- def cleanup_non_standard_separator(key, user_separator)
- escape_default_separator(key).tr(user_separator, I18n.default_separator)
+ # Store flattened translations in a variable.
+ def flattened_translations
+ @flattened_translations ||= flatten_translations(translations)
end
+
+ # Clean up flattened translations variable. Should be called whenever
+ # the internal hash is changed.
+ def reset_flattened_translations!
+ @flattened_translations = nil
+ end
+
+ # Overwrite merge_translations to clean up the internal hash so added
+ # translations are also cached.
+ def merge_translations(locale, data, options = {})
+ super
+ reset_flattened_translations!
+ end
+
end
end
end
View
21 lib/i18n/backend/helpers.rb
@@ -2,6 +2,7 @@ module I18n
module Backend
module Helpers
SEPARATOR_ESCAPE_CHAR = "\001"
+ WIND_SEPARATOR = "."
# Return a new hash with all keys and nested keys converted to symbols.
def deep_symbolize_keys(hash)
@@ -15,30 +16,24 @@ 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 = nil, subtree = false, prev_key = nil, result = {}, orig_hash=hash)
- separator ||= I18n.default_separator
-
+ def wind_keys(hash, subtree = false, prev_key = nil, result = {}, orig_hash=hash)
hash.each_pair do |key, value|
- key = escape_default_separator(key, separator)
- curr_key = [prev_key, key].compact.join(separator).to_sym
+ key = escape_default_separator(key)
+ curr_key = [prev_key, key].compact.join(WIND_SEPARATOR).to_sym
if value.is_a?(Hash)
result[curr_key] = value if subtree
- wind_keys(value, separator, subtree, curr_key, result, orig_hash)
+ wind_keys(value, subtree, curr_key, result, orig_hash)
else
- result[unescape_default_separator(curr_key)] = value
+ result[curr_key] = value
end
end
result
end
- def escape_default_separator(key, separator=nil)
- key.to_s.tr(separator || I18n.default_separator, SEPARATOR_ESCAPE_CHAR)
- end
-
- def unescape_default_separator(key, separator=nil)
- key.to_s.tr(SEPARATOR_ESCAPE_CHAR, separator || I18n.default_separator).to_sym
+ def escape_default_separator(key)
+ key.to_s.tr(WIND_SEPARATOR, SEPARATOR_ESCAPE_CHAR)
end
end
end
View
2 test/backend/fast_test.rb
@@ -26,7 +26,7 @@ def setup
end
def assert_flattens(expected, nested)
- assert_equal expected, @backend.send(:wind_keys, nested, nil, true)
+ assert_equal expected, @backend.send(:wind_keys, nested, true)
end
test "hash flattening works" do
View
2 test/backend/helpers_test.rb
@@ -9,7 +9,7 @@ def setup
test "wind_keys" do
hash = { "a" => { "b" => { "c" => "d", "e" => "f" }, "g" => "h" }, :"i.a" => "j", "g.a" => "h"}
- expected = { :"a.b.c" => "d", :"a.b.e" => "f", :"a.g" => "h", :"i.a" => "j", :"g.a" => "h" }
+ expected = { :"a.b.c" => "d", :"a.b.e" => "f", :"a.g" => "h", :"i\001a".to_sym => "j", :"g\001a".to_sym => "h" }
assert_equal expected, @backend.wind_keys(hash)
end

0 comments on commit 274cb4d

Please sign in to comment.