Skip to content

Instantly share code, notes, and snippets.

@tlux
Last active August 29, 2015 14:01
Show Gist options
  • Select an option

  • Save tlux/3117918abe7f88b20bd4 to your computer and use it in GitHub Desktop.

Select an option

Save tlux/3117918abe7f88b20bd4 to your computer and use it in GitHub Desktop.
I18n power for your JavaScript
window.I18n ||= {}
VALID_OPTIONS = ['scope', 'locale', 'default', 'fallbacks']
humanizeKeypath = (keypath) ->
console.warn "I18n: no translation found for #{keypath}"
_(keypath.split('.')).chain().last().humanize().value()
sanitizeKeypath = (keypath) ->
str = ""
if keypath
if _(keypath).isArray()
str += _(keypath).chain().flatten().compact().value().join('.')
else
str += keypath
str
buildEvalString = (keypath, locale) ->
['I18n.translations', locale, sanitizeKeypath(keypath)].join('.')
tryToInterpolate = (str, interpolations) ->
if _(str).isObject()
str
else
str.interpolate(interpolations)
_(I18n).extend
t: (keypath, options = {}) ->
@translate(keypath, options)
translate: (keypath, options = {}) ->
throw "I18n: no keypath defined" unless keypath
throw "I18n: no translations found" unless @translations
interpolations = _(options).omit(VALID_OPTIONS)
options = _(options).chain().pick(VALID_OPTIONS).defaults(locale: I18n.locale, fallbacks: true).value()
fallbacks = {}
fallbacks = I18n.fallbacks[options.locale] if options.fallbacks and _(I18n.fallbacks).has(options.locale)
fallbacks[options.locale] = [options.locale] if _(fallbacks).isEmpty()
translations = _(fallbacks).collect (locale) =>
if _(@translations).has(locale)
try
eval(buildEvalString([options.scope, keypath], locale))
catch
null
translation = _(translations).chain().select((translation) -> translation?).first().value()
if translation?
tryToInterpolate(translation, interpolations)
else
if options.default
tryToInterpolate(options.default, interpolations)
else
humanizeKeypath(keypath)
namespace :i18n do
desc 'Generates I18n JavaScript files and stores them in public/static/locales'
task :generate_js => :environment do
# Generate contained directory
dirname = ENV.fetch('DIRNAME') { "#{Rails.root}/public/static/locales" }
FileUtils.mkdir_p(dirname)
# Get contents of all translation files and merge them in a single Hash
locale_files = Dir.glob("#{Rails.root}/config/locales/**/*.yml")
translations = locale_files.inject({}) do |translations, file|
locale_translations = YAML.load_file(file)
locale_translations.deep_transform_keys! do |key|
key.split('/').map { |part| part.camelize(:lower) }.join('/')
end
translations.deep_merge!(locale_translations)
end
if I18n.respond_to?(:fallbacks)
fallback_combinations = I18n.available_locales.collect { |locale| I18n.fallbacks[locale].sort }.uniq
fallback_combinations.each do |locale_combination|
file_name = locale_combination.join('+')
path = File.join(dirname, "#{file_name}.js")
File.open(path, 'w') do |file|
file.puts header_data
locale_combination.each do |locale|
file.puts translation_data(locale, translations[locale.to_s])
end
end
puts "[#{locale_combination.join('+')}] #{path}"
end
else
translations.each do |locale, locale_translations|
path = File.join(dirname, "#{locale}.js")
File.open(path, 'w') do |file|
file.puts header_data
file.puts translation_data(locale, locale_translations)
end
puts "[#{locale}] #{path}"
end
end
end
def header_data
<<-JAVASCRIPT.strip_heredoc
I18n || (I18n = {});
I18n.translations || (I18n.translations = {});
JAVASCRIPT
end
def translation_data(locale, translations)
"I18n.translations.#{locale} = #{translations.to_json};"
end
end
module I18nHelper
def i18n_javascript
fallbacks = I18n.try(:fallbacks)
locales = Array(fallbacks ? fallbacks[I18n.locale] : I18n.locale).sort
capture do
concat javascript_tag <<-JAVASCRIPT.strip_heredoc
I18n || (I18n = {});
I18n.defaultLocale = #{I18n.default_locale.to_json};
I18n.fallbacks = #{fallbacks.to_h.to_json};
I18n.locale = #{I18n.locale.to_json};
JAVASCRIPT
concat "\n"
concat javascript_include_tag("/static/locales/#{locales.join('+')}.js")
end
end
end
# "Hello, %{name}!".interpolate(name: 'Tobias') # => "Hello, Tobias!"
String::interpolate = (interpolations = {}) ->
@replace /%\{(.*?)\}/g, (whole, key) ->
camelizedKey = _(key).camelize()
camelizedKey = camelizedKey.charAt(0).toLowerCase() + camelizedKey.slice(1)
interpolations[camelizedKey] || interpolations[key] || ''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment