lib/i18n/js.rb in i18n-js-3.0.0.rc8 vs lib/i18n/js.rb in i18n-js-3.0.0.rc9

- old
+ new

@@ -1,14 +1,15 @@ +require "yaml" require "i18n" require "fileutils" - require "i18n/js/utils" module I18n module JS require "i18n/js/dependencies" require "i18n/js/fallback_locales" + require "i18n/js/segment" if JS::Dependencies.rails? require "i18n/js/middleware" require "i18n/js/engine" end @@ -18,70 +19,74 @@ # The configuration file. This defaults to the `config/i18n-js.yml` file. # def self.config_file_path @config_file_path ||= DEFAULT_CONFIG_PATH end + def self.config_file_path=(new_path) @config_file_path = new_path end # Export translations to JavaScript, considering settings # from configuration file def self.export export_i18n_js - translation_segments.each do |filename, translations| - save(translations, filename) - end + translation_segments.each(&:save!) end - def self.segments_per_locale(pattern, scope) - I18n.available_locales.each_with_object({}) do |locale, segments| + def self.segments_per_locale(pattern, scope, exceptions, options) + I18n.available_locales.each_with_object([]) do |locale, segments| scope = [scope] unless scope.respond_to?(:each) - result = scoped_translations(scope.collect{|s| "#{locale}.#{s}"}) - merge_with_fallbacks!(result, locale, scope) if use_fallbacks? + result = scoped_translations(scope.collect{|s| "#{locale}.#{s}"}, exceptions) + merge_with_fallbacks!(result, locale, scope, exceptions) if use_fallbacks? next if result.empty? - - segment_name = ::I18n.interpolate(pattern,{:locale => locale}) - segments[segment_name] = result + segments << Segment.new(::I18n.interpolate(pattern, {:locale => locale}), result, options) end end - def self.segment_for_scope(scope) + def self.segment_for_scope(scope, exceptions) if scope == "*" - translations + exclude(translations, exceptions) else - scoped_translations(scope) + scoped_translations(scope, exceptions) end end def self.configured_segments - config[:translations].each_with_object({}) do |options, segments| - options.reverse_merge!(:only => "*") - if options[:file] =~ ::I18n::INTERPOLATION_PATTERN - segments.merge!(segments_per_locale(options[:file], options[:only])) + config[:translations].inject([]) do |segments, options| + file = options[:file] + only = options[:only] || '*' + exceptions = [options[:except] || []].flatten + + segment_options = options.slice(:namespace, :pretty_print) + + if file =~ ::I18n::INTERPOLATION_PATTERN + segments += segments_per_locale(file, only, exceptions, segment_options) else - result = segment_for_scope(options[:only]) - segments[options[:file]] = result unless result.empty? + result = segment_for_scope(only, exceptions) + segments << Segment.new(file, result, segment_options) unless result.empty? end + + segments end end def self.filtered_translations {}.tap do |result| - translation_segments.each do |filename, translations| - Utils.deep_merge!(result, translations) + translation_segments.each do |segment| + Utils.deep_merge!(result, segment.translations) end end end def self.translation_segments if config? && config[:translations] configured_segments else - {"#{DEFAULT_EXPORT_DIR_PATH}/translations.js" => translations} + [Segment.new("#{DEFAULT_EXPORT_DIR_PATH}/translations.js", translations)] end end # Load configuration file for partial exporting and # custom output directory @@ -97,32 +102,34 @@ # Check if configuration file exist def self.config? File.file? config_file_path end - # Convert translations to JSON string and save file. - def self.save(translations, file) - FileUtils.mkdir_p File.dirname(file) - - File.open(file, "w+") do |f| - f << %(I18n.translations || (I18n.translations = {});\n) - Utils.strip_keys_with_nil_values(translations).each do |locale, translations_for_locale| - f << %(I18n.translations["#{locale}"] = #{translations_for_locale.to_json};\n); - end - end - end - - def self.scoped_translations(scopes) # :nodoc: + def self.scoped_translations(scopes, exceptions = []) # :nodoc: result = {} [scopes].flatten.each do |scope| - Utils.deep_merge! result, filter(translations, scope) + translations_without_exceptions = exclude(translations, exceptions) + filtered_translations = filter(translations_without_exceptions, scope) + + Utils.deep_merge! result, filtered_translations end result end + # Exclude keys from translations listed in the `except:` section in the config file + def self.exclude(translations, exceptions) + return translations if exceptions.empty? + + exceptions.inject(translations) do |memo, exception| + Utils.deep_reject(memo) do |key, value| + key.to_s == exception.to_s + end + end + end + # Filter translations according to the specified scope. def self.filter(translations, scopes) scopes = scopes.split(".") if scopes.is_a?(String) scopes = scopes.clone scope = scopes.shift @@ -158,38 +165,41 @@ true end end # deep_merge! given result with result for fallback locale - def self.merge_with_fallbacks!(result, locale, scope) + def self.merge_with_fallbacks!(result, locale, scope, exceptions) result[locale] ||= {} fallback_locales = FallbackLocales.new(fallbacks, locale) fallback_locales.each do |fallback_locale| - fallback_result = scoped_translations(scope.collect{|s| "#{fallback_locale}.#{s}"}) # NOTE: Duplicated code here + fallback_result = scoped_translations(scope.collect{|s| "#{fallback_locale}.#{s}"}, exceptions) # NOTE: Duplicated code here result[locale] = Utils.deep_merge(fallback_result[fallback_locale], result[locale]) end end - ### Export i18n.js begin + # Copy i18n.js def self.export_i18n_js - return if export_i18n_js_dir_path.nil? + return unless export_i18n_js_dir_path.is_a? String FileUtils.mkdir_p(export_i18n_js_dir_path) i18n_js_path = File.expand_path('../../../app/assets/javascripts/i18n.js', __FILE__) FileUtils.cp(i18n_js_path, export_i18n_js_dir_path) end - def self.export_i18n_js_dir_path - return @export_i18n_js_dir_path if defined?(@export_i18n_js_dir_path) - @export_i18n_js_dir_path = DEFAULT_EXPORT_DIR_PATH + def self.export_i18n_js_dir_path + @export_i18n_js_dir_path ||= (config[:export_i18n_js] || :none) if config.has_key?(:export_i18n_js) + @export_i18n_js_dir_path ||= DEFAULT_EXPORT_DIR_PATH + @export_i18n_js_dir_path end + # Setting this to nil would disable i18n.js exporting def self.export_i18n_js_dir_path=(new_path) + new_path = :none unless new_path.is_a? String @export_i18n_js_dir_path = new_path end end end end