1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
4 const { AppConstants } = ChromeUtils.importESModule("resource://gre/modules/AppConstants.sys.mjs");
6 // Disable `xpc::IsInAutomation()` so incomplete locales do not generate
8 Services.prefs.setBoolPref(
9 "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer",
13 add_task(function test_methods_calling() {
14 const l10nReg = new L10nRegistry();
17 { path: "/localization/de/browser/menu.ftl", source: `
18 key-value1 = [de] Value2
20 { path: "/localization/en-US/browser/menu.ftl", source: `
21 key-value1 = [en] Value2
22 key-value2 = [en] Value3
28 const source = L10nFileSource.createMock("test", "app", ["de", "en-US"], "/localization/{locale}", fs);
29 l10nReg.registerSources([source]);
31 const l10n = new Localization([
33 ], true, l10nReg, ["de", "en-US"]);
37 let values = l10n.formatValuesSync([
44 strictEqual(values[0], "[de] Value2");
45 strictEqual(values[1], "[en] Value3");
46 strictEqual(values[2], null);
47 strictEqual(values[3], null);
51 let values = l10n.formatValuesSync([
58 strictEqual(values[0], "[de] Value2");
59 strictEqual(values[1], "[en] Value3");
60 strictEqual(values[2], null);
61 strictEqual(values[3], null);
65 strictEqual(l10n.formatValueSync("key-missing"), null);
66 strictEqual(l10n.formatValueSync("key-value1"), "[de] Value2");
67 strictEqual(l10n.formatValueSync("key-value2"), "[en] Value3");
68 strictEqual(l10n.formatValueSync("key-attr"), null);
72 let messages = l10n.formatMessagesSync([
79 strictEqual(messages[0].value, "[de] Value2");
80 strictEqual(messages[1], null);
81 strictEqual(messages[2].value, "[en] Value3");
82 strictEqual(messages[3].value, null);
86 add_task(function test_builtins() {
87 const known_platforms = {
95 { path: "/localization/en-US/test.ftl", source: `
97 ${ Object.values(known_platforms).map(
98 name => ` [${ name }] ${ name.toUpperCase() } Value\n`).join("") }
103 const source = L10nFileSource.createMock("test", "app", ["en-US"], "/localization/{locale}", fs);
104 const l10nReg = new L10nRegistry();
105 l10nReg.registerSources([source]);
107 const l10n = new Localization([
109 ], true, l10nReg, ["en-US"]);
111 let values = l10n.formatValuesSync([{id: "key"}]);
113 ok(values[0].includes(
114 `${ known_platforms[AppConstants.platform].toUpperCase() } Value`));
117 add_task(function test_add_remove_resourceIds() {
119 { path: "/localization/en-US/browser/menu.ftl", source: "key1 = Value1" },
120 { path: "/localization/en-US/toolkit/menu.ftl", source: "key2 = Value2" },
122 const originalRequested = Services.locale.requestedLocales;
124 const source = L10nFileSource.createMock("test", "app", ["en-US"], "/localization/{locale}", fs);
125 const l10nReg = new L10nRegistry();
126 l10nReg.registerSources([source]);
128 const l10n = new Localization(["/browser/menu.ftl"], true, l10nReg, ["en-US"]);
130 let values = l10n.formatValuesSync([{id: "key1"}, {id: "key2"}]);
132 strictEqual(values[0], "Value1");
133 strictEqual(values[1], null);
135 l10n.addResourceIds(["/toolkit/menu.ftl"]);
137 values = l10n.formatValuesSync([{id: "key1"}, {id: "key2"}]);
139 strictEqual(values[0], "Value1");
140 strictEqual(values[1], "Value2");
142 values = l10n.formatValuesSync(["key1", {id: "key2"}]);
144 strictEqual(values[0], "Value1");
145 strictEqual(values[1], "Value2");
147 values = l10n.formatValuesSync([{id: "key1"}, "key2"]);
149 strictEqual(values[0], "Value1");
150 strictEqual(values[1], "Value2");
152 l10n.removeResourceIds(["/browser/menu.ftl"]);
154 values = l10n.formatValuesSync([{id: "key1"}, {id: "key2"}]);
156 strictEqual(values[0], null);
157 strictEqual(values[1], "Value2");
160 add_task(function test_calling_sync_methods_in_async_mode_fails() {
161 const l10n = new Localization(["/browser/menu.ftl"], false);
163 Assert.throws(() => {
164 l10n.formatValuesSync([{ id: "key1" }, { id: "key2" }]);
165 }, /Can't use formatValuesSync when state is async./);
167 Assert.throws(() => {
168 l10n.formatValueSync("key1");
169 }, /Can't use formatValueSync when state is async./);
171 Assert.throws(() => {
172 l10n.formatMessagesSync([{ id: "key1"}]);
173 }, /Can't use formatMessagesSync when state is async./);
177 * This test verifies that when a required resource is missing,
178 * we fallback entirely to the next locale for all entries.
180 add_task(function test_format_from_missing_required_resource() {
181 const l10nReg = new L10nRegistry();
184 { path: "/localization/de/browser/menu.ftl", source: `
185 key-value = [de] Value1
187 { path: "/localization/de/browser/missing-in-en-US.ftl", source: `
188 key-missing = [de] MissingValue
190 { path: "/localization/en-US/browser/menu.ftl", source: `
191 key-value = [en] Value1
195 const source = L10nFileSource.createMock("test", "app", ["de", "en-US"], "/localization/{locale}", fs);
196 l10nReg.registerSources([source]);
198 // returns correct contexts for [en-US, de]
200 let l10n = new Localization([
202 "/browser/missing-in-en-US.ftl",
203 ], true, l10nReg, ["en-US", "de"]);
206 let values = l10n.formatValuesSync([
211 strictEqual(values[0], "[de] Value1");
212 strictEqual(values[1], "[de] MissingValue");
215 // returns correct contexts for [de, en-US]
217 l10n = new Localization([
219 {path: "/browser/missing-in-en-US.ftl", optional: false},
220 ], true, l10nReg, ["de", "en-US"]);
223 let values = l10n.formatValuesSync([
228 strictEqual(values[0], "[de] Value1");
229 strictEqual(values[1], "[de] MissingValue");
234 * This test verifies that when an optional resource is missing
235 * we continue to populate entires from other resources in the same locale
236 * and only fallback entries from the optional resource to the next locale.
238 add_task(function test_format_from_missing_optional_resource() {
239 const l10nReg = new L10nRegistry();
242 { path: "/localization/de/browser/menu.ftl", source: `
243 key-value = [de] Value1
245 { path: "/localization/de/browser/missing-in-en-US.ftl", source: `
246 key-missing = [de] MissingValue
248 { path: "/localization/en-US/browser/menu.ftl", source: `
249 key-value = [en] Value1
253 const source = L10nFileSource.createMock("test", "app", ["de", "en-US"], "/localization/{locale}", fs);
254 l10nReg.registerSources([source]);
256 // returns correct contexts for [en-US, de]
258 let l10n = new Localization([
259 {path: "/browser/menu.ftl", optional: false},
260 {path: "/browser/missing-in-en-US.ftl", optional: true},
261 ], true, l10nReg, ["en-US", "de"]);
264 let values = l10n.formatValuesSync([
269 strictEqual(values[0], "[en] Value1");
270 strictEqual(values[1], "[de] MissingValue");
273 // returns correct contexts for [de, en-US]
275 l10n = new Localization([
276 {path: "/browser/menu.ftl", optional: false},
277 {path: "/browser/missing-in-en-US.ftl", optional: true},
278 ], true, l10nReg, ["de", "en-US"]);
281 let values = l10n.formatValuesSync([
286 strictEqual(values[0], "[de] Value1");
287 strictEqual(values[1], "[de] MissingValue");