@generaltranslation/react-core 11.1.12 → 11.1.13
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 +8 -0
- package/dist/functions/helpers/getTranslationsSnapshot.cjs +1 -1
- package/dist/functions/helpers/getTranslationsSnapshot.cjs.map +1 -1
- package/dist/functions/helpers/getTranslationsSnapshot.d.ts +3 -4
- package/dist/functions/helpers/getTranslationsSnapshot.d.ts.map +1 -1
- package/dist/functions/helpers/getTranslationsSnapshot.mjs +1 -1
- package/dist/functions/helpers/getTranslationsSnapshot.mjs.map +1 -1
- package/dist/i18n-store/I18nStore.cjs +1 -1
- package/dist/i18n-store/I18nStore.cjs.map +1 -1
- package/dist/i18n-store/I18nStore.d.ts +8 -0
- package/dist/i18n-store/I18nStore.d.ts.map +1 -1
- package/dist/i18n-store/I18nStore.mjs +1 -1
- package/dist/i18n-store/I18nStore.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @generaltranslation/react-core
|
|
2
2
|
|
|
3
|
+
## 11.1.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#2144](https://github.com/generaltranslation/gt/pull/2144) [`4422032`](https://github.com/generaltranslation/gt/commit/4422032bb5d365aabe095ee1ff103fd5bfdee578) Thanks [@eoinest](https://github.com/eoinest)! - Log runtime translation failures from the i18n store instead of letting them escape as unhandled promise rejections that crash the dev server during SSR
|
|
8
|
+
|
|
9
|
+
- [#2144](https://github.com/generaltranslation/gt/pull/2144) [`4422032`](https://github.com/generaltranslation/gt/commit/4422032bb5d365aabe095ee1ff103fd5bfdee578) Thanks [@eoinest](https://github.com/eoinest)! - Return a snapshot with no entry for the locale, and warn, when `getTranslationsSnapshot()` cannot load translations for that locale, instead of letting the loader error propagate. Selecting a locale whose translation files do not exist yet crashed server route loaders (such as the TanStack Start root loader) with an HTTP 500 in development; content for that locale now renders untranslated. Because the failed locale is omitted rather than hydrated as an empty cache entry, a later lookup retries the loader once translations exist.
|
|
10
|
+
|
|
3
11
|
## 11.1.12
|
|
4
12
|
|
|
5
13
|
## 11.1.11
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`../../i18n-cache/singleton-operations.cjs`);async function
|
|
1
|
+
require(`../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../i18n-cache/singleton-operations.cjs`);let t=require(`generaltranslation/internal`);async function n(n){let r=e.getReactI18nCache();try{return{[n]:await r.loadTranslations(n)}}catch(e){return console.warn((0,t.createDiagnosticMessage)({source:`@generaltranslation/react-core`,severity:`Warning`,whatHappened:`Could not load translations for locale "${n}", so content for this locale renders untranslated`,why:`the translation loader failed, usually because translations for this locale have not been generated yet`,fix:`Generate translations for this locale, or check your loadTranslations configuration.`,details:(0,t.formatDiagnosticErrorDetails)(e)})),{}}}exports.getTranslationsSnapshot=n;
|
|
2
2
|
//# sourceMappingURL=getTranslationsSnapshot.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getTranslationsSnapshot.cjs","names":["getReactI18nCache"],"sources":["../../../src/functions/helpers/getTranslationsSnapshot.ts"],"sourcesContent":["import { Hash, Locale } from 'gt-i18n/internal/types';\nimport { Translation } from 'gt-i18n/types';\nimport { getReactI18nCache } from '../../i18n-cache/singleton-operations';\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"getTranslationsSnapshot.cjs","names":["getReactI18nCache"],"sources":["../../../src/functions/helpers/getTranslationsSnapshot.ts"],"sourcesContent":["import { Hash, Locale } from 'gt-i18n/internal/types';\nimport { Translation } from 'gt-i18n/types';\nimport {\n createDiagnosticMessage,\n formatDiagnosticErrorDetails,\n} from 'generaltranslation/internal';\nimport { getReactI18nCache } from '../../i18n-cache/singleton-operations';\n\n/**\n * Serializable cached translations for provider hydration; a failed load\n * yields a snapshot with no entry for the locale, so hydration caches nothing\n * and a later lookup retries. TODO: perhaps move to /i18n for type generics\n */\nexport async function getTranslationsSnapshot(\n locale: Locale\n): Promise<Record<Locale, Record<Hash, Translation>>> {\n const i18nCache = getReactI18nCache();\n try {\n return { [locale]: await i18nCache.loadTranslations(locale) };\n } catch (error) {\n console.warn(\n createDiagnosticMessage({\n source: '@generaltranslation/react-core',\n severity: 'Warning',\n whatHappened: `Could not load translations for locale \"${locale}\", so content for this locale renders untranslated`,\n why: 'the translation loader failed, usually because translations for this locale have not been generated yet',\n fix: 'Generate translations for this locale, or check your loadTranslations configuration.',\n details: formatDiagnosticErrorDetails(error),\n })\n );\n return {};\n }\n}\n"],"mappings":"0JAaA,eAAsB,EACpB,EACoD,CACpD,IAAM,EAAYA,EAAAA,mBAAmB,CACrC,GAAI,CACF,MAAO,EAAG,GAAS,MAAM,EAAU,iBAAiB,EAAO,CAAE,OACtD,EAAO,CAWd,OAVA,QAAQ,MAAA,EAAA,EAAA,yBACkB,CACtB,OAAQ,iCACR,SAAU,UACV,aAAc,2CAA2C,EAAO,oDAChE,IAAK,0GACL,IAAK,uFACL,SAAA,EAAA,EAAA,8BAAsC,EAAM,CAC7C,CAAC,CACH,CACM,EAAE"}
|
|
@@ -3,10 +3,9 @@ import { Hash, Locale } from "gt-i18n/internal/types";
|
|
|
3
3
|
|
|
4
4
|
//#region src/functions/helpers/getTranslationsSnapshot.d.ts
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* TODO: perhaps should be moved to /i18n if allowing for type generics
|
|
6
|
+
* Serializable cached translations for provider hydration; a failed load
|
|
7
|
+
* yields a snapshot with no entry for the locale, so hydration caches nothing
|
|
8
|
+
* and a later lookup retries. TODO: perhaps move to /i18n for type generics
|
|
10
9
|
*/
|
|
11
10
|
declare function getTranslationsSnapshot(locale: Locale): Promise<Record<Locale, Record<Hash, Translation>>>;
|
|
12
11
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getTranslationsSnapshot.d.ts","names":[],"sources":["../../../src/functions/helpers/getTranslationsSnapshot.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"getTranslationsSnapshot.d.ts","names":[],"sources":["../../../src/functions/helpers/getTranslationsSnapshot.ts"],"mappings":";;;;;;AAaA;;;iBAAsB,uBAAA,CACpB,MAAA,EAAQ,MAAA,GACP,OAAA,CAAQ,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,IAAA,EAAM,WAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{getReactI18nCache as e}from"../../i18n-cache/singleton-operations.mjs";async function
|
|
1
|
+
import{getReactI18nCache as e}from"../../i18n-cache/singleton-operations.mjs";import{createDiagnosticMessage as t,formatDiagnosticErrorDetails as n}from"generaltranslation/internal";async function r(r){let i=e();try{return{[r]:await i.loadTranslations(r)}}catch(e){return console.warn(t({source:`@generaltranslation/react-core`,severity:`Warning`,whatHappened:`Could not load translations for locale "${r}", so content for this locale renders untranslated`,why:`the translation loader failed, usually because translations for this locale have not been generated yet`,fix:`Generate translations for this locale, or check your loadTranslations configuration.`,details:n(e)})),{}}}export{r as getTranslationsSnapshot};
|
|
2
2
|
//# sourceMappingURL=getTranslationsSnapshot.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getTranslationsSnapshot.mjs","names":[],"sources":["../../../src/functions/helpers/getTranslationsSnapshot.ts"],"sourcesContent":["import { Hash, Locale } from 'gt-i18n/internal/types';\nimport { Translation } from 'gt-i18n/types';\nimport { getReactI18nCache } from '../../i18n-cache/singleton-operations';\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"getTranslationsSnapshot.mjs","names":[],"sources":["../../../src/functions/helpers/getTranslationsSnapshot.ts"],"sourcesContent":["import { Hash, Locale } from 'gt-i18n/internal/types';\nimport { Translation } from 'gt-i18n/types';\nimport {\n createDiagnosticMessage,\n formatDiagnosticErrorDetails,\n} from 'generaltranslation/internal';\nimport { getReactI18nCache } from '../../i18n-cache/singleton-operations';\n\n/**\n * Serializable cached translations for provider hydration; a failed load\n * yields a snapshot with no entry for the locale, so hydration caches nothing\n * and a later lookup retries. TODO: perhaps move to /i18n for type generics\n */\nexport async function getTranslationsSnapshot(\n locale: Locale\n): Promise<Record<Locale, Record<Hash, Translation>>> {\n const i18nCache = getReactI18nCache();\n try {\n return { [locale]: await i18nCache.loadTranslations(locale) };\n } catch (error) {\n console.warn(\n createDiagnosticMessage({\n source: '@generaltranslation/react-core',\n severity: 'Warning',\n whatHappened: `Could not load translations for locale \"${locale}\", so content for this locale renders untranslated`,\n why: 'the translation loader failed, usually because translations for this locale have not been generated yet',\n fix: 'Generate translations for this locale, or check your loadTranslations configuration.',\n details: formatDiagnosticErrorDetails(error),\n })\n );\n return {};\n }\n}\n"],"mappings":"sLAaA,eAAsB,EACpB,EACoD,CACpD,IAAM,EAAY,GAAmB,CACrC,GAAI,CACF,MAAO,EAAG,GAAS,MAAM,EAAU,iBAAiB,EAAO,CAAE,OACtD,EAAO,CAWd,OAVA,QAAQ,KACN,EAAwB,CACtB,OAAQ,iCACR,SAAU,UACV,aAAc,2CAA2C,EAAO,oDAChE,IAAK,0GACL,IAAK,uFACL,QAAS,EAA6B,EAAM,CAC7C,CAAC,CACH,CACM,EAAE"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../i18n-cache/singleton-operations.cjs`),t=require(`./utils/subscriptions.cjs`),n=require(`./utils/translations.cjs`),r=require(`./utils/dictionaries.cjs`);let i=require(`gt-i18n/internal`);var
|
|
1
|
+
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../i18n-cache/singleton-operations.cjs`),t=require(`./utils/subscriptions.cjs`),n=require(`./utils/translations.cjs`),r=require(`./utils/dictionaries.cjs`);let i=require(`gt-i18n/internal`),a=require(`generaltranslation/internal`);function o(e){if(e instanceof Error)return`${e.name}|${e.message}`;if(typeof e==`object`&&e)try{return`object|${JSON.stringify(e)}`}catch{return`object|${String(e)}`}return`${typeof e}|${String(e)}`}var s=class{translateListeners=new Set;dictionaryEntryListeners=new Set;dictionaryObjectListeners=new Set;loggedRuntimeTranslationErrors=new Set;constructor(){}updateTranslations=t=>{e.getReactI18nCache().updateTranslations(t)};updateDictionaries=t=>{e.getReactI18nCache().updateDictionaries(t)};translate=async t=>e.getReactI18nCache().lookupTranslationWithFallback(t.locale,t.message,t.options).then(()=>{this.emitTranslateEvent(t)}).catch(e=>this.logRuntimeTranslationError(e));translateDictionaryEntry=t=>{e.getReactI18nCache().lookupDictionaryWithFallback(t.locale,t.id).then(()=>{this.emitDictionaryEvent(t)}).catch(e=>this.logRuntimeTranslationError(e))};translateDictionaryObject=t=>{e.getReactI18nCache().lookupDictionaryObjWithFallback(t.locale,t.id).then(()=>{this.emitDictionaryEvent(t)}).catch(e=>this.logRuntimeTranslationError(e))};logRuntimeTranslationError(e){let t=(0,a.formatDiagnosticErrorDetails)(e),n=o(e);if(!this.loggedRuntimeTranslationErrors.has(n)){if(this.loggedRuntimeTranslationErrors.add(n),this.loggedRuntimeTranslationErrors.size>100){let e=this.loggedRuntimeTranslationErrors.values().next().value;e!==void 0&&this.loggedRuntimeTranslationErrors.delete(e)}console.error((0,a.createDiagnosticMessage)({source:`@generaltranslation/react-core`,severity:`Error`,whatHappened:`A runtime translation request failed.`,wayOut:`Rendering falls back to untranslated content.`,details:t}))}}subscribeToTranslate=(e,n)=>{let r=(0,i.getTranslateListenerKey)(e);return t.subscribeToSet(this.translateListeners,e=>{(0,i.getTranslateListenerKey)(e)===r&&n()})};subscribeToTranslationEvents=e=>t.subscribeToSet(this.translateListeners,e);subscribeToDictionaryEntryEvents=e=>t.subscribeToSet(this.dictionaryEntryListeners,e);subscribeToDictionaryObjectEvents=e=>t.subscribeToSet(this.dictionaryObjectListeners,e);getTranslateSnapshot=(t,r={})=>n.lookupTranslation(r,t)??e.getReactI18nCache().lookupTranslation(t.locale,t.message,t.options);getDictionaryEntrySnapshot=(t,n={})=>r.lookupDictionaryEntry(n,t)??e.getReactI18nCache().lookupDictionary(t.locale,t.id);getDictionaryObjectSnapshot=(t,n={})=>r.lookupDictionaryObject(n,t)??e.getReactI18nCache().lookupDictionaryObj(t.locale,t.id);emitTranslateEvent(e){this.translateListeners.forEach(t=>t(e))}emitDictionaryEvent(e){this.dictionaryEntryListeners.forEach(t=>t(e)),this.dictionaryObjectListeners.forEach(t=>{t(e)})}};exports.I18nStore=s;
|
|
2
2
|
//# sourceMappingURL=I18nStore.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"I18nStore.cjs","names":["getReactI18nCache","subscribeToSet","lookupTranslation","lookupDictionaryEntry","lookupDictionaryObject"],"sources":["../../src/i18n-store/I18nStore.ts"],"sourcesContent":["import { getTranslateListenerKey } from 'gt-i18n/internal';\nimport type {\n DictionaryEntrySnapshot,\n DictionaryLookup,\n DictionaryObjectSnapshot,\n StoreListener,\n TranslateEventListener,\n TranslateLookup,\n TranslateSnapshot,\n Unsubscribe,\n} from './storeTypes';\nimport type { Dictionary, Translation } from 'gt-i18n/types';\nimport { subscribeToSet } from './utils/subscriptions';\nimport { Hash, Locale } from 'gt-i18n/internal/types';\nimport { getReactI18nCache } from '../i18n-cache/singleton-operations';\nimport { lookupTranslation } from './utils/translations';\nimport {\n lookupDictionaryEntry,\n lookupDictionaryObject,\n} from './utils/dictionaries';\n\nexport type DictionaryStoreListener = (event: DictionaryLookup) => void;\n\n/**\n * I18nStore gives us the ability to perform client-side updates to translations.\n * Primarily useful for dev hot reload.\n *\n * This is the stateful primitive behind lookup subscriptions and runtime\n * translation requests. It intentionally does not know whether lookups are\n * being served from SPA singletons or SRA provider snapshots; that policy lives\n * in LookupAdapter, not in this store.\n */\nexport class I18nStore {\n // ----- Listener Sets ----- //\n\n private translateListeners = new Set<TranslateEventListener>();\n private dictionaryEntryListeners = new Set<DictionaryStoreListener>();\n private dictionaryObjectListeners = new Set<DictionaryStoreListener>();\n\n /**\n * I18nCache must be already initialized\n */\n constructor() {}\n\n // ========== Translation Updates ========== //\n\n updateTranslations = (\n translations: Record<Locale, Record<Hash, Translation>>\n ): void => {\n getReactI18nCache().updateTranslations(translations);\n };\n\n updateDictionaries = (dictionaries: Record<Locale, Dictionary>): void => {\n getReactI18nCache().updateDictionaries(dictionaries);\n };\n\n // ========== runtime translation ========== //\n\n translate = async <T extends Translation>(\n lookup: TranslateLookup<T>\n ): Promise<void> => {\n return getReactI18nCache()\n .lookupTranslationWithFallback(\n lookup.locale,\n lookup.message,\n lookup.options\n )\n .then((
|
|
1
|
+
{"version":3,"file":"I18nStore.cjs","names":["getReactI18nCache","subscribeToSet","lookupTranslation","lookupDictionaryEntry","lookupDictionaryObject"],"sources":["../../src/i18n-store/I18nStore.ts"],"sourcesContent":["import {\n createDiagnosticMessage,\n formatDiagnosticErrorDetails,\n} from 'generaltranslation/internal';\nimport { getTranslateListenerKey } from 'gt-i18n/internal';\nimport type {\n DictionaryEntrySnapshot,\n DictionaryLookup,\n DictionaryObjectSnapshot,\n StoreListener,\n TranslateEventListener,\n TranslateLookup,\n TranslateSnapshot,\n Unsubscribe,\n} from './storeTypes';\nimport type { Dictionary, Translation } from 'gt-i18n/types';\nimport { subscribeToSet } from './utils/subscriptions';\nimport { Hash, Locale } from 'gt-i18n/internal/types';\nimport { getReactI18nCache } from '../i18n-cache/singleton-operations';\nimport { lookupTranslation } from './utils/translations';\nimport {\n lookupDictionaryEntry,\n lookupDictionaryObject,\n} from './utils/dictionaries';\n\nexport type DictionaryStoreListener = (event: DictionaryLookup) => void;\n\nconst MAX_LOGGED_RUNTIME_TRANSLATION_ERRORS = 100;\n\nfunction getRuntimeTranslationErrorDedupeKey(error: unknown): string {\n if (error instanceof Error) {\n return `${error.name}|${error.message}`;\n }\n if (error !== null && typeof error === 'object') {\n try {\n return `object|${JSON.stringify(error)}`;\n } catch {\n return `object|${String(error)}`;\n }\n }\n return `${typeof error}|${String(error)}`;\n}\n\n/**\n * I18nStore gives us the ability to perform client-side updates to translations.\n * Primarily useful for dev hot reload.\n *\n * This is the stateful primitive behind lookup subscriptions and runtime\n * translation requests. It intentionally does not know whether lookups are\n * being served from SPA singletons or SRA provider snapshots; that policy lives\n * in LookupAdapter, not in this store.\n */\nexport class I18nStore {\n // ----- Listener Sets ----- //\n\n private translateListeners = new Set<TranslateEventListener>();\n private dictionaryEntryListeners = new Set<DictionaryStoreListener>();\n private dictionaryObjectListeners = new Set<DictionaryStoreListener>();\n private loggedRuntimeTranslationErrors = new Set<string>();\n\n /**\n * I18nCache must be already initialized\n */\n constructor() {}\n\n // ========== Translation Updates ========== //\n\n updateTranslations = (\n translations: Record<Locale, Record<Hash, Translation>>\n ): void => {\n getReactI18nCache().updateTranslations(translations);\n };\n\n updateDictionaries = (dictionaries: Record<Locale, Dictionary>): void => {\n getReactI18nCache().updateDictionaries(dictionaries);\n };\n\n // ========== runtime translation ========== //\n\n translate = async <T extends Translation>(\n lookup: TranslateLookup<T>\n ): Promise<void> => {\n return getReactI18nCache()\n .lookupTranslationWithFallback(\n lookup.locale,\n lookup.message,\n lookup.options\n )\n .then(() => {\n this.emitTranslateEvent(lookup);\n })\n .catch((error) => this.logRuntimeTranslationError(error));\n };\n\n translateDictionaryEntry = (lookup: DictionaryLookup): void => {\n getReactI18nCache()\n .lookupDictionaryWithFallback(lookup.locale, lookup.id)\n .then(() => {\n this.emitDictionaryEvent(lookup);\n })\n .catch((error) => this.logRuntimeTranslationError(error));\n };\n\n translateDictionaryObject = (lookup: DictionaryLookup): void => {\n getReactI18nCache()\n .lookupDictionaryObjWithFallback(lookup.locale, lookup.id)\n .then(() => {\n this.emitDictionaryEvent(lookup);\n })\n .catch((error) => this.logRuntimeTranslationError(error));\n };\n\n /**\n * Runtime translation runs fire-and-forget, so a rejected request (for\n * example a 401 from an invalid dev API key) is logged here instead of\n * escaping as an unhandled rejection that kills the dev server during SSR.\n * Identical failures log once.\n */\n private logRuntimeTranslationError(error: unknown): void {\n const details = formatDiagnosticErrorDetails(error);\n const dedupeKey = getRuntimeTranslationErrorDedupeKey(error);\n if (this.loggedRuntimeTranslationErrors.has(dedupeKey)) return;\n this.loggedRuntimeTranslationErrors.add(dedupeKey);\n if (\n this.loggedRuntimeTranslationErrors.size >\n MAX_LOGGED_RUNTIME_TRANSLATION_ERRORS\n ) {\n const oldest = this.loggedRuntimeTranslationErrors.values().next().value;\n if (oldest !== undefined) {\n this.loggedRuntimeTranslationErrors.delete(oldest);\n }\n }\n console.error(\n createDiagnosticMessage({\n source: '@generaltranslation/react-core',\n severity: 'Error',\n whatHappened: 'A runtime translation request failed.',\n wayOut: 'Rendering falls back to untranslated content.',\n details,\n })\n );\n }\n\n // ========== UseSyncExternalStore ========== //\n\n // ----- Subscriptions ----- //\n\n // Keep subscription methods as arrow fields so hooks can pass them by\n // reference without losing access to this store instance.\n subscribeToTranslate = <T extends Translation>(\n lookup: TranslateLookup<T>,\n listener: StoreListener\n ): Unsubscribe => {\n const lookupKey = getTranslateListenerKey(lookup);\n const wrappedListener: TranslateEventListener = (lookup) => {\n if (getTranslateListenerKey(lookup) === lookupKey) {\n listener();\n }\n };\n return subscribeToSet(this.translateListeners, wrappedListener);\n };\n\n subscribeToTranslationEvents = (\n listener: TranslateEventListener\n ): Unsubscribe => {\n return subscribeToSet(this.translateListeners, listener);\n };\n\n subscribeToDictionaryEntryEvents = (\n listener: DictionaryStoreListener\n ): Unsubscribe => {\n return subscribeToSet(this.dictionaryEntryListeners, listener);\n };\n\n subscribeToDictionaryObjectEvents = (\n listener: DictionaryStoreListener\n ): Unsubscribe => {\n return subscribeToSet(this.dictionaryObjectListeners, listener);\n };\n\n // ----- Snapshots ----- //\n\n getTranslateSnapshot = <T extends Translation>(\n lookup: TranslateLookup<T>,\n translationsSnapshot: Record<Locale, Record<Hash, Translation>> = {}\n ): TranslateSnapshot<T> => {\n return (\n lookupTranslation(translationsSnapshot, lookup) ??\n getReactI18nCache().lookupTranslation<T>(\n lookup.locale,\n lookup.message,\n lookup.options\n )\n );\n };\n\n getDictionaryEntrySnapshot = (\n lookup: DictionaryLookup,\n dictionariesSnapshot: Record<Locale, Dictionary> = {}\n ): DictionaryEntrySnapshot => {\n return (\n lookupDictionaryEntry(dictionariesSnapshot, lookup) ??\n getReactI18nCache().lookupDictionary(lookup.locale, lookup.id)\n );\n };\n\n getDictionaryObjectSnapshot = (\n lookup: DictionaryLookup,\n dictionariesSnapshot: Record<Locale, Dictionary> = {}\n ): DictionaryObjectSnapshot => {\n return (\n lookupDictionaryObject(dictionariesSnapshot, lookup) ??\n getReactI18nCache().lookupDictionaryObj(lookup.locale, lookup.id)\n );\n };\n\n // ----- Listener Utilities ----- //\n\n private emitTranslateEvent(event: TranslateLookup): void {\n this.translateListeners.forEach((listener) => listener(event));\n }\n\n private emitDictionaryEvent(event: DictionaryLookup): void {\n this.dictionaryEntryListeners.forEach((listener) => listener(event));\n this.dictionaryObjectListeners.forEach((listener) => {\n listener(event);\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@ declare class I18nStore {
|
|
|
17
17
|
private translateListeners;
|
|
18
18
|
private dictionaryEntryListeners;
|
|
19
19
|
private dictionaryObjectListeners;
|
|
20
|
+
private loggedRuntimeTranslationErrors;
|
|
20
21
|
/**
|
|
21
22
|
* I18nCache must be already initialized
|
|
22
23
|
*/
|
|
@@ -26,6 +27,13 @@ declare class I18nStore {
|
|
|
26
27
|
translate: <T extends Translation>(lookup: TranslateLookup<T>) => Promise<void>;
|
|
27
28
|
translateDictionaryEntry: (lookup: DictionaryLookup) => void;
|
|
28
29
|
translateDictionaryObject: (lookup: DictionaryLookup) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Runtime translation runs fire-and-forget, so a rejected request (for
|
|
32
|
+
* example a 401 from an invalid dev API key) is logged here instead of
|
|
33
|
+
* escaping as an unhandled rejection that kills the dev server during SSR.
|
|
34
|
+
* Identical failures log once.
|
|
35
|
+
*/
|
|
36
|
+
private logRuntimeTranslationError;
|
|
29
37
|
subscribeToTranslate: <T extends Translation>(lookup: TranslateLookup<T>, listener: StoreListener) => Unsubscribe;
|
|
30
38
|
subscribeToTranslationEvents: (listener: TranslateEventListener) => Unsubscribe;
|
|
31
39
|
subscribeToDictionaryEntryEvents: (listener: DictionaryStoreListener) => Unsubscribe;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"I18nStore.d.ts","names":[],"sources":["../../src/i18n-store/I18nStore.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"I18nStore.d.ts","names":[],"sources":["../../src/i18n-store/I18nStore.ts"],"mappings":";;;;;KAyBY,uBAAA,IAA2B,KAAA,EAAO,gBAAA;;AAA9C;;;;;AA2BA;;;cAAa,SAAA;EAAA,QAGH,kBAAA;EAAA,QACA,wBAAA;EAAA,QACA,yBAAA;EAAA,QACA,8BAAA;EAemC;;;;EAN3C,kBAAA,GACE,YAAA,EAAc,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,IAAA,EAAM,WAAA;EAK5C,kBAAA,GAAsB,YAAA,EAAc,MAAA,CAAO,MAAA,EAAQ,UAAA;EAMnD,SAAA,aAA6B,WAAA,EAC3B,MAAA,EAAQ,eAAA,CAAgB,CAAA,MACvB,OAAA;EAaH,wBAAA,GAA4B,MAAA,EAAQ,gBAAA;EASpC,yBAAA,GAA6B,MAAA,EAAQ,gBAAA;EA8CH;;;;;;EAAA,QA/B1B,0BAAA;EA+BR,oBAAA,aAAkC,WAAA,EAChC,MAAA,EAAQ,eAAA,CAAgB,CAAA,GACxB,QAAA,EAAU,aAAA,KACT,WAAA;EAUH,4BAAA,GACE,QAAA,EAAU,sBAAA,KACT,WAAA;EAIH,gCAAA,GACE,QAAA,EAAU,uBAAA,KACT,WAAA;EAIH,iCAAA,GACE,QAAA,EAAU,uBAAA,KACT,WAAA;EAMH,oBAAA,aAAkC,WAAA,EAChC,MAAA,EAAQ,eAAA,CAAgB,CAAA,GACxB,oBAAA,GAAsB,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,IAAA,EAAM,WAAA,OACjD,iBAAA,CAAkB,CAAA;EAWrB,0BAAA,GACE,MAAA,EAAQ,gBAAA,EACR,oBAAA,GAAsB,MAAA,CAAO,MAAA,EAAQ,UAAA,MACpC,uBAAA;EAOH,2BAAA,GACE,MAAA,EAAQ,gBAAA,EACR,oBAAA,GAAsB,MAAA,CAAO,MAAA,EAAQ,UAAA,MACpC,wBAAA;EAAA,QASK,kBAAA;EAAA,QAIA,mBAAA;AAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{getReactI18nCache as e}from"../i18n-cache/singleton-operations.mjs";import{subscribeToSet as t}from"./utils/subscriptions.mjs";import{lookupTranslation as n}from"./utils/translations.mjs";import{lookupDictionaryEntry as r,lookupDictionaryObject as i}from"./utils/dictionaries.mjs";import{getTranslateListenerKey as a}from"gt-i18n/internal";var
|
|
1
|
+
import{getReactI18nCache as e}from"../i18n-cache/singleton-operations.mjs";import{subscribeToSet as t}from"./utils/subscriptions.mjs";import{lookupTranslation as n}from"./utils/translations.mjs";import{lookupDictionaryEntry as r,lookupDictionaryObject as i}from"./utils/dictionaries.mjs";import{getTranslateListenerKey as a}from"gt-i18n/internal";import{createDiagnosticMessage as o,formatDiagnosticErrorDetails as s}from"generaltranslation/internal";function c(e){if(e instanceof Error)return`${e.name}|${e.message}`;if(typeof e==`object`&&e)try{return`object|${JSON.stringify(e)}`}catch{return`object|${String(e)}`}return`${typeof e}|${String(e)}`}var l=class{translateListeners=new Set;dictionaryEntryListeners=new Set;dictionaryObjectListeners=new Set;loggedRuntimeTranslationErrors=new Set;constructor(){}updateTranslations=t=>{e().updateTranslations(t)};updateDictionaries=t=>{e().updateDictionaries(t)};translate=async t=>e().lookupTranslationWithFallback(t.locale,t.message,t.options).then(()=>{this.emitTranslateEvent(t)}).catch(e=>this.logRuntimeTranslationError(e));translateDictionaryEntry=t=>{e().lookupDictionaryWithFallback(t.locale,t.id).then(()=>{this.emitDictionaryEvent(t)}).catch(e=>this.logRuntimeTranslationError(e))};translateDictionaryObject=t=>{e().lookupDictionaryObjWithFallback(t.locale,t.id).then(()=>{this.emitDictionaryEvent(t)}).catch(e=>this.logRuntimeTranslationError(e))};logRuntimeTranslationError(e){let t=s(e),n=c(e);if(!this.loggedRuntimeTranslationErrors.has(n)){if(this.loggedRuntimeTranslationErrors.add(n),this.loggedRuntimeTranslationErrors.size>100){let e=this.loggedRuntimeTranslationErrors.values().next().value;e!==void 0&&this.loggedRuntimeTranslationErrors.delete(e)}console.error(o({source:`@generaltranslation/react-core`,severity:`Error`,whatHappened:`A runtime translation request failed.`,wayOut:`Rendering falls back to untranslated content.`,details:t}))}}subscribeToTranslate=(e,n)=>{let r=a(e);return t(this.translateListeners,e=>{a(e)===r&&n()})};subscribeToTranslationEvents=e=>t(this.translateListeners,e);subscribeToDictionaryEntryEvents=e=>t(this.dictionaryEntryListeners,e);subscribeToDictionaryObjectEvents=e=>t(this.dictionaryObjectListeners,e);getTranslateSnapshot=(t,r={})=>n(r,t)??e().lookupTranslation(t.locale,t.message,t.options);getDictionaryEntrySnapshot=(t,n={})=>r(n,t)??e().lookupDictionary(t.locale,t.id);getDictionaryObjectSnapshot=(t,n={})=>i(n,t)??e().lookupDictionaryObj(t.locale,t.id);emitTranslateEvent(e){this.translateListeners.forEach(t=>t(e))}emitDictionaryEvent(e){this.dictionaryEntryListeners.forEach(t=>t(e)),this.dictionaryObjectListeners.forEach(t=>{t(e)})}};export{l as I18nStore};
|
|
2
2
|
//# sourceMappingURL=I18nStore.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"I18nStore.mjs","names":[],"sources":["../../src/i18n-store/I18nStore.ts"],"sourcesContent":["import { getTranslateListenerKey } from 'gt-i18n/internal';\nimport type {\n DictionaryEntrySnapshot,\n DictionaryLookup,\n DictionaryObjectSnapshot,\n StoreListener,\n TranslateEventListener,\n TranslateLookup,\n TranslateSnapshot,\n Unsubscribe,\n} from './storeTypes';\nimport type { Dictionary, Translation } from 'gt-i18n/types';\nimport { subscribeToSet } from './utils/subscriptions';\nimport { Hash, Locale } from 'gt-i18n/internal/types';\nimport { getReactI18nCache } from '../i18n-cache/singleton-operations';\nimport { lookupTranslation } from './utils/translations';\nimport {\n lookupDictionaryEntry,\n lookupDictionaryObject,\n} from './utils/dictionaries';\n\nexport type DictionaryStoreListener = (event: DictionaryLookup) => void;\n\n/**\n * I18nStore gives us the ability to perform client-side updates to translations.\n * Primarily useful for dev hot reload.\n *\n * This is the stateful primitive behind lookup subscriptions and runtime\n * translation requests. It intentionally does not know whether lookups are\n * being served from SPA singletons or SRA provider snapshots; that policy lives\n * in LookupAdapter, not in this store.\n */\nexport class I18nStore {\n // ----- Listener Sets ----- //\n\n private translateListeners = new Set<TranslateEventListener>();\n private dictionaryEntryListeners = new Set<DictionaryStoreListener>();\n private dictionaryObjectListeners = new Set<DictionaryStoreListener>();\n\n /**\n * I18nCache must be already initialized\n */\n constructor() {}\n\n // ========== Translation Updates ========== //\n\n updateTranslations = (\n translations: Record<Locale, Record<Hash, Translation>>\n ): void => {\n getReactI18nCache().updateTranslations(translations);\n };\n\n updateDictionaries = (dictionaries: Record<Locale, Dictionary>): void => {\n getReactI18nCache().updateDictionaries(dictionaries);\n };\n\n // ========== runtime translation ========== //\n\n translate = async <T extends Translation>(\n lookup: TranslateLookup<T>\n ): Promise<void> => {\n return getReactI18nCache()\n .lookupTranslationWithFallback(\n lookup.locale,\n lookup.message,\n lookup.options\n )\n .then((
|
|
1
|
+
{"version":3,"file":"I18nStore.mjs","names":[],"sources":["../../src/i18n-store/I18nStore.ts"],"sourcesContent":["import {\n createDiagnosticMessage,\n formatDiagnosticErrorDetails,\n} from 'generaltranslation/internal';\nimport { getTranslateListenerKey } from 'gt-i18n/internal';\nimport type {\n DictionaryEntrySnapshot,\n DictionaryLookup,\n DictionaryObjectSnapshot,\n StoreListener,\n TranslateEventListener,\n TranslateLookup,\n TranslateSnapshot,\n Unsubscribe,\n} from './storeTypes';\nimport type { Dictionary, Translation } from 'gt-i18n/types';\nimport { subscribeToSet } from './utils/subscriptions';\nimport { Hash, Locale } from 'gt-i18n/internal/types';\nimport { getReactI18nCache } from '../i18n-cache/singleton-operations';\nimport { lookupTranslation } from './utils/translations';\nimport {\n lookupDictionaryEntry,\n lookupDictionaryObject,\n} from './utils/dictionaries';\n\nexport type DictionaryStoreListener = (event: DictionaryLookup) => void;\n\nconst MAX_LOGGED_RUNTIME_TRANSLATION_ERRORS = 100;\n\nfunction getRuntimeTranslationErrorDedupeKey(error: unknown): string {\n if (error instanceof Error) {\n return `${error.name}|${error.message}`;\n }\n if (error !== null && typeof error === 'object') {\n try {\n return `object|${JSON.stringify(error)}`;\n } catch {\n return `object|${String(error)}`;\n }\n }\n return `${typeof error}|${String(error)}`;\n}\n\n/**\n * I18nStore gives us the ability to perform client-side updates to translations.\n * Primarily useful for dev hot reload.\n *\n * This is the stateful primitive behind lookup subscriptions and runtime\n * translation requests. It intentionally does not know whether lookups are\n * being served from SPA singletons or SRA provider snapshots; that policy lives\n * in LookupAdapter, not in this store.\n */\nexport class I18nStore {\n // ----- Listener Sets ----- //\n\n private translateListeners = new Set<TranslateEventListener>();\n private dictionaryEntryListeners = new Set<DictionaryStoreListener>();\n private dictionaryObjectListeners = new Set<DictionaryStoreListener>();\n private loggedRuntimeTranslationErrors = new Set<string>();\n\n /**\n * I18nCache must be already initialized\n */\n constructor() {}\n\n // ========== Translation Updates ========== //\n\n updateTranslations = (\n translations: Record<Locale, Record<Hash, Translation>>\n ): void => {\n getReactI18nCache().updateTranslations(translations);\n };\n\n updateDictionaries = (dictionaries: Record<Locale, Dictionary>): void => {\n getReactI18nCache().updateDictionaries(dictionaries);\n };\n\n // ========== runtime translation ========== //\n\n translate = async <T extends Translation>(\n lookup: TranslateLookup<T>\n ): Promise<void> => {\n return getReactI18nCache()\n .lookupTranslationWithFallback(\n lookup.locale,\n lookup.message,\n lookup.options\n )\n .then(() => {\n this.emitTranslateEvent(lookup);\n })\n .catch((error) => this.logRuntimeTranslationError(error));\n };\n\n translateDictionaryEntry = (lookup: DictionaryLookup): void => {\n getReactI18nCache()\n .lookupDictionaryWithFallback(lookup.locale, lookup.id)\n .then(() => {\n this.emitDictionaryEvent(lookup);\n })\n .catch((error) => this.logRuntimeTranslationError(error));\n };\n\n translateDictionaryObject = (lookup: DictionaryLookup): void => {\n getReactI18nCache()\n .lookupDictionaryObjWithFallback(lookup.locale, lookup.id)\n .then(() => {\n this.emitDictionaryEvent(lookup);\n })\n .catch((error) => this.logRuntimeTranslationError(error));\n };\n\n /**\n * Runtime translation runs fire-and-forget, so a rejected request (for\n * example a 401 from an invalid dev API key) is logged here instead of\n * escaping as an unhandled rejection that kills the dev server during SSR.\n * Identical failures log once.\n */\n private logRuntimeTranslationError(error: unknown): void {\n const details = formatDiagnosticErrorDetails(error);\n const dedupeKey = getRuntimeTranslationErrorDedupeKey(error);\n if (this.loggedRuntimeTranslationErrors.has(dedupeKey)) return;\n this.loggedRuntimeTranslationErrors.add(dedupeKey);\n if (\n this.loggedRuntimeTranslationErrors.size >\n MAX_LOGGED_RUNTIME_TRANSLATION_ERRORS\n ) {\n const oldest = this.loggedRuntimeTranslationErrors.values().next().value;\n if (oldest !== undefined) {\n this.loggedRuntimeTranslationErrors.delete(oldest);\n }\n }\n console.error(\n createDiagnosticMessage({\n source: '@generaltranslation/react-core',\n severity: 'Error',\n whatHappened: 'A runtime translation request failed.',\n wayOut: 'Rendering falls back to untranslated content.',\n details,\n })\n );\n }\n\n // ========== UseSyncExternalStore ========== //\n\n // ----- Subscriptions ----- //\n\n // Keep subscription methods as arrow fields so hooks can pass them by\n // reference without losing access to this store instance.\n subscribeToTranslate = <T extends Translation>(\n lookup: TranslateLookup<T>,\n listener: StoreListener\n ): Unsubscribe => {\n const lookupKey = getTranslateListenerKey(lookup);\n const wrappedListener: TranslateEventListener = (lookup) => {\n if (getTranslateListenerKey(lookup) === lookupKey) {\n listener();\n }\n };\n return subscribeToSet(this.translateListeners, wrappedListener);\n };\n\n subscribeToTranslationEvents = (\n listener: TranslateEventListener\n ): Unsubscribe => {\n return subscribeToSet(this.translateListeners, listener);\n };\n\n subscribeToDictionaryEntryEvents = (\n listener: DictionaryStoreListener\n ): Unsubscribe => {\n return subscribeToSet(this.dictionaryEntryListeners, listener);\n };\n\n subscribeToDictionaryObjectEvents = (\n listener: DictionaryStoreListener\n ): Unsubscribe => {\n return subscribeToSet(this.dictionaryObjectListeners, listener);\n };\n\n // ----- Snapshots ----- //\n\n getTranslateSnapshot = <T extends Translation>(\n lookup: TranslateLookup<T>,\n translationsSnapshot: Record<Locale, Record<Hash, Translation>> = {}\n ): TranslateSnapshot<T> => {\n return (\n lookupTranslation(translationsSnapshot, lookup) ??\n getReactI18nCache().lookupTranslation<T>(\n lookup.locale,\n lookup.message,\n lookup.options\n )\n );\n };\n\n getDictionaryEntrySnapshot = (\n lookup: DictionaryLookup,\n dictionariesSnapshot: Record<Locale, Dictionary> = {}\n ): DictionaryEntrySnapshot => {\n return (\n lookupDictionaryEntry(dictionariesSnapshot, lookup) ??\n getReactI18nCache().lookupDictionary(lookup.locale, lookup.id)\n );\n };\n\n getDictionaryObjectSnapshot = (\n lookup: DictionaryLookup,\n dictionariesSnapshot: Record<Locale, Dictionary> = {}\n ): DictionaryObjectSnapshot => {\n return (\n lookupDictionaryObject(dictionariesSnapshot, lookup) ??\n getReactI18nCache().lookupDictionaryObj(lookup.locale, lookup.id)\n );\n };\n\n // ----- Listener Utilities ----- //\n\n private emitTranslateEvent(event: TranslateLookup): void {\n this.translateListeners.forEach((listener) => listener(event));\n }\n\n private emitDictionaryEvent(event: DictionaryLookup): void {\n this.dictionaryEntryListeners.forEach((listener) => listener(event));\n this.dictionaryObjectListeners.forEach((listener) => {\n listener(event);\n });\n }\n}\n"],"mappings":"mcA6BA,SAAS,EAAoC,EAAwB,CACnE,GAAI,aAAiB,MACnB,MAAO,GAAG,EAAM,KAAK,GAAG,EAAM,UAEhC,GAAsB,OAAO,GAAU,UAAnC,EACF,GAAI,CACF,MAAO,UAAU,KAAK,UAAU,EAAM,QAChC,CACN,MAAO,UAAU,OAAO,EAAM,GAGlC,MAAO,GAAG,OAAO,EAAM,GAAG,OAAO,EAAM,GAYzC,IAAa,EAAb,KAAuB,CAGrB,mBAA6B,IAAI,IACjC,yBAAmC,IAAI,IACvC,0BAAoC,IAAI,IACxC,+BAAyC,IAAI,IAK7C,aAAc,EAId,mBACE,GACS,CACT,GAAmB,CAAC,mBAAmB,EAAa,EAGtD,mBAAsB,GAAmD,CACvE,GAAmB,CAAC,mBAAmB,EAAa,EAKtD,UAAY,KACV,IAEO,GAAmB,CACvB,8BACC,EAAO,OACP,EAAO,QACP,EAAO,QACR,CACA,SAAW,CACV,KAAK,mBAAmB,EAAO,EAC/B,CACD,MAAO,GAAU,KAAK,2BAA2B,EAAM,CAAC,CAG7D,yBAA4B,GAAmC,CAC7D,GAAmB,CAChB,6BAA6B,EAAO,OAAQ,EAAO,GAAG,CACtD,SAAW,CACV,KAAK,oBAAoB,EAAO,EAChC,CACD,MAAO,GAAU,KAAK,2BAA2B,EAAM,CAAC,EAG7D,0BAA6B,GAAmC,CAC9D,GAAmB,CAChB,gCAAgC,EAAO,OAAQ,EAAO,GAAG,CACzD,SAAW,CACV,KAAK,oBAAoB,EAAO,EAChC,CACD,MAAO,GAAU,KAAK,2BAA2B,EAAM,CAAC,EAS7D,2BAAmC,EAAsB,CACvD,IAAM,EAAU,EAA6B,EAAM,CAC7C,EAAY,EAAoC,EAAM,CACxD,SAAK,+BAA+B,IAAI,EAAU,CAEtD,IADA,KAAK,+BAA+B,IAAI,EAAU,CAEhD,KAAK,+BAA+B,KACpC,IACA,CACA,IAAM,EAAS,KAAK,+BAA+B,QAAQ,CAAC,MAAM,CAAC,MAC/D,IAAW,IAAA,IACb,KAAK,+BAA+B,OAAO,EAAO,CAGtD,QAAQ,MACN,EAAwB,CACtB,OAAQ,iCACR,SAAU,QACV,aAAc,wCACd,OAAQ,gDACR,UACD,CAAC,CACH,EASH,sBACE,EACA,IACgB,CAChB,IAAM,EAAY,EAAwB,EAAO,CAMjD,OAAO,EAAe,KAAK,mBALsB,GAAW,CACtD,EAAwB,EAAO,GAAK,GACtC,GAAU,EAGiD,EAGjE,6BACE,GAEO,EAAe,KAAK,mBAAoB,EAAS,CAG1D,iCACE,GAEO,EAAe,KAAK,yBAA0B,EAAS,CAGhE,kCACE,GAEO,EAAe,KAAK,0BAA2B,EAAS,CAKjE,sBACE,EACA,EAAkE,EAAE,GAGlE,EAAkB,EAAsB,EAAO,EAC/C,GAAmB,CAAC,kBAClB,EAAO,OACP,EAAO,QACP,EAAO,QACR,CAIL,4BACE,EACA,EAAmD,EAAE,GAGnD,EAAsB,EAAsB,EAAO,EACnD,GAAmB,CAAC,iBAAiB,EAAO,OAAQ,EAAO,GAAG,CAIlE,6BACE,EACA,EAAmD,EAAE,GAGnD,EAAuB,EAAsB,EAAO,EACpD,GAAmB,CAAC,oBAAoB,EAAO,OAAQ,EAAO,GAAG,CAMrE,mBAA2B,EAA8B,CACvD,KAAK,mBAAmB,QAAS,GAAa,EAAS,EAAM,CAAC,CAGhE,oBAA4B,EAA+B,CACzD,KAAK,yBAAyB,QAAS,GAAa,EAAS,EAAM,CAAC,CACpE,KAAK,0BAA0B,QAAS,GAAa,CACnD,EAAS,EAAM,EACf"}
|