2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-03-04 01:15:08 +08:00
discourse/spec/lib/js_locale_helper_spec.rb
David Taylor d7de0f6735
DEV: Refactor locale bundle loading (#37114)
Previously, locale bundles were using `require()` directly, and were
very sensitive to load order. This made it very hard to refactor things,
especially for our upcoming move to Vite.

This commit updates the four types of locale bundle to contain only very
simple JS code, with no dependencies at the top level. They simply add
POJO and functions to the `window._discourse_locale_data` global. When
`discourse-i18n` is loaded, it checks that global, loads up the data,
and executes the functions (passing in any dependencies like
messageformat/runtime where required).

Changes in the HTML files are to bring the locale bundles up to the
first position, since they no longer have any dependencies, and we need
to be 100% sure they're loaded before discourse-i18n.

Tests are updated for the new bundle format, and the most complex ones
have been converted to system specs, so that we no longer need to create
a mock environment for executing messageformat/discourse-i18n/etc.

`lib/deprecated` changes (and associated pretty-text changes) are to
make the dependencies more formalized, because `require()` is subject to
race conditions, which started being hit following the locale refactor.

---------

Co-authored-by: Jarek Radosz <jradosz@gmail.com>
2026-01-16 11:45:14 +00:00

84 lines
2.3 KiB
Ruby

# frozen_string_literal: true
RSpec.describe JsLocaleHelper do
let(:v8_ctx) do
ctx = MiniRacer::Context.new
ctx.eval("var window = globalThis;")
ctx
end
module StubLoadTranslations
def set_translations(locale, translations)
@loaded_translations ||= ActiveSupport::HashWithIndifferentAccess.new
@loaded_translations[locale] = translations
end
def clear_cache!
@loaded_translations = nil
@loaded_merges = nil
end
end
JsLocaleHelper.extend StubLoadTranslations
before { JsLocaleHelper.clear_cache! }
after { JsLocaleHelper.clear_cache! }
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
LocaleSiteSetting.values.each do |locale|
it "generates valid JS for #{locale[:value]} locale" do
js = JsLocaleHelper.output_locale(locale[:value])
v8_ctx.eval(js)
end
it "finds moment.js locale file for #{locale[:value]}" do
content = JsLocaleHelper.moment_locale(locale[:value])
if (locale[:value] == SiteSettings::DefaultsProvider::DEFAULT_LOCALE)
expect(content).to eq("")
else
expect(content).to_not eq("")
end
end
it "generates valid MF locales for the '#{locale[:value]}' locale" do
expect(described_class.output_MF(locale[:value])).not_to match(/Failed to compile/)
end
end
describe ".output_client_overrides" do
subject(:client_overrides) { described_class.output_client_overrides("en") }
before do
Fabricate(
:translation_override,
locale: "en",
translation_key: "js.user.preferences.title",
value: "SHOULD_SHOW",
)
Fabricate(
:translation_override,
locale: "en",
translation_key: "js.user.preferences",
value: "SHOULD_NOT_SHOW",
status: "deprecated",
)
end
it "does not output deprecated translation overrides" do
expect(client_overrides).to include("SHOULD_SHOW")
expect(client_overrides).not_to include("SHOULD_NOT_SHOW")
end
end
end