@dialpad/i18n 1.22.3 → 1.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/force-pull-translations.js +2 -0
- package/bin/pull-translations.js +2 -0
- package/bin/should-pull.js +2 -0
- package/bin/translate-dialpadistan.js +2 -0
- package/bin/translation-screenshots-check.js +2 -0
- package/bin/upload-translation-service.js +2 -0
- package/dist/i18n.cjs +883 -878
- package/dist/i18n.cjs.map +1 -1
- package/dist/i18n.js +883 -878
- package/dist/i18n.js.map +1 -1
- package/dist/types/index.d.ts +2 -4
- package/dist/types/index.js +1 -2
- package/{README.md → docs/README.md} +280 -84
- package/index.ts +18 -5
- package/package.json +50 -26
- package/.eslintignore +0 -1
- package/.eslintrc.cjs +0 -12
- package/.prettierignore +0 -3
- package/.rush/temp/chunked-rush-logs/i18n.build.chunks.jsonl +0 -22
- package/.rush/temp/chunked-rush-logs/i18n.format.chunks.jsonl +0 -19
- package/.rush/temp/chunked-rush-logs/i18n.lint.chunks.jsonl +0 -2
- package/.rush/temp/package-deps_build.json +0 -24
- package/.rush/temp/package-deps_format.json +0 -24
- package/.rush/temp/package-deps_lint.json +0 -24
- package/.rush/temp/shrinkwrap-deps.json +0 -12
- package/CHANGELOG.json +0 -63
- package/CHANGELOG.md +0 -30
- package/base-tsconfig.json +0 -19
- package/dialpad-i18n-1.22.2.tgz +0 -0
- package/dist/types/src/locale-manager.d.ts +0 -53
- package/dist/types/src/locale-manager.js +0 -146
- package/eslint-tsconfig.json +0 -5
- package/index.html +0 -11
- package/rush-logs/i18n.build.error.log +0 -0
- package/rush-logs/i18n.build.log +0 -22
- package/rush-logs/i18n.format.error.log +0 -0
- package/rush-logs/i18n.format.log +0 -19
- package/rush-logs/i18n.lint.error.log +0 -0
- package/rush-logs/i18n.lint.log +0 -2
- package/src/__test__/locale-manager.find.test.ts +0 -78
- package/src/__test__/locale-manager.formatters.test.ts +0 -139
- package/src/__test__/locale-manager.multiple.test.ts +0 -349
- package/src/__test__/locale-manager.test.ts +0 -511
- package/src/locale-manager.ts +0 -198
- package/tsconfig.json +0 -10
- package/vite.config.ts +0 -39
package/dist/i18n.cjs
CHANGED
|
@@ -765,7 +765,7 @@ var init_esm_shims$1 = __esm$1({
|
|
|
765
765
|
}
|
|
766
766
|
});
|
|
767
767
|
var require_rfdc = __commonJS$1({
|
|
768
|
-
"../../node_modules/.pnpm/rfdc@1.4.1/node_modules/rfdc/index.js"(
|
|
768
|
+
"../../node_modules/.pnpm/rfdc@1.4.1/node_modules/rfdc/index.js"(exports$1, module2) {
|
|
769
769
|
init_esm_shims$1();
|
|
770
770
|
module2.exports = rfdc2;
|
|
771
771
|
function copyBuffer(cur) {
|
|
@@ -1271,7 +1271,7 @@ var init_esm_shims = __esm({
|
|
|
1271
1271
|
}
|
|
1272
1272
|
});
|
|
1273
1273
|
var require_speakingurl = __commonJS({
|
|
1274
|
-
"../../node_modules/.pnpm/speakingurl@14.0.1/node_modules/speakingurl/lib/speakingurl.js"(
|
|
1274
|
+
"../../node_modules/.pnpm/speakingurl@14.0.1/node_modules/speakingurl/lib/speakingurl.js"(exports$1, module2) {
|
|
1275
1275
|
init_esm_shims();
|
|
1276
1276
|
(function(root) {
|
|
1277
1277
|
var charMap = {
|
|
@@ -2792,11 +2792,11 @@ var require_speakingurl = __commonJS({
|
|
|
2792
2792
|
} catch (e) {
|
|
2793
2793
|
}
|
|
2794
2794
|
}
|
|
2795
|
-
})(
|
|
2795
|
+
})(exports$1);
|
|
2796
2796
|
}
|
|
2797
2797
|
});
|
|
2798
2798
|
var require_speakingurl2 = __commonJS({
|
|
2799
|
-
"../../node_modules/.pnpm/speakingurl@14.0.1/node_modules/speakingurl/index.js"(
|
|
2799
|
+
"../../node_modules/.pnpm/speakingurl@14.0.1/node_modules/speakingurl/index.js"(exports$1, module2) {
|
|
2800
2800
|
init_esm_shims();
|
|
2801
2801
|
module2.exports = require_speakingurl();
|
|
2802
2802
|
}
|
|
@@ -3358,7 +3358,7 @@ init_esm_shims();
|
|
|
3358
3358
|
init_esm_shims();
|
|
3359
3359
|
var TIMELINE_LAYERS_STATE_STORAGE_ID = "__VUE_DEVTOOLS_KIT_TIMELINE_LAYERS_STATE__";
|
|
3360
3360
|
function getTimelineLayersStateFromStorage() {
|
|
3361
|
-
if (!isBrowser || typeof localStorage === "undefined" || localStorage === null) {
|
|
3361
|
+
if (typeof window === "undefined" || !isBrowser || typeof localStorage === "undefined" || localStorage === null) {
|
|
3362
3362
|
return {
|
|
3363
3363
|
recordingState: false,
|
|
3364
3364
|
mouseEventEnabled: false,
|
|
@@ -3368,7 +3368,7 @@ function getTimelineLayersStateFromStorage() {
|
|
|
3368
3368
|
selected: ""
|
|
3369
3369
|
};
|
|
3370
3370
|
}
|
|
3371
|
-
const state = localStorage.getItem(TIMELINE_LAYERS_STATE_STORAGE_ID);
|
|
3371
|
+
const state = typeof localStorage.getItem !== "undefined" ? localStorage.getItem(TIMELINE_LAYERS_STATE_STORAGE_ID) : null;
|
|
3372
3372
|
return state ? JSON.parse(state) : {
|
|
3373
3373
|
recordingState: false,
|
|
3374
3374
|
mouseEventEnabled: false,
|
|
@@ -5579,889 +5579,889 @@ function createStorageWrapper() {
|
|
|
5579
5579
|
}
|
|
5580
5580
|
return globalThis.__i18nStorage;
|
|
5581
5581
|
}
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
/**
|
|
5626
|
-
* Format this `FluentNumber` to a string.
|
|
5627
|
-
*/
|
|
5628
|
-
toString(scope) {
|
|
5629
|
-
try {
|
|
5630
|
-
const nf = scope.memoizeIntlObject(Intl.NumberFormat, this.opts);
|
|
5631
|
-
return nf.format(this.value);
|
|
5632
|
-
} catch (err) {
|
|
5633
|
-
scope.reportError(err);
|
|
5634
|
-
return this.value.toString(10);
|
|
5582
|
+
const RE_MESSAGE_START = /^(-?[a-zA-Z][\w-]*) *= */gm;
|
|
5583
|
+
const RE_ATTRIBUTE_START = /\.([a-zA-Z][\w-]*) *= */y;
|
|
5584
|
+
const RE_VARIANT_START = /\*?\[/y;
|
|
5585
|
+
const RE_NUMBER_LITERAL = /(-?[0-9]+(?:\.([0-9]+))?)/y;
|
|
5586
|
+
const RE_IDENTIFIER = /([a-zA-Z][\w-]*)/y;
|
|
5587
|
+
const RE_REFERENCE = /([$-])?([a-zA-Z][\w-]*)(?:\.([a-zA-Z][\w-]*))?/y;
|
|
5588
|
+
const RE_FUNCTION_NAME = /^[A-Z][A-Z0-9_-]*$/;
|
|
5589
|
+
const RE_TEXT_RUN = /([^{}\n\r]+)/y;
|
|
5590
|
+
const RE_STRING_RUN = /([^\\"\n\r]*)/y;
|
|
5591
|
+
const RE_STRING_ESCAPE = /\\([\\"])/y;
|
|
5592
|
+
const RE_UNICODE_ESCAPE = /\\u([a-fA-F0-9]{4})|\\U([a-fA-F0-9]{6})/y;
|
|
5593
|
+
const RE_LEADING_NEWLINES = /^\n+/;
|
|
5594
|
+
const RE_TRAILING_SPACES = / +$/;
|
|
5595
|
+
const RE_BLANK_LINES = / *\r?\n/g;
|
|
5596
|
+
const RE_INDENT = /( *)$/;
|
|
5597
|
+
const TOKEN_BRACE_OPEN = /{\s*/y;
|
|
5598
|
+
const TOKEN_BRACE_CLOSE = /\s*}/y;
|
|
5599
|
+
const TOKEN_BRACKET_OPEN = /\[\s*/y;
|
|
5600
|
+
const TOKEN_BRACKET_CLOSE = /\s*] */y;
|
|
5601
|
+
const TOKEN_PAREN_OPEN = /\s*\(\s*/y;
|
|
5602
|
+
const TOKEN_ARROW = /\s*->\s*/y;
|
|
5603
|
+
const TOKEN_COLON = /\s*:\s*/y;
|
|
5604
|
+
const TOKEN_COMMA = /\s*,?\s*/y;
|
|
5605
|
+
const TOKEN_BLANK = /\s+/y;
|
|
5606
|
+
class FluentResource {
|
|
5607
|
+
constructor(source) {
|
|
5608
|
+
this.body = [];
|
|
5609
|
+
RE_MESSAGE_START.lastIndex = 0;
|
|
5610
|
+
let cursor = 0;
|
|
5611
|
+
while (true) {
|
|
5612
|
+
let next = RE_MESSAGE_START.exec(source);
|
|
5613
|
+
if (next === null) {
|
|
5614
|
+
break;
|
|
5615
|
+
}
|
|
5616
|
+
cursor = RE_MESSAGE_START.lastIndex;
|
|
5617
|
+
try {
|
|
5618
|
+
this.body.push(parseMessage(next[1]));
|
|
5619
|
+
} catch (err) {
|
|
5620
|
+
if (err instanceof SyntaxError) {
|
|
5621
|
+
continue;
|
|
5622
|
+
}
|
|
5623
|
+
throw err;
|
|
5624
|
+
}
|
|
5635
5625
|
}
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
/**
|
|
5640
|
-
* Create an instance of `FluentDateTime` with options to the
|
|
5641
|
-
* `Intl.DateTimeFormat` constructor.
|
|
5642
|
-
*
|
|
5643
|
-
* @param value The number value of this `FluentDateTime`, in milliseconds.
|
|
5644
|
-
* @param opts Options which will be passed to `Intl.DateTimeFormat`.
|
|
5645
|
-
*/
|
|
5646
|
-
constructor(value, opts = {}) {
|
|
5647
|
-
super(value);
|
|
5648
|
-
this.opts = opts;
|
|
5649
|
-
}
|
|
5650
|
-
/**
|
|
5651
|
-
* Format this `FluentDateTime` to a string.
|
|
5652
|
-
*/
|
|
5653
|
-
toString(scope) {
|
|
5654
|
-
try {
|
|
5655
|
-
const dtf = scope.memoizeIntlObject(Intl.DateTimeFormat, this.opts);
|
|
5656
|
-
return dtf.format(this.value);
|
|
5657
|
-
} catch (err) {
|
|
5658
|
-
scope.reportError(err);
|
|
5659
|
-
return new Date(this.value).toISOString();
|
|
5626
|
+
function test(re) {
|
|
5627
|
+
re.lastIndex = cursor;
|
|
5628
|
+
return re.test(source);
|
|
5660
5629
|
}
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
if (key instanceof FluentNumber2 && selector instanceof FluentNumber2 && key.value === selector.value) {
|
|
5671
|
-
return true;
|
|
5672
|
-
}
|
|
5673
|
-
if (selector instanceof FluentNumber2 && typeof key === "string") {
|
|
5674
|
-
let category = scope.memoizeIntlObject(Intl.PluralRules, selector.opts).select(selector.value);
|
|
5675
|
-
if (key === category) {
|
|
5676
|
-
return true;
|
|
5630
|
+
function consumeChar(char, errorClass) {
|
|
5631
|
+
if (source[cursor] === char) {
|
|
5632
|
+
cursor++;
|
|
5633
|
+
return true;
|
|
5634
|
+
}
|
|
5635
|
+
if (errorClass) {
|
|
5636
|
+
throw new errorClass(`Expected ${char}`);
|
|
5637
|
+
}
|
|
5638
|
+
return false;
|
|
5677
5639
|
}
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
}
|
|
5688
|
-
function getArguments(scope, args) {
|
|
5689
|
-
const positional = [];
|
|
5690
|
-
const named = /* @__PURE__ */ Object.create(null);
|
|
5691
|
-
for (const arg of args) {
|
|
5692
|
-
if (arg.type === "narg") {
|
|
5693
|
-
named[arg.name] = resolveExpression(scope, arg.value);
|
|
5694
|
-
} else {
|
|
5695
|
-
positional.push(resolveExpression(scope, arg));
|
|
5640
|
+
function consumeToken(re, errorClass) {
|
|
5641
|
+
if (test(re)) {
|
|
5642
|
+
cursor = re.lastIndex;
|
|
5643
|
+
return true;
|
|
5644
|
+
}
|
|
5645
|
+
if (errorClass) {
|
|
5646
|
+
throw new errorClass(`Expected ${re.toString()}`);
|
|
5647
|
+
}
|
|
5648
|
+
return false;
|
|
5696
5649
|
}
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
return new FluentNumber2(expr.value, {
|
|
5706
|
-
minimumFractionDigits: expr.precision
|
|
5707
|
-
});
|
|
5708
|
-
case "var":
|
|
5709
|
-
return resolveVariableReference(scope, expr);
|
|
5710
|
-
case "mesg":
|
|
5711
|
-
return resolveMessageReference(scope, expr);
|
|
5712
|
-
case "term":
|
|
5713
|
-
return resolveTermReference(scope, expr);
|
|
5714
|
-
case "func":
|
|
5715
|
-
return resolveFunctionReference(scope, expr);
|
|
5716
|
-
case "select":
|
|
5717
|
-
return resolveSelectExpression(scope, expr);
|
|
5718
|
-
default:
|
|
5719
|
-
return new FluentNone2();
|
|
5720
|
-
}
|
|
5721
|
-
}
|
|
5722
|
-
function resolveVariableReference(scope, { name }) {
|
|
5723
|
-
let arg;
|
|
5724
|
-
if (scope.params) {
|
|
5725
|
-
if (Object.prototype.hasOwnProperty.call(scope.params, name)) {
|
|
5726
|
-
arg = scope.params[name];
|
|
5727
|
-
} else {
|
|
5728
|
-
return new FluentNone2(`$${name}`);
|
|
5650
|
+
function match2(re) {
|
|
5651
|
+
re.lastIndex = cursor;
|
|
5652
|
+
let result = re.exec(source);
|
|
5653
|
+
if (result === null) {
|
|
5654
|
+
throw new SyntaxError(`Expected ${re.toString()}`);
|
|
5655
|
+
}
|
|
5656
|
+
cursor = re.lastIndex;
|
|
5657
|
+
return result;
|
|
5729
5658
|
}
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
}
|
|
5739
|
-
switch (typeof arg) {
|
|
5740
|
-
case "string":
|
|
5741
|
-
return arg;
|
|
5742
|
-
case "number":
|
|
5743
|
-
return new FluentNumber2(arg);
|
|
5744
|
-
case "object":
|
|
5745
|
-
if (arg instanceof Date) {
|
|
5746
|
-
return new FluentDateTime2(arg.getTime());
|
|
5659
|
+
function match1(re) {
|
|
5660
|
+
return match2(re)[1];
|
|
5661
|
+
}
|
|
5662
|
+
function parseMessage(id) {
|
|
5663
|
+
let value = parsePattern();
|
|
5664
|
+
let attributes = parseAttributes();
|
|
5665
|
+
if (value === null && Object.keys(attributes).length === 0) {
|
|
5666
|
+
throw new SyntaxError("Expected message value or attributes");
|
|
5747
5667
|
}
|
|
5748
|
-
|
|
5749
|
-
scope.reportError(new TypeError(`Variable type not supported: $${name}, ${typeof arg}`));
|
|
5750
|
-
return new FluentNone2(`$${name}`);
|
|
5751
|
-
}
|
|
5752
|
-
}
|
|
5753
|
-
function resolveMessageReference(scope, { name, attr }) {
|
|
5754
|
-
const message = scope.bundle._messages.get(name);
|
|
5755
|
-
if (!message) {
|
|
5756
|
-
scope.reportError(new ReferenceError(`Unknown message: ${name}`));
|
|
5757
|
-
return new FluentNone2(name);
|
|
5758
|
-
}
|
|
5759
|
-
if (attr) {
|
|
5760
|
-
const attribute = message.attributes[attr];
|
|
5761
|
-
if (attribute) {
|
|
5762
|
-
return resolvePattern(scope, attribute);
|
|
5668
|
+
return { id, value, attributes };
|
|
5763
5669
|
}
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
const term = scope.bundle._terms.get(id);
|
|
5776
|
-
if (!term) {
|
|
5777
|
-
scope.reportError(new ReferenceError(`Unknown term: ${id}`));
|
|
5778
|
-
return new FluentNone2(id);
|
|
5779
|
-
}
|
|
5780
|
-
if (attr) {
|
|
5781
|
-
const attribute = term.attributes[attr];
|
|
5782
|
-
if (attribute) {
|
|
5783
|
-
scope.params = getArguments(scope, args).named;
|
|
5784
|
-
const resolved2 = resolvePattern(scope, attribute);
|
|
5785
|
-
scope.params = null;
|
|
5786
|
-
return resolved2;
|
|
5787
|
-
}
|
|
5788
|
-
scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`));
|
|
5789
|
-
return new FluentNone2(`${id}.${attr}`);
|
|
5790
|
-
}
|
|
5791
|
-
scope.params = getArguments(scope, args).named;
|
|
5792
|
-
const resolved = resolvePattern(scope, term.value);
|
|
5793
|
-
scope.params = null;
|
|
5794
|
-
return resolved;
|
|
5795
|
-
}
|
|
5796
|
-
function resolveFunctionReference(scope, { name, args }) {
|
|
5797
|
-
let func = scope.bundle._functions[name];
|
|
5798
|
-
if (!func) {
|
|
5799
|
-
scope.reportError(new ReferenceError(`Unknown function: ${name}()`));
|
|
5800
|
-
return new FluentNone2(`${name}()`);
|
|
5801
|
-
}
|
|
5802
|
-
if (typeof func !== "function") {
|
|
5803
|
-
scope.reportError(new TypeError(`Function ${name}() is not callable`));
|
|
5804
|
-
return new FluentNone2(`${name}()`);
|
|
5805
|
-
}
|
|
5806
|
-
try {
|
|
5807
|
-
let resolved = getArguments(scope, args);
|
|
5808
|
-
return func(resolved.positional, resolved.named);
|
|
5809
|
-
} catch (err) {
|
|
5810
|
-
scope.reportError(err);
|
|
5811
|
-
return new FluentNone2(`${name}()`);
|
|
5812
|
-
}
|
|
5813
|
-
}
|
|
5814
|
-
function resolveSelectExpression(scope, { selector, variants, star }) {
|
|
5815
|
-
let sel = resolveExpression(scope, selector);
|
|
5816
|
-
if (sel instanceof FluentNone2) {
|
|
5817
|
-
return getDefault(scope, variants, star);
|
|
5818
|
-
}
|
|
5819
|
-
for (const variant of variants) {
|
|
5820
|
-
const key = resolveExpression(scope, variant.key);
|
|
5821
|
-
if (match(scope, sel, key)) {
|
|
5822
|
-
return resolvePattern(scope, variant.value);
|
|
5823
|
-
}
|
|
5824
|
-
}
|
|
5825
|
-
return getDefault(scope, variants, star);
|
|
5826
|
-
}
|
|
5827
|
-
function resolveComplexPattern(scope, ptn) {
|
|
5828
|
-
if (scope.dirty.has(ptn)) {
|
|
5829
|
-
scope.reportError(new RangeError("Cyclic reference"));
|
|
5830
|
-
return new FluentNone2();
|
|
5831
|
-
}
|
|
5832
|
-
scope.dirty.add(ptn);
|
|
5833
|
-
const result = [];
|
|
5834
|
-
const useIsolating = scope.bundle._useIsolating && ptn.length > 1;
|
|
5835
|
-
for (const elem of ptn) {
|
|
5836
|
-
if (typeof elem === "string") {
|
|
5837
|
-
result.push(scope.bundle._transform(elem));
|
|
5838
|
-
continue;
|
|
5670
|
+
function parseAttributes() {
|
|
5671
|
+
let attrs = /* @__PURE__ */ Object.create(null);
|
|
5672
|
+
while (test(RE_ATTRIBUTE_START)) {
|
|
5673
|
+
let name = match1(RE_ATTRIBUTE_START);
|
|
5674
|
+
let value = parsePattern();
|
|
5675
|
+
if (value === null) {
|
|
5676
|
+
throw new SyntaxError("Expected attribute value");
|
|
5677
|
+
}
|
|
5678
|
+
attrs[name] = value;
|
|
5679
|
+
}
|
|
5680
|
+
return attrs;
|
|
5839
5681
|
}
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5682
|
+
function parsePattern() {
|
|
5683
|
+
let first;
|
|
5684
|
+
if (test(RE_TEXT_RUN)) {
|
|
5685
|
+
first = match1(RE_TEXT_RUN);
|
|
5686
|
+
}
|
|
5687
|
+
if (source[cursor] === "{" || source[cursor] === "}") {
|
|
5688
|
+
return parsePatternElements(first ? [first] : [], Infinity);
|
|
5689
|
+
}
|
|
5690
|
+
let indent = parseIndent();
|
|
5691
|
+
if (indent) {
|
|
5692
|
+
if (first) {
|
|
5693
|
+
return parsePatternElements([first, indent], indent.length);
|
|
5694
|
+
}
|
|
5695
|
+
indent.value = trim(indent.value, RE_LEADING_NEWLINES);
|
|
5696
|
+
return parsePatternElements([indent], indent.length);
|
|
5697
|
+
}
|
|
5698
|
+
if (first) {
|
|
5699
|
+
return trim(first, RE_TRAILING_SPACES);
|
|
5700
|
+
}
|
|
5701
|
+
return null;
|
|
5844
5702
|
}
|
|
5845
|
-
|
|
5846
|
-
|
|
5703
|
+
function parsePatternElements(elements = [], commonIndent) {
|
|
5704
|
+
while (true) {
|
|
5705
|
+
if (test(RE_TEXT_RUN)) {
|
|
5706
|
+
elements.push(match1(RE_TEXT_RUN));
|
|
5707
|
+
continue;
|
|
5708
|
+
}
|
|
5709
|
+
if (source[cursor] === "{") {
|
|
5710
|
+
elements.push(parsePlaceable());
|
|
5711
|
+
continue;
|
|
5712
|
+
}
|
|
5713
|
+
if (source[cursor] === "}") {
|
|
5714
|
+
throw new SyntaxError("Unbalanced closing brace");
|
|
5715
|
+
}
|
|
5716
|
+
let indent = parseIndent();
|
|
5717
|
+
if (indent) {
|
|
5718
|
+
elements.push(indent);
|
|
5719
|
+
commonIndent = Math.min(commonIndent, indent.length);
|
|
5720
|
+
continue;
|
|
5721
|
+
}
|
|
5722
|
+
break;
|
|
5723
|
+
}
|
|
5724
|
+
let lastIndex = elements.length - 1;
|
|
5725
|
+
let lastElement = elements[lastIndex];
|
|
5726
|
+
if (typeof lastElement === "string") {
|
|
5727
|
+
elements[lastIndex] = trim(lastElement, RE_TRAILING_SPACES);
|
|
5728
|
+
}
|
|
5729
|
+
let baked = [];
|
|
5730
|
+
for (let element of elements) {
|
|
5731
|
+
if (element instanceof Indent) {
|
|
5732
|
+
element = element.value.slice(0, element.value.length - commonIndent);
|
|
5733
|
+
}
|
|
5734
|
+
if (element) {
|
|
5735
|
+
baked.push(element);
|
|
5736
|
+
}
|
|
5737
|
+
}
|
|
5738
|
+
return baked;
|
|
5847
5739
|
}
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5740
|
+
function parsePlaceable() {
|
|
5741
|
+
consumeToken(TOKEN_BRACE_OPEN, SyntaxError);
|
|
5742
|
+
let selector = parseInlineExpression();
|
|
5743
|
+
if (consumeToken(TOKEN_BRACE_CLOSE)) {
|
|
5744
|
+
return selector;
|
|
5745
|
+
}
|
|
5746
|
+
if (consumeToken(TOKEN_ARROW)) {
|
|
5747
|
+
let variants = parseVariants();
|
|
5748
|
+
consumeToken(TOKEN_BRACE_CLOSE, SyntaxError);
|
|
5749
|
+
return {
|
|
5750
|
+
type: "select",
|
|
5751
|
+
selector,
|
|
5752
|
+
...variants
|
|
5753
|
+
};
|
|
5754
|
+
}
|
|
5755
|
+
throw new SyntaxError("Unclosed placeable");
|
|
5851
5756
|
}
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
}
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5757
|
+
function parseInlineExpression() {
|
|
5758
|
+
if (source[cursor] === "{") {
|
|
5759
|
+
return parsePlaceable();
|
|
5760
|
+
}
|
|
5761
|
+
if (test(RE_REFERENCE)) {
|
|
5762
|
+
let [, sigil, name, attr = null] = match2(RE_REFERENCE);
|
|
5763
|
+
if (sigil === "$") {
|
|
5764
|
+
return { type: "var", name };
|
|
5765
|
+
}
|
|
5766
|
+
if (consumeToken(TOKEN_PAREN_OPEN)) {
|
|
5767
|
+
let args = parseArguments();
|
|
5768
|
+
if (sigil === "-") {
|
|
5769
|
+
return { type: "term", name, attr, args };
|
|
5770
|
+
}
|
|
5771
|
+
if (RE_FUNCTION_NAME.test(name)) {
|
|
5772
|
+
return { type: "func", name, args };
|
|
5773
|
+
}
|
|
5774
|
+
throw new SyntaxError("Function names must be all upper-case");
|
|
5775
|
+
}
|
|
5776
|
+
if (sigil === "-") {
|
|
5777
|
+
return {
|
|
5778
|
+
type: "term",
|
|
5779
|
+
name,
|
|
5780
|
+
attr,
|
|
5781
|
+
args: []
|
|
5782
|
+
};
|
|
5783
|
+
}
|
|
5784
|
+
return { type: "mesg", name, attr };
|
|
5785
|
+
}
|
|
5786
|
+
return parseLiteral();
|
|
5874
5787
|
}
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5788
|
+
function parseArguments() {
|
|
5789
|
+
let args = [];
|
|
5790
|
+
while (true) {
|
|
5791
|
+
switch (source[cursor]) {
|
|
5792
|
+
case ")":
|
|
5793
|
+
cursor++;
|
|
5794
|
+
return args;
|
|
5795
|
+
case void 0:
|
|
5796
|
+
throw new SyntaxError("Unclosed argument list");
|
|
5797
|
+
}
|
|
5798
|
+
args.push(parseArgument());
|
|
5799
|
+
consumeToken(TOKEN_COMMA);
|
|
5800
|
+
}
|
|
5882
5801
|
}
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5802
|
+
function parseArgument() {
|
|
5803
|
+
let expr = parseInlineExpression();
|
|
5804
|
+
if (expr.type !== "mesg") {
|
|
5805
|
+
return expr;
|
|
5806
|
+
}
|
|
5807
|
+
if (consumeToken(TOKEN_COLON)) {
|
|
5808
|
+
return {
|
|
5809
|
+
type: "narg",
|
|
5810
|
+
name: expr.name,
|
|
5811
|
+
value: parseLiteral()
|
|
5812
|
+
};
|
|
5813
|
+
}
|
|
5814
|
+
return expr;
|
|
5886
5815
|
}
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5816
|
+
function parseVariants() {
|
|
5817
|
+
let variants = [];
|
|
5818
|
+
let count = 0;
|
|
5819
|
+
let star;
|
|
5820
|
+
while (test(RE_VARIANT_START)) {
|
|
5821
|
+
if (consumeChar("*")) {
|
|
5822
|
+
star = count;
|
|
5823
|
+
}
|
|
5824
|
+
let key = parseVariantKey();
|
|
5825
|
+
let value = parsePattern();
|
|
5826
|
+
if (value === null) {
|
|
5827
|
+
throw new SyntaxError("Expected variant value");
|
|
5828
|
+
}
|
|
5829
|
+
variants[count++] = { key, value };
|
|
5830
|
+
}
|
|
5831
|
+
if (count === 0) {
|
|
5832
|
+
return null;
|
|
5833
|
+
}
|
|
5834
|
+
if (star === void 0) {
|
|
5835
|
+
throw new SyntaxError("Expected default variant");
|
|
5836
|
+
}
|
|
5837
|
+
return { variants, star };
|
|
5838
|
+
}
|
|
5839
|
+
function parseVariantKey() {
|
|
5840
|
+
consumeToken(TOKEN_BRACKET_OPEN, SyntaxError);
|
|
5841
|
+
let key;
|
|
5842
|
+
if (test(RE_NUMBER_LITERAL)) {
|
|
5843
|
+
key = parseNumberLiteral();
|
|
5844
|
+
} else {
|
|
5845
|
+
key = {
|
|
5846
|
+
type: "str",
|
|
5847
|
+
value: match1(RE_IDENTIFIER)
|
|
5848
|
+
};
|
|
5849
|
+
}
|
|
5850
|
+
consumeToken(TOKEN_BRACKET_CLOSE, SyntaxError);
|
|
5851
|
+
return key;
|
|
5852
|
+
}
|
|
5853
|
+
function parseLiteral() {
|
|
5854
|
+
if (test(RE_NUMBER_LITERAL)) {
|
|
5855
|
+
return parseNumberLiteral();
|
|
5856
|
+
}
|
|
5857
|
+
if (source[cursor] === '"') {
|
|
5858
|
+
return parseStringLiteral();
|
|
5859
|
+
}
|
|
5860
|
+
throw new SyntaxError("Invalid expression");
|
|
5861
|
+
}
|
|
5862
|
+
function parseNumberLiteral() {
|
|
5863
|
+
let [, value, fraction = ""] = match2(RE_NUMBER_LITERAL);
|
|
5864
|
+
let precision = fraction.length;
|
|
5865
|
+
return {
|
|
5866
|
+
type: "num",
|
|
5867
|
+
value: parseFloat(value),
|
|
5868
|
+
precision
|
|
5869
|
+
};
|
|
5870
|
+
}
|
|
5871
|
+
function parseStringLiteral() {
|
|
5872
|
+
consumeChar('"', SyntaxError);
|
|
5873
|
+
let value = "";
|
|
5874
|
+
while (true) {
|
|
5875
|
+
value += match1(RE_STRING_RUN);
|
|
5876
|
+
if (source[cursor] === "\\") {
|
|
5877
|
+
value += parseEscapeSequence();
|
|
5878
|
+
continue;
|
|
5879
|
+
}
|
|
5880
|
+
if (consumeChar('"')) {
|
|
5881
|
+
return { type: "str", value };
|
|
5882
|
+
}
|
|
5883
|
+
throw new SyntaxError("Unclosed string literal");
|
|
5884
|
+
}
|
|
5885
|
+
}
|
|
5886
|
+
function parseEscapeSequence() {
|
|
5887
|
+
if (test(RE_STRING_ESCAPE)) {
|
|
5888
|
+
return match1(RE_STRING_ESCAPE);
|
|
5889
|
+
}
|
|
5890
|
+
if (test(RE_UNICODE_ESCAPE)) {
|
|
5891
|
+
let [, codepoint4, codepoint6] = match2(RE_UNICODE_ESCAPE);
|
|
5892
|
+
let codepoint = parseInt(codepoint4 || codepoint6, 16);
|
|
5893
|
+
return codepoint <= 55295 || 57344 <= codepoint ? String.fromCodePoint(codepoint) : "�";
|
|
5894
|
+
}
|
|
5895
|
+
throw new SyntaxError("Unknown escape sequence");
|
|
5896
|
+
}
|
|
5897
|
+
function parseIndent() {
|
|
5898
|
+
let start = cursor;
|
|
5899
|
+
consumeToken(TOKEN_BLANK);
|
|
5900
|
+
switch (source[cursor]) {
|
|
5901
|
+
case ".":
|
|
5902
|
+
case "[":
|
|
5903
|
+
case "*":
|
|
5904
|
+
case "}":
|
|
5905
|
+
case void 0:
|
|
5906
|
+
return false;
|
|
5907
|
+
case "{":
|
|
5908
|
+
return makeIndent(source.slice(start, cursor));
|
|
5909
|
+
}
|
|
5910
|
+
if (source[cursor - 1] === " ") {
|
|
5911
|
+
return makeIndent(source.slice(start, cursor));
|
|
5912
|
+
}
|
|
5913
|
+
return false;
|
|
5914
|
+
}
|
|
5915
|
+
function trim(text, re) {
|
|
5916
|
+
return text.replace(re, "");
|
|
5917
|
+
}
|
|
5918
|
+
function makeIndent(blank) {
|
|
5919
|
+
let value = blank.replace(RE_BLANK_LINES, "\n");
|
|
5920
|
+
let length = RE_INDENT.exec(blank)[1].length;
|
|
5921
|
+
return new Indent(value, length);
|
|
5895
5922
|
}
|
|
5896
5923
|
}
|
|
5897
|
-
return unwrapped;
|
|
5898
|
-
}
|
|
5899
|
-
const NUMBER_ALLOWED = [
|
|
5900
|
-
"unitDisplay",
|
|
5901
|
-
"currencyDisplay",
|
|
5902
|
-
"useGrouping",
|
|
5903
|
-
"minimumIntegerDigits",
|
|
5904
|
-
"minimumFractionDigits",
|
|
5905
|
-
"maximumFractionDigits",
|
|
5906
|
-
"minimumSignificantDigits",
|
|
5907
|
-
"maximumSignificantDigits"
|
|
5908
|
-
];
|
|
5909
|
-
function NUMBER(args, opts) {
|
|
5910
|
-
let arg = args[0];
|
|
5911
|
-
if (arg instanceof FluentNone2) {
|
|
5912
|
-
return new FluentNone2(`NUMBER(${arg.valueOf()})`);
|
|
5913
|
-
}
|
|
5914
|
-
if (arg instanceof FluentNumber2) {
|
|
5915
|
-
return new FluentNumber2(arg.valueOf(), {
|
|
5916
|
-
...arg.opts,
|
|
5917
|
-
...values(opts, NUMBER_ALLOWED)
|
|
5918
|
-
});
|
|
5919
|
-
}
|
|
5920
|
-
if (arg instanceof FluentDateTime2) {
|
|
5921
|
-
return new FluentNumber2(arg.valueOf(), {
|
|
5922
|
-
...values(opts, NUMBER_ALLOWED)
|
|
5923
|
-
});
|
|
5924
|
-
}
|
|
5925
|
-
throw new TypeError("Invalid argument to NUMBER");
|
|
5926
|
-
}
|
|
5927
|
-
const DATETIME_ALLOWED = [
|
|
5928
|
-
"dateStyle",
|
|
5929
|
-
"timeStyle",
|
|
5930
|
-
"fractionalSecondDigits",
|
|
5931
|
-
"dayPeriod",
|
|
5932
|
-
"hour12",
|
|
5933
|
-
"weekday",
|
|
5934
|
-
"era",
|
|
5935
|
-
"year",
|
|
5936
|
-
"month",
|
|
5937
|
-
"day",
|
|
5938
|
-
"hour",
|
|
5939
|
-
"minute",
|
|
5940
|
-
"second",
|
|
5941
|
-
"timeZoneName"
|
|
5942
|
-
];
|
|
5943
|
-
function DATETIME(args, opts) {
|
|
5944
|
-
let arg = args[0];
|
|
5945
|
-
if (arg instanceof FluentNone2) {
|
|
5946
|
-
return new FluentNone2(`DATETIME(${arg.valueOf()})`);
|
|
5947
|
-
}
|
|
5948
|
-
if (arg instanceof FluentDateTime2) {
|
|
5949
|
-
return new FluentDateTime2(arg.valueOf(), {
|
|
5950
|
-
...arg.opts,
|
|
5951
|
-
...values(opts, DATETIME_ALLOWED)
|
|
5952
|
-
});
|
|
5953
|
-
}
|
|
5954
|
-
if (arg instanceof FluentNumber2) {
|
|
5955
|
-
return new FluentDateTime2(arg.valueOf(), {
|
|
5956
|
-
...values(opts, DATETIME_ALLOWED)
|
|
5957
|
-
});
|
|
5958
|
-
}
|
|
5959
|
-
throw new TypeError("Invalid argument to DATETIME");
|
|
5960
5924
|
}
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
if (memoizer === void 0) {
|
|
5966
|
-
memoizer = /* @__PURE__ */ new Map();
|
|
5967
|
-
cache.set(stringLocale, memoizer);
|
|
5925
|
+
class Indent {
|
|
5926
|
+
constructor(value, length) {
|
|
5927
|
+
this.value = value;
|
|
5928
|
+
this.length = length;
|
|
5968
5929
|
}
|
|
5969
|
-
return memoizer;
|
|
5970
5930
|
}
|
|
5971
|
-
class
|
|
5931
|
+
class FluentType2 {
|
|
5972
5932
|
/**
|
|
5973
|
-
* Create
|
|
5974
|
-
*
|
|
5975
|
-
* The `locales` argument is used to instantiate `Intl` formatters used by
|
|
5976
|
-
* translations. The `options` object can be used to configure the bundle.
|
|
5977
|
-
*
|
|
5978
|
-
* Examples:
|
|
5979
|
-
*
|
|
5980
|
-
* let bundle = new FluentBundle(["en-US", "en"]);
|
|
5981
|
-
*
|
|
5982
|
-
* let bundle = new FluentBundle(locales, {useIsolating: false});
|
|
5983
|
-
*
|
|
5984
|
-
* let bundle = new FluentBundle(locales, {
|
|
5985
|
-
* useIsolating: true,
|
|
5986
|
-
* functions: {
|
|
5987
|
-
* NODE_ENV: () => process.env.NODE_ENV
|
|
5988
|
-
* }
|
|
5989
|
-
* });
|
|
5990
|
-
*
|
|
5991
|
-
* Available options:
|
|
5992
|
-
*
|
|
5993
|
-
* - `functions` - an object of additional functions available to
|
|
5994
|
-
* translations as builtins.
|
|
5995
|
-
*
|
|
5996
|
-
* - `useIsolating` - boolean specifying whether to use Unicode isolation
|
|
5997
|
-
* marks (FSI, PDI) for bidi interpolations. Default: `true`.
|
|
5933
|
+
* Create a `FluentType` instance.
|
|
5998
5934
|
*
|
|
5999
|
-
*
|
|
5935
|
+
* @param value The JavaScript value to wrap.
|
|
6000
5936
|
*/
|
|
6001
|
-
constructor(
|
|
6002
|
-
this.
|
|
6003
|
-
this._messages = /* @__PURE__ */ new Map();
|
|
6004
|
-
this.locales = Array.isArray(locales) ? locales : [locales];
|
|
6005
|
-
this._functions = {
|
|
6006
|
-
NUMBER,
|
|
6007
|
-
DATETIME,
|
|
6008
|
-
...functions
|
|
6009
|
-
};
|
|
6010
|
-
this._useIsolating = useIsolating;
|
|
6011
|
-
this._transform = transform;
|
|
6012
|
-
this._intls = getMemoizerForLocale(locales);
|
|
5937
|
+
constructor(value) {
|
|
5938
|
+
this.value = value;
|
|
6013
5939
|
}
|
|
6014
5940
|
/**
|
|
6015
|
-
*
|
|
6016
|
-
*
|
|
6017
|
-
* @param id - The identifier of the message to check.
|
|
5941
|
+
* Unwrap the raw value stored by this `FluentType`.
|
|
6018
5942
|
*/
|
|
6019
|
-
|
|
6020
|
-
return this.
|
|
5943
|
+
valueOf() {
|
|
5944
|
+
return this.value;
|
|
6021
5945
|
}
|
|
5946
|
+
}
|
|
5947
|
+
class FluentNone2 extends FluentType2 {
|
|
6022
5948
|
/**
|
|
6023
|
-
*
|
|
6024
|
-
*
|
|
6025
|
-
* Raw messages are `{value, attributes}` shapes containing translation units
|
|
6026
|
-
* called `Patterns`. `Patterns` are implementation-specific; they should be
|
|
6027
|
-
* treated as black boxes and formatted with `FluentBundle.formatPattern`.
|
|
6028
|
-
*
|
|
6029
|
-
* @param id - The identifier of the message to check.
|
|
5949
|
+
* Create an instance of `FluentNone` with an optional fallback value.
|
|
5950
|
+
* @param value The fallback value of this `FluentNone`.
|
|
6030
5951
|
*/
|
|
6031
|
-
|
|
6032
|
-
|
|
5952
|
+
constructor(value = "???") {
|
|
5953
|
+
super(value);
|
|
6033
5954
|
}
|
|
6034
5955
|
/**
|
|
6035
|
-
*
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
*
|
|
6044
|
-
*
|
|
6045
|
-
*
|
|
6046
|
-
* - `allowOverrides` - boolean specifying whether it's allowed to override
|
|
6047
|
-
* an existing message or term with a new value. Default: `false`.
|
|
5956
|
+
* Format this `FluentNone` to the fallback string.
|
|
5957
|
+
*/
|
|
5958
|
+
toString(scope) {
|
|
5959
|
+
return `{${this.value}}`;
|
|
5960
|
+
}
|
|
5961
|
+
}
|
|
5962
|
+
class FluentNumber2 extends FluentType2 {
|
|
5963
|
+
/**
|
|
5964
|
+
* Create an instance of `FluentNumber` with options to the
|
|
5965
|
+
* `Intl.NumberFormat` constructor.
|
|
6048
5966
|
*
|
|
6049
|
-
* @param
|
|
6050
|
-
* @param
|
|
5967
|
+
* @param value The number value of this `FluentNumber`.
|
|
5968
|
+
* @param opts Options which will be passed to `Intl.NumberFormat`.
|
|
6051
5969
|
*/
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
}
|
|
6067
|
-
this._messages.set(entry.id, entry);
|
|
6068
|
-
}
|
|
5970
|
+
constructor(value, opts = {}) {
|
|
5971
|
+
super(value);
|
|
5972
|
+
this.opts = opts;
|
|
5973
|
+
}
|
|
5974
|
+
/**
|
|
5975
|
+
* Format this `FluentNumber` to a string.
|
|
5976
|
+
*/
|
|
5977
|
+
toString(scope) {
|
|
5978
|
+
try {
|
|
5979
|
+
const nf = scope.memoizeIntlObject(Intl.NumberFormat, this.opts);
|
|
5980
|
+
return nf.format(this.value);
|
|
5981
|
+
} catch (err) {
|
|
5982
|
+
scope.reportError(err);
|
|
5983
|
+
return this.value.toString(10);
|
|
6069
5984
|
}
|
|
6070
|
-
return errors;
|
|
6071
5985
|
}
|
|
5986
|
+
}
|
|
5987
|
+
class FluentDateTime2 extends FluentType2 {
|
|
6072
5988
|
/**
|
|
6073
|
-
*
|
|
6074
|
-
*
|
|
6075
|
-
* Format a raw `Pattern` into a string. `args` will be used to resolve
|
|
6076
|
-
* references to variables passed as arguments to the translation.
|
|
6077
|
-
*
|
|
6078
|
-
* In case of errors `formatPattern` will try to salvage as much of the
|
|
6079
|
-
* translation as possible and will still return a string. For performance
|
|
6080
|
-
* reasons, the encountered errors are not returned but instead are appended
|
|
6081
|
-
* to the `errors` array passed as the third argument.
|
|
6082
|
-
*
|
|
6083
|
-
* let errors = [];
|
|
6084
|
-
* bundle.addResource(
|
|
6085
|
-
* new FluentResource("hello = Hello, {$name}!"));
|
|
6086
|
-
*
|
|
6087
|
-
* let hello = bundle.getMessage("hello");
|
|
6088
|
-
* if (hello.value) {
|
|
6089
|
-
* bundle.formatPattern(hello.value, {name: "Jane"}, errors);
|
|
6090
|
-
* // Returns "Hello, Jane!" and `errors` is empty.
|
|
6091
|
-
*
|
|
6092
|
-
* bundle.formatPattern(hello.value, undefined, errors);
|
|
6093
|
-
* // Returns "Hello, {$name}!" and `errors` is now:
|
|
6094
|
-
* // [<ReferenceError: Unknown variable: name>]
|
|
6095
|
-
* }
|
|
5989
|
+
* Create an instance of `FluentDateTime` with options to the
|
|
5990
|
+
* `Intl.DateTimeFormat` constructor.
|
|
6096
5991
|
*
|
|
6097
|
-
*
|
|
5992
|
+
* @param value The number value of this `FluentDateTime`, in milliseconds.
|
|
5993
|
+
* @param opts Options which will be passed to `Intl.DateTimeFormat`.
|
|
6098
5994
|
*/
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
5995
|
+
constructor(value, opts = {}) {
|
|
5996
|
+
super(value);
|
|
5997
|
+
this.opts = opts;
|
|
5998
|
+
}
|
|
5999
|
+
/**
|
|
6000
|
+
* Format this `FluentDateTime` to a string.
|
|
6001
|
+
*/
|
|
6002
|
+
toString(scope) {
|
|
6104
6003
|
try {
|
|
6105
|
-
|
|
6106
|
-
return
|
|
6004
|
+
const dtf = scope.memoizeIntlObject(Intl.DateTimeFormat, this.opts);
|
|
6005
|
+
return dtf.format(this.value);
|
|
6107
6006
|
} catch (err) {
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
return new FluentNone2().toString(scope);
|
|
6111
|
-
}
|
|
6112
|
-
throw err;
|
|
6007
|
+
scope.reportError(err);
|
|
6008
|
+
return new Date(this.value).toISOString();
|
|
6113
6009
|
}
|
|
6114
6010
|
}
|
|
6115
6011
|
}
|
|
6116
|
-
const
|
|
6117
|
-
const
|
|
6118
|
-
const
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
const RE_INDENT = /( *)$/;
|
|
6131
|
-
const TOKEN_BRACE_OPEN = /{\s*/y;
|
|
6132
|
-
const TOKEN_BRACE_CLOSE = /\s*}/y;
|
|
6133
|
-
const TOKEN_BRACKET_OPEN = /\[\s*/y;
|
|
6134
|
-
const TOKEN_BRACKET_CLOSE = /\s*] */y;
|
|
6135
|
-
const TOKEN_PAREN_OPEN = /\s*\(\s*/y;
|
|
6136
|
-
const TOKEN_ARROW = /\s*->\s*/y;
|
|
6137
|
-
const TOKEN_COLON = /\s*:\s*/y;
|
|
6138
|
-
const TOKEN_COMMA = /\s*,?\s*/y;
|
|
6139
|
-
const TOKEN_BLANK = /\s+/y;
|
|
6140
|
-
class FluentResource {
|
|
6141
|
-
constructor(source) {
|
|
6142
|
-
this.body = [];
|
|
6143
|
-
RE_MESSAGE_START.lastIndex = 0;
|
|
6144
|
-
let cursor = 0;
|
|
6145
|
-
while (true) {
|
|
6146
|
-
let next = RE_MESSAGE_START.exec(source);
|
|
6147
|
-
if (next === null) {
|
|
6148
|
-
break;
|
|
6149
|
-
}
|
|
6150
|
-
cursor = RE_MESSAGE_START.lastIndex;
|
|
6151
|
-
try {
|
|
6152
|
-
this.body.push(parseMessage(next[1]));
|
|
6153
|
-
} catch (err) {
|
|
6154
|
-
if (err instanceof SyntaxError) {
|
|
6155
|
-
continue;
|
|
6156
|
-
}
|
|
6157
|
-
throw err;
|
|
6158
|
-
}
|
|
6012
|
+
const MAX_PLACEABLES = 100;
|
|
6013
|
+
const FSI = "";
|
|
6014
|
+
const PDI = "";
|
|
6015
|
+
function match(scope, selector, key) {
|
|
6016
|
+
if (key === selector) {
|
|
6017
|
+
return true;
|
|
6018
|
+
}
|
|
6019
|
+
if (key instanceof FluentNumber2 && selector instanceof FluentNumber2 && key.value === selector.value) {
|
|
6020
|
+
return true;
|
|
6021
|
+
}
|
|
6022
|
+
if (selector instanceof FluentNumber2 && typeof key === "string") {
|
|
6023
|
+
let category = scope.memoizeIntlObject(Intl.PluralRules, selector.opts).select(selector.value);
|
|
6024
|
+
if (key === category) {
|
|
6025
|
+
return true;
|
|
6159
6026
|
}
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6027
|
+
}
|
|
6028
|
+
return false;
|
|
6029
|
+
}
|
|
6030
|
+
function getDefault(scope, variants, star) {
|
|
6031
|
+
if (variants[star]) {
|
|
6032
|
+
return resolvePattern(scope, variants[star].value);
|
|
6033
|
+
}
|
|
6034
|
+
scope.reportError(new RangeError("No default"));
|
|
6035
|
+
return new FluentNone2();
|
|
6036
|
+
}
|
|
6037
|
+
function getArguments(scope, args) {
|
|
6038
|
+
const positional = [];
|
|
6039
|
+
const named = /* @__PURE__ */ Object.create(null);
|
|
6040
|
+
for (const arg of args) {
|
|
6041
|
+
if (arg.type === "narg") {
|
|
6042
|
+
named[arg.name] = resolveExpression(scope, arg.value);
|
|
6043
|
+
} else {
|
|
6044
|
+
positional.push(resolveExpression(scope, arg));
|
|
6163
6045
|
}
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
return
|
|
6046
|
+
}
|
|
6047
|
+
return { positional, named };
|
|
6048
|
+
}
|
|
6049
|
+
function resolveExpression(scope, expr) {
|
|
6050
|
+
switch (expr.type) {
|
|
6051
|
+
case "str":
|
|
6052
|
+
return expr.value;
|
|
6053
|
+
case "num":
|
|
6054
|
+
return new FluentNumber2(expr.value, {
|
|
6055
|
+
minimumFractionDigits: expr.precision
|
|
6056
|
+
});
|
|
6057
|
+
case "var":
|
|
6058
|
+
return resolveVariableReference(scope, expr);
|
|
6059
|
+
case "mesg":
|
|
6060
|
+
return resolveMessageReference(scope, expr);
|
|
6061
|
+
case "term":
|
|
6062
|
+
return resolveTermReference(scope, expr);
|
|
6063
|
+
case "func":
|
|
6064
|
+
return resolveFunctionReference(scope, expr);
|
|
6065
|
+
case "select":
|
|
6066
|
+
return resolveSelectExpression(scope, expr);
|
|
6067
|
+
default:
|
|
6068
|
+
return new FluentNone2();
|
|
6069
|
+
}
|
|
6070
|
+
}
|
|
6071
|
+
function resolveVariableReference(scope, { name }) {
|
|
6072
|
+
let arg;
|
|
6073
|
+
if (scope.params) {
|
|
6074
|
+
if (Object.prototype.hasOwnProperty.call(scope.params, name)) {
|
|
6075
|
+
arg = scope.params[name];
|
|
6076
|
+
} else {
|
|
6077
|
+
return new FluentNone2(`$${name}`);
|
|
6173
6078
|
}
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6079
|
+
} else if (scope.args && Object.prototype.hasOwnProperty.call(scope.args, name)) {
|
|
6080
|
+
arg = scope.args[name];
|
|
6081
|
+
} else {
|
|
6082
|
+
scope.reportError(new ReferenceError(`Unknown variable: $${name}`));
|
|
6083
|
+
return new FluentNone2(`$${name}`);
|
|
6084
|
+
}
|
|
6085
|
+
if (arg instanceof FluentType2) {
|
|
6086
|
+
return arg;
|
|
6087
|
+
}
|
|
6088
|
+
switch (typeof arg) {
|
|
6089
|
+
case "string":
|
|
6090
|
+
return arg;
|
|
6091
|
+
case "number":
|
|
6092
|
+
return new FluentNumber2(arg);
|
|
6093
|
+
case "object":
|
|
6094
|
+
if (arg instanceof Date) {
|
|
6095
|
+
return new FluentDateTime2(arg.getTime());
|
|
6181
6096
|
}
|
|
6182
|
-
|
|
6097
|
+
default:
|
|
6098
|
+
scope.reportError(new TypeError(`Variable type not supported: $${name}, ${typeof arg}`));
|
|
6099
|
+
return new FluentNone2(`$${name}`);
|
|
6100
|
+
}
|
|
6101
|
+
}
|
|
6102
|
+
function resolveMessageReference(scope, { name, attr }) {
|
|
6103
|
+
const message = scope.bundle._messages.get(name);
|
|
6104
|
+
if (!message) {
|
|
6105
|
+
scope.reportError(new ReferenceError(`Unknown message: ${name}`));
|
|
6106
|
+
return new FluentNone2(name);
|
|
6107
|
+
}
|
|
6108
|
+
if (attr) {
|
|
6109
|
+
const attribute = message.attributes[attr];
|
|
6110
|
+
if (attribute) {
|
|
6111
|
+
return resolvePattern(scope, attribute);
|
|
6183
6112
|
}
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6113
|
+
scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`));
|
|
6114
|
+
return new FluentNone2(`${name}.${attr}`);
|
|
6115
|
+
}
|
|
6116
|
+
if (message.value) {
|
|
6117
|
+
return resolvePattern(scope, message.value);
|
|
6118
|
+
}
|
|
6119
|
+
scope.reportError(new ReferenceError(`No value: ${name}`));
|
|
6120
|
+
return new FluentNone2(name);
|
|
6121
|
+
}
|
|
6122
|
+
function resolveTermReference(scope, { name, attr, args }) {
|
|
6123
|
+
const id = `-${name}`;
|
|
6124
|
+
const term = scope.bundle._terms.get(id);
|
|
6125
|
+
if (!term) {
|
|
6126
|
+
scope.reportError(new ReferenceError(`Unknown term: ${id}`));
|
|
6127
|
+
return new FluentNone2(id);
|
|
6128
|
+
}
|
|
6129
|
+
if (attr) {
|
|
6130
|
+
const attribute = term.attributes[attr];
|
|
6131
|
+
if (attribute) {
|
|
6132
|
+
scope.params = getArguments(scope, args).named;
|
|
6133
|
+
const resolved2 = resolvePattern(scope, attribute);
|
|
6134
|
+
scope.params = null;
|
|
6135
|
+
return resolved2;
|
|
6192
6136
|
}
|
|
6193
|
-
|
|
6194
|
-
|
|
6137
|
+
scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`));
|
|
6138
|
+
return new FluentNone2(`${id}.${attr}`);
|
|
6139
|
+
}
|
|
6140
|
+
scope.params = getArguments(scope, args).named;
|
|
6141
|
+
const resolved = resolvePattern(scope, term.value);
|
|
6142
|
+
scope.params = null;
|
|
6143
|
+
return resolved;
|
|
6144
|
+
}
|
|
6145
|
+
function resolveFunctionReference(scope, { name, args }) {
|
|
6146
|
+
let func = scope.bundle._functions[name];
|
|
6147
|
+
if (!func) {
|
|
6148
|
+
scope.reportError(new ReferenceError(`Unknown function: ${name}()`));
|
|
6149
|
+
return new FluentNone2(`${name}()`);
|
|
6150
|
+
}
|
|
6151
|
+
if (typeof func !== "function") {
|
|
6152
|
+
scope.reportError(new TypeError(`Function ${name}() is not callable`));
|
|
6153
|
+
return new FluentNone2(`${name}()`);
|
|
6154
|
+
}
|
|
6155
|
+
try {
|
|
6156
|
+
let resolved = getArguments(scope, args);
|
|
6157
|
+
return func(resolved.positional, resolved.named);
|
|
6158
|
+
} catch (err) {
|
|
6159
|
+
scope.reportError(err);
|
|
6160
|
+
return new FluentNone2(`${name}()`);
|
|
6161
|
+
}
|
|
6162
|
+
}
|
|
6163
|
+
function resolveSelectExpression(scope, { selector, variants, star }) {
|
|
6164
|
+
let sel = resolveExpression(scope, selector);
|
|
6165
|
+
if (sel instanceof FluentNone2) {
|
|
6166
|
+
return getDefault(scope, variants, star);
|
|
6167
|
+
}
|
|
6168
|
+
for (const variant of variants) {
|
|
6169
|
+
const key = resolveExpression(scope, variant.key);
|
|
6170
|
+
if (match(scope, sel, key)) {
|
|
6171
|
+
return resolvePattern(scope, variant.value);
|
|
6195
6172
|
}
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6173
|
+
}
|
|
6174
|
+
return getDefault(scope, variants, star);
|
|
6175
|
+
}
|
|
6176
|
+
function resolveComplexPattern(scope, ptn) {
|
|
6177
|
+
if (scope.dirty.has(ptn)) {
|
|
6178
|
+
scope.reportError(new RangeError("Cyclic reference"));
|
|
6179
|
+
return new FluentNone2();
|
|
6180
|
+
}
|
|
6181
|
+
scope.dirty.add(ptn);
|
|
6182
|
+
const result = [];
|
|
6183
|
+
const useIsolating = scope.bundle._useIsolating && ptn.length > 1;
|
|
6184
|
+
for (const elem of ptn) {
|
|
6185
|
+
if (typeof elem === "string") {
|
|
6186
|
+
result.push(scope.bundle._transform(elem));
|
|
6187
|
+
continue;
|
|
6203
6188
|
}
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
let value = parsePattern();
|
|
6209
|
-
if (value === null) {
|
|
6210
|
-
throw new SyntaxError("Expected attribute value");
|
|
6211
|
-
}
|
|
6212
|
-
attrs[name] = value;
|
|
6213
|
-
}
|
|
6214
|
-
return attrs;
|
|
6189
|
+
scope.placeables++;
|
|
6190
|
+
if (scope.placeables > MAX_PLACEABLES) {
|
|
6191
|
+
scope.dirty.delete(ptn);
|
|
6192
|
+
throw new RangeError(`Too many placeables expanded: ${scope.placeables}, max allowed is ${MAX_PLACEABLES}`);
|
|
6215
6193
|
}
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
if (test(RE_TEXT_RUN)) {
|
|
6219
|
-
first = match1(RE_TEXT_RUN);
|
|
6220
|
-
}
|
|
6221
|
-
if (source[cursor] === "{" || source[cursor] === "}") {
|
|
6222
|
-
return parsePatternElements(first ? [first] : [], Infinity);
|
|
6223
|
-
}
|
|
6224
|
-
let indent = parseIndent();
|
|
6225
|
-
if (indent) {
|
|
6226
|
-
if (first) {
|
|
6227
|
-
return parsePatternElements([first, indent], indent.length);
|
|
6228
|
-
}
|
|
6229
|
-
indent.value = trim(indent.value, RE_LEADING_NEWLINES);
|
|
6230
|
-
return parsePatternElements([indent], indent.length);
|
|
6231
|
-
}
|
|
6232
|
-
if (first) {
|
|
6233
|
-
return trim(first, RE_TRAILING_SPACES);
|
|
6234
|
-
}
|
|
6235
|
-
return null;
|
|
6194
|
+
if (useIsolating) {
|
|
6195
|
+
result.push(FSI);
|
|
6236
6196
|
}
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
elements.push(match1(RE_TEXT_RUN));
|
|
6241
|
-
continue;
|
|
6242
|
-
}
|
|
6243
|
-
if (source[cursor] === "{") {
|
|
6244
|
-
elements.push(parsePlaceable());
|
|
6245
|
-
continue;
|
|
6246
|
-
}
|
|
6247
|
-
if (source[cursor] === "}") {
|
|
6248
|
-
throw new SyntaxError("Unbalanced closing brace");
|
|
6249
|
-
}
|
|
6250
|
-
let indent = parseIndent();
|
|
6251
|
-
if (indent) {
|
|
6252
|
-
elements.push(indent);
|
|
6253
|
-
commonIndent = Math.min(commonIndent, indent.length);
|
|
6254
|
-
continue;
|
|
6255
|
-
}
|
|
6256
|
-
break;
|
|
6257
|
-
}
|
|
6258
|
-
let lastIndex = elements.length - 1;
|
|
6259
|
-
let lastElement = elements[lastIndex];
|
|
6260
|
-
if (typeof lastElement === "string") {
|
|
6261
|
-
elements[lastIndex] = trim(lastElement, RE_TRAILING_SPACES);
|
|
6262
|
-
}
|
|
6263
|
-
let baked = [];
|
|
6264
|
-
for (let element of elements) {
|
|
6265
|
-
if (element instanceof Indent) {
|
|
6266
|
-
element = element.value.slice(0, element.value.length - commonIndent);
|
|
6267
|
-
}
|
|
6268
|
-
if (element) {
|
|
6269
|
-
baked.push(element);
|
|
6270
|
-
}
|
|
6271
|
-
}
|
|
6272
|
-
return baked;
|
|
6197
|
+
result.push(resolveExpression(scope, elem).toString(scope));
|
|
6198
|
+
if (useIsolating) {
|
|
6199
|
+
result.push(PDI);
|
|
6273
6200
|
}
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6201
|
+
}
|
|
6202
|
+
scope.dirty.delete(ptn);
|
|
6203
|
+
return result.join("");
|
|
6204
|
+
}
|
|
6205
|
+
function resolvePattern(scope, value) {
|
|
6206
|
+
if (typeof value === "string") {
|
|
6207
|
+
return scope.bundle._transform(value);
|
|
6208
|
+
}
|
|
6209
|
+
return resolveComplexPattern(scope, value);
|
|
6210
|
+
}
|
|
6211
|
+
class Scope2 {
|
|
6212
|
+
constructor(bundle, errors, args) {
|
|
6213
|
+
this.dirty = /* @__PURE__ */ new WeakSet();
|
|
6214
|
+
this.params = null;
|
|
6215
|
+
this.placeables = 0;
|
|
6216
|
+
this.bundle = bundle;
|
|
6217
|
+
this.errors = errors;
|
|
6218
|
+
this.args = args;
|
|
6219
|
+
}
|
|
6220
|
+
reportError(error) {
|
|
6221
|
+
if (!this.errors || !(error instanceof Error)) {
|
|
6222
|
+
throw error;
|
|
6290
6223
|
}
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
return { type: "var", name };
|
|
6299
|
-
}
|
|
6300
|
-
if (consumeToken(TOKEN_PAREN_OPEN)) {
|
|
6301
|
-
let args = parseArguments();
|
|
6302
|
-
if (sigil === "-") {
|
|
6303
|
-
return { type: "term", name, attr, args };
|
|
6304
|
-
}
|
|
6305
|
-
if (RE_FUNCTION_NAME.test(name)) {
|
|
6306
|
-
return { type: "func", name, args };
|
|
6307
|
-
}
|
|
6308
|
-
throw new SyntaxError("Function names must be all upper-case");
|
|
6309
|
-
}
|
|
6310
|
-
if (sigil === "-") {
|
|
6311
|
-
return {
|
|
6312
|
-
type: "term",
|
|
6313
|
-
name,
|
|
6314
|
-
attr,
|
|
6315
|
-
args: []
|
|
6316
|
-
};
|
|
6317
|
-
}
|
|
6318
|
-
return { type: "mesg", name, attr };
|
|
6319
|
-
}
|
|
6320
|
-
return parseLiteral();
|
|
6224
|
+
this.errors.push(error);
|
|
6225
|
+
}
|
|
6226
|
+
memoizeIntlObject(ctor, opts) {
|
|
6227
|
+
let cache2 = this.bundle._intls.get(ctor);
|
|
6228
|
+
if (!cache2) {
|
|
6229
|
+
cache2 = {};
|
|
6230
|
+
this.bundle._intls.set(ctor, cache2);
|
|
6321
6231
|
}
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
switch (source[cursor]) {
|
|
6326
|
-
case ")":
|
|
6327
|
-
cursor++;
|
|
6328
|
-
return args;
|
|
6329
|
-
case void 0:
|
|
6330
|
-
throw new SyntaxError("Unclosed argument list");
|
|
6331
|
-
}
|
|
6332
|
-
args.push(parseArgument());
|
|
6333
|
-
consumeToken(TOKEN_COMMA);
|
|
6334
|
-
}
|
|
6232
|
+
let id = JSON.stringify(opts);
|
|
6233
|
+
if (!cache2[id]) {
|
|
6234
|
+
cache2[id] = new ctor(this.bundle.locales, opts);
|
|
6335
6235
|
}
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
name: expr.name,
|
|
6345
|
-
value: parseLiteral()
|
|
6346
|
-
};
|
|
6347
|
-
}
|
|
6348
|
-
return expr;
|
|
6236
|
+
return cache2[id];
|
|
6237
|
+
}
|
|
6238
|
+
}
|
|
6239
|
+
function values(opts, allowed) {
|
|
6240
|
+
const unwrapped = /* @__PURE__ */ Object.create(null);
|
|
6241
|
+
for (const [name, opt] of Object.entries(opts)) {
|
|
6242
|
+
if (allowed.includes(name)) {
|
|
6243
|
+
unwrapped[name] = opt.valueOf();
|
|
6349
6244
|
}
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6245
|
+
}
|
|
6246
|
+
return unwrapped;
|
|
6247
|
+
}
|
|
6248
|
+
const NUMBER_ALLOWED = [
|
|
6249
|
+
"unitDisplay",
|
|
6250
|
+
"currencyDisplay",
|
|
6251
|
+
"useGrouping",
|
|
6252
|
+
"minimumIntegerDigits",
|
|
6253
|
+
"minimumFractionDigits",
|
|
6254
|
+
"maximumFractionDigits",
|
|
6255
|
+
"minimumSignificantDigits",
|
|
6256
|
+
"maximumSignificantDigits"
|
|
6257
|
+
];
|
|
6258
|
+
function NUMBER(args, opts) {
|
|
6259
|
+
let arg = args[0];
|
|
6260
|
+
if (arg instanceof FluentNone2) {
|
|
6261
|
+
return new FluentNone2(`NUMBER(${arg.valueOf()})`);
|
|
6262
|
+
}
|
|
6263
|
+
if (arg instanceof FluentNumber2) {
|
|
6264
|
+
return new FluentNumber2(arg.valueOf(), {
|
|
6265
|
+
...arg.opts,
|
|
6266
|
+
...values(opts, NUMBER_ALLOWED)
|
|
6267
|
+
});
|
|
6268
|
+
}
|
|
6269
|
+
if (arg instanceof FluentDateTime2) {
|
|
6270
|
+
return new FluentNumber2(arg.valueOf(), {
|
|
6271
|
+
...values(opts, NUMBER_ALLOWED)
|
|
6272
|
+
});
|
|
6273
|
+
}
|
|
6274
|
+
throw new TypeError("Invalid argument to NUMBER");
|
|
6275
|
+
}
|
|
6276
|
+
const DATETIME_ALLOWED = [
|
|
6277
|
+
"dateStyle",
|
|
6278
|
+
"timeStyle",
|
|
6279
|
+
"fractionalSecondDigits",
|
|
6280
|
+
"dayPeriod",
|
|
6281
|
+
"hour12",
|
|
6282
|
+
"weekday",
|
|
6283
|
+
"era",
|
|
6284
|
+
"year",
|
|
6285
|
+
"month",
|
|
6286
|
+
"day",
|
|
6287
|
+
"hour",
|
|
6288
|
+
"minute",
|
|
6289
|
+
"second",
|
|
6290
|
+
"timeZoneName"
|
|
6291
|
+
];
|
|
6292
|
+
function DATETIME(args, opts) {
|
|
6293
|
+
let arg = args[0];
|
|
6294
|
+
if (arg instanceof FluentNone2) {
|
|
6295
|
+
return new FluentNone2(`DATETIME(${arg.valueOf()})`);
|
|
6296
|
+
}
|
|
6297
|
+
if (arg instanceof FluentDateTime2) {
|
|
6298
|
+
return new FluentDateTime2(arg.valueOf(), {
|
|
6299
|
+
...arg.opts,
|
|
6300
|
+
...values(opts, DATETIME_ALLOWED)
|
|
6301
|
+
});
|
|
6302
|
+
}
|
|
6303
|
+
if (arg instanceof FluentNumber2) {
|
|
6304
|
+
return new FluentDateTime2(arg.valueOf(), {
|
|
6305
|
+
...values(opts, DATETIME_ALLOWED)
|
|
6306
|
+
});
|
|
6307
|
+
}
|
|
6308
|
+
throw new TypeError("Invalid argument to DATETIME");
|
|
6309
|
+
}
|
|
6310
|
+
const cache = /* @__PURE__ */ new Map();
|
|
6311
|
+
function getMemoizerForLocale(locales) {
|
|
6312
|
+
const stringLocale = Array.isArray(locales) ? locales.join(" ") : locales;
|
|
6313
|
+
let memoizer = cache.get(stringLocale);
|
|
6314
|
+
if (memoizer === void 0) {
|
|
6315
|
+
memoizer = /* @__PURE__ */ new Map();
|
|
6316
|
+
cache.set(stringLocale, memoizer);
|
|
6317
|
+
}
|
|
6318
|
+
return memoizer;
|
|
6319
|
+
}
|
|
6320
|
+
class FluentBundle2 {
|
|
6321
|
+
/**
|
|
6322
|
+
* Create an instance of `FluentBundle`.
|
|
6323
|
+
*
|
|
6324
|
+
* The `locales` argument is used to instantiate `Intl` formatters used by
|
|
6325
|
+
* translations. The `options` object can be used to configure the bundle.
|
|
6326
|
+
*
|
|
6327
|
+
* Examples:
|
|
6328
|
+
*
|
|
6329
|
+
* let bundle = new FluentBundle(["en-US", "en"]);
|
|
6330
|
+
*
|
|
6331
|
+
* let bundle = new FluentBundle(locales, {useIsolating: false});
|
|
6332
|
+
*
|
|
6333
|
+
* let bundle = new FluentBundle(locales, {
|
|
6334
|
+
* useIsolating: true,
|
|
6335
|
+
* functions: {
|
|
6336
|
+
* NODE_ENV: () => process.env.NODE_ENV
|
|
6337
|
+
* }
|
|
6338
|
+
* });
|
|
6339
|
+
*
|
|
6340
|
+
* Available options:
|
|
6341
|
+
*
|
|
6342
|
+
* - `functions` - an object of additional functions available to
|
|
6343
|
+
* translations as builtins.
|
|
6344
|
+
*
|
|
6345
|
+
* - `useIsolating` - boolean specifying whether to use Unicode isolation
|
|
6346
|
+
* marks (FSI, PDI) for bidi interpolations. Default: `true`.
|
|
6347
|
+
*
|
|
6348
|
+
* - `transform` - a function used to transform string parts of patterns.
|
|
6349
|
+
*/
|
|
6350
|
+
constructor(locales, { functions, useIsolating = true, transform = (v) => v } = {}) {
|
|
6351
|
+
this._terms = /* @__PURE__ */ new Map();
|
|
6352
|
+
this._messages = /* @__PURE__ */ new Map();
|
|
6353
|
+
this.locales = Array.isArray(locales) ? locales : [locales];
|
|
6354
|
+
this._functions = {
|
|
6355
|
+
NUMBER,
|
|
6356
|
+
DATETIME,
|
|
6357
|
+
...functions
|
|
6358
|
+
};
|
|
6359
|
+
this._useIsolating = useIsolating;
|
|
6360
|
+
this._transform = transform;
|
|
6361
|
+
this._intls = getMemoizerForLocale(locales);
|
|
6362
|
+
}
|
|
6363
|
+
/**
|
|
6364
|
+
* Check if a message is present in the bundle.
|
|
6365
|
+
*
|
|
6366
|
+
* @param id - The identifier of the message to check.
|
|
6367
|
+
*/
|
|
6368
|
+
hasMessage(id) {
|
|
6369
|
+
return this._messages.has(id);
|
|
6370
|
+
}
|
|
6371
|
+
/**
|
|
6372
|
+
* Return a raw unformatted message object from the bundle.
|
|
6373
|
+
*
|
|
6374
|
+
* Raw messages are `{value, attributes}` shapes containing translation units
|
|
6375
|
+
* called `Patterns`. `Patterns` are implementation-specific; they should be
|
|
6376
|
+
* treated as black boxes and formatted with `FluentBundle.formatPattern`.
|
|
6377
|
+
*
|
|
6378
|
+
* @param id - The identifier of the message to check.
|
|
6379
|
+
*/
|
|
6380
|
+
getMessage(id) {
|
|
6381
|
+
return this._messages.get(id);
|
|
6382
|
+
}
|
|
6383
|
+
/**
|
|
6384
|
+
* Add a translation resource to the bundle.
|
|
6385
|
+
*
|
|
6386
|
+
* The translation resource must be an instance of `FluentResource`.
|
|
6387
|
+
*
|
|
6388
|
+
* let res = new FluentResource("foo = Foo");
|
|
6389
|
+
* bundle.addResource(res);
|
|
6390
|
+
* bundle.getMessage("foo");
|
|
6391
|
+
* // → {value: .., attributes: {..}}
|
|
6392
|
+
*
|
|
6393
|
+
* Available options:
|
|
6394
|
+
*
|
|
6395
|
+
* - `allowOverrides` - boolean specifying whether it's allowed to override
|
|
6396
|
+
* an existing message or term with a new value. Default: `false`.
|
|
6397
|
+
*
|
|
6398
|
+
* @param res - FluentResource object.
|
|
6399
|
+
* @param options
|
|
6400
|
+
*/
|
|
6401
|
+
addResource(res, { allowOverrides = false } = {}) {
|
|
6402
|
+
const errors = [];
|
|
6403
|
+
for (let i = 0; i < res.body.length; i++) {
|
|
6404
|
+
let entry = res.body[i];
|
|
6405
|
+
if (entry.id.startsWith("-")) {
|
|
6406
|
+
if (allowOverrides === false && this._terms.has(entry.id)) {
|
|
6407
|
+
errors.push(new Error(`Attempt to override an existing term: "${entry.id}"`));
|
|
6408
|
+
continue;
|
|
6362
6409
|
}
|
|
6363
|
-
|
|
6364
|
-
}
|
|
6365
|
-
if (count === 0) {
|
|
6366
|
-
return null;
|
|
6367
|
-
}
|
|
6368
|
-
if (star === void 0) {
|
|
6369
|
-
throw new SyntaxError("Expected default variant");
|
|
6370
|
-
}
|
|
6371
|
-
return { variants, star };
|
|
6372
|
-
}
|
|
6373
|
-
function parseVariantKey() {
|
|
6374
|
-
consumeToken(TOKEN_BRACKET_OPEN, SyntaxError);
|
|
6375
|
-
let key;
|
|
6376
|
-
if (test(RE_NUMBER_LITERAL)) {
|
|
6377
|
-
key = parseNumberLiteral();
|
|
6410
|
+
this._terms.set(entry.id, entry);
|
|
6378
6411
|
} else {
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
value: match1(RE_IDENTIFIER)
|
|
6382
|
-
};
|
|
6383
|
-
}
|
|
6384
|
-
consumeToken(TOKEN_BRACKET_CLOSE, SyntaxError);
|
|
6385
|
-
return key;
|
|
6386
|
-
}
|
|
6387
|
-
function parseLiteral() {
|
|
6388
|
-
if (test(RE_NUMBER_LITERAL)) {
|
|
6389
|
-
return parseNumberLiteral();
|
|
6390
|
-
}
|
|
6391
|
-
if (source[cursor] === '"') {
|
|
6392
|
-
return parseStringLiteral();
|
|
6393
|
-
}
|
|
6394
|
-
throw new SyntaxError("Invalid expression");
|
|
6395
|
-
}
|
|
6396
|
-
function parseNumberLiteral() {
|
|
6397
|
-
let [, value, fraction = ""] = match2(RE_NUMBER_LITERAL);
|
|
6398
|
-
let precision = fraction.length;
|
|
6399
|
-
return {
|
|
6400
|
-
type: "num",
|
|
6401
|
-
value: parseFloat(value),
|
|
6402
|
-
precision
|
|
6403
|
-
};
|
|
6404
|
-
}
|
|
6405
|
-
function parseStringLiteral() {
|
|
6406
|
-
consumeChar('"', SyntaxError);
|
|
6407
|
-
let value = "";
|
|
6408
|
-
while (true) {
|
|
6409
|
-
value += match1(RE_STRING_RUN);
|
|
6410
|
-
if (source[cursor] === "\\") {
|
|
6411
|
-
value += parseEscapeSequence();
|
|
6412
|
+
if (allowOverrides === false && this._messages.has(entry.id)) {
|
|
6413
|
+
errors.push(new Error(`Attempt to override an existing message: "${entry.id}"`));
|
|
6412
6414
|
continue;
|
|
6413
6415
|
}
|
|
6414
|
-
|
|
6415
|
-
return { type: "str", value };
|
|
6416
|
-
}
|
|
6417
|
-
throw new SyntaxError("Unclosed string literal");
|
|
6416
|
+
this._messages.set(entry.id, entry);
|
|
6418
6417
|
}
|
|
6419
6418
|
}
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6419
|
+
return errors;
|
|
6420
|
+
}
|
|
6421
|
+
/**
|
|
6422
|
+
* Format a `Pattern` to a string.
|
|
6423
|
+
*
|
|
6424
|
+
* Format a raw `Pattern` into a string. `args` will be used to resolve
|
|
6425
|
+
* references to variables passed as arguments to the translation.
|
|
6426
|
+
*
|
|
6427
|
+
* In case of errors `formatPattern` will try to salvage as much of the
|
|
6428
|
+
* translation as possible and will still return a string. For performance
|
|
6429
|
+
* reasons, the encountered errors are not returned but instead are appended
|
|
6430
|
+
* to the `errors` array passed as the third argument.
|
|
6431
|
+
*
|
|
6432
|
+
* let errors = [];
|
|
6433
|
+
* bundle.addResource(
|
|
6434
|
+
* new FluentResource("hello = Hello, {$name}!"));
|
|
6435
|
+
*
|
|
6436
|
+
* let hello = bundle.getMessage("hello");
|
|
6437
|
+
* if (hello.value) {
|
|
6438
|
+
* bundle.formatPattern(hello.value, {name: "Jane"}, errors);
|
|
6439
|
+
* // Returns "Hello, Jane!" and `errors` is empty.
|
|
6440
|
+
*
|
|
6441
|
+
* bundle.formatPattern(hello.value, undefined, errors);
|
|
6442
|
+
* // Returns "Hello, {$name}!" and `errors` is now:
|
|
6443
|
+
* // [<ReferenceError: Unknown variable: name>]
|
|
6444
|
+
* }
|
|
6445
|
+
*
|
|
6446
|
+
* If `errors` is omitted, the first encountered error will be thrown.
|
|
6447
|
+
*/
|
|
6448
|
+
formatPattern(pattern, args = null, errors = null) {
|
|
6449
|
+
if (typeof pattern === "string") {
|
|
6450
|
+
return this._transform(pattern);
|
|
6430
6451
|
}
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
case void 0:
|
|
6440
|
-
return false;
|
|
6441
|
-
case "{":
|
|
6442
|
-
return makeIndent(source.slice(start, cursor));
|
|
6443
|
-
}
|
|
6444
|
-
if (source[cursor - 1] === " ") {
|
|
6445
|
-
return makeIndent(source.slice(start, cursor));
|
|
6452
|
+
let scope = new Scope2(this, errors, args);
|
|
6453
|
+
try {
|
|
6454
|
+
let value = resolveComplexPattern(scope, pattern);
|
|
6455
|
+
return value.toString(scope);
|
|
6456
|
+
} catch (err) {
|
|
6457
|
+
if (scope.errors && err instanceof Error) {
|
|
6458
|
+
scope.errors.push(err);
|
|
6459
|
+
return new FluentNone2().toString(scope);
|
|
6446
6460
|
}
|
|
6447
|
-
|
|
6448
|
-
}
|
|
6449
|
-
function trim(text, re) {
|
|
6450
|
-
return text.replace(re, "");
|
|
6451
|
-
}
|
|
6452
|
-
function makeIndent(blank) {
|
|
6453
|
-
let value = blank.replace(RE_BLANK_LINES, "\n");
|
|
6454
|
-
let length = RE_INDENT.exec(blank)[1].length;
|
|
6455
|
-
return new Indent(value, length);
|
|
6461
|
+
throw err;
|
|
6456
6462
|
}
|
|
6457
6463
|
}
|
|
6458
6464
|
}
|
|
6459
|
-
class Indent {
|
|
6460
|
-
constructor(value, length) {
|
|
6461
|
-
this.value = value;
|
|
6462
|
-
this.length = length;
|
|
6463
|
-
}
|
|
6464
|
-
}
|
|
6465
6465
|
class RawBundleSource {
|
|
6466
6466
|
constructor(params) {
|
|
6467
6467
|
__publicField(this, "bundles", /* @__PURE__ */ new Map());
|
|
@@ -6785,6 +6785,63 @@ class BaseLocaleManager {
|
|
|
6785
6785
|
return `${locales}|${[...namespaces].sort()}`;
|
|
6786
6786
|
}
|
|
6787
6787
|
}
|
|
6788
|
+
const DEFAULT_FETCH = (key, init) => fetch(`/locales/${key}`, init);
|
|
6789
|
+
class HTTPBundleSource {
|
|
6790
|
+
constructor(params) {
|
|
6791
|
+
__publicField(this, "fetch");
|
|
6792
|
+
__publicField(this, "resources", /* @__PURE__ */ new Map());
|
|
6793
|
+
this.fetch = params.fetch ?? DEFAULT_FETCH;
|
|
6794
|
+
}
|
|
6795
|
+
addSource(resource) {
|
|
6796
|
+
throw new Error("Method not implemented.");
|
|
6797
|
+
}
|
|
6798
|
+
getKey(locale, namespace) {
|
|
6799
|
+
return `${namespace}/${locale}`;
|
|
6800
|
+
}
|
|
6801
|
+
getBundles(locales, namespaces) {
|
|
6802
|
+
const bundles = [];
|
|
6803
|
+
const promises = [];
|
|
6804
|
+
for (const locale of locales) {
|
|
6805
|
+
const bundle = new FluentBundle2(locale);
|
|
6806
|
+
bundles.push(bundle);
|
|
6807
|
+
for (const namespace of namespaces) {
|
|
6808
|
+
const key = this.getKey(locale, namespace);
|
|
6809
|
+
const resource = this.resources.get(key);
|
|
6810
|
+
if (resource) bundle.addResource(resource);
|
|
6811
|
+
else promises.push([bundle, key, this.fetchResource(key)]);
|
|
6812
|
+
}
|
|
6813
|
+
}
|
|
6814
|
+
void this.awaitResources(promises);
|
|
6815
|
+
return bundles;
|
|
6816
|
+
}
|
|
6817
|
+
async awaitResources(promises) {
|
|
6818
|
+
for (const [bundle, key, promise] of promises) {
|
|
6819
|
+
let resource = null;
|
|
6820
|
+
try {
|
|
6821
|
+
resource = await promise;
|
|
6822
|
+
} catch (error) {
|
|
6823
|
+
console.warn(`exception while fetching resource for "${key}"`);
|
|
6824
|
+
console.error(error);
|
|
6825
|
+
}
|
|
6826
|
+
if (resource === null) {
|
|
6827
|
+
console.warn(`couldn't load resource for "${key}"`);
|
|
6828
|
+
} else {
|
|
6829
|
+
bundle.addResource(resource);
|
|
6830
|
+
}
|
|
6831
|
+
}
|
|
6832
|
+
}
|
|
6833
|
+
async fetchResource(key) {
|
|
6834
|
+
const response = await this.fetch(key);
|
|
6835
|
+
if (response.ok) {
|
|
6836
|
+
const resource = new FluentResource(await response.text());
|
|
6837
|
+
this.resources.set(key, resource);
|
|
6838
|
+
return resource;
|
|
6839
|
+
} else {
|
|
6840
|
+
console.warn(`could not load i18n for ${key}`);
|
|
6841
|
+
return null;
|
|
6842
|
+
}
|
|
6843
|
+
}
|
|
6844
|
+
}
|
|
6788
6845
|
const INJECTION_KEY_PREFIX = "GLOBAL_LOCALE_MANAGER";
|
|
6789
6846
|
const globalLocaleManagers = /* @__PURE__ */ new Map();
|
|
6790
6847
|
class LocaleManager extends BaseLocaleManager {
|
|
@@ -6917,66 +6974,14 @@ function useI18N(namespace = "default") {
|
|
|
6917
6974
|
function parseInjectionName(namespace) {
|
|
6918
6975
|
return `${INJECTION_KEY_PREFIX}.${namespace}`;
|
|
6919
6976
|
}
|
|
6920
|
-
|
|
6921
|
-
class HTTPBundleSource {
|
|
6922
|
-
constructor(params) {
|
|
6923
|
-
__publicField(this, "fetch");
|
|
6924
|
-
__publicField(this, "resources", /* @__PURE__ */ new Map());
|
|
6925
|
-
this.fetch = params.fetch ?? DEFAULT_FETCH;
|
|
6926
|
-
}
|
|
6927
|
-
addSource(resource) {
|
|
6928
|
-
throw new Error("Method not implemented.");
|
|
6929
|
-
}
|
|
6930
|
-
getKey(locale, namespace) {
|
|
6931
|
-
return `${namespace}/${locale}`;
|
|
6932
|
-
}
|
|
6933
|
-
getBundles(locales, namespaces) {
|
|
6934
|
-
const bundles = [];
|
|
6935
|
-
const promises = [];
|
|
6936
|
-
for (const locale of locales) {
|
|
6937
|
-
const bundle = new FluentBundle2(locale);
|
|
6938
|
-
bundles.push(bundle);
|
|
6939
|
-
for (const namespace of namespaces) {
|
|
6940
|
-
const key = this.getKey(locale, namespace);
|
|
6941
|
-
const resource = this.resources.get(key);
|
|
6942
|
-
if (resource) bundle.addResource(resource);
|
|
6943
|
-
else promises.push([bundle, key, this.fetchResource(key)]);
|
|
6944
|
-
}
|
|
6945
|
-
}
|
|
6946
|
-
void this.awaitResources(promises);
|
|
6947
|
-
return bundles;
|
|
6948
|
-
}
|
|
6949
|
-
async awaitResources(promises) {
|
|
6950
|
-
for (const [bundle, key, promise] of promises) {
|
|
6951
|
-
let resource = null;
|
|
6952
|
-
try {
|
|
6953
|
-
resource = await promise;
|
|
6954
|
-
} catch (error) {
|
|
6955
|
-
console.warn(`exception while fetching resource for "${key}"`);
|
|
6956
|
-
console.error(error);
|
|
6957
|
-
}
|
|
6958
|
-
if (resource === null) {
|
|
6959
|
-
console.warn(`couldn't load resource for "${key}"`);
|
|
6960
|
-
} else {
|
|
6961
|
-
bundle.addResource(resource);
|
|
6962
|
-
}
|
|
6963
|
-
}
|
|
6964
|
-
}
|
|
6965
|
-
async fetchResource(key) {
|
|
6966
|
-
const response = await this.fetch(key);
|
|
6967
|
-
if (response.ok) {
|
|
6968
|
-
const resource = new FluentResource(await response.text());
|
|
6969
|
-
this.resources.set(key, resource);
|
|
6970
|
-
return resource;
|
|
6971
|
-
} else {
|
|
6972
|
-
console.warn(`could not load i18n for ${key}`);
|
|
6973
|
-
return null;
|
|
6974
|
-
}
|
|
6975
|
-
}
|
|
6976
|
-
}
|
|
6977
|
+
exports.BaseLocaleManager = BaseLocaleManager;
|
|
6977
6978
|
exports.HTTPBundleSource = HTTPBundleSource;
|
|
6978
6979
|
exports.INJECTION_KEY_PREFIX = INJECTION_KEY_PREFIX;
|
|
6979
6980
|
exports.LocaleManager = LocaleManager;
|
|
6981
|
+
exports.MemoryStorageWrapper = MemoryStorageWrapper;
|
|
6980
6982
|
exports.RawBundleSource = RawBundleSource;
|
|
6983
|
+
exports.createStorageWrapper = createStorageWrapper;
|
|
6984
|
+
exports.findLocaleManager = findLocaleManager;
|
|
6985
|
+
exports.globalLocaleManagers = globalLocaleManagers;
|
|
6981
6986
|
exports.useI18N = useI18N;
|
|
6982
6987
|
//# sourceMappingURL=i18n.cjs.map
|