@astroscope/i18n 1.1.0 → 1.1.2

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 (40) hide show
  1. package/dist/client/directives/idle.d.ts +0 -1
  2. package/dist/client/directives/idle.d.ts.map +1 -1
  3. package/dist/client/directives/load.d.ts +0 -1
  4. package/dist/client/directives/load.d.ts.map +1 -1
  5. package/dist/client/directives/media.d.ts +0 -1
  6. package/dist/client/directives/media.d.ts.map +1 -1
  7. package/dist/client/directives/only.d.ts +0 -1
  8. package/dist/client/directives/only.d.ts.map +1 -1
  9. package/dist/client/directives/utils.d.ts.map +1 -1
  10. package/dist/client/directives/visible.d.ts +0 -1
  11. package/dist/client/directives/visible.d.ts.map +1 -1
  12. package/dist/client/translate.d.ts +1 -2
  13. package/dist/client/translate.d.ts.map +1 -1
  14. package/dist/{context-DLfoS-uR.js → context-BEQ6qqX5.js} +8 -2
  15. package/dist/context-BEQ6qqX5.js.map +1 -0
  16. package/dist/extraction/index.d.ts +1 -2
  17. package/dist/extraction/index.d.ts.map +1 -1
  18. package/dist/{i18n-DzmH9JmE.d.ts → i18n-Dzh54-at.d.ts} +2 -3
  19. package/dist/i18n-Dzh54-at.d.ts.map +1 -0
  20. package/dist/index.d.ts +2 -3
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +3 -2
  23. package/dist/index.js.map +1 -1
  24. package/dist/internal.d.ts +1 -2
  25. package/dist/internal.d.ts.map +1 -1
  26. package/dist/internal.js +1 -1
  27. package/dist/{rich-CqNMP3tk.d.ts → rich-BWszYAzS.d.ts} +2 -1
  28. package/dist/rich-BWszYAzS.d.ts.map +1 -0
  29. package/dist/server/translate.d.ts +1 -2
  30. package/dist/server/translate.d.ts.map +1 -1
  31. package/dist/server/translate.js +1 -1
  32. package/dist/types-Bo4jMK8g.d.ts.map +1 -1
  33. package/dist/types-C98CcjtN.d.ts.map +1 -1
  34. package/dist/{types-BfyoJsoB.d.ts → types-CkqZWnXH.d.ts} +3 -3
  35. package/dist/types-CkqZWnXH.d.ts.map +1 -0
  36. package/package.json +7 -7
  37. package/dist/context-DLfoS-uR.js.map +0 -1
  38. package/dist/i18n-DzmH9JmE.d.ts.map +0 -1
  39. package/dist/rich-CqNMP3tk.d.ts.map +0 -1
  40. package/dist/types-BfyoJsoB.d.ts.map +0 -1
@@ -1,5 +1,4 @@
1
1
  import { ClientDirective } from "astro";
2
-
3
2
  //#region src/client/directives/idle.d.ts
4
3
  declare const idleDirective: ClientDirective;
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"idle.d.ts","names":[],"sources":["../../../src/client/directives/idle.ts"],"mappings":";;;cASM,aAAA,EAAe,eAYpB"}
1
+ {"version":3,"file":"idle.d.ts","names":[],"sources":["../../../src/client/directives/idle.ts"],"mappings":";;cASM,eAAe"}
@@ -1,5 +1,4 @@
1
1
  import { ClientDirective } from "astro";
2
-
3
2
  //#region src/client/directives/load.d.ts
4
3
  declare const loadDirective: ClientDirective;
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"load.d.ts","names":[],"sources":["../../../src/client/directives/load.ts"],"mappings":";;;cASM,aAAA,EAAe,eAIpB"}
1
+ {"version":3,"file":"load.d.ts","names":[],"sources":["../../../src/client/directives/load.ts"],"mappings":";;cASM,eAAe"}
@@ -1,5 +1,4 @@
1
1
  import { ClientDirective } from "astro";
2
-
3
2
  //#region src/client/directives/media.d.ts
4
3
  declare const mediaDirective: ClientDirective;
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"media.d.ts","names":[],"sources":["../../../src/client/directives/media.ts"],"mappings":";;;cASM,cAAA,EAAgB,eAerB"}
1
+ {"version":3,"file":"media.d.ts","names":[],"sources":["../../../src/client/directives/media.ts"],"mappings":";;cASM,gBAAgB"}
@@ -1,5 +1,4 @@
1
1
  import { ClientDirective } from "astro";
2
-
3
2
  //#region src/client/directives/only.d.ts
4
3
  declare const onlyDirective: ClientDirective;
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"only.d.ts","names":[],"sources":["../../../src/client/directives/only.ts"],"mappings":";;;cAWM,aAAA,EAAe,eAIpB"}
1
+ {"version":3,"file":"only.d.ts","names":[],"sources":["../../../src/client/directives/only.ts"],"mappings":";;cAWM,eAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","names":[],"sources":["../../../src/client/directives/utils.ts"],"mappings":";;AAqBA;;;;iBAAgB,kBAAA,CAAmB,EAAe,EAAX,WAAW"}
1
+ {"version":3,"file":"utils.d.ts","names":[],"sources":["../../../src/client/directives/utils.ts"],"mappings":";;;;;;iBAqBgB,mBAAmB,IAAI"}
@@ -1,5 +1,4 @@
1
1
  import { ClientDirective } from "astro";
2
-
3
2
  //#region src/client/directives/visible.d.ts
4
3
  declare const visibleDirective: ClientDirective;
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"visible.d.ts","names":[],"sources":["../../../src/client/directives/visible.ts"],"mappings":";;;cASM,gBAAA,EAAkB,eAuBvB"}
1
+ {"version":3,"file":"visible.d.ts","names":[],"sources":["../../../src/client/directives/visible.ts"],"mappings":";;cASM,kBAAkB"}
@@ -1,6 +1,5 @@
1
- import { t as RichComponents } from "../rich-CqNMP3tk.js";
1
+ import { t as RichComponents } from "../rich-BWszYAzS.js";
2
2
  import { a as TranslationMeta, i as TranslateFunction } from "../types-C98CcjtN.js";
3
-
4
3
  //#region src/client/translate.d.ts
5
4
  declare function getLocale(): string;
6
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"translate.d.ts","names":[],"sources":["../../src/client/translate.ts"],"mappings":";;;;iBAQgB,SAAA;;AAAhB;;;;AAAyB;AAiBzB;;;;AAuCuB;AAqBvB;;cA5Da,CAAA,EAAG,iBAuCO;;;;;;;;;;;;;;;;;;;AA0BT;iBALE,IAAA,cACd,GAAA,UACA,IAAA,GAAO,eAAA,uBACP,UAAA,GAAa,cAAA,CAAe,CAAA,eAC5B,MAAA,GAAS,MAAA,0CACE,CAAA"}
1
+ {"version":3,"file":"translate.d.ts","names":[],"sources":["../../src/client/translate.ts"],"mappings":";;;iBAQgB;;;;;;;;;;;;;;cAiBH,GAAG;;;;;;;;;;;;;;;;;;;;iBA4DA,KAAK,aACnB,aACA,OAAO,sCACP,aAAa,eAAe,gBAC5B,SAAS,gDACE"}
@@ -46,6 +46,12 @@ function generateBB26(index) {
46
46
  } while (remaining >= 0);
47
47
  return name;
48
48
  }
49
+ /**
50
+ * Generate a JS-safe variable name for the inline i18n script.
51
+ */
52
+ function generateVarName(index) {
53
+ return `_${generateBB26(index)}`;
54
+ }
49
55
  //#endregion
50
56
  //#region src/server/i18n.ts
