mirror of
https://github.com/discourse/discourse.git
synced 2025-09-05 08:59:27 +08:00
FEATURE: Allow plugins to register a new locale
This commit is contained in:
parent
ba6cd83e3a
commit
eb52c5469e
29 changed files with 480 additions and 71 deletions
48
spec/components/fallback_locale_list_spec.rb
Normal file
48
spec/components/fallback_locale_list_spec.rb
Normal file
|
@ -0,0 +1,48 @@
|
|||
require 'rails_helper'
|
||||
require 'i18n/backend/fallback_locale_list'
|
||||
|
||||
describe I18n::Backend::FallbackLocaleList do
|
||||
let(:list) { I18n::Backend::FallbackLocaleList.new }
|
||||
|
||||
it "works when default_locale is English" do
|
||||
SiteSetting.default_locale = :en
|
||||
|
||||
expect(list[:ru]).to eq([:ru, :en])
|
||||
expect(list[:en]).to eq([:en])
|
||||
end
|
||||
|
||||
it "works when default_locale is not English" do
|
||||
SiteSetting.default_locale = :de
|
||||
|
||||
expect(list[:ru]).to eq([:ru, :de, :en])
|
||||
expect(list[:de]).to eq([:de, :en])
|
||||
expect(list[:en]).to eq([:en, :de])
|
||||
end
|
||||
|
||||
context "when plugin registered fallback locale" do
|
||||
before do
|
||||
DiscoursePluginRegistry.register_locale("es_MX", fallbackLocale: "es")
|
||||
DiscoursePluginRegistry.register_locale("de_AT", fallbackLocale: "de")
|
||||
end
|
||||
|
||||
after do
|
||||
DiscoursePluginRegistry.reset!
|
||||
end
|
||||
|
||||
it "works when default_locale is English" do
|
||||
SiteSetting.default_locale = :en
|
||||
|
||||
expect(list[:de_AT]).to eq([:de_AT, :de, :en])
|
||||
expect(list[:de]).to eq([:de, :en])
|
||||
expect(list[:en]).to eq([:en])
|
||||
end
|
||||
|
||||
it "works when default_locale is not English" do
|
||||
SiteSetting.default_locale = :de
|
||||
|
||||
expect(list[:es_MX]).to eq([:es_MX, :es, :de, :en])
|
||||
expect(list[:es]).to eq([:es, :de, :en])
|
||||
expect(list[:en]).to eq([:en, :de])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,9 @@
|
|||
require "rails_helper"
|
||||
|
||||
describe "translate accelerator" do
|
||||
after do
|
||||
I18n.reload!
|
||||
end
|
||||
|
||||
it "overrides for both string and symbol keys" do
|
||||
key = "user.email.not_allowed"
|
||||
|
@ -32,4 +35,39 @@ describe "translate accelerator" do
|
|||
end
|
||||
end
|
||||
|
||||
context "plugins" do
|
||||
before do
|
||||
DiscoursePluginRegistry.register_locale(
|
||||
"foo",
|
||||
name: "Foo",
|
||||
nativeName: "Foo Bar",
|
||||
plural: {
|
||||
keys: [:one, :few, :other],
|
||||
rule: lambda do |n|
|
||||
return :one if n == 1
|
||||
return :few if n < 10
|
||||
:other
|
||||
end
|
||||
}
|
||||
)
|
||||
|
||||
LocaleSiteSetting.reset!
|
||||
I18n.reload!
|
||||
end
|
||||
|
||||
after do
|
||||
DiscoursePluginRegistry.reset!
|
||||
LocaleSiteSetting.reset!
|
||||
end
|
||||
|
||||
it "loads plural rules from plugins" do
|
||||
I18n.backend.store_translations(:foo, items: { one: 'one item', few: 'some items', other: "%{count} items" })
|
||||
I18n.locale = :foo
|
||||
|
||||
expect(I18n.t('i18n.plural.keys')).to eq([:one, :few, :other])
|
||||
expect(I18n.t('items', count: 1)).to eq('one item')
|
||||
expect(I18n.t('items', count: 3)).to eq('some items')
|
||||
expect(I18n.t('items', count: 20)).to eq('20 items')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -34,12 +34,17 @@ describe JsLocaleHelper do
|
|||
end
|
||||
|
||||
context "message format" do
|
||||
def message_format_filename(locale)
|
||||
Rails.root + "lib/javascripts/locale/#{locale}.js"
|
||||
end
|
||||
|
||||
def setup_message_format(format)
|
||||
filename = message_format_filename('en')
|
||||
compiled = JsLocaleHelper.compile_message_format(filename, 'en', 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.load(filename)
|
||||
@ctx.eval("var test = #{compiled}")
|
||||
end
|
||||
|
||||
|
@ -110,7 +115,7 @@ describe JsLocaleHelper do
|
|||
end
|
||||
|
||||
it 'load pluralizations rules before precompile' do
|
||||
message = JsLocaleHelper.compile_message_format('ru', 'format')
|
||||
message = JsLocaleHelper.compile_message_format(message_format_filename('ru'), 'ru', 'format')
|
||||
expect(message).not_to match 'Plural Function not found'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,8 +10,8 @@ describe Plugin::Instance do
|
|||
context "find_all" do
|
||||
it "can find plugins correctly" do
|
||||
plugins = Plugin::Instance.find_all("#{Rails.root}/spec/fixtures/plugins")
|
||||
expect(plugins.count).to eq(1)
|
||||
plugin = plugins[0]
|
||||
expect(plugins.count).to eq(2)
|
||||
plugin = plugins[1]
|
||||
|
||||
expect(plugin.name).to eq("plugin-name")
|
||||
expect(plugin.path).to eq("#{Rails.root}/spec/fixtures/plugins/my_plugin/plugin.rb")
|
||||
|
@ -268,4 +268,108 @@ describe Plugin::Instance do
|
|||
expect(called).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context "locales" do
|
||||
let(:plugin_path) { "#{Rails.root}/spec/fixtures/plugins/custom_locales" }
|
||||
let!(:plugin) { Plugin::Instance.new(nil, "#{plugin_path}/plugin.rb") }
|
||||
let(:plural) do
|
||||
{
|
||||
keys: [:one, :few, :other],
|
||||
rule: lambda do |n|
|
||||
return :one if n == 1
|
||||
return :few if n < 10
|
||||
:other
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def register_locale(locale, opts)
|
||||
plugin.register_locale(locale, opts)
|
||||
plugin.activate!
|
||||
|
||||
DiscoursePluginRegistry.locales[locale]
|
||||
end
|
||||
|
||||
it "enables the registered locales only on activate" do
|
||||
plugin.register_locale("foo", name: "Foo", nativeName: "Foo Bar", plural: plural)
|
||||
plugin.register_locale("es_MX", name: "Spanish (Mexico)", nativeName: "Español (México)", fallbackLocale: "es")
|
||||
expect(DiscoursePluginRegistry.locales.count).to eq(0)
|
||||
|
||||
plugin.activate!
|
||||
expect(DiscoursePluginRegistry.locales.count).to eq(2)
|
||||
end
|
||||
|
||||
it "allows finding the locale by string and symbol" do
|
||||
register_locale("foo", name: "Foo", nativeName: "Foo Bar", plural: plural)
|
||||
|
||||
expect(DiscoursePluginRegistry.locales).to have_key(:foo)
|
||||
expect(DiscoursePluginRegistry.locales).to have_key('foo')
|
||||
end
|
||||
|
||||
it "correctly registers a new locale" do
|
||||
locale = register_locale("foo", name: "Foo", nativeName: "Foo Bar", plural: plural)
|
||||
|
||||
expect(DiscoursePluginRegistry.locales.count).to eq(1)
|
||||
expect(DiscoursePluginRegistry.locales).to have_key(:foo)
|
||||
|
||||
expect(locale[:fallbackLocale]).to be_nil
|
||||
expect(locale[:message_format]).to eq(["foo", "#{plugin_path}/lib/javascripts/locale/message_format/foo.js"])
|
||||
expect(locale[:moment_js]).to eq(["foo", "#{plugin_path}/lib/javascripts/locale/moment_js/foo.js"])
|
||||
expect(locale[:plural]).to eq(plural.with_indifferent_access)
|
||||
|
||||
expect(Rails.configuration.assets.precompile).to include("locales/foo.js")
|
||||
end
|
||||
|
||||
it "correctly registers a new locale using a fallback locale" do
|
||||
locale = register_locale("es_MX", name: "Spanish (Mexico)", nativeName: "Español (México)", fallbackLocale: "es")
|
||||
|
||||
expect(DiscoursePluginRegistry.locales.count).to eq(1)
|
||||
expect(DiscoursePluginRegistry.locales).to have_key(:es_MX)
|
||||
|
||||
expect(locale[:fallbackLocale]).to eq("es")
|
||||
expect(locale[:message_format]).to eq(["es", "#{Rails.root}/lib/javascripts/locale/es.js"])
|
||||
expect(locale[:moment_js]).to eq(["es", "#{Rails.root}/lib/javascripts/moment_locale/es.js"])
|
||||
expect(locale[:plural]).to be_nil
|
||||
|
||||
expect(Rails.configuration.assets.precompile).to include("locales/es_MX.js")
|
||||
end
|
||||
|
||||
it "correctly registers a new locale when some files exist in core" do
|
||||
locale = register_locale("tlh", name: "Klingon", nativeName: "tlhIngan Hol", plural: plural)
|
||||
|
||||
expect(DiscoursePluginRegistry.locales.count).to eq(1)
|
||||
expect(DiscoursePluginRegistry.locales).to have_key(:tlh)
|
||||
|
||||
expect(locale[:fallbackLocale]).to be_nil
|
||||
expect(locale[:message_format]).to eq(["tlh", "#{plugin_path}/lib/javascripts/locale/message_format/tlh.js"])
|
||||
expect(locale[:moment_js]).to eq(["tlh", "#{Rails.root}/lib/javascripts/moment_locale/tlh.js"])
|
||||
expect(locale[:plural]).to eq(plural.with_indifferent_access)
|
||||
|
||||
expect(Rails.configuration.assets.precompile).to include("locales/tlh.js")
|
||||
end
|
||||
|
||||
it "does not register a new locale when the fallback locale does not exist" do
|
||||
register_locale("bar", name: "Bar", nativeName: "Bar", fallbackLocale: "foo")
|
||||
expect(DiscoursePluginRegistry.locales.count).to eq(0)
|
||||
end
|
||||
|
||||
[
|
||||
"config/locales/client.foo.yml",
|
||||
"config/locales/server.foo.yml",
|
||||
"lib/javascripts/locale/message_format/foo.js",
|
||||
"lib/javascripts/locale/moment_js/foo.js",
|
||||
"assets/locales/foo.js.erb"
|
||||
].each do |path|
|
||||
it "does not register a new locale when #{path} is missing" do
|
||||
path = "#{plugin_path}/#{path}"
|
||||
File.stubs('exist?').returns(false)
|
||||
File.stubs('exist?').with(regexp_matches(/#{Regexp.quote(plugin_path)}.*/)).returns(true)
|
||||
File.stubs('exist?').with(path).returns(false)
|
||||
|
||||
register_locale("foo", name: "Foo", nativeName: "Foo Bar", plural: plural)
|
||||
expect(DiscoursePluginRegistry.locales.count).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
2
spec/fixtures/plugins/custom_locales/assets/locales/es_MX.js.erb
vendored
Normal file
2
spec/fixtures/plugins/custom_locales/assets/locales/es_MX.js.erb
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
//= require locales/i18n
|
||||
<%= JsLocaleHelper.output_locale(:es_MX) %>
|
2
spec/fixtures/plugins/custom_locales/assets/locales/foo.js.erb
vendored
Normal file
2
spec/fixtures/plugins/custom_locales/assets/locales/foo.js.erb
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
//= require locales/i18n
|
||||
<%= JsLocaleHelper.output_locale(:foo) %>
|
2
spec/fixtures/plugins/custom_locales/assets/locales/tlh.js.erb
vendored
Normal file
2
spec/fixtures/plugins/custom_locales/assets/locales/tlh.js.erb
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
//= require locales/i18n
|
||||
<%= JsLocaleHelper.output_locale(:tlh) %>
|
1
spec/fixtures/plugins/custom_locales/config/locales/client.es_MX.yml
vendored
Normal file
1
spec/fixtures/plugins/custom_locales/config/locales/client.es_MX.yml
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
es_MX:
|
1
spec/fixtures/plugins/custom_locales/config/locales/client.foo.yml
vendored
Normal file
1
spec/fixtures/plugins/custom_locales/config/locales/client.foo.yml
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
foo:
|
1
spec/fixtures/plugins/custom_locales/config/locales/client.tlh.yml
vendored
Normal file
1
spec/fixtures/plugins/custom_locales/config/locales/client.tlh.yml
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
tlh:
|
1
spec/fixtures/plugins/custom_locales/config/locales/server.es_MX.yml
vendored
Normal file
1
spec/fixtures/plugins/custom_locales/config/locales/server.es_MX.yml
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
es_MX:
|
1
spec/fixtures/plugins/custom_locales/config/locales/server.foo.yml
vendored
Normal file
1
spec/fixtures/plugins/custom_locales/config/locales/server.foo.yml
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
foo:
|
1
spec/fixtures/plugins/custom_locales/config/locales/server.tlh.yml
vendored
Normal file
1
spec/fixtures/plugins/custom_locales/config/locales/server.tlh.yml
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
tlh:
|
1
spec/fixtures/plugins/custom_locales/lib/javascripts/locale/message_format/foo.js
vendored
Normal file
1
spec/fixtures/plugins/custom_locales/lib/javascripts/locale/message_format/foo.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
// this file should contain plural rules
|
1
spec/fixtures/plugins/custom_locales/lib/javascripts/locale/message_format/tlh.js
vendored
Normal file
1
spec/fixtures/plugins/custom_locales/lib/javascripts/locale/message_format/tlh.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
// this file should contain plural rules
|
1
spec/fixtures/plugins/custom_locales/lib/javascripts/locale/moment_js/foo.js
vendored
Normal file
1
spec/fixtures/plugins/custom_locales/lib/javascripts/locale/moment_js/foo.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
// this file should contain the locale configuration for moment.js
|
4
spec/fixtures/plugins/custom_locales/plugin.rb
vendored
Normal file
4
spec/fixtures/plugins/custom_locales/plugin.rb
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
# name: custom-locales
|
||||
# about: Fixtures for plugin that adds new locales
|
||||
# version: 1.0
|
||||
# authors: Gerhard Schlager
|
|
@ -1,6 +1,15 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe LocaleSiteSetting do
|
||||
def core_locales
|
||||
pattern = File.join(Rails.root, 'config', 'locales', 'client.*.yml')
|
||||
Dir.glob(pattern).map { |x| x.split('.')[-2] }
|
||||
end
|
||||
|
||||
def native_locale_name(locale)
|
||||
value = LocaleSiteSetting.values.find { |v| v[:value] == locale }
|
||||
value[:name]
|
||||
end
|
||||
|
||||
describe 'valid_value?' do
|
||||
it 'returns true for a locale that we have translations for' do
|
||||
|
@ -14,8 +23,69 @@ describe LocaleSiteSetting do
|
|||
|
||||
describe 'values' do
|
||||
it 'returns all the locales that we have translations for' do
|
||||
expect(LocaleSiteSetting.values.map { |x| x[:value] }).to include(*Dir.glob(File.join(Rails.root, 'config', 'locales', 'client.*.yml')).map { |x| x.split('.')[-2] })
|
||||
expect(LocaleSiteSetting.values.map { |x| x[:value] }).to include(*core_locales)
|
||||
end
|
||||
|
||||
it 'returns native names' do
|
||||
expect(native_locale_name('de')).to eq('Deutsch')
|
||||
expect(native_locale_name('zh_CN')).to eq('中文')
|
||||
expect(native_locale_name('zh_TW')).to eq('中文 (TW)')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with locales from plugin' do
|
||||
before do
|
||||
DiscoursePluginRegistry.register_locale("foo", name: "Foo", nativeName: "Native Foo")
|
||||
DiscoursePluginRegistry.register_locale("bar", name: "Bar", nativeName: "Native Bar")
|
||||
DiscoursePluginRegistry.register_locale("de", name: "Renamed German", nativeName: "Native renamed German")
|
||||
DiscoursePluginRegistry.register_locale("de_AT", name: "German (Austria)", nativeName: "Österreichisch", fallbackLocale: "de")
|
||||
DiscoursePluginRegistry.register_locale("tlh")
|
||||
|
||||
# Plugins normally register a locale before LocaleSiteSetting is initialized.
|
||||
# That's not happening in tests, so we need to call reset!
|
||||
LocaleSiteSetting.reset!
|
||||
end
|
||||
|
||||
after do
|
||||
DiscoursePluginRegistry.reset!
|
||||
end
|
||||
|
||||
describe 'valid_value?' do
|
||||
it 'returns true for locales from core' do
|
||||
expect(LocaleSiteSetting.valid_value?('en')).to eq(true)
|
||||
expect(LocaleSiteSetting.valid_value?('de')).to eq(true)
|
||||
end
|
||||
|
||||
it 'returns true for locales added by plugins' do
|
||||
expect(LocaleSiteSetting.valid_value?('foo')).to eq(true)
|
||||
expect(LocaleSiteSetting.valid_value?('bar')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'values' do
|
||||
it 'returns native names added by plugin' do
|
||||
expect(native_locale_name('foo')).to eq('Native Foo')
|
||||
expect(native_locale_name('bar')).to eq('Native Bar')
|
||||
end
|
||||
|
||||
it 'does not allow plugins to override native names that exist in core' do
|
||||
expect(native_locale_name('de')).to eq('Deutsch')
|
||||
end
|
||||
|
||||
it 'returns the language code when no nativeName is set' do
|
||||
expect(native_locale_name('tlh')).to eq('tlh')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'fallback_locale' do
|
||||
it 'returns the fallback locale registered by plugin' do
|
||||
expect(LocaleSiteSetting.fallback_locale('de_AT')).to eq(:de)
|
||||
expect(LocaleSiteSetting.fallback_locale(:de_AT)).to eq(:de)
|
||||
end
|
||||
|
||||
it 'returns nothing when no fallback locale was registered' do
|
||||
expect(LocaleSiteSetting.fallback_locale('foo')).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue