gt-react 10.19.17 → 10.19.19
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/CHANGELOG.md +19 -0
- package/dist/browser.cjs +698 -871
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +9 -6
- package/dist/browser.d.cts.map +1 -1
- package/dist/browser.d.mts +9 -6
- package/dist/browser.d.mts.map +1 -1
- package/dist/browser.mjs +698 -871
- package/dist/browser.mjs.map +1 -1
- package/dist/client.cjs +183 -182
- package/dist/client.cjs.map +1 -1
- package/dist/client.mjs +183 -182
- package/dist/client.mjs.map +1 -1
- package/dist/index.cjs +183 -182
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +183 -182
- package/dist/index.mjs.map +1 -1
- package/dist/internal.cjs +327 -326
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.mjs +301 -300
- package/dist/internal.mjs.map +1 -1
- package/dist/macros.cjs +465 -639
- package/dist/macros.cjs.map +1 -1
- package/dist/macros.mjs +465 -639
- package/dist/macros.mjs.map +1 -1
- package/package.json +5 -5
package/dist/macros.cjs
CHANGED
|
@@ -4188,14 +4188,17 @@ function extractVars(icuString) {
|
|
|
4188
4188
|
});
|
|
4189
4189
|
return variables;
|
|
4190
4190
|
}
|
|
4191
|
+
const CONTAINS_INDEXED_GT_REGEX = new RegExp(`${VAR_IDENTIFIER}\\d+`);
|
|
4191
4192
|
/**
|
|
4192
4193
|
* Given an indexed ICU string, condenses any select to an argument
|
|
4194
|
+
* Unindexed _gt_ source strings and indexed _gt_# translation strings
|
|
4195
|
+
* are mutually exclusive.
|
|
4193
4196
|
* indexVars('Hello {_gt_1, select, other {World}}') => 'Hello {_gt_1}'
|
|
4194
4197
|
* @param {string} icuString - The ICU string to condense.
|
|
4195
4198
|
* @returns {string} The condensed ICU string.
|
|
4196
4199
|
*/
|
|
4197
4200
|
function condenseVars(icuString) {
|
|
4198
|
-
if (!
|
|
4201
|
+
if (!CONTAINS_INDEXED_GT_REGEX.test(icuString)) return icuString;
|
|
4199
4202
|
function visitor(child) {
|
|
4200
4203
|
child.type = import_types.TYPE.argument;
|
|
4201
4204
|
Reflect.deleteProperty(child, "options");
|
|
@@ -4342,7 +4345,7 @@ function sanitizeJsxChildren(childrenAsObjects) {
|
|
|
4342
4345
|
return Array.isArray(childrenAsObjects) ? childrenAsObjects.map(sanitizeChild) : sanitizeChild(childrenAsObjects);
|
|
4343
4346
|
}
|
|
4344
4347
|
//#endregion
|
|
4345
|
-
//#region ../i18n/dist/versionId-
|
|
4348
|
+
//#region ../i18n/dist/versionId-BTjLA0FZ.mjs
|
|
4346
4349
|
/**
|
|
4347
4350
|
* Throw errors if there are any errors and log warnings if there are any warnings
|
|
4348
4351
|
* @param {ValidationResult[]} results - The results to print
|
|
@@ -4608,83 +4611,269 @@ function routeCreateTranslationLoader({ type, remoteTranslationLoaderParams, loa
|
|
|
4608
4611
|
case "disabled": return createFallbackTranslationLoader();
|
|
4609
4612
|
}
|
|
4610
4613
|
}
|
|
4611
|
-
function
|
|
4612
|
-
|
|
4613
|
-
const
|
|
4614
|
-
return
|
|
4614
|
+
function getDictionaryPath(id) {
|
|
4615
|
+
const path = id ? id.split(".") : [];
|
|
4616
|
+
for (const segment of path) assertSafeDictionaryPathSegment(segment, id);
|
|
4617
|
+
return path;
|
|
4618
|
+
}
|
|
4619
|
+
function assertSafeDictionaryPathSegment(segment, path) {
|
|
4620
|
+
if (segment === "__proto__" || segment === "constructor" || segment === "prototype") throw new Error(`Dictionary path "${path}" contains an unsafe segment`);
|
|
4615
4621
|
}
|
|
4616
|
-
function
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4622
|
+
function isDictionaryObject(value) {
|
|
4623
|
+
return typeof value === "object" && value != null && !Array.isArray(value);
|
|
4624
|
+
}
|
|
4625
|
+
function cloneDictionaryValue(value) {
|
|
4626
|
+
if (value === void 0 || typeof value === "string") return value;
|
|
4627
|
+
return structuredClone(value);
|
|
4628
|
+
}
|
|
4629
|
+
function getDictionaryValueAtPath(dictionary, path) {
|
|
4630
|
+
let current = dictionary;
|
|
4631
|
+
for (const segment of getDictionaryPath(path)) {
|
|
4632
|
+
if (!isDictionaryObject(current)) return;
|
|
4633
|
+
current = current[segment];
|
|
4634
|
+
}
|
|
4635
|
+
return current;
|
|
4636
|
+
}
|
|
4637
|
+
function setDictionaryValueAtPath(dictionary, path, value) {
|
|
4638
|
+
const segments = getDictionaryPath(path);
|
|
4639
|
+
if (isDictionaryObject(value)) assertSafeDictionaryObject(value, path);
|
|
4640
|
+
if (segments.length === 0) {
|
|
4641
|
+
if (isDictionaryObject(value)) replaceDictionary(dictionary, value);
|
|
4642
|
+
return;
|
|
4643
|
+
}
|
|
4644
|
+
let current = dictionary;
|
|
4645
|
+
for (const segment of segments.slice(0, -1)) {
|
|
4646
|
+
const next = current[segment];
|
|
4647
|
+
if (!isDictionaryObject(next)) current[segment] = {};
|
|
4648
|
+
current = current[segment];
|
|
4649
|
+
}
|
|
4650
|
+
const leafSegment = segments[segments.length - 1];
|
|
4651
|
+
current[leafSegment] = value;
|
|
4652
|
+
}
|
|
4653
|
+
function getDictionaryEntry(value) {
|
|
4654
|
+
if (!isDictionaryLeafNode(value)) return;
|
|
4655
|
+
return {
|
|
4656
|
+
entry: Array.isArray(value) ? value[0] : value,
|
|
4657
|
+
options: Array.isArray(value) ? value[1] ?? {} : {}
|
|
4658
|
+
};
|
|
4659
|
+
}
|
|
4660
|
+
function getDictionaryValue(value) {
|
|
4661
|
+
if (Object.keys(value.options).length === 0) return value.entry;
|
|
4662
|
+
return [value.entry, value.options];
|
|
4620
4663
|
}
|
|
4664
|
+
function resolveDictionaryLookupOptions(options) {
|
|
4665
|
+
const { $format, context, ...rest } = options;
|
|
4666
|
+
return {
|
|
4667
|
+
...rest,
|
|
4668
|
+
$format: isStringFormat($format) ? $format : "ICU",
|
|
4669
|
+
...rest.$context === void 0 && typeof context === "string" && { $context: context }
|
|
4670
|
+
};
|
|
4671
|
+
}
|
|
4672
|
+
function isDictionaryLeafNode(value) {
|
|
4673
|
+
if (typeof value === "string") return true;
|
|
4674
|
+
if (!Array.isArray(value) || typeof value[0] !== "string") return false;
|
|
4675
|
+
if (value.length === 1) return true;
|
|
4676
|
+
return value.length === 2 && isDictionaryOptions(value[1]);
|
|
4677
|
+
}
|
|
4678
|
+
function isDictionaryOptions(value) {
|
|
4679
|
+
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
4680
|
+
const options = value;
|
|
4681
|
+
return (options.$context === void 0 || typeof options.$context === "string") && (options.$format === void 0 || isStringFormat(options.$format)) && (options.$maxChars === void 0 || typeof options.$maxChars === "number") && (options.context === void 0 || typeof options.context === "string");
|
|
4682
|
+
}
|
|
4683
|
+
function isStringFormat(value) {
|
|
4684
|
+
return value === "ICU" || value === "I18NEXT" || value === "STRING";
|
|
4685
|
+
}
|
|
4686
|
+
function replaceDictionary(target, source) {
|
|
4687
|
+
for (const key of Object.keys(target)) delete target[key];
|
|
4688
|
+
for (const key of Object.keys(source)) target[key] = source[key];
|
|
4689
|
+
}
|
|
4690
|
+
function assertSafeDictionaryObject(dictionary, parentPath = "") {
|
|
4691
|
+
for (const [key, value] of Object.entries(dictionary)) {
|
|
4692
|
+
const path = parentPath ? `${parentPath}.${key}` : key;
|
|
4693
|
+
assertSafeDictionaryPathSegment(key, path);
|
|
4694
|
+
if (isDictionaryObject(value)) assertSafeDictionaryObject(value, path);
|
|
4695
|
+
}
|
|
4696
|
+
}
|
|
4697
|
+
var DictionarySourceNotFoundError = class extends Error {
|
|
4698
|
+
constructor(id) {
|
|
4699
|
+
super(`I18nManager: source dictionary entry ${id} is not defined`);
|
|
4700
|
+
this.name = "DictionarySourceNotFoundError";
|
|
4701
|
+
}
|
|
4702
|
+
};
|
|
4621
4703
|
/**
|
|
4622
|
-
*
|
|
4623
|
-
*
|
|
4624
|
-
* to invoke the cache miss method when a cache miss occurs.
|
|
4625
|
-
*
|
|
4626
|
-
* TODO: maybe add "OutputValue" as a reflection of "InputKey"
|
|
4704
|
+
* Builds the dictionary value for a requested path by combining existing target
|
|
4705
|
+
* translations with runtime translations of any source leaves that are missing.
|
|
4627
4706
|
*/
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4707
|
+
async function materializeDictionaryValue({ key, sourceValue, targetValue, translateEntry }) {
|
|
4708
|
+
if (getDictionaryEntry(targetValue) !== void 0) return cloneDictionaryValue(targetValue);
|
|
4709
|
+
if (isDictionaryObject(targetValue) && !isDictionaryObject(sourceValue)) return cloneDictionaryValue(targetValue);
|
|
4710
|
+
const sourceEntry = getDictionaryEntry(sourceValue);
|
|
4711
|
+
if (sourceEntry !== void 0) return await translateEntry(key, sourceEntry);
|
|
4712
|
+
if (!isDictionaryObject(sourceValue)) throw new DictionarySourceNotFoundError(key);
|
|
4713
|
+
const targetDictionary = isDictionaryObject(targetValue) ? targetValue : {};
|
|
4714
|
+
const keys = new Set([...Object.keys(sourceValue), ...Object.keys(targetDictionary)]);
|
|
4715
|
+
const entries = await Promise.all(Array.from(keys).map(async (childKey) => {
|
|
4716
|
+
const childPath = key ? `${key}.${childKey}` : childKey;
|
|
4717
|
+
assertSafeDictionaryPathSegment(childKey, childPath);
|
|
4718
|
+
const childSource = sourceValue[childKey];
|
|
4719
|
+
if (childSource === void 0) return [childKey, cloneDictionaryValue(targetDictionary[childKey])];
|
|
4720
|
+
return [childKey, await materializeDictionaryValue({
|
|
4721
|
+
key: childPath,
|
|
4722
|
+
sourceValue: childSource,
|
|
4723
|
+
targetValue: targetDictionary[childKey],
|
|
4724
|
+
translateEntry
|
|
4725
|
+
})];
|
|
4726
|
+
}));
|
|
4727
|
+
return Object.fromEntries(entries);
|
|
4728
|
+
}
|
|
4729
|
+
function cloneDictionaryEntry(entry) {
|
|
4730
|
+
return {
|
|
4731
|
+
entry: entry.entry,
|
|
4732
|
+
options: structuredClone(entry.options)
|
|
4733
|
+
};
|
|
4734
|
+
}
|
|
4735
|
+
var DictionaryCache = class {
|
|
4736
|
+
constructor({ init, lifecycle = {}, runtimeTranslate }) {
|
|
4737
|
+
this.pendingTranslations = /* @__PURE__ */ new Map();
|
|
4738
|
+
this.pendingMaterializations = /* @__PURE__ */ new Map();
|
|
4638
4739
|
this.cache = structuredClone(init);
|
|
4639
|
-
this.
|
|
4640
|
-
this.
|
|
4740
|
+
this.runtimeTranslate = runtimeTranslate;
|
|
4741
|
+
this.lifecycle = lifecycle;
|
|
4641
4742
|
}
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4743
|
+
getEntry(key) {
|
|
4744
|
+
const value = getDictionaryValueAtPath(this.cache, key);
|
|
4745
|
+
const entry = getDictionaryEntry(value);
|
|
4746
|
+
if (entry === void 0) return;
|
|
4747
|
+
const outputEntry = cloneDictionaryEntry(entry);
|
|
4748
|
+
this.lifecycle.onHit?.({
|
|
4749
|
+
inputKey: key,
|
|
4750
|
+
cacheKey: key,
|
|
4751
|
+
cacheValue: value,
|
|
4752
|
+
outputValue: outputEntry
|
|
4753
|
+
});
|
|
4754
|
+
return outputEntry;
|
|
4647
4755
|
}
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4756
|
+
getValue(key) {
|
|
4757
|
+
const value = getDictionaryValueAtPath(this.cache, key);
|
|
4758
|
+
if (value === void 0) return;
|
|
4759
|
+
const outputValue = cloneDictionaryValue(value);
|
|
4760
|
+
this.lifecycle.onDictionaryObjectCacheHit?.({
|
|
4761
|
+
inputKey: key,
|
|
4762
|
+
cacheKey: key,
|
|
4763
|
+
cacheValue: value,
|
|
4764
|
+
outputValue
|
|
4765
|
+
});
|
|
4766
|
+
return outputValue;
|
|
4767
|
+
}
|
|
4768
|
+
setValue(key, value) {
|
|
4769
|
+
setDictionaryValueAtPath(this.cache, key, cloneDictionaryValue(value));
|
|
4654
4770
|
}
|
|
4655
|
-
/**
|
|
4656
|
-
* Get the internal cache
|
|
4657
|
-
* @returns The internal cache
|
|
4658
|
-
*
|
|
4659
|
-
* @internal - used by gt-tanstack-start
|
|
4660
|
-
*/
|
|
4661
4771
|
getInternalCache() {
|
|
4662
|
-
return
|
|
4772
|
+
return cloneDictionaryValue(this.cache);
|
|
4773
|
+
}
|
|
4774
|
+
async materializeValue(key, sourceValue, targetValue = getDictionaryValueAtPath(this.cache, key)) {
|
|
4775
|
+
let materializationPromise = this.pendingMaterializations.get(key);
|
|
4776
|
+
if (!materializationPromise) {
|
|
4777
|
+
materializationPromise = materializeDictionaryValue({
|
|
4778
|
+
key,
|
|
4779
|
+
sourceValue,
|
|
4780
|
+
targetValue,
|
|
4781
|
+
translateEntry: async (entryKey, sourceEntry) => getDictionaryValue(await this.materializeEntry(entryKey, sourceEntry))
|
|
4782
|
+
}).then((value) => {
|
|
4783
|
+
this.setValue(key, value);
|
|
4784
|
+
return value;
|
|
4785
|
+
});
|
|
4786
|
+
this.pendingMaterializations.set(key, materializationPromise);
|
|
4787
|
+
}
|
|
4788
|
+
try {
|
|
4789
|
+
return await materializationPromise;
|
|
4790
|
+
} finally {
|
|
4791
|
+
this.pendingMaterializations.delete(key);
|
|
4792
|
+
}
|
|
4663
4793
|
}
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4794
|
+
async materializeEntry(key, sourceEntry) {
|
|
4795
|
+
let translationPromise = this.pendingTranslations.get(key);
|
|
4796
|
+
if (!translationPromise) {
|
|
4797
|
+
translationPromise = this.runtimeTranslate(key, sourceEntry).then((value) => {
|
|
4798
|
+
setDictionaryValueAtPath(this.cache, key, value);
|
|
4799
|
+
const entry = getDictionaryEntry(value);
|
|
4800
|
+
if (entry === void 0) throw new Error("DictionaryCache materializeEntry did not return a DictionaryEntry");
|
|
4801
|
+
this.lifecycle.onMiss?.({
|
|
4802
|
+
inputKey: key,
|
|
4803
|
+
cacheKey: key,
|
|
4804
|
+
cacheValue: value,
|
|
4805
|
+
outputValue: cloneDictionaryEntry(entry)
|
|
4806
|
+
});
|
|
4807
|
+
return cloneDictionaryEntry(entry);
|
|
4808
|
+
});
|
|
4809
|
+
this.pendingTranslations.set(key, translationPromise);
|
|
4810
|
+
}
|
|
4811
|
+
try {
|
|
4812
|
+
return cloneDictionaryEntry(await translationPromise);
|
|
4813
|
+
} finally {
|
|
4814
|
+
this.pendingTranslations.delete(key);
|
|
4815
|
+
}
|
|
4669
4816
|
}
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4817
|
+
};
|
|
4818
|
+
var ResourceCache = class {
|
|
4819
|
+
constructor({ load, lifecycle = {}, ttl }) {
|
|
4820
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
4821
|
+
this.pendingLoads = /* @__PURE__ */ new Map();
|
|
4822
|
+
this.loadResource = load;
|
|
4823
|
+
this.lifecycle = lifecycle;
|
|
4824
|
+
this.ttl = ttl === null ? -1 : ttl ?? 6e4;
|
|
4825
|
+
}
|
|
4826
|
+
get(key) {
|
|
4827
|
+
const entry = this.cache.get(key);
|
|
4828
|
+
if (!entry || this.isExpired(entry)) return;
|
|
4829
|
+
this.lifecycle.onHit?.({
|
|
4830
|
+
inputKey: key,
|
|
4831
|
+
cacheKey: key,
|
|
4832
|
+
cacheValue: entry,
|
|
4833
|
+
outputValue: entry.value
|
|
4834
|
+
});
|
|
4835
|
+
return entry.value;
|
|
4836
|
+
}
|
|
4837
|
+
set(key, value, { expiresAt = this.getExpiresAt() } = {}) {
|
|
4838
|
+
this.cache.set(key, {
|
|
4839
|
+
expiresAt,
|
|
4840
|
+
value
|
|
4841
|
+
});
|
|
4842
|
+
}
|
|
4843
|
+
async getOrLoad(key) {
|
|
4844
|
+
return this.get(key) ?? await this.load(key);
|
|
4845
|
+
}
|
|
4846
|
+
async load(key) {
|
|
4847
|
+
let loadPromise = this.pendingLoads.get(key);
|
|
4848
|
+
if (!loadPromise) {
|
|
4849
|
+
loadPromise = this.loadResource(key).then((value) => {
|
|
4850
|
+
const entry = {
|
|
4851
|
+
expiresAt: this.getExpiresAt(),
|
|
4852
|
+
value
|
|
4853
|
+
};
|
|
4854
|
+
this.cache.set(key, entry);
|
|
4855
|
+
this.lifecycle.onMiss?.({
|
|
4856
|
+
inputKey: key,
|
|
4857
|
+
cacheKey: key,
|
|
4858
|
+
cacheValue: entry,
|
|
4859
|
+
outputValue: entry.value
|
|
4860
|
+
});
|
|
4861
|
+
return entry;
|
|
4862
|
+
});
|
|
4863
|
+
this.pendingLoads.set(key, loadPromise);
|
|
4864
|
+
}
|
|
4680
4865
|
try {
|
|
4681
|
-
|
|
4682
|
-
this.setCache(cacheKey, value);
|
|
4683
|
-
return value;
|
|
4866
|
+
return (await loadPromise).value;
|
|
4684
4867
|
} finally {
|
|
4685
|
-
|
|
4868
|
+
this.pendingLoads.delete(key);
|
|
4686
4869
|
}
|
|
4687
4870
|
}
|
|
4871
|
+
getExpiresAt() {
|
|
4872
|
+
return this.ttl < 0 ? this.ttl : Date.now() + this.ttl;
|
|
4873
|
+
}
|
|
4874
|
+
isExpired(entry) {
|
|
4875
|
+
return entry.expiresAt > 0 && entry.expiresAt < Date.now();
|
|
4876
|
+
}
|
|
4688
4877
|
};
|
|
4689
4878
|
/**
|
|
4690
4879
|
* Hash a message string
|
|
@@ -4729,20 +4918,22 @@ function normalizeBatchConfig(batchConfig) {
|
|
|
4729
4918
|
* Locale logic is handled at the LocalesCache level. Use a callback function that has the
|
|
4730
4919
|
* locale parameter embedded if you wish to use the locale code.
|
|
4731
4920
|
*/
|
|
4732
|
-
var TranslationsCache = class
|
|
4921
|
+
var TranslationsCache = class {
|
|
4733
4922
|
/**
|
|
4734
4923
|
* Constructor
|
|
4735
4924
|
* @param {Object} params - The parameters for the cache
|
|
4736
4925
|
* @param {Record<Hash, TranslationValue>} params.init - The initial cache
|
|
4737
4926
|
* @param {Function} params.fallback - Get the fallback value for a cache miss
|
|
4738
4927
|
*/
|
|
4739
|
-
constructor({ init, translateMany, lifecycle, batchConfig }) {
|
|
4740
|
-
|
|
4741
|
-
this.
|
|
4742
|
-
this.
|
|
4743
|
-
this.
|
|
4744
|
-
this.
|
|
4745
|
-
this.
|
|
4928
|
+
constructor({ init, translateMany, lifecycle = {}, batchConfig }) {
|
|
4929
|
+
this.pendingTranslations = /* @__PURE__ */ new Map();
|
|
4930
|
+
this.queue = [];
|
|
4931
|
+
this.batchTimer = null;
|
|
4932
|
+
this.activeRequests = 0;
|
|
4933
|
+
this.cache = structuredClone(init);
|
|
4934
|
+
this.translateMany = translateMany;
|
|
4935
|
+
this.batchConfig = normalizeBatchConfig(batchConfig);
|
|
4936
|
+
this.lifecycle = lifecycle;
|
|
4746
4937
|
}
|
|
4747
4938
|
/**
|
|
4748
4939
|
* Get the translation value for a given key
|
|
@@ -4750,10 +4941,11 @@ var TranslationsCache = class extends Cache {
|
|
|
4750
4941
|
* @returns The translation value
|
|
4751
4942
|
*/
|
|
4752
4943
|
get(key) {
|
|
4753
|
-
const
|
|
4754
|
-
|
|
4944
|
+
const cacheKey = this.getCacheKey(key);
|
|
4945
|
+
const value = this.cache[cacheKey];
|
|
4946
|
+
if (value != null) this.lifecycle.onHit?.({
|
|
4755
4947
|
inputKey: key,
|
|
4756
|
-
cacheKey
|
|
4948
|
+
cacheKey,
|
|
4757
4949
|
cacheValue: value,
|
|
4758
4950
|
outputValue: value
|
|
4759
4951
|
});
|
|
@@ -4765,75 +4957,64 @@ var TranslationsCache = class extends Cache {
|
|
|
4765
4957
|
* @returns The translation value
|
|
4766
4958
|
*/
|
|
4767
4959
|
async miss(key) {
|
|
4768
|
-
const
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4960
|
+
const cacheKey = this.getCacheKey(key);
|
|
4961
|
+
let translationPromise = this.pendingTranslations.get(cacheKey);
|
|
4962
|
+
if (!translationPromise) {
|
|
4963
|
+
translationPromise = this.translate(key);
|
|
4964
|
+
this.pendingTranslations.set(cacheKey, translationPromise);
|
|
4965
|
+
}
|
|
4966
|
+
try {
|
|
4967
|
+
const value = await translationPromise;
|
|
4968
|
+
if (value != null) this.lifecycle.onMiss?.({
|
|
4969
|
+
inputKey: key,
|
|
4970
|
+
cacheKey,
|
|
4971
|
+
cacheValue: value,
|
|
4972
|
+
outputValue: value
|
|
4973
|
+
});
|
|
4974
|
+
return value;
|
|
4975
|
+
} finally {
|
|
4976
|
+
this.pendingTranslations.delete(cacheKey);
|
|
4977
|
+
}
|
|
4776
4978
|
}
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
*/
|
|
4782
|
-
genKey(key) {
|
|
4979
|
+
getInternalCache() {
|
|
4980
|
+
return structuredClone(this.cache);
|
|
4981
|
+
}
|
|
4982
|
+
getCacheKey(key) {
|
|
4783
4983
|
return hashMessage(key.message, key.options);
|
|
4784
4984
|
}
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
*/
|
|
4790
|
-
fallback(key) {
|
|
4791
|
-
const translationPromise = this._enqueueTranslation(key);
|
|
4792
|
-
if (this._queue.length >= this._batchConfig.maxBatchSize) this._flushNow();
|
|
4793
|
-
else this._scheduleBatch();
|
|
4985
|
+
translate(key) {
|
|
4986
|
+
const translationPromise = this.enqueueTranslation(key);
|
|
4987
|
+
if (this.queue.length >= this.batchConfig.maxBatchSize) this.flushNow();
|
|
4988
|
+
else this.scheduleBatch();
|
|
4794
4989
|
return translationPromise;
|
|
4795
4990
|
}
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
if (this._batchTimer) {
|
|
4801
|
-
clearTimeout(this._batchTimer);
|
|
4802
|
-
this._batchTimer = null;
|
|
4991
|
+
flushNow() {
|
|
4992
|
+
if (this.batchTimer) {
|
|
4993
|
+
clearTimeout(this.batchTimer);
|
|
4994
|
+
this.batchTimer = null;
|
|
4803
4995
|
}
|
|
4804
|
-
this.
|
|
4805
|
-
}
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
this.
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
* Drain the queue
|
|
4818
|
-
*/
|
|
4819
|
-
_drainQueue() {
|
|
4820
|
-
while (this._queue.length > 0 && this._activeRequests < this._batchConfig.maxConcurrentRequests) {
|
|
4821
|
-
const batch = this._queue.splice(0, this._batchConfig.maxBatchSize);
|
|
4822
|
-
this._sendBatchRequest(batch);
|
|
4996
|
+
this.drainQueue();
|
|
4997
|
+
}
|
|
4998
|
+
scheduleBatch() {
|
|
4999
|
+
if (this.batchTimer) return;
|
|
5000
|
+
this.batchTimer = setTimeout(() => {
|
|
5001
|
+
this.batchTimer = null;
|
|
5002
|
+
this.drainQueue();
|
|
5003
|
+
}, this.batchConfig.batchInterval);
|
|
5004
|
+
}
|
|
5005
|
+
drainQueue() {
|
|
5006
|
+
while (this.queue.length > 0 && this.activeRequests < this.batchConfig.maxConcurrentRequests) {
|
|
5007
|
+
const batch = this.queue.splice(0, this.batchConfig.maxBatchSize);
|
|
5008
|
+
this.sendBatchRequest(batch);
|
|
4823
5009
|
}
|
|
4824
|
-
if (this.
|
|
5010
|
+
if (this.queue.length > 0) this.scheduleBatch();
|
|
4825
5011
|
}
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
* @param {TranslationKey<TranslationValue>} key - The translation key
|
|
4829
|
-
* @returns {Promise<TranslationValue>} The translation promise
|
|
4830
|
-
*/
|
|
4831
|
-
_enqueueTranslation(key) {
|
|
4832
|
-
const hash = this.genKey(key);
|
|
5012
|
+
enqueueTranslation(key) {
|
|
5013
|
+
const hash = this.getCacheKey(key);
|
|
4833
5014
|
const options = key.options;
|
|
4834
5015
|
const metadataOptions = options;
|
|
4835
5016
|
return new Promise((resolve, reject) => {
|
|
4836
|
-
this.
|
|
5017
|
+
this.queue.push({
|
|
4837
5018
|
key: hash,
|
|
4838
5019
|
source: key.message,
|
|
4839
5020
|
metadata: {
|
|
@@ -4848,38 +5029,28 @@ var TranslationsCache = class extends Cache {
|
|
|
4848
5029
|
});
|
|
4849
5030
|
});
|
|
4850
5031
|
}
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
* @param {QueueEntry<TranslationValue>[]} batch - The batch of requests to send
|
|
4854
|
-
*/
|
|
4855
|
-
async _sendBatchRequest(batch) {
|
|
4856
|
-
this._activeRequests++;
|
|
5032
|
+
async sendBatchRequest(batch) {
|
|
5033
|
+
this.activeRequests++;
|
|
4857
5034
|
const requests = convertBatchToTranslateManyParams(batch);
|
|
4858
|
-
const response = await this.
|
|
4859
|
-
if (response) this.
|
|
4860
|
-
this.
|
|
5035
|
+
const response = await this.sendBatchRequestWithErrorHandling(batch, requests);
|
|
5036
|
+
if (response) this.handleTranslationResponse(batch, response);
|
|
5037
|
+
this.activeRequests--;
|
|
4861
5038
|
}
|
|
4862
|
-
|
|
4863
|
-
* Send a translation request with error handling
|
|
4864
|
-
*/
|
|
4865
|
-
async _sendBatchRequestWithErrorHandling(batch, requests) {
|
|
5039
|
+
async sendBatchRequestWithErrorHandling(batch, requests) {
|
|
4866
5040
|
try {
|
|
4867
|
-
return await this.
|
|
5041
|
+
return await this.translateMany(requests);
|
|
4868
5042
|
} catch (error) {
|
|
4869
5043
|
for (const entry of batch) entry.reject(error);
|
|
4870
5044
|
return;
|
|
4871
5045
|
}
|
|
4872
5046
|
}
|
|
4873
|
-
|
|
4874
|
-
* Handle a translation response
|
|
4875
|
-
*/
|
|
4876
|
-
_handleTranslationResponse(batch, response) {
|
|
5047
|
+
handleTranslationResponse(batch, response) {
|
|
4877
5048
|
for (const entry of batch) {
|
|
4878
5049
|
const { key } = entry;
|
|
4879
5050
|
const result = response[key];
|
|
4880
5051
|
if (result && result.success) {
|
|
4881
5052
|
const translation = result.translation;
|
|
4882
|
-
this.
|
|
5053
|
+
this.cache[key] = translation;
|
|
4883
5054
|
entry.resolve(translation);
|
|
4884
5055
|
} else entry.reject(result?.error);
|
|
4885
5056
|
}
|
|
@@ -4897,415 +5068,87 @@ function convertBatchToTranslateManyParams(batch) {
|
|
|
4897
5068
|
return acc;
|
|
4898
5069
|
}, {});
|
|
4899
5070
|
}
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
* @param {CreateTranslateMany} params.createTranslateMany - Factory function for creating a translate many function
|
|
4915
|
-
*/
|
|
4916
|
-
constructor({ init = {}, ttl, batchConfig, loadTranslations, createTranslateMany, lifecycle: { onLocalesCacheHit: onHit, onLocalesCacheMiss: onMiss, onTranslationsCacheHit, onTranslationsCacheMiss } }) {
|
|
4917
|
-
super(init, {
|
|
4918
|
-
onHit,
|
|
4919
|
-
onMiss
|
|
5071
|
+
var LocalesCache = class {
|
|
5072
|
+
constructor({ ttl, batchConfig, defaultLocale, dictionary = {}, loadTranslations, loadDictionary, createTranslateMany, translateDictionaryEntry, lifecycle }) {
|
|
5073
|
+
this.translations = new ResourceCache({
|
|
5074
|
+
ttl,
|
|
5075
|
+
load: async (locale) => new TranslationsCache({
|
|
5076
|
+
init: await loadTranslations(locale),
|
|
5077
|
+
lifecycle: createTranslationsCacheLifecycle(locale, lifecycle),
|
|
5078
|
+
translateMany: createTranslateMany(locale),
|
|
5079
|
+
batchConfig
|
|
5080
|
+
}),
|
|
5081
|
+
lifecycle: {
|
|
5082
|
+
onHit: lifecycle.onLocalesCacheHit,
|
|
5083
|
+
onMiss: lifecycle.onLocalesCacheMiss
|
|
5084
|
+
}
|
|
4920
5085
|
});
|
|
4921
|
-
this.
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
*/
|
|
4934
|
-
get(key) {
|
|
4935
|
-
const entry = this.getCache(key);
|
|
4936
|
-
if (!entry || entry.expiresAt > 0 && entry.expiresAt < Date.now()) return;
|
|
4937
|
-
const value = entry.translationsCache;
|
|
4938
|
-
if (value != null && this.onHit) this.onHit({
|
|
4939
|
-
inputKey: key,
|
|
4940
|
-
cacheKey: this.genKey(key),
|
|
4941
|
-
cacheValue: entry,
|
|
4942
|
-
outputValue: value
|
|
5086
|
+
this.dictionaries = new ResourceCache({
|
|
5087
|
+
ttl,
|
|
5088
|
+
load: async (locale) => createDictionaryCache({
|
|
5089
|
+
locale,
|
|
5090
|
+
dictionary: await loadDictionary(locale),
|
|
5091
|
+
translate: translateDictionaryEntry,
|
|
5092
|
+
lifecycle
|
|
5093
|
+
}),
|
|
5094
|
+
lifecycle: {
|
|
5095
|
+
onHit: lifecycle.onLocalesDictionaryCacheHit,
|
|
5096
|
+
onMiss: lifecycle.onLocalesDictionaryCacheMiss
|
|
5097
|
+
}
|
|
4943
5098
|
});
|
|
4944
|
-
|
|
5099
|
+
this.dictionaries.set(defaultLocale, createDictionaryCache({
|
|
5100
|
+
locale: defaultLocale,
|
|
5101
|
+
dictionary,
|
|
5102
|
+
translate: translateDictionaryEntry,
|
|
5103
|
+
lifecycle
|
|
5104
|
+
}), { expiresAt: -1 });
|
|
4945
5105
|
}
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
* @param key - The locale
|
|
4949
|
-
* @returns The translations cache
|
|
4950
|
-
*/
|
|
4951
|
-
async miss(key) {
|
|
4952
|
-
const cacheValue = await this.missCache(key);
|
|
4953
|
-
const value = cacheValue.translationsCache;
|
|
4954
|
-
if (value != null && this.onMiss) this.onMiss({
|
|
4955
|
-
inputKey: key,
|
|
4956
|
-
cacheKey: this.genKey(key),
|
|
4957
|
-
cacheValue,
|
|
4958
|
-
outputValue: value
|
|
4959
|
-
});
|
|
4960
|
-
return value;
|
|
5106
|
+
getTranslations(locale) {
|
|
5107
|
+
return this.translations.get(locale);
|
|
4961
5108
|
}
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
* @param key - The locale
|
|
4965
|
-
* @returns The cache key
|
|
4966
|
-
*
|
|
4967
|
-
* This is just an identity function, no transformation needed
|
|
4968
|
-
*/
|
|
4969
|
-
genKey(key) {
|
|
4970
|
-
return key;
|
|
5109
|
+
getOrLoadTranslations(locale) {
|
|
5110
|
+
return this.translations.getOrLoad(locale);
|
|
4971
5111
|
}
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
* @param locale - The locale
|
|
4975
|
-
* @returns The cache entry
|
|
4976
|
-
*/
|
|
4977
|
-
async fallback(locale) {
|
|
4978
|
-
return {
|
|
4979
|
-
translationsCache: new TranslationsCache({
|
|
4980
|
-
init: await this._translationLoader(locale),
|
|
4981
|
-
lifecycle: this._createTranslationsCacheLifecycle(locale),
|
|
4982
|
-
translateMany: this._createTranslateMany(locale),
|
|
4983
|
-
batchConfig: this._batchConfig
|
|
4984
|
-
}),
|
|
4985
|
-
expiresAt: this.ttl < 0 ? this.ttl : Date.now() + this.ttl
|
|
4986
|
-
};
|
|
5112
|
+
getDictionary(locale) {
|
|
5113
|
+
return this.dictionaries.get(locale);
|
|
4987
5114
|
}
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
* @param locale - The locale
|
|
4991
|
-
* @returns The translations cache lifecycle
|
|
4992
|
-
*/
|
|
4993
|
-
_createTranslationsCacheLifecycle(locale) {
|
|
4994
|
-
return {
|
|
4995
|
-
onHit: this._onTranslationsCacheHit ? (params) => this._onTranslationsCacheHit({
|
|
4996
|
-
locale,
|
|
4997
|
-
...params
|
|
4998
|
-
}) : void 0,
|
|
4999
|
-
onMiss: this._onTranslationsCacheMiss ? (params) => this._onTranslationsCacheMiss({
|
|
5000
|
-
locale,
|
|
5001
|
-
...params
|
|
5002
|
-
}) : void 0
|
|
5003
|
-
};
|
|
5115
|
+
getOrLoadDictionary(locale) {
|
|
5116
|
+
return this.dictionaries.getOrLoad(locale);
|
|
5004
5117
|
}
|
|
5005
5118
|
};
|
|
5006
|
-
function
|
|
5007
|
-
if (!id) return [];
|
|
5008
|
-
return id.split(".");
|
|
5009
|
-
}
|
|
5010
|
-
function isDictionaryValue(value) {
|
|
5011
|
-
return typeof value === "object" && value != null && !Array.isArray(value);
|
|
5012
|
-
}
|
|
5013
|
-
function getDictionaryEntry(value) {
|
|
5014
|
-
if (!isDictionaryLeafNode(value)) return;
|
|
5119
|
+
function createTranslationsCacheLifecycle(locale, lifecycle) {
|
|
5015
5120
|
return {
|
|
5016
|
-
|
|
5017
|
-
|
|
5121
|
+
onHit: withLocale(locale, lifecycle.onTranslationsCacheHit),
|
|
5122
|
+
onMiss: withLocale(locale, lifecycle.onTranslationsCacheMiss)
|
|
5018
5123
|
};
|
|
5019
5124
|
}
|
|
5020
|
-
function
|
|
5021
|
-
|
|
5022
|
-
return
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
};
|
|
5031
|
-
}
|
|
5032
|
-
function isDictionaryLeafNode(value) {
|
|
5033
|
-
if (typeof value === "string") return true;
|
|
5034
|
-
if (!Array.isArray(value) || typeof value[0] !== "string") return false;
|
|
5035
|
-
if (value.length === 1) return true;
|
|
5036
|
-
return value.length === 2 && isDictionaryOptions(value[1]);
|
|
5037
|
-
}
|
|
5038
|
-
function isDictionaryOptions(value) {
|
|
5039
|
-
if (typeof value !== "object" || value == null || Array.isArray(value)) return false;
|
|
5040
|
-
const options = value;
|
|
5041
|
-
return (options.$context === void 0 || typeof options.$context === "string") && (options.$format === void 0 || isStringFormat(options.$format)) && (options.$maxChars === void 0 || typeof options.$maxChars === "number") && (options.context === void 0 || typeof options.context === "string");
|
|
5125
|
+
function createDictionaryCache({ locale, dictionary, translate, lifecycle }) {
|
|
5126
|
+
const { onDictionaryCacheHit, onDictionaryCacheMiss, onDictionaryObjectCacheHit } = lifecycle;
|
|
5127
|
+
return new DictionaryCache({
|
|
5128
|
+
init: dictionary,
|
|
5129
|
+
runtimeTranslate: (key, sourceEntry) => translate(locale, key, sourceEntry),
|
|
5130
|
+
lifecycle: {
|
|
5131
|
+
onHit: withLocale(locale, onDictionaryCacheHit),
|
|
5132
|
+
onMiss: withLocale(locale, onDictionaryCacheMiss),
|
|
5133
|
+
onDictionaryObjectCacheHit: withLocale(locale, onDictionaryObjectCacheHit)
|
|
5134
|
+
}
|
|
5135
|
+
});
|
|
5042
5136
|
}
|
|
5043
|
-
function
|
|
5044
|
-
return
|
|
5137
|
+
function withLocale(locale, callback) {
|
|
5138
|
+
return callback ? (params) => callback({
|
|
5139
|
+
locale,
|
|
5140
|
+
...params
|
|
5141
|
+
}) : void 0;
|
|
5045
5142
|
}
|
|
5046
|
-
|
|
5047
|
-
for (const key of Object.keys(target)) delete target[key];
|
|
5048
|
-
Object.assign(target, source);
|
|
5049
|
-
}
|
|
5050
|
-
var DictionarySourceNotFoundError = class extends Error {
|
|
5051
|
-
constructor(id) {
|
|
5052
|
-
super(`I18nManager: source dictionary entry ${id} is not defined`);
|
|
5053
|
-
this.name = "DictionarySourceNotFoundError";
|
|
5054
|
-
}
|
|
5055
|
-
};
|
|
5056
|
-
/**
|
|
5057
|
-
* A cache for a single locale's dictionary
|
|
5058
|
-
*
|
|
5059
|
-
* Principles:
|
|
5060
|
-
* - This class is language agnostic, and should never store the locale code as a parameter.
|
|
5061
|
-
* Locale logic is handled at the LocalesDictionaryCache level. Use a callback function
|
|
5062
|
-
* that has the locale parameter embedded if you wish to use the locale code.
|
|
5063
|
-
*/
|
|
5064
|
-
var DictionaryCache = class extends Cache {
|
|
5065
|
-
/**
|
|
5066
|
-
* Constructor
|
|
5067
|
-
* @param {Object} params - The parameters for the cache
|
|
5068
|
-
* @param {Dictionary} params.init - The initial cache
|
|
5069
|
-
*/
|
|
5070
|
-
constructor({ init, lifecycle, runtimeTranslate }) {
|
|
5071
|
-
super(init, lifecycle);
|
|
5072
|
-
this._runtimeTranslate = runtimeTranslate;
|
|
5073
|
-
this.onHitObj = lifecycle?.onHitObj;
|
|
5074
|
-
this.onMissObj = lifecycle?.onMissObj;
|
|
5075
|
-
}
|
|
5076
|
-
/**
|
|
5077
|
-
* Get the dictionary value for a given key
|
|
5078
|
-
* @param key - The dictionary key
|
|
5079
|
-
* @returns The dictionary value
|
|
5080
|
-
*/
|
|
5081
|
-
get(key) {
|
|
5082
|
-
const value = this.getCache(key);
|
|
5083
|
-
const entry = getDictionaryEntry(value);
|
|
5084
|
-
if (entry === void 0) return;
|
|
5085
|
-
if (this.onHit) this.onHit({
|
|
5086
|
-
inputKey: key,
|
|
5087
|
-
cacheKey: this.genKey(key),
|
|
5088
|
-
cacheValue: value,
|
|
5089
|
-
outputValue: entry
|
|
5090
|
-
});
|
|
5091
|
-
return entry;
|
|
5092
|
-
}
|
|
5093
|
-
set(key, value) {
|
|
5094
|
-
const dictionaryValue = getDictionaryValue(value);
|
|
5095
|
-
this.setCache(this.genKey(key), dictionaryValue);
|
|
5096
|
-
}
|
|
5097
|
-
getObj(key) {
|
|
5098
|
-
const value = this.getCache(key);
|
|
5099
|
-
if (value === void 0) return;
|
|
5100
|
-
const outputValue = structuredClone(value);
|
|
5101
|
-
if (this.onHitObj) this.onHitObj({
|
|
5102
|
-
inputKey: key,
|
|
5103
|
-
cacheKey: this.genKey(key),
|
|
5104
|
-
cacheValue: value,
|
|
5105
|
-
outputValue
|
|
5106
|
-
});
|
|
5107
|
-
return outputValue;
|
|
5108
|
-
}
|
|
5109
|
-
setObj(key, value) {
|
|
5110
|
-
this.setCache(this.genKey(key), structuredClone(value));
|
|
5111
|
-
}
|
|
5112
|
-
async missObj(key, sourceObject) {
|
|
5113
|
-
const sourceEntry = getDictionaryEntry(sourceObject);
|
|
5114
|
-
if (sourceEntry !== void 0) return getDictionaryValue(await this.miss(key, sourceEntry));
|
|
5115
|
-
if (!isDictionaryValue(sourceObject)) throw new DictionarySourceNotFoundError(key);
|
|
5116
|
-
const translatedEntries = await Promise.all(Object.entries(sourceObject).map(async ([childKey, childSource]) => {
|
|
5117
|
-
const childPath = key ? `${key}.${childKey}` : childKey;
|
|
5118
|
-
return [childKey, await this.missObj(childPath, childSource)];
|
|
5119
|
-
}));
|
|
5120
|
-
const translatedObject = Object.fromEntries(translatedEntries);
|
|
5121
|
-
this.setObj(key, translatedObject);
|
|
5122
|
-
return translatedObject;
|
|
5123
|
-
}
|
|
5124
|
-
/**
|
|
5125
|
-
* Miss the cache
|
|
5126
|
-
* @param key - The dictionary key
|
|
5127
|
-
* @returns The dictionary value
|
|
5128
|
-
*/
|
|
5129
|
-
async miss(key, sourceEntry) {
|
|
5130
|
-
const value = await this.missCache(key, sourceEntry);
|
|
5131
|
-
const entry = getDictionaryEntry(value);
|
|
5132
|
-
if (entry === void 0) throw new Error("DictionaryCache missCache did not return a DictionaryEntry");
|
|
5133
|
-
if (this.onMiss) this.onMiss({
|
|
5134
|
-
inputKey: key,
|
|
5135
|
-
cacheKey: this.genKey(key),
|
|
5136
|
-
cacheValue: value,
|
|
5137
|
-
outputValue: entry
|
|
5138
|
-
});
|
|
5139
|
-
return entry;
|
|
5140
|
-
}
|
|
5141
|
-
/**
|
|
5142
|
-
* Set the value for a key
|
|
5143
|
-
*/
|
|
5144
|
-
setCache(cacheKey, value) {
|
|
5145
|
-
const cache = this.getMutableCache();
|
|
5146
|
-
const dictionaryPath = getDictionaryPath(cacheKey);
|
|
5147
|
-
if (dictionaryPath.length === 0) {
|
|
5148
|
-
if (isDictionaryValue(value)) replaceDictionary(cache, value);
|
|
5149
|
-
return;
|
|
5150
|
-
}
|
|
5151
|
-
let current = cache;
|
|
5152
|
-
for (const key of dictionaryPath.slice(0, -1)) {
|
|
5153
|
-
const next = current[key];
|
|
5154
|
-
if (!isDictionaryValue(next)) current[key] = {};
|
|
5155
|
-
current = current[key];
|
|
5156
|
-
}
|
|
5157
|
-
current[dictionaryPath[dictionaryPath.length - 1]] = value;
|
|
5158
|
-
}
|
|
5159
|
-
/**
|
|
5160
|
-
* Look up the key
|
|
5161
|
-
*/
|
|
5162
|
-
getCache(key) {
|
|
5163
|
-
const dictionaryPath = getDictionaryPath(this.genKey(key));
|
|
5164
|
-
let current = this.getMutableCache();
|
|
5165
|
-
if (dictionaryPath.length === 0) return current;
|
|
5166
|
-
for (const pathSegment of dictionaryPath) {
|
|
5167
|
-
if (!isDictionaryValue(current)) return;
|
|
5168
|
-
current = current[pathSegment];
|
|
5169
|
-
}
|
|
5170
|
-
return current;
|
|
5171
|
-
}
|
|
5172
|
-
/**
|
|
5173
|
-
* Generate a key for the cache
|
|
5174
|
-
* @param key - The dictionary key
|
|
5175
|
-
* @returns The key
|
|
5176
|
-
*/
|
|
5177
|
-
genKey(key) {
|
|
5178
|
-
return key;
|
|
5179
|
-
}
|
|
5180
|
-
/**
|
|
5181
|
-
* Get the fallback value for a cache miss
|
|
5182
|
-
* @param key - The dictionary key
|
|
5183
|
-
* @returns The fallback value
|
|
5184
|
-
*
|
|
5185
|
-
* @throws {Error} - If the fallback is not implemented
|
|
5186
|
-
*/
|
|
5187
|
-
fallback(key, sourceEntry) {
|
|
5188
|
-
return this._runtimeTranslate(key, sourceEntry);
|
|
5189
|
-
}
|
|
5190
|
-
};
|
|
5191
|
-
/**
|
|
5192
|
-
* Cache for looking up dictionaries by locale
|
|
5193
|
-
*/
|
|
5194
|
-
var LocalesDictionaryCache = class extends Cache {
|
|
5195
|
-
/**
|
|
5196
|
-
* Constructor
|
|
5197
|
-
* @param {Object} params - The parameters for the cache
|
|
5198
|
-
* @param {number | null} params.ttl - The time to live for cache entries
|
|
5199
|
-
* @param {DictionaryLoader} params.loadDictionary - The dictionary loader function
|
|
5200
|
-
*/
|
|
5201
|
-
constructor({ ttl, defaultLocale, dictionary = {}, loadDictionary, runtimeTranslate, lifecycle: { onLocalesDictionaryCacheHit: onHit, onLocalesDictionaryCacheMiss: onMiss, onDictionaryCacheHit, onDictionaryCacheMiss, onDictionaryObjectCacheHit } }) {
|
|
5202
|
-
super({}, {
|
|
5203
|
-
onHit,
|
|
5204
|
-
onMiss
|
|
5205
|
-
});
|
|
5206
|
-
this.ttl = DEFAULT_CACHE_EXPIRY_TIME;
|
|
5207
|
-
this.ttl = ttl === null ? -1 : ttl ?? 6e4;
|
|
5208
|
-
this._dictionaryLoader = loadDictionary;
|
|
5209
|
-
this._runtimeTranslate = runtimeTranslate;
|
|
5210
|
-
this._onDictionaryCacheHit = onDictionaryCacheHit;
|
|
5211
|
-
this._onDictionaryCacheMiss = onDictionaryCacheMiss;
|
|
5212
|
-
this._onDictionaryObjectCacheHit = onDictionaryObjectCacheHit;
|
|
5213
|
-
this.setCache(defaultLocale, {
|
|
5214
|
-
dictionaryCache: new DictionaryCache({
|
|
5215
|
-
init: dictionary,
|
|
5216
|
-
runtimeTranslate: this._createDictionaryRuntimeTranslate(defaultLocale),
|
|
5217
|
-
lifecycle: this._createDictionaryCacheLifecycle(defaultLocale)
|
|
5218
|
-
}),
|
|
5219
|
-
expiresAt: -1
|
|
5220
|
-
});
|
|
5221
|
-
}
|
|
5222
|
-
/**
|
|
5223
|
-
* Get the dictionary for a given locale
|
|
5224
|
-
* @param key - The locale
|
|
5225
|
-
* @returns The dictionary
|
|
5226
|
-
*/
|
|
5227
|
-
get(key) {
|
|
5228
|
-
const entry = this.getCache(key);
|
|
5229
|
-
if (!entry || entry.expiresAt > 0 && entry.expiresAt < Date.now()) return;
|
|
5230
|
-
const value = entry.dictionaryCache;
|
|
5231
|
-
if (value != null && this.onHit) this.onHit({
|
|
5232
|
-
inputKey: key,
|
|
5233
|
-
cacheKey: this.genKey(key),
|
|
5234
|
-
cacheValue: entry,
|
|
5235
|
-
outputValue: value
|
|
5236
|
-
});
|
|
5237
|
-
return value;
|
|
5238
|
-
}
|
|
5239
|
-
/**
|
|
5240
|
-
* Miss the cache
|
|
5241
|
-
* @param key - The locale
|
|
5242
|
-
* @returns The dictionary cache
|
|
5243
|
-
*/
|
|
5244
|
-
async miss(key) {
|
|
5245
|
-
const cacheValue = await this.missCache(key);
|
|
5246
|
-
const value = cacheValue.dictionaryCache;
|
|
5247
|
-
if (value != null && this.onMiss) this.onMiss({
|
|
5248
|
-
inputKey: key,
|
|
5249
|
-
cacheKey: this.genKey(key),
|
|
5250
|
-
cacheValue,
|
|
5251
|
-
outputValue: value
|
|
5252
|
-
});
|
|
5253
|
-
return value;
|
|
5254
|
-
}
|
|
5255
|
-
/**
|
|
5256
|
-
* Generate the cache key for a given locale
|
|
5257
|
-
* @param key - The locale
|
|
5258
|
-
* @returns The cache key
|
|
5259
|
-
*
|
|
5260
|
-
* This is just an identity function, no transformation needed
|
|
5261
|
-
*/
|
|
5262
|
-
genKey(key) {
|
|
5263
|
-
return key;
|
|
5264
|
-
}
|
|
5265
|
-
/**
|
|
5266
|
-
* Fallback for a cache miss
|
|
5267
|
-
* @param locale - The locale
|
|
5268
|
-
* @returns The cache entry
|
|
5269
|
-
*/
|
|
5270
|
-
async fallback(locale) {
|
|
5271
|
-
return {
|
|
5272
|
-
dictionaryCache: new DictionaryCache({
|
|
5273
|
-
init: await this._dictionaryLoader(locale),
|
|
5274
|
-
runtimeTranslate: this._createDictionaryRuntimeTranslate(locale),
|
|
5275
|
-
lifecycle: this._createDictionaryCacheLifecycle(locale)
|
|
5276
|
-
}),
|
|
5277
|
-
expiresAt: this.ttl < 0 ? this.ttl : Date.now() + this.ttl
|
|
5278
|
-
};
|
|
5279
|
-
}
|
|
5280
|
-
/**
|
|
5281
|
-
* Create the dictionary cache lifecycle
|
|
5282
|
-
* @param locale - The locale
|
|
5283
|
-
* @returns The dictionary cache lifecycle
|
|
5284
|
-
*/
|
|
5285
|
-
_createDictionaryCacheLifecycle(locale) {
|
|
5286
|
-
return {
|
|
5287
|
-
onHit: this._onDictionaryCacheHit ? (params) => this._onDictionaryCacheHit({
|
|
5288
|
-
locale,
|
|
5289
|
-
...params
|
|
5290
|
-
}) : void 0,
|
|
5291
|
-
onMiss: this._onDictionaryCacheMiss ? (params) => this._onDictionaryCacheMiss({
|
|
5292
|
-
locale,
|
|
5293
|
-
...params
|
|
5294
|
-
}) : void 0,
|
|
5295
|
-
onHitObj: this._onDictionaryObjectCacheHit ? (params) => this._onDictionaryObjectCacheHit({
|
|
5296
|
-
locale,
|
|
5297
|
-
...params
|
|
5298
|
-
}) : void 0
|
|
5299
|
-
};
|
|
5300
|
-
}
|
|
5301
|
-
_createDictionaryRuntimeTranslate(locale) {
|
|
5302
|
-
return (key, sourceEntry) => this._runtimeTranslate(locale, key, sourceEntry);
|
|
5303
|
-
}
|
|
5304
|
-
};
|
|
5143
|
+
const LOCALES_CACHE_HIT_EVENT_NAME = "locales-cache-hit";
|
|
5305
5144
|
const LOCALES_CACHE_MISS_EVENT_NAME = "locales-cache-miss";
|
|
5145
|
+
const TRANSLATIONS_CACHE_HIT_EVENT_NAME = "translations-cache-hit";
|
|
5306
5146
|
const TRANSLATIONS_CACHE_MISS_EVENT_NAME = "translations-cache-miss";
|
|
5147
|
+
const LOCALES_DICTIONARY_CACHE_HIT_EVENT_NAME = "locales-dictionary-cache-hit";
|
|
5307
5148
|
const LOCALES_DICTIONARY_CACHE_MISS_EVENT_NAME = "locales-dictionary-cache-miss";
|
|
5149
|
+
const DICTIONARY_CACHE_HIT_EVENT_NAME = "dictionary-cache-hit";
|
|
5308
5150
|
const DICTIONARY_CACHE_MISS_EVENT_NAME = "dictionary-cache-miss";
|
|
5151
|
+
const DICTIONARY_OBJECT_CACHE_HIT_EVENT_NAME = "dictionary-object-cache-hit";
|
|
5309
5152
|
/**
|
|
5310
5153
|
* Maps consumer-facing lifecycle callbacks to internal locales cache lifecycle callbacks.
|
|
5311
5154
|
* The consumer API exposes simplified params (locale, hash, value) while the internal
|
|
@@ -5313,22 +5156,24 @@ const DICTIONARY_CACHE_MISS_EVENT_NAME = "dictionary-cache-miss";
|
|
|
5313
5156
|
*
|
|
5314
5157
|
* @deprecated - move to subscription api instead
|
|
5315
5158
|
*/
|
|
5316
|
-
function createLifecycleCallbacks(emit) {
|
|
5159
|
+
function createLifecycleCallbacks(emit, hasListeners = () => true) {
|
|
5317
5160
|
return {
|
|
5318
5161
|
onLocalesCacheHit: (params) => {
|
|
5319
|
-
|
|
5162
|
+
if (!hasListeners("locales-cache-hit")) return;
|
|
5163
|
+
emit(LOCALES_CACHE_HIT_EVENT_NAME, {
|
|
5320
5164
|
locale: params.inputKey,
|
|
5321
5165
|
translations: params.outputValue.getInternalCache()
|
|
5322
5166
|
});
|
|
5323
5167
|
},
|
|
5324
5168
|
onLocalesCacheMiss: (params) => {
|
|
5169
|
+
if (!hasListeners("locales-cache-miss")) return;
|
|
5325
5170
|
emit(LOCALES_CACHE_MISS_EVENT_NAME, {
|
|
5326
5171
|
locale: params.inputKey,
|
|
5327
5172
|
translations: params.outputValue.getInternalCache()
|
|
5328
5173
|
});
|
|
5329
5174
|
},
|
|
5330
5175
|
onTranslationsCacheHit: (params) => {
|
|
5331
|
-
emit(
|
|
5176
|
+
emit(TRANSLATIONS_CACHE_HIT_EVENT_NAME, {
|
|
5332
5177
|
locale: params.locale,
|
|
5333
5178
|
hash: params.cacheKey,
|
|
5334
5179
|
translation: params.outputValue
|
|
@@ -5342,19 +5187,21 @@ function createLifecycleCallbacks(emit) {
|
|
|
5342
5187
|
});
|
|
5343
5188
|
},
|
|
5344
5189
|
onLocalesDictionaryCacheHit: (params) => {
|
|
5345
|
-
|
|
5190
|
+
if (!hasListeners("locales-dictionary-cache-hit")) return;
|
|
5191
|
+
emit(LOCALES_DICTIONARY_CACHE_HIT_EVENT_NAME, {
|
|
5346
5192
|
locale: params.inputKey,
|
|
5347
5193
|
dictionary: params.outputValue.getInternalCache()
|
|
5348
5194
|
});
|
|
5349
5195
|
},
|
|
5350
5196
|
onLocalesDictionaryCacheMiss: (params) => {
|
|
5197
|
+
if (!hasListeners("locales-dictionary-cache-miss")) return;
|
|
5351
5198
|
emit(LOCALES_DICTIONARY_CACHE_MISS_EVENT_NAME, {
|
|
5352
5199
|
locale: params.inputKey,
|
|
5353
5200
|
dictionary: params.outputValue.getInternalCache()
|
|
5354
5201
|
});
|
|
5355
5202
|
},
|
|
5356
5203
|
onDictionaryCacheHit: (params) => {
|
|
5357
|
-
emit(
|
|
5204
|
+
emit(DICTIONARY_CACHE_HIT_EVENT_NAME, {
|
|
5358
5205
|
locale: params.locale,
|
|
5359
5206
|
id: params.cacheKey,
|
|
5360
5207
|
dictionaryEntry: params.outputValue
|
|
@@ -5368,7 +5215,7 @@ function createLifecycleCallbacks(emit) {
|
|
|
5368
5215
|
});
|
|
5369
5216
|
},
|
|
5370
5217
|
onDictionaryObjectCacheHit: (params) => {
|
|
5371
|
-
emit(
|
|
5218
|
+
emit(DICTIONARY_OBJECT_CACHE_HIT_EVENT_NAME, {
|
|
5372
5219
|
locale: params.locale,
|
|
5373
5220
|
id: params.cacheKey,
|
|
5374
5221
|
dictionaryValue: params.outputValue
|
|
@@ -5403,6 +5250,9 @@ var EventEmitter = class {
|
|
|
5403
5250
|
emit(eventName, event) {
|
|
5404
5251
|
this.listeners[eventName]?.forEach((subscriber) => subscriber(event));
|
|
5405
5252
|
}
|
|
5253
|
+
hasListeners(eventName) {
|
|
5254
|
+
return (this.listeners[eventName]?.size ?? 0) > 0;
|
|
5255
|
+
}
|
|
5406
5256
|
};
|
|
5407
5257
|
/**
|
|
5408
5258
|
* Subscribes to the lifecycle callbacks and emits the events to the event emitter
|
|
@@ -5412,7 +5262,7 @@ var EventEmitter = class {
|
|
|
5412
5262
|
* and is only used internally
|
|
5413
5263
|
*/
|
|
5414
5264
|
function subscribeLifecycleCallbacks({ onLocalesCacheHit, onLocalesCacheMiss, onTranslationsCacheHit, onTranslationsCacheMiss, onLocalesDictionaryCacheHit, onLocalesDictionaryCacheMiss, onDictionaryCacheHit, onDictionaryCacheMiss, onDictionaryObjectCacheHit }, subscribe) {
|
|
5415
|
-
if (onLocalesCacheHit) subscribe(
|
|
5265
|
+
if (onLocalesCacheHit) subscribe(LOCALES_CACHE_HIT_EVENT_NAME, (event) => {
|
|
5416
5266
|
onLocalesCacheHit({
|
|
5417
5267
|
...event,
|
|
5418
5268
|
value: event.translations
|
|
@@ -5424,7 +5274,7 @@ function subscribeLifecycleCallbacks({ onLocalesCacheHit, onLocalesCacheMiss, on
|
|
|
5424
5274
|
value: event.translations
|
|
5425
5275
|
});
|
|
5426
5276
|
});
|
|
5427
|
-
if (onTranslationsCacheHit) subscribe(
|
|
5277
|
+
if (onTranslationsCacheHit) subscribe(TRANSLATIONS_CACHE_HIT_EVENT_NAME, (event) => {
|
|
5428
5278
|
onTranslationsCacheHit({
|
|
5429
5279
|
...event,
|
|
5430
5280
|
value: event.translation
|
|
@@ -5436,19 +5286,19 @@ function subscribeLifecycleCallbacks({ onLocalesCacheHit, onLocalesCacheMiss, on
|
|
|
5436
5286
|
value: event.translation
|
|
5437
5287
|
});
|
|
5438
5288
|
});
|
|
5439
|
-
if (onLocalesDictionaryCacheHit) subscribe(
|
|
5289
|
+
if (onLocalesDictionaryCacheHit) subscribe(LOCALES_DICTIONARY_CACHE_HIT_EVENT_NAME, (event) => {
|
|
5440
5290
|
onLocalesDictionaryCacheHit(event);
|
|
5441
5291
|
});
|
|
5442
5292
|
if (onLocalesDictionaryCacheMiss) subscribe(LOCALES_DICTIONARY_CACHE_MISS_EVENT_NAME, (event) => {
|
|
5443
5293
|
onLocalesDictionaryCacheMiss(event);
|
|
5444
5294
|
});
|
|
5445
|
-
if (onDictionaryCacheHit) subscribe(
|
|
5295
|
+
if (onDictionaryCacheHit) subscribe(DICTIONARY_CACHE_HIT_EVENT_NAME, (event) => {
|
|
5446
5296
|
onDictionaryCacheHit(event);
|
|
5447
5297
|
});
|
|
5448
5298
|
if (onDictionaryCacheMiss) subscribe(DICTIONARY_CACHE_MISS_EVENT_NAME, (event) => {
|
|
5449
5299
|
onDictionaryCacheMiss(event);
|
|
5450
5300
|
});
|
|
5451
|
-
if (onDictionaryObjectCacheHit) subscribe(
|
|
5301
|
+
if (onDictionaryObjectCacheHit) subscribe(DICTIONARY_OBJECT_CACHE_HIT_EVENT_NAME, (event) => {
|
|
5452
5302
|
onDictionaryObjectCacheHit(event);
|
|
5453
5303
|
});
|
|
5454
5304
|
}
|
|
@@ -5479,26 +5329,32 @@ var I18nManager = class extends EventEmitter {
|
|
|
5479
5329
|
locales: this.config.locales,
|
|
5480
5330
|
customMapping: this.config.customMapping
|
|
5481
5331
|
});
|
|
5482
|
-
const loadTranslations =
|
|
5483
|
-
|
|
5332
|
+
const loadTranslations = routeCreateTranslationLoader({
|
|
5333
|
+
loadTranslations: params.loadTranslations,
|
|
5334
|
+
type: getLoadTranslationsType(params),
|
|
5335
|
+
remoteTranslationLoaderParams: {
|
|
5336
|
+
cacheUrl: params.cacheUrl,
|
|
5337
|
+
projectId: params.projectId,
|
|
5338
|
+
_versionId: params._versionId,
|
|
5339
|
+
_branchId: params._branchId,
|
|
5340
|
+
customMapping: params.customMapping
|
|
5341
|
+
}
|
|
5342
|
+
});
|
|
5343
|
+
const loadDictionary = params.loadDictionary ?? (() => Promise.resolve({}));
|
|
5484
5344
|
const runtimeTranslationTimeout = this.config.runtimeTranslation?.timeout ?? DEFAULT_TRANSLATION_TIMEOUT;
|
|
5485
5345
|
const runtimeTranslationMetadata = this.config.runtimeTranslation?.metadata ?? {};
|
|
5486
5346
|
const createTranslateMany = createTranslateManyFactory(this.getGTClassClean(), runtimeTranslationTimeout, runtimeTranslationMetadata);
|
|
5487
5347
|
subscribeLifecycleCallbacks(params.lifecycle ?? {}, (...args) => this.subscribe(...args));
|
|
5488
|
-
const lifecycle = createLifecycleCallbacks((...args) => this.emit(...args));
|
|
5348
|
+
const lifecycle = createLifecycleCallbacks((...args) => this.emit(...args), (eventName) => this.hasListeners(eventName));
|
|
5489
5349
|
this.localesCache = new LocalesCache({
|
|
5490
|
-
loadTranslations,
|
|
5491
|
-
createTranslateMany,
|
|
5492
|
-
lifecycle,
|
|
5493
|
-
ttl: this.config.cacheExpiryTime,
|
|
5494
|
-
batchConfig: this.config.batchConfig
|
|
5495
|
-
});
|
|
5496
|
-
this.localesDictionaryCache = new LocalesDictionaryCache({
|
|
5497
5350
|
defaultLocale: this.config.defaultLocale,
|
|
5498
5351
|
dictionary: params.dictionary,
|
|
5352
|
+
loadTranslations,
|
|
5499
5353
|
loadDictionary,
|
|
5500
|
-
|
|
5354
|
+
createTranslateMany,
|
|
5355
|
+
translateDictionaryEntry: (locale, id, sourceEntry) => this.translateDictionaryEntry(locale, id, sourceEntry),
|
|
5501
5356
|
ttl: this.config.cacheExpiryTime,
|
|
5357
|
+
batchConfig: this.config.batchConfig,
|
|
5502
5358
|
lifecycle
|
|
5503
5359
|
});
|
|
5504
5360
|
}
|
|
@@ -5570,9 +5426,7 @@ var I18nManager = class extends EventEmitter {
|
|
|
5570
5426
|
try {
|
|
5571
5427
|
const translationLocale = this.resolveCacheLocale(locale);
|
|
5572
5428
|
if (!translationLocale) return {};
|
|
5573
|
-
|
|
5574
|
-
if (!txCache) txCache = await this.localesCache.miss(translationLocale);
|
|
5575
|
-
return txCache.getInternalCache();
|
|
5429
|
+
return (await this.localesCache.getOrLoadTranslations(translationLocale)).getInternalCache();
|
|
5576
5430
|
} catch (error) {
|
|
5577
5431
|
this.handleError(error);
|
|
5578
5432
|
return {};
|
|
@@ -5585,10 +5439,8 @@ var I18nManager = class extends EventEmitter {
|
|
|
5585
5439
|
async loadDictionary(locale) {
|
|
5586
5440
|
try {
|
|
5587
5441
|
const dictionaryLocale = this.resolveCacheLocale(locale);
|
|
5588
|
-
if (!dictionaryLocale) return this.
|
|
5589
|
-
|
|
5590
|
-
if (!dictionaryCache) dictionaryCache = await this.localesDictionaryCache.miss(dictionaryLocale);
|
|
5591
|
-
return dictionaryCache.getInternalCache();
|
|
5442
|
+
if (!dictionaryLocale) return this.getDefaultDictionaryCache()?.getInternalCache() ?? {};
|
|
5443
|
+
return (await this.localesCache.getOrLoadDictionary(dictionaryLocale)).getInternalCache();
|
|
5592
5444
|
} catch (error) {
|
|
5593
5445
|
this.handleError(error);
|
|
5594
5446
|
return {};
|
|
@@ -5599,8 +5451,8 @@ var I18nManager = class extends EventEmitter {
|
|
|
5599
5451
|
*/
|
|
5600
5452
|
lookupDictionary(locale, id) {
|
|
5601
5453
|
try {
|
|
5602
|
-
const dictionaryLocale = this.
|
|
5603
|
-
return this.
|
|
5454
|
+
const dictionaryLocale = this.resolveDictionaryCacheLocale(locale);
|
|
5455
|
+
return this.localesCache.getDictionary(dictionaryLocale)?.getEntry(id);
|
|
5604
5456
|
} catch (error) {
|
|
5605
5457
|
this.handleError(error);
|
|
5606
5458
|
return;
|
|
@@ -5611,8 +5463,8 @@ var I18nManager = class extends EventEmitter {
|
|
|
5611
5463
|
*/
|
|
5612
5464
|
lookupDictionaryObj(locale, id) {
|
|
5613
5465
|
try {
|
|
5614
|
-
const dictionaryLocale = this.
|
|
5615
|
-
return this.
|
|
5466
|
+
const dictionaryLocale = this.resolveDictionaryCacheLocale(locale);
|
|
5467
|
+
return this.localesCache.getDictionary(dictionaryLocale)?.getValue(id);
|
|
5616
5468
|
} catch (error) {
|
|
5617
5469
|
this.handleError(error);
|
|
5618
5470
|
return;
|
|
@@ -5625,19 +5477,10 @@ var I18nManager = class extends EventEmitter {
|
|
|
5625
5477
|
async lookupDictionaryWithFallback(locale, id) {
|
|
5626
5478
|
try {
|
|
5627
5479
|
const dictionaryLocale = this.resolveCacheLocale(locale);
|
|
5628
|
-
if (!dictionaryLocale)
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
}
|
|
5633
|
-
let dictionaryCache = this.localesDictionaryCache.get(dictionaryLocale);
|
|
5634
|
-
if (!dictionaryCache) dictionaryCache = await this.localesDictionaryCache.miss(dictionaryLocale);
|
|
5635
|
-
let dictionaryEntry = dictionaryCache.get(id);
|
|
5636
|
-
if (dictionaryEntry === void 0) {
|
|
5637
|
-
const sourceEntry = this.localesDictionaryCache.get(this.config.defaultLocale)?.get(id);
|
|
5638
|
-
if (sourceEntry === void 0) throw new DictionarySourceNotFoundError(id);
|
|
5639
|
-
dictionaryEntry = await dictionaryCache.miss(id, sourceEntry);
|
|
5640
|
-
}
|
|
5480
|
+
if (!dictionaryLocale) return this.getSourceDictionaryEntry(id);
|
|
5481
|
+
const dictionaryCache = await this.localesCache.getOrLoadDictionary(dictionaryLocale);
|
|
5482
|
+
let dictionaryEntry = dictionaryCache.getEntry(id);
|
|
5483
|
+
if (dictionaryEntry === void 0) dictionaryEntry = await dictionaryCache.materializeEntry(id, this.getSourceDictionaryEntry(id));
|
|
5641
5484
|
return dictionaryEntry;
|
|
5642
5485
|
} catch (error) {
|
|
5643
5486
|
this.handleError(error);
|
|
@@ -5651,25 +5494,41 @@ var I18nManager = class extends EventEmitter {
|
|
|
5651
5494
|
async lookupDictionaryObjWithFallback(locale, id) {
|
|
5652
5495
|
try {
|
|
5653
5496
|
const dictionaryLocale = this.resolveCacheLocale(locale);
|
|
5654
|
-
if (!dictionaryLocale)
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5497
|
+
if (!dictionaryLocale) return this.getSourceDictionaryObject(id);
|
|
5498
|
+
const dictionaryCache = await this.localesCache.getOrLoadDictionary(dictionaryLocale);
|
|
5499
|
+
const targetObject = dictionaryCache.getValue(id);
|
|
5500
|
+
const sourceObject = this.getSourceDictionaryObject(id, { throwOnMissing: false });
|
|
5501
|
+
if (sourceObject === void 0) {
|
|
5502
|
+
if (targetObject !== void 0) return targetObject;
|
|
5503
|
+
throw new DictionarySourceNotFoundError(id);
|
|
5658
5504
|
}
|
|
5659
|
-
|
|
5660
|
-
if (!dictionaryCache) dictionaryCache = await this.localesDictionaryCache.miss(dictionaryLocale);
|
|
5661
|
-
let dictionaryObject = dictionaryCache.getObj(id);
|
|
5662
|
-
if (dictionaryObject === void 0) {
|
|
5663
|
-
const sourceObject = this.localesDictionaryCache.get(this.config.defaultLocale)?.getObj(id);
|
|
5664
|
-
if (sourceObject === void 0) throw new DictionarySourceNotFoundError(id);
|
|
5665
|
-
dictionaryObject = await dictionaryCache.missObj(id, sourceObject);
|
|
5666
|
-
}
|
|
5667
|
-
return dictionaryObject;
|
|
5505
|
+
return await dictionaryCache.materializeValue(id, sourceObject, targetObject);
|
|
5668
5506
|
} catch (error) {
|
|
5669
5507
|
this.handleError(error);
|
|
5670
5508
|
return;
|
|
5671
5509
|
}
|
|
5672
5510
|
}
|
|
5511
|
+
async translateDictionaryEntry(locale, id, sourceEntry) {
|
|
5512
|
+
const translation = await this.lookupTranslationWithFallbackResolved(locale, sourceEntry.entry, resolveDictionaryLookupOptions(sourceEntry.options));
|
|
5513
|
+
if (typeof translation !== "string") throw new Error(`Dictionary entry "${id}" could not be translated into a string. Check the source entry and translation loader output.`);
|
|
5514
|
+
return translation;
|
|
5515
|
+
}
|
|
5516
|
+
getSourceDictionaryEntry(id) {
|
|
5517
|
+
const sourceEntry = this.getDefaultDictionaryCache()?.getEntry(id);
|
|
5518
|
+
if (sourceEntry === void 0) throw new DictionarySourceNotFoundError(id);
|
|
5519
|
+
return sourceEntry;
|
|
5520
|
+
}
|
|
5521
|
+
getSourceDictionaryObject(id, { throwOnMissing = true } = {}) {
|
|
5522
|
+
const sourceObject = this.getDefaultDictionaryCache()?.getValue(id);
|
|
5523
|
+
if (sourceObject === void 0 && throwOnMissing) throw new DictionarySourceNotFoundError(id);
|
|
5524
|
+
return sourceObject;
|
|
5525
|
+
}
|
|
5526
|
+
getDefaultDictionaryCache() {
|
|
5527
|
+
return this.localesCache.getDictionary(this.config.defaultLocale);
|
|
5528
|
+
}
|
|
5529
|
+
resolveDictionaryCacheLocale(locale) {
|
|
5530
|
+
return this.resolveCacheLocale(locale) ?? this.config.defaultLocale;
|
|
5531
|
+
}
|
|
5673
5532
|
/**
|
|
5674
5533
|
* Just lookup a translation
|
|
5675
5534
|
*/
|
|
@@ -5677,7 +5536,7 @@ var I18nManager = class extends EventEmitter {
|
|
|
5677
5536
|
try {
|
|
5678
5537
|
const { translationLocale, options: lookupOptions } = this.resolveLookupParams(locale, options);
|
|
5679
5538
|
if (!translationLocale) return message;
|
|
5680
|
-
const txCache = this.localesCache.
|
|
5539
|
+
const txCache = this.localesCache.getTranslations(translationLocale);
|
|
5681
5540
|
if (!txCache) return void 0;
|
|
5682
5541
|
return txCache.get({
|
|
5683
5542
|
message,
|
|
@@ -5715,9 +5574,7 @@ var I18nManager = class extends EventEmitter {
|
|
|
5715
5574
|
if (!translationLocale) return (message) => message;
|
|
5716
5575
|
const resolvedPrefetchEntries = resolvePrefetchEntriesByLocale(prefetchEntries, translationLocale, (entryLocale) => this.resolveCacheLocale(entryLocale) ?? this.resolveLocale(entryLocale));
|
|
5717
5576
|
if (resolvedPrefetchEntries.length !== prefetchEntries.length) logger_default.warn(`I18nManager: getLookupTranslation(): prefetchEntries must all be the same locale, ignoring all entries that are not for ${translationLocale}`);
|
|
5718
|
-
|
|
5719
|
-
if (!txCache) txCache = await this.localesCache.miss(translationLocale);
|
|
5720
|
-
if (!txCache) return () => void 0;
|
|
5577
|
+
const txCache = await this.localesCache.getOrLoadTranslations(translationLocale);
|
|
5721
5578
|
await Promise.all(resolvedPrefetchEntries.filter((entry) => txCache.get(entry) == null).map((entry) => txCache.miss(entry)));
|
|
5722
5579
|
return (message, options = {}) => {
|
|
5723
5580
|
return txCache.get({
|
|
@@ -5819,8 +5676,7 @@ var I18nManager = class extends EventEmitter {
|
|
|
5819
5676
|
async lookupTranslationWithFallbackResolved(locale, message, options) {
|
|
5820
5677
|
const { translationLocale, options: lookupOptions } = this.resolveLookupParams(locale, options);
|
|
5821
5678
|
if (!translationLocale) return message;
|
|
5822
|
-
|
|
5823
|
-
if (!txCache) txCache = await this.localesCache.miss(translationLocale);
|
|
5679
|
+
const txCache = await this.localesCache.getOrLoadTranslations(translationLocale);
|
|
5824
5680
|
let translation = txCache.get({
|
|
5825
5681
|
message,
|
|
5826
5682
|
options: lookupOptions
|
|
@@ -5832,14 +5688,6 @@ var I18nManager = class extends EventEmitter {
|
|
|
5832
5688
|
return translation;
|
|
5833
5689
|
}
|
|
5834
5690
|
/**
|
|
5835
|
-
* Runtime lookup function for dictionaries
|
|
5836
|
-
*/
|
|
5837
|
-
async dictionaryRuntimeTranslate(locale, id, sourceEntry) {
|
|
5838
|
-
const translation = await this.lookupTranslationWithFallbackResolved(locale, sourceEntry.entry, resolveDictionaryLookupOptions(sourceEntry.options));
|
|
5839
|
-
if (typeof translation !== "string") throw new Error(`Dictionary entry "${id}" could not be translated into a string. Check the source entry and translation loader output.`);
|
|
5840
|
-
return translation;
|
|
5841
|
-
}
|
|
5842
|
-
/**
|
|
5843
5691
|
* A helper function to create a gt class that is locale agnostic
|
|
5844
5692
|
* This is helpful for when our getLocale function is bound to a
|
|
5845
5693
|
* specific context
|
|
@@ -5936,28 +5784,6 @@ function resolvePrefetchEntriesByLocale(prefetchEntries, locale, resolveLocale)
|
|
|
5936
5784
|
}
|
|
5937
5785
|
});
|
|
5938
5786
|
}
|
|
5939
|
-
/**
|
|
5940
|
-
* Helper function for creating a translation loader
|
|
5941
|
-
*/
|
|
5942
|
-
function createTranslationLoader(params) {
|
|
5943
|
-
return routeCreateTranslationLoader({
|
|
5944
|
-
loadTranslations: params.loadTranslations,
|
|
5945
|
-
type: getLoadTranslationsType(params),
|
|
5946
|
-
remoteTranslationLoaderParams: {
|
|
5947
|
-
cacheUrl: params.cacheUrl,
|
|
5948
|
-
projectId: params.projectId,
|
|
5949
|
-
_versionId: params._versionId,
|
|
5950
|
-
_branchId: params._branchId,
|
|
5951
|
-
customMapping: params.customMapping
|
|
5952
|
-
}
|
|
5953
|
-
});
|
|
5954
|
-
}
|
|
5955
|
-
/**
|
|
5956
|
-
* Helper function for creating a dictionary loader
|
|
5957
|
-
*/
|
|
5958
|
-
function createDictionaryLoader(params) {
|
|
5959
|
-
return params.loadDictionary ?? (() => Promise.resolve({}));
|
|
5960
|
-
}
|
|
5961
5787
|
let i18nManager = void 0;
|
|
5962
5788
|
let fallbackDefaultLocale = "en";
|
|
5963
5789
|
let conditionStore = { getLocale: () => fallbackDefaultLocale };
|