test_localization_sync.js (8039B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 const { AppConstants } = ChromeUtils.importESModule("resource://gre/modules/AppConstants.sys.mjs"); 5 6 // Disable `xpc::IsInAutomation()` so incomplete locales do not generate 7 // errors. 8 Services.prefs.setBoolPref( 9 "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer", 10 false 11 ); 12 13 add_task(function test_methods_calling() { 14 const l10nReg = new L10nRegistry(); 15 16 const fs = [ 17 { path: "/localization/de/browser/menu.ftl", source: ` 18 key-value1 = [de] Value2 19 ` }, 20 { path: "/localization/en-US/browser/menu.ftl", source: ` 21 key-value1 = [en] Value2 22 key-value2 = [en] Value3 23 key-attr = 24 .label = [en] Label 3 25 ` }, 26 ]; 27 28 const source = L10nFileSource.createMock("test", "app", ["de", "en-US"], "/localization/{locale}", fs); 29 l10nReg.registerSources([source]); 30 31 const l10n = new Localization([ 32 "/browser/menu.ftl", 33 ], true, l10nReg, ["de", "en-US"]); 34 35 36 { 37 let values = l10n.formatValuesSync([ 38 {id: "key-value1"}, 39 {id: "key-value2"}, 40 {id: "key-missing"}, 41 {id: "key-attr"} 42 ]); 43 44 strictEqual(values[0], "[de] Value2"); 45 strictEqual(values[1], "[en] Value3"); 46 strictEqual(values[2], null); 47 strictEqual(values[3], null); 48 } 49 50 { 51 let values = l10n.formatValuesSync([ 52 "key-value1", 53 "key-value2", 54 "key-missing", 55 "key-attr" 56 ]); 57 58 strictEqual(values[0], "[de] Value2"); 59 strictEqual(values[1], "[en] Value3"); 60 strictEqual(values[2], null); 61 strictEqual(values[3], null); 62 } 63 64 { 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); 69 } 70 71 { 72 let messages = l10n.formatMessagesSync([ 73 {id: "key-value1"}, 74 {id: "key-missing"}, 75 {id: "key-value2"}, 76 {id: "key-attr"}, 77 ]); 78 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); 83 } 84 }); 85 86 add_task(function test_builtins() { 87 const known_platforms = { 88 "linux": "linux", 89 "win": "windows", 90 "macosx": "macos", 91 "android": "android", 92 }; 93 94 const fs = [ 95 { path: "/localization/en-US/test.ftl", source: ` 96 key = { PLATFORM() -> 97 ${ Object.values(known_platforms).map( 98 name => ` [${ name }] ${ name.toUpperCase() } Value\n`).join("") } 99 *[other] OTHER Value 100 }` }, 101 ]; 102 103 const source = L10nFileSource.createMock("test", "app", ["en-US"], "/localization/{locale}", fs); 104 const l10nReg = new L10nRegistry(); 105 l10nReg.registerSources([source]); 106 107 const l10n = new Localization([ 108 "/test.ftl", 109 ], true, l10nReg, ["en-US"]); 110 111 let values = l10n.formatValuesSync([{id: "key"}]); 112 113 ok(values[0].includes( 114 `${ known_platforms[AppConstants.platform].toUpperCase() } Value`)); 115 }); 116 117 add_task(function test_add_remove_resourceIds() { 118 const fs = [ 119 { path: "/localization/en-US/browser/menu.ftl", source: "key1 = Value1" }, 120 { path: "/localization/en-US/toolkit/menu.ftl", source: "key2 = Value2" }, 121 ]; 122 const originalRequested = Services.locale.requestedLocales; 123 124 const source = L10nFileSource.createMock("test", "app", ["en-US"], "/localization/{locale}", fs); 125 const l10nReg = new L10nRegistry(); 126 l10nReg.registerSources([source]); 127 128 const l10n = new Localization(["/browser/menu.ftl"], true, l10nReg, ["en-US"]); 129 130 let values = l10n.formatValuesSync([{id: "key1"}, {id: "key2"}]); 131 132 strictEqual(values[0], "Value1"); 133 strictEqual(values[1], null); 134 135 l10n.addResourceIds(["/toolkit/menu.ftl"]); 136 137 values = l10n.formatValuesSync([{id: "key1"}, {id: "key2"}]); 138 139 strictEqual(values[0], "Value1"); 140 strictEqual(values[1], "Value2"); 141 142 values = l10n.formatValuesSync(["key1", {id: "key2"}]); 143 144 strictEqual(values[0], "Value1"); 145 strictEqual(values[1], "Value2"); 146 147 values = l10n.formatValuesSync([{id: "key1"}, "key2"]); 148 149 strictEqual(values[0], "Value1"); 150 strictEqual(values[1], "Value2"); 151 152 l10n.removeResourceIds(["/browser/menu.ftl"]); 153 154 values = l10n.formatValuesSync([{id: "key1"}, {id: "key2"}]); 155 156 strictEqual(values[0], null); 157 strictEqual(values[1], "Value2"); 158 }); 159 160 add_task(function test_calling_sync_methods_in_async_mode_fails() { 161 const l10n = new Localization(["/browser/menu.ftl"], false); 162 163 Assert.throws(() => { 164 l10n.formatValuesSync([{ id: "key1" }, { id: "key2" }]); 165 }, /Can't use formatValuesSync when state is async./); 166 167 Assert.throws(() => { 168 l10n.formatValueSync("key1"); 169 }, /Can't use formatValueSync when state is async./); 170 171 Assert.throws(() => { 172 l10n.formatMessagesSync([{ id: "key1"}]); 173 }, /Can't use formatMessagesSync when state is async./); 174 }); 175 176 /** 177 * This test verifies that when a required resource is missing, 178 * we fallback entirely to the next locale for all entries. 179 */ 180 add_task(function test_format_from_missing_required_resource() { 181 const l10nReg = new L10nRegistry(); 182 183 const fs = [ 184 { path: "/localization/de/browser/menu.ftl", source: ` 185 key-value = [de] Value1 186 ` }, 187 { path: "/localization/de/browser/missing-in-en-US.ftl", source: ` 188 key-missing = [de] MissingValue 189 ` }, 190 { path: "/localization/en-US/browser/menu.ftl", source: ` 191 key-value = [en] Value1 192 ` }, 193 ]; 194 195 const source = L10nFileSource.createMock("test", "app", ["de", "en-US"], "/localization/{locale}", fs); 196 l10nReg.registerSources([source]); 197 198 // returns correct contexts for [en-US, de] 199 200 let l10n = new Localization([ 201 "/browser/menu.ftl", 202 "/browser/missing-in-en-US.ftl", 203 ], true, l10nReg, ["en-US", "de"]); 204 205 { 206 let values = l10n.formatValuesSync([ 207 {id: "key-value"}, 208 {id: "key-missing"}, 209 ]); 210 211 strictEqual(values[0], "[de] Value1"); 212 strictEqual(values[1], "[de] MissingValue"); 213 } 214 215 // returns correct contexts for [de, en-US] 216 217 l10n = new Localization([ 218 "/browser/menu.ftl", 219 {path: "/browser/missing-in-en-US.ftl", optional: false}, 220 ], true, l10nReg, ["de", "en-US"]); 221 222 { 223 let values = l10n.formatValuesSync([ 224 {id: "key-value"}, 225 {id: "key-missing"}, 226 ]); 227 228 strictEqual(values[0], "[de] Value1"); 229 strictEqual(values[1], "[de] MissingValue"); 230 } 231 }); 232 233 /** 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. 237 */ 238 add_task(function test_format_from_missing_optional_resource() { 239 const l10nReg = new L10nRegistry(); 240 241 const fs = [ 242 { path: "/localization/de/browser/menu.ftl", source: ` 243 key-value = [de] Value1 244 ` }, 245 { path: "/localization/de/browser/missing-in-en-US.ftl", source: ` 246 key-missing = [de] MissingValue 247 ` }, 248 { path: "/localization/en-US/browser/menu.ftl", source: ` 249 key-value = [en] Value1 250 ` }, 251 ]; 252 253 const source = L10nFileSource.createMock("test", "app", ["de", "en-US"], "/localization/{locale}", fs); 254 l10nReg.registerSources([source]); 255 256 // returns correct contexts for [en-US, de] 257 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"]); 262 263 { 264 let values = l10n.formatValuesSync([ 265 {id: "key-value"}, 266 {id: "key-missing"}, 267 ]); 268 269 strictEqual(values[0], "[en] Value1"); 270 strictEqual(values[1], "[de] MissingValue"); 271 } 272 273 // returns correct contexts for [de, en-US] 274 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"]); 279 280 { 281 let values = l10n.formatValuesSync([ 282 {id: "key-value"}, 283 {id: "key-missing"}, 284 ]); 285 286 strictEqual(values[0], "[de] Value1"); 287 strictEqual(values[1], "[de] MissingValue"); 288 } 289 });