mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06: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:
@@ -15,6 +15,7 @@ describe JsLocaleHelper do
|
||||
@loaded_merges = nil
|
||||
end
|
||||
end
|
||||
|
||||
JsLocaleHelper.extend StubLoadTranslations
|
||||
|
||||
after do
|
||||
@@ -22,64 +23,68 @@ describe JsLocaleHelper do
|
||||
JsLocaleHelper.clear_cache!
|
||||
end
|
||||
|
||||
it 'should be able to generate translations' do
|
||||
expect(JsLocaleHelper.output_locale('en').length).to be > 0
|
||||
describe "#output_locale" do
|
||||
|
||||
it "doesn't change the cached translations hash" do
|
||||
I18n.locale = :fr
|
||||
expect(JsLocaleHelper.output_locale('fr').length).to be > 0
|
||||
expect(JsLocaleHelper.translations_for('fr')['fr'].keys).to contain_exactly("js", "admin_js", "wizard_js")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def setup_message_format(format)
|
||||
@ctx = MiniRacer::Context.new
|
||||
@ctx.eval('MessageFormat = {locale: {}};')
|
||||
@ctx.load(Rails.root + 'lib/javascripts/locale/en.js')
|
||||
compiled = JsLocaleHelper.compile_message_format('en', format)
|
||||
@ctx.eval("var test = #{compiled}")
|
||||
end
|
||||
context "message format" do
|
||||
|
||||
def localize(opts)
|
||||
@ctx.eval("test(#{opts.to_json})")
|
||||
end
|
||||
def setup_message_format(format)
|
||||
@ctx = MiniRacer::Context.new
|
||||
@ctx.eval('MessageFormat = {locale: {}};')
|
||||
@ctx.load(Rails.root + 'lib/javascripts/locale/en.js')
|
||||
compiled = JsLocaleHelper.compile_message_format('en', format)
|
||||
@ctx.eval("var test = #{compiled}")
|
||||
end
|
||||
|
||||
it 'handles plurals' do
|
||||
setup_message_format('{NUM_RESULTS, plural,
|
||||
one {1 result}
|
||||
other {# results}
|
||||
}')
|
||||
expect(localize(NUM_RESULTS: 1)).to eq('1 result')
|
||||
expect(localize(NUM_RESULTS: 2)).to eq('2 results')
|
||||
end
|
||||
def localize(opts)
|
||||
@ctx.eval("test(#{opts.to_json})")
|
||||
end
|
||||
|
||||
it 'handles double plurals' do
|
||||
setup_message_format('{NUM_RESULTS, plural,
|
||||
one {1 result}
|
||||
other {# results}
|
||||
} and {NUM_APPLES, plural,
|
||||
one {1 apple}
|
||||
other {# apples}
|
||||
}')
|
||||
it 'handles plurals' do
|
||||
setup_message_format('{NUM_RESULTS, plural,
|
||||
one {1 result}
|
||||
other {# results}
|
||||
}')
|
||||
expect(localize(NUM_RESULTS: 1)).to eq('1 result')
|
||||
expect(localize(NUM_RESULTS: 2)).to eq('2 results')
|
||||
end
|
||||
|
||||
expect(localize(NUM_RESULTS: 1, NUM_APPLES: 2)).to eq('1 result and 2 apples')
|
||||
expect(localize(NUM_RESULTS: 2, NUM_APPLES: 1)).to eq('2 results and 1 apple')
|
||||
end
|
||||
it 'handles double plurals' do
|
||||
setup_message_format('{NUM_RESULTS, plural,
|
||||
one {1 result}
|
||||
other {# results}
|
||||
} and {NUM_APPLES, plural,
|
||||
one {1 apple}
|
||||
other {# apples}
|
||||
}')
|
||||
|
||||
it 'handles select' do
|
||||
setup_message_format('{GENDER, select, male {He} female {She} other {They}} read a book')
|
||||
expect(localize(GENDER: 'male')).to eq('He read a book')
|
||||
expect(localize(GENDER: 'female')).to eq('She read a book')
|
||||
expect(localize(GENDER: 'none')).to eq('They read a book')
|
||||
end
|
||||
expect(localize(NUM_RESULTS: 1, NUM_APPLES: 2)).to eq('1 result and 2 apples')
|
||||
expect(localize(NUM_RESULTS: 2, NUM_APPLES: 1)).to eq('2 results and 1 apple')
|
||||
end
|
||||
|
||||
it 'can strip out message formats' do
|
||||
hash = {"a" => "b", "c" => { "d" => {"f_MF" => "bob"} }}
|
||||
expect(JsLocaleHelper.strip_out_message_formats!(hash)).to eq({"c.d.f_MF" => "bob"})
|
||||
expect(hash["c"]["d"]).to eq({})
|
||||
end
|
||||
it 'handles select' do
|
||||
setup_message_format('{GENDER, select, male {He} female {She} other {They}} read a book')
|
||||
expect(localize(GENDER: 'male')).to eq('He read a book')
|
||||
expect(localize(GENDER: 'female')).to eq('She read a book')
|
||||
expect(localize(GENDER: 'none')).to eq('They read a book')
|
||||
end
|
||||
|
||||
it 'handles message format special keys' do
|
||||
ctx = MiniRacer::Context.new
|
||||
ctx.eval("I18n = {};")
|
||||
it 'can strip out message formats' do
|
||||
hash = {"a" => "b", "c" => { "d" => {"f_MF" => "bob"} }}
|
||||
expect(JsLocaleHelper.strip_out_message_formats!(hash)).to eq({"c.d.f_MF" => "bob"})
|
||||
expect(hash["c"]["d"]).to eq({})
|
||||
end
|
||||
|
||||
JsLocaleHelper.set_translations 'en', {
|
||||
"en" =>
|
||||
{
|
||||
it 'handles message format special keys' do
|
||||
JsLocaleHelper.set_translations('en', {
|
||||
"en" => {
|
||||
"js" => {
|
||||
"hello" => "world",
|
||||
"test_MF" => "{HELLO} {COUNT, plural, one {1 duck} other {# ducks}}",
|
||||
@@ -87,26 +92,29 @@ describe JsLocaleHelper do
|
||||
"simple_MF" => "{COUNT, plural, one {1} other {#}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
ctx.eval(JsLocaleHelper.output_locale('en'))
|
||||
ctx = MiniRacer::Context.new
|
||||
ctx.eval("I18n = { pluralizationRules: {} };")
|
||||
ctx.eval(JsLocaleHelper.output_locale('en'))
|
||||
|
||||
expect(ctx.eval('I18n.translations["en"]["js"]["hello"]')).to eq("world")
|
||||
expect(ctx.eval('I18n.translations["en"]["js"]["test_MF"]')).to eq(nil)
|
||||
expect(ctx.eval('I18n.translations["en"]["js"]["hello"]')).to eq("world")
|
||||
expect(ctx.eval('I18n.translations["en"]["js"]["test_MF"]')).to eq(nil)
|
||||
|
||||
expect(ctx.eval('I18n.messageFormat("test_MF", { HELLO: "hi", COUNT: 3 })')).to eq("hi 3 ducks")
|
||||
expect(ctx.eval('I18n.messageFormat("error_MF", { HELLO: "hi", COUNT: 3 })')).to match(/Invalid Format/)
|
||||
expect(ctx.eval('I18n.messageFormat("missing", {})')).to match(/missing/)
|
||||
expect(ctx.eval('I18n.messageFormat("simple_MF", {})')).to match(/COUNT/) # error
|
||||
end
|
||||
expect(ctx.eval('I18n.messageFormat("test_MF", { HELLO: "hi", COUNT: 3 })')).to eq("hi 3 ducks")
|
||||
expect(ctx.eval('I18n.messageFormat("error_MF", { HELLO: "hi", COUNT: 3 })')).to match(/Invalid Format/)
|
||||
expect(ctx.eval('I18n.messageFormat("missing", {})')).to match(/missing/)
|
||||
expect(ctx.eval('I18n.messageFormat("simple_MF", {})')).to match(/COUNT/) # error
|
||||
end
|
||||
|
||||
it 'load pluralizations rules before precompile' do
|
||||
message = JsLocaleHelper.compile_message_format('ru', 'format')
|
||||
expect(message).not_to match 'Plural Function not found'
|
||||
it 'load pluralizations rules before precompile' do
|
||||
message = JsLocaleHelper.compile_message_format('ru', 'format')
|
||||
expect(message).not_to match 'Plural Function not found'
|
||||
end
|
||||
end
|
||||
|
||||
it 'performs fallbacks to english if a translation is not available' do
|
||||
JsLocaleHelper.set_translations 'en', {
|
||||
JsLocaleHelper.set_translations('en', {
|
||||
"en" => {
|
||||
"js" => {
|
||||
"only_english" => "1-en",
|
||||
@@ -115,8 +123,9 @@ describe JsLocaleHelper do
|
||||
"all_three" => "7-en",
|
||||
}
|
||||
}
|
||||
}
|
||||
JsLocaleHelper.set_translations 'ru', {
|
||||
})
|
||||
|
||||
JsLocaleHelper.set_translations('ru', {
|
||||
"ru" => {
|
||||
"js" => {
|
||||
"only_site" => "2-ru",
|
||||
@@ -125,8 +134,9 @@ describe JsLocaleHelper do
|
||||
"all_three" => "7-ru",
|
||||
}
|
||||
}
|
||||
}
|
||||
JsLocaleHelper.set_translations 'uk', {
|
||||
})
|
||||
|
||||
JsLocaleHelper.set_translations('uk', {
|
||||
"uk" => {
|
||||
"js" => {
|
||||
"only_user" => "4-uk",
|
||||
@@ -135,7 +145,7 @@ describe JsLocaleHelper do
|
||||
"all_three" => "7-uk",
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expected = {
|
||||
"none" => "[uk.js.none]",
|
||||
@@ -157,9 +167,9 @@ describe JsLocaleHelper do
|
||||
ctx.eval(JsLocaleHelper.output_locale(I18n.locale))
|
||||
ctx.eval('I18n.defaultLocale = "ru";')
|
||||
|
||||
# Test - unneeded translations are not emitted
|
||||
expect(ctx.eval('I18n.translations.en.js').keys).to eq(["only_english"])
|
||||
expect(ctx.eval('I18n.translations.ru.js').keys).to eq(["only_site", "english_and_site"])
|
||||
expect(ctx.eval('I18n.translations.en.js').keys).to contain_exactly("only_english")
|
||||
expect(ctx.eval('I18n.translations.ru.js').keys).to contain_exactly("only_site", "english_and_site")
|
||||
expect(ctx.eval('I18n.translations.uk.js').keys).to contain_exactly("all_three", "english_and_user", "only_user", "site_and_user")
|
||||
|
||||
expected.each do |key, expect|
|
||||
expect(ctx.eval("I18n.t(#{"js.#{key}".inspect})")).to eq(expect)
|
||||
|
||||
Reference in New Issue
Block a user