@dialpad/i18n 1.22.3 → 1.24.1

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.
Files changed (46) hide show
  1. package/bin/force-pull-translations.js +2 -0
  2. package/bin/pull-translations.js +2 -0
  3. package/bin/should-pull.js +2 -0
  4. package/bin/translate-dialpadistan.js +2 -0
  5. package/bin/translation-screenshots-check.js +2 -0
  6. package/bin/upload-translation-service.js +2 -0
  7. package/dist/i18n.cjs +883 -878
  8. package/dist/i18n.cjs.map +1 -1
  9. package/dist/i18n.js +883 -878
  10. package/dist/i18n.js.map +1 -1
  11. package/dist/types/index.d.ts +2 -4
  12. package/dist/types/index.js +1 -2
  13. package/{README.md → docs/README.md} +280 -84
  14. package/index.ts +18 -5
  15. package/package.json +50 -26
  16. package/.eslintignore +0 -1
  17. package/.eslintrc.cjs +0 -12
  18. package/.prettierignore +0 -3
  19. package/.rush/temp/chunked-rush-logs/i18n.build.chunks.jsonl +0 -22
  20. package/.rush/temp/chunked-rush-logs/i18n.format.chunks.jsonl +0 -19
  21. package/.rush/temp/chunked-rush-logs/i18n.lint.chunks.jsonl +0 -2
  22. package/.rush/temp/package-deps_build.json +0 -24
  23. package/.rush/temp/package-deps_format.json +0 -24
  24. package/.rush/temp/package-deps_lint.json +0 -24
  25. package/.rush/temp/shrinkwrap-deps.json +0 -12
  26. package/CHANGELOG.json +0 -63
  27. package/CHANGELOG.md +0 -30
  28. package/base-tsconfig.json +0 -19
  29. package/dialpad-i18n-1.22.2.tgz +0 -0
  30. package/dist/types/src/locale-manager.d.ts +0 -53
  31. package/dist/types/src/locale-manager.js +0 -146
  32. package/eslint-tsconfig.json +0 -5
  33. package/index.html +0 -11
  34. package/rush-logs/i18n.build.error.log +0 -0
  35. package/rush-logs/i18n.build.log +0 -22
  36. package/rush-logs/i18n.format.error.log +0 -0
  37. package/rush-logs/i18n.format.log +0 -19
  38. package/rush-logs/i18n.lint.error.log +0 -0
  39. package/rush-logs/i18n.lint.log +0 -2
  40. package/src/__test__/locale-manager.find.test.ts +0 -78
  41. package/src/__test__/locale-manager.formatters.test.ts +0 -139
  42. package/src/__test__/locale-manager.multiple.test.ts +0 -349
  43. package/src/__test__/locale-manager.test.ts +0 -511
  44. package/src/locale-manager.ts +0 -198
  45. package/tsconfig.json +0 -10
  46. 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"(exports2, module2) {
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"(exports2, module2) {
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
- })(exports2);
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"(exports2, module2) {
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
- class FluentType2 {
5583
- /**
5584
- * Create a `FluentType` instance.
5585
- *
5586
- * @param value The JavaScript value to wrap.
5587
- */
5588
- constructor(value) {
5589
- this.value = value;
5590
- }
5591
- /**
5592
- * Unwrap the raw value stored by this `FluentType`.
5593
- */
5594
- valueOf() {
5595
- return this.value;
5596
- }
5597
- }
5598
- class FluentNone2 extends FluentType2 {
5599
- /**
5600
- * Create an instance of `FluentNone` with an optional fallback value.
5601
- * @param value The fallback value of this `FluentNone`.
5602
- */
5603
- constructor(value = "???") {
5604
- super(value);
5605
- }
5606
- /**
5607
- * Format this `FluentNone` to the fallback string.
5608
- */
5609
- toString(scope) {
5610
- return `{${this.value}}`;
5611
- }
5612
- }
5613
- class FluentNumber2 extends FluentType2 {
5614
- /**
5615
- * Create an instance of `FluentNumber` with options to the
5616
- * `Intl.NumberFormat` constructor.
5617
- *
5618
- * @param value The number value of this `FluentNumber`.
5619
- * @param opts Options which will be passed to `Intl.NumberFormat`.
5620
- */
5621
- constructor(value, opts = {}) {
5622
- super(value);
5623
- this.opts = opts;
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
- class FluentDateTime2 extends FluentType2 {
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
- const MAX_PLACEABLES = 100;
5664
- const FSI = "⁨";
5665
- const PDI = "⁩";
5666
- function match(scope, selector, key) {
5667
- if (key === selector) {
5668
- return true;
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
- return false;
5680
- }
5681
- function getDefault(scope, variants, star) {
5682
- if (variants[star]) {
5683
- return resolvePattern(scope, variants[star].value);
5684
- }
5685
- scope.reportError(new RangeError("No default"));
5686
- return new FluentNone2();
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
- return { positional, named };
5699
- }
5700
- function resolveExpression(scope, expr) {
5701
- switch (expr.type) {
5702
- case "str":
5703
- return expr.value;
5704
- case "num":
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
- } else if (scope.args && Object.prototype.hasOwnProperty.call(scope.args, name)) {
5731
- arg = scope.args[name];
5732
- } else {
5733
- scope.reportError(new ReferenceError(`Unknown variable: $${name}`));
5734
- return new FluentNone2(`$${name}`);
5735
- }
5736
- if (arg instanceof FluentType2) {
5737
- return arg;
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
- default:
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
- scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`));
5765
- return new FluentNone2(`${name}.${attr}`);
5766
- }
5767
- if (message.value) {
5768
- return resolvePattern(scope, message.value);
5769
- }
5770
- scope.reportError(new ReferenceError(`No value: ${name}`));
5771
- return new FluentNone2(name);
5772
- }
5773
- function resolveTermReference(scope, { name, attr, args }) {
5774
- const id = `-${name}`;
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
- scope.placeables++;
5841
- if (scope.placeables > MAX_PLACEABLES) {
5842
- scope.dirty.delete(ptn);
5843
- throw new RangeError(`Too many placeables expanded: ${scope.placeables}, max allowed is ${MAX_PLACEABLES}`);
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
- if (useIsolating) {
5846
- result.push(FSI);
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
- result.push(resolveExpression(scope, elem).toString(scope));
5849
- if (useIsolating) {
5850
- result.push(PDI);
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
- scope.dirty.delete(ptn);
5854
- return result.join("");
5855
- }
5856
- function resolvePattern(scope, value) {
5857
- if (typeof value === "string") {
5858
- return scope.bundle._transform(value);
5859
- }
5860
- return resolveComplexPattern(scope, value);
5861
- }
5862
- class Scope2 {
5863
- constructor(bundle, errors, args) {
5864
- this.dirty = /* @__PURE__ */ new WeakSet();
5865
- this.params = null;
5866
- this.placeables = 0;
5867
- this.bundle = bundle;
5868
- this.errors = errors;
5869
- this.args = args;
5870
- }
5871
- reportError(error) {
5872
- if (!this.errors || !(error instanceof Error)) {
5873
- throw error;
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
- this.errors.push(error);
5876
- }
5877
- memoizeIntlObject(ctor, opts) {
5878
- let cache2 = this.bundle._intls.get(ctor);
5879
- if (!cache2) {
5880
- cache2 = {};
5881
- this.bundle._intls.set(ctor, cache2);
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
- let id = JSON.stringify(opts);
5884
- if (!cache2[id]) {
5885
- cache2[id] = new ctor(this.bundle.locales, opts);
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
- return cache2[id];
5888
- }
5889
- }
5890
- function values(opts, allowed) {
5891
- const unwrapped = /* @__PURE__ */ Object.create(null);
5892
- for (const [name, opt] of Object.entries(opts)) {
5893
- if (allowed.includes(name)) {
5894
- unwrapped[name] = opt.valueOf();
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
- const cache = /* @__PURE__ */ new Map();
5962
- function getMemoizerForLocale(locales) {
5963
- const stringLocale = Array.isArray(locales) ? locales.join(" ") : locales;
5964
- let memoizer = cache.get(stringLocale);
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 FluentBundle2 {
5931
+ class FluentType2 {
5972
5932
  /**
5973
- * Create an instance of `FluentBundle`.
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
- * - `transform` - a function used to transform string parts of patterns.
5935
+ * @param value The JavaScript value to wrap.
6000
5936
  */
6001
- constructor(locales, { functions, useIsolating = true, transform = (v) => v } = {}) {
6002
- this._terms = /* @__PURE__ */ new Map();
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
- * Check if a message is present in the bundle.
6016
- *
6017
- * @param id - The identifier of the message to check.
5941
+ * Unwrap the raw value stored by this `FluentType`.
6018
5942
  */
6019
- hasMessage(id) {
6020
- return this._messages.has(id);
5943
+ valueOf() {
5944
+ return this.value;
6021
5945
  }
5946
+ }
5947
+ class FluentNone2 extends FluentType2 {
6022
5948
  /**
6023
- * Return a raw unformatted message object from the bundle.
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
- getMessage(id) {
6032
- return this._messages.get(id);
5952
+ constructor(value = "???") {
5953
+ super(value);
6033
5954
  }
6034
5955
  /**
6035
- * Add a translation resource to the bundle.
6036
- *
6037
- * The translation resource must be an instance of `FluentResource`.
6038
- *
6039
- * let res = new FluentResource("foo = Foo");
6040
- * bundle.addResource(res);
6041
- * bundle.getMessage("foo");
6042
- * // → {value: .., attributes: {..}}
6043
- *
6044
- * Available options:
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 res - FluentResource object.
6050
- * @param options
5967
+ * @param value The number value of this `FluentNumber`.
5968
+ * @param opts Options which will be passed to `Intl.NumberFormat`.
6051
5969
  */
6052
- addResource(res, { allowOverrides = false } = {}) {
6053
- const errors = [];
6054
- for (let i = 0; i < res.body.length; i++) {
6055
- let entry = res.body[i];
6056
- if (entry.id.startsWith("-")) {
6057
- if (allowOverrides === false && this._terms.has(entry.id)) {
6058
- errors.push(new Error(`Attempt to override an existing term: "${entry.id}"`));
6059
- continue;
6060
- }
6061
- this._terms.set(entry.id, entry);
6062
- } else {
6063
- if (allowOverrides === false && this._messages.has(entry.id)) {
6064
- errors.push(new Error(`Attempt to override an existing message: "${entry.id}"`));
6065
- continue;
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
- * Format a `Pattern` to a string.
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
- * If `errors` is omitted, the first encountered error will be thrown.
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
- formatPattern(pattern, args = null, errors = null) {
6100
- if (typeof pattern === "string") {
6101
- return this._transform(pattern);
6102
- }
6103
- let scope = new Scope2(this, errors, args);
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
- let value = resolveComplexPattern(scope, pattern);
6106
- return value.toString(scope);
6004
+ const dtf = scope.memoizeIntlObject(Intl.DateTimeFormat, this.opts);
6005
+ return dtf.format(this.value);
6107
6006
  } catch (err) {
6108
- if (scope.errors && err instanceof Error) {
6109
- scope.errors.push(err);
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 RE_MESSAGE_START = /^(-?[a-zA-Z][\w-]*) *= */gm;
6117
- const RE_ATTRIBUTE_START = /\.([a-zA-Z][\w-]*) *= */y;
6118
- const RE_VARIANT_START = /\*?\[/y;
6119
- const RE_NUMBER_LITERAL = /(-?[0-9]+(?:\.([0-9]+))?)/y;
6120
- const RE_IDENTIFIER = /([a-zA-Z][\w-]*)/y;
6121
- const RE_REFERENCE = /([$-])?([a-zA-Z][\w-]*)(?:\.([a-zA-Z][\w-]*))?/y;
6122
- const RE_FUNCTION_NAME = /^[A-Z][A-Z0-9_-]*$/;
6123
- const RE_TEXT_RUN = /([^{}\n\r]+)/y;
6124
- const RE_STRING_RUN = /([^\\"\n\r]*)/y;
6125
- const RE_STRING_ESCAPE = /\\([\\"])/y;
6126
- const RE_UNICODE_ESCAPE = /\\u([a-fA-F0-9]{4})|\\U([a-fA-F0-9]{6})/y;
6127
- const RE_LEADING_NEWLINES = /^\n+/;
6128
- const RE_TRAILING_SPACES = / +$/;
6129
- const RE_BLANK_LINES = / *\r?\n/g;
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
- function test(re) {
6161
- re.lastIndex = cursor;
6162
- return re.test(source);
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
- function consumeChar(char, errorClass) {
6165
- if (source[cursor] === char) {
6166
- cursor++;
6167
- return true;
6168
- }
6169
- if (errorClass) {
6170
- throw new errorClass(`Expected ${char}`);
6171
- }
6172
- return false;
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
- function consumeToken(re, errorClass) {
6175
- if (test(re)) {
6176
- cursor = re.lastIndex;
6177
- return true;
6178
- }
6179
- if (errorClass) {
6180
- throw new errorClass(`Expected ${re.toString()}`);
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
- return false;
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
- function match2(re) {
6185
- re.lastIndex = cursor;
6186
- let result = re.exec(source);
6187
- if (result === null) {
6188
- throw new SyntaxError(`Expected ${re.toString()}`);
6189
- }
6190
- cursor = re.lastIndex;
6191
- return result;
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
- function match1(re) {
6194
- return match2(re)[1];
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
- function parseMessage(id) {
6197
- let value = parsePattern();
6198
- let attributes = parseAttributes();
6199
- if (value === null && Object.keys(attributes).length === 0) {
6200
- throw new SyntaxError("Expected message value or attributes");
6201
- }
6202
- return { id, value, attributes };
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
- function parseAttributes() {
6205
- let attrs = /* @__PURE__ */ Object.create(null);
6206
- while (test(RE_ATTRIBUTE_START)) {
6207
- let name = match1(RE_ATTRIBUTE_START);
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
- function parsePattern() {
6217
- let first;
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
- function parsePatternElements(elements = [], commonIndent) {
6238
- while (true) {
6239
- if (test(RE_TEXT_RUN)) {
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
- function parsePlaceable() {
6275
- consumeToken(TOKEN_BRACE_OPEN, SyntaxError);
6276
- let selector = parseInlineExpression();
6277
- if (consumeToken(TOKEN_BRACE_CLOSE)) {
6278
- return selector;
6279
- }
6280
- if (consumeToken(TOKEN_ARROW)) {
6281
- let variants = parseVariants();
6282
- consumeToken(TOKEN_BRACE_CLOSE, SyntaxError);
6283
- return {
6284
- type: "select",
6285
- selector,
6286
- ...variants
6287
- };
6288
- }
6289
- throw new SyntaxError("Unclosed placeable");
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
- function parseInlineExpression() {
6292
- if (source[cursor] === "{") {
6293
- return parsePlaceable();
6294
- }
6295
- if (test(RE_REFERENCE)) {
6296
- let [, sigil, name, attr = null] = match2(RE_REFERENCE);
6297
- if (sigil === "$") {
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
- function parseArguments() {
6323
- let args = [];
6324
- while (true) {
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
- function parseArgument() {
6337
- let expr = parseInlineExpression();
6338
- if (expr.type !== "mesg") {
6339
- return expr;
6340
- }
6341
- if (consumeToken(TOKEN_COLON)) {
6342
- return {
6343
- type: "narg",
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
- function parseVariants() {
6351
- let variants = [];
6352
- let count = 0;
6353
- let star;
6354
- while (test(RE_VARIANT_START)) {
6355
- if (consumeChar("*")) {
6356
- star = count;
6357
- }
6358
- let key = parseVariantKey();
6359
- let value = parsePattern();
6360
- if (value === null) {
6361
- throw new SyntaxError("Expected variant value");
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
- variants[count++] = { key, value };
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
- key = {
6380
- type: "str",
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
- if (consumeChar('"')) {
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
- function parseEscapeSequence() {
6421
- if (test(RE_STRING_ESCAPE)) {
6422
- return match1(RE_STRING_ESCAPE);
6423
- }
6424
- if (test(RE_UNICODE_ESCAPE)) {
6425
- let [, codepoint4, codepoint6] = match2(RE_UNICODE_ESCAPE);
6426
- let codepoint = parseInt(codepoint4 || codepoint6, 16);
6427
- return codepoint <= 55295 || 57344 <= codepoint ? String.fromCodePoint(codepoint) : "�";
6428
- }
6429
- throw new SyntaxError("Unknown escape sequence");
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
- function parseIndent() {
6432
- let start = cursor;
6433
- consumeToken(TOKEN_BLANK);
6434
- switch (source[cursor]) {
6435
- case ".":
6436
- case "[":
6437
- case "*":
6438
- case "}":
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
- return false;
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
- const DEFAULT_FETCH = (key, init) => fetch(`/locales/${key}`, init);
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