I18n uses YAML files to store translations, however when using an integer as a map key, the translation is then missing when referenced. This may be unexpected at first, but below describes the translation process, and why it is happening.
en:
1:
foo: 'bar'
I18n.translate('1.foo') #=> "translation missing: en.1.foo"
We might have expected 'bar'
I18n.translate
callslookup
callsI18n.normalize_keys
(i18n-0.6.1/lib/i18n.rb:255) callsnormalize_key
(i18n-0.6.1/lib/i18n.rb:303)
The normalize_key
method is shown below:
def normalize_key(key, separator)
normalized_key_cache[separator][key] ||=
case key
when Array
key.map { |k| normalize_key(k, separator) }.flatten
else
keys = key.to_s.split(separator)
keys.delete('')
keys.map! { |k| k.to_sym }
keys
end
end
Note that this calls key.to_s
followed by .to_sym
. e.g. normalize_key("1.foo", ".") # => [:"1", :foo]
The translation file is loaded in the lookup
method at this time with the key preserved in Integer format. However our lookup key is now: key.to_s.to_sym
They integer map key is converted to a symbol, however we are now comparing :"1"
with "1"
and the translation fails because the key is missing.
Even though YAML supports Integers as map keys - use string representations of Integers as map keys when using I18n