experimental-ciao-react 1.1.9 → 1.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +6 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -4
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -281,7 +281,6 @@ const useTranslationStore = (0, zustand.create)()((0, zustand_middleware.persist
|
|
|
281
281
|
isHydrated: false,
|
|
282
282
|
serverVersion: null,
|
|
283
283
|
lastVersionCheck: null,
|
|
284
|
-
cachedLanguages: [],
|
|
285
284
|
setLanguage: (language) => {
|
|
286
285
|
set({
|
|
287
286
|
currentLanguage: language,
|
|
@@ -326,16 +325,12 @@ const useTranslationStore = (0, zustand.create)()((0, zustand_middleware.persist
|
|
|
326
325
|
serverVersion: version,
|
|
327
326
|
lastVersionCheck: Date.now()
|
|
328
327
|
});
|
|
329
|
-
},
|
|
330
|
-
setCachedLanguages: (languages) => {
|
|
331
|
-
set({ cachedLanguages: languages });
|
|
332
328
|
}
|
|
333
329
|
}), {
|
|
334
330
|
name: "ciao-tools-language",
|
|
335
331
|
partialize: (state) => ({
|
|
336
332
|
currentLanguage: state.currentLanguage,
|
|
337
|
-
serverVersion: state.serverVersion
|
|
338
|
-
cachedLanguages: state.cachedLanguages
|
|
333
|
+
serverVersion: state.serverVersion
|
|
339
334
|
}),
|
|
340
335
|
onRehydrateStorage: () => (_, error) => {
|
|
341
336
|
if (!error && hydrationResolver) hydrationResolver();
|
|
@@ -374,7 +369,7 @@ async function fetchTranslations(url) {
|
|
|
374
369
|
function useHotUpdates(config, projectId) {
|
|
375
370
|
const isCheckingRef = (0, react.useRef)(false);
|
|
376
371
|
const hasCheckedOnMountRef = (0, react.useRef)(false);
|
|
377
|
-
const { serverVersion, setServerVersion, addLanguage
|
|
372
|
+
const { serverVersion, setServerVersion, addLanguage } = useTranslationStore();
|
|
378
373
|
const checkForUpdates = (0, react.useCallback)(async () => {
|
|
379
374
|
if (!config || !projectId || isCheckingRef.current) return;
|
|
380
375
|
if (config.enabled !== true) return;
|
|
@@ -389,12 +384,11 @@ function useHotUpdates(config, projectId) {
|
|
|
389
384
|
console.log("[ciao-tools] Found latest.json, version:", manifest.version);
|
|
390
385
|
const isFirstCheck = serverVersion === null;
|
|
391
386
|
const hasNewVersion = serverVersion !== null && manifest.version > serverVersion;
|
|
392
|
-
|
|
393
|
-
if (isFirstCheck || hasNewVersion || hasNoCache) {
|
|
387
|
+
if (isFirstCheck || hasNewVersion) {
|
|
394
388
|
if (Object.keys(manifest.urls).length > 0) {
|
|
395
|
-
const reason = hasNewVersion ? "new version" :
|
|
389
|
+
const reason = hasNewVersion ? "new version" : "first check";
|
|
396
390
|
console.log(`[ciao-tools] Fetching translations (${reason})...`);
|
|
397
|
-
await clearCache(projectId);
|
|
391
|
+
if (hasNewVersion) await clearCache(projectId);
|
|
398
392
|
const updatedLanguages = [];
|
|
399
393
|
for (const [langCode, url] of Object.entries(manifest.urls)) try {
|
|
400
394
|
const translations = await fetchTranslations(url);
|
|
@@ -405,7 +399,6 @@ function useHotUpdates(config, projectId) {
|
|
|
405
399
|
console.error(`[ciao-tools] Failed to fetch ${langCode} translations:`, err);
|
|
406
400
|
}
|
|
407
401
|
if (updatedLanguages.length > 0) {
|
|
408
|
-
setCachedLanguages(updatedLanguages);
|
|
409
402
|
console.log("[ciao-tools] Updated translations for:", updatedLanguages);
|
|
410
403
|
if (hasNewVersion && config.onTranslationsUpdated) config.onTranslationsUpdated(updatedLanguages);
|
|
411
404
|
}
|
|
@@ -422,9 +415,7 @@ function useHotUpdates(config, projectId) {
|
|
|
422
415
|
projectId,
|
|
423
416
|
serverVersion,
|
|
424
417
|
setServerVersion,
|
|
425
|
-
addLanguage
|
|
426
|
-
cachedLanguages,
|
|
427
|
-
setCachedLanguages
|
|
418
|
+
addLanguage
|
|
428
419
|
]);
|
|
429
420
|
(0, react.useEffect)(() => {
|
|
430
421
|
if (!config || !projectId) return;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["dbPromise: Promise<IDBDatabase> | null","entry: CacheEntry","options: Intl.DateTimeFormatOptions","result: string","key: string","format: string | undefined","hydrationResolver: (() => void) | null","updatedLanguages: string[]","LANGUAGE_DATA: Record<\n\tstring,\n\t{ name: string; nativeName: string; flag: string }\n>","values: InterpolationValues | undefined","elements: ReactElement[]","result: ReactNode[]","match: RegExpExecArray | null","translated: string"],"sources":["../src/components/CTContextBlock.tsx","../src/cache.ts","../src/interpolate.ts","../src/store.ts","../src/hooks/useHotUpdates.ts","../src/components/CTProvider.tsx","../src/components/LanguageSwitcher.tsx","../src/hooks/useCt.ts","../src/components/Trans.tsx","../src/hooks/useLanguage.ts"],"sourcesContent":["import React from \"react\";\nimport type { CTContextBlockProps } from \"../types\";\n\nexport function CTContextBlock({ children }: CTContextBlockProps) {\n\treturn <>{children}</>;\n}\n","import type { TranslationMap } from \"./types\";\n\nconst DB_NAME = \"ciao-tools-translations\";\nconst DB_VERSION = 1;\nconst STORE_NAME = \"translations\";\n\ninterface CacheEntry {\n\tlanguage: string;\n\tprojectId: string;\n\tdata: TranslationMap;\n\turl: string;\n\tcachedAt: number;\n}\n\nlet dbPromise: Promise<IDBDatabase> | null = null;\n\nfunction openDB(): Promise<IDBDatabase> {\n\tif (dbPromise) return dbPromise;\n\n\tdbPromise = new Promise((resolve, reject) => {\n\t\tif (typeof indexedDB === \"undefined\") {\n\t\t\treject(new Error(\"IndexedDB not available\"));\n\t\t\treturn;\n\t\t}\n\n\t\tconst request = indexedDB.open(DB_NAME, DB_VERSION);\n\n\t\trequest.onerror = () => reject(request.error);\n\t\trequest.onsuccess = () => resolve(request.result);\n\n\t\trequest.onupgradeneeded = (event) => {\n\t\t\tconst db = (event.target as IDBOpenDBRequest).result;\n\t\t\tif (!db.objectStoreNames.contains(STORE_NAME)) {\n\t\t\t\tconst store = db.createObjectStore(STORE_NAME, { keyPath: \"url\" });\n\t\t\t\tstore.createIndex(\"language\", \"language\", { unique: false });\n\t\t\t\tstore.createIndex(\"projectId\", \"projectId\", { unique: false });\n\t\t\t}\n\t\t};\n\t});\n\n\treturn dbPromise;\n}\n\nexport async function getCachedTranslation(\n\turl: string,\n): Promise<TranslationMap | null> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readonly\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\t\t\tconst request = store.get(url);\n\n\t\t\trequest.onerror = () => reject(request.error);\n\t\t\trequest.onsuccess = () => {\n\t\t\t\tconst entry = request.result as CacheEntry | undefined;\n\t\t\t\tresolve(entry?.data ?? null);\n\t\t\t};\n\t\t});\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function cacheTranslation(\n\turl: string,\n\tlanguage: string,\n\tprojectId: string,\n\tdata: TranslationMap,\n): Promise<void> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readwrite\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\n\t\t\tconst entry: CacheEntry = {\n\t\t\t\turl,\n\t\t\t\tlanguage,\n\t\t\t\tprojectId,\n\t\t\t\tdata,\n\t\t\t\tcachedAt: Date.now(),\n\t\t\t};\n\n\t\t\tconst request = store.put(entry);\n\t\t\trequest.onerror = () => reject(request.error);\n\t\t\trequest.onsuccess = () => resolve();\n\t\t});\n\t} catch {\n\t\t// Silently fail - caching is optional\n\t}\n}\n\nexport async function clearCache(projectId?: string): Promise<void> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readwrite\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\n\t\t\tif (projectId) {\n\t\t\t\tconst index = store.index(\"projectId\");\n\t\t\t\tconst request = index.openCursor(IDBKeyRange.only(projectId));\n\t\t\t\trequest.onsuccess = (event) => {\n\t\t\t\t\tconst cursor = (event.target as IDBRequest).result;\n\t\t\t\t\tif (cursor) {\n\t\t\t\t\t\tcursor.delete();\n\t\t\t\t\t\tcursor.continue();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\ttransaction.oncomplete = () => resolve();\n\t\t\t\ttransaction.onerror = () => reject(transaction.error);\n\t\t\t} else {\n\t\t\t\tconst request = store.clear();\n\t\t\t\trequest.onerror = () => reject(request.error);\n\t\t\t\trequest.onsuccess = () => resolve();\n\t\t\t}\n\t\t});\n\t} catch {\n\t\t// Silently fail\n\t}\n}\n\nexport async function getCacheStats(): Promise<{\n\tcount: number;\n\tlanguages: string[];\n}> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readonly\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\n\t\t\tconst countRequest = store.count();\n\t\t\tconst languages = new Set<string>();\n\n\t\t\tconst cursorRequest = store.openCursor();\n\t\t\tcursorRequest.onsuccess = (event) => {\n\t\t\t\tconst cursor = (event.target as IDBRequest).result;\n\t\t\t\tif (cursor) {\n\t\t\t\t\tlanguages.add((cursor.value as CacheEntry).language);\n\t\t\t\t\tcursor.continue();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\ttransaction.oncomplete = () => {\n\t\t\t\tresolve({\n\t\t\t\t\tcount: countRequest.result,\n\t\t\t\t\tlanguages: Array.from(languages),\n\t\t\t\t});\n\t\t\t};\n\t\t\ttransaction.onerror = () => reject(transaction.error);\n\t\t});\n\t} catch {\n\t\treturn { count: 0, languages: [] };\n\t}\n}\n","export type InterpolationValues = Record<string, unknown>;\n\nconst numberFormatCache = new Map<string, Intl.NumberFormat>();\nconst dateFormatCache = new Map<string, Intl.DateTimeFormat>();\nconst pluralRulesCache = new Map<string, Intl.PluralRules>();\n\nexport function clearFormatterCache(): void {\n\tnumberFormatCache.clear();\n\tdateFormatCache.clear();\n\tpluralRulesCache.clear();\n}\n\nfunction getNumberFormatter(locale: string): Intl.NumberFormat {\n\tconst key = `number:${locale}`;\n\tif (!numberFormatCache.has(key)) {\n\t\tnumberFormatCache.set(\n\t\t\tkey,\n\t\t\tnew Intl.NumberFormat(locale, {\n\t\t\t\tmaximumFractionDigits: 20,\n\t\t\t}),\n\t\t);\n\t}\n\treturn numberFormatCache.get(key)!;\n}\n\nfunction getCurrencyFormatter(\n\tlocale: string,\n\tcurrency: string,\n): Intl.NumberFormat {\n\tconst key = `currency:${locale}:${currency}`;\n\tif (!numberFormatCache.has(key)) {\n\t\tnumberFormatCache.set(\n\t\t\tkey,\n\t\t\tnew Intl.NumberFormat(locale, {\n\t\t\t\tstyle: \"currency\",\n\t\t\t\tcurrency,\n\t\t\t}),\n\t\t);\n\t}\n\treturn numberFormatCache.get(key)!;\n}\n\nfunction getPercentFormatter(locale: string): Intl.NumberFormat {\n\tconst key = `percent:${locale}`;\n\tif (!numberFormatCache.has(key)) {\n\t\tnumberFormatCache.set(\n\t\t\tkey,\n\t\t\tnew Intl.NumberFormat(locale, {\n\t\t\t\tstyle: \"percent\",\n\t\t\t\tminimumFractionDigits: 0,\n\t\t\t\tmaximumFractionDigits: 2,\n\t\t\t}),\n\t\t);\n\t}\n\treturn numberFormatCache.get(key)!;\n}\n\nfunction getDateFormatter(\n\tlocale: string,\n\tstyle: \"short\" | \"medium\" | \"long\" | \"full\",\n): Intl.DateTimeFormat {\n\tconst key = `date:${locale}:${style}`;\n\tif (!dateFormatCache.has(key)) {\n\t\tconst options: Intl.DateTimeFormatOptions = {\n\t\t\tdateStyle: style,\n\t\t};\n\t\tdateFormatCache.set(key, new Intl.DateTimeFormat(locale, options));\n\t}\n\treturn dateFormatCache.get(key)!;\n}\n\nfunction getTimeFormatter(\n\tlocale: string,\n\tstyle: \"short\" | \"medium\" | \"long\" | \"full\",\n): Intl.DateTimeFormat {\n\tconst key = `time:${locale}:${style}`;\n\tif (!dateFormatCache.has(key)) {\n\t\tconst options: Intl.DateTimeFormatOptions = {\n\t\t\ttimeStyle: style,\n\t\t};\n\t\tdateFormatCache.set(key, new Intl.DateTimeFormat(locale, options));\n\t}\n\treturn dateFormatCache.get(key)!;\n}\n\nfunction getPluralRules(locale: string): Intl.PluralRules {\n\tif (!pluralRulesCache.has(locale)) {\n\t\tpluralRulesCache.set(locale, new Intl.PluralRules(locale));\n\t}\n\treturn pluralRulesCache.get(locale)!;\n}\n\nfunction formatValue(\n\tvalue: unknown,\n\tformat: string | undefined,\n\tlocale: string,\n): string {\n\tif (value === null || value === undefined) {\n\t\treturn \"\";\n\t}\n\n\tif (!format) {\n\t\treturn String(value);\n\t}\n\n\tconst parts = format.split(\":\");\n\tconst formatType = parts[0];\n\n\tswitch (formatType) {\n\t\tcase \"number\": {\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tif (Number.isNaN(num)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn getNumberFormatter(locale).format(num);\n\t\t}\n\n\t\tcase \"currency\": {\n\t\t\tconst currency = parts[1];\n\t\t\tif (!currency) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tif (Number.isNaN(num)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn getCurrencyFormatter(locale, currency).format(num);\n\t\t}\n\n\t\tcase \"percent\": {\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tif (Number.isNaN(num)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn getPercentFormatter(locale).format(num);\n\t\t}\n\n\t\tcase \"date\": {\n\t\t\tif (!(value instanceof Date)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst style =\n\t\t\t\t(parts[1] as \"short\" | \"medium\" | \"long\" | \"full\") || \"medium\";\n\t\t\treturn getDateFormatter(locale, style).format(value);\n\t\t}\n\n\t\tcase \"time\": {\n\t\t\tif (!(value instanceof Date)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst style =\n\t\t\t\t(parts[1] as \"short\" | \"medium\" | \"long\" | \"full\") || \"medium\";\n\t\t\treturn getTimeFormatter(locale, style).format(value);\n\t\t}\n\n\t\tcase \"plural\": {\n\t\t\tconst singular = parts[1];\n\t\t\tconst plural = parts[2];\n\t\t\tif (!singular || !plural) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tconst rules = getPluralRules(locale);\n\t\t\tconst category = rules.select(num);\n\t\t\treturn category === \"one\" ? singular : plural;\n\t\t}\n\n\t\tdefault:\n\t\t\treturn String(value);\n\t}\n}\n\nexport function interpolate(\n\ttext: string,\n\tvalues: InterpolationValues | undefined,\n\tlocale: string,\n): string {\n\t// Temporarily replace escaped braces with placeholder characters\n\tconst escaped = text.replace(/\\{\\{/g, \"\\x00\").replace(/\\}\\}/g, \"\\x01\");\n\n\tlet result: string;\n\tif (!values || Object.keys(values).length === 0) {\n\t\tresult = escaped;\n\t} else {\n\t\tresult = escaped.replace(/\\{([^}]+)\\}/g, (match, placeholder) => {\n\t\t\tconst trimmed = placeholder.trim();\n\t\t\tconst colonIndex = trimmed.indexOf(\":\");\n\n\t\t\tlet key: string;\n\t\t\tlet format: string | undefined;\n\n\t\t\tif (colonIndex === -1) {\n\t\t\t\tkey = trimmed;\n\t\t\t\tformat = undefined;\n\t\t\t} else {\n\t\t\t\tkey = trimmed.substring(0, colonIndex);\n\t\t\t\tformat = trimmed.substring(colonIndex + 1);\n\t\t\t}\n\n\t\t\tif (!(key in values)) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tconst value = values[key];\n\t\t\treturn formatValue(value, format, locale);\n\t\t});\n\t}\n\n\t// Restore escaped braces\n\treturn result.replace(/\\x00/g, \"{\").replace(/\\x01/g, \"}\");\n}\n","import { create } from \"zustand\";\nimport { persist } from \"zustand/middleware\";\nimport { interpolate } from \"./interpolate\";\nimport type {\n\tInterpolationValues,\n\tLanguageTranslations,\n\tTranslationMap,\n\tTranslationStore,\n} from \"./types\";\n\nlet hydrationResolver: (() => void) | null = null;\nconst hydrationPromise = new Promise<void>((resolve) => {\n\thydrationResolver = resolve;\n});\n\nexport const useTranslationStore = create<TranslationStore>()(\n\tpersist(\n\t\t(set) => ({\n\t\t\tcurrentLanguage: \"en\",\n\t\t\tdefaultLanguage: \"en\",\n\t\t\tavailableLanguages: [\"en\"],\n\t\t\ttranslations: {},\n\t\t\tisLoading: false,\n\t\t\tisReady: false,\n\t\t\tisHydrated: false,\n\t\t\tserverVersion: null,\n\t\t\tlastVersionCheck: null,\n\t\t\tcachedLanguages: [],\n\n\t\t\tsetLanguage: (language: string) => {\n\t\t\t\tset({ currentLanguage: language, isReady: false });\n\t\t\t},\n\n\t\t\tloadTranslations: (translations: LanguageTranslations) => {\n\t\t\t\tset((state) => {\n\t\t\t\t\tconst languages = Object.keys(translations);\n\t\t\t\t\tconst availableLanguages = [\n\t\t\t\t\t\t...new Set([...state.availableLanguages, ...languages]),\n\t\t\t\t\t];\n\t\t\t\t\tconst merged = { ...state.translations };\n\t\t\t\t\tfor (const lang of languages) {\n\t\t\t\t\t\tmerged[lang] = { ...merged[lang], ...translations[lang] };\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttranslations: merged,\n\t\t\t\t\t\tavailableLanguages,\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t},\n\n\t\t\taddLanguage: (language: string, translations: TranslationMap) => {\n\t\t\t\tset((state) => ({\n\t\t\t\t\ttranslations: {\n\t\t\t\t\t\t...state.translations,\n\t\t\t\t\t\t[language]: { ...state.translations[language], ...translations },\n\t\t\t\t\t},\n\t\t\t\t\tavailableLanguages: state.availableLanguages.includes(language)\n\t\t\t\t\t\t? state.availableLanguages\n\t\t\t\t\t\t: [...state.availableLanguages, language],\n\t\t\t\t}));\n\t\t\t},\n\n\t\t\tsetLoading: (loading: boolean) => {\n\t\t\t\tset({ isLoading: loading });\n\t\t\t},\n\n\t\t\tsetReady: (ready: boolean) => {\n\t\t\t\tset({ isReady: ready });\n\t\t\t},\n\n\t\t\tsetServerVersion: (version: number) => {\n\t\t\t\tset({ serverVersion: version, lastVersionCheck: Date.now() });\n\t\t\t},\n\n\t\t\tsetCachedLanguages: (languages: string[]) => {\n\t\t\t\tset({ cachedLanguages: languages });\n\t\t\t},\n\t\t}),\n\t\t{\n\t\t\tname: \"ciao-tools-language\",\n\t\t\tpartialize: (state) => ({\n\t\t\t\tcurrentLanguage: state.currentLanguage,\n\t\t\t\tserverVersion: state.serverVersion,\n\t\t\t\tcachedLanguages: state.cachedLanguages,\n\t\t\t}),\n\t\t\tonRehydrateStorage: () => (_, error) => {\n\t\t\t\tif (!error && hydrationResolver) {\n\t\t\t\t\thydrationResolver();\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t),\n);\n\nhydrationPromise.then(() => {\n\tuseTranslationStore.setState({ isHydrated: true });\n});\n\nexport function getTranslation(\n\ttranslations: LanguageTranslations,\n\tlanguage: string,\n\ttext: string,\n\tvalues?: InterpolationValues,\n): string {\n\tconst translated = translations[language]?.[text] ?? text;\n\n\tif (!values || Object.keys(values).length === 0) {\n\t\treturn translated;\n\t}\n\n\treturn interpolate(translated, values, language);\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { clearCache, cacheTranslation } from \"../cache\";\nimport { useTranslationStore } from \"../store\";\nimport type { HotUpdateConfig, TranslationMap } from \"../types\";\n\nconst CDN_BASE_URL = \"https://t1.ciao-tools.com\";\n\ninterface LatestManifest {\n\tversion: number;\n\tupdatedAt: string;\n\turls: Record<string, string>;\n}\n\nasync function fetchLatestManifest(projectId: string): Promise<LatestManifest | null> {\n\tconst url = `${CDN_BASE_URL}/translations/${projectId}/latest.json`;\n\ttry {\n\t\tconst response = await fetch(url, { cache: \"no-cache\" });\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 404) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tthrow new Error(`Failed to fetch latest manifest: ${response.statusText}`);\n\t\t}\n\t\treturn response.json();\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function fetchTranslations(url: string): Promise<TranslationMap> {\n\tconst response = await fetch(url);\n\tif (!response.ok) {\n\t\tthrow new Error(`Failed to fetch translations: ${response.statusText}`);\n\t}\n\treturn response.json();\n}\n\nexport function useHotUpdates(\n\tconfig: HotUpdateConfig | undefined,\n\tprojectId: string | undefined,\n) {\n\tconst isCheckingRef = useRef(false);\n\tconst hasCheckedOnMountRef = useRef(false);\n\n\tconst { serverVersion, setServerVersion, addLanguage, cachedLanguages, setCachedLanguages } = useTranslationStore();\n\n\tconst checkForUpdates = useCallback(async () => {\n\t\tif (!config || !projectId || isCheckingRef.current) return;\n\t\tif (config.enabled !== true) return;\n\n\t\tisCheckingRef.current = true;\n\n\t\ttry {\n\t\t\tconsole.log(\"[ciao-tools] Checking for hot updates...\");\n\t\t\tconst manifest = await fetchLatestManifest(projectId);\n\n\t\t\tif (!manifest) {\n\t\t\t\tconsole.log(\"[ciao-tools] No latest.json found (project may not have hot updates yet)\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconsole.log(\"[ciao-tools] Found latest.json, version:\", manifest.version);\n\n\t\t\tconst isFirstCheck = serverVersion === null;\n\t\t\tconst hasNewVersion = serverVersion !== null && manifest.version > serverVersion;\n\t\t\tconst hasNoCache = cachedLanguages.length === 0;\n\n\t\t\tif (isFirstCheck || hasNewVersion || hasNoCache) {\n\t\t\t\tif (Object.keys(manifest.urls).length > 0) {\n\t\t\t\t\tconst reason = hasNewVersion ? \"new version\" : hasNoCache ? \"no cached translations\" : \"first check\";\n\t\t\t\t\tconsole.log(`[ciao-tools] Fetching translations (${reason})...`);\n\t\t\t\t\tawait clearCache(projectId);\n\n\t\t\t\t\tconst updatedLanguages: string[] = [];\n\n\t\t\t\t\tfor (const [langCode, url] of Object.entries(manifest.urls)) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst translations = await fetchTranslations(url);\n\t\t\t\t\t\t\taddLanguage(langCode, translations);\n\t\t\t\t\t\t\tawait cacheTranslation(url, langCode, projectId, translations);\n\t\t\t\t\t\t\tupdatedLanguages.push(langCode);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tconsole.error(`[ciao-tools] Failed to fetch ${langCode} translations:`, err);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (updatedLanguages.length > 0) {\n\t\t\t\t\t\tsetCachedLanguages(updatedLanguages);\n\t\t\t\t\t\tconsole.log(\"[ciao-tools] Updated translations for:\", updatedLanguages);\n\t\t\t\t\t\tif (hasNewVersion && config.onTranslationsUpdated) {\n\t\t\t\t\t\t\tconfig.onTranslationsUpdated(updatedLanguages);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconsole.log(\"[ciao-tools] Already up to date (version \" + manifest.version + \")\");\n\t\t\t}\n\n\t\t\tsetServerVersion(manifest.version);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"[ciao-tools] Hot update check failed:\", error);\n\t\t} finally {\n\t\t\tisCheckingRef.current = false;\n\t\t}\n\t}, [config, projectId, serverVersion, setServerVersion, addLanguage, cachedLanguages, setCachedLanguages]);\n\n\tuseEffect(() => {\n\t\tif (!config || !projectId) return;\n\t\tif (config.enabled !== true) return;\n\n\t\tif (!hasCheckedOnMountRef.current) {\n\t\t\thasCheckedOnMountRef.current = true;\n\t\t\tcheckForUpdates();\n\t\t}\n\n\t\tconst handleVisibilityChange = () => {\n\t\t\tif (document.visibilityState === \"visible\") {\n\t\t\t\tcheckForUpdates();\n\t\t\t}\n\t\t};\n\n\t\tdocument.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n\t\t};\n\t}, [config, projectId, checkForUpdates]);\n\n\treturn { checkForUpdates };\n}\n","import React, { useCallback, useEffect, useRef, type ReactNode } from \"react\";\nimport { getCachedTranslation, cacheTranslation } from \"../cache\";\nimport { useTranslationStore } from \"../store\";\nimport { useHotUpdates } from \"../hooks/useHotUpdates\";\nimport type { CiaoManifest, CTProviderProps, TranslationMap } from \"../types\";\n\nconst PRELOAD_DELAY_MS = 5000;\n\nasync function fetchTranslationsFromCDN(url: string): Promise<TranslationMap> {\n\tconst response = await fetch(url);\n\tif (!response.ok) {\n\t\tthrow new Error(`Failed to fetch translations: ${response.statusText}`);\n\t}\n\treturn response.json();\n}\n\nfunction detectBrowserLanguage(availableLanguages: string[]): string | null {\n\tif (typeof navigator === \"undefined\") return null;\n\n\tconst browserLangs = navigator.languages || [navigator.language];\n\n\tfor (const browserLang of browserLangs) {\n\t\tconst normalized = browserLang.toLowerCase();\n\t\tif (availableLanguages.includes(normalized)) {\n\t\t\treturn normalized;\n\t\t}\n\t\tconst langCode = normalized.split(\"-\")[0];\n\t\tif (availableLanguages.includes(langCode)) {\n\t\t\treturn langCode;\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction getManifestUrlsHash(manifest: CiaoManifest | undefined): string {\n\tif (!manifest) return \"\";\n\treturn JSON.stringify(manifest.cdnUrls);\n}\n\nexport function CTProvider({\n\tchildren,\n\ttranslations,\n\tmanifest,\n\tdefaultLanguage = \"en\",\n\tavailableLanguages,\n\tonLanguageChange,\n\tdetectLanguage = true,\n\tblockUntilReady = true,\n\tfallback = null,\n\tpreloadLanguages = true,\n\tpreloadDelay = PRELOAD_DELAY_MS,\n\thotUpdates,\n}: CTProviderProps) {\n\tconst {\n\t\tloadTranslations,\n\t\tsetLanguage,\n\t\taddLanguage,\n\t\tsetLoading,\n\t\tsetReady,\n\t\tcurrentLanguage,\n\t\ttranslations: storeTranslations,\n\t\tisReady,\n\t\tisHydrated,\n\t} = useTranslationStore();\n\n\tconst manifestRef = useRef<CiaoManifest | undefined>(manifest);\n\tconst loadedUrlsRef = useRef<Map<string, string>>(new Map());\n\tconst previousManifestHashRef = useRef<string>(\"\");\n\tconst initializedRef = useRef(false);\n\tconst preloadTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n\tuseEffect(() => {\n\t\tmanifestRef.current = manifest;\n\n\t\tconst newHash = getManifestUrlsHash(manifest);\n\t\tconst oldHash = previousManifestHashRef.current;\n\n\t\tif (oldHash && newHash && oldHash !== newHash) {\n\t\t\tloadedUrlsRef.current.clear();\n\t\t\tuseTranslationStore.setState({ translations: {} });\n\t\t}\n\n\t\tpreviousManifestHashRef.current = newHash;\n\t}, [manifest]);\n\n\tuseEffect(() => {\n\t\tif (translations) {\n\t\t\tloadTranslations(translations);\n\t\t\tsetReady(true);\n\t\t}\n\t}, [translations, loadTranslations, setReady]);\n\n\tuseEffect(() => {\n\t\tif (!isHydrated) return;\n\t\tif (initializedRef.current) return;\n\t\tinitializedRef.current = true;\n\n\t\tconst store = useTranslationStore.getState();\n\t\tconst effectiveLanguages = manifest\n\t\t\t? [...manifest.languages]\n\t\t\t: availableLanguages || [];\n\n\t\tconst hasPersistedLanguage =\n\t\t\tstore.currentLanguage &&\n\t\t\tstore.currentLanguage !== \"en\" &&\n\t\t\teffectiveLanguages.includes(store.currentLanguage);\n\n\t\tif (hasPersistedLanguage) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (detectLanguage && effectiveLanguages.length > 0) {\n\t\t\tconst detected = detectBrowserLanguage(effectiveLanguages);\n\t\t\tif (detected) {\n\t\t\t\tsetLanguage(detected);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (defaultLanguage && defaultLanguage !== store.currentLanguage) {\n\t\t\tsetLanguage(defaultLanguage);\n\t\t}\n\t}, [\n\t\tmanifest,\n\t\tavailableLanguages,\n\t\tdefaultLanguage,\n\t\tdetectLanguage,\n\t\tsetLanguage,\n\t\tisHydrated,\n\t]);\n\n\tuseEffect(() => {\n\t\tconst effectiveLanguages = manifest\n\t\t\t? [...manifest.languages]\n\t\t\t: availableLanguages;\n\n\t\tif (effectiveLanguages) {\n\t\t\tconst store = useTranslationStore.getState();\n\t\t\tconst merged = [\n\t\t\t\t...new Set([...store.availableLanguages, ...effectiveLanguages]),\n\t\t\t];\n\t\t\tuseTranslationStore.setState({\n\t\t\t\tavailableLanguages: merged,\n\t\t\t\tdefaultLanguage,\n\t\t\t});\n\t\t}\n\t}, [availableLanguages, manifest, defaultLanguage]);\n\n\tconst loadLanguageFromCDN = useCallback(\n\t\tasync (language: string, isPreload = false): Promise<boolean> => {\n\t\t\tconst currentManifest = manifestRef.current;\n\t\t\tif (!currentManifest) {\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst cdnUrl = currentManifest.cdnUrls[language];\n\t\t\tif (!cdnUrl) {\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst loadedUrl = loadedUrlsRef.current.get(language);\n\t\t\tif (loadedUrl === cdnUrl) {\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (!isPreload) {\n\t\t\t\tsetLoading(true);\n\t\t\t\tsetReady(false);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst cached = await getCachedTranslation(cdnUrl);\n\t\t\t\tif (cached) {\n\t\t\t\t\taddLanguage(language, cached);\n\t\t\t\t\tloadedUrlsRef.current.set(language, cdnUrl);\n\t\t\t\t\tif (!isPreload) {\n\t\t\t\t\t\tsetReady(true);\n\t\t\t\t\t\tsetLoading(false);\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tconst translationData = await fetchTranslationsFromCDN(cdnUrl);\n\t\t\t\taddLanguage(language, translationData);\n\t\t\t\tloadedUrlsRef.current.set(language, cdnUrl);\n\n\t\t\t\tawait cacheTranslation(\n\t\t\t\t\tcdnUrl,\n\t\t\t\t\tlanguage,\n\t\t\t\t\tcurrentManifest.projectId,\n\t\t\t\t\ttranslationData,\n\t\t\t\t);\n\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn true;\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`[ciao-tools] Failed to load translations for ${language}:`,\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn false;\n\t\t\t} finally {\n\t\t\t\tif (!isPreload) setLoading(false);\n\t\t\t}\n\t\t},\n\t\t[addLanguage, setLoading, setReady],\n\t);\n\n\tuseEffect(() => {\n\t\tif (!isHydrated) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (currentLanguage === manifest?.sourceLanguage) {\n\t\t\tsetReady(true);\n\t\t\treturn;\n\t\t}\n\n\t\tif (manifest && currentLanguage) {\n\t\t\tloadLanguageFromCDN(currentLanguage, false);\n\t\t} else if (!manifest) {\n\t\t\tsetReady(true);\n\t\t}\n\t}, [manifest, currentLanguage, loadLanguageFromCDN, setReady, isHydrated]);\n\n\tuseEffect(() => {\n\t\tif (!preloadLanguages || !manifest) return;\n\n\t\tif (preloadTimeoutRef.current) {\n\t\t\tclearTimeout(preloadTimeoutRef.current);\n\t\t}\n\n\t\tpreloadTimeoutRef.current = setTimeout(async () => {\n\t\t\tconst languages = [...manifest.languages];\n\t\t\tfor (const language of languages) {\n\t\t\t\tif (language === manifest.sourceLanguage) continue;\n\t\t\t\tif (language === currentLanguage) continue;\n\n\t\t\t\tawait loadLanguageFromCDN(language, true);\n\t\t\t}\n\t\t}, preloadDelay);\n\n\t\treturn () => {\n\t\t\tif (preloadTimeoutRef.current) {\n\t\t\t\tclearTimeout(preloadTimeoutRef.current);\n\t\t\t}\n\t\t};\n\t}, [\n\t\tmanifest,\n\t\tcurrentLanguage,\n\t\tpreloadLanguages,\n\t\tpreloadDelay,\n\t\tloadLanguageFromCDN,\n\t]);\n\n\tuseEffect(() => {\n\t\tif (onLanguageChange) {\n\t\t\tonLanguageChange(currentLanguage);\n\t\t}\n\t}, [currentLanguage, onLanguageChange]);\n\n\tuseHotUpdates(hotUpdates, manifest?.projectId);\n\n\tif (blockUntilReady && (!isReady || !isHydrated)) {\n\t\treturn <>{fallback}</>;\n\t}\n\n\treturn <>{children}</>;\n}\n","import React, { createContext, useContext, useCallback, type ReactNode } from \"react\";\nimport { useTranslationStore } from \"../store\";\n\nexport const LANGUAGE_DATA: Record<\n\tstring,\n\t{ name: string; nativeName: string; flag: string }\n> = {\n\ten: { name: \"English\", nativeName: \"English\", flag: \"🇺🇸\" },\n\tes: { name: \"Spanish\", nativeName: \"Español\", flag: \"🇪🇸\" },\n\tfr: { name: \"French\", nativeName: \"Français\", flag: \"🇫🇷\" },\n\tde: { name: \"German\", nativeName: \"Deutsch\", flag: \"🇩🇪\" },\n\tit: { name: \"Italian\", nativeName: \"Italiano\", flag: \"🇮🇹\" },\n\tpt: { name: \"Portuguese\", nativeName: \"Português\", flag: \"🇵🇹\" },\n\tja: { name: \"Japanese\", nativeName: \"日本語\", flag: \"🇯🇵\" },\n\tko: { name: \"Korean\", nativeName: \"한국어\", flag: \"🇰🇷\" },\n\tzh: { name: \"Chinese\", nativeName: \"中文\", flag: \"🇨🇳\" },\n\tar: { name: \"Arabic\", nativeName: \"العربية\", flag: \"🇸🇦\" },\n\tru: { name: \"Russian\", nativeName: \"Русский\", flag: \"🇷🇺\" },\n\tnl: { name: \"Dutch\", nativeName: \"Nederlands\", flag: \"🇳🇱\" },\n\tpl: { name: \"Polish\", nativeName: \"Polski\", flag: \"🇵🇱\" },\n\tsv: { name: \"Swedish\", nativeName: \"Svenska\", flag: \"🇸🇪\" },\n\tda: { name: \"Danish\", nativeName: \"Dansk\", flag: \"🇩🇰\" },\n\tfi: { name: \"Finnish\", nativeName: \"Suomi\", flag: \"🇫🇮\" },\n\tno: { name: \"Norwegian\", nativeName: \"Norsk\", flag: \"🇳🇴\" },\n\ttr: { name: \"Turkish\", nativeName: \"Türkçe\", flag: \"🇹🇷\" },\n\tcs: { name: \"Czech\", nativeName: \"Čeština\", flag: \"🇨🇿\" },\n\tel: { name: \"Greek\", nativeName: \"Ελληνικά\", flag: \"🇬🇷\" },\n\the: { name: \"Hebrew\", nativeName: \"עברית\", flag: \"🇮🇱\" },\n\thu: { name: \"Hungarian\", nativeName: \"Magyar\", flag: \"🇭🇺\" },\n\tid: { name: \"Indonesian\", nativeName: \"Bahasa Indonesia\", flag: \"🇮🇩\" },\n\tth: { name: \"Thai\", nativeName: \"ไทย\", flag: \"🇹🇭\" },\n\tvi: { name: \"Vietnamese\", nativeName: \"Tiếng Việt\", flag: \"🇻🇳\" },\n\tuk: { name: \"Ukrainian\", nativeName: \"Українська\", flag: \"🇺🇦\" },\n\tro: { name: \"Romanian\", nativeName: \"Română\", flag: \"🇷🇴\" },\n\tbg: { name: \"Bulgarian\", nativeName: \"Български\", flag: \"🇧🇬\" },\n\tsk: { name: \"Slovak\", nativeName: \"Slovenčina\", flag: \"🇸🇰\" },\n\tlt: { name: \"Lithuanian\", nativeName: \"Lietuvių\", flag: \"🇱🇹\" },\n\tlv: { name: \"Latvian\", nativeName: \"Latviešu\", flag: \"🇱🇻\" },\n\tet: { name: \"Estonian\", nativeName: \"Eesti\", flag: \"🇪🇪\" },\n\tsl: { name: \"Slovenian\", nativeName: \"Slovenščina\", flag: \"🇸🇮\" },\n\tbs: { name: \"Bosnian\", nativeName: \"Bosanski\", flag: \"🇧🇦\" },\n\thr: { name: \"Croatian\", nativeName: \"Hrvatski\", flag: \"🇭🇷\" },\n\tsr: { name: \"Serbian\", nativeName: \"Српски\", flag: \"🇷🇸\" },\n\tkmr: { name: \"Kurdish\", nativeName: \"Kurdî\", flag: \"🇮🇶\" },\n\tfa: { name: \"Persian\", nativeName: \"فارسی\", flag: \"🇮🇷\" },\n\thi: { name: \"Hindi\", nativeName: \"हिन्दी\", flag: \"🇮🇳\" },\n\tbn: { name: \"Bengali\", nativeName: \"বাংলা\", flag: \"🇧🇩\" },\n\tms: { name: \"Malay\", nativeName: \"Bahasa Melayu\", flag: \"🇲🇾\" },\n};\n\nexport interface LanguageInfo {\n\tcode: string;\n\tname: string;\n\tnativeName: string;\n\tflag: string;\n}\n\nexport function getLanguageInfo(code: string): Omit<LanguageInfo, \"code\"> {\n\tconst normalized = code.toLowerCase();\n\treturn (\n\t\tLANGUAGE_DATA[normalized] ?? {\n\t\t\tname: code.toUpperCase(),\n\t\t\tnativeName: code.toUpperCase(),\n\t\t\tflag: \"🌐\",\n\t\t}\n\t);\n}\n\nexport function getFullLanguageInfo(code: string): LanguageInfo {\n\treturn {\n\t\tcode,\n\t\t...getLanguageInfo(code),\n\t};\n}\n\nexport type LanguageSwitcherDisplay =\n\t| \"flag\"\n\t| \"name\"\n\t| \"native\"\n\t| \"flag-name\"\n\t| \"flag-native\"\n\t| \"code\";\n\nexport function formatLanguageDisplay(\n\tcode: string,\n\tdisplay: LanguageSwitcherDisplay = \"flag-native\",\n): string {\n\tconst info = getLanguageInfo(code);\n\tswitch (display) {\n\t\tcase \"flag\":\n\t\t\treturn info.flag;\n\t\tcase \"name\":\n\t\t\treturn info.name;\n\t\tcase \"native\":\n\t\t\treturn info.nativeName;\n\t\tcase \"flag-name\":\n\t\t\treturn `${info.flag} ${info.name}`;\n\t\tcase \"flag-native\":\n\t\t\treturn `${info.flag} ${info.nativeName}`;\n\t\tcase \"code\":\n\t\t\treturn code.toUpperCase();\n\t\tdefault:\n\t\t\treturn `${info.flag} ${info.nativeName}`;\n\t}\n}\n\n// Simple default LanguageSwitcher (backward compatible)\nexport type LanguageSwitcherVariant = \"dropdown\" | \"buttons\" | \"minimal\";\n\nexport interface LanguageSwitcherProps {\n\tclassName?: string;\n\tvariant?: LanguageSwitcherVariant;\n\tdisplay?: LanguageSwitcherDisplay;\n\tonChange?: (language: string) => void;\n}\n\nexport default function LanguageSwitcher({\n\tclassName,\n\tvariant = \"dropdown\",\n\tdisplay = \"flag-native\",\n\tonChange,\n}: LanguageSwitcherProps) {\n\tconst { currentLanguage, availableLanguages, setLanguage } =\n\t\tuseTranslationStore();\n\n\tconst handleChange = (newLanguage: string) => {\n\t\tsetLanguage(newLanguage);\n\t\tonChange?.(newLanguage);\n\t};\n\n\tif (variant === \"buttons\") {\n\t\treturn (\n\t\t\t<div className={className} role=\"group\" aria-label=\"Language selection\">\n\t\t\t\t{availableLanguages.map((lang) => (\n\t\t\t\t\t<button\n\t\t\t\t\t\tkey={lang}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => handleChange(lang)}\n\t\t\t\t\t\taria-pressed={currentLanguage === lang}\n\t\t\t\t\t\tdata-active={currentLanguage === lang}\n\t\t\t\t\t>\n\t\t\t\t\t\t{formatLanguageDisplay(lang, display)}\n\t\t\t\t\t</button>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (variant === \"minimal\") {\n\t\treturn (\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName={className}\n\t\t\t\tonClick={() => {\n\t\t\t\t\tconst currentIndex = availableLanguages.indexOf(currentLanguage);\n\t\t\t\t\tconst nextIndex = (currentIndex + 1) % availableLanguages.length;\n\t\t\t\t\thandleChange(availableLanguages[nextIndex]);\n\t\t\t\t}}\n\t\t\t\taria-label={`Current language: ${getLanguageInfo(currentLanguage).name}. Click to change.`}\n\t\t\t>\n\t\t\t\t{formatLanguageDisplay(currentLanguage, display)}\n\t\t\t</button>\n\t\t);\n\t}\n\n\treturn (\n\t\t<select\n\t\t\tvalue={currentLanguage}\n\t\t\tonChange={(e) => handleChange(e.target.value)}\n\t\t\tclassName={className}\n\t\t\taria-label=\"Select language\"\n\t\t>\n\t\t\t{availableLanguages.map((lang) => (\n\t\t\t\t<option key={lang} value={lang}>\n\t\t\t\t\t{formatLanguageDisplay(lang, display)}\n\t\t\t\t</option>\n\t\t\t))}\n\t\t</select>\n\t);\n}\n","import { useCallback } from \"react\";\nimport { getTranslation, useTranslationStore } from \"../store\";\nimport type { CTFunction, InterpolationValues } from \"../types\";\n\nfunction isInterpolationValues(arg: unknown): arg is InterpolationValues {\n\treturn (\n\t\ttypeof arg === \"object\" &&\n\t\targ !== null &&\n\t\t!Array.isArray(arg) &&\n\t\t!(arg instanceof Date)\n\t);\n}\n\nexport function useCt(): CTFunction {\n\tconst { translations, currentLanguage } = useTranslationStore();\n\n\tconst ct = useCallback(\n\t\t(\n\t\t\ttext: string,\n\t\t\tcontextOrValues?: string | InterpolationValues,\n\t\t\tmaybeValues?: InterpolationValues,\n\t\t): string => {\n\t\t\tlet values: InterpolationValues | undefined;\n\n\t\t\tif (typeof contextOrValues === \"string\") {\n\t\t\t\tvalues = maybeValues;\n\t\t\t} else if (isInterpolationValues(contextOrValues)) {\n\t\t\t\tvalues = contextOrValues;\n\t\t\t}\n\n\t\t\treturn getTranslation(translations, currentLanguage, text, values);\n\t\t},\n\t\t[translations, currentLanguage],\n\t) as CTFunction;\n\n\treturn ct;\n}\n","import React, {\n\tChildren,\n\tcloneElement,\n\tisValidElement,\n\ttype ReactNode,\n\ttype ReactElement,\n} from \"react\";\nimport { useCt } from \"../hooks/useCt\";\nimport type { InterpolationValues } from \"../types\";\n\nexport interface TransProps {\n\tchildren: ReactNode;\n\tcontext?: string;\n\tvalues?: InterpolationValues;\n}\n\ninterface ParsedChild {\n\ttype: \"text\" | \"element\";\n\tcontent: string;\n\telement?: ReactElement;\n\tindex?: number;\n}\n\nfunction parseChildren(children: ReactNode): {\n\ttemplate: string;\n\telements: ReactElement[];\n} {\n\tconst elements: ReactElement[] = [];\n\tlet template = \"\";\n\n\tconst processNode = (node: ReactNode): string => {\n\t\tif (node === null || node === undefined) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (typeof node === \"string\") {\n\t\t\treturn node;\n\t\t}\n\n\t\tif (typeof node === \"number\") {\n\t\t\treturn String(node);\n\t\t}\n\n\t\tif (isValidElement(node)) {\n\t\t\tconst index = elements.length;\n\t\t\telements.push(node);\n\t\t\tconst innerContent = processNode(node.props.children);\n\t\t\treturn `<${index}>${innerContent}</${index}>`;\n\t\t}\n\n\t\tif (Array.isArray(node)) {\n\t\t\treturn node.map(processNode).join(\"\");\n\t\t}\n\n\t\treturn \"\";\n\t};\n\n\ttemplate = processNode(children);\n\treturn { template, elements };\n}\n\nfunction reconstructChildren(\n\ttranslated: string,\n\telements: ReactElement[],\n): ReactNode {\n\tif (elements.length === 0) {\n\t\treturn translated;\n\t}\n\n\tconst result: ReactNode[] = [];\n\tlet remaining = translated;\n\tlet keyCounter = 0;\n\n\tconst tagRegex = /<(\\d+)>(.*?)<\\/\\1>/gs;\n\n\tlet lastIndex = 0;\n\tlet match: RegExpExecArray | null;\n\n\t// Reset regex state\n\ttagRegex.lastIndex = 0;\n\n\twhile ((match = tagRegex.exec(translated)) !== null) {\n\t\t// Add text before the match\n\t\tif (match.index > lastIndex) {\n\t\t\tconst textBefore = translated.slice(lastIndex, match.index);\n\t\t\tif (textBefore) {\n\t\t\t\tresult.push(textBefore);\n\t\t\t}\n\t\t}\n\n\t\tconst elementIndex = parseInt(match[1], 10);\n\t\tconst innerContent = match[2];\n\t\tconst originalElement = elements[elementIndex];\n\n\t\tif (originalElement) {\n\t\t\t// Recursively process inner content in case of nested tags\n\t\t\tconst processedInner = reconstructChildren(innerContent, elements);\n\t\t\tconst cloned = cloneElement(originalElement, {\n\t\t\t\tkey: `trans-${keyCounter++}`,\n\t\t\t\tchildren: processedInner,\n\t\t\t});\n\t\t\tresult.push(cloned);\n\t\t}\n\n\t\tlastIndex = match.index + match[0].length;\n\t}\n\n\t// Add remaining text after last match\n\tif (lastIndex < translated.length) {\n\t\tresult.push(translated.slice(lastIndex));\n\t}\n\n\t// If no matches found, return the original string\n\tif (result.length === 0) {\n\t\treturn translated;\n\t}\n\n\treturn result.length === 1 ? result[0] : result;\n}\n\nexport function Trans({ children, context, values }: TransProps) {\n\tconst ct = useCt();\n\n\t// Parse children to extract template and elements\n\tconst { template, elements } = parseChildren(children);\n\n\t// Translate the template\n\tlet translated: string;\n\tif (context && values) {\n\t\ttranslated = ct(template, context, values);\n\t} else if (context) {\n\t\ttranslated = ct(template, context);\n\t} else if (values) {\n\t\ttranslated = ct(template, values);\n\t} else {\n\t\ttranslated = ct(template);\n\t}\n\n\t// Reconstruct with original elements\n\treturn <>{reconstructChildren(translated, elements)}</>;\n}\n","import { useCallback } from \"react\";\nimport { useTranslationStore } from \"../store\";\nimport {\n\tgetLanguageInfo,\n\tgetFullLanguageInfo,\n\tLANGUAGE_DATA,\n\ttype LanguageInfo,\n} from \"../components/LanguageSwitcher\";\n\nexport function useCurrentLanguage(): string {\n\treturn useTranslationStore((state) => state.currentLanguage);\n}\n\nexport function useSetLanguage(): (language: string) => void {\n\treturn useTranslationStore((state) => state.setLanguage);\n}\n\nexport function useAvailableLanguages(): string[] {\n\treturn useTranslationStore((state) => state.availableLanguages);\n}\n\nexport function useIsLoading(): boolean {\n\treturn useTranslationStore((state) => state.isLoading);\n}\n\nexport function useIsReady(): boolean {\n\treturn useTranslationStore((state) => state.isReady);\n}\n\nexport function useLanguageInfo(code?: string): LanguageInfo {\n\tconst currentLanguage = useTranslationStore((state) => state.currentLanguage);\n\tconst targetCode = code ?? currentLanguage;\n\treturn getFullLanguageInfo(targetCode);\n}\n\nexport function useAvailableLanguagesInfo(): LanguageInfo[] {\n\tconst availableLanguages = useTranslationStore(\n\t\t(state) => state.availableLanguages,\n\t);\n\treturn availableLanguages.map(getFullLanguageInfo);\n}\n\nexport function useLanguage() {\n\tconst currentLanguage = useTranslationStore((state) => state.currentLanguage);\n\tconst availableLanguages = useTranslationStore(\n\t\t(state) => state.availableLanguages,\n\t);\n\tconst setLanguage = useTranslationStore((state) => state.setLanguage);\n\tconst isLoading = useTranslationStore((state) => state.isLoading);\n\tconst isReady = useTranslationStore((state) => state.isReady);\n\n\tconst currentLanguageInfo = getFullLanguageInfo(currentLanguage);\n\tconst availableLanguagesInfo = availableLanguages.map(getFullLanguageInfo);\n\n\tconst cycleLanguage = useCallback(() => {\n\t\tconst currentIndex = availableLanguages.indexOf(currentLanguage);\n\t\tconst nextIndex = (currentIndex + 1) % availableLanguages.length;\n\t\tsetLanguage(availableLanguages[nextIndex]);\n\t}, [availableLanguages, currentLanguage, setLanguage]);\n\n\treturn {\n\t\tcurrentLanguage,\n\t\tcurrentLanguageInfo,\n\t\tavailableLanguages,\n\t\tavailableLanguagesInfo,\n\t\tsetLanguage,\n\t\tcycleLanguage,\n\t\tisLoading,\n\t\tisReady,\n\t};\n}\n\nexport {\n\tgetLanguageInfo,\n\tgetFullLanguageInfo,\n\tLANGUAGE_DATA,\n\ttype LanguageInfo,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["dbPromise: Promise<IDBDatabase> | null","entry: CacheEntry","options: Intl.DateTimeFormatOptions","result: string","key: string","format: string | undefined","hydrationResolver: (() => void) | null","updatedLanguages: string[]","LANGUAGE_DATA: Record<\n\tstring,\n\t{ name: string; nativeName: string; flag: string }\n>","values: InterpolationValues | undefined","elements: ReactElement[]","result: ReactNode[]","match: RegExpExecArray | null","translated: string"],"sources":["../src/components/CTContextBlock.tsx","../src/cache.ts","../src/interpolate.ts","../src/store.ts","../src/hooks/useHotUpdates.ts","../src/components/CTProvider.tsx","../src/components/LanguageSwitcher.tsx","../src/hooks/useCt.ts","../src/components/Trans.tsx","../src/hooks/useLanguage.ts"],"sourcesContent":["import React from \"react\";\nimport type { CTContextBlockProps } from \"../types\";\n\nexport function CTContextBlock({ children }: CTContextBlockProps) {\n\treturn <>{children}</>;\n}\n","import type { TranslationMap } from \"./types\";\n\nconst DB_NAME = \"ciao-tools-translations\";\nconst DB_VERSION = 1;\nconst STORE_NAME = \"translations\";\n\ninterface CacheEntry {\n\tlanguage: string;\n\tprojectId: string;\n\tdata: TranslationMap;\n\turl: string;\n\tcachedAt: number;\n}\n\nlet dbPromise: Promise<IDBDatabase> | null = null;\n\nfunction openDB(): Promise<IDBDatabase> {\n\tif (dbPromise) return dbPromise;\n\n\tdbPromise = new Promise((resolve, reject) => {\n\t\tif (typeof indexedDB === \"undefined\") {\n\t\t\treject(new Error(\"IndexedDB not available\"));\n\t\t\treturn;\n\t\t}\n\n\t\tconst request = indexedDB.open(DB_NAME, DB_VERSION);\n\n\t\trequest.onerror = () => reject(request.error);\n\t\trequest.onsuccess = () => resolve(request.result);\n\n\t\trequest.onupgradeneeded = (event) => {\n\t\t\tconst db = (event.target as IDBOpenDBRequest).result;\n\t\t\tif (!db.objectStoreNames.contains(STORE_NAME)) {\n\t\t\t\tconst store = db.createObjectStore(STORE_NAME, { keyPath: \"url\" });\n\t\t\t\tstore.createIndex(\"language\", \"language\", { unique: false });\n\t\t\t\tstore.createIndex(\"projectId\", \"projectId\", { unique: false });\n\t\t\t}\n\t\t};\n\t});\n\n\treturn dbPromise;\n}\n\nexport async function getCachedTranslation(\n\turl: string,\n): Promise<TranslationMap | null> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readonly\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\t\t\tconst request = store.get(url);\n\n\t\t\trequest.onerror = () => reject(request.error);\n\t\t\trequest.onsuccess = () => {\n\t\t\t\tconst entry = request.result as CacheEntry | undefined;\n\t\t\t\tresolve(entry?.data ?? null);\n\t\t\t};\n\t\t});\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function cacheTranslation(\n\turl: string,\n\tlanguage: string,\n\tprojectId: string,\n\tdata: TranslationMap,\n): Promise<void> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readwrite\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\n\t\t\tconst entry: CacheEntry = {\n\t\t\t\turl,\n\t\t\t\tlanguage,\n\t\t\t\tprojectId,\n\t\t\t\tdata,\n\t\t\t\tcachedAt: Date.now(),\n\t\t\t};\n\n\t\t\tconst request = store.put(entry);\n\t\t\trequest.onerror = () => reject(request.error);\n\t\t\trequest.onsuccess = () => resolve();\n\t\t});\n\t} catch {\n\t\t// Silently fail - caching is optional\n\t}\n}\n\nexport async function clearCache(projectId?: string): Promise<void> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readwrite\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\n\t\t\tif (projectId) {\n\t\t\t\tconst index = store.index(\"projectId\");\n\t\t\t\tconst request = index.openCursor(IDBKeyRange.only(projectId));\n\t\t\t\trequest.onsuccess = (event) => {\n\t\t\t\t\tconst cursor = (event.target as IDBRequest).result;\n\t\t\t\t\tif (cursor) {\n\t\t\t\t\t\tcursor.delete();\n\t\t\t\t\t\tcursor.continue();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\ttransaction.oncomplete = () => resolve();\n\t\t\t\ttransaction.onerror = () => reject(transaction.error);\n\t\t\t} else {\n\t\t\t\tconst request = store.clear();\n\t\t\t\trequest.onerror = () => reject(request.error);\n\t\t\t\trequest.onsuccess = () => resolve();\n\t\t\t}\n\t\t});\n\t} catch {\n\t\t// Silently fail\n\t}\n}\n\nexport async function getCacheStats(): Promise<{\n\tcount: number;\n\tlanguages: string[];\n}> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readonly\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\n\t\t\tconst countRequest = store.count();\n\t\t\tconst languages = new Set<string>();\n\n\t\t\tconst cursorRequest = store.openCursor();\n\t\t\tcursorRequest.onsuccess = (event) => {\n\t\t\t\tconst cursor = (event.target as IDBRequest).result;\n\t\t\t\tif (cursor) {\n\t\t\t\t\tlanguages.add((cursor.value as CacheEntry).language);\n\t\t\t\t\tcursor.continue();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\ttransaction.oncomplete = () => {\n\t\t\t\tresolve({\n\t\t\t\t\tcount: countRequest.result,\n\t\t\t\t\tlanguages: Array.from(languages),\n\t\t\t\t});\n\t\t\t};\n\t\t\ttransaction.onerror = () => reject(transaction.error);\n\t\t});\n\t} catch {\n\t\treturn { count: 0, languages: [] };\n\t}\n}\n","export type InterpolationValues = Record<string, unknown>;\n\nconst numberFormatCache = new Map<string, Intl.NumberFormat>();\nconst dateFormatCache = new Map<string, Intl.DateTimeFormat>();\nconst pluralRulesCache = new Map<string, Intl.PluralRules>();\n\nexport function clearFormatterCache(): void {\n\tnumberFormatCache.clear();\n\tdateFormatCache.clear();\n\tpluralRulesCache.clear();\n}\n\nfunction getNumberFormatter(locale: string): Intl.NumberFormat {\n\tconst key = `number:${locale}`;\n\tif (!numberFormatCache.has(key)) {\n\t\tnumberFormatCache.set(\n\t\t\tkey,\n\t\t\tnew Intl.NumberFormat(locale, {\n\t\t\t\tmaximumFractionDigits: 20,\n\t\t\t}),\n\t\t);\n\t}\n\treturn numberFormatCache.get(key)!;\n}\n\nfunction getCurrencyFormatter(\n\tlocale: string,\n\tcurrency: string,\n): Intl.NumberFormat {\n\tconst key = `currency:${locale}:${currency}`;\n\tif (!numberFormatCache.has(key)) {\n\t\tnumberFormatCache.set(\n\t\t\tkey,\n\t\t\tnew Intl.NumberFormat(locale, {\n\t\t\t\tstyle: \"currency\",\n\t\t\t\tcurrency,\n\t\t\t}),\n\t\t);\n\t}\n\treturn numberFormatCache.get(key)!;\n}\n\nfunction getPercentFormatter(locale: string): Intl.NumberFormat {\n\tconst key = `percent:${locale}`;\n\tif (!numberFormatCache.has(key)) {\n\t\tnumberFormatCache.set(\n\t\t\tkey,\n\t\t\tnew Intl.NumberFormat(locale, {\n\t\t\t\tstyle: \"percent\",\n\t\t\t\tminimumFractionDigits: 0,\n\t\t\t\tmaximumFractionDigits: 2,\n\t\t\t}),\n\t\t);\n\t}\n\treturn numberFormatCache.get(key)!;\n}\n\nfunction getDateFormatter(\n\tlocale: string,\n\tstyle: \"short\" | \"medium\" | \"long\" | \"full\",\n): Intl.DateTimeFormat {\n\tconst key = `date:${locale}:${style}`;\n\tif (!dateFormatCache.has(key)) {\n\t\tconst options: Intl.DateTimeFormatOptions = {\n\t\t\tdateStyle: style,\n\t\t};\n\t\tdateFormatCache.set(key, new Intl.DateTimeFormat(locale, options));\n\t}\n\treturn dateFormatCache.get(key)!;\n}\n\nfunction getTimeFormatter(\n\tlocale: string,\n\tstyle: \"short\" | \"medium\" | \"long\" | \"full\",\n): Intl.DateTimeFormat {\n\tconst key = `time:${locale}:${style}`;\n\tif (!dateFormatCache.has(key)) {\n\t\tconst options: Intl.DateTimeFormatOptions = {\n\t\t\ttimeStyle: style,\n\t\t};\n\t\tdateFormatCache.set(key, new Intl.DateTimeFormat(locale, options));\n\t}\n\treturn dateFormatCache.get(key)!;\n}\n\nfunction getPluralRules(locale: string): Intl.PluralRules {\n\tif (!pluralRulesCache.has(locale)) {\n\t\tpluralRulesCache.set(locale, new Intl.PluralRules(locale));\n\t}\n\treturn pluralRulesCache.get(locale)!;\n}\n\nfunction formatValue(\n\tvalue: unknown,\n\tformat: string | undefined,\n\tlocale: string,\n): string {\n\tif (value === null || value === undefined) {\n\t\treturn \"\";\n\t}\n\n\tif (!format) {\n\t\treturn String(value);\n\t}\n\n\tconst parts = format.split(\":\");\n\tconst formatType = parts[0];\n\n\tswitch (formatType) {\n\t\tcase \"number\": {\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tif (Number.isNaN(num)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn getNumberFormatter(locale).format(num);\n\t\t}\n\n\t\tcase \"currency\": {\n\t\t\tconst currency = parts[1];\n\t\t\tif (!currency) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tif (Number.isNaN(num)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn getCurrencyFormatter(locale, currency).format(num);\n\t\t}\n\n\t\tcase \"percent\": {\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tif (Number.isNaN(num)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn getPercentFormatter(locale).format(num);\n\t\t}\n\n\t\tcase \"date\": {\n\t\t\tif (!(value instanceof Date)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst style =\n\t\t\t\t(parts[1] as \"short\" | \"medium\" | \"long\" | \"full\") || \"medium\";\n\t\t\treturn getDateFormatter(locale, style).format(value);\n\t\t}\n\n\t\tcase \"time\": {\n\t\t\tif (!(value instanceof Date)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst style =\n\t\t\t\t(parts[1] as \"short\" | \"medium\" | \"long\" | \"full\") || \"medium\";\n\t\t\treturn getTimeFormatter(locale, style).format(value);\n\t\t}\n\n\t\tcase \"plural\": {\n\t\t\tconst singular = parts[1];\n\t\t\tconst plural = parts[2];\n\t\t\tif (!singular || !plural) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tconst rules = getPluralRules(locale);\n\t\t\tconst category = rules.select(num);\n\t\t\treturn category === \"one\" ? singular : plural;\n\t\t}\n\n\t\tdefault:\n\t\t\treturn String(value);\n\t}\n}\n\nexport function interpolate(\n\ttext: string,\n\tvalues: InterpolationValues | undefined,\n\tlocale: string,\n): string {\n\t// Temporarily replace escaped braces with placeholder characters\n\tconst escaped = text.replace(/\\{\\{/g, \"\\x00\").replace(/\\}\\}/g, \"\\x01\");\n\n\tlet result: string;\n\tif (!values || Object.keys(values).length === 0) {\n\t\tresult = escaped;\n\t} else {\n\t\tresult = escaped.replace(/\\{([^}]+)\\}/g, (match, placeholder) => {\n\t\t\tconst trimmed = placeholder.trim();\n\t\t\tconst colonIndex = trimmed.indexOf(\":\");\n\n\t\t\tlet key: string;\n\t\t\tlet format: string | undefined;\n\n\t\t\tif (colonIndex === -1) {\n\t\t\t\tkey = trimmed;\n\t\t\t\tformat = undefined;\n\t\t\t} else {\n\t\t\t\tkey = trimmed.substring(0, colonIndex);\n\t\t\t\tformat = trimmed.substring(colonIndex + 1);\n\t\t\t}\n\n\t\t\tif (!(key in values)) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tconst value = values[key];\n\t\t\treturn formatValue(value, format, locale);\n\t\t});\n\t}\n\n\t// Restore escaped braces\n\treturn result.replace(/\\x00/g, \"{\").replace(/\\x01/g, \"}\");\n}\n","import { create } from \"zustand\";\nimport { persist } from \"zustand/middleware\";\nimport { interpolate } from \"./interpolate\";\nimport type {\n\tInterpolationValues,\n\tLanguageTranslations,\n\tTranslationMap,\n\tTranslationStore,\n} from \"./types\";\n\nlet hydrationResolver: (() => void) | null = null;\nconst hydrationPromise = new Promise<void>((resolve) => {\n\thydrationResolver = resolve;\n});\n\nexport const useTranslationStore = create<TranslationStore>()(\n\tpersist(\n\t\t(set) => ({\n\t\t\tcurrentLanguage: \"en\",\n\t\t\tdefaultLanguage: \"en\",\n\t\t\tavailableLanguages: [\"en\"],\n\t\t\ttranslations: {},\n\t\t\tisLoading: false,\n\t\t\tisReady: false,\n\t\t\tisHydrated: false,\n\t\t\tserverVersion: null,\n\t\t\tlastVersionCheck: null,\n\n\t\t\tsetLanguage: (language: string) => {\n\t\t\t\tset({ currentLanguage: language, isReady: false });\n\t\t\t},\n\n\t\t\tloadTranslations: (translations: LanguageTranslations) => {\n\t\t\t\tset((state) => {\n\t\t\t\t\tconst languages = Object.keys(translations);\n\t\t\t\t\tconst availableLanguages = [\n\t\t\t\t\t\t...new Set([...state.availableLanguages, ...languages]),\n\t\t\t\t\t];\n\t\t\t\t\tconst merged = { ...state.translations };\n\t\t\t\t\tfor (const lang of languages) {\n\t\t\t\t\t\tmerged[lang] = { ...merged[lang], ...translations[lang] };\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttranslations: merged,\n\t\t\t\t\t\tavailableLanguages,\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t},\n\n\t\t\taddLanguage: (language: string, translations: TranslationMap) => {\n\t\t\t\tset((state) => ({\n\t\t\t\t\ttranslations: {\n\t\t\t\t\t\t...state.translations,\n\t\t\t\t\t\t[language]: { ...state.translations[language], ...translations },\n\t\t\t\t\t},\n\t\t\t\t\tavailableLanguages: state.availableLanguages.includes(language)\n\t\t\t\t\t\t? state.availableLanguages\n\t\t\t\t\t\t: [...state.availableLanguages, language],\n\t\t\t\t}));\n\t\t\t},\n\n\t\t\tsetLoading: (loading: boolean) => {\n\t\t\t\tset({ isLoading: loading });\n\t\t\t},\n\n\t\t\tsetReady: (ready: boolean) => {\n\t\t\t\tset({ isReady: ready });\n\t\t\t},\n\n\t\t\tsetServerVersion: (version: number) => {\n\t\t\t\tset({ serverVersion: version, lastVersionCheck: Date.now() });\n\t\t\t},\n\t\t}),\n\t\t{\n\t\t\tname: \"ciao-tools-language\",\n\t\t\tpartialize: (state) => ({\n\t\t\t\tcurrentLanguage: state.currentLanguage,\n\t\t\t\tserverVersion: state.serverVersion,\n\t\t\t}),\n\t\t\tonRehydrateStorage: () => (_, error) => {\n\t\t\t\tif (!error && hydrationResolver) {\n\t\t\t\t\thydrationResolver();\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t),\n);\n\nhydrationPromise.then(() => {\n\tuseTranslationStore.setState({ isHydrated: true });\n});\n\nexport function getTranslation(\n\ttranslations: LanguageTranslations,\n\tlanguage: string,\n\ttext: string,\n\tvalues?: InterpolationValues,\n): string {\n\tconst translated = translations[language]?.[text] ?? text;\n\n\tif (!values || Object.keys(values).length === 0) {\n\t\treturn translated;\n\t}\n\n\treturn interpolate(translated, values, language);\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { clearCache, cacheTranslation } from \"../cache\";\nimport { useTranslationStore } from \"../store\";\nimport type { HotUpdateConfig, TranslationMap } from \"../types\";\n\nconst CDN_BASE_URL = \"https://t1.ciao-tools.com\";\n\ninterface LatestManifest {\n\tversion: number;\n\tupdatedAt: string;\n\turls: Record<string, string>;\n}\n\nasync function fetchLatestManifest(projectId: string): Promise<LatestManifest | null> {\n\tconst url = `${CDN_BASE_URL}/translations/${projectId}/latest.json`;\n\ttry {\n\t\tconst response = await fetch(url, { cache: \"no-cache\" });\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 404) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tthrow new Error(`Failed to fetch latest manifest: ${response.statusText}`);\n\t\t}\n\t\treturn response.json();\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function fetchTranslations(url: string): Promise<TranslationMap> {\n\tconst response = await fetch(url);\n\tif (!response.ok) {\n\t\tthrow new Error(`Failed to fetch translations: ${response.statusText}`);\n\t}\n\treturn response.json();\n}\n\nexport function useHotUpdates(\n\tconfig: HotUpdateConfig | undefined,\n\tprojectId: string | undefined,\n) {\n\tconst isCheckingRef = useRef(false);\n\tconst hasCheckedOnMountRef = useRef(false);\n\n\tconst { serverVersion, setServerVersion, addLanguage } = useTranslationStore();\n\n\tconst checkForUpdates = useCallback(async () => {\n\t\tif (!config || !projectId || isCheckingRef.current) return;\n\t\tif (config.enabled !== true) return;\n\n\t\tisCheckingRef.current = true;\n\n\t\ttry {\n\t\t\tconsole.log(\"[ciao-tools] Checking for hot updates...\");\n\t\t\tconst manifest = await fetchLatestManifest(projectId);\n\n\t\t\tif (!manifest) {\n\t\t\t\tconsole.log(\"[ciao-tools] No latest.json found (project may not have hot updates yet)\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconsole.log(\"[ciao-tools] Found latest.json, version:\", manifest.version);\n\n\t\t\tconst isFirstCheck = serverVersion === null;\n\t\t\tconst hasNewVersion = serverVersion !== null && manifest.version > serverVersion;\n\n\t\t\tif (isFirstCheck || hasNewVersion) {\n\t\t\t\tif (Object.keys(manifest.urls).length > 0) {\n\t\t\t\t\tconst reason = hasNewVersion ? \"new version\" : \"first check\";\n\t\t\t\t\tconsole.log(`[ciao-tools] Fetching translations (${reason})...`);\n\n\t\t\t\t\t// Only clear cache when there's actually a new version\n\t\t\t\t\tif (hasNewVersion) {\n\t\t\t\t\t\tawait clearCache(projectId);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst updatedLanguages: string[] = [];\n\n\t\t\t\t\tfor (const [langCode, url] of Object.entries(manifest.urls)) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst translations = await fetchTranslations(url);\n\t\t\t\t\t\t\taddLanguage(langCode, translations);\n\t\t\t\t\t\t\tawait cacheTranslation(url, langCode, projectId, translations);\n\t\t\t\t\t\t\tupdatedLanguages.push(langCode);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tconsole.error(`[ciao-tools] Failed to fetch ${langCode} translations:`, err);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (updatedLanguages.length > 0) {\n\t\t\t\t\t\tconsole.log(\"[ciao-tools] Updated translations for:\", updatedLanguages);\n\t\t\t\t\t\tif (hasNewVersion && config.onTranslationsUpdated) {\n\t\t\t\t\t\t\tconfig.onTranslationsUpdated(updatedLanguages);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconsole.log(\"[ciao-tools] Already up to date (version \" + manifest.version + \")\");\n\t\t\t}\n\n\t\t\tsetServerVersion(manifest.version);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"[ciao-tools] Hot update check failed:\", error);\n\t\t} finally {\n\t\t\tisCheckingRef.current = false;\n\t\t}\n\t}, [config, projectId, serverVersion, setServerVersion, addLanguage]);\n\n\tuseEffect(() => {\n\t\tif (!config || !projectId) return;\n\t\tif (config.enabled !== true) return;\n\n\t\tif (!hasCheckedOnMountRef.current) {\n\t\t\thasCheckedOnMountRef.current = true;\n\t\t\tcheckForUpdates();\n\t\t}\n\n\t\tconst handleVisibilityChange = () => {\n\t\t\tif (document.visibilityState === \"visible\") {\n\t\t\t\tcheckForUpdates();\n\t\t\t}\n\t\t};\n\n\t\tdocument.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n\t\t};\n\t}, [config, projectId, checkForUpdates]);\n\n\treturn { checkForUpdates };\n}\n","import React, { useCallback, useEffect, useRef, type ReactNode } from \"react\";\nimport { getCachedTranslation, cacheTranslation } from \"../cache\";\nimport { useTranslationStore } from \"../store\";\nimport { useHotUpdates } from \"../hooks/useHotUpdates\";\nimport type { CiaoManifest, CTProviderProps, TranslationMap } from \"../types\";\n\nconst PRELOAD_DELAY_MS = 5000;\n\nasync function fetchTranslationsFromCDN(url: string): Promise<TranslationMap> {\n\tconst response = await fetch(url);\n\tif (!response.ok) {\n\t\tthrow new Error(`Failed to fetch translations: ${response.statusText}`);\n\t}\n\treturn response.json();\n}\n\nfunction detectBrowserLanguage(availableLanguages: string[]): string | null {\n\tif (typeof navigator === \"undefined\") return null;\n\n\tconst browserLangs = navigator.languages || [navigator.language];\n\n\tfor (const browserLang of browserLangs) {\n\t\tconst normalized = browserLang.toLowerCase();\n\t\tif (availableLanguages.includes(normalized)) {\n\t\t\treturn normalized;\n\t\t}\n\t\tconst langCode = normalized.split(\"-\")[0];\n\t\tif (availableLanguages.includes(langCode)) {\n\t\t\treturn langCode;\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction getManifestUrlsHash(manifest: CiaoManifest | undefined): string {\n\tif (!manifest) return \"\";\n\treturn JSON.stringify(manifest.cdnUrls);\n}\n\nexport function CTProvider({\n\tchildren,\n\ttranslations,\n\tmanifest,\n\tdefaultLanguage = \"en\",\n\tavailableLanguages,\n\tonLanguageChange,\n\tdetectLanguage = true,\n\tblockUntilReady = true,\n\tfallback = null,\n\tpreloadLanguages = true,\n\tpreloadDelay = PRELOAD_DELAY_MS,\n\thotUpdates,\n}: CTProviderProps) {\n\tconst {\n\t\tloadTranslations,\n\t\tsetLanguage,\n\t\taddLanguage,\n\t\tsetLoading,\n\t\tsetReady,\n\t\tcurrentLanguage,\n\t\ttranslations: storeTranslations,\n\t\tisReady,\n\t\tisHydrated,\n\t} = useTranslationStore();\n\n\tconst manifestRef = useRef<CiaoManifest | undefined>(manifest);\n\tconst loadedUrlsRef = useRef<Map<string, string>>(new Map());\n\tconst previousManifestHashRef = useRef<string>(\"\");\n\tconst initializedRef = useRef(false);\n\tconst preloadTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n\tuseEffect(() => {\n\t\tmanifestRef.current = manifest;\n\n\t\tconst newHash = getManifestUrlsHash(manifest);\n\t\tconst oldHash = previousManifestHashRef.current;\n\n\t\tif (oldHash && newHash && oldHash !== newHash) {\n\t\t\tloadedUrlsRef.current.clear();\n\t\t\tuseTranslationStore.setState({ translations: {} });\n\t\t}\n\n\t\tpreviousManifestHashRef.current = newHash;\n\t}, [manifest]);\n\n\tuseEffect(() => {\n\t\tif (translations) {\n\t\t\tloadTranslations(translations);\n\t\t\tsetReady(true);\n\t\t}\n\t}, [translations, loadTranslations, setReady]);\n\n\tuseEffect(() => {\n\t\tif (!isHydrated) return;\n\t\tif (initializedRef.current) return;\n\t\tinitializedRef.current = true;\n\n\t\tconst store = useTranslationStore.getState();\n\t\tconst effectiveLanguages = manifest\n\t\t\t? [...manifest.languages]\n\t\t\t: availableLanguages || [];\n\n\t\tconst hasPersistedLanguage =\n\t\t\tstore.currentLanguage &&\n\t\t\tstore.currentLanguage !== \"en\" &&\n\t\t\teffectiveLanguages.includes(store.currentLanguage);\n\n\t\tif (hasPersistedLanguage) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (detectLanguage && effectiveLanguages.length > 0) {\n\t\t\tconst detected = detectBrowserLanguage(effectiveLanguages);\n\t\t\tif (detected) {\n\t\t\t\tsetLanguage(detected);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (defaultLanguage && defaultLanguage !== store.currentLanguage) {\n\t\t\tsetLanguage(defaultLanguage);\n\t\t}\n\t}, [\n\t\tmanifest,\n\t\tavailableLanguages,\n\t\tdefaultLanguage,\n\t\tdetectLanguage,\n\t\tsetLanguage,\n\t\tisHydrated,\n\t]);\n\n\tuseEffect(() => {\n\t\tconst effectiveLanguages = manifest\n\t\t\t? [...manifest.languages]\n\t\t\t: availableLanguages;\n\n\t\tif (effectiveLanguages) {\n\t\t\tconst store = useTranslationStore.getState();\n\t\t\tconst merged = [\n\t\t\t\t...new Set([...store.availableLanguages, ...effectiveLanguages]),\n\t\t\t];\n\t\t\tuseTranslationStore.setState({\n\t\t\t\tavailableLanguages: merged,\n\t\t\t\tdefaultLanguage,\n\t\t\t});\n\t\t}\n\t}, [availableLanguages, manifest, defaultLanguage]);\n\n\tconst loadLanguageFromCDN = useCallback(\n\t\tasync (language: string, isPreload = false): Promise<boolean> => {\n\t\t\tconst currentManifest = manifestRef.current;\n\t\t\tif (!currentManifest) {\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst cdnUrl = currentManifest.cdnUrls[language];\n\t\t\tif (!cdnUrl) {\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst loadedUrl = loadedUrlsRef.current.get(language);\n\t\t\tif (loadedUrl === cdnUrl) {\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (!isPreload) {\n\t\t\t\tsetLoading(true);\n\t\t\t\tsetReady(false);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst cached = await getCachedTranslation(cdnUrl);\n\t\t\t\tif (cached) {\n\t\t\t\t\taddLanguage(language, cached);\n\t\t\t\t\tloadedUrlsRef.current.set(language, cdnUrl);\n\t\t\t\t\tif (!isPreload) {\n\t\t\t\t\t\tsetReady(true);\n\t\t\t\t\t\tsetLoading(false);\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tconst translationData = await fetchTranslationsFromCDN(cdnUrl);\n\t\t\t\taddLanguage(language, translationData);\n\t\t\t\tloadedUrlsRef.current.set(language, cdnUrl);\n\n\t\t\t\tawait cacheTranslation(\n\t\t\t\t\tcdnUrl,\n\t\t\t\t\tlanguage,\n\t\t\t\t\tcurrentManifest.projectId,\n\t\t\t\t\ttranslationData,\n\t\t\t\t);\n\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn true;\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`[ciao-tools] Failed to load translations for ${language}:`,\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn false;\n\t\t\t} finally {\n\t\t\t\tif (!isPreload) setLoading(false);\n\t\t\t}\n\t\t},\n\t\t[addLanguage, setLoading, setReady],\n\t);\n\n\tuseEffect(() => {\n\t\tif (!isHydrated) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (currentLanguage === manifest?.sourceLanguage) {\n\t\t\tsetReady(true);\n\t\t\treturn;\n\t\t}\n\n\t\tif (manifest && currentLanguage) {\n\t\t\tloadLanguageFromCDN(currentLanguage, false);\n\t\t} else if (!manifest) {\n\t\t\tsetReady(true);\n\t\t}\n\t}, [manifest, currentLanguage, loadLanguageFromCDN, setReady, isHydrated]);\n\n\tuseEffect(() => {\n\t\tif (!preloadLanguages || !manifest) return;\n\n\t\tif (preloadTimeoutRef.current) {\n\t\t\tclearTimeout(preloadTimeoutRef.current);\n\t\t}\n\n\t\tpreloadTimeoutRef.current = setTimeout(async () => {\n\t\t\tconst languages = [...manifest.languages];\n\t\t\tfor (const language of languages) {\n\t\t\t\tif (language === manifest.sourceLanguage) continue;\n\t\t\t\tif (language === currentLanguage) continue;\n\n\t\t\t\tawait loadLanguageFromCDN(language, true);\n\t\t\t}\n\t\t}, preloadDelay);\n\n\t\treturn () => {\n\t\t\tif (preloadTimeoutRef.current) {\n\t\t\t\tclearTimeout(preloadTimeoutRef.current);\n\t\t\t}\n\t\t};\n\t}, [\n\t\tmanifest,\n\t\tcurrentLanguage,\n\t\tpreloadLanguages,\n\t\tpreloadDelay,\n\t\tloadLanguageFromCDN,\n\t]);\n\n\tuseEffect(() => {\n\t\tif (onLanguageChange) {\n\t\t\tonLanguageChange(currentLanguage);\n\t\t}\n\t}, [currentLanguage, onLanguageChange]);\n\n\tuseHotUpdates(hotUpdates, manifest?.projectId);\n\n\tif (blockUntilReady && (!isReady || !isHydrated)) {\n\t\treturn <>{fallback}</>;\n\t}\n\n\treturn <>{children}</>;\n}\n","import React, { createContext, useContext, useCallback, type ReactNode } from \"react\";\nimport { useTranslationStore } from \"../store\";\n\nexport const LANGUAGE_DATA: Record<\n\tstring,\n\t{ name: string; nativeName: string; flag: string }\n> = {\n\ten: { name: \"English\", nativeName: \"English\", flag: \"🇺🇸\" },\n\tes: { name: \"Spanish\", nativeName: \"Español\", flag: \"🇪🇸\" },\n\tfr: { name: \"French\", nativeName: \"Français\", flag: \"🇫🇷\" },\n\tde: { name: \"German\", nativeName: \"Deutsch\", flag: \"🇩🇪\" },\n\tit: { name: \"Italian\", nativeName: \"Italiano\", flag: \"🇮🇹\" },\n\tpt: { name: \"Portuguese\", nativeName: \"Português\", flag: \"🇵🇹\" },\n\tja: { name: \"Japanese\", nativeName: \"日本語\", flag: \"🇯🇵\" },\n\tko: { name: \"Korean\", nativeName: \"한국어\", flag: \"🇰🇷\" },\n\tzh: { name: \"Chinese\", nativeName: \"中文\", flag: \"🇨🇳\" },\n\tar: { name: \"Arabic\", nativeName: \"العربية\", flag: \"🇸🇦\" },\n\tru: { name: \"Russian\", nativeName: \"Русский\", flag: \"🇷🇺\" },\n\tnl: { name: \"Dutch\", nativeName: \"Nederlands\", flag: \"🇳🇱\" },\n\tpl: { name: \"Polish\", nativeName: \"Polski\", flag: \"🇵🇱\" },\n\tsv: { name: \"Swedish\", nativeName: \"Svenska\", flag: \"🇸🇪\" },\n\tda: { name: \"Danish\", nativeName: \"Dansk\", flag: \"🇩🇰\" },\n\tfi: { name: \"Finnish\", nativeName: \"Suomi\", flag: \"🇫🇮\" },\n\tno: { name: \"Norwegian\", nativeName: \"Norsk\", flag: \"🇳🇴\" },\n\ttr: { name: \"Turkish\", nativeName: \"Türkçe\", flag: \"🇹🇷\" },\n\tcs: { name: \"Czech\", nativeName: \"Čeština\", flag: \"🇨🇿\" },\n\tel: { name: \"Greek\", nativeName: \"Ελληνικά\", flag: \"🇬🇷\" },\n\the: { name: \"Hebrew\", nativeName: \"עברית\", flag: \"🇮🇱\" },\n\thu: { name: \"Hungarian\", nativeName: \"Magyar\", flag: \"🇭🇺\" },\n\tid: { name: \"Indonesian\", nativeName: \"Bahasa Indonesia\", flag: \"🇮🇩\" },\n\tth: { name: \"Thai\", nativeName: \"ไทย\", flag: \"🇹🇭\" },\n\tvi: { name: \"Vietnamese\", nativeName: \"Tiếng Việt\", flag: \"🇻🇳\" },\n\tuk: { name: \"Ukrainian\", nativeName: \"Українська\", flag: \"🇺🇦\" },\n\tro: { name: \"Romanian\", nativeName: \"Română\", flag: \"🇷🇴\" },\n\tbg: { name: \"Bulgarian\", nativeName: \"Български\", flag: \"🇧🇬\" },\n\tsk: { name: \"Slovak\", nativeName: \"Slovenčina\", flag: \"🇸🇰\" },\n\tlt: { name: \"Lithuanian\", nativeName: \"Lietuvių\", flag: \"🇱🇹\" },\n\tlv: { name: \"Latvian\", nativeName: \"Latviešu\", flag: \"🇱🇻\" },\n\tet: { name: \"Estonian\", nativeName: \"Eesti\", flag: \"🇪🇪\" },\n\tsl: { name: \"Slovenian\", nativeName: \"Slovenščina\", flag: \"🇸🇮\" },\n\tbs: { name: \"Bosnian\", nativeName: \"Bosanski\", flag: \"🇧🇦\" },\n\thr: { name: \"Croatian\", nativeName: \"Hrvatski\", flag: \"🇭🇷\" },\n\tsr: { name: \"Serbian\", nativeName: \"Српски\", flag: \"🇷🇸\" },\n\tkmr: { name: \"Kurdish\", nativeName: \"Kurdî\", flag: \"🇮🇶\" },\n\tfa: { name: \"Persian\", nativeName: \"فارسی\", flag: \"🇮🇷\" },\n\thi: { name: \"Hindi\", nativeName: \"हिन्दी\", flag: \"🇮🇳\" },\n\tbn: { name: \"Bengali\", nativeName: \"বাংলা\", flag: \"🇧🇩\" },\n\tms: { name: \"Malay\", nativeName: \"Bahasa Melayu\", flag: \"🇲🇾\" },\n};\n\nexport interface LanguageInfo {\n\tcode: string;\n\tname: string;\n\tnativeName: string;\n\tflag: string;\n}\n\nexport function getLanguageInfo(code: string): Omit<LanguageInfo, \"code\"> {\n\tconst normalized = code.toLowerCase();\n\treturn (\n\t\tLANGUAGE_DATA[normalized] ?? {\n\t\t\tname: code.toUpperCase(),\n\t\t\tnativeName: code.toUpperCase(),\n\t\t\tflag: \"🌐\",\n\t\t}\n\t);\n}\n\nexport function getFullLanguageInfo(code: string): LanguageInfo {\n\treturn {\n\t\tcode,\n\t\t...getLanguageInfo(code),\n\t};\n}\n\nexport type LanguageSwitcherDisplay =\n\t| \"flag\"\n\t| \"name\"\n\t| \"native\"\n\t| \"flag-name\"\n\t| \"flag-native\"\n\t| \"code\";\n\nexport function formatLanguageDisplay(\n\tcode: string,\n\tdisplay: LanguageSwitcherDisplay = \"flag-native\",\n): string {\n\tconst info = getLanguageInfo(code);\n\tswitch (display) {\n\t\tcase \"flag\":\n\t\t\treturn info.flag;\n\t\tcase \"name\":\n\t\t\treturn info.name;\n\t\tcase \"native\":\n\t\t\treturn info.nativeName;\n\t\tcase \"flag-name\":\n\t\t\treturn `${info.flag} ${info.name}`;\n\t\tcase \"flag-native\":\n\t\t\treturn `${info.flag} ${info.nativeName}`;\n\t\tcase \"code\":\n\t\t\treturn code.toUpperCase();\n\t\tdefault:\n\t\t\treturn `${info.flag} ${info.nativeName}`;\n\t}\n}\n\n// Simple default LanguageSwitcher (backward compatible)\nexport type LanguageSwitcherVariant = \"dropdown\" | \"buttons\" | \"minimal\";\n\nexport interface LanguageSwitcherProps {\n\tclassName?: string;\n\tvariant?: LanguageSwitcherVariant;\n\tdisplay?: LanguageSwitcherDisplay;\n\tonChange?: (language: string) => void;\n}\n\nexport default function LanguageSwitcher({\n\tclassName,\n\tvariant = \"dropdown\",\n\tdisplay = \"flag-native\",\n\tonChange,\n}: LanguageSwitcherProps) {\n\tconst { currentLanguage, availableLanguages, setLanguage } =\n\t\tuseTranslationStore();\n\n\tconst handleChange = (newLanguage: string) => {\n\t\tsetLanguage(newLanguage);\n\t\tonChange?.(newLanguage);\n\t};\n\n\tif (variant === \"buttons\") {\n\t\treturn (\n\t\t\t<div className={className} role=\"group\" aria-label=\"Language selection\">\n\t\t\t\t{availableLanguages.map((lang) => (\n\t\t\t\t\t<button\n\t\t\t\t\t\tkey={lang}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => handleChange(lang)}\n\t\t\t\t\t\taria-pressed={currentLanguage === lang}\n\t\t\t\t\t\tdata-active={currentLanguage === lang}\n\t\t\t\t\t>\n\t\t\t\t\t\t{formatLanguageDisplay(lang, display)}\n\t\t\t\t\t</button>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (variant === \"minimal\") {\n\t\treturn (\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName={className}\n\t\t\t\tonClick={() => {\n\t\t\t\t\tconst currentIndex = availableLanguages.indexOf(currentLanguage);\n\t\t\t\t\tconst nextIndex = (currentIndex + 1) % availableLanguages.length;\n\t\t\t\t\thandleChange(availableLanguages[nextIndex]);\n\t\t\t\t}}\n\t\t\t\taria-label={`Current language: ${getLanguageInfo(currentLanguage).name}. Click to change.`}\n\t\t\t>\n\t\t\t\t{formatLanguageDisplay(currentLanguage, display)}\n\t\t\t</button>\n\t\t);\n\t}\n\n\treturn (\n\t\t<select\n\t\t\tvalue={currentLanguage}\n\t\t\tonChange={(e) => handleChange(e.target.value)}\n\t\t\tclassName={className}\n\t\t\taria-label=\"Select language\"\n\t\t>\n\t\t\t{availableLanguages.map((lang) => (\n\t\t\t\t<option key={lang} value={lang}>\n\t\t\t\t\t{formatLanguageDisplay(lang, display)}\n\t\t\t\t</option>\n\t\t\t))}\n\t\t</select>\n\t);\n}\n","import { useCallback } from \"react\";\nimport { getTranslation, useTranslationStore } from \"../store\";\nimport type { CTFunction, InterpolationValues } from \"../types\";\n\nfunction isInterpolationValues(arg: unknown): arg is InterpolationValues {\n\treturn (\n\t\ttypeof arg === \"object\" &&\n\t\targ !== null &&\n\t\t!Array.isArray(arg) &&\n\t\t!(arg instanceof Date)\n\t);\n}\n\nexport function useCt(): CTFunction {\n\tconst { translations, currentLanguage } = useTranslationStore();\n\n\tconst ct = useCallback(\n\t\t(\n\t\t\ttext: string,\n\t\t\tcontextOrValues?: string | InterpolationValues,\n\t\t\tmaybeValues?: InterpolationValues,\n\t\t): string => {\n\t\t\tlet values: InterpolationValues | undefined;\n\n\t\t\tif (typeof contextOrValues === \"string\") {\n\t\t\t\tvalues = maybeValues;\n\t\t\t} else if (isInterpolationValues(contextOrValues)) {\n\t\t\t\tvalues = contextOrValues;\n\t\t\t}\n\n\t\t\treturn getTranslation(translations, currentLanguage, text, values);\n\t\t},\n\t\t[translations, currentLanguage],\n\t) as CTFunction;\n\n\treturn ct;\n}\n","import React, {\n\tChildren,\n\tcloneElement,\n\tisValidElement,\n\ttype ReactNode,\n\ttype ReactElement,\n} from \"react\";\nimport { useCt } from \"../hooks/useCt\";\nimport type { InterpolationValues } from \"../types\";\n\nexport interface TransProps {\n\tchildren: ReactNode;\n\tcontext?: string;\n\tvalues?: InterpolationValues;\n}\n\ninterface ParsedChild {\n\ttype: \"text\" | \"element\";\n\tcontent: string;\n\telement?: ReactElement;\n\tindex?: number;\n}\n\nfunction parseChildren(children: ReactNode): {\n\ttemplate: string;\n\telements: ReactElement[];\n} {\n\tconst elements: ReactElement[] = [];\n\tlet template = \"\";\n\n\tconst processNode = (node: ReactNode): string => {\n\t\tif (node === null || node === undefined) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (typeof node === \"string\") {\n\t\t\treturn node;\n\t\t}\n\n\t\tif (typeof node === \"number\") {\n\t\t\treturn String(node);\n\t\t}\n\n\t\tif (isValidElement(node)) {\n\t\t\tconst index = elements.length;\n\t\t\telements.push(node);\n\t\t\tconst innerContent = processNode(node.props.children);\n\t\t\treturn `<${index}>${innerContent}</${index}>`;\n\t\t}\n\n\t\tif (Array.isArray(node)) {\n\t\t\treturn node.map(processNode).join(\"\");\n\t\t}\n\n\t\treturn \"\";\n\t};\n\n\ttemplate = processNode(children);\n\treturn { template, elements };\n}\n\nfunction reconstructChildren(\n\ttranslated: string,\n\telements: ReactElement[],\n): ReactNode {\n\tif (elements.length === 0) {\n\t\treturn translated;\n\t}\n\n\tconst result: ReactNode[] = [];\n\tlet remaining = translated;\n\tlet keyCounter = 0;\n\n\tconst tagRegex = /<(\\d+)>(.*?)<\\/\\1>/gs;\n\n\tlet lastIndex = 0;\n\tlet match: RegExpExecArray | null;\n\n\t// Reset regex state\n\ttagRegex.lastIndex = 0;\n\n\twhile ((match = tagRegex.exec(translated)) !== null) {\n\t\t// Add text before the match\n\t\tif (match.index > lastIndex) {\n\t\t\tconst textBefore = translated.slice(lastIndex, match.index);\n\t\t\tif (textBefore) {\n\t\t\t\tresult.push(textBefore);\n\t\t\t}\n\t\t}\n\n\t\tconst elementIndex = parseInt(match[1], 10);\n\t\tconst innerContent = match[2];\n\t\tconst originalElement = elements[elementIndex];\n\n\t\tif (originalElement) {\n\t\t\t// Recursively process inner content in case of nested tags\n\t\t\tconst processedInner = reconstructChildren(innerContent, elements);\n\t\t\tconst cloned = cloneElement(originalElement, {\n\t\t\t\tkey: `trans-${keyCounter++}`,\n\t\t\t\tchildren: processedInner,\n\t\t\t});\n\t\t\tresult.push(cloned);\n\t\t}\n\n\t\tlastIndex = match.index + match[0].length;\n\t}\n\n\t// Add remaining text after last match\n\tif (lastIndex < translated.length) {\n\t\tresult.push(translated.slice(lastIndex));\n\t}\n\n\t// If no matches found, return the original string\n\tif (result.length === 0) {\n\t\treturn translated;\n\t}\n\n\treturn result.length === 1 ? result[0] : result;\n}\n\nexport function Trans({ children, context, values }: TransProps) {\n\tconst ct = useCt();\n\n\t// Parse children to extract template and elements\n\tconst { template, elements } = parseChildren(children);\n\n\t// Translate the template\n\tlet translated: string;\n\tif (context && values) {\n\t\ttranslated = ct(template, context, values);\n\t} else if (context) {\n\t\ttranslated = ct(template, context);\n\t} else if (values) {\n\t\ttranslated = ct(template, values);\n\t} else {\n\t\ttranslated = ct(template);\n\t}\n\n\t// Reconstruct with original elements\n\treturn <>{reconstructChildren(translated, elements)}</>;\n}\n","import { useCallback } from \"react\";\nimport { useTranslationStore } from \"../store\";\nimport {\n\tgetLanguageInfo,\n\tgetFullLanguageInfo,\n\tLANGUAGE_DATA,\n\ttype LanguageInfo,\n} from \"../components/LanguageSwitcher\";\n\nexport function useCurrentLanguage(): string {\n\treturn useTranslationStore((state) => state.currentLanguage);\n}\n\nexport function useSetLanguage(): (language: string) => void {\n\treturn useTranslationStore((state) => state.setLanguage);\n}\n\nexport function useAvailableLanguages(): string[] {\n\treturn useTranslationStore((state) => state.availableLanguages);\n}\n\nexport function useIsLoading(): boolean {\n\treturn useTranslationStore((state) => state.isLoading);\n}\n\nexport function useIsReady(): boolean {\n\treturn useTranslationStore((state) => state.isReady);\n}\n\nexport function useLanguageInfo(code?: string): LanguageInfo {\n\tconst currentLanguage = useTranslationStore((state) => state.currentLanguage);\n\tconst targetCode = code ?? currentLanguage;\n\treturn getFullLanguageInfo(targetCode);\n}\n\nexport function useAvailableLanguagesInfo(): LanguageInfo[] {\n\tconst availableLanguages = useTranslationStore(\n\t\t(state) => state.availableLanguages,\n\t);\n\treturn availableLanguages.map(getFullLanguageInfo);\n}\n\nexport function useLanguage() {\n\tconst currentLanguage = useTranslationStore((state) => state.currentLanguage);\n\tconst availableLanguages = useTranslationStore(\n\t\t(state) => state.availableLanguages,\n\t);\n\tconst setLanguage = useTranslationStore((state) => state.setLanguage);\n\tconst isLoading = useTranslationStore((state) => state.isLoading);\n\tconst isReady = useTranslationStore((state) => state.isReady);\n\n\tconst currentLanguageInfo = getFullLanguageInfo(currentLanguage);\n\tconst availableLanguagesInfo = availableLanguages.map(getFullLanguageInfo);\n\n\tconst cycleLanguage = useCallback(() => {\n\t\tconst currentIndex = availableLanguages.indexOf(currentLanguage);\n\t\tconst nextIndex = (currentIndex + 1) % availableLanguages.length;\n\t\tsetLanguage(availableLanguages[nextIndex]);\n\t}, [availableLanguages, currentLanguage, setLanguage]);\n\n\treturn {\n\t\tcurrentLanguage,\n\t\tcurrentLanguageInfo,\n\t\tavailableLanguages,\n\t\tavailableLanguagesInfo,\n\t\tsetLanguage,\n\t\tcycleLanguage,\n\t\tisLoading,\n\t\tisReady,\n\t};\n}\n\nexport {\n\tgetLanguageInfo,\n\tgetFullLanguageInfo,\n\tLANGUAGE_DATA,\n\ttype LanguageInfo,\n};\n"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -16,7 +16,6 @@ interface TranslationState {
|
|
|
16
16
|
isHydrated: boolean;
|
|
17
17
|
serverVersion: number | null;
|
|
18
18
|
lastVersionCheck: number | null;
|
|
19
|
-
cachedLanguages: string[];
|
|
20
19
|
}
|
|
21
20
|
interface TranslationActions {
|
|
22
21
|
setLanguage: (language: string) => void;
|
|
@@ -25,7 +24,6 @@ interface TranslationActions {
|
|
|
25
24
|
setLoading: (isLoading: boolean) => void;
|
|
26
25
|
setReady: (isReady: boolean) => void;
|
|
27
26
|
setServerVersion: (version: number) => void;
|
|
28
|
-
setCachedLanguages: (languages: string[]) => void;
|
|
29
27
|
}
|
|
30
28
|
type TranslationStore = TranslationState & TranslationActions;
|
|
31
29
|
interface CiaoManifest {
|
|
@@ -166,7 +164,6 @@ declare const useTranslationStore: zustand0.UseBoundStore<Omit<zustand0.StoreApi
|
|
|
166
164
|
setOptions: (options: Partial<zustand_middleware0.PersistOptions<TranslationStore, {
|
|
167
165
|
currentLanguage: string;
|
|
168
166
|
serverVersion: number | null;
|
|
169
|
-
cachedLanguages: string[];
|
|
170
167
|
}>>) => void;
|
|
171
168
|
clearStorage: () => void;
|
|
172
169
|
rehydrate: () => Promise<void> | void;
|
|
@@ -176,7 +173,6 @@ declare const useTranslationStore: zustand0.UseBoundStore<Omit<zustand0.StoreApi
|
|
|
176
173
|
getOptions: () => Partial<zustand_middleware0.PersistOptions<TranslationStore, {
|
|
177
174
|
currentLanguage: string;
|
|
178
175
|
serverVersion: number | null;
|
|
179
|
-
cachedLanguages: string[];
|
|
180
176
|
}>>;
|
|
181
177
|
};
|
|
182
178
|
}>;
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/components/CTContextBlock.tsx","../src/components/CTProvider.tsx","../src/components/LanguageSwitcher.tsx","../src/components/Trans.tsx","../src/hooks/useCt.ts","../src/hooks/useLanguage.ts","../src/hooks/useHotUpdates.ts","../src/interpolate.ts","../src/store.ts","../src/cache.ts"],"sourcesContent":[],"mappings":";;;;;KAAY,cAAA,GAAiB;KAEjB,oBAAA,GAAuB,eAAe;KAEtC,mBAAA,GAAsB;UAEjB,gBAAA;;EANL,eAAA,EAAc,MAAA;EAEd,kBAAA,EAAA,MAAoB,EAAA;EAEpB,YAAA,EAMG,oBANmB;EAEjB,SAAA,EAAA,OAAA;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/components/CTContextBlock.tsx","../src/components/CTProvider.tsx","../src/components/LanguageSwitcher.tsx","../src/components/Trans.tsx","../src/hooks/useCt.ts","../src/hooks/useLanguage.ts","../src/hooks/useHotUpdates.ts","../src/interpolate.ts","../src/store.ts","../src/cache.ts"],"sourcesContent":[],"mappings":";;;;;KAAY,cAAA,GAAiB;KAEjB,oBAAA,GAAuB,eAAe;KAEtC,mBAAA,GAAsB;UAEjB,gBAAA;;EANL,eAAA,EAAc,MAAA;EAEd,kBAAA,EAAA,MAAoB,EAAA;EAEpB,YAAA,EAMG,oBANmB;EAEjB,SAAA,EAAA,OAAA;EAYA,OAAA,EAAA,OAAA;EASL,UAAA,EAAA,OAAgB;EAEX,aAAA,EAAY,MAAA,GAAA,IAKV;EAIF,gBAAA,EAAe,MAAA,GAAA,IAAA;AAKhC;AACiB,UA1BA,kBAAA,CA0BA;EACL,WAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EACI,gBAAA,EAAA,CAAA,YAAA,EA1BkB,oBA0BlB,EAAA,GAAA,IAAA;EAMJ,WAAM,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,YAAA,EA/B6B,cA+B7B,EAAA,GAAA,IAAA;EAGJ,UAAA,EAAA,CAAA,SAAA,EAAA,OAAA,EAAA,GAAA,IAAA;EAAe,QAAA,EAAA,CAAA,OAAA,EAAA,OAAA,EAAA,GAAA,IAAA;EAGZ,gBAAA,EAAA,CAAA,OAAmB,EAAA,MAEzB,EAAA,GAAA,IAAM;AAQjB;KAzCY,gBAAA,GAAmB,mBAAmB;UAEjC,YAAA;;EC1BD,SAAA,EAAA,MAAc;EAAG,cAAA,EAAA,MAAA;EAAY,SAAA,EAAA,SAAA,MAAA,EAAA;EAAmB,OAAA,ED+BtD,QC/BsD,CD+B7C,MC/B6C,CAAA,MAAA,EAAA,MAAA,CAAA,CAAA;EAAA,WAAA,EAAA,MAAA;;UDmC/C,eAAA;;EEED,qBAAU,CAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,EAAA,GAAA,IAAA;;AAEzB,UFCgB,eAAA,CEDhB;EACA,QAAA,EFCU,KAAA,CAAM,SEDhB;EACA,QAAA,CAAA,EFCW,YEDX;EACA,YAAA,CAAA,EFCe,oBEDf;EACA,eAAA,CAAA,EAAA,MAAA;EACA,kBAAA,CAAA,EAAA,MAAA,EAAA;EACA,gBAAA,CAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EACA,cAAA,CAAA,EAAA,OAAA;EACA,eAAA,CAAA,EAAA,OAAA;EACA,QAAA,CAAA,EFCW,KAAA,CAAM,SEDjB;EACA,gBAAA,CAAA,EAAA,OAAA;EACE,YAAA,CAAA,EAAA,MAAA;EAAe,UAAA,CAAA,EFEJ,eEFI;;UFKD,mBAAA;;YAEN,KAAA,CAAM;AGzDjB;AAgFgB,KHfJ,UAAA,GGeI;EAwBJ,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EAEK,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAqB,MAAA,CAAA,EAAA,MAE3B;EAKa,CAAA,IAAA,EAAA,MAAA,EAAA,MAAgB,EH7ChB,mBG6CgB,CAAA,EAAA,MAAA;EACvC,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA,MAAA,EAAA,MAAA,EH7CwC,mBG6CxC,CAAA,EAAA,MAAA;CACA;;;iBFnHe,cAAA;;GAA6B,sBAAmB,OAAA,CAAA,GAAA,CAAA;;;iBCqChD,UAAA;;;;;;;;;;;;;GAab,kBAAe,OAAA,CAAA,GAAA,CAAA;;;cClDL,eAAe;;;;AHH5B,CAAA,CAAA;AAEY,UGgDK,YAAA,CHhDe;EAEpB,IAAA,EAAA,MAAA;EAEK,IAAA,EAAA,MAAA;EAYA,UAAA,EAAA,MAAA;EASL,IAAA,EAAA,MAAA;AAEZ;AASiB,iBGmBD,eAAA,CHnBgB,IAAA,EAAA,MAAA,CAAA,EGmBe,IHnBf,CGmBoB,YHnBpB,EAAA,MAAA,CAAA;AAKf,iBGyBD,mBAAA,CHzBgB,IAAA,EAAA,MAAA,CAAA,EGyBmB,YHzBnB;AACf,KG+BL,uBAAA,GH/BK,MAAA,GAAA,MAAA,GAAA,QAAA,GAAA,WAAA,GAAA,aAAA,GAAA,MAAA;AACL,iBGsCI,qBAAA,CHtCJ,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EGwCF,uBHxCE,CAAA,EAAA,MAAA;AACI,KG6DJ,uBAAA,GH7DI,UAAA,GAAA,SAAA,GAAA,SAAA;AAME,UGyDD,qBAAA,CHzDC;EAGJ,SAAA,CAAA,EAAA,MAAA;EAAe,OAAA,CAAA,EGwDlB,uBHxDkB;EAGZ,OAAA,CAAA,EGsDN,uBHtDyB;EAUxB,QAAA,CAAA,EAAA,CAAA,QAAU,EAAA,MAGE,EAAA,GAAA,IAAA;;iBG6CA,gBAAA;;;;;GAKrB,wBAAqB,OAAA,CAAA,GAAA,CAAA;;;UC/GP,UAAA;YACN;;EJXC,MAAA,CAAA,EIaF,mBJbgB;AAE1B;AAEY,iBIoHI,KAAA,CJpHe;EAAA,QAAG;EAAA,OAAM;EAAA;AAAA,CAAA,EIoHa,UJpHb,CAAA,EIoHuB,OAAA,CAAA,GAAA,CAAA,OJpHvB;;;iBKSxB,KAAA,CAAA,GAAS;;;iBCJT,kBAAA,CAAA;iBAIA,cAAA,CAAA;iBAIA,qBAAA,CAAA;iBAIA,YAAA,CAAA;ANrBJ,iBMyBI,UAAA,CAAA,CNzBa,EAAA,OAAM;AAEvB,iBM2BI,eAAA,CN3BkC,IAAA,CAAA,EAAA,MAAA,CAAA,EM2BF,YN3BP;AAE7B,iBM+BI,yBAAA,CAAA,CN/BwB,EM+BK,YN/BL,EAAA;AAEvB,iBMoCD,WAAA,CAAA,CNhCD,EAAA;EAQE,eAAA,EAAA,MAAkB;EASvB,mBAAgB,EMeD,YNfI;EAEd,kBAAY,EAAA,MAAA,EAKV;EAIF,sBAAe,EMIL,YNJK,EAAA;EAKf,WAAA,EAAA,CAAA,QAAe,EAAA,MAAA,EAAA,GAAA,IAAA;EACrB,aAAM,EAAA,GAAA,GAAA,IAAA;EACL,SAAA,EAAA,OAAA;EACI,OAAA,EAAA,OAAA;CAMJ;;;iBOfI,aAAA,SACP;yBAAA;;;;KCtCG,qBAAA,GAAsB;iBAMlB,mBAAA,CAAA;iBAsKA,WAAA,uBAEP;;;cC/JI,8BAAmB,cAAA,KAAA,QAAA,CAAA,SAAA;;;;MTfpB,aAAc,EAAA,MAAG,GAAA,IAAM;IAEvB,CAAA,CAAA,CAAA,EAAA,GAAA,IAAA;IAEA,YAAA,EAAA,GAAA,GAAmB,IAAA;IAEd,SAAA,EAAA,GAAA,UAAgB,CAAA,IAIlB,CAAA,GAAA,IAAA;IAQE,WAAA,EAAA,GAAA,GAAkB,OAAA;IASvB,SAAA,EAAA,CAAA,EAAA,EAAgB,CAAA,KAAA,kBAAG,EAAA,GAAmB,IAAA,EAAA,GAAA,GAAA,GAAA,IAAkB;IAEnD,iBAAY,EAAA,CAAA,EAAA,EAKV,CAAA,KAAA,kBAAD,EAAA,GAAA,IAAA,EAAA,GAAA,GAAA,GAAA,IAAA;IAID,UAAA,EAAA,GAAe,UAAA,mCAAA,iBAAA,EAAA;MAKf,eAAe,EAAA,MAAA;MACf,aAAA,EAAA,MAAA,GAAA,IAAA;IACL,CAAA,CAAA,CAAA;EACI,CAAA;CAMJ,CAAA;;;iBUyCU,UAAA,sBAAgC;iBA8BhC,aAAA,CAAA,GAAiB;EV3H3B,KAAA,EAAA,MAAA;EAEA,SAAA,EAAA,MAAA,EAAA;AAEZ,CAAA,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,6 @@ interface TranslationState {
|
|
|
16
16
|
isHydrated: boolean;
|
|
17
17
|
serverVersion: number | null;
|
|
18
18
|
lastVersionCheck: number | null;
|
|
19
|
-
cachedLanguages: string[];
|
|
20
19
|
}
|
|
21
20
|
interface TranslationActions {
|
|
22
21
|
setLanguage: (language: string) => void;
|
|
@@ -25,7 +24,6 @@ interface TranslationActions {
|
|
|
25
24
|
setLoading: (isLoading: boolean) => void;
|
|
26
25
|
setReady: (isReady: boolean) => void;
|
|
27
26
|
setServerVersion: (version: number) => void;
|
|
28
|
-
setCachedLanguages: (languages: string[]) => void;
|
|
29
27
|
}
|
|
30
28
|
type TranslationStore = TranslationState & TranslationActions;
|
|
31
29
|
interface CiaoManifest {
|
|
@@ -166,7 +164,6 @@ declare const useTranslationStore: zustand0.UseBoundStore<Omit<zustand0.StoreApi
|
|
|
166
164
|
setOptions: (options: Partial<zustand_middleware0.PersistOptions<TranslationStore, {
|
|
167
165
|
currentLanguage: string;
|
|
168
166
|
serverVersion: number | null;
|
|
169
|
-
cachedLanguages: string[];
|
|
170
167
|
}>>) => void;
|
|
171
168
|
clearStorage: () => void;
|
|
172
169
|
rehydrate: () => Promise<void> | void;
|
|
@@ -176,7 +173,6 @@ declare const useTranslationStore: zustand0.UseBoundStore<Omit<zustand0.StoreApi
|
|
|
176
173
|
getOptions: () => Partial<zustand_middleware0.PersistOptions<TranslationStore, {
|
|
177
174
|
currentLanguage: string;
|
|
178
175
|
serverVersion: number | null;
|
|
179
|
-
cachedLanguages: string[];
|
|
180
176
|
}>>;
|
|
181
177
|
};
|
|
182
178
|
}>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/components/CTContextBlock.tsx","../src/components/CTProvider.tsx","../src/components/LanguageSwitcher.tsx","../src/components/Trans.tsx","../src/hooks/useCt.ts","../src/hooks/useLanguage.ts","../src/hooks/useHotUpdates.ts","../src/interpolate.ts","../src/store.ts","../src/cache.ts"],"sourcesContent":[],"mappings":";;;;;KAAY,cAAA,GAAiB;KAEjB,oBAAA,GAAuB,eAAe;KAEtC,mBAAA,GAAsB;UAEjB,gBAAA;;EANL,eAAA,EAAc,MAAA;EAEd,kBAAA,EAAA,MAAoB,EAAA;EAEpB,YAAA,EAMG,oBANmB;EAEjB,SAAA,EAAA,OAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/components/CTContextBlock.tsx","../src/components/CTProvider.tsx","../src/components/LanguageSwitcher.tsx","../src/components/Trans.tsx","../src/hooks/useCt.ts","../src/hooks/useLanguage.ts","../src/hooks/useHotUpdates.ts","../src/interpolate.ts","../src/store.ts","../src/cache.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -253,7 +253,6 @@ const useTranslationStore = create()(persist((set) => ({
|
|
|
253
253
|
isHydrated: false,
|
|
254
254
|
serverVersion: null,
|
|
255
255
|
lastVersionCheck: null,
|
|
256
|
-
cachedLanguages: [],
|
|
257
256
|
setLanguage: (language) => {
|
|
258
257
|
set({
|
|
259
258
|
currentLanguage: language,
|
|
@@ -298,16 +297,12 @@ const useTranslationStore = create()(persist((set) => ({
|
|
|
298
297
|
serverVersion: version,
|
|
299
298
|
lastVersionCheck: Date.now()
|
|
300
299
|
});
|
|
301
|
-
},
|
|
302
|
-
setCachedLanguages: (languages) => {
|
|
303
|
-
set({ cachedLanguages: languages });
|
|
304
300
|
}
|
|
305
301
|
}), {
|
|
306
302
|
name: "ciao-tools-language",
|
|
307
303
|
partialize: (state) => ({
|
|
308
304
|
currentLanguage: state.currentLanguage,
|
|
309
|
-
serverVersion: state.serverVersion
|
|
310
|
-
cachedLanguages: state.cachedLanguages
|
|
305
|
+
serverVersion: state.serverVersion
|
|
311
306
|
}),
|
|
312
307
|
onRehydrateStorage: () => (_, error) => {
|
|
313
308
|
if (!error && hydrationResolver) hydrationResolver();
|
|
@@ -346,7 +341,7 @@ async function fetchTranslations(url) {
|
|
|
346
341
|
function useHotUpdates(config, projectId) {
|
|
347
342
|
const isCheckingRef = useRef(false);
|
|
348
343
|
const hasCheckedOnMountRef = useRef(false);
|
|
349
|
-
const { serverVersion, setServerVersion, addLanguage
|
|
344
|
+
const { serverVersion, setServerVersion, addLanguage } = useTranslationStore();
|
|
350
345
|
const checkForUpdates = useCallback(async () => {
|
|
351
346
|
if (!config || !projectId || isCheckingRef.current) return;
|
|
352
347
|
if (config.enabled !== true) return;
|
|
@@ -361,12 +356,11 @@ function useHotUpdates(config, projectId) {
|
|
|
361
356
|
console.log("[ciao-tools] Found latest.json, version:", manifest.version);
|
|
362
357
|
const isFirstCheck = serverVersion === null;
|
|
363
358
|
const hasNewVersion = serverVersion !== null && manifest.version > serverVersion;
|
|
364
|
-
|
|
365
|
-
if (isFirstCheck || hasNewVersion || hasNoCache) {
|
|
359
|
+
if (isFirstCheck || hasNewVersion) {
|
|
366
360
|
if (Object.keys(manifest.urls).length > 0) {
|
|
367
|
-
const reason = hasNewVersion ? "new version" :
|
|
361
|
+
const reason = hasNewVersion ? "new version" : "first check";
|
|
368
362
|
console.log(`[ciao-tools] Fetching translations (${reason})...`);
|
|
369
|
-
await clearCache(projectId);
|
|
363
|
+
if (hasNewVersion) await clearCache(projectId);
|
|
370
364
|
const updatedLanguages = [];
|
|
371
365
|
for (const [langCode, url] of Object.entries(manifest.urls)) try {
|
|
372
366
|
const translations = await fetchTranslations(url);
|
|
@@ -377,7 +371,6 @@ function useHotUpdates(config, projectId) {
|
|
|
377
371
|
console.error(`[ciao-tools] Failed to fetch ${langCode} translations:`, err);
|
|
378
372
|
}
|
|
379
373
|
if (updatedLanguages.length > 0) {
|
|
380
|
-
setCachedLanguages(updatedLanguages);
|
|
381
374
|
console.log("[ciao-tools] Updated translations for:", updatedLanguages);
|
|
382
375
|
if (hasNewVersion && config.onTranslationsUpdated) config.onTranslationsUpdated(updatedLanguages);
|
|
383
376
|
}
|
|
@@ -394,9 +387,7 @@ function useHotUpdates(config, projectId) {
|
|
|
394
387
|
projectId,
|
|
395
388
|
serverVersion,
|
|
396
389
|
setServerVersion,
|
|
397
|
-
addLanguage
|
|
398
|
-
cachedLanguages,
|
|
399
|
-
setCachedLanguages
|
|
390
|
+
addLanguage
|
|
400
391
|
]);
|
|
401
392
|
useEffect(() => {
|
|
402
393
|
if (!config || !projectId) return;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["dbPromise: Promise<IDBDatabase> | null","entry: CacheEntry","options: Intl.DateTimeFormatOptions","result: string","key: string","format: string | undefined","hydrationResolver: (() => void) | null","updatedLanguages: string[]","LANGUAGE_DATA: Record<\n\tstring,\n\t{ name: string; nativeName: string; flag: string }\n>","values: InterpolationValues | undefined","elements: ReactElement[]","result: ReactNode[]","match: RegExpExecArray | null","translated: string"],"sources":["../src/components/CTContextBlock.tsx","../src/cache.ts","../src/interpolate.ts","../src/store.ts","../src/hooks/useHotUpdates.ts","../src/components/CTProvider.tsx","../src/components/LanguageSwitcher.tsx","../src/hooks/useCt.ts","../src/components/Trans.tsx","../src/hooks/useLanguage.ts"],"sourcesContent":["import React from \"react\";\nimport type { CTContextBlockProps } from \"../types\";\n\nexport function CTContextBlock({ children }: CTContextBlockProps) {\n\treturn <>{children}</>;\n}\n","import type { TranslationMap } from \"./types\";\n\nconst DB_NAME = \"ciao-tools-translations\";\nconst DB_VERSION = 1;\nconst STORE_NAME = \"translations\";\n\ninterface CacheEntry {\n\tlanguage: string;\n\tprojectId: string;\n\tdata: TranslationMap;\n\turl: string;\n\tcachedAt: number;\n}\n\nlet dbPromise: Promise<IDBDatabase> | null = null;\n\nfunction openDB(): Promise<IDBDatabase> {\n\tif (dbPromise) return dbPromise;\n\n\tdbPromise = new Promise((resolve, reject) => {\n\t\tif (typeof indexedDB === \"undefined\") {\n\t\t\treject(new Error(\"IndexedDB not available\"));\n\t\t\treturn;\n\t\t}\n\n\t\tconst request = indexedDB.open(DB_NAME, DB_VERSION);\n\n\t\trequest.onerror = () => reject(request.error);\n\t\trequest.onsuccess = () => resolve(request.result);\n\n\t\trequest.onupgradeneeded = (event) => {\n\t\t\tconst db = (event.target as IDBOpenDBRequest).result;\n\t\t\tif (!db.objectStoreNames.contains(STORE_NAME)) {\n\t\t\t\tconst store = db.createObjectStore(STORE_NAME, { keyPath: \"url\" });\n\t\t\t\tstore.createIndex(\"language\", \"language\", { unique: false });\n\t\t\t\tstore.createIndex(\"projectId\", \"projectId\", { unique: false });\n\t\t\t}\n\t\t};\n\t});\n\n\treturn dbPromise;\n}\n\nexport async function getCachedTranslation(\n\turl: string,\n): Promise<TranslationMap | null> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readonly\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\t\t\tconst request = store.get(url);\n\n\t\t\trequest.onerror = () => reject(request.error);\n\t\t\trequest.onsuccess = () => {\n\t\t\t\tconst entry = request.result as CacheEntry | undefined;\n\t\t\t\tresolve(entry?.data ?? null);\n\t\t\t};\n\t\t});\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function cacheTranslation(\n\turl: string,\n\tlanguage: string,\n\tprojectId: string,\n\tdata: TranslationMap,\n): Promise<void> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readwrite\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\n\t\t\tconst entry: CacheEntry = {\n\t\t\t\turl,\n\t\t\t\tlanguage,\n\t\t\t\tprojectId,\n\t\t\t\tdata,\n\t\t\t\tcachedAt: Date.now(),\n\t\t\t};\n\n\t\t\tconst request = store.put(entry);\n\t\t\trequest.onerror = () => reject(request.error);\n\t\t\trequest.onsuccess = () => resolve();\n\t\t});\n\t} catch {\n\t\t// Silently fail - caching is optional\n\t}\n}\n\nexport async function clearCache(projectId?: string): Promise<void> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readwrite\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\n\t\t\tif (projectId) {\n\t\t\t\tconst index = store.index(\"projectId\");\n\t\t\t\tconst request = index.openCursor(IDBKeyRange.only(projectId));\n\t\t\t\trequest.onsuccess = (event) => {\n\t\t\t\t\tconst cursor = (event.target as IDBRequest).result;\n\t\t\t\t\tif (cursor) {\n\t\t\t\t\t\tcursor.delete();\n\t\t\t\t\t\tcursor.continue();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\ttransaction.oncomplete = () => resolve();\n\t\t\t\ttransaction.onerror = () => reject(transaction.error);\n\t\t\t} else {\n\t\t\t\tconst request = store.clear();\n\t\t\t\trequest.onerror = () => reject(request.error);\n\t\t\t\trequest.onsuccess = () => resolve();\n\t\t\t}\n\t\t});\n\t} catch {\n\t\t// Silently fail\n\t}\n}\n\nexport async function getCacheStats(): Promise<{\n\tcount: number;\n\tlanguages: string[];\n}> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readonly\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\n\t\t\tconst countRequest = store.count();\n\t\t\tconst languages = new Set<string>();\n\n\t\t\tconst cursorRequest = store.openCursor();\n\t\t\tcursorRequest.onsuccess = (event) => {\n\t\t\t\tconst cursor = (event.target as IDBRequest).result;\n\t\t\t\tif (cursor) {\n\t\t\t\t\tlanguages.add((cursor.value as CacheEntry).language);\n\t\t\t\t\tcursor.continue();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\ttransaction.oncomplete = () => {\n\t\t\t\tresolve({\n\t\t\t\t\tcount: countRequest.result,\n\t\t\t\t\tlanguages: Array.from(languages),\n\t\t\t\t});\n\t\t\t};\n\t\t\ttransaction.onerror = () => reject(transaction.error);\n\t\t});\n\t} catch {\n\t\treturn { count: 0, languages: [] };\n\t}\n}\n","export type InterpolationValues = Record<string, unknown>;\n\nconst numberFormatCache = new Map<string, Intl.NumberFormat>();\nconst dateFormatCache = new Map<string, Intl.DateTimeFormat>();\nconst pluralRulesCache = new Map<string, Intl.PluralRules>();\n\nexport function clearFormatterCache(): void {\n\tnumberFormatCache.clear();\n\tdateFormatCache.clear();\n\tpluralRulesCache.clear();\n}\n\nfunction getNumberFormatter(locale: string): Intl.NumberFormat {\n\tconst key = `number:${locale}`;\n\tif (!numberFormatCache.has(key)) {\n\t\tnumberFormatCache.set(\n\t\t\tkey,\n\t\t\tnew Intl.NumberFormat(locale, {\n\t\t\t\tmaximumFractionDigits: 20,\n\t\t\t}),\n\t\t);\n\t}\n\treturn numberFormatCache.get(key)!;\n}\n\nfunction getCurrencyFormatter(\n\tlocale: string,\n\tcurrency: string,\n): Intl.NumberFormat {\n\tconst key = `currency:${locale}:${currency}`;\n\tif (!numberFormatCache.has(key)) {\n\t\tnumberFormatCache.set(\n\t\t\tkey,\n\t\t\tnew Intl.NumberFormat(locale, {\n\t\t\t\tstyle: \"currency\",\n\t\t\t\tcurrency,\n\t\t\t}),\n\t\t);\n\t}\n\treturn numberFormatCache.get(key)!;\n}\n\nfunction getPercentFormatter(locale: string): Intl.NumberFormat {\n\tconst key = `percent:${locale}`;\n\tif (!numberFormatCache.has(key)) {\n\t\tnumberFormatCache.set(\n\t\t\tkey,\n\t\t\tnew Intl.NumberFormat(locale, {\n\t\t\t\tstyle: \"percent\",\n\t\t\t\tminimumFractionDigits: 0,\n\t\t\t\tmaximumFractionDigits: 2,\n\t\t\t}),\n\t\t);\n\t}\n\treturn numberFormatCache.get(key)!;\n}\n\nfunction getDateFormatter(\n\tlocale: string,\n\tstyle: \"short\" | \"medium\" | \"long\" | \"full\",\n): Intl.DateTimeFormat {\n\tconst key = `date:${locale}:${style}`;\n\tif (!dateFormatCache.has(key)) {\n\t\tconst options: Intl.DateTimeFormatOptions = {\n\t\t\tdateStyle: style,\n\t\t};\n\t\tdateFormatCache.set(key, new Intl.DateTimeFormat(locale, options));\n\t}\n\treturn dateFormatCache.get(key)!;\n}\n\nfunction getTimeFormatter(\n\tlocale: string,\n\tstyle: \"short\" | \"medium\" | \"long\" | \"full\",\n): Intl.DateTimeFormat {\n\tconst key = `time:${locale}:${style}`;\n\tif (!dateFormatCache.has(key)) {\n\t\tconst options: Intl.DateTimeFormatOptions = {\n\t\t\ttimeStyle: style,\n\t\t};\n\t\tdateFormatCache.set(key, new Intl.DateTimeFormat(locale, options));\n\t}\n\treturn dateFormatCache.get(key)!;\n}\n\nfunction getPluralRules(locale: string): Intl.PluralRules {\n\tif (!pluralRulesCache.has(locale)) {\n\t\tpluralRulesCache.set(locale, new Intl.PluralRules(locale));\n\t}\n\treturn pluralRulesCache.get(locale)!;\n}\n\nfunction formatValue(\n\tvalue: unknown,\n\tformat: string | undefined,\n\tlocale: string,\n): string {\n\tif (value === null || value === undefined) {\n\t\treturn \"\";\n\t}\n\n\tif (!format) {\n\t\treturn String(value);\n\t}\n\n\tconst parts = format.split(\":\");\n\tconst formatType = parts[0];\n\n\tswitch (formatType) {\n\t\tcase \"number\": {\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tif (Number.isNaN(num)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn getNumberFormatter(locale).format(num);\n\t\t}\n\n\t\tcase \"currency\": {\n\t\t\tconst currency = parts[1];\n\t\t\tif (!currency) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tif (Number.isNaN(num)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn getCurrencyFormatter(locale, currency).format(num);\n\t\t}\n\n\t\tcase \"percent\": {\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tif (Number.isNaN(num)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn getPercentFormatter(locale).format(num);\n\t\t}\n\n\t\tcase \"date\": {\n\t\t\tif (!(value instanceof Date)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst style =\n\t\t\t\t(parts[1] as \"short\" | \"medium\" | \"long\" | \"full\") || \"medium\";\n\t\t\treturn getDateFormatter(locale, style).format(value);\n\t\t}\n\n\t\tcase \"time\": {\n\t\t\tif (!(value instanceof Date)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst style =\n\t\t\t\t(parts[1] as \"short\" | \"medium\" | \"long\" | \"full\") || \"medium\";\n\t\t\treturn getTimeFormatter(locale, style).format(value);\n\t\t}\n\n\t\tcase \"plural\": {\n\t\t\tconst singular = parts[1];\n\t\t\tconst plural = parts[2];\n\t\t\tif (!singular || !plural) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tconst rules = getPluralRules(locale);\n\t\t\tconst category = rules.select(num);\n\t\t\treturn category === \"one\" ? singular : plural;\n\t\t}\n\n\t\tdefault:\n\t\t\treturn String(value);\n\t}\n}\n\nexport function interpolate(\n\ttext: string,\n\tvalues: InterpolationValues | undefined,\n\tlocale: string,\n): string {\n\t// Temporarily replace escaped braces with placeholder characters\n\tconst escaped = text.replace(/\\{\\{/g, \"\\x00\").replace(/\\}\\}/g, \"\\x01\");\n\n\tlet result: string;\n\tif (!values || Object.keys(values).length === 0) {\n\t\tresult = escaped;\n\t} else {\n\t\tresult = escaped.replace(/\\{([^}]+)\\}/g, (match, placeholder) => {\n\t\t\tconst trimmed = placeholder.trim();\n\t\t\tconst colonIndex = trimmed.indexOf(\":\");\n\n\t\t\tlet key: string;\n\t\t\tlet format: string | undefined;\n\n\t\t\tif (colonIndex === -1) {\n\t\t\t\tkey = trimmed;\n\t\t\t\tformat = undefined;\n\t\t\t} else {\n\t\t\t\tkey = trimmed.substring(0, colonIndex);\n\t\t\t\tformat = trimmed.substring(colonIndex + 1);\n\t\t\t}\n\n\t\t\tif (!(key in values)) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tconst value = values[key];\n\t\t\treturn formatValue(value, format, locale);\n\t\t});\n\t}\n\n\t// Restore escaped braces\n\treturn result.replace(/\\x00/g, \"{\").replace(/\\x01/g, \"}\");\n}\n","import { create } from \"zustand\";\nimport { persist } from \"zustand/middleware\";\nimport { interpolate } from \"./interpolate\";\nimport type {\n\tInterpolationValues,\n\tLanguageTranslations,\n\tTranslationMap,\n\tTranslationStore,\n} from \"./types\";\n\nlet hydrationResolver: (() => void) | null = null;\nconst hydrationPromise = new Promise<void>((resolve) => {\n\thydrationResolver = resolve;\n});\n\nexport const useTranslationStore = create<TranslationStore>()(\n\tpersist(\n\t\t(set) => ({\n\t\t\tcurrentLanguage: \"en\",\n\t\t\tdefaultLanguage: \"en\",\n\t\t\tavailableLanguages: [\"en\"],\n\t\t\ttranslations: {},\n\t\t\tisLoading: false,\n\t\t\tisReady: false,\n\t\t\tisHydrated: false,\n\t\t\tserverVersion: null,\n\t\t\tlastVersionCheck: null,\n\t\t\tcachedLanguages: [],\n\n\t\t\tsetLanguage: (language: string) => {\n\t\t\t\tset({ currentLanguage: language, isReady: false });\n\t\t\t},\n\n\t\t\tloadTranslations: (translations: LanguageTranslations) => {\n\t\t\t\tset((state) => {\n\t\t\t\t\tconst languages = Object.keys(translations);\n\t\t\t\t\tconst availableLanguages = [\n\t\t\t\t\t\t...new Set([...state.availableLanguages, ...languages]),\n\t\t\t\t\t];\n\t\t\t\t\tconst merged = { ...state.translations };\n\t\t\t\t\tfor (const lang of languages) {\n\t\t\t\t\t\tmerged[lang] = { ...merged[lang], ...translations[lang] };\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttranslations: merged,\n\t\t\t\t\t\tavailableLanguages,\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t},\n\n\t\t\taddLanguage: (language: string, translations: TranslationMap) => {\n\t\t\t\tset((state) => ({\n\t\t\t\t\ttranslations: {\n\t\t\t\t\t\t...state.translations,\n\t\t\t\t\t\t[language]: { ...state.translations[language], ...translations },\n\t\t\t\t\t},\n\t\t\t\t\tavailableLanguages: state.availableLanguages.includes(language)\n\t\t\t\t\t\t? state.availableLanguages\n\t\t\t\t\t\t: [...state.availableLanguages, language],\n\t\t\t\t}));\n\t\t\t},\n\n\t\t\tsetLoading: (loading: boolean) => {\n\t\t\t\tset({ isLoading: loading });\n\t\t\t},\n\n\t\t\tsetReady: (ready: boolean) => {\n\t\t\t\tset({ isReady: ready });\n\t\t\t},\n\n\t\t\tsetServerVersion: (version: number) => {\n\t\t\t\tset({ serverVersion: version, lastVersionCheck: Date.now() });\n\t\t\t},\n\n\t\t\tsetCachedLanguages: (languages: string[]) => {\n\t\t\t\tset({ cachedLanguages: languages });\n\t\t\t},\n\t\t}),\n\t\t{\n\t\t\tname: \"ciao-tools-language\",\n\t\t\tpartialize: (state) => ({\n\t\t\t\tcurrentLanguage: state.currentLanguage,\n\t\t\t\tserverVersion: state.serverVersion,\n\t\t\t\tcachedLanguages: state.cachedLanguages,\n\t\t\t}),\n\t\t\tonRehydrateStorage: () => (_, error) => {\n\t\t\t\tif (!error && hydrationResolver) {\n\t\t\t\t\thydrationResolver();\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t),\n);\n\nhydrationPromise.then(() => {\n\tuseTranslationStore.setState({ isHydrated: true });\n});\n\nexport function getTranslation(\n\ttranslations: LanguageTranslations,\n\tlanguage: string,\n\ttext: string,\n\tvalues?: InterpolationValues,\n): string {\n\tconst translated = translations[language]?.[text] ?? text;\n\n\tif (!values || Object.keys(values).length === 0) {\n\t\treturn translated;\n\t}\n\n\treturn interpolate(translated, values, language);\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { clearCache, cacheTranslation } from \"../cache\";\nimport { useTranslationStore } from \"../store\";\nimport type { HotUpdateConfig, TranslationMap } from \"../types\";\n\nconst CDN_BASE_URL = \"https://t1.ciao-tools.com\";\n\ninterface LatestManifest {\n\tversion: number;\n\tupdatedAt: string;\n\turls: Record<string, string>;\n}\n\nasync function fetchLatestManifest(projectId: string): Promise<LatestManifest | null> {\n\tconst url = `${CDN_BASE_URL}/translations/${projectId}/latest.json`;\n\ttry {\n\t\tconst response = await fetch(url, { cache: \"no-cache\" });\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 404) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tthrow new Error(`Failed to fetch latest manifest: ${response.statusText}`);\n\t\t}\n\t\treturn response.json();\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function fetchTranslations(url: string): Promise<TranslationMap> {\n\tconst response = await fetch(url);\n\tif (!response.ok) {\n\t\tthrow new Error(`Failed to fetch translations: ${response.statusText}`);\n\t}\n\treturn response.json();\n}\n\nexport function useHotUpdates(\n\tconfig: HotUpdateConfig | undefined,\n\tprojectId: string | undefined,\n) {\n\tconst isCheckingRef = useRef(false);\n\tconst hasCheckedOnMountRef = useRef(false);\n\n\tconst { serverVersion, setServerVersion, addLanguage, cachedLanguages, setCachedLanguages } = useTranslationStore();\n\n\tconst checkForUpdates = useCallback(async () => {\n\t\tif (!config || !projectId || isCheckingRef.current) return;\n\t\tif (config.enabled !== true) return;\n\n\t\tisCheckingRef.current = true;\n\n\t\ttry {\n\t\t\tconsole.log(\"[ciao-tools] Checking for hot updates...\");\n\t\t\tconst manifest = await fetchLatestManifest(projectId);\n\n\t\t\tif (!manifest) {\n\t\t\t\tconsole.log(\"[ciao-tools] No latest.json found (project may not have hot updates yet)\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconsole.log(\"[ciao-tools] Found latest.json, version:\", manifest.version);\n\n\t\t\tconst isFirstCheck = serverVersion === null;\n\t\t\tconst hasNewVersion = serverVersion !== null && manifest.version > serverVersion;\n\t\t\tconst hasNoCache = cachedLanguages.length === 0;\n\n\t\t\tif (isFirstCheck || hasNewVersion || hasNoCache) {\n\t\t\t\tif (Object.keys(manifest.urls).length > 0) {\n\t\t\t\t\tconst reason = hasNewVersion ? \"new version\" : hasNoCache ? \"no cached translations\" : \"first check\";\n\t\t\t\t\tconsole.log(`[ciao-tools] Fetching translations (${reason})...`);\n\t\t\t\t\tawait clearCache(projectId);\n\n\t\t\t\t\tconst updatedLanguages: string[] = [];\n\n\t\t\t\t\tfor (const [langCode, url] of Object.entries(manifest.urls)) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst translations = await fetchTranslations(url);\n\t\t\t\t\t\t\taddLanguage(langCode, translations);\n\t\t\t\t\t\t\tawait cacheTranslation(url, langCode, projectId, translations);\n\t\t\t\t\t\t\tupdatedLanguages.push(langCode);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tconsole.error(`[ciao-tools] Failed to fetch ${langCode} translations:`, err);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (updatedLanguages.length > 0) {\n\t\t\t\t\t\tsetCachedLanguages(updatedLanguages);\n\t\t\t\t\t\tconsole.log(\"[ciao-tools] Updated translations for:\", updatedLanguages);\n\t\t\t\t\t\tif (hasNewVersion && config.onTranslationsUpdated) {\n\t\t\t\t\t\t\tconfig.onTranslationsUpdated(updatedLanguages);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconsole.log(\"[ciao-tools] Already up to date (version \" + manifest.version + \")\");\n\t\t\t}\n\n\t\t\tsetServerVersion(manifest.version);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"[ciao-tools] Hot update check failed:\", error);\n\t\t} finally {\n\t\t\tisCheckingRef.current = false;\n\t\t}\n\t}, [config, projectId, serverVersion, setServerVersion, addLanguage, cachedLanguages, setCachedLanguages]);\n\n\tuseEffect(() => {\n\t\tif (!config || !projectId) return;\n\t\tif (config.enabled !== true) return;\n\n\t\tif (!hasCheckedOnMountRef.current) {\n\t\t\thasCheckedOnMountRef.current = true;\n\t\t\tcheckForUpdates();\n\t\t}\n\n\t\tconst handleVisibilityChange = () => {\n\t\t\tif (document.visibilityState === \"visible\") {\n\t\t\t\tcheckForUpdates();\n\t\t\t}\n\t\t};\n\n\t\tdocument.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n\t\t};\n\t}, [config, projectId, checkForUpdates]);\n\n\treturn { checkForUpdates };\n}\n","import React, { useCallback, useEffect, useRef, type ReactNode } from \"react\";\nimport { getCachedTranslation, cacheTranslation } from \"../cache\";\nimport { useTranslationStore } from \"../store\";\nimport { useHotUpdates } from \"../hooks/useHotUpdates\";\nimport type { CiaoManifest, CTProviderProps, TranslationMap } from \"../types\";\n\nconst PRELOAD_DELAY_MS = 5000;\n\nasync function fetchTranslationsFromCDN(url: string): Promise<TranslationMap> {\n\tconst response = await fetch(url);\n\tif (!response.ok) {\n\t\tthrow new Error(`Failed to fetch translations: ${response.statusText}`);\n\t}\n\treturn response.json();\n}\n\nfunction detectBrowserLanguage(availableLanguages: string[]): string | null {\n\tif (typeof navigator === \"undefined\") return null;\n\n\tconst browserLangs = navigator.languages || [navigator.language];\n\n\tfor (const browserLang of browserLangs) {\n\t\tconst normalized = browserLang.toLowerCase();\n\t\tif (availableLanguages.includes(normalized)) {\n\t\t\treturn normalized;\n\t\t}\n\t\tconst langCode = normalized.split(\"-\")[0];\n\t\tif (availableLanguages.includes(langCode)) {\n\t\t\treturn langCode;\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction getManifestUrlsHash(manifest: CiaoManifest | undefined): string {\n\tif (!manifest) return \"\";\n\treturn JSON.stringify(manifest.cdnUrls);\n}\n\nexport function CTProvider({\n\tchildren,\n\ttranslations,\n\tmanifest,\n\tdefaultLanguage = \"en\",\n\tavailableLanguages,\n\tonLanguageChange,\n\tdetectLanguage = true,\n\tblockUntilReady = true,\n\tfallback = null,\n\tpreloadLanguages = true,\n\tpreloadDelay = PRELOAD_DELAY_MS,\n\thotUpdates,\n}: CTProviderProps) {\n\tconst {\n\t\tloadTranslations,\n\t\tsetLanguage,\n\t\taddLanguage,\n\t\tsetLoading,\n\t\tsetReady,\n\t\tcurrentLanguage,\n\t\ttranslations: storeTranslations,\n\t\tisReady,\n\t\tisHydrated,\n\t} = useTranslationStore();\n\n\tconst manifestRef = useRef<CiaoManifest | undefined>(manifest);\n\tconst loadedUrlsRef = useRef<Map<string, string>>(new Map());\n\tconst previousManifestHashRef = useRef<string>(\"\");\n\tconst initializedRef = useRef(false);\n\tconst preloadTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n\tuseEffect(() => {\n\t\tmanifestRef.current = manifest;\n\n\t\tconst newHash = getManifestUrlsHash(manifest);\n\t\tconst oldHash = previousManifestHashRef.current;\n\n\t\tif (oldHash && newHash && oldHash !== newHash) {\n\t\t\tloadedUrlsRef.current.clear();\n\t\t\tuseTranslationStore.setState({ translations: {} });\n\t\t}\n\n\t\tpreviousManifestHashRef.current = newHash;\n\t}, [manifest]);\n\n\tuseEffect(() => {\n\t\tif (translations) {\n\t\t\tloadTranslations(translations);\n\t\t\tsetReady(true);\n\t\t}\n\t}, [translations, loadTranslations, setReady]);\n\n\tuseEffect(() => {\n\t\tif (!isHydrated) return;\n\t\tif (initializedRef.current) return;\n\t\tinitializedRef.current = true;\n\n\t\tconst store = useTranslationStore.getState();\n\t\tconst effectiveLanguages = manifest\n\t\t\t? [...manifest.languages]\n\t\t\t: availableLanguages || [];\n\n\t\tconst hasPersistedLanguage =\n\t\t\tstore.currentLanguage &&\n\t\t\tstore.currentLanguage !== \"en\" &&\n\t\t\teffectiveLanguages.includes(store.currentLanguage);\n\n\t\tif (hasPersistedLanguage) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (detectLanguage && effectiveLanguages.length > 0) {\n\t\t\tconst detected = detectBrowserLanguage(effectiveLanguages);\n\t\t\tif (detected) {\n\t\t\t\tsetLanguage(detected);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (defaultLanguage && defaultLanguage !== store.currentLanguage) {\n\t\t\tsetLanguage(defaultLanguage);\n\t\t}\n\t}, [\n\t\tmanifest,\n\t\tavailableLanguages,\n\t\tdefaultLanguage,\n\t\tdetectLanguage,\n\t\tsetLanguage,\n\t\tisHydrated,\n\t]);\n\n\tuseEffect(() => {\n\t\tconst effectiveLanguages = manifest\n\t\t\t? [...manifest.languages]\n\t\t\t: availableLanguages;\n\n\t\tif (effectiveLanguages) {\n\t\t\tconst store = useTranslationStore.getState();\n\t\t\tconst merged = [\n\t\t\t\t...new Set([...store.availableLanguages, ...effectiveLanguages]),\n\t\t\t];\n\t\t\tuseTranslationStore.setState({\n\t\t\t\tavailableLanguages: merged,\n\t\t\t\tdefaultLanguage,\n\t\t\t});\n\t\t}\n\t}, [availableLanguages, manifest, defaultLanguage]);\n\n\tconst loadLanguageFromCDN = useCallback(\n\t\tasync (language: string, isPreload = false): Promise<boolean> => {\n\t\t\tconst currentManifest = manifestRef.current;\n\t\t\tif (!currentManifest) {\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst cdnUrl = currentManifest.cdnUrls[language];\n\t\t\tif (!cdnUrl) {\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst loadedUrl = loadedUrlsRef.current.get(language);\n\t\t\tif (loadedUrl === cdnUrl) {\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (!isPreload) {\n\t\t\t\tsetLoading(true);\n\t\t\t\tsetReady(false);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst cached = await getCachedTranslation(cdnUrl);\n\t\t\t\tif (cached) {\n\t\t\t\t\taddLanguage(language, cached);\n\t\t\t\t\tloadedUrlsRef.current.set(language, cdnUrl);\n\t\t\t\t\tif (!isPreload) {\n\t\t\t\t\t\tsetReady(true);\n\t\t\t\t\t\tsetLoading(false);\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tconst translationData = await fetchTranslationsFromCDN(cdnUrl);\n\t\t\t\taddLanguage(language, translationData);\n\t\t\t\tloadedUrlsRef.current.set(language, cdnUrl);\n\n\t\t\t\tawait cacheTranslation(\n\t\t\t\t\tcdnUrl,\n\t\t\t\t\tlanguage,\n\t\t\t\t\tcurrentManifest.projectId,\n\t\t\t\t\ttranslationData,\n\t\t\t\t);\n\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn true;\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`[ciao-tools] Failed to load translations for ${language}:`,\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn false;\n\t\t\t} finally {\n\t\t\t\tif (!isPreload) setLoading(false);\n\t\t\t}\n\t\t},\n\t\t[addLanguage, setLoading, setReady],\n\t);\n\n\tuseEffect(() => {\n\t\tif (!isHydrated) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (currentLanguage === manifest?.sourceLanguage) {\n\t\t\tsetReady(true);\n\t\t\treturn;\n\t\t}\n\n\t\tif (manifest && currentLanguage) {\n\t\t\tloadLanguageFromCDN(currentLanguage, false);\n\t\t} else if (!manifest) {\n\t\t\tsetReady(true);\n\t\t}\n\t}, [manifest, currentLanguage, loadLanguageFromCDN, setReady, isHydrated]);\n\n\tuseEffect(() => {\n\t\tif (!preloadLanguages || !manifest) return;\n\n\t\tif (preloadTimeoutRef.current) {\n\t\t\tclearTimeout(preloadTimeoutRef.current);\n\t\t}\n\n\t\tpreloadTimeoutRef.current = setTimeout(async () => {\n\t\t\tconst languages = [...manifest.languages];\n\t\t\tfor (const language of languages) {\n\t\t\t\tif (language === manifest.sourceLanguage) continue;\n\t\t\t\tif (language === currentLanguage) continue;\n\n\t\t\t\tawait loadLanguageFromCDN(language, true);\n\t\t\t}\n\t\t}, preloadDelay);\n\n\t\treturn () => {\n\t\t\tif (preloadTimeoutRef.current) {\n\t\t\t\tclearTimeout(preloadTimeoutRef.current);\n\t\t\t}\n\t\t};\n\t}, [\n\t\tmanifest,\n\t\tcurrentLanguage,\n\t\tpreloadLanguages,\n\t\tpreloadDelay,\n\t\tloadLanguageFromCDN,\n\t]);\n\n\tuseEffect(() => {\n\t\tif (onLanguageChange) {\n\t\t\tonLanguageChange(currentLanguage);\n\t\t}\n\t}, [currentLanguage, onLanguageChange]);\n\n\tuseHotUpdates(hotUpdates, manifest?.projectId);\n\n\tif (blockUntilReady && (!isReady || !isHydrated)) {\n\t\treturn <>{fallback}</>;\n\t}\n\n\treturn <>{children}</>;\n}\n","import React, { createContext, useContext, useCallback, type ReactNode } from \"react\";\nimport { useTranslationStore } from \"../store\";\n\nexport const LANGUAGE_DATA: Record<\n\tstring,\n\t{ name: string; nativeName: string; flag: string }\n> = {\n\ten: { name: \"English\", nativeName: \"English\", flag: \"🇺🇸\" },\n\tes: { name: \"Spanish\", nativeName: \"Español\", flag: \"🇪🇸\" },\n\tfr: { name: \"French\", nativeName: \"Français\", flag: \"🇫🇷\" },\n\tde: { name: \"German\", nativeName: \"Deutsch\", flag: \"🇩🇪\" },\n\tit: { name: \"Italian\", nativeName: \"Italiano\", flag: \"🇮🇹\" },\n\tpt: { name: \"Portuguese\", nativeName: \"Português\", flag: \"🇵🇹\" },\n\tja: { name: \"Japanese\", nativeName: \"日本語\", flag: \"🇯🇵\" },\n\tko: { name: \"Korean\", nativeName: \"한국어\", flag: \"🇰🇷\" },\n\tzh: { name: \"Chinese\", nativeName: \"中文\", flag: \"🇨🇳\" },\n\tar: { name: \"Arabic\", nativeName: \"العربية\", flag: \"🇸🇦\" },\n\tru: { name: \"Russian\", nativeName: \"Русский\", flag: \"🇷🇺\" },\n\tnl: { name: \"Dutch\", nativeName: \"Nederlands\", flag: \"🇳🇱\" },\n\tpl: { name: \"Polish\", nativeName: \"Polski\", flag: \"🇵🇱\" },\n\tsv: { name: \"Swedish\", nativeName: \"Svenska\", flag: \"🇸🇪\" },\n\tda: { name: \"Danish\", nativeName: \"Dansk\", flag: \"🇩🇰\" },\n\tfi: { name: \"Finnish\", nativeName: \"Suomi\", flag: \"🇫🇮\" },\n\tno: { name: \"Norwegian\", nativeName: \"Norsk\", flag: \"🇳🇴\" },\n\ttr: { name: \"Turkish\", nativeName: \"Türkçe\", flag: \"🇹🇷\" },\n\tcs: { name: \"Czech\", nativeName: \"Čeština\", flag: \"🇨🇿\" },\n\tel: { name: \"Greek\", nativeName: \"Ελληνικά\", flag: \"🇬🇷\" },\n\the: { name: \"Hebrew\", nativeName: \"עברית\", flag: \"🇮🇱\" },\n\thu: { name: \"Hungarian\", nativeName: \"Magyar\", flag: \"🇭🇺\" },\n\tid: { name: \"Indonesian\", nativeName: \"Bahasa Indonesia\", flag: \"🇮🇩\" },\n\tth: { name: \"Thai\", nativeName: \"ไทย\", flag: \"🇹🇭\" },\n\tvi: { name: \"Vietnamese\", nativeName: \"Tiếng Việt\", flag: \"🇻🇳\" },\n\tuk: { name: \"Ukrainian\", nativeName: \"Українська\", flag: \"🇺🇦\" },\n\tro: { name: \"Romanian\", nativeName: \"Română\", flag: \"🇷🇴\" },\n\tbg: { name: \"Bulgarian\", nativeName: \"Български\", flag: \"🇧🇬\" },\n\tsk: { name: \"Slovak\", nativeName: \"Slovenčina\", flag: \"🇸🇰\" },\n\tlt: { name: \"Lithuanian\", nativeName: \"Lietuvių\", flag: \"🇱🇹\" },\n\tlv: { name: \"Latvian\", nativeName: \"Latviešu\", flag: \"🇱🇻\" },\n\tet: { name: \"Estonian\", nativeName: \"Eesti\", flag: \"🇪🇪\" },\n\tsl: { name: \"Slovenian\", nativeName: \"Slovenščina\", flag: \"🇸🇮\" },\n\tbs: { name: \"Bosnian\", nativeName: \"Bosanski\", flag: \"🇧🇦\" },\n\thr: { name: \"Croatian\", nativeName: \"Hrvatski\", flag: \"🇭🇷\" },\n\tsr: { name: \"Serbian\", nativeName: \"Српски\", flag: \"🇷🇸\" },\n\tkmr: { name: \"Kurdish\", nativeName: \"Kurdî\", flag: \"🇮🇶\" },\n\tfa: { name: \"Persian\", nativeName: \"فارسی\", flag: \"🇮🇷\" },\n\thi: { name: \"Hindi\", nativeName: \"हिन्दी\", flag: \"🇮🇳\" },\n\tbn: { name: \"Bengali\", nativeName: \"বাংলা\", flag: \"🇧🇩\" },\n\tms: { name: \"Malay\", nativeName: \"Bahasa Melayu\", flag: \"🇲🇾\" },\n};\n\nexport interface LanguageInfo {\n\tcode: string;\n\tname: string;\n\tnativeName: string;\n\tflag: string;\n}\n\nexport function getLanguageInfo(code: string): Omit<LanguageInfo, \"code\"> {\n\tconst normalized = code.toLowerCase();\n\treturn (\n\t\tLANGUAGE_DATA[normalized] ?? {\n\t\t\tname: code.toUpperCase(),\n\t\t\tnativeName: code.toUpperCase(),\n\t\t\tflag: \"🌐\",\n\t\t}\n\t);\n}\n\nexport function getFullLanguageInfo(code: string): LanguageInfo {\n\treturn {\n\t\tcode,\n\t\t...getLanguageInfo(code),\n\t};\n}\n\nexport type LanguageSwitcherDisplay =\n\t| \"flag\"\n\t| \"name\"\n\t| \"native\"\n\t| \"flag-name\"\n\t| \"flag-native\"\n\t| \"code\";\n\nexport function formatLanguageDisplay(\n\tcode: string,\n\tdisplay: LanguageSwitcherDisplay = \"flag-native\",\n): string {\n\tconst info = getLanguageInfo(code);\n\tswitch (display) {\n\t\tcase \"flag\":\n\t\t\treturn info.flag;\n\t\tcase \"name\":\n\t\t\treturn info.name;\n\t\tcase \"native\":\n\t\t\treturn info.nativeName;\n\t\tcase \"flag-name\":\n\t\t\treturn `${info.flag} ${info.name}`;\n\t\tcase \"flag-native\":\n\t\t\treturn `${info.flag} ${info.nativeName}`;\n\t\tcase \"code\":\n\t\t\treturn code.toUpperCase();\n\t\tdefault:\n\t\t\treturn `${info.flag} ${info.nativeName}`;\n\t}\n}\n\n// Simple default LanguageSwitcher (backward compatible)\nexport type LanguageSwitcherVariant = \"dropdown\" | \"buttons\" | \"minimal\";\n\nexport interface LanguageSwitcherProps {\n\tclassName?: string;\n\tvariant?: LanguageSwitcherVariant;\n\tdisplay?: LanguageSwitcherDisplay;\n\tonChange?: (language: string) => void;\n}\n\nexport default function LanguageSwitcher({\n\tclassName,\n\tvariant = \"dropdown\",\n\tdisplay = \"flag-native\",\n\tonChange,\n}: LanguageSwitcherProps) {\n\tconst { currentLanguage, availableLanguages, setLanguage } =\n\t\tuseTranslationStore();\n\n\tconst handleChange = (newLanguage: string) => {\n\t\tsetLanguage(newLanguage);\n\t\tonChange?.(newLanguage);\n\t};\n\n\tif (variant === \"buttons\") {\n\t\treturn (\n\t\t\t<div className={className} role=\"group\" aria-label=\"Language selection\">\n\t\t\t\t{availableLanguages.map((lang) => (\n\t\t\t\t\t<button\n\t\t\t\t\t\tkey={lang}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => handleChange(lang)}\n\t\t\t\t\t\taria-pressed={currentLanguage === lang}\n\t\t\t\t\t\tdata-active={currentLanguage === lang}\n\t\t\t\t\t>\n\t\t\t\t\t\t{formatLanguageDisplay(lang, display)}\n\t\t\t\t\t</button>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (variant === \"minimal\") {\n\t\treturn (\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName={className}\n\t\t\t\tonClick={() => {\n\t\t\t\t\tconst currentIndex = availableLanguages.indexOf(currentLanguage);\n\t\t\t\t\tconst nextIndex = (currentIndex + 1) % availableLanguages.length;\n\t\t\t\t\thandleChange(availableLanguages[nextIndex]);\n\t\t\t\t}}\n\t\t\t\taria-label={`Current language: ${getLanguageInfo(currentLanguage).name}. Click to change.`}\n\t\t\t>\n\t\t\t\t{formatLanguageDisplay(currentLanguage, display)}\n\t\t\t</button>\n\t\t);\n\t}\n\n\treturn (\n\t\t<select\n\t\t\tvalue={currentLanguage}\n\t\t\tonChange={(e) => handleChange(e.target.value)}\n\t\t\tclassName={className}\n\t\t\taria-label=\"Select language\"\n\t\t>\n\t\t\t{availableLanguages.map((lang) => (\n\t\t\t\t<option key={lang} value={lang}>\n\t\t\t\t\t{formatLanguageDisplay(lang, display)}\n\t\t\t\t</option>\n\t\t\t))}\n\t\t</select>\n\t);\n}\n","import { useCallback } from \"react\";\nimport { getTranslation, useTranslationStore } from \"../store\";\nimport type { CTFunction, InterpolationValues } from \"../types\";\n\nfunction isInterpolationValues(arg: unknown): arg is InterpolationValues {\n\treturn (\n\t\ttypeof arg === \"object\" &&\n\t\targ !== null &&\n\t\t!Array.isArray(arg) &&\n\t\t!(arg instanceof Date)\n\t);\n}\n\nexport function useCt(): CTFunction {\n\tconst { translations, currentLanguage } = useTranslationStore();\n\n\tconst ct = useCallback(\n\t\t(\n\t\t\ttext: string,\n\t\t\tcontextOrValues?: string | InterpolationValues,\n\t\t\tmaybeValues?: InterpolationValues,\n\t\t): string => {\n\t\t\tlet values: InterpolationValues | undefined;\n\n\t\t\tif (typeof contextOrValues === \"string\") {\n\t\t\t\tvalues = maybeValues;\n\t\t\t} else if (isInterpolationValues(contextOrValues)) {\n\t\t\t\tvalues = contextOrValues;\n\t\t\t}\n\n\t\t\treturn getTranslation(translations, currentLanguage, text, values);\n\t\t},\n\t\t[translations, currentLanguage],\n\t) as CTFunction;\n\n\treturn ct;\n}\n","import React, {\n\tChildren,\n\tcloneElement,\n\tisValidElement,\n\ttype ReactNode,\n\ttype ReactElement,\n} from \"react\";\nimport { useCt } from \"../hooks/useCt\";\nimport type { InterpolationValues } from \"../types\";\n\nexport interface TransProps {\n\tchildren: ReactNode;\n\tcontext?: string;\n\tvalues?: InterpolationValues;\n}\n\ninterface ParsedChild {\n\ttype: \"text\" | \"element\";\n\tcontent: string;\n\telement?: ReactElement;\n\tindex?: number;\n}\n\nfunction parseChildren(children: ReactNode): {\n\ttemplate: string;\n\telements: ReactElement[];\n} {\n\tconst elements: ReactElement[] = [];\n\tlet template = \"\";\n\n\tconst processNode = (node: ReactNode): string => {\n\t\tif (node === null || node === undefined) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (typeof node === \"string\") {\n\t\t\treturn node;\n\t\t}\n\n\t\tif (typeof node === \"number\") {\n\t\t\treturn String(node);\n\t\t}\n\n\t\tif (isValidElement(node)) {\n\t\t\tconst index = elements.length;\n\t\t\telements.push(node);\n\t\t\tconst innerContent = processNode(node.props.children);\n\t\t\treturn `<${index}>${innerContent}</${index}>`;\n\t\t}\n\n\t\tif (Array.isArray(node)) {\n\t\t\treturn node.map(processNode).join(\"\");\n\t\t}\n\n\t\treturn \"\";\n\t};\n\n\ttemplate = processNode(children);\n\treturn { template, elements };\n}\n\nfunction reconstructChildren(\n\ttranslated: string,\n\telements: ReactElement[],\n): ReactNode {\n\tif (elements.length === 0) {\n\t\treturn translated;\n\t}\n\n\tconst result: ReactNode[] = [];\n\tlet remaining = translated;\n\tlet keyCounter = 0;\n\n\tconst tagRegex = /<(\\d+)>(.*?)<\\/\\1>/gs;\n\n\tlet lastIndex = 0;\n\tlet match: RegExpExecArray | null;\n\n\t// Reset regex state\n\ttagRegex.lastIndex = 0;\n\n\twhile ((match = tagRegex.exec(translated)) !== null) {\n\t\t// Add text before the match\n\t\tif (match.index > lastIndex) {\n\t\t\tconst textBefore = translated.slice(lastIndex, match.index);\n\t\t\tif (textBefore) {\n\t\t\t\tresult.push(textBefore);\n\t\t\t}\n\t\t}\n\n\t\tconst elementIndex = parseInt(match[1], 10);\n\t\tconst innerContent = match[2];\n\t\tconst originalElement = elements[elementIndex];\n\n\t\tif (originalElement) {\n\t\t\t// Recursively process inner content in case of nested tags\n\t\t\tconst processedInner = reconstructChildren(innerContent, elements);\n\t\t\tconst cloned = cloneElement(originalElement, {\n\t\t\t\tkey: `trans-${keyCounter++}`,\n\t\t\t\tchildren: processedInner,\n\t\t\t});\n\t\t\tresult.push(cloned);\n\t\t}\n\n\t\tlastIndex = match.index + match[0].length;\n\t}\n\n\t// Add remaining text after last match\n\tif (lastIndex < translated.length) {\n\t\tresult.push(translated.slice(lastIndex));\n\t}\n\n\t// If no matches found, return the original string\n\tif (result.length === 0) {\n\t\treturn translated;\n\t}\n\n\treturn result.length === 1 ? result[0] : result;\n}\n\nexport function Trans({ children, context, values }: TransProps) {\n\tconst ct = useCt();\n\n\t// Parse children to extract template and elements\n\tconst { template, elements } = parseChildren(children);\n\n\t// Translate the template\n\tlet translated: string;\n\tif (context && values) {\n\t\ttranslated = ct(template, context, values);\n\t} else if (context) {\n\t\ttranslated = ct(template, context);\n\t} else if (values) {\n\t\ttranslated = ct(template, values);\n\t} else {\n\t\ttranslated = ct(template);\n\t}\n\n\t// Reconstruct with original elements\n\treturn <>{reconstructChildren(translated, elements)}</>;\n}\n","import { useCallback } from \"react\";\nimport { useTranslationStore } from \"../store\";\nimport {\n\tgetLanguageInfo,\n\tgetFullLanguageInfo,\n\tLANGUAGE_DATA,\n\ttype LanguageInfo,\n} from \"../components/LanguageSwitcher\";\n\nexport function useCurrentLanguage(): string {\n\treturn useTranslationStore((state) => state.currentLanguage);\n}\n\nexport function useSetLanguage(): (language: string) => void {\n\treturn useTranslationStore((state) => state.setLanguage);\n}\n\nexport function useAvailableLanguages(): string[] {\n\treturn useTranslationStore((state) => state.availableLanguages);\n}\n\nexport function useIsLoading(): boolean {\n\treturn useTranslationStore((state) => state.isLoading);\n}\n\nexport function useIsReady(): boolean {\n\treturn useTranslationStore((state) => state.isReady);\n}\n\nexport function useLanguageInfo(code?: string): LanguageInfo {\n\tconst currentLanguage = useTranslationStore((state) => state.currentLanguage);\n\tconst targetCode = code ?? currentLanguage;\n\treturn getFullLanguageInfo(targetCode);\n}\n\nexport function useAvailableLanguagesInfo(): LanguageInfo[] {\n\tconst availableLanguages = useTranslationStore(\n\t\t(state) => state.availableLanguages,\n\t);\n\treturn availableLanguages.map(getFullLanguageInfo);\n}\n\nexport function useLanguage() {\n\tconst currentLanguage = useTranslationStore((state) => state.currentLanguage);\n\tconst availableLanguages = useTranslationStore(\n\t\t(state) => state.availableLanguages,\n\t);\n\tconst setLanguage = useTranslationStore((state) => state.setLanguage);\n\tconst isLoading = useTranslationStore((state) => state.isLoading);\n\tconst isReady = useTranslationStore((state) => state.isReady);\n\n\tconst currentLanguageInfo = getFullLanguageInfo(currentLanguage);\n\tconst availableLanguagesInfo = availableLanguages.map(getFullLanguageInfo);\n\n\tconst cycleLanguage = useCallback(() => {\n\t\tconst currentIndex = availableLanguages.indexOf(currentLanguage);\n\t\tconst nextIndex = (currentIndex + 1) % availableLanguages.length;\n\t\tsetLanguage(availableLanguages[nextIndex]);\n\t}, [availableLanguages, currentLanguage, setLanguage]);\n\n\treturn {\n\t\tcurrentLanguage,\n\t\tcurrentLanguageInfo,\n\t\tavailableLanguages,\n\t\tavailableLanguagesInfo,\n\t\tsetLanguage,\n\t\tcycleLanguage,\n\t\tisLoading,\n\t\tisReady,\n\t};\n}\n\nexport {\n\tgetLanguageInfo,\n\tgetFullLanguageInfo,\n\tLANGUAGE_DATA,\n\ttype LanguageInfo,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["dbPromise: Promise<IDBDatabase> | null","entry: CacheEntry","options: Intl.DateTimeFormatOptions","result: string","key: string","format: string | undefined","hydrationResolver: (() => void) | null","updatedLanguages: string[]","LANGUAGE_DATA: Record<\n\tstring,\n\t{ name: string; nativeName: string; flag: string }\n>","values: InterpolationValues | undefined","elements: ReactElement[]","result: ReactNode[]","match: RegExpExecArray | null","translated: string"],"sources":["../src/components/CTContextBlock.tsx","../src/cache.ts","../src/interpolate.ts","../src/store.ts","../src/hooks/useHotUpdates.ts","../src/components/CTProvider.tsx","../src/components/LanguageSwitcher.tsx","../src/hooks/useCt.ts","../src/components/Trans.tsx","../src/hooks/useLanguage.ts"],"sourcesContent":["import React from \"react\";\nimport type { CTContextBlockProps } from \"../types\";\n\nexport function CTContextBlock({ children }: CTContextBlockProps) {\n\treturn <>{children}</>;\n}\n","import type { TranslationMap } from \"./types\";\n\nconst DB_NAME = \"ciao-tools-translations\";\nconst DB_VERSION = 1;\nconst STORE_NAME = \"translations\";\n\ninterface CacheEntry {\n\tlanguage: string;\n\tprojectId: string;\n\tdata: TranslationMap;\n\turl: string;\n\tcachedAt: number;\n}\n\nlet dbPromise: Promise<IDBDatabase> | null = null;\n\nfunction openDB(): Promise<IDBDatabase> {\n\tif (dbPromise) return dbPromise;\n\n\tdbPromise = new Promise((resolve, reject) => {\n\t\tif (typeof indexedDB === \"undefined\") {\n\t\t\treject(new Error(\"IndexedDB not available\"));\n\t\t\treturn;\n\t\t}\n\n\t\tconst request = indexedDB.open(DB_NAME, DB_VERSION);\n\n\t\trequest.onerror = () => reject(request.error);\n\t\trequest.onsuccess = () => resolve(request.result);\n\n\t\trequest.onupgradeneeded = (event) => {\n\t\t\tconst db = (event.target as IDBOpenDBRequest).result;\n\t\t\tif (!db.objectStoreNames.contains(STORE_NAME)) {\n\t\t\t\tconst store = db.createObjectStore(STORE_NAME, { keyPath: \"url\" });\n\t\t\t\tstore.createIndex(\"language\", \"language\", { unique: false });\n\t\t\t\tstore.createIndex(\"projectId\", \"projectId\", { unique: false });\n\t\t\t}\n\t\t};\n\t});\n\n\treturn dbPromise;\n}\n\nexport async function getCachedTranslation(\n\turl: string,\n): Promise<TranslationMap | null> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readonly\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\t\t\tconst request = store.get(url);\n\n\t\t\trequest.onerror = () => reject(request.error);\n\t\t\trequest.onsuccess = () => {\n\t\t\t\tconst entry = request.result as CacheEntry | undefined;\n\t\t\t\tresolve(entry?.data ?? null);\n\t\t\t};\n\t\t});\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function cacheTranslation(\n\turl: string,\n\tlanguage: string,\n\tprojectId: string,\n\tdata: TranslationMap,\n): Promise<void> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readwrite\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\n\t\t\tconst entry: CacheEntry = {\n\t\t\t\turl,\n\t\t\t\tlanguage,\n\t\t\t\tprojectId,\n\t\t\t\tdata,\n\t\t\t\tcachedAt: Date.now(),\n\t\t\t};\n\n\t\t\tconst request = store.put(entry);\n\t\t\trequest.onerror = () => reject(request.error);\n\t\t\trequest.onsuccess = () => resolve();\n\t\t});\n\t} catch {\n\t\t// Silently fail - caching is optional\n\t}\n}\n\nexport async function clearCache(projectId?: string): Promise<void> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readwrite\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\n\t\t\tif (projectId) {\n\t\t\t\tconst index = store.index(\"projectId\");\n\t\t\t\tconst request = index.openCursor(IDBKeyRange.only(projectId));\n\t\t\t\trequest.onsuccess = (event) => {\n\t\t\t\t\tconst cursor = (event.target as IDBRequest).result;\n\t\t\t\t\tif (cursor) {\n\t\t\t\t\t\tcursor.delete();\n\t\t\t\t\t\tcursor.continue();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\ttransaction.oncomplete = () => resolve();\n\t\t\t\ttransaction.onerror = () => reject(transaction.error);\n\t\t\t} else {\n\t\t\t\tconst request = store.clear();\n\t\t\t\trequest.onerror = () => reject(request.error);\n\t\t\t\trequest.onsuccess = () => resolve();\n\t\t\t}\n\t\t});\n\t} catch {\n\t\t// Silently fail\n\t}\n}\n\nexport async function getCacheStats(): Promise<{\n\tcount: number;\n\tlanguages: string[];\n}> {\n\ttry {\n\t\tconst db = await openDB();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst transaction = db.transaction(STORE_NAME, \"readonly\");\n\t\t\tconst store = transaction.objectStore(STORE_NAME);\n\n\t\t\tconst countRequest = store.count();\n\t\t\tconst languages = new Set<string>();\n\n\t\t\tconst cursorRequest = store.openCursor();\n\t\t\tcursorRequest.onsuccess = (event) => {\n\t\t\t\tconst cursor = (event.target as IDBRequest).result;\n\t\t\t\tif (cursor) {\n\t\t\t\t\tlanguages.add((cursor.value as CacheEntry).language);\n\t\t\t\t\tcursor.continue();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\ttransaction.oncomplete = () => {\n\t\t\t\tresolve({\n\t\t\t\t\tcount: countRequest.result,\n\t\t\t\t\tlanguages: Array.from(languages),\n\t\t\t\t});\n\t\t\t};\n\t\t\ttransaction.onerror = () => reject(transaction.error);\n\t\t});\n\t} catch {\n\t\treturn { count: 0, languages: [] };\n\t}\n}\n","export type InterpolationValues = Record<string, unknown>;\n\nconst numberFormatCache = new Map<string, Intl.NumberFormat>();\nconst dateFormatCache = new Map<string, Intl.DateTimeFormat>();\nconst pluralRulesCache = new Map<string, Intl.PluralRules>();\n\nexport function clearFormatterCache(): void {\n\tnumberFormatCache.clear();\n\tdateFormatCache.clear();\n\tpluralRulesCache.clear();\n}\n\nfunction getNumberFormatter(locale: string): Intl.NumberFormat {\n\tconst key = `number:${locale}`;\n\tif (!numberFormatCache.has(key)) {\n\t\tnumberFormatCache.set(\n\t\t\tkey,\n\t\t\tnew Intl.NumberFormat(locale, {\n\t\t\t\tmaximumFractionDigits: 20,\n\t\t\t}),\n\t\t);\n\t}\n\treturn numberFormatCache.get(key)!;\n}\n\nfunction getCurrencyFormatter(\n\tlocale: string,\n\tcurrency: string,\n): Intl.NumberFormat {\n\tconst key = `currency:${locale}:${currency}`;\n\tif (!numberFormatCache.has(key)) {\n\t\tnumberFormatCache.set(\n\t\t\tkey,\n\t\t\tnew Intl.NumberFormat(locale, {\n\t\t\t\tstyle: \"currency\",\n\t\t\t\tcurrency,\n\t\t\t}),\n\t\t);\n\t}\n\treturn numberFormatCache.get(key)!;\n}\n\nfunction getPercentFormatter(locale: string): Intl.NumberFormat {\n\tconst key = `percent:${locale}`;\n\tif (!numberFormatCache.has(key)) {\n\t\tnumberFormatCache.set(\n\t\t\tkey,\n\t\t\tnew Intl.NumberFormat(locale, {\n\t\t\t\tstyle: \"percent\",\n\t\t\t\tminimumFractionDigits: 0,\n\t\t\t\tmaximumFractionDigits: 2,\n\t\t\t}),\n\t\t);\n\t}\n\treturn numberFormatCache.get(key)!;\n}\n\nfunction getDateFormatter(\n\tlocale: string,\n\tstyle: \"short\" | \"medium\" | \"long\" | \"full\",\n): Intl.DateTimeFormat {\n\tconst key = `date:${locale}:${style}`;\n\tif (!dateFormatCache.has(key)) {\n\t\tconst options: Intl.DateTimeFormatOptions = {\n\t\t\tdateStyle: style,\n\t\t};\n\t\tdateFormatCache.set(key, new Intl.DateTimeFormat(locale, options));\n\t}\n\treturn dateFormatCache.get(key)!;\n}\n\nfunction getTimeFormatter(\n\tlocale: string,\n\tstyle: \"short\" | \"medium\" | \"long\" | \"full\",\n): Intl.DateTimeFormat {\n\tconst key = `time:${locale}:${style}`;\n\tif (!dateFormatCache.has(key)) {\n\t\tconst options: Intl.DateTimeFormatOptions = {\n\t\t\ttimeStyle: style,\n\t\t};\n\t\tdateFormatCache.set(key, new Intl.DateTimeFormat(locale, options));\n\t}\n\treturn dateFormatCache.get(key)!;\n}\n\nfunction getPluralRules(locale: string): Intl.PluralRules {\n\tif (!pluralRulesCache.has(locale)) {\n\t\tpluralRulesCache.set(locale, new Intl.PluralRules(locale));\n\t}\n\treturn pluralRulesCache.get(locale)!;\n}\n\nfunction formatValue(\n\tvalue: unknown,\n\tformat: string | undefined,\n\tlocale: string,\n): string {\n\tif (value === null || value === undefined) {\n\t\treturn \"\";\n\t}\n\n\tif (!format) {\n\t\treturn String(value);\n\t}\n\n\tconst parts = format.split(\":\");\n\tconst formatType = parts[0];\n\n\tswitch (formatType) {\n\t\tcase \"number\": {\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tif (Number.isNaN(num)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn getNumberFormatter(locale).format(num);\n\t\t}\n\n\t\tcase \"currency\": {\n\t\t\tconst currency = parts[1];\n\t\t\tif (!currency) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tif (Number.isNaN(num)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn getCurrencyFormatter(locale, currency).format(num);\n\t\t}\n\n\t\tcase \"percent\": {\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tif (Number.isNaN(num)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn getPercentFormatter(locale).format(num);\n\t\t}\n\n\t\tcase \"date\": {\n\t\t\tif (!(value instanceof Date)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst style =\n\t\t\t\t(parts[1] as \"short\" | \"medium\" | \"long\" | \"full\") || \"medium\";\n\t\t\treturn getDateFormatter(locale, style).format(value);\n\t\t}\n\n\t\tcase \"time\": {\n\t\t\tif (!(value instanceof Date)) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst style =\n\t\t\t\t(parts[1] as \"short\" | \"medium\" | \"long\" | \"full\") || \"medium\";\n\t\t\treturn getTimeFormatter(locale, style).format(value);\n\t\t}\n\n\t\tcase \"plural\": {\n\t\t\tconst singular = parts[1];\n\t\t\tconst plural = parts[2];\n\t\t\tif (!singular || !plural) {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\tconst num = typeof value === \"number\" ? value : Number(value);\n\t\t\tconst rules = getPluralRules(locale);\n\t\t\tconst category = rules.select(num);\n\t\t\treturn category === \"one\" ? singular : plural;\n\t\t}\n\n\t\tdefault:\n\t\t\treturn String(value);\n\t}\n}\n\nexport function interpolate(\n\ttext: string,\n\tvalues: InterpolationValues | undefined,\n\tlocale: string,\n): string {\n\t// Temporarily replace escaped braces with placeholder characters\n\tconst escaped = text.replace(/\\{\\{/g, \"\\x00\").replace(/\\}\\}/g, \"\\x01\");\n\n\tlet result: string;\n\tif (!values || Object.keys(values).length === 0) {\n\t\tresult = escaped;\n\t} else {\n\t\tresult = escaped.replace(/\\{([^}]+)\\}/g, (match, placeholder) => {\n\t\t\tconst trimmed = placeholder.trim();\n\t\t\tconst colonIndex = trimmed.indexOf(\":\");\n\n\t\t\tlet key: string;\n\t\t\tlet format: string | undefined;\n\n\t\t\tif (colonIndex === -1) {\n\t\t\t\tkey = trimmed;\n\t\t\t\tformat = undefined;\n\t\t\t} else {\n\t\t\t\tkey = trimmed.substring(0, colonIndex);\n\t\t\t\tformat = trimmed.substring(colonIndex + 1);\n\t\t\t}\n\n\t\t\tif (!(key in values)) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tconst value = values[key];\n\t\t\treturn formatValue(value, format, locale);\n\t\t});\n\t}\n\n\t// Restore escaped braces\n\treturn result.replace(/\\x00/g, \"{\").replace(/\\x01/g, \"}\");\n}\n","import { create } from \"zustand\";\nimport { persist } from \"zustand/middleware\";\nimport { interpolate } from \"./interpolate\";\nimport type {\n\tInterpolationValues,\n\tLanguageTranslations,\n\tTranslationMap,\n\tTranslationStore,\n} from \"./types\";\n\nlet hydrationResolver: (() => void) | null = null;\nconst hydrationPromise = new Promise<void>((resolve) => {\n\thydrationResolver = resolve;\n});\n\nexport const useTranslationStore = create<TranslationStore>()(\n\tpersist(\n\t\t(set) => ({\n\t\t\tcurrentLanguage: \"en\",\n\t\t\tdefaultLanguage: \"en\",\n\t\t\tavailableLanguages: [\"en\"],\n\t\t\ttranslations: {},\n\t\t\tisLoading: false,\n\t\t\tisReady: false,\n\t\t\tisHydrated: false,\n\t\t\tserverVersion: null,\n\t\t\tlastVersionCheck: null,\n\n\t\t\tsetLanguage: (language: string) => {\n\t\t\t\tset({ currentLanguage: language, isReady: false });\n\t\t\t},\n\n\t\t\tloadTranslations: (translations: LanguageTranslations) => {\n\t\t\t\tset((state) => {\n\t\t\t\t\tconst languages = Object.keys(translations);\n\t\t\t\t\tconst availableLanguages = [\n\t\t\t\t\t\t...new Set([...state.availableLanguages, ...languages]),\n\t\t\t\t\t];\n\t\t\t\t\tconst merged = { ...state.translations };\n\t\t\t\t\tfor (const lang of languages) {\n\t\t\t\t\t\tmerged[lang] = { ...merged[lang], ...translations[lang] };\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttranslations: merged,\n\t\t\t\t\t\tavailableLanguages,\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t},\n\n\t\t\taddLanguage: (language: string, translations: TranslationMap) => {\n\t\t\t\tset((state) => ({\n\t\t\t\t\ttranslations: {\n\t\t\t\t\t\t...state.translations,\n\t\t\t\t\t\t[language]: { ...state.translations[language], ...translations },\n\t\t\t\t\t},\n\t\t\t\t\tavailableLanguages: state.availableLanguages.includes(language)\n\t\t\t\t\t\t? state.availableLanguages\n\t\t\t\t\t\t: [...state.availableLanguages, language],\n\t\t\t\t}));\n\t\t\t},\n\n\t\t\tsetLoading: (loading: boolean) => {\n\t\t\t\tset({ isLoading: loading });\n\t\t\t},\n\n\t\t\tsetReady: (ready: boolean) => {\n\t\t\t\tset({ isReady: ready });\n\t\t\t},\n\n\t\t\tsetServerVersion: (version: number) => {\n\t\t\t\tset({ serverVersion: version, lastVersionCheck: Date.now() });\n\t\t\t},\n\t\t}),\n\t\t{\n\t\t\tname: \"ciao-tools-language\",\n\t\t\tpartialize: (state) => ({\n\t\t\t\tcurrentLanguage: state.currentLanguage,\n\t\t\t\tserverVersion: state.serverVersion,\n\t\t\t}),\n\t\t\tonRehydrateStorage: () => (_, error) => {\n\t\t\t\tif (!error && hydrationResolver) {\n\t\t\t\t\thydrationResolver();\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t),\n);\n\nhydrationPromise.then(() => {\n\tuseTranslationStore.setState({ isHydrated: true });\n});\n\nexport function getTranslation(\n\ttranslations: LanguageTranslations,\n\tlanguage: string,\n\ttext: string,\n\tvalues?: InterpolationValues,\n): string {\n\tconst translated = translations[language]?.[text] ?? text;\n\n\tif (!values || Object.keys(values).length === 0) {\n\t\treturn translated;\n\t}\n\n\treturn interpolate(translated, values, language);\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { clearCache, cacheTranslation } from \"../cache\";\nimport { useTranslationStore } from \"../store\";\nimport type { HotUpdateConfig, TranslationMap } from \"../types\";\n\nconst CDN_BASE_URL = \"https://t1.ciao-tools.com\";\n\ninterface LatestManifest {\n\tversion: number;\n\tupdatedAt: string;\n\turls: Record<string, string>;\n}\n\nasync function fetchLatestManifest(projectId: string): Promise<LatestManifest | null> {\n\tconst url = `${CDN_BASE_URL}/translations/${projectId}/latest.json`;\n\ttry {\n\t\tconst response = await fetch(url, { cache: \"no-cache\" });\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 404) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tthrow new Error(`Failed to fetch latest manifest: ${response.statusText}`);\n\t\t}\n\t\treturn response.json();\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function fetchTranslations(url: string): Promise<TranslationMap> {\n\tconst response = await fetch(url);\n\tif (!response.ok) {\n\t\tthrow new Error(`Failed to fetch translations: ${response.statusText}`);\n\t}\n\treturn response.json();\n}\n\nexport function useHotUpdates(\n\tconfig: HotUpdateConfig | undefined,\n\tprojectId: string | undefined,\n) {\n\tconst isCheckingRef = useRef(false);\n\tconst hasCheckedOnMountRef = useRef(false);\n\n\tconst { serverVersion, setServerVersion, addLanguage } = useTranslationStore();\n\n\tconst checkForUpdates = useCallback(async () => {\n\t\tif (!config || !projectId || isCheckingRef.current) return;\n\t\tif (config.enabled !== true) return;\n\n\t\tisCheckingRef.current = true;\n\n\t\ttry {\n\t\t\tconsole.log(\"[ciao-tools] Checking for hot updates...\");\n\t\t\tconst manifest = await fetchLatestManifest(projectId);\n\n\t\t\tif (!manifest) {\n\t\t\t\tconsole.log(\"[ciao-tools] No latest.json found (project may not have hot updates yet)\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconsole.log(\"[ciao-tools] Found latest.json, version:\", manifest.version);\n\n\t\t\tconst isFirstCheck = serverVersion === null;\n\t\t\tconst hasNewVersion = serverVersion !== null && manifest.version > serverVersion;\n\n\t\t\tif (isFirstCheck || hasNewVersion) {\n\t\t\t\tif (Object.keys(manifest.urls).length > 0) {\n\t\t\t\t\tconst reason = hasNewVersion ? \"new version\" : \"first check\";\n\t\t\t\t\tconsole.log(`[ciao-tools] Fetching translations (${reason})...`);\n\n\t\t\t\t\t// Only clear cache when there's actually a new version\n\t\t\t\t\tif (hasNewVersion) {\n\t\t\t\t\t\tawait clearCache(projectId);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst updatedLanguages: string[] = [];\n\n\t\t\t\t\tfor (const [langCode, url] of Object.entries(manifest.urls)) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst translations = await fetchTranslations(url);\n\t\t\t\t\t\t\taddLanguage(langCode, translations);\n\t\t\t\t\t\t\tawait cacheTranslation(url, langCode, projectId, translations);\n\t\t\t\t\t\t\tupdatedLanguages.push(langCode);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tconsole.error(`[ciao-tools] Failed to fetch ${langCode} translations:`, err);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (updatedLanguages.length > 0) {\n\t\t\t\t\t\tconsole.log(\"[ciao-tools] Updated translations for:\", updatedLanguages);\n\t\t\t\t\t\tif (hasNewVersion && config.onTranslationsUpdated) {\n\t\t\t\t\t\t\tconfig.onTranslationsUpdated(updatedLanguages);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconsole.log(\"[ciao-tools] Already up to date (version \" + manifest.version + \")\");\n\t\t\t}\n\n\t\t\tsetServerVersion(manifest.version);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"[ciao-tools] Hot update check failed:\", error);\n\t\t} finally {\n\t\t\tisCheckingRef.current = false;\n\t\t}\n\t}, [config, projectId, serverVersion, setServerVersion, addLanguage]);\n\n\tuseEffect(() => {\n\t\tif (!config || !projectId) return;\n\t\tif (config.enabled !== true) return;\n\n\t\tif (!hasCheckedOnMountRef.current) {\n\t\t\thasCheckedOnMountRef.current = true;\n\t\t\tcheckForUpdates();\n\t\t}\n\n\t\tconst handleVisibilityChange = () => {\n\t\t\tif (document.visibilityState === \"visible\") {\n\t\t\t\tcheckForUpdates();\n\t\t\t}\n\t\t};\n\n\t\tdocument.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n\t\t};\n\t}, [config, projectId, checkForUpdates]);\n\n\treturn { checkForUpdates };\n}\n","import React, { useCallback, useEffect, useRef, type ReactNode } from \"react\";\nimport { getCachedTranslation, cacheTranslation } from \"../cache\";\nimport { useTranslationStore } from \"../store\";\nimport { useHotUpdates } from \"../hooks/useHotUpdates\";\nimport type { CiaoManifest, CTProviderProps, TranslationMap } from \"../types\";\n\nconst PRELOAD_DELAY_MS = 5000;\n\nasync function fetchTranslationsFromCDN(url: string): Promise<TranslationMap> {\n\tconst response = await fetch(url);\n\tif (!response.ok) {\n\t\tthrow new Error(`Failed to fetch translations: ${response.statusText}`);\n\t}\n\treturn response.json();\n}\n\nfunction detectBrowserLanguage(availableLanguages: string[]): string | null {\n\tif (typeof navigator === \"undefined\") return null;\n\n\tconst browserLangs = navigator.languages || [navigator.language];\n\n\tfor (const browserLang of browserLangs) {\n\t\tconst normalized = browserLang.toLowerCase();\n\t\tif (availableLanguages.includes(normalized)) {\n\t\t\treturn normalized;\n\t\t}\n\t\tconst langCode = normalized.split(\"-\")[0];\n\t\tif (availableLanguages.includes(langCode)) {\n\t\t\treturn langCode;\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction getManifestUrlsHash(manifest: CiaoManifest | undefined): string {\n\tif (!manifest) return \"\";\n\treturn JSON.stringify(manifest.cdnUrls);\n}\n\nexport function CTProvider({\n\tchildren,\n\ttranslations,\n\tmanifest,\n\tdefaultLanguage = \"en\",\n\tavailableLanguages,\n\tonLanguageChange,\n\tdetectLanguage = true,\n\tblockUntilReady = true,\n\tfallback = null,\n\tpreloadLanguages = true,\n\tpreloadDelay = PRELOAD_DELAY_MS,\n\thotUpdates,\n}: CTProviderProps) {\n\tconst {\n\t\tloadTranslations,\n\t\tsetLanguage,\n\t\taddLanguage,\n\t\tsetLoading,\n\t\tsetReady,\n\t\tcurrentLanguage,\n\t\ttranslations: storeTranslations,\n\t\tisReady,\n\t\tisHydrated,\n\t} = useTranslationStore();\n\n\tconst manifestRef = useRef<CiaoManifest | undefined>(manifest);\n\tconst loadedUrlsRef = useRef<Map<string, string>>(new Map());\n\tconst previousManifestHashRef = useRef<string>(\"\");\n\tconst initializedRef = useRef(false);\n\tconst preloadTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n\tuseEffect(() => {\n\t\tmanifestRef.current = manifest;\n\n\t\tconst newHash = getManifestUrlsHash(manifest);\n\t\tconst oldHash = previousManifestHashRef.current;\n\n\t\tif (oldHash && newHash && oldHash !== newHash) {\n\t\t\tloadedUrlsRef.current.clear();\n\t\t\tuseTranslationStore.setState({ translations: {} });\n\t\t}\n\n\t\tpreviousManifestHashRef.current = newHash;\n\t}, [manifest]);\n\n\tuseEffect(() => {\n\t\tif (translations) {\n\t\t\tloadTranslations(translations);\n\t\t\tsetReady(true);\n\t\t}\n\t}, [translations, loadTranslations, setReady]);\n\n\tuseEffect(() => {\n\t\tif (!isHydrated) return;\n\t\tif (initializedRef.current) return;\n\t\tinitializedRef.current = true;\n\n\t\tconst store = useTranslationStore.getState();\n\t\tconst effectiveLanguages = manifest\n\t\t\t? [...manifest.languages]\n\t\t\t: availableLanguages || [];\n\n\t\tconst hasPersistedLanguage =\n\t\t\tstore.currentLanguage &&\n\t\t\tstore.currentLanguage !== \"en\" &&\n\t\t\teffectiveLanguages.includes(store.currentLanguage);\n\n\t\tif (hasPersistedLanguage) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (detectLanguage && effectiveLanguages.length > 0) {\n\t\t\tconst detected = detectBrowserLanguage(effectiveLanguages);\n\t\t\tif (detected) {\n\t\t\t\tsetLanguage(detected);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (defaultLanguage && defaultLanguage !== store.currentLanguage) {\n\t\t\tsetLanguage(defaultLanguage);\n\t\t}\n\t}, [\n\t\tmanifest,\n\t\tavailableLanguages,\n\t\tdefaultLanguage,\n\t\tdetectLanguage,\n\t\tsetLanguage,\n\t\tisHydrated,\n\t]);\n\n\tuseEffect(() => {\n\t\tconst effectiveLanguages = manifest\n\t\t\t? [...manifest.languages]\n\t\t\t: availableLanguages;\n\n\t\tif (effectiveLanguages) {\n\t\t\tconst store = useTranslationStore.getState();\n\t\t\tconst merged = [\n\t\t\t\t...new Set([...store.availableLanguages, ...effectiveLanguages]),\n\t\t\t];\n\t\t\tuseTranslationStore.setState({\n\t\t\t\tavailableLanguages: merged,\n\t\t\t\tdefaultLanguage,\n\t\t\t});\n\t\t}\n\t}, [availableLanguages, manifest, defaultLanguage]);\n\n\tconst loadLanguageFromCDN = useCallback(\n\t\tasync (language: string, isPreload = false): Promise<boolean> => {\n\t\t\tconst currentManifest = manifestRef.current;\n\t\t\tif (!currentManifest) {\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst cdnUrl = currentManifest.cdnUrls[language];\n\t\t\tif (!cdnUrl) {\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst loadedUrl = loadedUrlsRef.current.get(language);\n\t\t\tif (loadedUrl === cdnUrl) {\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (!isPreload) {\n\t\t\t\tsetLoading(true);\n\t\t\t\tsetReady(false);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst cached = await getCachedTranslation(cdnUrl);\n\t\t\t\tif (cached) {\n\t\t\t\t\taddLanguage(language, cached);\n\t\t\t\t\tloadedUrlsRef.current.set(language, cdnUrl);\n\t\t\t\t\tif (!isPreload) {\n\t\t\t\t\t\tsetReady(true);\n\t\t\t\t\t\tsetLoading(false);\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tconst translationData = await fetchTranslationsFromCDN(cdnUrl);\n\t\t\t\taddLanguage(language, translationData);\n\t\t\t\tloadedUrlsRef.current.set(language, cdnUrl);\n\n\t\t\t\tawait cacheTranslation(\n\t\t\t\t\tcdnUrl,\n\t\t\t\t\tlanguage,\n\t\t\t\t\tcurrentManifest.projectId,\n\t\t\t\t\ttranslationData,\n\t\t\t\t);\n\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn true;\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`[ciao-tools] Failed to load translations for ${language}:`,\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t\tif (!isPreload) setReady(true);\n\t\t\t\treturn false;\n\t\t\t} finally {\n\t\t\t\tif (!isPreload) setLoading(false);\n\t\t\t}\n\t\t},\n\t\t[addLanguage, setLoading, setReady],\n\t);\n\n\tuseEffect(() => {\n\t\tif (!isHydrated) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (currentLanguage === manifest?.sourceLanguage) {\n\t\t\tsetReady(true);\n\t\t\treturn;\n\t\t}\n\n\t\tif (manifest && currentLanguage) {\n\t\t\tloadLanguageFromCDN(currentLanguage, false);\n\t\t} else if (!manifest) {\n\t\t\tsetReady(true);\n\t\t}\n\t}, [manifest, currentLanguage, loadLanguageFromCDN, setReady, isHydrated]);\n\n\tuseEffect(() => {\n\t\tif (!preloadLanguages || !manifest) return;\n\n\t\tif (preloadTimeoutRef.current) {\n\t\t\tclearTimeout(preloadTimeoutRef.current);\n\t\t}\n\n\t\tpreloadTimeoutRef.current = setTimeout(async () => {\n\t\t\tconst languages = [...manifest.languages];\n\t\t\tfor (const language of languages) {\n\t\t\t\tif (language === manifest.sourceLanguage) continue;\n\t\t\t\tif (language === currentLanguage) continue;\n\n\t\t\t\tawait loadLanguageFromCDN(language, true);\n\t\t\t}\n\t\t}, preloadDelay);\n\n\t\treturn () => {\n\t\t\tif (preloadTimeoutRef.current) {\n\t\t\t\tclearTimeout(preloadTimeoutRef.current);\n\t\t\t}\n\t\t};\n\t}, [\n\t\tmanifest,\n\t\tcurrentLanguage,\n\t\tpreloadLanguages,\n\t\tpreloadDelay,\n\t\tloadLanguageFromCDN,\n\t]);\n\n\tuseEffect(() => {\n\t\tif (onLanguageChange) {\n\t\t\tonLanguageChange(currentLanguage);\n\t\t}\n\t}, [currentLanguage, onLanguageChange]);\n\n\tuseHotUpdates(hotUpdates, manifest?.projectId);\n\n\tif (blockUntilReady && (!isReady || !isHydrated)) {\n\t\treturn <>{fallback}</>;\n\t}\n\n\treturn <>{children}</>;\n}\n","import React, { createContext, useContext, useCallback, type ReactNode } from \"react\";\nimport { useTranslationStore } from \"../store\";\n\nexport const LANGUAGE_DATA: Record<\n\tstring,\n\t{ name: string; nativeName: string; flag: string }\n> = {\n\ten: { name: \"English\", nativeName: \"English\", flag: \"🇺🇸\" },\n\tes: { name: \"Spanish\", nativeName: \"Español\", flag: \"🇪🇸\" },\n\tfr: { name: \"French\", nativeName: \"Français\", flag: \"🇫🇷\" },\n\tde: { name: \"German\", nativeName: \"Deutsch\", flag: \"🇩🇪\" },\n\tit: { name: \"Italian\", nativeName: \"Italiano\", flag: \"🇮🇹\" },\n\tpt: { name: \"Portuguese\", nativeName: \"Português\", flag: \"🇵🇹\" },\n\tja: { name: \"Japanese\", nativeName: \"日本語\", flag: \"🇯🇵\" },\n\tko: { name: \"Korean\", nativeName: \"한국어\", flag: \"🇰🇷\" },\n\tzh: { name: \"Chinese\", nativeName: \"中文\", flag: \"🇨🇳\" },\n\tar: { name: \"Arabic\", nativeName: \"العربية\", flag: \"🇸🇦\" },\n\tru: { name: \"Russian\", nativeName: \"Русский\", flag: \"🇷🇺\" },\n\tnl: { name: \"Dutch\", nativeName: \"Nederlands\", flag: \"🇳🇱\" },\n\tpl: { name: \"Polish\", nativeName: \"Polski\", flag: \"🇵🇱\" },\n\tsv: { name: \"Swedish\", nativeName: \"Svenska\", flag: \"🇸🇪\" },\n\tda: { name: \"Danish\", nativeName: \"Dansk\", flag: \"🇩🇰\" },\n\tfi: { name: \"Finnish\", nativeName: \"Suomi\", flag: \"🇫🇮\" },\n\tno: { name: \"Norwegian\", nativeName: \"Norsk\", flag: \"🇳🇴\" },\n\ttr: { name: \"Turkish\", nativeName: \"Türkçe\", flag: \"🇹🇷\" },\n\tcs: { name: \"Czech\", nativeName: \"Čeština\", flag: \"🇨🇿\" },\n\tel: { name: \"Greek\", nativeName: \"Ελληνικά\", flag: \"🇬🇷\" },\n\the: { name: \"Hebrew\", nativeName: \"עברית\", flag: \"🇮🇱\" },\n\thu: { name: \"Hungarian\", nativeName: \"Magyar\", flag: \"🇭🇺\" },\n\tid: { name: \"Indonesian\", nativeName: \"Bahasa Indonesia\", flag: \"🇮🇩\" },\n\tth: { name: \"Thai\", nativeName: \"ไทย\", flag: \"🇹🇭\" },\n\tvi: { name: \"Vietnamese\", nativeName: \"Tiếng Việt\", flag: \"🇻🇳\" },\n\tuk: { name: \"Ukrainian\", nativeName: \"Українська\", flag: \"🇺🇦\" },\n\tro: { name: \"Romanian\", nativeName: \"Română\", flag: \"🇷🇴\" },\n\tbg: { name: \"Bulgarian\", nativeName: \"Български\", flag: \"🇧🇬\" },\n\tsk: { name: \"Slovak\", nativeName: \"Slovenčina\", flag: \"🇸🇰\" },\n\tlt: { name: \"Lithuanian\", nativeName: \"Lietuvių\", flag: \"🇱🇹\" },\n\tlv: { name: \"Latvian\", nativeName: \"Latviešu\", flag: \"🇱🇻\" },\n\tet: { name: \"Estonian\", nativeName: \"Eesti\", flag: \"🇪🇪\" },\n\tsl: { name: \"Slovenian\", nativeName: \"Slovenščina\", flag: \"🇸🇮\" },\n\tbs: { name: \"Bosnian\", nativeName: \"Bosanski\", flag: \"🇧🇦\" },\n\thr: { name: \"Croatian\", nativeName: \"Hrvatski\", flag: \"🇭🇷\" },\n\tsr: { name: \"Serbian\", nativeName: \"Српски\", flag: \"🇷🇸\" },\n\tkmr: { name: \"Kurdish\", nativeName: \"Kurdî\", flag: \"🇮🇶\" },\n\tfa: { name: \"Persian\", nativeName: \"فارسی\", flag: \"🇮🇷\" },\n\thi: { name: \"Hindi\", nativeName: \"हिन्दी\", flag: \"🇮🇳\" },\n\tbn: { name: \"Bengali\", nativeName: \"বাংলা\", flag: \"🇧🇩\" },\n\tms: { name: \"Malay\", nativeName: \"Bahasa Melayu\", flag: \"🇲🇾\" },\n};\n\nexport interface LanguageInfo {\n\tcode: string;\n\tname: string;\n\tnativeName: string;\n\tflag: string;\n}\n\nexport function getLanguageInfo(code: string): Omit<LanguageInfo, \"code\"> {\n\tconst normalized = code.toLowerCase();\n\treturn (\n\t\tLANGUAGE_DATA[normalized] ?? {\n\t\t\tname: code.toUpperCase(),\n\t\t\tnativeName: code.toUpperCase(),\n\t\t\tflag: \"🌐\",\n\t\t}\n\t);\n}\n\nexport function getFullLanguageInfo(code: string): LanguageInfo {\n\treturn {\n\t\tcode,\n\t\t...getLanguageInfo(code),\n\t};\n}\n\nexport type LanguageSwitcherDisplay =\n\t| \"flag\"\n\t| \"name\"\n\t| \"native\"\n\t| \"flag-name\"\n\t| \"flag-native\"\n\t| \"code\";\n\nexport function formatLanguageDisplay(\n\tcode: string,\n\tdisplay: LanguageSwitcherDisplay = \"flag-native\",\n): string {\n\tconst info = getLanguageInfo(code);\n\tswitch (display) {\n\t\tcase \"flag\":\n\t\t\treturn info.flag;\n\t\tcase \"name\":\n\t\t\treturn info.name;\n\t\tcase \"native\":\n\t\t\treturn info.nativeName;\n\t\tcase \"flag-name\":\n\t\t\treturn `${info.flag} ${info.name}`;\n\t\tcase \"flag-native\":\n\t\t\treturn `${info.flag} ${info.nativeName}`;\n\t\tcase \"code\":\n\t\t\treturn code.toUpperCase();\n\t\tdefault:\n\t\t\treturn `${info.flag} ${info.nativeName}`;\n\t}\n}\n\n// Simple default LanguageSwitcher (backward compatible)\nexport type LanguageSwitcherVariant = \"dropdown\" | \"buttons\" | \"minimal\";\n\nexport interface LanguageSwitcherProps {\n\tclassName?: string;\n\tvariant?: LanguageSwitcherVariant;\n\tdisplay?: LanguageSwitcherDisplay;\n\tonChange?: (language: string) => void;\n}\n\nexport default function LanguageSwitcher({\n\tclassName,\n\tvariant = \"dropdown\",\n\tdisplay = \"flag-native\",\n\tonChange,\n}: LanguageSwitcherProps) {\n\tconst { currentLanguage, availableLanguages, setLanguage } =\n\t\tuseTranslationStore();\n\n\tconst handleChange = (newLanguage: string) => {\n\t\tsetLanguage(newLanguage);\n\t\tonChange?.(newLanguage);\n\t};\n\n\tif (variant === \"buttons\") {\n\t\treturn (\n\t\t\t<div className={className} role=\"group\" aria-label=\"Language selection\">\n\t\t\t\t{availableLanguages.map((lang) => (\n\t\t\t\t\t<button\n\t\t\t\t\t\tkey={lang}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => handleChange(lang)}\n\t\t\t\t\t\taria-pressed={currentLanguage === lang}\n\t\t\t\t\t\tdata-active={currentLanguage === lang}\n\t\t\t\t\t>\n\t\t\t\t\t\t{formatLanguageDisplay(lang, display)}\n\t\t\t\t\t</button>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (variant === \"minimal\") {\n\t\treturn (\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName={className}\n\t\t\t\tonClick={() => {\n\t\t\t\t\tconst currentIndex = availableLanguages.indexOf(currentLanguage);\n\t\t\t\t\tconst nextIndex = (currentIndex + 1) % availableLanguages.length;\n\t\t\t\t\thandleChange(availableLanguages[nextIndex]);\n\t\t\t\t}}\n\t\t\t\taria-label={`Current language: ${getLanguageInfo(currentLanguage).name}. Click to change.`}\n\t\t\t>\n\t\t\t\t{formatLanguageDisplay(currentLanguage, display)}\n\t\t\t</button>\n\t\t);\n\t}\n\n\treturn (\n\t\t<select\n\t\t\tvalue={currentLanguage}\n\t\t\tonChange={(e) => handleChange(e.target.value)}\n\t\t\tclassName={className}\n\t\t\taria-label=\"Select language\"\n\t\t>\n\t\t\t{availableLanguages.map((lang) => (\n\t\t\t\t<option key={lang} value={lang}>\n\t\t\t\t\t{formatLanguageDisplay(lang, display)}\n\t\t\t\t</option>\n\t\t\t))}\n\t\t</select>\n\t);\n}\n","import { useCallback } from \"react\";\nimport { getTranslation, useTranslationStore } from \"../store\";\nimport type { CTFunction, InterpolationValues } from \"../types\";\n\nfunction isInterpolationValues(arg: unknown): arg is InterpolationValues {\n\treturn (\n\t\ttypeof arg === \"object\" &&\n\t\targ !== null &&\n\t\t!Array.isArray(arg) &&\n\t\t!(arg instanceof Date)\n\t);\n}\n\nexport function useCt(): CTFunction {\n\tconst { translations, currentLanguage } = useTranslationStore();\n\n\tconst ct = useCallback(\n\t\t(\n\t\t\ttext: string,\n\t\t\tcontextOrValues?: string | InterpolationValues,\n\t\t\tmaybeValues?: InterpolationValues,\n\t\t): string => {\n\t\t\tlet values: InterpolationValues | undefined;\n\n\t\t\tif (typeof contextOrValues === \"string\") {\n\t\t\t\tvalues = maybeValues;\n\t\t\t} else if (isInterpolationValues(contextOrValues)) {\n\t\t\t\tvalues = contextOrValues;\n\t\t\t}\n\n\t\t\treturn getTranslation(translations, currentLanguage, text, values);\n\t\t},\n\t\t[translations, currentLanguage],\n\t) as CTFunction;\n\n\treturn ct;\n}\n","import React, {\n\tChildren,\n\tcloneElement,\n\tisValidElement,\n\ttype ReactNode,\n\ttype ReactElement,\n} from \"react\";\nimport { useCt } from \"../hooks/useCt\";\nimport type { InterpolationValues } from \"../types\";\n\nexport interface TransProps {\n\tchildren: ReactNode;\n\tcontext?: string;\n\tvalues?: InterpolationValues;\n}\n\ninterface ParsedChild {\n\ttype: \"text\" | \"element\";\n\tcontent: string;\n\telement?: ReactElement;\n\tindex?: number;\n}\n\nfunction parseChildren(children: ReactNode): {\n\ttemplate: string;\n\telements: ReactElement[];\n} {\n\tconst elements: ReactElement[] = [];\n\tlet template = \"\";\n\n\tconst processNode = (node: ReactNode): string => {\n\t\tif (node === null || node === undefined) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (typeof node === \"string\") {\n\t\t\treturn node;\n\t\t}\n\n\t\tif (typeof node === \"number\") {\n\t\t\treturn String(node);\n\t\t}\n\n\t\tif (isValidElement(node)) {\n\t\t\tconst index = elements.length;\n\t\t\telements.push(node);\n\t\t\tconst innerContent = processNode(node.props.children);\n\t\t\treturn `<${index}>${innerContent}</${index}>`;\n\t\t}\n\n\t\tif (Array.isArray(node)) {\n\t\t\treturn node.map(processNode).join(\"\");\n\t\t}\n\n\t\treturn \"\";\n\t};\n\n\ttemplate = processNode(children);\n\treturn { template, elements };\n}\n\nfunction reconstructChildren(\n\ttranslated: string,\n\telements: ReactElement[],\n): ReactNode {\n\tif (elements.length === 0) {\n\t\treturn translated;\n\t}\n\n\tconst result: ReactNode[] = [];\n\tlet remaining = translated;\n\tlet keyCounter = 0;\n\n\tconst tagRegex = /<(\\d+)>(.*?)<\\/\\1>/gs;\n\n\tlet lastIndex = 0;\n\tlet match: RegExpExecArray | null;\n\n\t// Reset regex state\n\ttagRegex.lastIndex = 0;\n\n\twhile ((match = tagRegex.exec(translated)) !== null) {\n\t\t// Add text before the match\n\t\tif (match.index > lastIndex) {\n\t\t\tconst textBefore = translated.slice(lastIndex, match.index);\n\t\t\tif (textBefore) {\n\t\t\t\tresult.push(textBefore);\n\t\t\t}\n\t\t}\n\n\t\tconst elementIndex = parseInt(match[1], 10);\n\t\tconst innerContent = match[2];\n\t\tconst originalElement = elements[elementIndex];\n\n\t\tif (originalElement) {\n\t\t\t// Recursively process inner content in case of nested tags\n\t\t\tconst processedInner = reconstructChildren(innerContent, elements);\n\t\t\tconst cloned = cloneElement(originalElement, {\n\t\t\t\tkey: `trans-${keyCounter++}`,\n\t\t\t\tchildren: processedInner,\n\t\t\t});\n\t\t\tresult.push(cloned);\n\t\t}\n\n\t\tlastIndex = match.index + match[0].length;\n\t}\n\n\t// Add remaining text after last match\n\tif (lastIndex < translated.length) {\n\t\tresult.push(translated.slice(lastIndex));\n\t}\n\n\t// If no matches found, return the original string\n\tif (result.length === 0) {\n\t\treturn translated;\n\t}\n\n\treturn result.length === 1 ? result[0] : result;\n}\n\nexport function Trans({ children, context, values }: TransProps) {\n\tconst ct = useCt();\n\n\t// Parse children to extract template and elements\n\tconst { template, elements } = parseChildren(children);\n\n\t// Translate the template\n\tlet translated: string;\n\tif (context && values) {\n\t\ttranslated = ct(template, context, values);\n\t} else if (context) {\n\t\ttranslated = ct(template, context);\n\t} else if (values) {\n\t\ttranslated = ct(template, values);\n\t} else {\n\t\ttranslated = ct(template);\n\t}\n\n\t// Reconstruct with original elements\n\treturn <>{reconstructChildren(translated, elements)}</>;\n}\n","import { useCallback } from \"react\";\nimport { useTranslationStore } from \"../store\";\nimport {\n\tgetLanguageInfo,\n\tgetFullLanguageInfo,\n\tLANGUAGE_DATA,\n\ttype LanguageInfo,\n} from \"../components/LanguageSwitcher\";\n\nexport function useCurrentLanguage(): string {\n\treturn useTranslationStore((state) => state.currentLanguage);\n}\n\nexport function useSetLanguage(): (language: string) => void {\n\treturn useTranslationStore((state) => state.setLanguage);\n}\n\nexport function useAvailableLanguages(): string[] {\n\treturn useTranslationStore((state) => state.availableLanguages);\n}\n\nexport function useIsLoading(): boolean {\n\treturn useTranslationStore((state) => state.isLoading);\n}\n\nexport function useIsReady(): boolean {\n\treturn useTranslationStore((state) => state.isReady);\n}\n\nexport function useLanguageInfo(code?: string): LanguageInfo {\n\tconst currentLanguage = useTranslationStore((state) => state.currentLanguage);\n\tconst targetCode = code ?? currentLanguage;\n\treturn getFullLanguageInfo(targetCode);\n}\n\nexport function useAvailableLanguagesInfo(): LanguageInfo[] {\n\tconst availableLanguages = useTranslationStore(\n\t\t(state) => state.availableLanguages,\n\t);\n\treturn availableLanguages.map(getFullLanguageInfo);\n}\n\nexport function useLanguage() {\n\tconst currentLanguage = useTranslationStore((state) => state.currentLanguage);\n\tconst availableLanguages = useTranslationStore(\n\t\t(state) => state.availableLanguages,\n\t);\n\tconst setLanguage = useTranslationStore((state) => state.setLanguage);\n\tconst isLoading = useTranslationStore((state) => state.isLoading);\n\tconst isReady = useTranslationStore((state) => state.isReady);\n\n\tconst currentLanguageInfo = getFullLanguageInfo(currentLanguage);\n\tconst availableLanguagesInfo = availableLanguages.map(getFullLanguageInfo);\n\n\tconst cycleLanguage = useCallback(() => {\n\t\tconst currentIndex = availableLanguages.indexOf(currentLanguage);\n\t\tconst nextIndex = (currentIndex + 1) % availableLanguages.length;\n\t\tsetLanguage(availableLanguages[nextIndex]);\n\t}, [availableLanguages, currentLanguage, setLanguage]);\n\n\treturn {\n\t\tcurrentLanguage,\n\t\tcurrentLanguageInfo,\n\t\tavailableLanguages,\n\t\tavailableLanguagesInfo,\n\t\tsetLanguage,\n\t\tcycleLanguage,\n\t\tisLoading,\n\t\tisReady,\n\t};\n}\n\nexport {\n\tgetLanguageInfo,\n\tgetFullLanguageInfo,\n\tLANGUAGE_DATA,\n\ttype LanguageInfo,\n};\n"],"mappings":"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"}
|