51
57
  var I18nSingleton = class {
@@ -183,7 +189,7 @@ var I18nSingleton = class {
183
189
  for (const deps of Object.values(imports)) deps.forEach((d) => allChunks.add(d));
184
190
  const chunkToVar = /* @__PURE__ */ new Map();
185
191
  let varIndex = 0;
186
- for (const chunk of allChunks) chunkToVar.set(chunk, generateBB26(varIndex++));
192
+ for (const chunk of allChunks) chunkToVar.set(chunk, generateVarName(varIndex++));
187
193
  const varDecls = [...chunkToVar.entries()].map(([chunk, v]) => `${v}=${JSON.stringify(chunk)}`).join(",");
188
194
  const hashesObj = Object.entries(hashes).map(([chunk, hash]) => `[${chunkToVar.get(chunk)}]:${JSON.stringify(hash)}`).join(",");
189
195
  const importsObj = Object.entries(imports).filter(([chunk]) => chunkToVar.has(chunk)).map(([chunk, deps]) => {
@@ -244,4 +250,4 @@ function getContext() {
244
250
  //#endregion
245
251
  export { runWithContext as n, i18n as r, getContext as t };
246
252
 
247
- //# sourceMappingURL=context-DLfoS-uR.js.map
253
+ //# sourceMappingURL=context-BEQ6qqX5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-BEQ6qqX5.js","names":[],"sources":["../src/extraction/hash.ts","../src/server/utils.ts","../src/server/i18n.ts","../src/server/context.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport type { RawTranslations } from '../shared/types.js';\nimport type { ChunkManifest } from './types.js';\n\n/**\n * Hash a string to a short hash (for cache busting)\n */\nfunction hashString(str: string): string {\n return createHash('sha256').update(str).digest('hex').substring(0, 8);\n}\n\n/**\n * Compute hash for chunk translations\n */\nexport function computeChunkHash(translations: RawTranslations, keys: string[]): string {\n const relevantTranslations: RawTranslations = {};\n\n for (const key of [...keys].sort()) {\n if (translations[key] !== undefined) {\n relevantTranslations[key] = translations[key];\n }\n }\n\n return hashString(JSON.stringify(relevantTranslations));\n}\n\n/**\n * Compute hashes for all chunks in manifest\n */\nexport function computeAllChunkHashes(translations: RawTranslations, manifest: ChunkManifest): Record<string, string> {\n const hashes: Record<string, string> = {};\n\n for (const [chunkId, keys] of Object.entries(manifest)) {\n hashes[chunkId] = computeChunkHash(translations, keys);\n }\n\n return hashes;\n}\n","const LOWERCASE_A = 97;\n\n/**\n * Convert index to lowercase letter: 0→'a', 1→'b', ..., 25→'z'\n */\nfunction indexToLetter(index: number): string {\n return String.fromCharCode(LOWERCASE_A + index);\n}\n\n/**\n * Generate short variable name using bijective base-26: 0→'a', 25→'z', 26→'aa', 27→'ab', ...\n */\nexport function generateBB26(index: number): string {\n let name = '';\n let remaining = index;\n\n do {\n name = indexToLetter(remaining % 26) + name;\n remaining = Math.floor(remaining / 26) - 1;\n } while (remaining >= 0);\n\n return name;\n}\n\n/**\n * Generate a JS-safe variable name for the inline i18n script.\n */\nexport function generateVarName(index: number): string {\n return `_${generateBB26(index)}`;\n}\n","import { computeAllChunkHashes } from '../extraction/hash.js';\nimport { getGlobalState } from '../extraction/manifest.js';\nimport type { ExtractionManifest } from '../extraction/types.js';\nimport { compileTranslations } from '../shared/compiler.js';\nimport type { CompiledTranslations, RawTranslations } from '../shared/types.js';\nimport type { FallbackBehavior } from './types.js';\nimport { generateVarName } from './utils.js';\n\nexport type I18nConfig = {\n locales: string[];\n defaultLocale?: string | undefined;\n fallback?: FallbackBehavior | undefined;\n};\n\ntype NormalizedConfig = {\n locales: string[];\n defaultLocale: string;\n fallback: FallbackBehavior;\n};\n\nclass I18nSingleton {\n // normalized user config with defaults applied\n private config: NormalizedConfig | null = null;\n\n // locale -> raw translation strings (before ICU compilation)\n private rawCache = new Map<string, RawTranslations>();\n\n // locale -> raw translations merged with manifest fallbacks\n private mergedCache = new Map<string, RawTranslations>();\n\n // locale -> compiled ICU MessageFormat functions\n private compiledCache = new Map<string, CompiledTranslations>();\n\n // locale -> chunk name -> content hash (for cache busting)\n private hashCache = new Map<string, Record<string, string>>();\n\n // locale -> inline script for I18nScript component\n private scriptCache = new Map<string, string>();\n\n // \"locale:chunkName\" -> encoded chunk response body\n private chunkCache = new Map<string, Uint8Array>();\n\n // manifest getter (set by init module, provides live data in dev mode)\n private manifestGetter: (() => ExtractionManifest) | null = null;\n\n // tracks the manifest version to detect when derived caches need invalidation\n private manifestVersion = 0;\n\n async configure(config: I18nConfig): Promise<void> {\n if (!config.locales?.length) {\n throw new Error('i18n.configure(): locales array is required and must not be empty');\n }\n\n for (const locale of config.locales) {\n if (!locale) {\n throw new Error('i18n.configure(): locale cannot be empty');\n }\n\n if (locale !== locale.trim()) {\n throw new Error(`i18n.configure(): locale \"${locale}\" has leading or trailing whitespace`);\n }\n }\n\n if (new Set(config.locales).size !== config.locales.length) {\n throw new Error('i18n.configure(): locales array contains duplicates');\n }\n\n if (config.defaultLocale !== undefined) {\n if (!config.defaultLocale) {\n throw new Error('i18n.configure(): defaultLocale cannot be empty');\n }\n\n if (config.defaultLocale !== config.defaultLocale.trim()) {\n throw new Error(`i18n.configure(): defaultLocale \"${config.defaultLocale}\" has leading or trailing whitespace`);\n }\n\n if (!config.locales.includes(config.defaultLocale)) {\n throw new Error(`i18n.configure(): defaultLocale \"${config.defaultLocale}\" is not in locales array`);\n }\n }\n\n this.config = {\n locales: config.locales,\n defaultLocale: config.defaultLocale ?? config.locales[0]!,\n fallback: config.fallback ?? 'fallback',\n };\n\n // dynamically import manifest getter from virtual module\n // this removes the need for a separate `import '@astroscope/i18n/init'`\n if (!this.manifestGetter) {\n const m = await import('virtual:@astroscope/i18n/manifest');\n this.manifestGetter = m.getManifest;\n }\n }\n\n isConfigured(): boolean {\n return this.config !== null;\n }\n\n getConfig(): NormalizedConfig {\n if (!this.config) {\n throw new Error('i18n not configured. Call i18n.configure() first.');\n }\n\n return this.config;\n }\n\n setTranslations(locale: string, raw: RawTranslations): void {\n this.rawCache.set(locale, raw);\n this.mergedCache.delete(locale); // invalidate merged cache\n this.compiledCache.delete(locale); // invalidate compiled cache\n this.hashCache.delete(locale); // invalidate hash cache\n this.scriptCache.delete(locale); // invalidate script cache\n\n // invalidate chunk cache entries for this locale\n for (const key of this.chunkCache.keys()) {\n if (key.startsWith(`${locale}:`)) {\n this.chunkCache.delete(key);\n }\n }\n\n // recompute hashes if chunk manifest exists (production only)\n const { chunks } = this.getManifest();\n\n if (Object.keys(chunks).length > 0) {\n this.hashCache.set(locale, computeAllChunkHashes(raw, chunks));\n }\n }\n\n getTranslations(locale: string): RawTranslations {\n this.invalidateIfManifestChanged();\n\n const cached = this.mergedCache.get(locale);\n\n if (cached) {\n return cached;\n }\n\n const raw = this.rawCache.get(locale) ?? {};\n const manifest = this.manifestGetter?.() ?? { keys: [], chunks: {}, imports: {} };\n\n if (manifest.keys.length === 0) {\n return raw;\n }\n\n // merge fallbacks for keys that don't have translations\n const withFallbacks: RawTranslations = { ...raw };\n\n for (const { key, meta } of manifest.keys) {\n if (!(key in withFallbacks) && meta.fallback) {\n withFallbacks[key] = meta.fallback;\n }\n }\n\n this.mergedCache.set(locale, withFallbacks);\n\n return withFallbacks;\n }\n\n getCompiledTranslations(locale: string): CompiledTranslations {\n const cached = this.compiledCache.get(locale);\n\n if (cached) {\n return cached;\n }\n\n const compiled = compileTranslations(locale, this.getTranslations(locale));\n\n this.compiledCache.set(locale, compiled);\n\n return compiled;\n }\n\n /**\n * Get the extraction manifest (keys + chunks).\n * - keys: translation keys extracted from codebase with metadata\n * - chunks: mapping of chunk names to their translation keys\n */\n getManifest(): ExtractionManifest {\n if (!this.manifestGetter) {\n throw new Error('i18n manifest not initialized. Call i18n.configure() first.');\n }\n\n return this.manifestGetter();\n }\n\n getHashes(locale: string): Record<string, string> {\n return this.hashCache.get(locale) ?? {};\n }\n\n /**\n * Get the encoded chunk response body for a locale/chunk combination.\n * Cached to avoid repeated JSON.stringify and encoding on each request.\n * Returns undefined if chunk not found in manifest.\n */\n getChunkBody(locale: string, chunkName: string): Uint8Array | undefined {\n const keys = this.getManifest().chunks[chunkName];\n\n if (!keys) {\n return undefined;\n }\n\n const cacheKey = `${locale}:${chunkName}`;\n const cached = this.chunkCache.get(cacheKey);\n\n if (cached) {\n return cached;\n }\n\n const translations = this.getTranslations(locale);\n const chunkTranslations: RawTranslations = {};\n\n for (const key of keys) {\n if (translations[key]) {\n chunkTranslations[key] = translations[key];\n }\n }\n\n const js = `/* @astroscope/i18n chunk: ${chunkName} */\n(function() {\n var i = window.__i18n__;\n if (i) Object.assign(i.translations, ${JSON.stringify(chunkTranslations)});\n})();\n`;\n\n const body = new TextEncoder().encode(js);\n\n this.chunkCache.set(cacheKey, body);\n\n return body;\n }\n\n /**\n * Get the inline script for I18nScript component.\n * Cached per locale, invalidated when translations change.\n */\n getClientScript(locale: string): string {\n const cached = this.scriptCache.get(locale);\n\n if (cached) {\n return cached;\n }\n\n const script = this.createClientScript(locale);\n\n this.scriptCache.set(locale, script);\n\n return script;\n }\n\n private createClientScript(locale: string): string {\n const { chunks, imports } = this.getManifest();\n const hasChunks = Object.keys(chunks).length > 0;\n\n if (!hasChunks) {\n const raw = this.getTranslations(locale);\n\n return `window.__i18n__=${JSON.stringify({ locale, hashes: {}, imports: {}, translations: raw })};`;\n }\n\n const hashes = this.getHashes(locale);\n\n // collect all unique chunk names used in hashes and imports\n const allChunks = new Set<string>(Object.keys(hashes));\n\n for (const deps of Object.values(imports)) {\n deps.forEach((d) => allChunks.add(d));\n }\n\n // generate short variable names: _a, _b, _c, ..., _z, _aa, _ab, ...\n const chunkToVar = new Map<string, string>();\n let varIndex = 0;\n\n for (const chunk of allChunks) {\n chunkToVar.set(chunk, generateVarName(varIndex++));\n }\n\n // build IIFE with aliases for compact output\n const varDecls = [...chunkToVar.entries()].map(([chunk, v]) => `${v}=${JSON.stringify(chunk)}`).join(',');\n\n const hashesObj = Object.entries(hashes)\n .map(([chunk, hash]) => `[${chunkToVar.get(chunk)}]:${JSON.stringify(hash)}`)\n .join(',');\n\n // only include imports that are in our chunk set (have translations for this locale)\n const importsObj = Object.entries(imports)\n .filter(([chunk]) => chunkToVar.has(chunk))\n .map(([chunk, deps]) => {\n const validDeps = deps.filter((d) => chunkToVar.has(d));\n\n return validDeps.length > 0\n ? `[${chunkToVar.get(chunk)}]:[${validDeps.map((d) => chunkToVar.get(d)).join(',')}]`\n : null;\n })\n .filter(Boolean)\n .join(',');\n\n return (\n `(()=>{var ${varDecls};` +\n `window.__i18n__={locale:${JSON.stringify(locale)},hashes:{${hashesObj}},imports:{${importsObj}},translations:{}};` +\n `})();`\n );\n }\n\n /**\n * Clear translations for specified locale(s).\n * @param locales - Locale(s) to clear, or all if not specified\n */\n clear(locales?: string | string[] | undefined): void {\n const targets = this.resolveLocales(locales);\n\n for (const locale of targets) {\n this.rawCache.delete(locale);\n this.mergedCache.delete(locale);\n this.compiledCache.delete(locale);\n this.hashCache.delete(locale);\n this.scriptCache.delete(locale);\n\n // clear chunk cache entries for this locale\n for (const key of this.chunkCache.keys()) {\n if (key.startsWith(`${locale}:`)) {\n this.chunkCache.delete(key);\n }\n }\n }\n }\n\n /**\n * invalidate derived caches when the extraction manifest has changed (dev mode HMR)\n */\n private invalidateIfManifestChanged(): void {\n const { version } = getGlobalState();\n\n if (version === this.manifestVersion) {\n return;\n }\n\n this.manifestVersion = version;\n this.mergedCache.clear();\n this.compiledCache.clear();\n this.scriptCache.clear();\n this.chunkCache.clear();\n }\n\n private resolveLocales(locales?: string | string[] | undefined): string[] {\n if (!locales) {\n return this.config?.locales ?? [];\n }\n\n if (typeof locales === 'string') {\n return [locales];\n }\n\n return locales;\n }\n}\n\nexport const i18n = new I18nSingleton();\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { I18nContext } from './types.js';\n\nconst als = new AsyncLocalStorage<I18nContext>();\n\n/**\n * Run a function with i18n context (called by middleware)\n */\nexport function runWithContext<T>(context: I18nContext, fn: () => T): T {\n return als.run(context, fn);\n}\n\n/**\n * Get the current i18n context\n */\nexport function getContext(): I18nContext | null {\n return als.getStore() ?? null;\n}\n"],"mappings":"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"}
@@ -1,8 +1,7 @@
1
- import { n as ExtractedKey, r as ExtractionManifest, t as ChunkManifest } from "../types-BfyoJsoB.js";
1
+ import { n as ExtractedKey, r as ExtractionManifest, t as ChunkManifest } from "../types-CkqZWnXH.js";
2
2
  import { t as ConsistencyCheckLevel } from "../types-Bo4jMK8g.js";
3
3
  import { AstroIntegrationLogger } from "astro";
4
4
  import { Plugin } from "vite";
5
-
6
5
  //#region src/extraction/manifest.d.ts
7
6
  /**
8
7
  * Get the current extraction manifest (for dev mode live access).
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/extraction/manifest.ts","../../src/extraction/vite-plugin.ts"],"mappings":";;;;;;ACwBA;;;;AAAA,iBDwBgB,WAAA,IAAe,kBAAkB;;;KCxBrC,qBAAA;EACV,MAAA,EAAQ,sBAAA;EACR,WAAA,EAAa,qBAAqB;AAAA;;;;ADsBa;;;;ACxBjD;;;iBAyCgB,cAAA,CAAe,OAAA,EAAS,qBAAA,GAAwB,MAAM"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/extraction/manifest.ts","../../src/extraction/vite-plugin.ts"],"mappings":";;;;;;;;;iBAgDgB,eAAe;;;KCxBnB;EACV,QAAQ;EACR,aAAa;;;;;;;;;;;;iBAuCC,eAAe,SAAS,wBAAwB"}
@@ -1,6 +1,5 @@
1
1
  import { a as TranslationMeta, r as RawTranslations, t as CompiledTranslations } from "./types-C98CcjtN.js";
2
- import { r as ExtractionManifest } from "./types-BfyoJsoB.js";
3
-
2
+ import { r as ExtractionManifest } from "./types-CkqZWnXH.js";
4
3
  //#region src/server/types.d.ts
5
4
  /**
6
5
  * Fallback behavior when translation is missing
@@ -76,4 +75,4 @@ declare class I18nSingleton {
76
75
  declare const i18n: I18nSingleton;
77
76
  //#endregion
78
77
  export { I18nContext as i, i18n as n, FallbackBehavior as r, I18nConfig as t };
79
- //# sourceMappingURL=i18n-DzmH9JmE.d.ts.map
78
+ //# sourceMappingURL=i18n-Dzh54-at.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n-Dzh54-at.d.ts","names":[],"sources":["../src/server/types.ts","../src/server/i18n.ts"],"mappings":";;;;;;KAKY,oDACuB,aAAa,OAAO;;;;KAK3C;EACV;EAEA,cAAc;EAEd,iBAAiB;EACjB,UAAU;;;;KCTA;EACV;EACA;EACA,WAAW;;KAGR;EACH;EACA;EACA,UAAU;;cAGN;UAEI;UAGA;UAGA;UAGA;UAGA;UAGA;UAGA;UAGA;UAGA;EAEF,UAAU,QAAQ,aAAa;EA+CrC;EAIA,aAAa;EAQb,gBAAgB,gBAAgB,KAAK;EAsBrC,gBAAgB,iBAAiB;EA8BjC,wBAAwB,iBAAiB;;;;;;EAmBzC,eAAe;EAQf,UAAU,iBAAiB;;;;;;EAS3B,aAAa,gBAAgB,oBAAoB;;;;;EAyCjD,gBAAgB;UAcR;;;;;EA0DR,MAAM;;;;UAsBE;UAcA;;cAaG,MAAI"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import { a as TranslationMeta, r as RawTranslations } from "./types-C98CcjtN.js";
2
- import { n as ExtractedKey, r as ExtractionManifest } from "./types-BfyoJsoB.js";
2
+ import { n as ExtractedKey, r as ExtractionManifest } from "./types-CkqZWnXH.js";
3
3
  import { n as I18nOptions } from "./types-Bo4jMK8g.js";
4
- import { n as i18n, r as FallbackBehavior, t as I18nConfig } from "./i18n-DzmH9JmE.js";
4
+ import { n as i18n, r as FallbackBehavior, t as I18nConfig } from "./i18n-Dzh54-at.js";
5
5
  import { ExcludePattern } from "@astroscope/node/excludes";
6
6
  import { APIContext, AstroIntegration, MiddlewareHandler } from "astro";
7
-
8
7
  //#region src/integration/integration.d.ts
9
8
  /**
10
9
  * Astro integration for i18n with automatic per-chunk translation loading.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/integration/integration.ts","../src/server/middleware.ts","../src/server/locale.ts"],"mappings":";;;;;;;;;;;;;;AAE8C;iBAWtB,eAAA,CAAgB,OAAA,GAAS,WAAA,GAAmB,gBAAgB;;;KCNxE,qBAAA;EACV,MAAA,GAAS,GAAA,EAAK,UAAA;;;;;ADN8B;;;;;;;;AAWsC;;;;ACNpF;;;;;EAuBE,OAAA,GAAU,cAAA,OAAqB,OAAA,EAAS,UAAA;AAAA;;;;;;;;;;AAAU;AAmGpD;;;;AAA8D;AAkC9D;;;;iBAlCgB,yBAAA,IAA6B,iBAAiB;;;;AAkCyB;;;;AC7JvF;;;;AAA6C;;;;;;;;iBD6J7B,oBAAA,CAAqB,OAAA,EAAS,qBAAA,GAAwB,iBAAiB;;;;;;;iBC7JvE,YAAA,CAAa,OAAgB,EAAP,OAAO"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/integration/integration.ts","../src/server/middleware.ts","../src/server/locale.ts"],"mappings":";;;;;;;;;;;;;;iBAawB,gBAAgB,UAAS,cAAmB;;;KCNxD;EACV,SAAS,KAAK;;;;;;;;;;;;;;;;;;;;;;EAsBd,UAAU,qBAAqB,SAAS;;;;;;;;;;;;;;;;;;;;;iBAmG1B,6BAA6B;;;;;;;;;;;;;;;;;;;;iBAkC7B,qBAAqB,SAAS,wBAAwB;;;;;;;iBC7JtD,aAAa,SAAS"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as i18nVitePlugin } from "./vite-plugin-BbdVKdt8.js";
2
- import { n as runWithContext, r as i18n } from "./context-DLfoS-uR.js";
2
+ import { n as runWithContext, r as i18n } from "./context-BEQ6qqX5.js";
3
3
  import { RECOMMENDED_EXCLUDES, shouldExclude } from "@astroscope/node/excludes";
4
4
  import { overrideRequestRoute } from "@astroscope/node/log";
5
5
  //#region src/integration/integration.ts
@@ -46,7 +46,8 @@ function i18nIntegration(options = {}) {
46
46
  declare namespace astroHTML.JSX {
47
47
  interface AstroBuiltinAttributes {
48
48
  ${CLIENT_DIRECTIVES.map((d) => {
49
- return ` 'client:${d}'?: ${typeMap[d.replace("-x", "")]};`;
49
+ const base = d.replace("-x", "");
50
+ return ` 'client:${d}'?: ${typeMap[base]};`;
50
51
  }).join("\n")}
51
52
  }
52
53
  }`
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/integration/integration.ts","../src/server/middleware.ts","../src/server/locale.ts"],"sourcesContent":["import type { AstroIntegration } from 'astro';\nimport { i18nVitePlugin } from '../extraction/vite-plugin.js';\nimport type { I18nOptions } from './types.js';\n\nconst CLIENT_DIRECTIVES = ['load-x', 'idle-x', 'visible-x', 'media-x', 'only-x'] as const;\n\n/**\n * Astro integration for i18n with automatic per-chunk translation loading.\n *\n * Registers:\n * - Client directives (`client:load-x`, `client:idle-x`, `client:visible-x`, `client:media-x`, `client:only-x`)\n * - Vite plugin for translation key extraction\n */\nexport default function i18nIntegration(options: I18nOptions = {}): AstroIntegration {\n const { consistency = 'error' } = options;\n\n return {\n name: '@astroscope/i18n',\n hooks: {\n 'astro:config:setup': ({ addClientDirective, updateConfig, logger }) => {\n for (const directive of CLIENT_DIRECTIVES) {\n const base = directive.replace('-x', '');\n addClientDirective({\n name: directive,\n entrypoint: `@astroscope/i18n/client-directives/${base}.js`,\n });\n }\n\n updateConfig({\n vite: {\n plugins: [i18nVitePlugin({ logger, consistency })],\n },\n });\n },\n 'astro:config:done': ({ injectTypes }) => {\n // inject client directive types for LSP support\n const typeMap: Record<string, string> = {\n load: 'boolean',\n idle: 'boolean',\n visible: 'boolean | string',\n media: 'string',\n only: 'string',\n };\n\n const attributes = CLIENT_DIRECTIVES.map((d) => {\n const base = d.replace('-x', '');\n return ` 'client:${d}'?: ${typeMap[base]};`;\n }).join('\\n');\n\n injectTypes({\n filename: 'client-directives.d.ts',\n content: `// generated by @astroscope/i18n\ndeclare namespace astroHTML.JSX {\n interface AstroBuiltinAttributes {\n${attributes}\n }\n}`,\n });\n },\n },\n };\n}\n","import { type ExcludePattern, RECOMMENDED_EXCLUDES, shouldExclude } from '@astroscope/node/excludes';\nimport { overrideRequestRoute } from '@astroscope/node/log';\nimport type { APIContext, MiddlewareHandler } from 'astro';\nimport { runWithContext } from './context.js';\nimport { i18n } from './i18n.js';\nimport type { I18nContext } from './types.js';\n\nexport type I18nMiddlewareOptions = {\n locale: (ctx: APIContext) => string;\n /**\n * Patterns to exclude from locale context setup.\n * Defaults to RECOMMENDED_EXCLUDES if not provided.\n *\n * @example\n * ```ts\n * import { RECOMMENDED_EXCLUDES } from '@astroscope/node/excludes';\n *\n * // extend defaults\n * createI18nMiddleware({\n * locale: (ctx) => ctx.locals.session?.locale ?? 'en',\n * exclude: [...RECOMMENDED_EXCLUDES, { exact: '/health' }],\n * })\n *\n * // disable excludes entirely\n * createI18nMiddleware({\n * locale: (ctx) => ctx.locals.session?.locale ?? 'en',\n * exclude: [],\n * })\n * ```\n */\n exclude?: ExcludePattern[] | ((context: APIContext) => boolean) | undefined;\n};\n\nconst I18N_ENDPOINT_PREFIX = '/_i18n/';\n\n// astro has no route behind the chunk endpoint, so requests would otherwise be\n// logged and measured under whatever routing matched — typically `/404`\nconst I18N_ENDPOINT_ROUTE = '/_i18n/[locale]/[chunk]';\n\n/**\n * Serve a translation chunk. Returns `undefined` when the path isn't a chunk\n * request, and the caller passes it on to astro.\n */\nfunction createChunkResponse(pathname: string): Response | undefined {\n if (!pathname.startsWith(I18N_ENDPOINT_PREFIX)) {\n return undefined;\n }\n\n if (!i18n.isConfigured()) {\n console.warn(`[@astroscope/i18n] not configured, passing through: ${pathname}`);\n\n return undefined;\n }\n\n const path = pathname.slice(I18N_ENDPOINT_PREFIX.length);\n\n // attempt to parse as efficient as possible\n // expected path format: {locale}/{chunkName}.{hash}.js\n // avoiding regex or split for performance\n const slashIdx = path.indexOf('/');\n\n if (slashIdx === -1) {\n return undefined;\n }\n\n const locale = path.slice(0, slashIdx);\n\n // validate locale against configured locales to prevent arbitrary locale injection\n const config = i18n.getConfig();\n\n if (!config.locales.includes(locale)) {\n return new Response('/* unknown locale */', {\n status: 404,\n headers: { 'Content-Type': 'application/javascript' },\n });\n }\n\n const rest = path.slice(slashIdx + 1);\n\n if (!rest.endsWith('.js')) {\n return undefined;\n }\n\n const withoutJs = rest.slice(0, -3);\n const lastDotIdx = withoutJs.lastIndexOf('.');\n\n if (lastDotIdx === -1) {\n return undefined;\n }\n\n const chunkName = withoutJs.slice(0, lastDotIdx);\n const body = i18n.getChunkBody(locale, chunkName);\n\n if (!body) {\n return new Response(`/* chunk not found: ${chunkName} */`, {\n status: 404,\n headers: { 'Content-Type': 'application/javascript' },\n });\n }\n\n return new Response(body as BodyInit, {\n status: 200,\n headers: {\n 'Content-Type': 'text/javascript; charset=utf-8',\n 'Content-Length': String(body.byteLength),\n 'Cache-Control': 'public, max-age=31536000, immutable',\n },\n });\n}\n\n/**\n * Create the i18n chunk middleware that serves translation chunks at `/_i18n/` endpoints.\n *\n * Place this early in your middleware sequence (before session/auth)\n * to avoid unnecessary overhead for static translation requests.\n *\n * @example\n * ```typescript\n * // src/middleware.ts\n * import { sequence } from 'astro:middleware';\n * import { createI18nChunkMiddleware, createI18nMiddleware } from '@astroscope/i18n';\n *\n * export const onRequest = sequence(\n * createI18nChunkMiddleware(), // early: serves /_i18n/ chunks\n * sessionMiddleware,\n * createI18nMiddleware({ locale: (ctx) => ... }), // after session\n * );\n * ```\n */\nexport function createI18nChunkMiddleware(): MiddlewareHandler {\n return (ctx, next) => {\n const response = createChunkResponse(ctx.url.pathname);\n\n if (!response) {\n return next();\n }\n\n // this middleware, not astro's routing, is what serves the request\n overrideRequestRoute(I18N_ENDPOINT_ROUTE);\n\n return response;\n };\n}\n\n/**\n * Create the i18n locale middleware.\n *\n * Sets up the request context with locale and translations for use by\n * `t()` and `<I18nScript />`. Place this after session middleware if\n * your locale detection depends on session/cookies.\n *\n * @example\n * ```typescript\n * import { createI18nMiddleware, detectLocale, i18n } from '@astroscope/i18n';\n *\n * export const i18nMiddleware = createI18nMiddleware({\n * locale: (ctx) =>\n * ctx.cookies.get('locale')?.value ??\n * detectLocale(ctx.request) ??\n * i18n.getConfig().defaultLocale,\n * });\n * ```\n */\nexport function createI18nMiddleware(options: I18nMiddlewareOptions): MiddlewareHandler {\n return (ctx, next) => {\n if (shouldExclude(ctx, options.exclude ?? RECOMMENDED_EXCLUDES)) {\n return next();\n }\n\n if (!i18n.isConfigured()) {\n console.warn(`[@astroscope/i18n] not configured, passing through: ${ctx.url.pathname}`);\n\n return next();\n }\n\n const locale = options.locale(ctx);\n\n const context: I18nContext = {\n locale,\n translations: i18n.getCompiledTranslations(locale),\n rawTranslations: i18n.getTranslations(locale),\n fallback: i18n.getConfig().fallback,\n };\n\n return runWithContext(context, () => next());\n };\n}\n","import { i18n } from './i18n.js';\n\n/**\n * Detect locale from Accept-Language header.\n * Returns best match from configured locales, or undefined if none match.\n */\nexport function detectLocale(request: Request): string | undefined {\n if (!i18n.isConfigured()) return undefined;\n\n const { locales } = i18n.getConfig();\n const acceptLanguage = request.headers.get('accept-language');\n\n if (!acceptLanguage) return undefined;\n\n const preferred = acceptLanguage\n .split(',')\n .map((part) => {\n // optional whitespace around `;` is legal per rfc 9110\n const [lang, q = 'q=1'] = part.split(';').map((s) => s.trim());\n const baseLang = lang?.split('-')[0]?.toLowerCase();\n\n return {\n lang: baseLang,\n q: parseFloat(q.replace('q=', '')),\n };\n })\n .filter((p): p is { lang: string; q: number } => !!p.lang)\n .sort((a, b) => b.q - a.q);\n\n for (const { lang } of preferred) {\n if (locales.includes(lang)) {\n return lang;\n }\n }\n\n return undefined;\n}\n"],"mappings":";;;;;AAIA,MAAM,oBAAoB;CAAC;CAAU;CAAU;CAAa;CAAW;AAAQ;;;;;;;;AAS/E,SAAwB,gBAAgB,UAAuB,CAAC,GAAqB;CACnF,MAAM,EAAE,cAAc,YAAY;CAElC,OAAO;EACL,MAAM;EACN,OAAO;GACL,uBAAuB,EAAE,oBAAoB,cAAc,aAAa;IACtE,KAAK,MAAM,aAAa,mBAEtB,mBAAmB;KACjB,MAAM;KACN,YAAY,sCAHD,UAAU,QAAQ,MAAM,EAGkB,EAAE;IACzD,CAAC;IAGH,aAAa,EACX,MAAM,EACJ,SAAS,CAAC,eAAe;KAAE;KAAQ;IAAY,CAAC,CAAC,EACnD,EACF,CAAC;GACH;GACA,sBAAsB,EAAE,kBAAkB;IAExC,MAAM,UAAkC;KACtC,MAAM;KACN,MAAM;KACN,SAAS;KACT,OAAO;KACP,MAAM;IACR;IAOA,YAAY;KACV,UAAU;KACV,SAAS;;;EAPQ,kBAAkB,KAAK,MAAM;MAE9C,OAAO,eAAe,EAAE,MAAM,QADjB,EAAE,QAAQ,MAAM,EACY,GAAG;KAC9C,CAAC,CAAC,CAAC,KAAK,IAOL,EAAE;;;IAGL,CAAC;GACH;EACF;CACF;AACF;;;AC5BA,MAAM,uBAAuB;AAI7B,MAAM,sBAAsB;;;;;AAM5B,SAAS,oBAAoB,UAAwC;CACnE,IAAI,CAAC,SAAS,WAAW,oBAAoB,GAC3C;CAGF,IAAI,CAAC,KAAK,aAAa,GAAG;EACxB,QAAQ,KAAK,uDAAuD,UAAU;EAE9E;CACF;CAEA,MAAM,OAAO,SAAS,MAAM,CAA2B;CAKvD,MAAM,WAAW,KAAK,QAAQ,GAAG;CAEjC,IAAI,aAAa,IACf;CAGF,MAAM,SAAS,KAAK,MAAM,GAAG,QAAQ;CAKrC,IAAI,CAFW,KAAK,UAEV,CAAC,CAAC,QAAQ,SAAS,MAAM,GACjC,OAAO,IAAI,SAAS,wBAAwB;EAC1C,QAAQ;EACR,SAAS,EAAE,gBAAgB,yBAAyB;CACtD,CAAC;CAGH,MAAM,OAAO,KAAK,MAAM,WAAW,CAAC;CAEpC,IAAI,CAAC,KAAK,SAAS,KAAK,GACtB;CAGF,MAAM,YAAY,KAAK,MAAM,GAAG,EAAE;CAClC,MAAM,aAAa,UAAU,YAAY,GAAG;CAE5C,IAAI,eAAe,IACjB;CAGF,MAAM,YAAY,UAAU,MAAM,GAAG,UAAU;CAC/C,MAAM,OAAO,KAAK,aAAa,QAAQ,SAAS;CAEhD,IAAI,CAAC,MACH,OAAO,IAAI,SAAS,uBAAuB,UAAU,MAAM;EACzD,QAAQ;EACR,SAAS,EAAE,gBAAgB,yBAAyB;CACtD,CAAC;CAGH,OAAO,IAAI,SAAS,MAAkB;EACpC,QAAQ;EACR,SAAS;GACP,gBAAgB;GAChB,kBAAkB,OAAO,KAAK,UAAU;GACxC,iBAAiB;EACnB;CACF,CAAC;AACH;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,4BAA+C;CAC7D,QAAQ,KAAK,SAAS;EACpB,MAAM,WAAW,oBAAoB,IAAI,IAAI,QAAQ;EAErD,IAAI,CAAC,UACH,OAAO,KAAK;EAId,qBAAqB,mBAAmB;EAExC,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,qBAAqB,SAAmD;CACtF,QAAQ,KAAK,SAAS;EACpB,IAAI,cAAc,KAAK,QAAQ,WAAW,oBAAoB,GAC5D,OAAO,KAAK;EAGd,IAAI,CAAC,KAAK,aAAa,GAAG;GACxB,QAAQ,KAAK,uDAAuD,IAAI,IAAI,UAAU;GAEtF,OAAO,KAAK;EACd;EAEA,MAAM,SAAS,QAAQ,OAAO,GAAG;EASjC,OAAO,eAAe;GANpB;GACA,cAAc,KAAK,wBAAwB,MAAM;GACjD,iBAAiB,KAAK,gBAAgB,MAAM;GAC5C,UAAU,KAAK,UAAU,CAAC,CAAC;EAGD,SAAS,KAAK,CAAC;CAC7C;AACF;;;;;;;ACpLA,SAAgB,aAAa,SAAsC;CACjE,IAAI,CAAC,KAAK,aAAa,GAAG,OAAO,KAAA;CAEjC,MAAM,EAAE,YAAY,KAAK,UAAU;CACnC,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,iBAAiB;CAE5D,IAAI,CAAC,gBAAgB,OAAO,KAAA;CAE5B,MAAM,YAAY,eACf,MAAM,GAAG,CAAC,CACV,KAAK,SAAS;EAEb,MAAM,CAAC,MAAM,IAAI,SAAS,KAAK,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK,CAAC;EAG7D,OAAO;GACL,MAHe,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,YAAY;GAIhD,GAAG,WAAW,EAAE,QAAQ,MAAM,EAAE,CAAC;EACnC;CACF,CAAC,CAAC,CACD,QAAQ,MAAwC,CAAC,CAAC,EAAE,IAAI,CAAC,CACzD,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC;CAE3B,KAAK,MAAM,EAAE,UAAU,WACrB,IAAI,QAAQ,SAAS,IAAI,GACvB,OAAO;AAKb"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/integration/integration.ts","../src/server/middleware.ts","../src/server/locale.ts"],"sourcesContent":["import type { AstroIntegration } from 'astro';\nimport { i18nVitePlugin } from '../extraction/vite-plugin.js';\nimport type { I18nOptions } from './types.js';\n\nconst CLIENT_DIRECTIVES = ['load-x', 'idle-x', 'visible-x', 'media-x', 'only-x'] as const;\n\n/**\n * Astro integration for i18n with automatic per-chunk translation loading.\n *\n * Registers:\n * - Client directives (`client:load-x`, `client:idle-x`, `client:visible-x`, `client:media-x`, `client:only-x`)\n * - Vite plugin for translation key extraction\n */\nexport default function i18nIntegration(options: I18nOptions = {}): AstroIntegration {\n const { consistency = 'error' } = options;\n\n return {\n name: '@astroscope/i18n',\n hooks: {\n 'astro:config:setup': ({ addClientDirective, updateConfig, logger }) => {\n for (const directive of CLIENT_DIRECTIVES) {\n const base = directive.replace('-x', '');\n addClientDirective({\n name: directive,\n entrypoint: `@astroscope/i18n/client-directives/${base}.js`,\n });\n }\n\n updateConfig({\n vite: {\n plugins: [i18nVitePlugin({ logger, consistency })],\n },\n });\n },\n 'astro:config:done': ({ injectTypes }) => {\n // inject client directive types for LSP support\n const typeMap: Record<string, string> = {\n load: 'boolean',\n idle: 'boolean',\n visible: 'boolean | string',\n media: 'string',\n only: 'string',\n };\n\n const attributes = CLIENT_DIRECTIVES.map((d) => {\n const base = d.replace('-x', '');\n return ` 'client:${d}'?: ${typeMap[base]};`;\n }).join('\\n');\n\n injectTypes({\n filename: 'client-directives.d.ts',\n content: `// generated by @astroscope/i18n\ndeclare namespace astroHTML.JSX {\n interface AstroBuiltinAttributes {\n${attributes}\n }\n}`,\n });\n },\n },\n };\n}\n","import { type ExcludePattern, RECOMMENDED_EXCLUDES, shouldExclude } from '@astroscope/node/excludes';\nimport { overrideRequestRoute } from '@astroscope/node/log';\nimport type { APIContext, MiddlewareHandler } from 'astro';\nimport { runWithContext } from './context.js';\nimport { i18n } from './i18n.js';\nimport type { I18nContext } from './types.js';\n\nexport type I18nMiddlewareOptions = {\n locale: (ctx: APIContext) => string;\n /**\n * Patterns to exclude from locale context setup.\n * Defaults to RECOMMENDED_EXCLUDES if not provided.\n *\n * @example\n * ```ts\n * import { RECOMMENDED_EXCLUDES } from '@astroscope/node/excludes';\n *\n * // extend defaults\n * createI18nMiddleware({\n * locale: (ctx) => ctx.locals.session?.locale ?? 'en',\n * exclude: [...RECOMMENDED_EXCLUDES, { exact: '/health' }],\n * })\n *\n * // disable excludes entirely\n * createI18nMiddleware({\n * locale: (ctx) => ctx.locals.session?.locale ?? 'en',\n * exclude: [],\n * })\n * ```\n */\n exclude?: ExcludePattern[] | ((context: APIContext) => boolean) | undefined;\n};\n\nconst I18N_ENDPOINT_PREFIX = '/_i18n/';\n\n// astro has no route behind the chunk endpoint, so requests would otherwise be\n// logged and measured under whatever routing matched — typically `/404`\nconst I18N_ENDPOINT_ROUTE = '/_i18n/[locale]/[chunk]';\n\n/**\n * Serve a translation chunk. Returns `undefined` when the path isn't a chunk\n * request, and the caller passes it on to astro.\n */\nfunction createChunkResponse(pathname: string): Response | undefined {\n if (!pathname.startsWith(I18N_ENDPOINT_PREFIX)) {\n return undefined;\n }\n\n if (!i18n.isConfigured()) {\n console.warn(`[@astroscope/i18n] not configured, passing through: ${pathname}`);\n\n return undefined;\n }\n\n const path = pathname.slice(I18N_ENDPOINT_PREFIX.length);\n\n // attempt to parse as efficient as possible\n // expected path format: {locale}/{chunkName}.{hash}.js\n // avoiding regex or split for performance\n const slashIdx = path.indexOf('/');\n\n if (slashIdx === -1) {\n return undefined;\n }\n\n const locale = path.slice(0, slashIdx);\n\n // validate locale against configured locales to prevent arbitrary locale injection\n const config = i18n.getConfig();\n\n if (!config.locales.includes(locale)) {\n return new Response('/* unknown locale */', {\n status: 404,\n headers: { 'Content-Type': 'application/javascript' },\n });\n }\n\n const rest = path.slice(slashIdx + 1);\n\n if (!rest.endsWith('.js')) {\n return undefined;\n }\n\n const withoutJs = rest.slice(0, -3);\n const lastDotIdx = withoutJs.lastIndexOf('.');\n\n if (lastDotIdx === -1) {\n return undefined;\n }\n\n const chunkName = withoutJs.slice(0, lastDotIdx);\n const body = i18n.getChunkBody(locale, chunkName);\n\n if (!body) {\n return new Response(`/* chunk not found: ${chunkName} */`, {\n status: 404,\n headers: { 'Content-Type': 'application/javascript' },\n });\n }\n\n return new Response(body as BodyInit, {\n status: 200,\n headers: {\n 'Content-Type': 'text/javascript; charset=utf-8',\n 'Content-Length': String(body.byteLength),\n 'Cache-Control': 'public, max-age=31536000, immutable',\n },\n });\n}\n\n/**\n * Create the i18n chunk middleware that serves translation chunks at `/_i18n/` endpoints.\n *\n * Place this early in your middleware sequence (before session/auth)\n * to avoid unnecessary overhead for static translation requests.\n *\n * @example\n * ```typescript\n * // src/middleware.ts\n * import { sequence } from 'astro:middleware';\n * import { createI18nChunkMiddleware, createI18nMiddleware } from '@astroscope/i18n';\n *\n * export const onRequest = sequence(\n * createI18nChunkMiddleware(), // early: serves /_i18n/ chunks\n * sessionMiddleware,\n * createI18nMiddleware({ locale: (ctx) => ... }), // after session\n * );\n * ```\n */\nexport function createI18nChunkMiddleware(): MiddlewareHandler {\n return (ctx, next) => {\n const response = createChunkResponse(ctx.url.pathname);\n\n if (!response) {\n return next();\n }\n\n // this middleware, not astro's routing, is what serves the request\n overrideRequestRoute(I18N_ENDPOINT_ROUTE);\n\n return response;\n };\n}\n\n/**\n * Create the i18n locale middleware.\n *\n * Sets up the request context with locale and translations for use by\n * `t()` and `<I18nScript />`. Place this after session middleware if\n * your locale detection depends on session/cookies.\n *\n * @example\n * ```typescript\n * import { createI18nMiddleware, detectLocale, i18n } from '@astroscope/i18n';\n *\n * export const i18nMiddleware = createI18nMiddleware({\n * locale: (ctx) =>\n * ctx.cookies.get('locale')?.value ??\n * detectLocale(ctx.request) ??\n * i18n.getConfig().defaultLocale,\n * });\n * ```\n */\nexport function createI18nMiddleware(options: I18nMiddlewareOptions): MiddlewareHandler {\n return (ctx, next) => {\n if (shouldExclude(ctx, options.exclude ?? RECOMMENDED_EXCLUDES)) {\n return next();\n }\n\n if (!i18n.isConfigured()) {\n console.warn(`[@astroscope/i18n] not configured, passing through: ${ctx.url.pathname}`);\n\n return next();\n }\n\n const locale = options.locale(ctx);\n\n const context: I18nContext = {\n locale,\n translations: i18n.getCompiledTranslations(locale),\n rawTranslations: i18n.getTranslations(locale),\n fallback: i18n.getConfig().fallback,\n };\n\n return runWithContext(context, () => next());\n };\n}\n","import { i18n } from './i18n.js';\n\n/**\n * Detect locale from Accept-Language header.\n * Returns best match from configured locales, or undefined if none match.\n */\nexport function detectLocale(request: Request): string | undefined {\n if (!i18n.isConfigured()) return undefined;\n\n const { locales } = i18n.getConfig();\n const acceptLanguage = request.headers.get('accept-language');\n\n if (!acceptLanguage) return undefined;\n\n const preferred = acceptLanguage\n .split(',')\n .map((part) => {\n // optional whitespace around `;` is legal per rfc 9110\n const [lang, q = 'q=1'] = part.split(';').map((s) => s.trim());\n const baseLang = lang?.split('-')[0]?.toLowerCase();\n\n return {\n lang: baseLang,\n q: parseFloat(q.replace('q=', '')),\n };\n })\n .filter((p): p is { lang: string; q: number } => !!p.lang)\n .sort((a, b) => b.q - a.q);\n\n for (const { lang } of preferred) {\n if (locales.includes(lang)) {\n return lang;\n }\n }\n\n return undefined;\n}\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import { n as I18nClientState } from "./types-C98CcjtN.js";
2
- import { i as I18nContext, n as i18n } from "./i18n-DzmH9JmE.js";
3
-
2
+ import { i as I18nContext, n as i18n } from "./i18n-Dzh54-at.js";
4
3
  //#region src/server/context.d.ts
5
4
  /**
6
5
  * Get the current i18n context
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","names":[],"sources":["../src/server/context.ts"],"mappings":";;;;;;;iBAegB,UAAA,IAAc,WAAW"}
1
+ {"version":3,"file":"internal.d.ts","names":[],"sources":["../src/server/context.ts"],"mappings":";;;;;;iBAegB,cAAc"}
package/dist/internal.js CHANGED
@@ -1,2 +1,2 @@
1
- import { r as i18n, t as getContext } from "./context-DLfoS-uR.js";
1
+ import { r as i18n, t as getContext } from "./context-BEQ6qqX5.js";
2
2
  export { getContext, i18n };
@@ -1,3 +1,4 @@
1
+ import "messageformat";
1
2
  //#region src/shared/rich.d.ts
2
3
  /**
3
4
  * Component callbacks for rich text rendering.
@@ -14,4 +15,4 @@
14
15
  type RichComponents<T = unknown> = Record<string, (children: (string | T)[]) => T>;
15
16
  //#endregion
16
17
  export { RichComponents as t };
17
- //# sourceMappingURL=rich-CqNMP3tk.d.ts.map
18
+ //# sourceMappingURL=rich-BWszYAzS.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rich-BWszYAzS.d.ts","names":[],"sources":["../src/shared/rich.ts"],"mappings":";;;;;;;;;;;;;;KAiBY,eAAe,eAAe,gBAAgB,oBAAoB,SAAS"}
@@ -1,6 +1,5 @@
1
- import { t as RichComponents } from "../rich-CqNMP3tk.js";
1
+ import { t as RichComponents } from "../rich-BWszYAzS.js";
2
2
  import { a as TranslationMeta, i as TranslateFunction } from "../types-C98CcjtN.js";
3
-
4
3
  //#region src/server/translate.d.ts
5
4
  /**
6
5
  * Get the current locale from request context.
@@ -1 +1 @@
1
- {"version":3,"file":"translate.d.ts","names":[],"sources":["../../src/server/translate.ts"],"mappings":";;;;;;AAmCA;;iBAAgB,SAAA;;AAAS;AAYzB;;;;AAwCuB;cAxCV,CAAA,EAAG,iBAwCO;;;;;;;;;;;;;;;;;;;;iBAqBP,IAAA,cACd,GAAA,UACA,IAAA,GAAO,eAAA,uBACP,UAAA,GAAa,cAAA,CAAe,CAAA,eAC5B,MAAA,GAAS,MAAA,0CACE,CAAA"}
1
+ {"version":3,"file":"translate.d.ts","names":[],"sources":["../../src/server/translate.ts"],"mappings":";;;;;;;iBAmCgB;;;;;;;;cAYH,GAAG;;;;;;;;;;;;;;;;;;;;iBA6DA,KAAK,aACnB,aACA,OAAO,sCACP,aAAa,eAAe,gBAC5B,SAAS,gDACE"}
@@ -1,4 +1,4 @@
1
- import { r as i18n, t as getContext } from "../context-DLfoS-uR.js";
1
+ import { r as i18n, t as getContext } from "../context-BEQ6qqX5.js";
2
2
  import { r as formatMessageToParts, t as compileMessage } from "../compiler-CkOVGWU5.js";
3
3
  import { n as normalizeMeta, t as partsToNodes } from "../rich-CHisXE-A.js";
4
4
  //#region src/server/translate.ts
@@ -1 +1 @@
1
- {"version":3,"file":"types-Bo4jMK8g.d.ts","names":[],"sources":["../src/integration/types.ts"],"mappings":";;AAQA;;;;AAAiC;AAEjC;;KAFY,qBAAA;AAAA,UAEK,WAAA;EAKoB;;;;EAAnC,WAAA,GAAc,qBAAqB;AAAA"}
1
+ {"version":3,"file":"types-Bo4jMK8g.d.ts","names":[],"sources":["../src/integration/types.ts"],"mappings":";;;;;;;;;KAQY;UAEK;;;;;EAKf,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"types-C98CcjtN.d.ts","names":[],"sources":["../src/shared/types.ts"],"mappings":";;AAGA;;KAAY,WAAA;EACV,QAAA;EACA,WAAW;AAAA;;;;KAMD,eAAA;EACV,QAAA;EACA,SAAA,GAAY,MAAM,SAAS,WAAA;EAC3B,WAAA;AAAA;;AAAW;AAMb;KAAY,mBAAA,IAAuB,MAA4C,GAAnC,MAAM;;;AAA6B;KAKnE,oBAAA,GAAuB,MAAM,SAAS,mBAAA;;;;KAKtC,eAAA,GAAkB,MAAM;AAApC;;;AAAA,KAKY,eAAA;EACV,MAAA;EACA,MAAA,EAAQ,MAAA;EACR,YAAA,EAAc,MAAA;EACd,OAAA,EAAS,MAAA;AAAA;;;;;;;;;;;;;KAeC,iBAAA,IACV,GAAA,UACA,IAAA,EAAM,eAAA,WACN,MAAA,GAAS,MAAM"}
1
+ {"version":3,"file":"types-C98CcjtN.d.ts","names":[],"sources":["../src/shared/types.ts"],"mappings":";;;;KAGY;EACV;EACA;;;;;KAMU;EACV;EACA,YAAY,eAAe;EAC3B;;;;;KAMU,uBAAuB,SAAS;;;;KAKhC,uBAAuB,eAAe;;;;KAKtC,kBAAkB;;;;KAKlB;EACV;EACA,QAAQ;EACR,cAAc;EACd,SAAS;;;;;;;;;;;;;;KAeC,qBACV,aACA,MAAM,0BACN,SAAS"}
@@ -1,12 +1,12 @@
1
1
  import { a as TranslationMeta } from "./types-C98CcjtN.js";
2
-
3
2
  //#region src/extraction/types.d.ts
4
3
  /**
5
4
  * Deduplicated translation key with all file locations (used in manifest)
6
5
  */
7
6
  type ExtractedKey = {
8
7
  key: string;
9
- meta: TranslationMeta; /** All locations where this key is used (file:line format) */
8
+ meta: TranslationMeta;
9
+ /** All locations where this key is used (file:line format) */
10
10
  files: string[];
11
11
  };
12
12
  /**
@@ -28,4 +28,4 @@ type ExtractionManifest = {
28
28
  };
29
29
  //#endregion
30
30
  export { ExtractedKey as n, ExtractionManifest as r, ChunkManifest as t };
31
- //# sourceMappingURL=types-BfyoJsoB.d.ts.map
31
+ //# sourceMappingURL=types-CkqZWnXH.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-CkqZWnXH.d.ts","names":[],"sources":["../src/extraction/types.ts"],"mappings":";;;;;KA8BY;EACV;EACA,MAAM;;EAEN;;;;;KAMU,gBAAgB;;;;;KAMhB,kBAAkB;;;;KAKlB;EACV,MAAM;EACN,QAAQ;EACR,SAAS"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astroscope/i18n",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "i18n for Astro + React islands — MessageFormat 2, automatic tree-shaking, parallel loading, any translation source",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -90,18 +90,18 @@
90
90
  "messageformat": "^4.0.0"
91
91
  },
92
92
  "devDependencies": {
93
- "@babel/types": "^8.0.0",
93
+ "@babel/types": "^8.0.4",
94
94
  "@types/babel__core": "^7.20.5",
95
- "astro": "^7.0.3",
96
- "tsdown": "^0.22.3",
95
+ "astro": "^7.0.9",
96
+ "tsdown": "^0.22.8",
97
97
  "typescript": "^6.0.3",
98
- "vite": "^8.1.0",
99
- "@astroscope/node": "^1.3.0"
98
+ "vite": "^8.1.5",
99
+ "@astroscope/node": "^1.4.0"
100
100
  },
101
101
  "peerDependencies": {
102
102
  "astro": "^7.0.0",
103
103
  "vite": "^8.0.0",
104
- "@astroscope/node": "^1.3.0"
104
+ "@astroscope/node": "^1.4.0"
105
105
  },
106
106
  "scripts": {
107
107
  "build": "tsdown src/index.ts src/internal.ts src/extraction/index.ts src/server/translate.ts src/client/translate.ts src/client/directives/load.ts src/client/directives/idle.ts src/client/directives/visible.ts src/client/directives/media.ts src/client/directives/only.ts src/client/directives/utils.ts --format esm --dts --no-fixed-extension --deps.never-bundle astro --deps.never-bundle astro/client/load.js --deps.never-bundle astro/client/idle.js --deps.never-bundle astro/client/visible.js --deps.never-bundle astro/client/media.js --deps.never-bundle astro/client/only.js --deps.never-bundle virtual:@astroscope/i18n/manifest --deps.never-bundle @babel/core",
@@ -1 +0,0 @@
1
- {"version":3,"file":"context-DLfoS-uR.js","names":[],"sources":["../src/extraction/hash.ts","../src/server/utils.ts","../src/server/i18n.ts","../src/server/context.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport type { RawTranslations } from '../shared/types.js';\nimport type { ChunkManifest } from './types.js';\n\n/**\n * Hash a string to a short hash (for cache busting)\n */\nfunction hashString(str: string): string {\n return createHash('sha256').update(str).digest('hex').substring(0, 8);\n}\n\n/**\n * Compute hash for chunk translations\n */\nexport function computeChunkHash(translations: RawTranslations, keys: string[]): string {\n const relevantTranslations: RawTranslations = {};\n\n for (const key of [...keys].sort()) {\n if (translations[key] !== undefined) {\n relevantTranslations[key] = translations[key];\n }\n }\n\n return hashString(JSON.stringify(relevantTranslations));\n}\n\n/**\n * Compute hashes for all chunks in manifest\n */\nexport function computeAllChunkHashes(translations: RawTranslations, manifest: ChunkManifest): Record<string, string> {\n const hashes: Record<string, string> = {};\n\n for (const [chunkId, keys] of Object.entries(manifest)) {\n hashes[chunkId] = computeChunkHash(translations, keys);\n }\n\n return hashes;\n}\n","const LOWERCASE_A = 97;\n\n/**\n * Convert index to lowercase letter: 0→'a', 1→'b', ..., 25→'z'\n */\nfunction indexToLetter(index: number): string {\n return String.fromCharCode(LOWERCASE_A + index);\n}\n\n/**\n * Generate short variable name using bijective base-26: 0→'a', 25→'z', 26→'aa', 27→'ab', ...\n */\nexport function generateBB26(index: number): string {\n let name = '';\n let remaining = index;\n\n do {\n name = indexToLetter(remaining % 26) + name;\n remaining = Math.floor(remaining / 26) - 1;\n } while (remaining >= 0);\n\n return name;\n}\n","import { computeAllChunkHashes } from '../extraction/hash.js';\nimport { getGlobalState } from '../extraction/manifest.js';\nimport type { ExtractionManifest } from '../extraction/types.js';\nimport { compileTranslations } from '../shared/compiler.js';\nimport type { CompiledTranslations, RawTranslations } from '../shared/types.js';\nimport type { FallbackBehavior } from './types.js';\nimport { generateBB26 } from './utils.js';\n\nexport type I18nConfig = {\n locales: string[];\n defaultLocale?: string | undefined;\n fallback?: FallbackBehavior | undefined;\n};\n\ntype NormalizedConfig = {\n locales: string[];\n defaultLocale: string;\n fallback: FallbackBehavior;\n};\n\nclass I18nSingleton {\n // normalized user config with defaults applied\n private config: NormalizedConfig | null = null;\n\n // locale -> raw translation strings (before ICU compilation)\n private rawCache = new Map<string, RawTranslations>();\n\n // locale -> raw translations merged with manifest fallbacks\n private mergedCache = new Map<string, RawTranslations>();\n\n // locale -> compiled ICU MessageFormat functions\n private compiledCache = new Map<string, CompiledTranslations>();\n\n // locale -> chunk name -> content hash (for cache busting)\n private hashCache = new Map<string, Record<string, string>>();\n\n // locale -> inline script for I18nScript component\n private scriptCache = new Map<string, string>();\n\n // \"locale:chunkName\" -> encoded chunk response body\n private chunkCache = new Map<string, Uint8Array>();\n\n // manifest getter (set by init module, provides live data in dev mode)\n private manifestGetter: (() => ExtractionManifest) | null = null;\n\n // tracks the manifest version to detect when derived caches need invalidation\n private manifestVersion = 0;\n\n async configure(config: I18nConfig): Promise<void> {\n if (!config.locales?.length) {\n throw new Error('i18n.configure(): locales array is required and must not be empty');\n }\n\n for (const locale of config.locales) {\n if (!locale) {\n throw new Error('i18n.configure(): locale cannot be empty');\n }\n\n if (locale !== locale.trim()) {\n throw new Error(`i18n.configure(): locale \"${locale}\" has leading or trailing whitespace`);\n }\n }\n\n if (new Set(config.locales).size !== config.locales.length) {\n throw new Error('i18n.configure(): locales array contains duplicates');\n }\n\n if (config.defaultLocale !== undefined) {\n if (!config.defaultLocale) {\n throw new Error('i18n.configure(): defaultLocale cannot be empty');\n }\n\n if (config.defaultLocale !== config.defaultLocale.trim()) {\n throw new Error(`i18n.configure(): defaultLocale \"${config.defaultLocale}\" has leading or trailing whitespace`);\n }\n\n if (!config.locales.includes(config.defaultLocale)) {\n throw new Error(`i18n.configure(): defaultLocale \"${config.defaultLocale}\" is not in locales array`);\n }\n }\n\n this.config = {\n locales: config.locales,\n defaultLocale: config.defaultLocale ?? config.locales[0]!,\n fallback: config.fallback ?? 'fallback',\n };\n\n // dynamically import manifest getter from virtual module\n // this removes the need for a separate `import '@astroscope/i18n/init'`\n if (!this.manifestGetter) {\n const m = await import('virtual:@astroscope/i18n/manifest');\n this.manifestGetter = m.getManifest;\n }\n }\n\n isConfigured(): boolean {\n return this.config !== null;\n }\n\n getConfig(): NormalizedConfig {\n if (!this.config) {\n throw new Error('i18n not configured. Call i18n.configure() first.');\n }\n\n return this.config;\n }\n\n setTranslations(locale: string, raw: RawTranslations): void {\n this.rawCache.set(locale, raw);\n this.mergedCache.delete(locale); // invalidate merged cache\n this.compiledCache.delete(locale); // invalidate compiled cache\n this.hashCache.delete(locale); // invalidate hash cache\n this.scriptCache.delete(locale); // invalidate script cache\n\n // invalidate chunk cache entries for this locale\n for (const key of this.chunkCache.keys()) {\n if (key.startsWith(`${locale}:`)) {\n this.chunkCache.delete(key);\n }\n }\n\n // recompute hashes if chunk manifest exists (production only)\n const { chunks } = this.getManifest();\n\n if (Object.keys(chunks).length > 0) {\n this.hashCache.set(locale, computeAllChunkHashes(raw, chunks));\n }\n }\n\n getTranslations(locale: string): RawTranslations {\n this.invalidateIfManifestChanged();\n\n const cached = this.mergedCache.get(locale);\n\n if (cached) {\n return cached;\n }\n\n const raw = this.rawCache.get(locale) ?? {};\n const manifest = this.manifestGetter?.() ?? { keys: [], chunks: {}, imports: {} };\n\n if (manifest.keys.length === 0) {\n return raw;\n }\n\n // merge fallbacks for keys that don't have translations\n const withFallbacks: RawTranslations = { ...raw };\n\n for (const { key, meta } of manifest.keys) {\n if (!(key in withFallbacks) && meta.fallback) {\n withFallbacks[key] = meta.fallback;\n }\n }\n\n this.mergedCache.set(locale, withFallbacks);\n\n return withFallbacks;\n }\n\n getCompiledTranslations(locale: string): CompiledTranslations {\n const cached = this.compiledCache.get(locale);\n\n if (cached) {\n return cached;\n }\n\n const compiled = compileTranslations(locale, this.getTranslations(locale));\n\n this.compiledCache.set(locale, compiled);\n\n return compiled;\n }\n\n /**\n * Get the extraction manifest (keys + chunks).\n * - keys: translation keys extracted from codebase with metadata\n * - chunks: mapping of chunk names to their translation keys\n */\n getManifest(): ExtractionManifest {\n if (!this.manifestGetter) {\n throw new Error('i18n manifest not initialized. Call i18n.configure() first.');\n }\n\n return this.manifestGetter();\n }\n\n getHashes(locale: string): Record<string, string> {\n return this.hashCache.get(locale) ?? {};\n }\n\n /**\n * Get the encoded chunk response body for a locale/chunk combination.\n * Cached to avoid repeated JSON.stringify and encoding on each request.\n * Returns undefined if chunk not found in manifest.\n */\n getChunkBody(locale: string, chunkName: string): Uint8Array | undefined {\n const keys = this.getManifest().chunks[chunkName];\n\n if (!keys) {\n return undefined;\n }\n\n const cacheKey = `${locale}:${chunkName}`;\n const cached = this.chunkCache.get(cacheKey);\n\n if (cached) {\n return cached;\n }\n\n const translations = this.getTranslations(locale);\n const chunkTranslations: RawTranslations = {};\n\n for (const key of keys) {\n if (translations[key]) {\n chunkTranslations[key] = translations[key];\n }\n }\n\n const js = `/* @astroscope/i18n chunk: ${chunkName} */\n(function() {\n var i = window.__i18n__;\n if (i) Object.assign(i.translations, ${JSON.stringify(chunkTranslations)});\n})();\n`;\n\n const body = new TextEncoder().encode(js);\n\n this.chunkCache.set(cacheKey, body);\n\n return body;\n }\n\n /**\n * Get the inline script for I18nScript component.\n * Cached per locale, invalidated when translations change.\n */\n getClientScript(locale: string): string {\n const cached = this.scriptCache.get(locale);\n\n if (cached) {\n return cached;\n }\n\n const script = this.createClientScript(locale);\n\n this.scriptCache.set(locale, script);\n\n return script;\n }\n\n private createClientScript(locale: string): string {\n const { chunks, imports } = this.getManifest();\n const hasChunks = Object.keys(chunks).length > 0;\n\n if (!hasChunks) {\n const raw = this.getTranslations(locale);\n\n return `window.__i18n__=${JSON.stringify({ locale, hashes: {}, imports: {}, translations: raw })};`;\n }\n\n const hashes = this.getHashes(locale);\n\n // collect all unique chunk names used in hashes and imports\n const allChunks = new Set<string>(Object.keys(hashes));\n\n for (const deps of Object.values(imports)) {\n deps.forEach((d) => allChunks.add(d));\n }\n\n // generate short variable names: a, b, c, ..., z, aa, ab, ...\n const chunkToVar = new Map<string, string>();\n let varIndex = 0;\n\n for (const chunk of allChunks) {\n chunkToVar.set(chunk, generateBB26(varIndex++));\n }\n\n // build IIFE with aliases for compact output\n const varDecls = [...chunkToVar.entries()].map(([chunk, v]) => `${v}=${JSON.stringify(chunk)}`).join(',');\n\n const hashesObj = Object.entries(hashes)\n .map(([chunk, hash]) => `[${chunkToVar.get(chunk)}]:${JSON.stringify(hash)}`)\n .join(',');\n\n // only include imports that are in our chunk set (have translations for this locale)\n const importsObj = Object.entries(imports)\n .filter(([chunk]) => chunkToVar.has(chunk))\n .map(([chunk, deps]) => {\n const validDeps = deps.filter((d) => chunkToVar.has(d));\n\n return validDeps.length > 0\n ? `[${chunkToVar.get(chunk)}]:[${validDeps.map((d) => chunkToVar.get(d)).join(',')}]`\n : null;\n })\n .filter(Boolean)\n .join(',');\n\n return (\n `(()=>{var ${varDecls};` +\n `window.__i18n__={locale:${JSON.stringify(locale)},hashes:{${hashesObj}},imports:{${importsObj}},translations:{}};` +\n `})();`\n );\n }\n\n /**\n * Clear translations for specified locale(s).\n * @param locales - Locale(s) to clear, or all if not specified\n */\n clear(locales?: string | string[] | undefined): void {\n const targets = this.resolveLocales(locales);\n\n for (const locale of targets) {\n this.rawCache.delete(locale);\n this.mergedCache.delete(locale);\n this.compiledCache.delete(locale);\n this.hashCache.delete(locale);\n this.scriptCache.delete(locale);\n\n // clear chunk cache entries for this locale\n for (const key of this.chunkCache.keys()) {\n if (key.startsWith(`${locale}:`)) {\n this.chunkCache.delete(key);\n }\n }\n }\n }\n\n /**\n * invalidate derived caches when the extraction manifest has changed (dev mode HMR)\n */\n private invalidateIfManifestChanged(): void {\n const { version } = getGlobalState();\n\n if (version === this.manifestVersion) {\n return;\n }\n\n this.manifestVersion = version;\n this.mergedCache.clear();\n this.compiledCache.clear();\n this.scriptCache.clear();\n this.chunkCache.clear();\n }\n\n private resolveLocales(locales?: string | string[] | undefined): string[] {\n if (!locales) {\n return this.config?.locales ?? [];\n }\n\n if (typeof locales === 'string') {\n return [locales];\n }\n\n return locales;\n }\n}\n\nexport const i18n = new I18nSingleton();\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { I18nContext } from './types.js';\n\nconst als = new AsyncLocalStorage<I18nContext>();\n\n/**\n * Run a function with i18n context (called by middleware)\n */\nexport function runWithContext<T>(context: I18nContext, fn: () => T): T {\n return als.run(context, fn);\n}\n\n/**\n * Get the current i18n context\n */\nexport function getContext(): I18nContext | null {\n return als.getStore() ?? null;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"i18n-DzmH9JmE.d.ts","names":[],"sources":["../src/server/types.ts","../src/server/i18n.ts"],"mappings":";;;;;;;KAKY,gBAAA,oCACuB,GAAA,UAAa,IAAA,GAAO,eAAe;;;;KAK1D,WAAA;EACV,MAAA;EAEA,YAAA,EAAc,oBAAA;EAEd,eAAA,EAAiB,eAAA;EACjB,QAAA,EAAU,gBAAA;AAAA;;;KCTA,UAAA;EACV,OAAA;EACA,aAAA;EACA,QAAA,GAAW,gBAAgB;AAAA;AAAA,KAGxB,gBAAA;EACH,OAAA;EACA,aAAA;EACA,QAAA,EAAU,gBAAgB;AAAA;AAAA,cAGtB,aAAA;EAAA,QAEI,MAAA;EAAA,QAGA,QAAA;EAAA,QAGA,WAAA;EAAA,QAGA,aAAA;EAAA,QAGA,SAAA;EAAA,QAGA,WAAA;EAAA,QAGA,UAAA;EAAA,QAGA,cAAA;EAAA,QAGA,eAAA;EAEF,SAAA,CAAU,MAAA,EAAQ,UAAA,GAAa,OAAA;EA+CrC,YAAA;EAIA,SAAA,IAAa,gBAAA;EAQb,eAAA,CAAgB,MAAA,UAAgB,GAAA,EAAK,eAAA;EAsBrC,eAAA,CAAgB,MAAA,WAAiB,eAAA;EA8BjC,uBAAA,CAAwB,MAAA,WAAiB,oBAAA;ED9If;;;;ACT5B;EA0KE,WAAA,IAAe,kBAAA;EAQf,SAAA,CAAU,MAAA,WAAiB,MAAA;EA/KA;;;;;EAwL3B,YAAA,CAAa,MAAA,UAAgB,SAAA,WAAoB,UAAA;EAxLtB;AAC3B;;;EAgOA,eAAA,CAAgB,MAAA;EAAA,QAcR,kBAAA;EA1OR;;;;EAoSA,KAAA,CAAM,OAAA;EAhSF;;;EAAA,QAsTI,2BAAA;EAAA,QAcA,cAAA;AAAA;AAAA,cAaG,IAAA,EAAI,aAAsB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"rich-CqNMP3tk.d.ts","names":[],"sources":["../src/shared/rich.ts"],"mappings":";;AAiBA;;;;;;;;;;;KAAY,cAAA,gBAA8B,MAAA,UAAgB,QAAA,YAAoB,CAAA,QAAS,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-BfyoJsoB.d.ts","names":[],"sources":["../src/extraction/types.ts"],"mappings":";;;;;;KA8BY,YAAA;EACV,GAAA;EACA,IAAA,EAAM,eAAe,EAsBG;EApBxB,KAAA;AAAA;;;;KAMU,aAAA,GAAgB,MAAM;;AAcR;;;KARd,eAAA,GAAkB,MAAM;;;;KAKxB,kBAAA;EACV,IAAA,EAAM,YAAA;EACN,MAAA,EAAQ,aAAA;EACR,OAAA,EAAS,eAAA;AAAA"}