class ReactOnRails::Locales::Base
def convert
def convert file_names.each do |name| template = send(:"template_#{name}") path = file(name) generate_file(template, path) end end
def default_locale
def default_locale @default_locale ||= I18n.default_locale.to_s || "en" end
def exist_files
def exist_files @exist_files ||= files.select { |file| File.exist?(file) } end
def file(name)
def file(name) "#{i18n_dir}/#{name}.#{file_format}" end
def file_format; end
def file_format; end
def file_names
def file_names %w[translations default] end
def files
def files @files ||= file_names.map { |n| file(n) } end
def files_are_outdated
def files_are_outdated latest_yml = locale_files.map { |file| File.mtime(file) }.max earliest = exist_files.map { |file| File.mtime(file) }.min latest_yml > earliest end
def flatten(translations)
def flatten(translations) translations.each_with_object({}) do |(k, v), h| if v.is_a? Hash flatten(v).map { |hk, hv| h[:"#{k}.#{hk}"] = hv } elsif v.is_a?(String) h[k] = v.gsub("%{", "{") elsif !v.is_a?(Array) h[k] = v end end end
def flatten_defaults(val)
def flatten_defaults(val) flatten(val).each_with_object({}) do |(k, v), h| key = format(k) h[key] = { id: k, defaultMessage: v } end end
def format(input)
def format(input) input.to_s.tr(".", "_").camelize(:lower).to_sym end
def generate_file(template, path)
def generate_file(template, path) result = ERB.new(template).result File.write(path, result) end
def generate_translations
def generate_translations translations = {} defaults = {} locale_files.each do |f| safe_load_options = ReactOnRails.configuration.i18n_yml_safe_load_options || {} translation = YAML.safe_load(File.open(f), **safe_load_options) key = translation.keys[0] val = flatten(translation[key]) translations = translations.deep_merge(key => val) defaults = defaults.deep_merge(flatten_defaults(val)) if key == default_locale rescue Psych::Exception => e raise ReactOnRails::Error, <<~MSG Error parsing #{f}: #{e.message} Consider fixing unsafe YAML or permitting with config.i18n_yml_safe_load_options MSG end [translations.to_json, defaults.to_json] end
def i18n_dir
def i18n_dir @i18n_dir ||= ReactOnRails.configuration.i18n_dir end
def i18n_yml_dir
def i18n_yml_dir @i18n_yml_dir ||= ReactOnRails.configuration.i18n_yml_dir end
def initialize
def initialize return if i18n_dir.nil? return unless obsolete? @translations, @defaults = generate_translations convert end
def locale_files
def locale_files @locale_files ||= if i18n_yml_dir.present? Dir["#{i18n_yml_dir}/**/*.yml"] else ReactOnRails::Utils.truthy_presence( Rails.application && Rails.application.config.i18n.load_path ).presence end end
def obsolete?
def obsolete? return true if exist_files.empty? files_are_outdated end
def template_default
def template_default <<-JS.strip_heredoc import { defineMessages } from 'react-intl'; const defaultLocale = '#{default_locale}'; const defaultMessages = defineMessages(#{@defaults}); export { defaultMessages, defaultLocale }; JS end
def template_translations
def template_translations <<-JS.strip_heredoc export const translations = #{@translations}; JS end