mirror of
https://github.com/discourse/discourse.git
synced 2026-08-04 10:23:17 -05:00
FIX: eradicate I18n fallback issues 💣
FIX: client's translation overrides were not working when the current locale was missing a key FIX: ExtraLocalesController.show was not properly handling multiple translations FIX: JsLocaleHelper#output_locale was not properly handling multiple translations FIX: ExtraLocalesController.show's spec which was randomly failing FIX: JsLocaleHelper#output_locale was muting cached translations hashes REFACTOR: move 'enableVerboseLocalization' to the 'localization' initializer REFACTOR: remove unused I18n.js methods (getFallbacks, localize, parseDate, toTime, strftime, toCurrency, toPercentage) REFACTOR: remove all I18n.pluralizationRules and instead use MessageFormat's pluralization rules TEST: add tests for localization initializer TEST: add tests for I18n.js
This commit is contained in:
@@ -42,7 +42,7 @@ module I18n
|
||||
end
|
||||
|
||||
# load it
|
||||
I18n.backend.load_translations(I18n.load_path.grep Regexp.new("\\.#{locale}\\.yml$"))
|
||||
I18n.backend.load_translations(I18n.load_path.grep(/\.#{Regexp.escape locale}\.yml$/))
|
||||
|
||||
@loaded_locales << locale
|
||||
end
|
||||
@@ -125,7 +125,7 @@ module I18n
|
||||
end
|
||||
|
||||
def client_overrides_json(locale)
|
||||
client_json = (overrides_by_locale(locale) || {}).select {|k, _| k.starts_with?('js.') || k.starts_with?('admin_js.')}
|
||||
client_json = (overrides_by_locale(locale) || {}).select { |k, _| k[/^(admin_js|js)\./] }
|
||||
MultiJson.dump(client_json)
|
||||
end
|
||||
|
||||
|
||||
@@ -7,9 +7,6 @@ module I18n
|
||||
include I18n::Backend::Pluralization
|
||||
|
||||
def available_locales
|
||||
# in case you are wondering this is:
|
||||
# Dir.glob( File.join(Rails.root, 'config', 'locales', 'client.*.yml') )
|
||||
# .map {|x| x.split('.')[-2]}.sort
|
||||
LocaleSiteSetting.supported_locales.map(&:to_sym)
|
||||
end
|
||||
|
||||
@@ -53,6 +50,7 @@ module I18n
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def find_results(regexp, results, translations, path=nil)
|
||||
return results if translations.blank?
|
||||
|
||||
|
||||
+37
-43
@@ -7,7 +7,7 @@ module JsLocaleHelper
|
||||
translations = {}
|
||||
|
||||
Dir["#{Rails.root}/plugins/*/config/locales/client.#{locale_str}.yml"].each do |file|
|
||||
if plugin_translations = YAML::load(File.open(file))[locale_str]
|
||||
if plugin_translations = YAML.load_file(file)[locale_str]
|
||||
translations.deep_merge!(plugin_translations)
|
||||
end
|
||||
end
|
||||
@@ -26,7 +26,7 @@ module JsLocaleHelper
|
||||
locale_str = locale.to_s
|
||||
|
||||
# load default translations
|
||||
translations = YAML::load(File.open("#{Rails.root}/config/locales/client.#{locale_str}.yml"))
|
||||
translations = YAML.load_file("#{Rails.root}/config/locales/client.#{locale_str}.yml")
|
||||
|
||||
# merge translations (plugin translations overwrite default translations)
|
||||
translations[locale_str]['js'].deep_merge!(plugin_translations(locale_str)['js']) if translations[locale_str] && plugin_translations(locale_str) && plugin_translations(locale_str)['js']
|
||||
@@ -35,23 +35,22 @@ module JsLocaleHelper
|
||||
end
|
||||
end
|
||||
|
||||
# purpose-built recursive algorithm ahoy!
|
||||
def self.deep_delete_matches(deleting_from, *checking_hashes)
|
||||
# deeply removes keys from "deleting_from" that are already present in "checking_hashes"
|
||||
def self.deep_delete_matches(deleting_from, checking_hashes)
|
||||
checking_hashes.compact!
|
||||
|
||||
new_hash = deleting_from.dup
|
||||
deleting_from.each do |key, value|
|
||||
if value.is_a? Hash
|
||||
# Recurse
|
||||
new_at_key = deep_delete_matches(deleting_from[key], *(checking_hashes.map {|h| h[key]}))
|
||||
if value.is_a?(Hash)
|
||||
new_at_key = deep_delete_matches(deleting_from[key], checking_hashes.map { |h| h[key] })
|
||||
if new_at_key.empty?
|
||||
new_hash.delete key
|
||||
new_hash.delete(key)
|
||||
else
|
||||
new_hash[key] = new_at_key
|
||||
end
|
||||
else
|
||||
if checking_hashes.any? {|h| h.include? key}
|
||||
new_hash.delete key
|
||||
if checking_hashes.any? { |h| h.include?(key) }
|
||||
new_hash.delete(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -66,8 +65,8 @@ module JsLocaleHelper
|
||||
loaded_locales = []
|
||||
|
||||
locales.map(&:to_s).each do |locale|
|
||||
all_translations[locale] = JsLocaleHelper.load_translations locale
|
||||
merged_translations[locale] = deep_delete_matches(all_translations[locale][locale], *loaded_locales.map { |l| merged_translations[l] })
|
||||
all_translations[locale] = load_translations(locale)
|
||||
merged_translations[locale] = deep_delete_matches(all_translations[locale][locale], loaded_locales.map { |l| merged_translations[l] })
|
||||
loaded_locales << locale
|
||||
end
|
||||
merged_translations
|
||||
@@ -75,12 +74,11 @@ module JsLocaleHelper
|
||||
end
|
||||
|
||||
def self.translations_for(locale_str)
|
||||
locale_sym = locale_str.to_sym
|
||||
|
||||
current_locale = I18n.locale
|
||||
I18n.locale = locale_sym
|
||||
locale_sym = locale_str.to_sym
|
||||
site_locale = SiteSetting.default_locale.to_sym
|
||||
|
||||
site_locale = SiteSetting.default_locale.to_sym
|
||||
I18n.locale = locale_sym
|
||||
|
||||
translations =
|
||||
if Rails.env.development?
|
||||
@@ -100,19 +98,23 @@ module JsLocaleHelper
|
||||
|
||||
def self.output_locale(locale)
|
||||
locale_str = locale.to_s
|
||||
translations = translations_for(locale_str).dup
|
||||
translations = Marshal.load(Marshal.dump(translations_for(locale_str)))
|
||||
|
||||
translations[locale_str].keys.each do |k|
|
||||
translations[locale_str].delete(k) unless k == "js"
|
||||
translations.keys.each do |locale|
|
||||
translations[locale].keys.each do |k|
|
||||
translations[locale].delete(k) unless k == "js"
|
||||
end
|
||||
end
|
||||
|
||||
message_formats = strip_out_message_formats!(translations[locale_str]['js'])
|
||||
|
||||
result = generate_message_format(message_formats, locale_str)
|
||||
|
||||
# I18n
|
||||
result << "I18n.translations = #{translations.to_json};\n"
|
||||
result << "I18n.locale = '#{locale_str}';\n"
|
||||
# loading moment here cause we must customize it
|
||||
result << "I18n.pluralizationRules.#{locale_str} = MessageFormat.locale.#{locale_str};\n" if locale_str != "en"
|
||||
|
||||
# moment
|
||||
result << File.read("#{Rails.root}/lib/javascripts/moment.js")
|
||||
result << moment_locale(locale_str)
|
||||
result << moment_formats
|
||||
@@ -136,33 +138,25 @@ module JsLocaleHelper
|
||||
def self.moment_locale(locale_str)
|
||||
# moment.js uses a different naming scheme for locale files
|
||||
locale_str = locale_str.tr('_', '-').downcase
|
||||
filename = Rails.root + "lib/javascripts/moment_locale/#{locale_str}.js"
|
||||
filename = "#{Rails.root}/lib/javascripts/moment_locale/#{locale_str}.js"
|
||||
|
||||
unless File.exists?(filename)
|
||||
# try the language without the territory
|
||||
locale_str = locale_str.partition('-').first
|
||||
filename = Rails.root + "lib/javascripts/moment_locale/#{locale_str}.js"
|
||||
end
|
||||
# try the language without the territory
|
||||
locale_str = locale_str.split("-")[0]
|
||||
filename = "#{Rails.root}/lib/javascripts/moment_locale/#{locale_str}.js" unless File.exists?(filename)
|
||||
|
||||
if File.exists?(filename)
|
||||
File.read(filename) << "\n"
|
||||
end || ""
|
||||
File.exists?(filename) ? File.read(filename) << "\n" : ""
|
||||
end
|
||||
|
||||
def self.generate_message_format(message_formats, locale_str)
|
||||
formats = message_formats.map { |k,v| k.inspect << " : " << compile_message_format(locale_str, v) }.join(", ")
|
||||
|
||||
filename = "#{Rails.root}/lib/javascripts/locale/#{locale_str}.js"
|
||||
filename = "#{Rails.root}/lib/javascripts/locale/en.js" unless File.exists?(filename)
|
||||
|
||||
result = "MessageFormat = {locale: {}};\n"
|
||||
|
||||
formats = message_formats.map{|k,v| k.inspect << " : " << compile_message_format(locale_str,v)}.join(", ")
|
||||
result << "I18n._compiledMFs = {#{formats}};\n\n"
|
||||
|
||||
filename = Rails.root + "lib/javascripts/locale/#{locale_str}.js"
|
||||
filename = Rails.root + "lib/javascripts/locale/en.js" unless File.exists?(filename)
|
||||
result << File.read(filename) << "\n\n"
|
||||
|
||||
result << File.read("#{Rails.root}/lib/javascripts/messageformat-lookup.js")
|
||||
|
||||
result
|
||||
result << "I18n._compiledMFs = {#{formats}};\n"
|
||||
result << File.read(filename) << "\n"
|
||||
result << File.read("#{Rails.root}/lib/javascripts/messageformat-lookup.js") << "\n"
|
||||
end
|
||||
|
||||
def self.reset_context
|
||||
@@ -174,7 +168,7 @@ module JsLocaleHelper
|
||||
@mutex.synchronize do
|
||||
yield @ctx ||= begin
|
||||
ctx = MiniRacer::Context.new
|
||||
ctx.load(Rails.root + 'lib/javascripts/messageformat.js')
|
||||
ctx.load("#{Rails.root}/lib/javascripts/messageformat.js")
|
||||
ctx
|
||||
end
|
||||
end
|
||||
@@ -182,7 +176,7 @@ module JsLocaleHelper
|
||||
|
||||
def self.compile_message_format(locale, format)
|
||||
with_context do |ctx|
|
||||
path = Rails.root + "lib/javascripts/locale/#{locale}.js"
|
||||
path = "#{Rails.root}/lib/javascripts/locale/#{locale}.js"
|
||||
ctx.load(path) if File.exists?(path)
|
||||
ctx.eval("mf = new MessageFormat('#{locale}');")
|
||||
ctx.eval("mf.precompile(mf.parse(#{format.inspect}))")
|
||||
|
||||
Reference in New Issue
Block a user