@embedpdf/plugin-i18n 2.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.cjs +2 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +399 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/actions.d.ts +15 -0
  8. package/dist/lib/i18n-plugin.d.ts +28 -0
  9. package/dist/lib/index.d.ts +9 -0
  10. package/dist/lib/locales/en.d.ts +2 -0
  11. package/dist/lib/locales/es.d.ts +2 -0
  12. package/dist/lib/locales/index.d.ts +2 -0
  13. package/dist/lib/manifest.d.ts +4 -0
  14. package/dist/lib/reducer.d.ts +5 -0
  15. package/dist/lib/types.d.ts +104 -0
  16. package/dist/preact/adapter.d.ts +5 -0
  17. package/dist/preact/core.d.ts +1 -0
  18. package/dist/preact/index.cjs +2 -0
  19. package/dist/preact/index.cjs.map +1 -0
  20. package/dist/preact/index.d.ts +1 -0
  21. package/dist/preact/index.js +70 -0
  22. package/dist/preact/index.js.map +1 -0
  23. package/dist/react/adapter.d.ts +2 -0
  24. package/dist/react/core.d.ts +1 -0
  25. package/dist/react/index.cjs +2 -0
  26. package/dist/react/index.cjs.map +1 -0
  27. package/dist/react/index.d.ts +1 -0
  28. package/dist/react/index.js +69 -0
  29. package/dist/react/index.js.map +1 -0
  30. package/dist/shared/components/index.d.ts +1 -0
  31. package/dist/shared/components/translate.d.ts +35 -0
  32. package/dist/shared/hooks/index.d.ts +1 -0
  33. package/dist/shared/hooks/use-i18n.d.ts +43 -0
  34. package/dist/shared/index.d.ts +3 -0
  35. package/dist/shared-preact/components/index.d.ts +1 -0
  36. package/dist/shared-preact/components/translate.d.ts +35 -0
  37. package/dist/shared-preact/hooks/index.d.ts +1 -0
  38. package/dist/shared-preact/hooks/use-i18n.d.ts +43 -0
  39. package/dist/shared-preact/index.d.ts +3 -0
  40. package/dist/shared-react/components/index.d.ts +1 -0
  41. package/dist/shared-react/components/translate.d.ts +35 -0
  42. package/dist/shared-react/hooks/index.d.ts +1 -0
  43. package/dist/shared-react/hooks/use-i18n.d.ts +43 -0
  44. package/dist/shared-react/index.d.ts +3 -0
  45. package/dist/svelte/components/Translate.svelte.d.ts +9 -0
  46. package/dist/svelte/components/index.d.ts +1 -0
  47. package/dist/svelte/hooks/index.d.ts +1 -0
  48. package/dist/svelte/hooks/use-i18n.svelte.d.ts +41 -0
  49. package/dist/svelte/index.cjs +2 -0
  50. package/dist/svelte/index.cjs.map +1 -0
  51. package/dist/svelte/index.d.ts +3 -0
  52. package/dist/svelte/index.js +90 -0
  53. package/dist/svelte/index.js.map +1 -0
  54. package/dist/vue/components/index.d.ts +1 -0
  55. package/dist/vue/components/translate.vue.d.ts +9 -0
  56. package/dist/vue/hooks/index.d.ts +1 -0
  57. package/dist/vue/hooks/use-i18n.d.ts +30 -0
  58. package/dist/vue/index.cjs +2 -0
  59. package/dist/vue/index.cjs.map +1 -0
  60. package/dist/vue/index.d.ts +3 -0
  61. package/dist/vue/index.js +98 -0
  62. package/dist/vue/index.js.map +1 -0
  63. package/package.json +81 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 CloudPDF
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),a={code:"en",name:"English",translations:{commands:{zoom:{in:"Zoom In",out:"Zoom Out",fitWidth:"Fit to Width",fitPage:"Fit to Page",automatic:"Automatic",level:"Zoom Level ({level}%)",inArea:"Zoom In Area"},fullscreen:{enter:"Enter Full Screen",exit:"Exit Full Screen"},rotate:{clockwise:"Rotate Clockwise",counterclockwise:"Rotate Counter-Clockwise"},menu:"Menu",sidebar:"Sidebar",search:"Search",comment:"Comment",download:"Download",print:"Print",openFile:"Open PDF",save:"Save",settings:"Settings",view:"View",annotate:"Annotate",shapes:"Shapes",redact:"Redact",fillAndSign:"Fill and Sign",form:"Form",pan:"Pan",pointer:"Pointer",undo:"Undo",redo:"Redo",copy:"Copy",screenshot:"Screenshot",nextPage:"Next Page",previousPage:"Previous Page"}}},t={code:"es",name:"Español",translations:{commands:{zoom:{in:"Acercar",out:"Alejar",fitWidth:"Ajustar al ancho",fitPage:"Ajustar a la página",automatic:"Automático",level:"Nivel de zoom ({level}%)",inArea:"Acercar área"},fullscreen:{enter:"Pantalla completa",exit:"Salir de pantalla completa"},rotate:{clockwise:"Girar a la derecha",counterclockwise:"Girar a la izquierda"},menu:"Menú",sidebar:"Barra lateral",search:"Buscar",comment:"Comentario",download:"Descargar",print:"Imprimir",openFile:"Abrir PDF",save:"Guardar",settings:"Configuración",view:"Ver",annotate:"Anotar",shapes:"Formas",redact:"Redactar",fillAndSign:"Rellenar y firmar",form:"Formulario",pan:"Desplazar",pointer:"Puntero",undo:"Deshacer",redo:"Rehacer",copy:"Copiar",screenshot:"Captura de pantalla",nextPage:"Página siguiente",previousPage:"Página anterior"}}},r="i18n",s={id:r,name:"I18n Plugin",version:"1.0.0",provides:["i18n"],requires:[],optional:[],defaultConfig:{enabled:!0,defaultLocale:"en",locales:[a,t]}},o="I18N/SET_LOCALE",n="I18N/REGISTER_LOCALE",i=e=>({type:o,payload:e}),l=e=>({type:n,payload:e}),c=class extends e.BasePlugin{constructor(a,t,r){super(a,t),this.locales=new Map,this.paramResolvers=new Map,this.paramsCache=new Map,this.localeChange$=e.createEmitter(),this.paramsChanged$=e.createScopedEmitter((e,a)=>({documentId:e,...a}),{cache:!1}),this.config=r,r.locales.forEach(e=>{this.locales.set(e.code,e),this.dispatch(l(e.code))}),r.paramResolvers&&Object.entries(r.paramResolvers).forEach(([e,a])=>{this.paramResolvers.set(e,a)}),this.dispatch(i(r.defaultLocale)),this.registry.getStore().subscribe((e,a)=>{this.detectParamChanges(a)})}async initialize(){this.logger.info("I18nPlugin","Initialize","I18n plugin initialized")}async destroy(){this.localeChange$.clear(),this.paramsChanged$.clear(),this.paramResolvers.clear(),this.paramsCache.clear(),super.destroy()}onDocumentClosed(e){this.paramsCache.delete(e),this.paramsChanged$.clearScope(e),this.logger.debug("I18nPlugin","DocumentClosed",`Cleaned up params cache for document: ${e}`)}buildCapability(){return{t:(e,a)=>this.translate(e,a),forDocument:e=>this.createI18nScope(e),registerParamResolver:(e,a)=>this.registerParamResolver(e,a),unregisterParamResolver:e=>this.unregisterParamResolver(e),setLocale:e=>this.setLocale(e),getLocale:()=>this.state.currentLocale,getAvailableLocales:()=>[...this.state.availableLocales],getLocaleInfo:e=>this.locales.get(e)??null,registerLocale:e=>this.registerLocale(e),hasLocale:e=>this.locales.has(e),onLocaleChange:this.localeChange$.on,onParamsChanged:this.paramsChanged$.onGlobal}}createI18nScope(e){return{t:(a,t)=>this.translate(a,{documentId:e,...t}),onParamsChanged:this.paramsChanged$.forScope(e)}}translate(e,a){const t=this.locales.get(this.state.currentLocale),r=this.config.fallbackLocale?this.locales.get(this.config.fallbackLocale):null;let s=this.getNestedValue(null==t?void 0:t.translations,e);if(!s&&r&&(s=this.getNestedValue(r.translations,e)),!s){if(!(null==a?void 0:a.fallback))return this.logger.warn("I18nPlugin","MissingTranslation",`Translation not found for key: ${e}`),e;s=a.fallback}let o=null==a?void 0:a.params;return!o&&this.paramResolvers.has(e)&&(o=this.resolveParams(e,null==a?void 0:a.documentId)),this.interpolate(s,o)}resolveParams(e,a){const t=this.paramResolvers.get(e);if(!t)return;const r=this.registry.getStore().getState();try{return t({state:r,documentId:a})}catch(s){return void this.logger.error("I18nPlugin","ParamResolverError",`Error resolving params for key "${e}":`,s)}}getNestedValue(e,a){if(!e)return;const t=a.split(".");let r=e;for(const s of t){if(null==r)return;r=r[s]}return"string"==typeof r?r:void 0}interpolate(e,a){return a?e.replace(/\{(\w+)\}/g,(e,t)=>{const r=a[t];return void 0!==r?String(r):e}):e}detectParamChanges(e){Object.keys(e.core.documents).forEach(a=>{this.detectDocumentParamChanges(a,e)})}detectDocumentParamChanges(a,t){const r=this.paramsCache.get(a),s=[];this.paramResolvers.forEach((o,n)=>{try{const i=o({state:t,documentId:a}),l=null==r?void 0:r.get(n);e.arePropsEqual(l,i)||(s.push(n),this.paramsCache.has(a)||this.paramsCache.set(a,new Map),this.paramsCache.get(a).set(n,i))}catch(i){this.logger.error("I18nPlugin","ParamDetectionError",`Error detecting param changes for key "${n}":`,i)}}),s.length>0&&(this.paramsChanged$.emit(a,{changedKeys:s}),this.logger.debug("I18nPlugin","ParamsChanged",`Translation params changed for document ${a}:`,s))}registerParamResolver(e,a){this.paramResolvers.has(e)&&this.logger.warn("I18nPlugin","ResolverOverwrite",`Param resolver for "${e}" already exists and will be overwritten`),this.paramResolvers.set(e,a),this.paramsCache.forEach(a=>{a.delete(e)}),this.logger.debug("I18nPlugin","ResolverRegistered",`Param resolver registered for: ${e}`)}unregisterParamResolver(e){this.paramResolvers.delete(e)&&(this.paramsCache.forEach(a=>{a.delete(e)}),this.logger.debug("I18nPlugin","ResolverUnregistered",`Param resolver unregistered for: ${e}`))}setLocale(e){if(!this.locales.has(e))return void this.logger.warn("I18nPlugin","LocaleNotFound",`Locale '${e}' is not registered`);const a=this.state.currentLocale;a!==e&&(this.dispatch(i(e)),this.localeChange$.emit({previousLocale:a,currentLocale:e}),this.logger.info("I18nPlugin","LocaleChanged",`Locale changed to: ${e}`))}registerLocale(e){this.locales.has(e.code)?this.logger.warn("I18nPlugin","LocaleAlreadyRegistered",`Locale '${e.code}' is already registered`):(this.locales.set(e.code,e),this.dispatch(l(e.code)),this.logger.info("I18nPlugin","LocaleRegistered",`Locale registered: ${e.code}`))}};c.id="i18n";let h=c;const g={currentLocale:"en",availableLocales:[]},d={manifest:s,create:(e,a)=>new h(r,e,a),reducer:(e=g,a)=>{switch(a.type){case o:{const t=a.payload;return e.availableLocales.includes(t)?{...e,currentLocale:t}:(console.warn(`I18nPlugin: Locale '${t}' not available`),e)}case n:{const t=a.payload;return e.availableLocales.includes(t)?e:{...e,availableLocales:[...e.availableLocales,t]}}default:return e}},initialState:g};exports.I18N_PLUGIN_ID=r,exports.I18nPlugin=h,exports.I18nPluginPackage=d,exports.enUS=a,exports.esES=t,exports.manifest=s;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/lib/locales/en.ts","../src/lib/locales/es.ts","../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/i18n-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { Locale } from '../types';\n\nexport const enUS: Locale = {\n code: 'en',\n name: 'English',\n translations: {\n commands: {\n zoom: {\n in: 'Zoom In',\n out: 'Zoom Out',\n fitWidth: 'Fit to Width',\n fitPage: 'Fit to Page',\n automatic: 'Automatic',\n level: 'Zoom Level ({level}%)',\n inArea: 'Zoom In Area',\n },\n fullscreen: {\n enter: 'Enter Full Screen',\n exit: 'Exit Full Screen',\n },\n rotate: {\n clockwise: 'Rotate Clockwise',\n counterclockwise: 'Rotate Counter-Clockwise',\n },\n menu: 'Menu',\n sidebar: 'Sidebar',\n search: 'Search',\n comment: 'Comment',\n download: 'Download',\n print: 'Print',\n openFile: 'Open PDF',\n save: 'Save',\n settings: 'Settings',\n view: 'View',\n annotate: 'Annotate',\n shapes: 'Shapes',\n redact: 'Redact',\n fillAndSign: 'Fill and Sign',\n form: 'Form',\n pan: 'Pan',\n pointer: 'Pointer',\n undo: 'Undo',\n redo: 'Redo',\n copy: 'Copy',\n screenshot: 'Screenshot',\n nextPage: 'Next Page',\n previousPage: 'Previous Page',\n },\n },\n};\n","import { Locale } from '../types';\n\nexport const esES: Locale = {\n code: 'es',\n name: 'Español',\n translations: {\n commands: {\n zoom: {\n in: 'Acercar',\n out: 'Alejar',\n fitWidth: 'Ajustar al ancho',\n fitPage: 'Ajustar a la página',\n automatic: 'Automático',\n level: 'Nivel de zoom ({level}%)',\n inArea: 'Acercar área',\n },\n fullscreen: {\n enter: 'Pantalla completa',\n exit: 'Salir de pantalla completa',\n },\n rotate: {\n clockwise: 'Girar a la derecha',\n counterclockwise: 'Girar a la izquierda',\n },\n menu: 'Menú',\n sidebar: 'Barra lateral',\n search: 'Buscar',\n comment: 'Comentario',\n download: 'Descargar',\n print: 'Imprimir',\n openFile: 'Abrir PDF',\n save: 'Guardar',\n settings: 'Configuración',\n view: 'Ver',\n annotate: 'Anotar',\n shapes: 'Formas',\n redact: 'Redactar',\n fillAndSign: 'Rellenar y firmar',\n form: 'Formulario',\n pan: 'Desplazar',\n pointer: 'Puntero',\n undo: 'Deshacer',\n redo: 'Rehacer',\n copy: 'Copiar',\n screenshot: 'Captura de pantalla',\n nextPage: 'Página siguiente',\n previousPage: 'Página anterior',\n },\n },\n};\n","import { PluginManifest } from '@embedpdf/core';\nimport { I18nPluginConfig } from './types';\nimport { enUS, esES } from './locales';\n\nexport const I18N_PLUGIN_ID = 'i18n';\n\nexport const manifest: PluginManifest<I18nPluginConfig> = {\n id: I18N_PLUGIN_ID,\n name: 'I18n Plugin',\n version: '1.0.0',\n provides: ['i18n'],\n requires: [],\n optional: [],\n defaultConfig: {\n enabled: true,\n defaultLocale: 'en',\n locales: [enUS, esES],\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { Locale, LocaleCode } from './types';\n\nexport const SET_LOCALE = 'I18N/SET_LOCALE';\nexport const REGISTER_LOCALE = 'I18N/REGISTER_LOCALE';\n\nexport interface SetLocaleAction extends Action {\n type: typeof SET_LOCALE;\n payload: LocaleCode;\n}\n\nexport interface RegisterLocaleAction extends Action {\n type: typeof REGISTER_LOCALE;\n payload: LocaleCode;\n}\n\nexport type I18nAction = SetLocaleAction | RegisterLocaleAction;\n\nexport const setLocale = (locale: LocaleCode): SetLocaleAction => ({\n type: SET_LOCALE,\n payload: locale,\n});\n\nexport const registerLocale = (locale: LocaleCode): RegisterLocaleAction => ({\n type: REGISTER_LOCALE,\n payload: locale,\n});\n","import {\n BasePlugin,\n PluginRegistry,\n StoreState,\n arePropsEqual,\n createEmitter,\n createScopedEmitter,\n} from '@embedpdf/core';\nimport {\n I18nCapability,\n I18nPluginConfig,\n I18nState,\n I18nScope,\n Locale,\n LocaleCode,\n LocaleChangeEvent,\n TranslationKey,\n TranslateOptions,\n ParamResolver,\n TranslationParamsChangedData,\n TranslationParamsChangedEvent,\n} from './types';\nimport {\n I18nAction,\n setLocale as setLocaleAction,\n registerLocale as registerLocaleAction,\n} from './actions';\n\nexport class I18nPlugin extends BasePlugin<\n I18nPluginConfig,\n I18nCapability,\n I18nState,\n I18nAction\n> {\n static readonly id = 'i18n' as const;\n\n private config: I18nPluginConfig;\n private locales = new Map<LocaleCode, Locale>();\n private paramResolvers = new Map<TranslationKey, ParamResolver>();\n\n // Cache resolved params per document per key\n // Map<documentId, Map<translationKey, resolvedParams>>\n private paramsCache = new Map<string, Map<TranslationKey, Record<string, string | number>>>();\n\n // Events\n private readonly localeChange$ = createEmitter<LocaleChangeEvent>();\n private readonly paramsChanged$ = createScopedEmitter<\n TranslationParamsChangedData,\n TranslationParamsChangedEvent,\n string\n >((documentId, data) => ({ documentId, ...data }), { cache: false });\n\n constructor(id: string, registry: PluginRegistry, config: I18nPluginConfig) {\n super(id, registry);\n\n this.config = config;\n\n // Register all provided locales\n config.locales.forEach((locale) => {\n this.locales.set(locale.code, locale);\n this.dispatch(registerLocaleAction(locale.code));\n });\n\n // Register param resolvers\n if (config.paramResolvers) {\n Object.entries(config.paramResolvers).forEach(([key, resolver]) => {\n this.paramResolvers.set(key, resolver);\n });\n }\n\n // Set initial locale\n this.dispatch(setLocaleAction(config.defaultLocale));\n\n // Subscribe to global store changes for param change detection\n this.registry.getStore().subscribe((_action, newState) => {\n this.detectParamChanges(newState);\n });\n }\n\n async initialize(): Promise<void> {\n this.logger.info('I18nPlugin', 'Initialize', 'I18n plugin initialized');\n }\n\n async destroy(): Promise<void> {\n this.localeChange$.clear();\n this.paramsChanged$.clear();\n this.paramResolvers.clear();\n this.paramsCache.clear();\n super.destroy();\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Clean up cache for closed document\n this.paramsCache.delete(documentId);\n this.paramsChanged$.clearScope(documentId);\n\n this.logger.debug(\n 'I18nPlugin',\n 'DocumentClosed',\n `Cleaned up params cache for document: ${documentId}`,\n );\n }\n\n protected buildCapability(): I18nCapability {\n return {\n t: (key, options) => this.translate(key, options),\n forDocument: (documentId) => this.createI18nScope(documentId),\n registerParamResolver: (key, resolver) => this.registerParamResolver(key, resolver),\n unregisterParamResolver: (key) => this.unregisterParamResolver(key),\n setLocale: (locale) => this.setLocale(locale),\n getLocale: () => this.state.currentLocale,\n getAvailableLocales: () => [...this.state.availableLocales],\n getLocaleInfo: (code) => this.locales.get(code) ?? null,\n registerLocale: (locale) => this.registerLocale(locale),\n hasLocale: (code) => this.locales.has(code),\n onLocaleChange: this.localeChange$.on,\n onParamsChanged: this.paramsChanged$.onGlobal,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createI18nScope(documentId: string): I18nScope {\n return {\n t: (key, options) => this.translate(key, { documentId, ...options }),\n onParamsChanged: this.paramsChanged$.forScope(documentId),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Translation Logic\n // ─────────────────────────────────────────────────────────\n\n private translate(key: TranslationKey, options?: TranslateOptions): string {\n const locale = this.locales.get(this.state.currentLocale);\n const fallbackLocale = this.config.fallbackLocale\n ? this.locales.get(this.config.fallbackLocale)\n : null;\n\n // Try current locale\n let value = this.getNestedValue(locale?.translations, key);\n\n // Try fallback locale\n if (!value && fallbackLocale) {\n value = this.getNestedValue(fallbackLocale.translations, key);\n }\n\n // If still not found, use fallback or return key\n if (!value) {\n if (options?.fallback) {\n // Use provided fallback string\n value = options.fallback;\n } else {\n this.logger.warn(\n 'I18nPlugin',\n 'MissingTranslation',\n `Translation not found for key: ${key}`,\n );\n return key;\n }\n }\n\n // Resolve params: explicit params take precedence over registered resolvers\n let params = options?.params;\n\n // If no explicit params and we have a resolver, try to resolve\n if (!params && this.paramResolvers.has(key)) {\n params = this.resolveParams(key, options?.documentId);\n }\n\n // Interpolate parameters (works for both found translations and fallback)\n return this.interpolate(value, params);\n }\n\n private resolveParams(\n key: TranslationKey,\n documentId?: string,\n ): Record<string, string | number> | undefined {\n const resolver = this.paramResolvers.get(key);\n if (!resolver) return undefined;\n\n const state = this.registry.getStore().getState();\n\n try {\n // Pass documentId (which may be undefined) to resolver\n return resolver({ state, documentId });\n } catch (error) {\n this.logger.error(\n 'I18nPlugin',\n 'ParamResolverError',\n `Error resolving params for key \"${key}\":`,\n error,\n );\n return undefined;\n }\n }\n\n private getNestedValue(obj: any, path: string): string | undefined {\n if (!obj) return undefined;\n\n const parts = path.split('.');\n let current = obj;\n\n for (const part of parts) {\n if (current === undefined || current === null) return undefined;\n current = current[part];\n }\n\n return typeof current === 'string' ? current : undefined;\n }\n\n private interpolate(str: string, params?: Record<string, string | number>): string {\n if (!params) return str;\n\n // Replace {key} with params[key]\n return str.replace(/\\{(\\w+)\\}/g, (match, key) => {\n const value = params[key];\n return value !== undefined ? String(value) : match;\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // Smart Param Change Detection\n // ─────────────────────────────────────────────────────────\n\n private detectParamChanges(newState: StoreState<any>): void {\n // Get all documents from core state\n const documentIds = Object.keys(newState.core.documents);\n\n documentIds.forEach((documentId) => {\n this.detectDocumentParamChanges(documentId, newState);\n });\n }\n\n private detectDocumentParamChanges(documentId: string, newState: StoreState<any>): void {\n const previousCache = this.paramsCache.get(documentId);\n const changedKeys: TranslationKey[] = [];\n\n // Re-resolve all params that have resolvers\n this.paramResolvers.forEach((resolver, key) => {\n try {\n const newParams = resolver({ state: newState, documentId });\n const prevParams = previousCache?.get(key);\n\n // Compare params (deep equality for simplicity)\n if (!arePropsEqual(prevParams, newParams)) {\n changedKeys.push(key);\n\n // Update cache\n if (!this.paramsCache.has(documentId)) {\n this.paramsCache.set(documentId, new Map());\n }\n this.paramsCache.get(documentId)!.set(key, newParams);\n }\n } catch (error) {\n this.logger.error(\n 'I18nPlugin',\n 'ParamDetectionError',\n `Error detecting param changes for key \"${key}\":`,\n error,\n );\n }\n });\n\n // Emit event if any params changed\n if (changedKeys.length > 0) {\n this.paramsChanged$.emit(documentId, { changedKeys });\n\n this.logger.debug(\n 'I18nPlugin',\n 'ParamsChanged',\n `Translation params changed for document ${documentId}:`,\n changedKeys,\n );\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Param Resolver Management\n // ─────────────────────────────────────────────────────────\n\n private registerParamResolver(key: TranslationKey, resolver: ParamResolver): void {\n if (this.paramResolvers.has(key)) {\n this.logger.warn(\n 'I18nPlugin',\n 'ResolverOverwrite',\n `Param resolver for \"${key}\" already exists and will be overwritten`,\n );\n }\n\n this.paramResolvers.set(key, resolver);\n\n // Clear cache for this key in all documents\n this.paramsCache.forEach((docCache) => {\n docCache.delete(key);\n });\n\n this.logger.debug('I18nPlugin', 'ResolverRegistered', `Param resolver registered for: ${key}`);\n }\n\n private unregisterParamResolver(key: TranslationKey): void {\n if (this.paramResolvers.delete(key)) {\n // Clear cache for this key in all documents\n this.paramsCache.forEach((docCache) => {\n docCache.delete(key);\n });\n\n this.logger.debug(\n 'I18nPlugin',\n 'ResolverUnregistered',\n `Param resolver unregistered for: ${key}`,\n );\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Locale Management\n // ─────────────────────────────────────────────────────────\n\n private setLocale(locale: LocaleCode): void {\n if (!this.locales.has(locale)) {\n this.logger.warn('I18nPlugin', 'LocaleNotFound', `Locale '${locale}' is not registered`);\n return;\n }\n\n const previousLocale = this.state.currentLocale;\n if (previousLocale === locale) return;\n\n this.dispatch(setLocaleAction(locale));\n\n this.localeChange$.emit({\n previousLocale,\n currentLocale: locale,\n });\n\n this.logger.info('I18nPlugin', 'LocaleChanged', `Locale changed to: ${locale}`);\n }\n\n private registerLocale(locale: Locale): void {\n if (this.locales.has(locale.code)) {\n this.logger.warn(\n 'I18nPlugin',\n 'LocaleAlreadyRegistered',\n `Locale '${locale.code}' is already registered`,\n );\n return;\n }\n\n this.locales.set(locale.code, locale);\n this.dispatch(registerLocaleAction(locale.code));\n\n this.logger.info('I18nPlugin', 'LocaleRegistered', `Locale registered: ${locale.code}`);\n }\n}\n","import { Reducer } from '@embedpdf/core';\nimport { I18nState } from './types';\nimport { I18nAction, SET_LOCALE, REGISTER_LOCALE } from './actions';\n\nexport const initialState: I18nState = {\n currentLocale: 'en',\n availableLocales: [],\n};\n\nexport const i18nReducer: Reducer<I18nState, I18nAction> = (state = initialState, action) => {\n switch (action.type) {\n case SET_LOCALE: {\n const locale = action.payload;\n if (!state.availableLocales.includes(locale)) {\n console.warn(`I18nPlugin: Locale '${locale}' not available`);\n return state;\n }\n return {\n ...state,\n currentLocale: locale,\n };\n }\n\n case REGISTER_LOCALE: {\n const locale = action.payload;\n if (state.availableLocales.includes(locale)) {\n return state; // Already registered\n }\n return {\n ...state,\n availableLocales: [...state.availableLocales, locale],\n };\n }\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, I18N_PLUGIN_ID } from './manifest';\nimport { I18nPluginConfig, I18nState } from './types';\nimport { I18nPlugin } from './i18n-plugin';\nimport { I18nAction } from './actions';\nimport { i18nReducer, initialState } from './reducer';\n\nexport const I18nPluginPackage: PluginPackage<I18nPlugin, I18nPluginConfig, I18nState, I18nAction> =\n {\n manifest,\n create: (registry, config) => new I18nPlugin(I18N_PLUGIN_ID, registry, config),\n reducer: i18nReducer,\n initialState,\n };\n\nexport * from './i18n-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './locales';\n"],"names":["enUS","code","name","translations","commands","zoom","in","out","fitWidth","fitPage","automatic","level","inArea","fullscreen","enter","exit","rotate","clockwise","counterclockwise","menu","sidebar","search","comment","download","print","openFile","save","settings","view","annotate","shapes","redact","fillAndSign","form","pan","pointer","undo","redo","copy","screenshot","nextPage","previousPage","esES","I18N_PLUGIN_ID","manifest","id","version","provides","requires","optional","defaultConfig","enabled","defaultLocale","locales","SET_LOCALE","REGISTER_LOCALE","setLocale","locale","type","payload","registerLocale","_I18nPlugin","BasePlugin","constructor","registry","config","super","this","Map","paramResolvers","paramsCache","localeChange$","createEmitter","paramsChanged$","createScopedEmitter","documentId","data","cache","forEach","set","dispatch","registerLocaleAction","Object","entries","key","resolver","setLocaleAction","getStore","subscribe","_action","newState","detectParamChanges","initialize","logger","info","destroy","clear","onDocumentClosed","delete","clearScope","debug","buildCapability","t","options","translate","forDocument","createI18nScope","registerParamResolver","unregisterParamResolver","getLocale","state","currentLocale","getAvailableLocales","availableLocales","getLocaleInfo","get","hasLocale","has","onLocaleChange","on","onParamsChanged","onGlobal","forScope","fallbackLocale","value","getNestedValue","fallback","warn","params","resolveParams","interpolate","getState","error","obj","path","parts","split","current","part","str","replace","match","String","keys","core","documents","detectDocumentParamChanges","previousCache","changedKeys","newParams","prevParams","arePropsEqual","push","length","emit","docCache","previousLocale","I18nPlugin","initialState","I18nPluginPackage","create","reducer","action","includes","console"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export * from './lib';
package/dist/index.js ADDED
@@ -0,0 +1,399 @@
1
+ import { BasePlugin, createEmitter, createScopedEmitter, arePropsEqual } from "@embedpdf/core";
2
+ const enUS = {
3
+ code: "en",
4
+ name: "English",
5
+ translations: {
6
+ commands: {
7
+ zoom: {
8
+ in: "Zoom In",
9
+ out: "Zoom Out",
10
+ fitWidth: "Fit to Width",
11
+ fitPage: "Fit to Page",
12
+ automatic: "Automatic",
13
+ level: "Zoom Level ({level}%)",
14
+ inArea: "Zoom In Area"
15
+ },
16
+ fullscreen: {
17
+ enter: "Enter Full Screen",
18
+ exit: "Exit Full Screen"
19
+ },
20
+ rotate: {
21
+ clockwise: "Rotate Clockwise",
22
+ counterclockwise: "Rotate Counter-Clockwise"
23
+ },
24
+ menu: "Menu",
25
+ sidebar: "Sidebar",
26
+ search: "Search",
27
+ comment: "Comment",
28
+ download: "Download",
29
+ print: "Print",
30
+ openFile: "Open PDF",
31
+ save: "Save",
32
+ settings: "Settings",
33
+ view: "View",
34
+ annotate: "Annotate",
35
+ shapes: "Shapes",
36
+ redact: "Redact",
37
+ fillAndSign: "Fill and Sign",
38
+ form: "Form",
39
+ pan: "Pan",
40
+ pointer: "Pointer",
41
+ undo: "Undo",
42
+ redo: "Redo",
43
+ copy: "Copy",
44
+ screenshot: "Screenshot",
45
+ nextPage: "Next Page",
46
+ previousPage: "Previous Page"
47
+ }
48
+ }
49
+ };
50
+ const esES = {
51
+ code: "es",
52
+ name: "Español",
53
+ translations: {
54
+ commands: {
55
+ zoom: {
56
+ in: "Acercar",
57
+ out: "Alejar",
58
+ fitWidth: "Ajustar al ancho",
59
+ fitPage: "Ajustar a la página",
60
+ automatic: "Automático",
61
+ level: "Nivel de zoom ({level}%)",
62
+ inArea: "Acercar área"
63
+ },
64
+ fullscreen: {
65
+ enter: "Pantalla completa",
66
+ exit: "Salir de pantalla completa"
67
+ },
68
+ rotate: {
69
+ clockwise: "Girar a la derecha",
70
+ counterclockwise: "Girar a la izquierda"
71
+ },
72
+ menu: "Menú",
73
+ sidebar: "Barra lateral",
74
+ search: "Buscar",
75
+ comment: "Comentario",
76
+ download: "Descargar",
77
+ print: "Imprimir",
78
+ openFile: "Abrir PDF",
79
+ save: "Guardar",
80
+ settings: "Configuración",
81
+ view: "Ver",
82
+ annotate: "Anotar",
83
+ shapes: "Formas",
84
+ redact: "Redactar",
85
+ fillAndSign: "Rellenar y firmar",
86
+ form: "Formulario",
87
+ pan: "Desplazar",
88
+ pointer: "Puntero",
89
+ undo: "Deshacer",
90
+ redo: "Rehacer",
91
+ copy: "Copiar",
92
+ screenshot: "Captura de pantalla",
93
+ nextPage: "Página siguiente",
94
+ previousPage: "Página anterior"
95
+ }
96
+ }
97
+ };
98
+ const I18N_PLUGIN_ID = "i18n";
99
+ const manifest = {
100
+ id: I18N_PLUGIN_ID,
101
+ name: "I18n Plugin",
102
+ version: "1.0.0",
103
+ provides: ["i18n"],
104
+ requires: [],
105
+ optional: [],
106
+ defaultConfig: {
107
+ enabled: true,
108
+ defaultLocale: "en",
109
+ locales: [enUS, esES]
110
+ }
111
+ };
112
+ const SET_LOCALE = "I18N/SET_LOCALE";
113
+ const REGISTER_LOCALE = "I18N/REGISTER_LOCALE";
114
+ const setLocale = (locale) => ({
115
+ type: SET_LOCALE,
116
+ payload: locale
117
+ });
118
+ const registerLocale = (locale) => ({
119
+ type: REGISTER_LOCALE,
120
+ payload: locale
121
+ });
122
+ const _I18nPlugin = class _I18nPlugin extends BasePlugin {
123
+ constructor(id, registry, config) {
124
+ super(id, registry);
125
+ this.locales = /* @__PURE__ */ new Map();
126
+ this.paramResolvers = /* @__PURE__ */ new Map();
127
+ this.paramsCache = /* @__PURE__ */ new Map();
128
+ this.localeChange$ = createEmitter();
129
+ this.paramsChanged$ = createScopedEmitter((documentId, data) => ({ documentId, ...data }), { cache: false });
130
+ this.config = config;
131
+ config.locales.forEach((locale) => {
132
+ this.locales.set(locale.code, locale);
133
+ this.dispatch(registerLocale(locale.code));
134
+ });
135
+ if (config.paramResolvers) {
136
+ Object.entries(config.paramResolvers).forEach(([key, resolver]) => {
137
+ this.paramResolvers.set(key, resolver);
138
+ });
139
+ }
140
+ this.dispatch(setLocale(config.defaultLocale));
141
+ this.registry.getStore().subscribe((_action, newState) => {
142
+ this.detectParamChanges(newState);
143
+ });
144
+ }
145
+ async initialize() {
146
+ this.logger.info("I18nPlugin", "Initialize", "I18n plugin initialized");
147
+ }
148
+ async destroy() {
149
+ this.localeChange$.clear();
150
+ this.paramsChanged$.clear();
151
+ this.paramResolvers.clear();
152
+ this.paramsCache.clear();
153
+ super.destroy();
154
+ }
155
+ onDocumentClosed(documentId) {
156
+ this.paramsCache.delete(documentId);
157
+ this.paramsChanged$.clearScope(documentId);
158
+ this.logger.debug(
159
+ "I18nPlugin",
160
+ "DocumentClosed",
161
+ `Cleaned up params cache for document: ${documentId}`
162
+ );
163
+ }
164
+ buildCapability() {
165
+ return {
166
+ t: (key, options) => this.translate(key, options),
167
+ forDocument: (documentId) => this.createI18nScope(documentId),
168
+ registerParamResolver: (key, resolver) => this.registerParamResolver(key, resolver),
169
+ unregisterParamResolver: (key) => this.unregisterParamResolver(key),
170
+ setLocale: (locale) => this.setLocale(locale),
171
+ getLocale: () => this.state.currentLocale,
172
+ getAvailableLocales: () => [...this.state.availableLocales],
173
+ getLocaleInfo: (code) => this.locales.get(code) ?? null,
174
+ registerLocale: (locale) => this.registerLocale(locale),
175
+ hasLocale: (code) => this.locales.has(code),
176
+ onLocaleChange: this.localeChange$.on,
177
+ onParamsChanged: this.paramsChanged$.onGlobal
178
+ };
179
+ }
180
+ // ─────────────────────────────────────────────────────────
181
+ // Document Scoping
182
+ // ─────────────────────────────────────────────────────────
183
+ createI18nScope(documentId) {
184
+ return {
185
+ t: (key, options) => this.translate(key, { documentId, ...options }),
186
+ onParamsChanged: this.paramsChanged$.forScope(documentId)
187
+ };
188
+ }
189
+ // ─────────────────────────────────────────────────────────
190
+ // Translation Logic
191
+ // ─────────────────────────────────────────────────────────
192
+ translate(key, options) {
193
+ const locale = this.locales.get(this.state.currentLocale);
194
+ const fallbackLocale = this.config.fallbackLocale ? this.locales.get(this.config.fallbackLocale) : null;
195
+ let value = this.getNestedValue(locale == null ? void 0 : locale.translations, key);
196
+ if (!value && fallbackLocale) {
197
+ value = this.getNestedValue(fallbackLocale.translations, key);
198
+ }
199
+ if (!value) {
200
+ if (options == null ? void 0 : options.fallback) {
201
+ value = options.fallback;
202
+ } else {
203
+ this.logger.warn(
204
+ "I18nPlugin",
205
+ "MissingTranslation",
206
+ `Translation not found for key: ${key}`
207
+ );
208
+ return key;
209
+ }
210
+ }
211
+ let params = options == null ? void 0 : options.params;
212
+ if (!params && this.paramResolvers.has(key)) {
213
+ params = this.resolveParams(key, options == null ? void 0 : options.documentId);
214
+ }
215
+ return this.interpolate(value, params);
216
+ }
217
+ resolveParams(key, documentId) {
218
+ const resolver = this.paramResolvers.get(key);
219
+ if (!resolver) return void 0;
220
+ const state = this.registry.getStore().getState();
221
+ try {
222
+ return resolver({ state, documentId });
223
+ } catch (error) {
224
+ this.logger.error(
225
+ "I18nPlugin",
226
+ "ParamResolverError",
227
+ `Error resolving params for key "${key}":`,
228
+ error
229
+ );
230
+ return void 0;
231
+ }
232
+ }
233
+ getNestedValue(obj, path) {
234
+ if (!obj) return void 0;
235
+ const parts = path.split(".");
236
+ let current = obj;
237
+ for (const part of parts) {
238
+ if (current === void 0 || current === null) return void 0;
239
+ current = current[part];
240
+ }
241
+ return typeof current === "string" ? current : void 0;
242
+ }
243
+ interpolate(str, params) {
244
+ if (!params) return str;
245
+ return str.replace(/\{(\w+)\}/g, (match, key) => {
246
+ const value = params[key];
247
+ return value !== void 0 ? String(value) : match;
248
+ });
249
+ }
250
+ // ─────────────────────────────────────────────────────────
251
+ // Smart Param Change Detection
252
+ // ─────────────────────────────────────────────────────────
253
+ detectParamChanges(newState) {
254
+ const documentIds = Object.keys(newState.core.documents);
255
+ documentIds.forEach((documentId) => {
256
+ this.detectDocumentParamChanges(documentId, newState);
257
+ });
258
+ }
259
+ detectDocumentParamChanges(documentId, newState) {
260
+ const previousCache = this.paramsCache.get(documentId);
261
+ const changedKeys = [];
262
+ this.paramResolvers.forEach((resolver, key) => {
263
+ try {
264
+ const newParams = resolver({ state: newState, documentId });
265
+ const prevParams = previousCache == null ? void 0 : previousCache.get(key);
266
+ if (!arePropsEqual(prevParams, newParams)) {
267
+ changedKeys.push(key);
268
+ if (!this.paramsCache.has(documentId)) {
269
+ this.paramsCache.set(documentId, /* @__PURE__ */ new Map());
270
+ }
271
+ this.paramsCache.get(documentId).set(key, newParams);
272
+ }
273
+ } catch (error) {
274
+ this.logger.error(
275
+ "I18nPlugin",
276
+ "ParamDetectionError",
277
+ `Error detecting param changes for key "${key}":`,
278
+ error
279
+ );
280
+ }
281
+ });
282
+ if (changedKeys.length > 0) {
283
+ this.paramsChanged$.emit(documentId, { changedKeys });
284
+ this.logger.debug(
285
+ "I18nPlugin",
286
+ "ParamsChanged",
287
+ `Translation params changed for document ${documentId}:`,
288
+ changedKeys
289
+ );
290
+ }
291
+ }
292
+ // ─────────────────────────────────────────────────────────
293
+ // Param Resolver Management
294
+ // ─────────────────────────────────────────────────────────
295
+ registerParamResolver(key, resolver) {
296
+ if (this.paramResolvers.has(key)) {
297
+ this.logger.warn(
298
+ "I18nPlugin",
299
+ "ResolverOverwrite",
300
+ `Param resolver for "${key}" already exists and will be overwritten`
301
+ );
302
+ }
303
+ this.paramResolvers.set(key, resolver);
304
+ this.paramsCache.forEach((docCache) => {
305
+ docCache.delete(key);
306
+ });
307
+ this.logger.debug("I18nPlugin", "ResolverRegistered", `Param resolver registered for: ${key}`);
308
+ }
309
+ unregisterParamResolver(key) {
310
+ if (this.paramResolvers.delete(key)) {
311
+ this.paramsCache.forEach((docCache) => {
312
+ docCache.delete(key);
313
+ });
314
+ this.logger.debug(
315
+ "I18nPlugin",
316
+ "ResolverUnregistered",
317
+ `Param resolver unregistered for: ${key}`
318
+ );
319
+ }
320
+ }
321
+ // ─────────────────────────────────────────────────────────
322
+ // Locale Management
323
+ // ─────────────────────────────────────────────────────────
324
+ setLocale(locale) {
325
+ if (!this.locales.has(locale)) {
326
+ this.logger.warn("I18nPlugin", "LocaleNotFound", `Locale '${locale}' is not registered`);
327
+ return;
328
+ }
329
+ const previousLocale = this.state.currentLocale;
330
+ if (previousLocale === locale) return;
331
+ this.dispatch(setLocale(locale));
332
+ this.localeChange$.emit({
333
+ previousLocale,
334
+ currentLocale: locale
335
+ });
336
+ this.logger.info("I18nPlugin", "LocaleChanged", `Locale changed to: ${locale}`);
337
+ }
338
+ registerLocale(locale) {
339
+ if (this.locales.has(locale.code)) {
340
+ this.logger.warn(
341
+ "I18nPlugin",
342
+ "LocaleAlreadyRegistered",
343
+ `Locale '${locale.code}' is already registered`
344
+ );
345
+ return;
346
+ }
347
+ this.locales.set(locale.code, locale);
348
+ this.dispatch(registerLocale(locale.code));
349
+ this.logger.info("I18nPlugin", "LocaleRegistered", `Locale registered: ${locale.code}`);
350
+ }
351
+ };
352
+ _I18nPlugin.id = "i18n";
353
+ let I18nPlugin = _I18nPlugin;
354
+ const initialState = {
355
+ currentLocale: "en",
356
+ availableLocales: []
357
+ };
358
+ const i18nReducer = (state = initialState, action) => {
359
+ switch (action.type) {
360
+ case SET_LOCALE: {
361
+ const locale = action.payload;
362
+ if (!state.availableLocales.includes(locale)) {
363
+ console.warn(`I18nPlugin: Locale '${locale}' not available`);
364
+ return state;
365
+ }
366
+ return {
367
+ ...state,
368
+ currentLocale: locale
369
+ };
370
+ }
371
+ case REGISTER_LOCALE: {
372
+ const locale = action.payload;
373
+ if (state.availableLocales.includes(locale)) {
374
+ return state;
375
+ }
376
+ return {
377
+ ...state,
378
+ availableLocales: [...state.availableLocales, locale]
379
+ };
380
+ }
381
+ default:
382
+ return state;
383
+ }
384
+ };
385
+ const I18nPluginPackage = {
386
+ manifest,
387
+ create: (registry, config) => new I18nPlugin(I18N_PLUGIN_ID, registry, config),
388
+ reducer: i18nReducer,
389
+ initialState
390
+ };
391
+ export {
392
+ I18N_PLUGIN_ID,
393
+ I18nPlugin,
394
+ I18nPluginPackage,
395
+ enUS,
396
+ esES,
397
+ manifest
398
+ };
399
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/lib/locales/en.ts","../src/lib/locales/es.ts","../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/i18n-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { Locale } from '../types';\n\nexport const enUS: Locale = {\n code: 'en',\n name: 'English',\n translations: {\n commands: {\n zoom: {\n in: 'Zoom In',\n out: 'Zoom Out',\n fitWidth: 'Fit to Width',\n fitPage: 'Fit to Page',\n automatic: 'Automatic',\n level: 'Zoom Level ({level}%)',\n inArea: 'Zoom In Area',\n },\n fullscreen: {\n enter: 'Enter Full Screen',\n exit: 'Exit Full Screen',\n },\n rotate: {\n clockwise: 'Rotate Clockwise',\n counterclockwise: 'Rotate Counter-Clockwise',\n },\n menu: 'Menu',\n sidebar: 'Sidebar',\n search: 'Search',\n comment: 'Comment',\n download: 'Download',\n print: 'Print',\n openFile: 'Open PDF',\n save: 'Save',\n settings: 'Settings',\n view: 'View',\n annotate: 'Annotate',\n shapes: 'Shapes',\n redact: 'Redact',\n fillAndSign: 'Fill and Sign',\n form: 'Form',\n pan: 'Pan',\n pointer: 'Pointer',\n undo: 'Undo',\n redo: 'Redo',\n copy: 'Copy',\n screenshot: 'Screenshot',\n nextPage: 'Next Page',\n previousPage: 'Previous Page',\n },\n },\n};\n","import { Locale } from '../types';\n\nexport const esES: Locale = {\n code: 'es',\n name: 'Español',\n translations: {\n commands: {\n zoom: {\n in: 'Acercar',\n out: 'Alejar',\n fitWidth: 'Ajustar al ancho',\n fitPage: 'Ajustar a la página',\n automatic: 'Automático',\n level: 'Nivel de zoom ({level}%)',\n inArea: 'Acercar área',\n },\n fullscreen: {\n enter: 'Pantalla completa',\n exit: 'Salir de pantalla completa',\n },\n rotate: {\n clockwise: 'Girar a la derecha',\n counterclockwise: 'Girar a la izquierda',\n },\n menu: 'Menú',\n sidebar: 'Barra lateral',\n search: 'Buscar',\n comment: 'Comentario',\n download: 'Descargar',\n print: 'Imprimir',\n openFile: 'Abrir PDF',\n save: 'Guardar',\n settings: 'Configuración',\n view: 'Ver',\n annotate: 'Anotar',\n shapes: 'Formas',\n redact: 'Redactar',\n fillAndSign: 'Rellenar y firmar',\n form: 'Formulario',\n pan: 'Desplazar',\n pointer: 'Puntero',\n undo: 'Deshacer',\n redo: 'Rehacer',\n copy: 'Copiar',\n screenshot: 'Captura de pantalla',\n nextPage: 'Página siguiente',\n previousPage: 'Página anterior',\n },\n },\n};\n","import { PluginManifest } from '@embedpdf/core';\nimport { I18nPluginConfig } from './types';\nimport { enUS, esES } from './locales';\n\nexport const I18N_PLUGIN_ID = 'i18n';\n\nexport const manifest: PluginManifest<I18nPluginConfig> = {\n id: I18N_PLUGIN_ID,\n name: 'I18n Plugin',\n version: '1.0.0',\n provides: ['i18n'],\n requires: [],\n optional: [],\n defaultConfig: {\n enabled: true,\n defaultLocale: 'en',\n locales: [enUS, esES],\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { Locale, LocaleCode } from './types';\n\nexport const SET_LOCALE = 'I18N/SET_LOCALE';\nexport const REGISTER_LOCALE = 'I18N/REGISTER_LOCALE';\n\nexport interface SetLocaleAction extends Action {\n type: typeof SET_LOCALE;\n payload: LocaleCode;\n}\n\nexport interface RegisterLocaleAction extends Action {\n type: typeof REGISTER_LOCALE;\n payload: LocaleCode;\n}\n\nexport type I18nAction = SetLocaleAction | RegisterLocaleAction;\n\nexport const setLocale = (locale: LocaleCode): SetLocaleAction => ({\n type: SET_LOCALE,\n payload: locale,\n});\n\nexport const registerLocale = (locale: LocaleCode): RegisterLocaleAction => ({\n type: REGISTER_LOCALE,\n payload: locale,\n});\n","import {\n BasePlugin,\n PluginRegistry,\n StoreState,\n arePropsEqual,\n createEmitter,\n createScopedEmitter,\n} from '@embedpdf/core';\nimport {\n I18nCapability,\n I18nPluginConfig,\n I18nState,\n I18nScope,\n Locale,\n LocaleCode,\n LocaleChangeEvent,\n TranslationKey,\n TranslateOptions,\n ParamResolver,\n TranslationParamsChangedData,\n TranslationParamsChangedEvent,\n} from './types';\nimport {\n I18nAction,\n setLocale as setLocaleAction,\n registerLocale as registerLocaleAction,\n} from './actions';\n\nexport class I18nPlugin extends BasePlugin<\n I18nPluginConfig,\n I18nCapability,\n I18nState,\n I18nAction\n> {\n static readonly id = 'i18n' as const;\n\n private config: I18nPluginConfig;\n private locales = new Map<LocaleCode, Locale>();\n private paramResolvers = new Map<TranslationKey, ParamResolver>();\n\n // Cache resolved params per document per key\n // Map<documentId, Map<translationKey, resolvedParams>>\n private paramsCache = new Map<string, Map<TranslationKey, Record<string, string | number>>>();\n\n // Events\n private readonly localeChange$ = createEmitter<LocaleChangeEvent>();\n private readonly paramsChanged$ = createScopedEmitter<\n TranslationParamsChangedData,\n TranslationParamsChangedEvent,\n string\n >((documentId, data) => ({ documentId, ...data }), { cache: false });\n\n constructor(id: string, registry: PluginRegistry, config: I18nPluginConfig) {\n super(id, registry);\n\n this.config = config;\n\n // Register all provided locales\n config.locales.forEach((locale) => {\n this.locales.set(locale.code, locale);\n this.dispatch(registerLocaleAction(locale.code));\n });\n\n // Register param resolvers\n if (config.paramResolvers) {\n Object.entries(config.paramResolvers).forEach(([key, resolver]) => {\n this.paramResolvers.set(key, resolver);\n });\n }\n\n // Set initial locale\n this.dispatch(setLocaleAction(config.defaultLocale));\n\n // Subscribe to global store changes for param change detection\n this.registry.getStore().subscribe((_action, newState) => {\n this.detectParamChanges(newState);\n });\n }\n\n async initialize(): Promise<void> {\n this.logger.info('I18nPlugin', 'Initialize', 'I18n plugin initialized');\n }\n\n async destroy(): Promise<void> {\n this.localeChange$.clear();\n this.paramsChanged$.clear();\n this.paramResolvers.clear();\n this.paramsCache.clear();\n super.destroy();\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Clean up cache for closed document\n this.paramsCache.delete(documentId);\n this.paramsChanged$.clearScope(documentId);\n\n this.logger.debug(\n 'I18nPlugin',\n 'DocumentClosed',\n `Cleaned up params cache for document: ${documentId}`,\n );\n }\n\n protected buildCapability(): I18nCapability {\n return {\n t: (key, options) => this.translate(key, options),\n forDocument: (documentId) => this.createI18nScope(documentId),\n registerParamResolver: (key, resolver) => this.registerParamResolver(key, resolver),\n unregisterParamResolver: (key) => this.unregisterParamResolver(key),\n setLocale: (locale) => this.setLocale(locale),\n getLocale: () => this.state.currentLocale,\n getAvailableLocales: () => [...this.state.availableLocales],\n getLocaleInfo: (code) => this.locales.get(code) ?? null,\n registerLocale: (locale) => this.registerLocale(locale),\n hasLocale: (code) => this.locales.has(code),\n onLocaleChange: this.localeChange$.on,\n onParamsChanged: this.paramsChanged$.onGlobal,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createI18nScope(documentId: string): I18nScope {\n return {\n t: (key, options) => this.translate(key, { documentId, ...options }),\n onParamsChanged: this.paramsChanged$.forScope(documentId),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Translation Logic\n // ─────────────────────────────────────────────────────────\n\n private translate(key: TranslationKey, options?: TranslateOptions): string {\n const locale = this.locales.get(this.state.currentLocale);\n const fallbackLocale = this.config.fallbackLocale\n ? this.locales.get(this.config.fallbackLocale)\n : null;\n\n // Try current locale\n let value = this.getNestedValue(locale?.translations, key);\n\n // Try fallback locale\n if (!value && fallbackLocale) {\n value = this.getNestedValue(fallbackLocale.translations, key);\n }\n\n // If still not found, use fallback or return key\n if (!value) {\n if (options?.fallback) {\n // Use provided fallback string\n value = options.fallback;\n } else {\n this.logger.warn(\n 'I18nPlugin',\n 'MissingTranslation',\n `Translation not found for key: ${key}`,\n );\n return key;\n }\n }\n\n // Resolve params: explicit params take precedence over registered resolvers\n let params = options?.params;\n\n // If no explicit params and we have a resolver, try to resolve\n if (!params && this.paramResolvers.has(key)) {\n params = this.resolveParams(key, options?.documentId);\n }\n\n // Interpolate parameters (works for both found translations and fallback)\n return this.interpolate(value, params);\n }\n\n private resolveParams(\n key: TranslationKey,\n documentId?: string,\n ): Record<string, string | number> | undefined {\n const resolver = this.paramResolvers.get(key);\n if (!resolver) return undefined;\n\n const state = this.registry.getStore().getState();\n\n try {\n // Pass documentId (which may be undefined) to resolver\n return resolver({ state, documentId });\n } catch (error) {\n this.logger.error(\n 'I18nPlugin',\n 'ParamResolverError',\n `Error resolving params for key \"${key}\":`,\n error,\n );\n return undefined;\n }\n }\n\n private getNestedValue(obj: any, path: string): string | undefined {\n if (!obj) return undefined;\n\n const parts = path.split('.');\n let current = obj;\n\n for (const part of parts) {\n if (current === undefined || current === null) return undefined;\n current = current[part];\n }\n\n return typeof current === 'string' ? current : undefined;\n }\n\n private interpolate(str: string, params?: Record<string, string | number>): string {\n if (!params) return str;\n\n // Replace {key} with params[key]\n return str.replace(/\\{(\\w+)\\}/g, (match, key) => {\n const value = params[key];\n return value !== undefined ? String(value) : match;\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // Smart Param Change Detection\n // ─────────────────────────────────────────────────────────\n\n private detectParamChanges(newState: StoreState<any>): void {\n // Get all documents from core state\n const documentIds = Object.keys(newState.core.documents);\n\n documentIds.forEach((documentId) => {\n this.detectDocumentParamChanges(documentId, newState);\n });\n }\n\n private detectDocumentParamChanges(documentId: string, newState: StoreState<any>): void {\n const previousCache = this.paramsCache.get(documentId);\n const changedKeys: TranslationKey[] = [];\n\n // Re-resolve all params that have resolvers\n this.paramResolvers.forEach((resolver, key) => {\n try {\n const newParams = resolver({ state: newState, documentId });\n const prevParams = previousCache?.get(key);\n\n // Compare params (deep equality for simplicity)\n if (!arePropsEqual(prevParams, newParams)) {\n changedKeys.push(key);\n\n // Update cache\n if (!this.paramsCache.has(documentId)) {\n this.paramsCache.set(documentId, new Map());\n }\n this.paramsCache.get(documentId)!.set(key, newParams);\n }\n } catch (error) {\n this.logger.error(\n 'I18nPlugin',\n 'ParamDetectionError',\n `Error detecting param changes for key \"${key}\":`,\n error,\n );\n }\n });\n\n // Emit event if any params changed\n if (changedKeys.length > 0) {\n this.paramsChanged$.emit(documentId, { changedKeys });\n\n this.logger.debug(\n 'I18nPlugin',\n 'ParamsChanged',\n `Translation params changed for document ${documentId}:`,\n changedKeys,\n );\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Param Resolver Management\n // ─────────────────────────────────────────────────────────\n\n private registerParamResolver(key: TranslationKey, resolver: ParamResolver): void {\n if (this.paramResolvers.has(key)) {\n this.logger.warn(\n 'I18nPlugin',\n 'ResolverOverwrite',\n `Param resolver for \"${key}\" already exists and will be overwritten`,\n );\n }\n\n this.paramResolvers.set(key, resolver);\n\n // Clear cache for this key in all documents\n this.paramsCache.forEach((docCache) => {\n docCache.delete(key);\n });\n\n this.logger.debug('I18nPlugin', 'ResolverRegistered', `Param resolver registered for: ${key}`);\n }\n\n private unregisterParamResolver(key: TranslationKey): void {\n if (this.paramResolvers.delete(key)) {\n // Clear cache for this key in all documents\n this.paramsCache.forEach((docCache) => {\n docCache.delete(key);\n });\n\n this.logger.debug(\n 'I18nPlugin',\n 'ResolverUnregistered',\n `Param resolver unregistered for: ${key}`,\n );\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Locale Management\n // ─────────────────────────────────────────────────────────\n\n private setLocale(locale: LocaleCode): void {\n if (!this.locales.has(locale)) {\n this.logger.warn('I18nPlugin', 'LocaleNotFound', `Locale '${locale}' is not registered`);\n return;\n }\n\n const previousLocale = this.state.currentLocale;\n if (previousLocale === locale) return;\n\n this.dispatch(setLocaleAction(locale));\n\n this.localeChange$.emit({\n previousLocale,\n currentLocale: locale,\n });\n\n this.logger.info('I18nPlugin', 'LocaleChanged', `Locale changed to: ${locale}`);\n }\n\n private registerLocale(locale: Locale): void {\n if (this.locales.has(locale.code)) {\n this.logger.warn(\n 'I18nPlugin',\n 'LocaleAlreadyRegistered',\n `Locale '${locale.code}' is already registered`,\n );\n return;\n }\n\n this.locales.set(locale.code, locale);\n this.dispatch(registerLocaleAction(locale.code));\n\n this.logger.info('I18nPlugin', 'LocaleRegistered', `Locale registered: ${locale.code}`);\n }\n}\n","import { Reducer } from '@embedpdf/core';\nimport { I18nState } from './types';\nimport { I18nAction, SET_LOCALE, REGISTER_LOCALE } from './actions';\n\nexport const initialState: I18nState = {\n currentLocale: 'en',\n availableLocales: [],\n};\n\nexport const i18nReducer: Reducer<I18nState, I18nAction> = (state = initialState, action) => {\n switch (action.type) {\n case SET_LOCALE: {\n const locale = action.payload;\n if (!state.availableLocales.includes(locale)) {\n console.warn(`I18nPlugin: Locale '${locale}' not available`);\n return state;\n }\n return {\n ...state,\n currentLocale: locale,\n };\n }\n\n case REGISTER_LOCALE: {\n const locale = action.payload;\n if (state.availableLocales.includes(locale)) {\n return state; // Already registered\n }\n return {\n ...state,\n availableLocales: [...state.availableLocales, locale],\n };\n }\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, I18N_PLUGIN_ID } from './manifest';\nimport { I18nPluginConfig, I18nState } from './types';\nimport { I18nPlugin } from './i18n-plugin';\nimport { I18nAction } from './actions';\nimport { i18nReducer, initialState } from './reducer';\n\nexport const I18nPluginPackage: PluginPackage<I18nPlugin, I18nPluginConfig, I18nState, I18nAction> =\n {\n manifest,\n create: (registry, config) => new I18nPlugin(I18N_PLUGIN_ID, registry, config),\n reducer: i18nReducer,\n initialState,\n };\n\nexport * from './i18n-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './locales';\n"],"names":["registerLocaleAction","setLocaleAction"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { Action } from '@embedpdf/core';
2
+ import { LocaleCode } from './types';
3
+ export declare const SET_LOCALE = "I18N/SET_LOCALE";
4
+ export declare const REGISTER_LOCALE = "I18N/REGISTER_LOCALE";
5
+ export interface SetLocaleAction extends Action {
6
+ type: typeof SET_LOCALE;
7
+ payload: LocaleCode;
8
+ }
9
+ export interface RegisterLocaleAction extends Action {
10
+ type: typeof REGISTER_LOCALE;
11
+ payload: LocaleCode;
12
+ }
13
+ export type I18nAction = SetLocaleAction | RegisterLocaleAction;
14
+ export declare const setLocale: (locale: LocaleCode) => SetLocaleAction;
15
+ export declare const registerLocale: (locale: LocaleCode) => RegisterLocaleAction;
@@ -0,0 +1,28 @@
1
+ import { BasePlugin, PluginRegistry } from '@embedpdf/core';
2
+ import { I18nCapability, I18nPluginConfig, I18nState } from './types';
3
+ import { I18nAction } from './actions';
4
+ export declare class I18nPlugin extends BasePlugin<I18nPluginConfig, I18nCapability, I18nState, I18nAction> {
5
+ static readonly id: "i18n";
6
+ private config;
7
+ private locales;
8
+ private paramResolvers;
9
+ private paramsCache;
10
+ private readonly localeChange$;
11
+ private readonly paramsChanged$;
12
+ constructor(id: string, registry: PluginRegistry, config: I18nPluginConfig);
13
+ initialize(): Promise<void>;
14
+ destroy(): Promise<void>;
15
+ protected onDocumentClosed(documentId: string): void;
16
+ protected buildCapability(): I18nCapability;
17
+ private createI18nScope;
18
+ private translate;
19
+ private resolveParams;
20
+ private getNestedValue;
21
+ private interpolate;
22
+ private detectParamChanges;
23
+ private detectDocumentParamChanges;
24
+ private registerParamResolver;
25
+ private unregisterParamResolver;
26
+ private setLocale;
27
+ private registerLocale;
28
+ }
@@ -0,0 +1,9 @@
1
+ import { PluginPackage } from '@embedpdf/core';
2
+ import { I18nPluginConfig, I18nState } from './types';
3
+ import { I18nPlugin } from './i18n-plugin';
4
+ import { I18nAction } from './actions';
5
+ export declare const I18nPluginPackage: PluginPackage<I18nPlugin, I18nPluginConfig, I18nState, I18nAction>;
6
+ export * from './i18n-plugin';
7
+ export * from './types';
8
+ export * from './manifest';
9
+ export * from './locales';
@@ -0,0 +1,2 @@
1
+ import { Locale } from '../types';
2
+ export declare const enUS: Locale;
@@ -0,0 +1,2 @@
1
+ import { Locale } from '../types';
2
+ export declare const esES: Locale;
@@ -0,0 +1,2 @@
1
+ export * from './en';
2
+ export * from './es';
@@ -0,0 +1,4 @@
1
+ import { PluginManifest } from '@embedpdf/core';
2
+ import { I18nPluginConfig } from './types';
3
+ export declare const I18N_PLUGIN_ID = "i18n";
4
+ export declare const manifest: PluginManifest<I18nPluginConfig>;