From 3739810afa3545e6747a9111185dc8808fff6078 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sun, 18 Nov 2012 17:41:31 +0000 Subject: [PATCH] Adds a custom i18n backend that lazily loads translations files. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@10843 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- config/initializers/30-redmine.rb | 3 +- lib/redmine/i18n.rb | 71 ++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/config/initializers/30-redmine.rb b/config/initializers/30-redmine.rb index 11a248959..1018ca18c 100644 --- a/config/initializers/30-redmine.rb +++ b/config/initializers/30-redmine.rb @@ -1,6 +1,5 @@ I18n.default_locale = 'en' -# Adds fallback to default locale for untranslated strings -I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) +I18n.backend = Redmine::I18n::Backend.new require 'redmine' diff --git a/lib/redmine/i18n.rb b/lib/redmine/i18n.rb index 12445b450..304175ee5 100644 --- a/lib/redmine/i18n.rb +++ b/lib/redmine/i18n.rb @@ -67,7 +67,7 @@ module Redmine end def valid_languages - @@valid_languages ||= Dir.glob(File.join(Rails.root, 'config', 'locales', '*.yml')).collect {|f| File.basename(f).split('.').first}.collect(&:to_sym) + ::I18n.available_locales end def find_language(lang) @@ -84,5 +84,74 @@ module Redmine def current_language ::I18n.locale end + + # Custom backend based on I18n::Backend::Simple with the following changes: + # * lazy loading of translation files + # * available_locales are determined by looking at translation file names + class Backend + (class << self; self; end).class_eval { public :include } + + module Implementation + include ::I18n::Backend::Base + + # Stores translations for the given locale in memory. + # This uses a deep merge for the translations hash, so existing + # translations will be overwritten by new ones only at the deepest + # level of the hash. + def store_translations(locale, data, options = {}) + locale = locale.to_sym + translations[locale] ||= {} + data = data.deep_symbolize_keys + translations[locale].deep_merge!(data) + end + + # Get available locales from the translations filenames + def available_locales + @available_locales ||= ::I18n.load_path.map {|path| File.basename(path, '.*').to_sym}.uniq.sort + end + + # Clean up translations + def reload! + @translations = nil + @available_locales = nil + super + end + + protected + + def init_translations(locale) + locale = locale.to_s + paths = ::I18n.load_path.select {|path| File.basename(path, '.*') == locale} + load_translations(paths) + translations[locale] ||= {} + end + + def translations + @translations ||= {} + end + + # Looks up a translation from the translations hash. Returns nil if + # eiher key is nil, or locale, scope or key do not exist as a key in the + # nested translations hash. Splits keys or scopes containing dots + # into multiple keys, i.e. currency.format is regarded the same as + # %w(currency format). + def lookup(locale, key, scope = [], options = {}) + init_translations(locale) unless translations.key?(locale) + keys = ::I18n.normalize_keys(locale, key, scope, options[:separator]) + + keys.inject(translations) do |result, _key| + _key = _key.to_sym + return nil unless result.is_a?(Hash) && result.has_key?(_key) + result = result[_key] + result = resolve(locale, _key, result, options.merge(:scope => nil)) if result.is_a?(Symbol) + result + end + end + end + + include Implementation + # Adds fallback to default locale for untranslated strings + include ::I18n::Backend::Fallbacks + end end end