Howto: Extending FastGettext with custom translation repository
Scenario: I want to have translations for one language in more files than one file. Current FastGettext::TranslationRepository::Yaml
can’t handle this. So we create our own Yamlr
module.
Readme.md tells something about custom modules, but one must be skilled to understand how to use this knowledge. This howto aims to fill this gap.
1. Modify load path
I know how to do this in Rails.
~~~ruby
# add to config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
~~~
This won’t load all files from /lib
directory, but tells Rails where to search when you call require function.
2. Add module to new load path
Create lib/fast_gettext/translation_repository
in Rails application. Now we move our yaml_recursive.rb
here. Yes, only one file here.
The source is modified version of the original Yaml module:
~~~`ruby require ‘fast_gettext/translation_repository/base’ require ‘yaml’ require ‘active_support/core_ext/hash/deep_merge.rb’
module FastGettext module TranslationRepository # Responsibility: # - find and store yaml files # - provide access to translations in yaml files class Yamlr < Base def initialize(name,options={}) super reload end
def available_locales
@files.keys
end
def plural(*keys)
['one', 'other', 'plural2', 'plural3'].map do |name|
self[yaml_dot_notation(keys.first, name)]
end
end
def pluralisation_rule
self['pluralisation_rule'] ? lambda{|n| eval(self['pluralisation_rule']) } : nil
end
def reload
find_and_store_files(@options)
super
end
protected
MAX_FIND_DEPTH = 10
def find_and_store_files(options)
@files = {}
path = options[:path] || 'config/locales'
Dir["#{path}/**/*.yml"].each do |yaml_file|
@files.deep_merge!(load_yaml(yaml_file))
end
@files
end
def current_translations
@files[FastGettext.locale] || super
end
# Given a yaml file return a hash of key -> translation
def load_yaml(file)
yaml = YAML.load_file(file)
yaml.keys.reduce({}) do |processed, locale|
processed[locale] ||= {}
processed[locale].merge!(yaml_hash_to_dot_notation(yaml[locale]))
processed
end
end
def yaml_hash_to_dot_notation(yaml_hash)
add_yaml_key({}, nil, yaml_hash)
end
def add_yaml_key(result, prefix, hash)
hash.each_pair do |key, value|
if value.kind_of?(Hash)
add_yaml_key(result, yaml_dot_notation(prefix, key), value)
else
result[yaml_dot_notation(prefix, key)] = value
end
end
result
end
def yaml_dot_notation(a,b)
a ? "#{a}.#{b}" : b
end
end end end ~~~`
Now we can read I18n translations too. To use these translations with fast_gettext you need to override calls to I18n. (TODO how?)
3. Enjoy
~~~`ruby rails c
… require ‘fast_gettext/translation_repository/yaml_recursive’ #=> true FastGettext.add_text_domain(‘lala’, path: ‘config/locales’, type: :yamlr) #=> { …our translations … } ~~~`
4. Debug
From the initializer:
~~~ruby
puts FastGettext.add_text_domain('lala', path: 'config/locales', type: :yamlr).inspect
~~~
Add Comment