@i18n-micro/preact 1.0.0 → 1.1.1
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 +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -13
- package/dist/index.mjs +218 -244
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const A=require("@i18n-micro/core"),c=require("preact"),R=require("preact/hooks"),M=c.createContext(null),W=c.createContext(null),z=c.createContext(null),q=c.createContext(null),F=()=>{const a=R.useContext(M);if(!a)throw new Error("[i18n-micro] I18nContext not found. Make sure I18nProvider is used.");return a},V=()=>R.useContext(W),G=()=>R.useContext(z),H=()=>R.useContext(q);function it({i18n:a,locales:t,defaultLocale:n,routingStrategy:e,children:r}){return c.h(M.Provider,{value:a},t?c.h(W.Provider,{value:t},n?c.h(z.Provider,{value:n},e?c.h(q.Provider,{value:e},r):r):r):r)}const N=a=>{const t=F(),n=H(),e=V(),r=G(),[,w]=R.useState(0);R.useEffect(()=>t.subscribe(()=>{w(f=>f+1)}),[t]);const m=a?.locales||e||[],y=a?.defaultLocale||r||t.locale,d=(o,f)=>n?.resolvePath?n.resolvePath(o,f||t.locale):o,l=o=>{if(t.locale=o,n){const f=n.getCurrentPath(),p=d(f,o);n.push(typeof p=="string"?{path:p}:{path:p.path||"/"})}};return{t:t.t.bind(t),ts:t.ts.bind(t),tc:t.tc.bind(t),tn:t.tn.bind(t),td:t.td.bind(t),tdr:t.tdr.bind(t),has:t.has.bind(t),get locale(){return t.locale},get fallbackLocale(){return t.fallbackLocale},get currentRoute(){return t.currentRoute},setLocale:o=>{t.locale=o},setRoute:t.setRoute.bind(t),getRoute:t.getRoute.bind(t),getLocales:()=>m,defaultLocale:()=>y,getLocaleName:()=>m.find(f=>f.code===t.locale)?.displayName||null,switchLocale:l,localeRoute:d,localePath:(o,f)=>{const p=d(o,f);return typeof p=="string"?p:p.path||"/"},addTranslations:t.addTranslations.bind(t),addRouteTranslations:t.addRouteTranslations.bind(t),clearCache:t.clearCache.bind(t)}},ut=a=>{const{prefix:t,groupClass:n,children:e,...r}=a,{t:w,getRoute:m}=N(),y=(o,f)=>{const p=w(`${t}.${o}`,f,void 0,m());return typeof p=="string"?p:String(p)},d=["i18n-group",n].filter(Boolean).join(" "),l=typeof e=="function"?e({prefix:t,t:y}):e;return c.h("div",{...r,className:d},l)},dt=a=>{const t=N(),n=H(),{to:e,activeStyle:r,localeRoute:w,children:m,...y}=a,d=w||t.localeRoute,l=()=>typeof e=="string"?/^(?:https?:\/\/|\/\/|[a-zA-Z0-9-]+\.[a-zA-Z]{2,})|tel:|mailto:/.test(e):!1,o=()=>{if(l()&&typeof e=="string")return/^https?:\/\//.test(e)?e:`https://${e}`},f=()=>{if(l())return typeof e=="string"?e:e?.path||"/";if(d){const g=d(e);return typeof g=="string"?g:g.path||"/"}if(!n?.resolvePath)return typeof e=="string"?e:e.path||"/";const i=n.resolvePath(e,t.locale);return typeof i=="string"?i:i.path||"/"},P=(()=>{if(l()||!n)return!1;const i=n.getCurrentPath(),g=f(),k=i.replace(/\/$/,""),u=g.replace(/\/$/,"");return!!(k===u||k.startsWith(`${u}/`))})()?r||{}:{},x=f(),_=i=>{a.onClick&&a.onClick(i),!i.defaultPrevented&&!i.button&&!i.metaKey&&!i.ctrlKey&&n&&!l()&&(i.preventDefault(),n.push({path:x}))};if(l())return c.h("a",{...y,href:o(),style:P,target:"_blank",rel:"noopener noreferrer"},m);if(n?.linkComponent){const i=n.linkComponent;if(typeof i=="string")return c.h(i,{...y,href:x,style:P},m);const g=i,k={...y,href:x,style:P};return c.h(g,k,m)}return c.h("a",{...y,href:x,style:P,onClick:_},m)},ft=a=>{const{locales:t,currentLocale:n,getLocaleName:e,switchLocale:r,localeRoute:w,customLabels:m={},customWrapperStyle:y,customButtonStyle:d,customDropdownStyle:l,customItemStyle:o,customLinkStyle:f,customActiveLinkStyle:p,customIconStyle:P,...x}=a,_=N(),i=F(),g=H(),k=V(),[u,I]=R.useState(!1),b=R.useRef(null),E=t||k||_.getLocales()||[],L=typeof n=="function"?n():typeof n=="string"?n:_.locale,h=e?e():_.getLocaleName(),v=s=>{s&&(s.stopPropagation(),s.preventDefault()),I(!u)},D=s=>m[s.code]||s.displayName||s.code,O=()=>{const s=E.find(C=>C.code===L);return s?D(s):h||L},B=s=>{if(I(!1),r){r(s);return}if(i.locale=s,!g)return;const C=g.getCurrentPath(),T=a.localeRoute?(()=>{const S=a.localeRoute(C,s);return typeof S=="string"?S:S.path||"/"})():g?.resolvePath?(()=>{const S=g.resolvePath(C,s);return typeof S=="string"?S:S.path||"/"})():C;g.push({path:T})},j={position:"relative",display:"inline-block",verticalAlign:"middle"},Z={padding:"4px 12px",fontSize:"16px",cursor:"pointer",backgroundColor:"#fff",border:"1px solid #333",transition:"background-color 0.3s ease",display:"flex",alignItems:"center",justifyContent:"space-between"},J={position:"absolute",top:"100%",left:"0",zIndex:1e3,backgroundColor:"#fff",border:"1px solid #333",listStyle:"none",padding:"0",margin:"4px 0 0 0",minWidth:"150px",boxShadow:"0 2px 8px rgba(0,0,0,0.15)"},Q={margin:"0",padding:"0"},X={display:"block",padding:"8px 12px",color:"#333",textDecoration:"none",transition:"background-color 0.3s ease",cursor:"pointer"},Y={fontWeight:"bold",color:"#007bff"},tt={marginLeft:"8px",display:"inline-block",transition:"transform 0.3s ease"},et={transform:"rotate(180deg)"};R.useEffect(()=>{if(!u)return;const s=C=>{if(!u)return;const T=C.target;if(!T||!b.current)return;const S=b.current.contains(T),lt=T.closest(".i18n-switcher-button")!==null;!S&&!lt&&I(!1)};return document.addEventListener("click",s),()=>{document.removeEventListener("click",s)}},[u]);const nt={...j,...y},rt={...Z,...d},ot={...J,...l},st={...Q,...o},at={...tt,...u?et:{},...P},ct=E.map(s=>{const C=s.code===L,T={...X,...C?Y:{},...f,...C?p:{},width:"100%",textAlign:"left",border:"none",background:"transparent"};return c.h("li",{key:s.code,style:st},c.h("button",{type:"button",className:`switcher-locale-${s.code}`,style:T,onClick:S=>{S.preventDefault(),S.stopPropagation(),B(s.code)}},D(s)))});return c.h("div",{ref:b,className:"i18n-switcher-wrapper",style:nt,...x},c.h("button",{type:"button",className:"i18n-switcher-button",style:rt,onClick:s=>{s.preventDefault(),s.stopPropagation(),v(s)},ariaHaspopup:"true",ariaExpanded:u},c.h("span",null,O()),c.h("span",{style:at},"▼")),u?c.h("ul",{className:"i18n-switcher-dropdown",style:ot},...ct):null)},pt=a=>{const{t,tc:n,tn:e,td:r,tdr:w,locale:m,getRoute:y}=N(),{keypath:d,params:l,tag:o="span",plural:f,defaultValue:p,html:P=!1,hideIfEmpty:x=!1,customPluralRule:_,number:i,date:g,relativeDate:k,...u}=a,I=y(),b=(L,h,v)=>c.h(L,h,v);if(i!==void 0){const L=Number(i),h=e(L),v=t(d,{number:h,...l||{}},void 0,I),D=typeof v=="string"?v:String(v);return P?b(o,{...u,dangerouslySetInnerHTML:{__html:D}},void 0):b(o,u,D)}if(g!==void 0){const L=r(g),h=t(d,{date:L,...l||{}},void 0,I),v=typeof h=="string"?h:String(h);return P?b(o,{...u,dangerouslySetInnerHTML:{__html:v}},void 0):b(o,u,v)}if(k!==void 0){const L=w(k),h=t(d,{relativeDate:L,...l||{}},void 0,I),v=typeof h=="string"?h:String(h);return P?b(o,{...u,dangerouslySetInnerHTML:{__html:v}},void 0):b(o,u,v)}if(f!==void 0){const L=Number.parseInt(f.toString(),10);let h;return _?h=_(d,L,l||{},m,(D,O,B)=>{const j=t(D,O,B,I);return typeof j=="string"?j:String(j)})||"":h=n(d,{count:L,...l||{}},p),P?b(o,{...u,dangerouslySetInnerHTML:{__html:h}},void 0):b(o,u,h)}const E=t(d,l,p,I),$=typeof E=="string"?E:String(E);return x&&!$.trim()?p?c.h(c.Fragment,null,p):null:P?b(o,{...u,dangerouslySetInnerHTML:{__html:$}},void 0):b(o,u,$)};class K extends A.BaseI18n{_locale;_fallbackLocale;_currentRoute="general";listeners=new Set;revision=0;storage;constructor(t){const n={translations:new Map};if(super({storage:n,plural:t.plural,missingWarn:t.missingWarn,missingHandler:t.missingHandler}),this.storage=n,this._locale=t.locale,this._fallbackLocale=t.fallbackLocale||t.locale,t.messages)for(const[e,r]of Object.entries(t.messages))this.helper.loadTranslations(e,r)}subscribe=t=>(this.listeners.add(t),()=>this.listeners.delete(t));getSnapshot=()=>`${this._locale}:${this._currentRoute}:${this.revision}`;notify(){this.revision++,this.listeners.forEach(t=>t())}get locale(){return this._locale}set locale(t){this._locale!==t&&(this._locale=t,this.notify())}get fallbackLocale(){return this._fallbackLocale}set fallbackLocale(t){this._fallbackLocale=t}get currentRoute(){return this._currentRoute}setRoute(t){this._currentRoute!==t&&(this._currentRoute=t,this.notify())}getLocale(){return this._locale}getFallbackLocale(){return this._fallbackLocale}getRoute(){return this._currentRoute}addTranslations(t,n,e=!0){super.loadTranslationsCore(t,n,e),this.notify()}addRouteTranslations(t,n,e,r=!0){super.loadRouteTranslationsCore(t,n,e,r),this.notify()}clearCache(){super.clearCache(),this.notify()}}function ht(a){return new K(a)}function U(a,t){const n=a.map(r=>r.code),e=(r,w)=>{const y=(typeof r=="string"?r:r.path||"/").split("/").filter(Boolean),d=y[0];d!==void 0&&n.includes(d)&&y.shift();const l=`/${y.join("/")}`;return w===t?l:`/${w}${l==="/"?"":l}`};return{linkComponent:void 0,getCurrentPath:()=>typeof window<"u"?window.location.pathname:"/",push:r=>{typeof window<"u"&&(window.history.pushState({},"",r.path),window.dispatchEvent(new Event("popstate")))},replace:r=>{typeof window<"u"&&(window.history.replaceState({},"",r.path),window.dispatchEvent(new Event("popstate")))},resolvePath:(r,w)=>e(r,w),getRoute:()=>typeof window<"u"?{fullPath:window.location.pathname+window.location.search,query:Object.fromEntries(new URLSearchParams(window.location.search))}:{fullPath:"/",query:{}}}}const gt=U;Object.defineProperty(exports,"FormatService",{enumerable:!0,get:()=>A.FormatService});Object.defineProperty(exports,"defaultPlural",{enumerable:!0,get:()=>A.defaultPlural});Object.defineProperty(exports,"interpolate",{enumerable:!0,get:()=>A.interpolate});exports.I18nContext=M;exports.I18nDefaultLocaleContext=z;exports.I18nGroup=ut;exports.I18nLink=dt;exports.I18nLocalesContext=W;exports.I18nProvider=it;exports.I18nRouterContext=q;exports.I18nSwitcher=ft;exports.I18nT=pt;exports.PreactI18n=K;exports.createBrowserHistoryAdapter=U;exports.createI18n=ht;exports.createPreactRouterAdapter=gt;exports.useI18n=N;exports.useI18nContext=F;exports.useI18nDefaultLocale=G;exports.useI18nLocales=V;exports.useI18nRouter=H;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/i18n.ts","../src/injection.ts","../src/context.tsx","../src/components/I18nT.tsx","../src/components/I18nLink.tsx","../src/components/I18nSwitcher.tsx","../src/components/I18nGroup.tsx","../src/router/adapter.tsx"],"sourcesContent":["import {\n BaseI18n,\n type TranslationCache,\n} from '@i18n-micro/core'\nimport type {\n Translations,\n PluralFunc,\n} from '@i18n-micro/types'\n\nexport interface PreactI18nOptions {\n locale: string\n fallbackLocale?: string\n messages?: Record<string, Translations>\n plural?: PluralFunc\n missingWarn?: boolean\n missingHandler?: (locale: string, key: string, routeName: string) => void\n}\n\n/**\n * Preact I18n Adapter\n *\n * Provides a Preact-compatible i18n instance that uses the shared core logic.\n * Implements Observer pattern for reactivity with useSyncExternalStore.\n * Works with Preact through preact/compat for React compatibility.\n */\nexport class PreactI18n extends BaseI18n {\n private _locale: string\n private _fallbackLocale: string\n private _currentRoute: string = 'general'\n private listeners = new Set<() => void>()\n private revision = 0\n\n // Cache для Core (plain objects, не реактивные)\n public readonly cache: TranslationCache\n\n constructor(options: PreactI18nOptions) {\n // Create cache first\n const cache: TranslationCache = {\n generalLocaleCache: {},\n routeLocaleCache: {},\n dynamicTranslationsCaches: [],\n serverTranslationCache: {},\n }\n\n // Call parent constructor with options\n super({\n cache,\n plural: options.plural,\n missingWarn: options.missingWarn,\n missingHandler: options.missingHandler,\n })\n\n // Assign cache to public readonly property\n this.cache = cache\n\n this._locale = options.locale\n this._fallbackLocale = options.fallbackLocale || options.locale\n\n // Загружаем начальные сообщения\n if (options.messages) {\n for (const [lang, msgs] of Object.entries(options.messages)) {\n this.helper.loadTranslations(lang, msgs)\n }\n }\n }\n\n // Для useSyncExternalStore\n subscribe = (listener: () => void) => {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n getSnapshot = () => {\n // Возвращаем комбинированную строку локали и ревизии кэша\n // Это заставит компонент перерендериться при изменении\n return `${this._locale}:${this._currentRoute}:${this.revision}`\n }\n\n private notify() {\n this.revision++\n this.listeners.forEach((listener) => {\n listener()\n })\n }\n\n // Геттер/Сеттер для локали\n get locale(): string {\n return this._locale\n }\n\n set locale(val: string) {\n if (this._locale !== val) {\n this._locale = val\n this.notify()\n }\n }\n\n // Геттер/Сеттер для fallback локали\n get fallbackLocale(): string {\n return this._fallbackLocale\n }\n\n set fallbackLocale(val: string) {\n this._fallbackLocale = val\n }\n\n // Геттер/Сеттер для текущего роута\n get currentRoute(): string {\n return this._currentRoute\n }\n\n setRoute(routeName: string): void {\n if (this._currentRoute !== routeName) {\n this._currentRoute = routeName\n this.notify()\n }\n }\n\n // --- Implementation of abstract methods ---\n\n public getLocale(): string {\n return this._locale\n }\n\n public getFallbackLocale(): string {\n return this._fallbackLocale\n }\n\n public getRoute(): string {\n return this._currentRoute\n }\n\n // Translation management (uses protected methods from base class)\n public addTranslations(locale: string, translations: Translations, merge: boolean = true): void {\n super.loadTranslationsCore(locale, translations, merge)\n this.notify()\n }\n\n public addRouteTranslations(\n locale: string,\n routeName: string,\n translations: Translations,\n merge: boolean = true,\n ): void {\n super.loadRouteTranslationsCore(locale, routeName, translations, merge)\n this.notify()\n }\n\n public override clearCache(): void {\n super.clearCache()\n this.notify()\n }\n}\n\n/**\n * Create a new PreactI18n instance\n */\nexport function createI18n(options: PreactI18nOptions): PreactI18n {\n return new PreactI18n(options)\n}\n","import { createContext } from 'preact'\nimport { useContext } from 'preact/hooks'\nimport type { PreactI18n } from './i18n'\nimport type { Locale } from '@i18n-micro/types'\nimport type { I18nRoutingStrategy } from './router/types'\n\n// Context keys (analogous to Vue's InjectionKey)\nexport const I18nContext = createContext<PreactI18n | null>(null)\nexport const I18nLocalesContext = createContext<Locale[] | null>(null)\nexport const I18nDefaultLocaleContext = createContext<string | null>(null)\nexport const I18nRouterContext = createContext<I18nRoutingStrategy | null>(null)\n\n// Helper hooks (analogous to Vue's inject)\nexport const useI18nContext = () => {\n const context = useContext(I18nContext)\n if (!context) {\n throw new Error('[i18n-micro] I18nContext not found. Make sure I18nProvider is used.')\n }\n return context\n}\n\nexport const useI18nLocales = () => {\n return useContext(I18nLocalesContext)\n}\n\nexport const useI18nDefaultLocale = () => {\n return useContext(I18nDefaultLocaleContext)\n}\n\nexport const useI18nRouter = () => {\n return useContext(I18nRouterContext)\n}\n","import { h } from 'preact'\nimport { useEffect, useState } from 'preact/hooks'\nimport type { ComponentChildren } from 'preact'\nimport type { PreactI18n } from './i18n'\nimport type {\n Translations,\n Params,\n TranslationKey,\n CleanTranslation,\n Locale,\n} from '@i18n-micro/types'\nimport {\n I18nContext,\n I18nLocalesContext,\n I18nDefaultLocaleContext,\n I18nRouterContext,\n useI18nContext,\n useI18nLocales,\n useI18nDefaultLocale,\n useI18nRouter,\n} from './injection'\nimport type { I18nRoutingStrategy } from './router/types'\n\nexport interface I18nProviderProps {\n i18n: PreactI18n\n locales?: Locale[]\n defaultLocale?: string\n routingStrategy?: I18nRoutingStrategy\n children?: ComponentChildren\n}\n\nexport function I18nProvider({ i18n, locales, defaultLocale, routingStrategy, children }: I18nProviderProps) {\n return h(\n I18nContext.Provider,\n { value: i18n },\n locales\n ? h(\n I18nLocalesContext.Provider,\n { value: locales },\n defaultLocale\n ? h(\n I18nDefaultLocaleContext.Provider,\n { value: defaultLocale },\n routingStrategy\n ? h(\n I18nRouterContext.Provider,\n { value: routingStrategy },\n children,\n )\n : children,\n )\n : children,\n )\n : children,\n )\n}\n\nexport interface UseI18nOptions {\n locales?: Locale[]\n defaultLocale?: string\n}\n\nexport interface UseI18nReturn {\n // Translation methods\n t: (key: TranslationKey, params?: Params, defaultValue?: string | null, routeName?: string) => CleanTranslation\n ts: (key: TranslationKey, params?: Params, defaultValue?: string, routeName?: string) => string\n tc: (key: TranslationKey, count: number | Params, defaultValue?: string) => string\n tn: (value: number, options?: Intl.NumberFormatOptions) => string\n td: (value: Date | number | string, options?: Intl.DateTimeFormatOptions) => string\n tdr: (value: Date | number | string, options?: Intl.RelativeTimeFormatOptions) => string\n has: (key: TranslationKey, routeName?: string) => boolean\n\n // Locale management\n locale: string\n fallbackLocale: string\n currentRoute: string\n setLocale: (locale: string) => void\n\n // Route management\n setRoute: (routeName: string) => void\n getRoute: () => string\n getLocales: () => Locale[]\n defaultLocale: () => string\n getLocaleName: () => string | null\n\n // Router methods (if router is available)\n switchLocale?: (locale: string) => void\n localeRoute?: (to: string | { path?: string }, locale?: string) => string | { path?: string }\n localePath?: (to: string | { path?: string }, locale?: string) => string\n\n // Translation management\n addTranslations: (locale: string, translations: Translations, merge?: boolean) => void\n addRouteTranslations: (locale: string, routeName: string, translations: Translations, merge?: boolean) => void\n clearCache: () => void\n}\n\nexport const useI18n = (options?: UseI18nOptions): UseI18nReturn => {\n const i18n = useI18nContext()\n const router = useI18nRouter()\n const injectedLocales = useI18nLocales()\n const injectedDefaultLocale = useI18nDefaultLocale()\n\n // --- Замена useSyncExternalStore для Pure Preact ---\n // Подписываемся на изменения в i18n и форсируем ре-рендер\n const [, forceUpdate] = useState(0)\n\n useEffect(() => {\n // subscribe возвращает функцию отписки\n const unsubscribe = i18n.subscribe(() => {\n forceUpdate(n => n + 1)\n })\n return unsubscribe\n }, [i18n])\n // ---------------------------------------------------\n\n const locales = options?.locales || injectedLocales || []\n const defaultLocale = options?.defaultLocale || injectedDefaultLocale || i18n.locale\n\n const resolveLocalePath = (to: string | { path?: string }, localeCode?: string): string | { path?: string } => {\n if (!router?.resolvePath) {\n return to\n }\n return router.resolvePath(to, localeCode || i18n.locale)\n }\n\n const switchLocaleHelper = (newLocale: string): void => {\n i18n.locale = newLocale\n if (router) {\n const currentPath = router.getCurrentPath()\n const newPath = resolveLocalePath(currentPath, newLocale)\n router.push(typeof newPath === 'string' ? { path: newPath } : { path: newPath.path || '/' })\n }\n }\n\n return {\n // Translation methods\n t: i18n.t.bind(i18n),\n ts: i18n.ts.bind(i18n),\n tc: i18n.tc.bind(i18n),\n tn: i18n.tn.bind(i18n),\n td: i18n.td.bind(i18n),\n tdr: i18n.tdr.bind(i18n),\n has: i18n.has.bind(i18n),\n\n // Locale management\n get locale() {\n return i18n.locale\n },\n get fallbackLocale() {\n return i18n.fallbackLocale\n },\n get currentRoute() {\n return i18n.currentRoute\n },\n setLocale: (locale: string) => {\n i18n.locale = locale\n },\n\n // Route management\n setRoute: i18n.setRoute.bind(i18n),\n getRoute: i18n.getRoute.bind(i18n),\n getLocales: () => locales,\n defaultLocale: () => defaultLocale,\n getLocaleName: () => {\n const current = locales.find(l => l.code === i18n.locale)\n return current?.displayName || null\n },\n\n // Router methods (always available, but navigation handled by components)\n switchLocale: switchLocaleHelper,\n localeRoute: resolveLocalePath,\n localePath: (to: string | { path?: string }, locale?: string) => {\n const res = resolveLocalePath(to, locale)\n return typeof res === 'string' ? res : (res.path || '/')\n },\n\n // Translation management\n addTranslations: i18n.addTranslations.bind(i18n),\n addRouteTranslations: i18n.addRouteTranslations.bind(i18n),\n clearCache: i18n.clearCache.bind(i18n),\n }\n}\n\n// Export context for advanced usage\nexport { I18nContext } from './injection'\n","import { h, Fragment } from 'preact'\nimport type { JSX } from 'preact'\nimport { useI18n } from '../context'\nimport type { TranslationKey, PluralFunc } from '@i18n-micro/types'\n\nexport interface I18nTProps extends Omit<JSX.HTMLAttributes<HTMLElement>, 'children'> {\n keypath: TranslationKey\n params?: Record<string, string | number | boolean>\n tag?: keyof JSX.IntrinsicElements\n plural?: number | string\n defaultValue?: string\n html?: boolean\n hideIfEmpty?: boolean\n customPluralRule?: PluralFunc\n number?: number | string\n date?: Date | string | number\n relativeDate?: Date | string | number\n children?: never // I18nT doesn't support children - translation is rendered as content\n}\n\nexport const I18nT = (props: I18nTProps): JSX.Element | null => {\n const { t, tc, tn, td, tdr, locale, getRoute } = useI18n()\n const {\n keypath,\n params,\n tag = 'span',\n plural,\n defaultValue,\n html = false,\n hideIfEmpty = false,\n customPluralRule,\n number,\n date,\n relativeDate,\n ...restProps\n } = props\n\n const route = getRoute()\n\n // Helper function to create element with proper typing\n const createElement = (\n elementTag: keyof JSX.IntrinsicElements,\n elementProps: JSX.HTMLAttributes<HTMLElement>,\n children?: string,\n ): JSX.Element => {\n return h(\n elementTag as unknown as keyof JSX.IntrinsicElements,\n elementProps as unknown as JSX.HTMLAttributes<HTMLElement>,\n children,\n ) as JSX.Element\n }\n\n // Handle number formatting\n if (number !== undefined) {\n const numberValue = Number(number)\n const formattedNumber = tn(numberValue)\n const translation = t(keypath, { number: formattedNumber, ...(params || {}) }, undefined, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n return createElement(tag, restProps, content)\n }\n\n // Handle date formatting\n if (date !== undefined) {\n const formattedDate = td(date)\n const translation = t(keypath, { date: formattedDate, ...(params || {}) }, undefined, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n return createElement(tag, restProps, content)\n }\n\n // Handle relative date formatting\n if (relativeDate !== undefined) {\n const formattedRelativeDate = tdr(relativeDate)\n const translation = t(keypath, { relativeDate: formattedRelativeDate, ...(params || {}) }, undefined, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n return createElement(tag, restProps, content)\n }\n\n // Handle pluralization\n if (plural !== undefined) {\n const count = Number.parseInt(plural.toString())\n let translation: string\n if (customPluralRule) {\n const result = customPluralRule(\n keypath,\n count,\n params || {},\n locale,\n (k: TranslationKey, p?: Record<string, string | number | boolean>, dv?: string) => {\n const tResult = t(k, p, dv, route)\n return typeof tResult === 'string' ? tResult : String(tResult)\n },\n )\n translation = result || ''\n }\n else {\n translation = tc(keypath, { count, ...(params || {}) }, defaultValue)\n }\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: translation } }, undefined)\n }\n return createElement(tag, restProps, translation)\n }\n\n // Regular translation\n const translation = t(keypath, params, defaultValue, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n\n if (hideIfEmpty && !content.trim()) {\n return defaultValue ? (h(Fragment, null, defaultValue) as JSX.Element) : null\n }\n\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n\n return createElement(tag, restProps, content)\n}\n","import { h } from 'preact'\nimport type { JSX } from 'preact'\nimport { useI18n } from '../context'\nimport { useI18nRouter } from '../injection'\n\nexport interface I18nLinkProps extends JSX.AnchorHTMLAttributes<HTMLAnchorElement> {\n to: string | { path?: string }\n activeStyle?: Record<string, string | number>\n localeRoute?: (to: string | { path?: string }, locale?: string) => string | { path?: string }\n}\n\nexport const I18nLink = (props: I18nLinkProps): JSX.Element => {\n const i18n = useI18n()\n const router = useI18nRouter()\n const { to, activeStyle, localeRoute: localeRouteProp, children, ...restProps } = props\n\n // Use prop if provided, otherwise fallback to useI18n\n const localeRoute = localeRouteProp || i18n.localeRoute\n\n const isExternalLink = (): boolean => {\n if (typeof to === 'string') {\n return /^(?:https?:\\/\\/|\\/\\/|[a-zA-Z0-9-]+\\.[a-zA-Z]{2,})|tel:|mailto:/.test(to)\n }\n return false\n }\n\n const externalHref = (): string | undefined => {\n if (isExternalLink() && typeof to === 'string') {\n if (!/^https?:\\/\\//.test(to)) {\n return `https://${to}`\n }\n return to\n }\n return undefined\n }\n\n const targetPath = (): string => {\n if (isExternalLink()) {\n if (typeof to === 'string') {\n return to\n }\n const toObj = to as { path?: string }\n return toObj?.path || '/'\n }\n\n if (localeRoute) {\n const res = localeRoute(to)\n return typeof res === 'string' ? res : (res.path || '/')\n }\n\n if (!router?.resolvePath) {\n return typeof to === 'string' ? to : (to.path || '/')\n }\n\n const res = router.resolvePath(to, i18n.locale)\n return typeof res === 'string' ? res : (res.path || '/')\n }\n\n const isActive = (): boolean => {\n if (isExternalLink() || !router) {\n return false\n }\n\n const currentPath = router.getCurrentPath()\n const linkPath = targetPath()\n\n // Normalize paths (remove trailing slashes)\n const normalizedCurrent = currentPath.replace(/\\/$/, '')\n const normalizedLink = linkPath.replace(/\\/$/, '')\n\n // Exact match (ignoring query params and hash)\n if (normalizedCurrent === normalizedLink) {\n return true\n }\n\n // Partial match: check if current path starts with link path\n // This allows parent routes to be marked as active\n if (normalizedCurrent.startsWith(normalizedLink + '/')) {\n return true\n }\n\n return false\n }\n\n const computedStyle: Record<string, string | number> = isActive() ? (activeStyle || {}) : {}\n const toValue = targetPath()\n\n const handleClick = (e: JSX.TargetedMouseEvent<HTMLAnchorElement>) => {\n if (props.onClick) {\n props.onClick(e)\n }\n\n // Если это не внешний линк и нет модификаторов (ctrl/meta)\n if (!e.defaultPrevented && !e.button && !e.metaKey && !e.ctrlKey && router && !isExternalLink()) {\n e.preventDefault()\n router.push({ path: toValue })\n }\n }\n\n if (isExternalLink()) {\n return h(\n 'a',\n {\n ...restProps,\n href: externalHref(),\n style: computedStyle,\n target: '_blank',\n rel: 'noopener noreferrer',\n },\n children,\n ) as JSX.Element\n }\n\n // Use router linkComponent if available\n if (router?.linkComponent) {\n const LinkComponent = router.linkComponent\n if (typeof LinkComponent === 'string') {\n return h(\n LinkComponent,\n {\n ...restProps,\n href: toValue,\n style: computedStyle,\n },\n children,\n ) as JSX.Element\n }\n // Type assertion needed because React.ComponentType from I18nRoutingStrategy\n // is compatible with Preact components at runtime\n const Component = LinkComponent as unknown as (props: {\n href: string\n children?: JSX.Element | JSX.Element[]\n style?: Record<string, string | number>\n className?: string\n [key: string]: unknown\n }) => JSX.Element\n // Extract only the props that are compatible with the component type\n const componentProps = {\n ...restProps,\n href: toValue,\n style: computedStyle,\n } as {\n href: string\n children?: JSX.Element | JSX.Element[]\n style?: Record<string, string | number>\n className?: string\n [key: string]: unknown\n }\n return h(\n Component,\n componentProps,\n children,\n ) as JSX.Element\n }\n\n // Fallback to anchor with onClick handler\n return h(\n 'a',\n {\n ...restProps,\n href: toValue,\n style: computedStyle,\n onClick: handleClick,\n },\n children,\n ) as JSX.Element\n}\n","import { h } from 'preact'\nimport { useState, useEffect, useRef } from 'preact/hooks'\nimport type { JSX } from 'preact'\nimport { useI18n } from '../context'\nimport { useI18nRouter, useI18nLocales, useI18nContext } from '../injection'\nimport type { Locale } from '@i18n-micro/types'\n\nexport interface I18nSwitcherProps extends JSX.HTMLAttributes<HTMLDivElement> {\n locales?: Locale[]\n currentLocale?: string | (() => string)\n getLocaleName?: () => string | null\n switchLocale?: (locale: string) => void\n localeRoute?: (to: string | { path?: string }, locale?: string) => string | { path?: string }\n customLabels?: Record<string, string>\n customWrapperStyle?: Record<string, string | number>\n customButtonStyle?: Record<string, string | number>\n customDropdownStyle?: Record<string, string | number>\n customItemStyle?: Record<string, string | number>\n customLinkStyle?: Record<string, string | number>\n customActiveLinkStyle?: Record<string, string | number>\n customIconStyle?: Record<string, string | number>\n}\n\nexport const I18nSwitcher = (props: I18nSwitcherProps): JSX.Element => {\n const {\n locales: localesProp,\n currentLocale: currentLocaleProp,\n getLocaleName: getLocaleNameProp,\n switchLocale: switchLocaleProp,\n localeRoute: _localeRouteProp,\n customLabels = {},\n customWrapperStyle,\n customButtonStyle,\n customDropdownStyle,\n customItemStyle,\n customLinkStyle,\n customActiveLinkStyle,\n customIconStyle,\n ...restProps\n } = props\n\n const i18n = useI18n()\n const i18nInstance = useI18nContext()\n const router = useI18nRouter()\n const injectedLocales = useI18nLocales()\n const [dropdownOpen, setDropdownOpen] = useState(false)\n const wrapperRef = useRef<HTMLDivElement>(null)\n\n // Use props if provided, otherwise fallback to injected or useI18n\n const locales = localesProp || injectedLocales || i18n.getLocales() || []\n\n // Get current locale value (handle both string and function)\n const getCurrentLocale = (): string => {\n if (typeof currentLocaleProp === 'function') {\n return currentLocaleProp()\n }\n if (typeof currentLocaleProp === 'string') {\n return currentLocaleProp\n }\n return i18n.locale\n }\n\n const currentLocale = getCurrentLocale()\n const currentLocaleName = getLocaleNameProp ? getLocaleNameProp() : i18n.getLocaleName()\n\n const toggleDropdown = (event?: Event) => {\n if (event) {\n event.stopPropagation()\n event.preventDefault()\n }\n setDropdownOpen(!dropdownOpen)\n }\n\n const localeLabel = (localeItem: Locale): string => {\n const current = customLabels[localeItem.code] || localeItem.displayName\n return current || localeItem.code\n }\n\n const currentLocaleLabel = (): string => {\n const current = locales.find(l => l.code === currentLocale)\n return current ? localeLabel(current) : (currentLocaleName || currentLocale)\n }\n\n const handleSwitchLocale = (code: string) => {\n setDropdownOpen(false)\n if (switchLocaleProp) {\n switchLocaleProp(code)\n return\n }\n\n i18nInstance.locale = code\n\n if (!router) {\n return\n }\n\n const currentPath = router.getCurrentPath()\n const newPath = props.localeRoute\n ? (() => {\n const res = props.localeRoute(currentPath, code)\n return typeof res === 'string' ? res : (res.path || '/')\n })()\n : (router?.resolvePath\n ? (() => {\n const res = router.resolvePath(currentPath, code)\n return typeof res === 'string' ? res : (res.path || '/')\n })()\n : currentPath)\n\n router.push({ path: newPath })\n }\n\n // Default Styles\n const wrapperStyle: Record<string, string | number> = {\n position: 'relative',\n display: 'inline-block',\n verticalAlign: 'middle',\n }\n\n const buttonStyle: Record<string, string | number> = {\n padding: '4px 12px',\n fontSize: '16px',\n cursor: 'pointer',\n backgroundColor: '#fff',\n border: '1px solid #333',\n transition: 'background-color 0.3s ease',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n }\n\n const dropdownStyle: Record<string, string | number> = {\n position: 'absolute',\n top: '100%',\n left: '0',\n zIndex: 1000,\n backgroundColor: '#fff',\n border: '1px solid #333',\n listStyle: 'none',\n padding: '0',\n margin: '4px 0 0 0',\n minWidth: '150px',\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n }\n\n const itemStyle: Record<string, string | number> = {\n margin: '0',\n padding: '0',\n }\n\n const linkStyle: Record<string, string | number> = {\n display: 'block',\n padding: '8px 12px',\n color: '#333',\n textDecoration: 'none',\n transition: 'background-color 0.3s ease',\n cursor: 'pointer',\n }\n\n const activeLinkStyle: Record<string, string | number> = {\n fontWeight: 'bold',\n color: '#007bff',\n }\n\n const iconStyle: Record<string, string | number> = {\n marginLeft: '8px',\n display: 'inline-block',\n transition: 'transform 0.3s ease',\n }\n\n const openIconStyle: Record<string, string | number> = {\n transform: 'rotate(180deg)',\n }\n\n useEffect(() => {\n if (!dropdownOpen) return\n const handler = (event: MouseEvent) => {\n if (!dropdownOpen) return\n\n const target = event.target as HTMLElement\n if (!target || !wrapperRef.current) return\n\n const isClickInside = wrapperRef.current.contains(target)\n const isButtonClick = target.closest('.i18n-switcher-button') !== null\n\n if (!isClickInside && !isButtonClick) {\n setDropdownOpen(false)\n }\n }\n document.addEventListener('click', handler)\n return () => {\n document.removeEventListener('click', handler)\n }\n }, [dropdownOpen])\n\n const mergedWrapperStyle = { ...wrapperStyle, ...customWrapperStyle }\n const mergedButtonStyle = { ...buttonStyle, ...customButtonStyle }\n const mergedDropdownStyle = { ...dropdownStyle, ...customDropdownStyle }\n const mergedItemStyle = { ...itemStyle, ...customItemStyle }\n const mergedIconStyle = {\n ...iconStyle,\n ...(dropdownOpen ? openIconStyle : {}),\n ...customIconStyle,\n }\n\n const dropdownItems = locales.map((localeItem) => {\n const isActive = localeItem.code === currentLocale\n const mergedLinkStyle = {\n ...linkStyle,\n ...(isActive ? activeLinkStyle : {}),\n ...customLinkStyle,\n ...(isActive ? customActiveLinkStyle : {}),\n width: '100%',\n textAlign: 'left',\n border: 'none',\n background: 'transparent',\n }\n\n return h(\n 'li',\n {\n key: localeItem.code,\n style: mergedItemStyle,\n },\n h(\n 'button',\n {\n type: 'button',\n className: `switcher-locale-${localeItem.code}`,\n style: mergedLinkStyle,\n onClick: (e: Event) => {\n e.preventDefault()\n e.stopPropagation()\n handleSwitchLocale(localeItem.code)\n },\n },\n localeLabel(localeItem),\n ),\n )\n })\n\n return h(\n 'div',\n {\n ref: wrapperRef,\n className: 'i18n-switcher-wrapper',\n style: mergedWrapperStyle,\n ...restProps,\n },\n h(\n 'button',\n {\n type: 'button',\n className: 'i18n-switcher-button',\n style: mergedButtonStyle,\n onClick: (e: Event) => {\n e.preventDefault()\n e.stopPropagation()\n toggleDropdown(e)\n },\n ariaHaspopup: 'true',\n ariaExpanded: dropdownOpen,\n },\n h('span', null, currentLocaleLabel()),\n h('span', { style: mergedIconStyle }, '▼'),\n ),\n dropdownOpen\n ? h(\n 'ul',\n {\n className: 'i18n-switcher-dropdown',\n style: mergedDropdownStyle,\n },\n ...dropdownItems,\n )\n : null,\n ) as JSX.Element\n}\n","import { h } from 'preact'\nimport type { JSX, ComponentChildren } from 'preact'\nimport { useI18n } from '../context'\nimport type { TranslationKey } from '@i18n-micro/types'\n\nexport interface I18nGroupProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, 'children'> {\n prefix: string\n groupClass?: string\n children?: (props: { prefix: string, t: (key: string, params?: Record<string, string | number | boolean>) => string }) => ComponentChildren\n}\n\nexport const I18nGroup = (props: I18nGroupProps): JSX.Element => {\n const { prefix, groupClass, children, ...restProps } = props\n const { t, getRoute } = useI18n()\n\n const translate = (key: string, params?: Record<string, string | number | boolean>): string => {\n const result = t(`${prefix}.${key}` as TranslationKey, params, undefined, getRoute())\n return typeof result === 'string' ? result : String(result)\n }\n\n const className = ['i18n-group', groupClass].filter(Boolean).join(' ')\n\n const childrenContent: ComponentChildren = typeof children === 'function'\n ? children({ prefix, t: translate })\n : children\n\n return h(\n 'div',\n { ...restProps, className },\n childrenContent,\n ) as JSX.Element\n}\n","import type { I18nRoutingStrategy } from './types'\nimport type { Locale } from '@i18n-micro/types'\n\n/**\n * Создает адаптер для работы с History API (универсальный для Pure Preact)\n * Работает с любым роутером, который использует History API (wouter, preact-router, и т.д.)\n */\nexport function createBrowserHistoryAdapter(\n locales: Locale[],\n defaultLocale: string,\n): I18nRoutingStrategy {\n const localeCodes = locales.map(loc => loc.code)\n\n /**\n * Path resolution logic (add prefix or not)\n */\n const resolvePath = (to: string | { path?: string }, locale: string): string | { path?: string } => {\n const path = typeof to === 'string' ? to : (to.path || '/')\n const pathSegments = path.split('/').filter(Boolean)\n\n // If path already starts with a locale, remove it\n if (pathSegments.length > 0 && localeCodes.includes(pathSegments[0])) {\n pathSegments.shift()\n }\n\n const cleanPath = '/' + pathSegments.join('/')\n\n // If default locale - return clean path\n if (locale === defaultLocale) {\n return cleanPath\n }\n\n // Otherwise add prefix\n return `/${locale}${cleanPath === '/' ? '' : cleanPath}`\n }\n\n return {\n // Просто рендерим <a>, навигацию перехватит onClick в I18nLink\n linkComponent: undefined,\n\n getCurrentPath: () => {\n if (typeof window !== 'undefined') {\n return window.location.pathname\n }\n return '/'\n },\n\n push: (target) => {\n if (typeof window !== 'undefined') {\n window.history.pushState({}, '', target.path)\n // Вызываем событие, чтобы роутеры (wouter/preact-router) узнали об изменении\n window.dispatchEvent(new Event('popstate'))\n }\n },\n\n replace: (target) => {\n if (typeof window !== 'undefined') {\n window.history.replaceState({}, '', target.path)\n window.dispatchEvent(new Event('popstate'))\n }\n },\n\n resolvePath: (to, locale) => resolvePath(to, locale),\n\n getRoute: () => {\n if (typeof window !== 'undefined') {\n return {\n fullPath: window.location.pathname + window.location.search,\n query: Object.fromEntries(new URLSearchParams(window.location.search)),\n }\n }\n return {\n fullPath: '/',\n query: {},\n }\n },\n }\n}\n\n// Export for backward compatibility (old name)\nexport const createPreactRouterAdapter = createBrowserHistoryAdapter\n"],"names":["PreactI18n","BaseI18n","options","cache","lang","msgs","listener","val","routeName","locale","translations","merge","createI18n","I18nContext","createContext","I18nLocalesContext","I18nDefaultLocaleContext","I18nRouterContext","useI18nContext","context","useContext","useI18nLocales","useI18nDefaultLocale","useI18nRouter","I18nProvider","i18n","locales","defaultLocale","routingStrategy","children","h","useI18n","router","injectedLocales","injectedDefaultLocale","forceUpdate","useState","useEffect","n","resolveLocalePath","to","localeCode","switchLocaleHelper","newLocale","currentPath","newPath","l","res","I18nT","props","tc","tn","td","tdr","getRoute","keypath","params","tag","plural","defaultValue","html","hideIfEmpty","customPluralRule","number","date","relativeDate","restProps","route","createElement","elementTag","elementProps","numberValue","formattedNumber","translation","content","formattedDate","formattedRelativeDate","count","k","p","dv","tResult","Fragment","I18nLink","activeStyle","localeRouteProp","localeRoute","isExternalLink","externalHref","targetPath","computedStyle","linkPath","normalizedCurrent","normalizedLink","toValue","handleClick","e","LinkComponent","Component","componentProps","I18nSwitcher","localesProp","currentLocaleProp","getLocaleNameProp","switchLocaleProp","_localeRouteProp","customLabels","customWrapperStyle","customButtonStyle","customDropdownStyle","customItemStyle","customLinkStyle","customActiveLinkStyle","customIconStyle","i18nInstance","dropdownOpen","setDropdownOpen","wrapperRef","useRef","currentLocale","currentLocaleName","toggleDropdown","event","localeLabel","localeItem","currentLocaleLabel","current","handleSwitchLocale","code","wrapperStyle","buttonStyle","dropdownStyle","itemStyle","linkStyle","activeLinkStyle","iconStyle","openIconStyle","handler","target","isClickInside","isButtonClick","mergedWrapperStyle","mergedButtonStyle","mergedDropdownStyle","mergedItemStyle","mergedIconStyle","dropdownItems","isActive","mergedLinkStyle","I18nGroup","prefix","groupClass","t","translate","key","result","className","childrenContent","createBrowserHistoryAdapter","localeCodes","loc","resolvePath","pathSegments","cleanPath","createPreactRouterAdapter"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/injection.ts","../src/context.tsx","../src/components/I18nGroup.tsx","../src/components/I18nLink.tsx","../src/components/I18nSwitcher.tsx","../src/components/I18nT.tsx","../src/i18n.ts","../src/router/adapter.tsx"],"sourcesContent":["import type { Locale } from '@i18n-micro/types'\nimport { createContext } from 'preact'\nimport { useContext } from 'preact/hooks'\nimport type { PreactI18n } from './i18n'\nimport type { I18nRoutingStrategy } from './router/types'\n\n// Context keys (analogous to Vue's InjectionKey)\nexport const I18nContext = createContext<PreactI18n | null>(null)\nexport const I18nLocalesContext = createContext<Locale[] | null>(null)\nexport const I18nDefaultLocaleContext = createContext<string | null>(null)\nexport const I18nRouterContext = createContext<I18nRoutingStrategy | null>(null)\n\n// Helper hooks (analogous to Vue's inject)\nexport const useI18nContext = () => {\n const context = useContext(I18nContext)\n if (!context) {\n throw new Error('[i18n-micro] I18nContext not found. Make sure I18nProvider is used.')\n }\n return context\n}\n\nexport const useI18nLocales = () => {\n return useContext(I18nLocalesContext)\n}\n\nexport const useI18nDefaultLocale = () => {\n return useContext(I18nDefaultLocaleContext)\n}\n\nexport const useI18nRouter = () => {\n return useContext(I18nRouterContext)\n}\n","import type { CleanTranslation, Locale, Params, TranslationKey, Translations } from '@i18n-micro/types'\nimport type { ComponentChildren } from 'preact'\nimport { h } from 'preact'\nimport { useEffect, useState } from 'preact/hooks'\nimport type { PreactI18n } from './i18n'\nimport {\n I18nContext,\n I18nDefaultLocaleContext,\n I18nLocalesContext,\n I18nRouterContext,\n useI18nContext,\n useI18nDefaultLocale,\n useI18nLocales,\n useI18nRouter,\n} from './injection'\nimport type { I18nRoutingStrategy } from './router/types'\n\nexport interface I18nProviderProps {\n i18n: PreactI18n\n locales?: Locale[]\n defaultLocale?: string\n routingStrategy?: I18nRoutingStrategy\n children?: ComponentChildren\n}\n\nexport function I18nProvider({ i18n, locales, defaultLocale, routingStrategy, children }: I18nProviderProps) {\n return h(\n I18nContext.Provider,\n { value: i18n },\n locales\n ? h(\n I18nLocalesContext.Provider,\n { value: locales },\n defaultLocale\n ? h(\n I18nDefaultLocaleContext.Provider,\n { value: defaultLocale },\n routingStrategy ? h(I18nRouterContext.Provider, { value: routingStrategy }, children) : children,\n )\n : children,\n )\n : children,\n )\n}\n\nexport interface UseI18nOptions {\n locales?: Locale[]\n defaultLocale?: string\n}\n\nexport interface UseI18nReturn {\n // Translation methods\n t: (key: TranslationKey, params?: Params, defaultValue?: string | null, routeName?: string) => CleanTranslation\n ts: (key: TranslationKey, params?: Params, defaultValue?: string, routeName?: string) => string\n tc: (key: TranslationKey, count: number | Params, defaultValue?: string) => string\n tn: (value: number, options?: Intl.NumberFormatOptions) => string\n td: (value: Date | number | string, options?: Intl.DateTimeFormatOptions) => string\n tdr: (value: Date | number | string, options?: Intl.RelativeTimeFormatOptions) => string\n has: (key: TranslationKey, routeName?: string) => boolean\n\n // Locale management\n locale: string\n fallbackLocale: string\n currentRoute: string\n setLocale: (locale: string) => void\n\n // Route management\n setRoute: (routeName: string) => void\n getRoute: () => string\n getLocales: () => Locale[]\n defaultLocale: () => string\n getLocaleName: () => string | null\n\n // Router methods (if router is available)\n switchLocale?: (locale: string) => void\n localeRoute?: (to: string | { path?: string }, locale?: string) => string | { path?: string }\n localePath?: (to: string | { path?: string }, locale?: string) => string\n\n // Translation management\n addTranslations: (locale: string, translations: Translations, merge?: boolean) => void\n addRouteTranslations: (locale: string, routeName: string, translations: Translations, merge?: boolean) => void\n clearCache: () => void\n}\n\nexport const useI18n = (options?: UseI18nOptions): UseI18nReturn => {\n const i18n = useI18nContext()\n const router = useI18nRouter()\n const injectedLocales = useI18nLocales()\n const injectedDefaultLocale = useI18nDefaultLocale()\n\n // --- Замена useSyncExternalStore для Pure Preact ---\n // Подписываемся на изменения в i18n и форсируем ре-рендер\n const [, forceUpdate] = useState(0)\n\n useEffect(() => {\n // subscribe возвращает функцию отписки\n const unsubscribe = i18n.subscribe(() => {\n forceUpdate((n) => n + 1)\n })\n return unsubscribe\n }, [i18n])\n // ---------------------------------------------------\n\n const locales = options?.locales || injectedLocales || []\n const defaultLocale = options?.defaultLocale || injectedDefaultLocale || i18n.locale\n\n const resolveLocalePath = (to: string | { path?: string }, localeCode?: string): string | { path?: string } => {\n if (!router?.resolvePath) {\n return to\n }\n return router.resolvePath(to, localeCode || i18n.locale)\n }\n\n const switchLocaleHelper = (newLocale: string): void => {\n i18n.locale = newLocale\n if (router) {\n const currentPath = router.getCurrentPath()\n const newPath = resolveLocalePath(currentPath, newLocale)\n router.push(typeof newPath === 'string' ? { path: newPath } : { path: newPath.path || '/' })\n }\n }\n\n return {\n // Translation methods\n t: i18n.t.bind(i18n),\n ts: i18n.ts.bind(i18n),\n tc: i18n.tc.bind(i18n),\n tn: i18n.tn.bind(i18n),\n td: i18n.td.bind(i18n),\n tdr: i18n.tdr.bind(i18n),\n has: i18n.has.bind(i18n),\n\n // Locale management\n get locale() {\n return i18n.locale\n },\n get fallbackLocale() {\n return i18n.fallbackLocale\n },\n get currentRoute() {\n return i18n.currentRoute\n },\n setLocale: (locale: string) => {\n i18n.locale = locale\n },\n\n // Route management\n setRoute: i18n.setRoute.bind(i18n),\n getRoute: i18n.getRoute.bind(i18n),\n getLocales: () => locales,\n defaultLocale: () => defaultLocale,\n getLocaleName: () => {\n const current = locales.find((l) => l.code === i18n.locale)\n return current?.displayName || null\n },\n\n // Router methods (always available, but navigation handled by components)\n switchLocale: switchLocaleHelper,\n localeRoute: resolveLocalePath,\n localePath: (to: string | { path?: string }, locale?: string) => {\n const res = resolveLocalePath(to, locale)\n return typeof res === 'string' ? res : res.path || '/'\n },\n\n // Translation management\n addTranslations: i18n.addTranslations.bind(i18n),\n addRouteTranslations: i18n.addRouteTranslations.bind(i18n),\n clearCache: i18n.clearCache.bind(i18n),\n }\n}\n\n// Export context for advanced usage\nexport { I18nContext } from './injection'\n","import type { TranslationKey } from '@i18n-micro/types'\nimport type { ComponentChildren, JSX } from 'preact'\nimport { h } from 'preact'\nimport { useI18n } from '../context'\n\nexport interface I18nGroupProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, 'children'> {\n prefix: string\n groupClass?: string\n children?: (props: { prefix: string; t: (key: string, params?: Record<string, string | number | boolean>) => string }) => ComponentChildren\n}\n\nexport const I18nGroup = (props: I18nGroupProps): JSX.Element => {\n const { prefix, groupClass, children, ...restProps } = props\n const { t, getRoute } = useI18n()\n\n const translate = (key: string, params?: Record<string, string | number | boolean>): string => {\n const result = t(`${prefix}.${key}` as TranslationKey, params, undefined, getRoute())\n return typeof result === 'string' ? result : String(result)\n }\n\n const className = ['i18n-group', groupClass].filter(Boolean).join(' ')\n\n const childrenContent: ComponentChildren = typeof children === 'function' ? children({ prefix, t: translate }) : children\n\n return h('div', { ...restProps, className }, childrenContent) as JSX.Element\n}\n","import type { JSX } from 'preact'\nimport { h } from 'preact'\nimport { useI18n } from '../context'\nimport { useI18nRouter } from '../injection'\n\nexport interface I18nLinkProps extends JSX.AnchorHTMLAttributes<HTMLAnchorElement> {\n to: string | { path?: string }\n activeStyle?: Record<string, string | number>\n localeRoute?: (to: string | { path?: string }, locale?: string) => string | { path?: string }\n}\n\nexport const I18nLink = (props: I18nLinkProps): JSX.Element => {\n const i18n = useI18n()\n const router = useI18nRouter()\n const { to, activeStyle, localeRoute: localeRouteProp, children, ...restProps } = props\n\n // Use prop if provided, otherwise fallback to useI18n\n const localeRoute = localeRouteProp || i18n.localeRoute\n\n const isExternalLink = (): boolean => {\n if (typeof to === 'string') {\n return /^(?:https?:\\/\\/|\\/\\/|[a-zA-Z0-9-]+\\.[a-zA-Z]{2,})|tel:|mailto:/.test(to)\n }\n return false\n }\n\n const externalHref = (): string | undefined => {\n if (isExternalLink() && typeof to === 'string') {\n if (!/^https?:\\/\\//.test(to)) {\n return `https://${to}`\n }\n return to\n }\n return undefined\n }\n\n const targetPath = (): string => {\n if (isExternalLink()) {\n if (typeof to === 'string') {\n return to\n }\n const toObj = to as { path?: string }\n return toObj?.path || '/'\n }\n\n if (localeRoute) {\n const res = localeRoute(to)\n return typeof res === 'string' ? res : res.path || '/'\n }\n\n if (!router?.resolvePath) {\n return typeof to === 'string' ? to : to.path || '/'\n }\n\n const res = router.resolvePath(to, i18n.locale)\n return typeof res === 'string' ? res : res.path || '/'\n }\n\n const isActive = (): boolean => {\n if (isExternalLink() || !router) {\n return false\n }\n\n const currentPath = router.getCurrentPath()\n const linkPath = targetPath()\n\n // Normalize paths (remove trailing slashes)\n const normalizedCurrent = currentPath.replace(/\\/$/, '')\n const normalizedLink = linkPath.replace(/\\/$/, '')\n\n // Exact match (ignoring query params and hash)\n if (normalizedCurrent === normalizedLink) {\n return true\n }\n\n // Partial match: check if current path starts with link path\n // This allows parent routes to be marked as active\n if (normalizedCurrent.startsWith(`${normalizedLink}/`)) {\n return true\n }\n\n return false\n }\n\n const computedStyle: Record<string, string | number> = isActive() ? activeStyle || {} : {}\n const toValue = targetPath()\n\n const handleClick = (e: JSX.TargetedMouseEvent<HTMLAnchorElement>) => {\n if (props.onClick) {\n props.onClick(e)\n }\n\n // Если это не внешний линк и нет модификаторов (ctrl/meta)\n if (!e.defaultPrevented && !e.button && !e.metaKey && !e.ctrlKey && router && !isExternalLink()) {\n e.preventDefault()\n router.push({ path: toValue })\n }\n }\n\n if (isExternalLink()) {\n return h(\n 'a',\n {\n ...restProps,\n href: externalHref(),\n style: computedStyle,\n target: '_blank',\n rel: 'noopener noreferrer',\n },\n children,\n ) as JSX.Element\n }\n\n // Use router linkComponent if available\n if (router?.linkComponent) {\n const LinkComponent = router.linkComponent\n if (typeof LinkComponent === 'string') {\n return h(\n LinkComponent,\n {\n ...restProps,\n href: toValue,\n style: computedStyle,\n },\n children,\n ) as JSX.Element\n }\n // Type assertion needed because React.ComponentType from I18nRoutingStrategy\n // is compatible with Preact components at runtime\n const Component = LinkComponent as unknown as (props: {\n href: string\n children?: JSX.Element | JSX.Element[]\n style?: Record<string, string | number>\n className?: string\n [key: string]: unknown\n }) => JSX.Element\n // Extract only the props that are compatible with the component type\n const componentProps = {\n ...restProps,\n href: toValue,\n style: computedStyle,\n } as {\n href: string\n children?: JSX.Element | JSX.Element[]\n style?: Record<string, string | number>\n className?: string\n [key: string]: unknown\n }\n return h(Component, componentProps, children) as JSX.Element\n }\n\n // Fallback to anchor with onClick handler\n return h(\n 'a',\n {\n ...restProps,\n href: toValue,\n style: computedStyle,\n onClick: handleClick,\n },\n children,\n ) as JSX.Element\n}\n","import type { Locale } from '@i18n-micro/types'\nimport type { JSX } from 'preact'\nimport { h } from 'preact'\nimport { useEffect, useRef, useState } from 'preact/hooks'\nimport { useI18n } from '../context'\nimport { useI18nContext, useI18nLocales, useI18nRouter } from '../injection'\n\nexport interface I18nSwitcherProps extends JSX.HTMLAttributes<HTMLDivElement> {\n locales?: Locale[]\n currentLocale?: string | (() => string)\n getLocaleName?: () => string | null\n switchLocale?: (locale: string) => void\n localeRoute?: (to: string | { path?: string }, locale?: string) => string | { path?: string }\n customLabels?: Record<string, string>\n customWrapperStyle?: Record<string, string | number>\n customButtonStyle?: Record<string, string | number>\n customDropdownStyle?: Record<string, string | number>\n customItemStyle?: Record<string, string | number>\n customLinkStyle?: Record<string, string | number>\n customActiveLinkStyle?: Record<string, string | number>\n customIconStyle?: Record<string, string | number>\n}\n\nexport const I18nSwitcher = (props: I18nSwitcherProps): JSX.Element => {\n const {\n locales: localesProp,\n currentLocale: currentLocaleProp,\n getLocaleName: getLocaleNameProp,\n switchLocale: switchLocaleProp,\n localeRoute: _localeRouteProp,\n customLabels = {},\n customWrapperStyle,\n customButtonStyle,\n customDropdownStyle,\n customItemStyle,\n customLinkStyle,\n customActiveLinkStyle,\n customIconStyle,\n ...restProps\n } = props\n\n const i18n = useI18n()\n const i18nInstance = useI18nContext()\n const router = useI18nRouter()\n const injectedLocales = useI18nLocales()\n const [dropdownOpen, setDropdownOpen] = useState(false)\n const wrapperRef = useRef<HTMLDivElement>(null)\n\n // Use props if provided, otherwise fallback to injected or useI18n\n const locales = localesProp || injectedLocales || i18n.getLocales() || []\n\n // Get current locale value (handle both string and function)\n const getCurrentLocale = (): string => {\n if (typeof currentLocaleProp === 'function') {\n return currentLocaleProp()\n }\n if (typeof currentLocaleProp === 'string') {\n return currentLocaleProp\n }\n return i18n.locale\n }\n\n const currentLocale = getCurrentLocale()\n const currentLocaleName = getLocaleNameProp ? getLocaleNameProp() : i18n.getLocaleName()\n\n const toggleDropdown = (event?: Event) => {\n if (event) {\n event.stopPropagation()\n event.preventDefault()\n }\n setDropdownOpen(!dropdownOpen)\n }\n\n const localeLabel = (localeItem: Locale): string => {\n const current = customLabels[localeItem.code] || localeItem.displayName\n return current || localeItem.code\n }\n\n const currentLocaleLabel = (): string => {\n const current = locales.find((l) => l.code === currentLocale)\n return current ? localeLabel(current) : currentLocaleName || currentLocale\n }\n\n const handleSwitchLocale = (code: string) => {\n setDropdownOpen(false)\n if (switchLocaleProp) {\n switchLocaleProp(code)\n return\n }\n\n i18nInstance.locale = code\n\n if (!router) {\n return\n }\n\n const currentPath = router.getCurrentPath()\n const newPath = props.localeRoute\n ? (() => {\n const res = props.localeRoute(currentPath, code)\n return typeof res === 'string' ? res : res.path || '/'\n })()\n : router?.resolvePath\n ? (() => {\n const res = router.resolvePath(currentPath, code)\n return typeof res === 'string' ? res : res.path || '/'\n })()\n : currentPath\n\n router.push({ path: newPath })\n }\n\n // Default Styles\n const wrapperStyle: Record<string, string | number> = {\n position: 'relative',\n display: 'inline-block',\n verticalAlign: 'middle',\n }\n\n const buttonStyle: Record<string, string | number> = {\n padding: '4px 12px',\n fontSize: '16px',\n cursor: 'pointer',\n backgroundColor: '#fff',\n border: '1px solid #333',\n transition: 'background-color 0.3s ease',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n }\n\n const dropdownStyle: Record<string, string | number> = {\n position: 'absolute',\n top: '100%',\n left: '0',\n zIndex: 1000,\n backgroundColor: '#fff',\n border: '1px solid #333',\n listStyle: 'none',\n padding: '0',\n margin: '4px 0 0 0',\n minWidth: '150px',\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n }\n\n const itemStyle: Record<string, string | number> = {\n margin: '0',\n padding: '0',\n }\n\n const linkStyle: Record<string, string | number> = {\n display: 'block',\n padding: '8px 12px',\n color: '#333',\n textDecoration: 'none',\n transition: 'background-color 0.3s ease',\n cursor: 'pointer',\n }\n\n const activeLinkStyle: Record<string, string | number> = {\n fontWeight: 'bold',\n color: '#007bff',\n }\n\n const iconStyle: Record<string, string | number> = {\n marginLeft: '8px',\n display: 'inline-block',\n transition: 'transform 0.3s ease',\n }\n\n const openIconStyle: Record<string, string | number> = {\n transform: 'rotate(180deg)',\n }\n\n useEffect(() => {\n if (!dropdownOpen) return\n const handler = (event: MouseEvent) => {\n if (!dropdownOpen) return\n\n const target = event.target as HTMLElement\n if (!target || !wrapperRef.current) return\n\n const isClickInside = wrapperRef.current.contains(target)\n const isButtonClick = target.closest('.i18n-switcher-button') !== null\n\n if (!isClickInside && !isButtonClick) {\n setDropdownOpen(false)\n }\n }\n document.addEventListener('click', handler)\n return () => {\n document.removeEventListener('click', handler)\n }\n }, [dropdownOpen])\n\n const mergedWrapperStyle = { ...wrapperStyle, ...customWrapperStyle }\n const mergedButtonStyle = { ...buttonStyle, ...customButtonStyle }\n const mergedDropdownStyle = { ...dropdownStyle, ...customDropdownStyle }\n const mergedItemStyle = { ...itemStyle, ...customItemStyle }\n const mergedIconStyle = {\n ...iconStyle,\n ...(dropdownOpen ? openIconStyle : {}),\n ...customIconStyle,\n }\n\n const dropdownItems = locales.map((localeItem) => {\n const isActive = localeItem.code === currentLocale\n const mergedLinkStyle = {\n ...linkStyle,\n ...(isActive ? activeLinkStyle : {}),\n ...customLinkStyle,\n ...(isActive ? customActiveLinkStyle : {}),\n width: '100%',\n textAlign: 'left',\n border: 'none',\n background: 'transparent',\n }\n\n return h(\n 'li',\n {\n key: localeItem.code,\n style: mergedItemStyle,\n },\n h(\n 'button',\n {\n type: 'button',\n className: `switcher-locale-${localeItem.code}`,\n style: mergedLinkStyle,\n onClick: (e: Event) => {\n e.preventDefault()\n e.stopPropagation()\n handleSwitchLocale(localeItem.code)\n },\n },\n localeLabel(localeItem),\n ),\n )\n })\n\n return h(\n 'div',\n {\n ref: wrapperRef,\n className: 'i18n-switcher-wrapper',\n style: mergedWrapperStyle,\n ...restProps,\n },\n h(\n 'button',\n {\n type: 'button',\n className: 'i18n-switcher-button',\n style: mergedButtonStyle,\n onClick: (e: Event) => {\n e.preventDefault()\n e.stopPropagation()\n toggleDropdown(e)\n },\n ariaHaspopup: 'true',\n ariaExpanded: dropdownOpen,\n },\n h('span', null, currentLocaleLabel()),\n h('span', { style: mergedIconStyle }, '▼'),\n ),\n dropdownOpen\n ? h(\n 'ul',\n {\n className: 'i18n-switcher-dropdown',\n style: mergedDropdownStyle,\n },\n ...dropdownItems,\n )\n : null,\n ) as JSX.Element\n}\n","import type { PluralFunc, TranslationKey } from '@i18n-micro/types'\nimport type { JSX } from 'preact'\nimport { Fragment, h } from 'preact'\nimport { useI18n } from '../context'\n\nexport interface I18nTProps extends Omit<JSX.HTMLAttributes<HTMLElement>, 'children'> {\n keypath: TranslationKey\n params?: Record<string, string | number | boolean>\n tag?: keyof JSX.IntrinsicElements\n plural?: number | string\n defaultValue?: string\n html?: boolean\n hideIfEmpty?: boolean\n customPluralRule?: PluralFunc\n number?: number | string\n date?: Date | string | number\n relativeDate?: Date | string | number\n children?: never // I18nT doesn't support children - translation is rendered as content\n}\n\nexport const I18nT = (props: I18nTProps): JSX.Element | null => {\n const { t, tc, tn, td, tdr, locale, getRoute } = useI18n()\n const {\n keypath,\n params,\n tag = 'span',\n plural,\n defaultValue,\n html = false,\n hideIfEmpty = false,\n customPluralRule,\n number,\n date,\n relativeDate,\n ...restProps\n } = props\n\n const route = getRoute()\n\n // Helper function to create element with proper typing\n const createElement = (elementTag: keyof JSX.IntrinsicElements, elementProps: JSX.HTMLAttributes<HTMLElement>, children?: string): JSX.Element => {\n return h(\n elementTag as unknown as keyof JSX.IntrinsicElements,\n elementProps as unknown as JSX.HTMLAttributes<HTMLElement>,\n children,\n ) as JSX.Element\n }\n\n // Handle number formatting\n if (number !== undefined) {\n const numberValue = Number(number)\n const formattedNumber = tn(numberValue)\n const translation = t(keypath, { number: formattedNumber, ...(params || {}) }, undefined, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n return createElement(tag, restProps, content)\n }\n\n // Handle date formatting\n if (date !== undefined) {\n const formattedDate = td(date)\n const translation = t(keypath, { date: formattedDate, ...(params || {}) }, undefined, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n return createElement(tag, restProps, content)\n }\n\n // Handle relative date formatting\n if (relativeDate !== undefined) {\n const formattedRelativeDate = tdr(relativeDate)\n const translation = t(keypath, { relativeDate: formattedRelativeDate, ...(params || {}) }, undefined, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n return createElement(tag, restProps, content)\n }\n\n // Handle pluralization\n if (plural !== undefined) {\n const count = Number.parseInt(plural.toString(), 10)\n let translation: string\n if (customPluralRule) {\n const result = customPluralRule(\n keypath,\n count,\n params || {},\n locale,\n (k: TranslationKey, p?: Record<string, string | number | boolean>, dv?: string) => {\n const tResult = t(k, p, dv, route)\n return typeof tResult === 'string' ? tResult : String(tResult)\n },\n )\n translation = result || ''\n } else {\n translation = tc(keypath, { count, ...(params || {}) }, defaultValue)\n }\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: translation } }, undefined)\n }\n return createElement(tag, restProps, translation)\n }\n\n // Regular translation\n const translation = t(keypath, params, defaultValue, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n\n if (hideIfEmpty && !content.trim()) {\n return defaultValue ? (h(Fragment, null, defaultValue) as JSX.Element) : null\n }\n\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n\n return createElement(tag, restProps, content)\n}\n","import { BaseI18n, type TranslationStorage } from '@i18n-micro/core'\nimport type { PluralFunc, Translations } from '@i18n-micro/types'\n\nexport interface PreactI18nOptions {\n locale: string\n fallbackLocale?: string\n messages?: Record<string, Translations>\n plural?: PluralFunc\n missingWarn?: boolean\n missingHandler?: (locale: string, key: string, routeName: string) => void\n}\n\nexport class PreactI18n extends BaseI18n {\n private _locale: string\n private _fallbackLocale: string\n private _currentRoute: string = 'general'\n private listeners = new Set<() => void>()\n private revision = 0\n\n public readonly storage: TranslationStorage\n\n constructor(options: PreactI18nOptions) {\n const storage: TranslationStorage = {\n translations: new Map<string, Translations>(),\n }\n\n super({\n storage,\n plural: options.plural,\n missingWarn: options.missingWarn,\n missingHandler: options.missingHandler,\n })\n\n this.storage = storage\n this._locale = options.locale\n this._fallbackLocale = options.fallbackLocale || options.locale\n\n if (options.messages) {\n for (const [lang, msgs] of Object.entries(options.messages)) {\n this.helper.loadTranslations(lang, msgs)\n }\n }\n }\n\n subscribe = (listener: () => void) => {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n getSnapshot = () => `${this._locale}:${this._currentRoute}:${this.revision}`\n\n private notify() {\n this.revision++\n this.listeners.forEach((listener) => listener())\n }\n\n get locale(): string {\n return this._locale\n }\n\n set locale(val: string) {\n if (this._locale !== val) {\n this._locale = val\n this.notify()\n }\n }\n\n get fallbackLocale(): string {\n return this._fallbackLocale\n }\n\n set fallbackLocale(val: string) {\n this._fallbackLocale = val\n }\n\n get currentRoute(): string {\n return this._currentRoute\n }\n\n setRoute(routeName: string): void {\n if (this._currentRoute !== routeName) {\n this._currentRoute = routeName\n this.notify()\n }\n }\n\n public getLocale(): string {\n return this._locale\n }\n\n public getFallbackLocale(): string {\n return this._fallbackLocale\n }\n\n public getRoute(): string {\n return this._currentRoute\n }\n\n public addTranslations(locale: string, translations: Translations, merge = true): void {\n super.loadTranslationsCore(locale, translations, merge)\n this.notify()\n }\n\n public addRouteTranslations(locale: string, routeName: string, translations: Translations, merge = true): void {\n super.loadRouteTranslationsCore(locale, routeName, translations, merge)\n this.notify()\n }\n\n public override clearCache(): void {\n super.clearCache()\n this.notify()\n }\n}\n\nexport function createI18n(options: PreactI18nOptions): PreactI18n {\n return new PreactI18n(options)\n}\n","import type { Locale } from '@i18n-micro/types'\nimport type { I18nRoutingStrategy } from './types'\n\n/**\n * Создает адаптер для работы с History API (универсальный для Pure Preact)\n * Работает с любым роутером, который использует History API (wouter, preact-router, и т.д.)\n */\nexport function createBrowserHistoryAdapter(locales: Locale[], defaultLocale: string): I18nRoutingStrategy {\n const localeCodes = locales.map((loc) => loc.code)\n\n /**\n * Path resolution logic (add prefix or not)\n */\n const resolvePath = (to: string | { path?: string }, locale: string): string | { path?: string } => {\n const path = typeof to === 'string' ? to : to.path || '/'\n const pathSegments = path.split('/').filter(Boolean)\n\n // If path already starts with a locale, remove it\n const first = pathSegments[0]\n if (first !== undefined && localeCodes.includes(first)) {\n pathSegments.shift()\n }\n\n const cleanPath = `/${pathSegments.join('/')}`\n\n // If default locale - return clean path\n if (locale === defaultLocale) {\n return cleanPath\n }\n\n // Otherwise add prefix\n return `/${locale}${cleanPath === '/' ? '' : cleanPath}`\n }\n\n return {\n // Просто рендерим <a>, навигацию перехватит onClick в I18nLink\n linkComponent: undefined,\n\n getCurrentPath: () => {\n if (typeof window !== 'undefined') {\n return window.location.pathname\n }\n return '/'\n },\n\n push: (target) => {\n if (typeof window !== 'undefined') {\n window.history.pushState({}, '', target.path)\n // Вызываем событие, чтобы роутеры (wouter/preact-router) узнали об изменении\n window.dispatchEvent(new Event('popstate'))\n }\n },\n\n replace: (target) => {\n if (typeof window !== 'undefined') {\n window.history.replaceState({}, '', target.path)\n window.dispatchEvent(new Event('popstate'))\n }\n },\n\n resolvePath: (to, locale) => resolvePath(to, locale),\n\n getRoute: () => {\n if (typeof window !== 'undefined') {\n return {\n fullPath: window.location.pathname + window.location.search,\n query: Object.fromEntries(new URLSearchParams(window.location.search)),\n }\n }\n return {\n fullPath: '/',\n query: {},\n }\n },\n }\n}\n\n// Export for backward compatibility (old name)\nexport const createPreactRouterAdapter = createBrowserHistoryAdapter\n"],"names":["I18nContext","createContext","I18nLocalesContext","I18nDefaultLocaleContext","I18nRouterContext","useI18nContext","context","useContext","useI18nLocales","useI18nDefaultLocale","useI18nRouter","I18nProvider","i18n","locales","defaultLocale","routingStrategy","children","h","useI18n","options","router","injectedLocales","injectedDefaultLocale","forceUpdate","useState","useEffect","n","resolveLocalePath","to","localeCode","switchLocaleHelper","newLocale","currentPath","newPath","locale","l","res","I18nGroup","props","prefix","groupClass","restProps","t","getRoute","translate","key","params","result","className","childrenContent","I18nLink","activeStyle","localeRouteProp","localeRoute","isExternalLink","externalHref","targetPath","computedStyle","linkPath","normalizedCurrent","normalizedLink","toValue","handleClick","e","LinkComponent","Component","componentProps","I18nSwitcher","localesProp","currentLocaleProp","getLocaleNameProp","switchLocaleProp","_localeRouteProp","customLabels","customWrapperStyle","customButtonStyle","customDropdownStyle","customItemStyle","customLinkStyle","customActiveLinkStyle","customIconStyle","i18nInstance","dropdownOpen","setDropdownOpen","wrapperRef","useRef","currentLocale","currentLocaleName","toggleDropdown","event","localeLabel","localeItem","currentLocaleLabel","current","handleSwitchLocale","code","wrapperStyle","buttonStyle","dropdownStyle","itemStyle","linkStyle","activeLinkStyle","iconStyle","openIconStyle","handler","target","isClickInside","isButtonClick","mergedWrapperStyle","mergedButtonStyle","mergedDropdownStyle","mergedItemStyle","mergedIconStyle","dropdownItems","isActive","mergedLinkStyle","I18nT","tc","tn","td","tdr","keypath","tag","plural","defaultValue","html","hideIfEmpty","customPluralRule","number","date","relativeDate","route","createElement","elementTag","elementProps","numberValue","formattedNumber","translation","content","formattedDate","formattedRelativeDate","count","k","p","dv","tResult","Fragment","PreactI18n","BaseI18n","storage","lang","msgs","listener","val","routeName","translations","merge","createI18n","createBrowserHistoryAdapter","localeCodes","loc","resolvePath","pathSegments","first","cleanPath","createPreactRouterAdapter"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -14,9 +14,9 @@ import { LocaleCode } from '@i18n-micro/types';
|
|
|
14
14
|
import { ModuleOptions } from '@i18n-micro/types';
|
|
15
15
|
import { Params } from '@i18n-micro/types';
|
|
16
16
|
import { PluralFunc } from '@i18n-micro/types';
|
|
17
|
-
import { TranslationCache } from '@i18n-micro/core';
|
|
18
17
|
import { TranslationKey } from '@i18n-micro/types';
|
|
19
18
|
import { Translations } from '@i18n-micro/types';
|
|
19
|
+
import { TranslationStorage } from '@i18n-micro/core';
|
|
20
20
|
import { VNode } from 'preact';
|
|
21
21
|
|
|
22
22
|
export { CleanTranslation }
|
|
@@ -27,9 +27,6 @@ export { CleanTranslation }
|
|
|
27
27
|
*/
|
|
28
28
|
export declare function createBrowserHistoryAdapter(locales: Locale[], defaultLocale: string): I18nRoutingStrategy;
|
|
29
29
|
|
|
30
|
-
/**
|
|
31
|
-
* Create a new PreactI18n instance
|
|
32
|
-
*/
|
|
33
30
|
export declare function createI18n(options: PreactI18nOptions): PreactI18n;
|
|
34
31
|
|
|
35
32
|
export declare const createPreactRouterAdapter: typeof createBrowserHistoryAdapter;
|
|
@@ -187,22 +184,15 @@ export { Params }
|
|
|
187
184
|
|
|
188
185
|
export { PluralFunc }
|
|
189
186
|
|
|
190
|
-
/**
|
|
191
|
-
* Preact I18n Adapter
|
|
192
|
-
*
|
|
193
|
-
* Provides a Preact-compatible i18n instance that uses the shared core logic.
|
|
194
|
-
* Implements Observer pattern for reactivity with useSyncExternalStore.
|
|
195
|
-
* Works with Preact through preact/compat for React compatibility.
|
|
196
|
-
*/
|
|
197
187
|
export declare class PreactI18n extends BaseI18n {
|
|
198
188
|
private _locale;
|
|
199
189
|
private _fallbackLocale;
|
|
200
190
|
private _currentRoute;
|
|
201
191
|
private listeners;
|
|
202
192
|
private revision;
|
|
203
|
-
readonly
|
|
193
|
+
readonly storage: TranslationStorage;
|
|
204
194
|
constructor(options: PreactI18nOptions);
|
|
205
|
-
subscribe: (listener: () => void) => () =>
|
|
195
|
+
subscribe: (listener: () => void) => () => boolean;
|
|
206
196
|
getSnapshot: () => string;
|
|
207
197
|
private notify;
|
|
208
198
|
get locale(): string;
|
package/dist/index.mjs
CHANGED
|
@@ -1,93 +1,14 @@
|
|
|
1
|
-
import { BaseI18n as
|
|
1
|
+
import { BaseI18n as ct } from "@i18n-micro/core";
|
|
2
2
|
import { FormatService as Rt, defaultPlural as xt, interpolate as It } from "@i18n-micro/core";
|
|
3
|
-
import { createContext as
|
|
4
|
-
import { useContext as
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
_fallbackLocale;
|
|
8
|
-
_currentRoute = "general";
|
|
9
|
-
listeners = /* @__PURE__ */ new Set();
|
|
10
|
-
revision = 0;
|
|
11
|
-
// Cache для Core (plain objects, не реактивные)
|
|
12
|
-
cache;
|
|
13
|
-
constructor(t) {
|
|
14
|
-
const n = {
|
|
15
|
-
generalLocaleCache: {},
|
|
16
|
-
routeLocaleCache: {},
|
|
17
|
-
dynamicTranslationsCaches: [],
|
|
18
|
-
serverTranslationCache: {}
|
|
19
|
-
};
|
|
20
|
-
if (super({
|
|
21
|
-
cache: n,
|
|
22
|
-
plural: t.plural,
|
|
23
|
-
missingWarn: t.missingWarn,
|
|
24
|
-
missingHandler: t.missingHandler
|
|
25
|
-
}), this.cache = n, this._locale = t.locale, this._fallbackLocale = t.fallbackLocale || t.locale, t.messages)
|
|
26
|
-
for (const [e, r] of Object.entries(t.messages))
|
|
27
|
-
this.helper.loadTranslations(e, r);
|
|
28
|
-
}
|
|
29
|
-
// Для useSyncExternalStore
|
|
30
|
-
subscribe = (t) => (this.listeners.add(t), () => {
|
|
31
|
-
this.listeners.delete(t);
|
|
32
|
-
});
|
|
33
|
-
getSnapshot = () => `${this._locale}:${this._currentRoute}:${this.revision}`;
|
|
34
|
-
notify() {
|
|
35
|
-
this.revision++, this.listeners.forEach((t) => {
|
|
36
|
-
t();
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
// Геттер/Сеттер для локали
|
|
40
|
-
get locale() {
|
|
41
|
-
return this._locale;
|
|
42
|
-
}
|
|
43
|
-
set locale(t) {
|
|
44
|
-
this._locale !== t && (this._locale = t, this.notify());
|
|
45
|
-
}
|
|
46
|
-
// Геттер/Сеттер для fallback локали
|
|
47
|
-
get fallbackLocale() {
|
|
48
|
-
return this._fallbackLocale;
|
|
49
|
-
}
|
|
50
|
-
set fallbackLocale(t) {
|
|
51
|
-
this._fallbackLocale = t;
|
|
52
|
-
}
|
|
53
|
-
// Геттер/Сеттер для текущего роута
|
|
54
|
-
get currentRoute() {
|
|
55
|
-
return this._currentRoute;
|
|
56
|
-
}
|
|
57
|
-
setRoute(t) {
|
|
58
|
-
this._currentRoute !== t && (this._currentRoute = t, this.notify());
|
|
59
|
-
}
|
|
60
|
-
// --- Implementation of abstract methods ---
|
|
61
|
-
getLocale() {
|
|
62
|
-
return this._locale;
|
|
63
|
-
}
|
|
64
|
-
getFallbackLocale() {
|
|
65
|
-
return this._fallbackLocale;
|
|
66
|
-
}
|
|
67
|
-
getRoute() {
|
|
68
|
-
return this._currentRoute;
|
|
69
|
-
}
|
|
70
|
-
// Translation management (uses protected methods from base class)
|
|
71
|
-
addTranslations(t, n, e = !0) {
|
|
72
|
-
super.loadTranslationsCore(t, n, e), this.notify();
|
|
73
|
-
}
|
|
74
|
-
addRouteTranslations(t, n, e, r = !0) {
|
|
75
|
-
super.loadRouteTranslationsCore(t, n, e, r), this.notify();
|
|
76
|
-
}
|
|
77
|
-
clearCache() {
|
|
78
|
-
super.clearCache(), this.notify();
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function yt(a) {
|
|
82
|
-
return new dt(a);
|
|
83
|
-
}
|
|
84
|
-
const O = H(null), F = H(null), V = H(null), q = H(null), K = () => {
|
|
85
|
-
const a = $(O);
|
|
3
|
+
import { createContext as $, h, Fragment as it } from "preact";
|
|
4
|
+
import { useContext as H, useState as W, useEffect as z, useRef as ut } from "preact/hooks";
|
|
5
|
+
const O = $(null), F = $(null), V = $(null), q = $(null), K = () => {
|
|
6
|
+
const a = H(O);
|
|
86
7
|
if (!a)
|
|
87
8
|
throw new Error("[i18n-micro] I18nContext not found. Make sure I18nProvider is used.");
|
|
88
9
|
return a;
|
|
89
|
-
}, U = () =>
|
|
90
|
-
function
|
|
10
|
+
}, U = () => H(F), dt = () => H(V), M = () => H(q);
|
|
11
|
+
function yt({ i18n: a, locales: t, defaultLocale: n, routingStrategy: e, children: o }) {
|
|
91
12
|
return h(
|
|
92
13
|
O.Provider,
|
|
93
14
|
{ value: a },
|
|
@@ -97,24 +18,20 @@ function bt({ i18n: a, locales: t, defaultLocale: n, routingStrategy: e, childre
|
|
|
97
18
|
n ? h(
|
|
98
19
|
V.Provider,
|
|
99
20
|
{ value: n },
|
|
100
|
-
e ? h(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
r
|
|
104
|
-
) : r
|
|
105
|
-
) : r
|
|
106
|
-
) : r
|
|
21
|
+
e ? h(q.Provider, { value: e }, o) : o
|
|
22
|
+
) : o
|
|
23
|
+
) : o
|
|
107
24
|
);
|
|
108
25
|
}
|
|
109
26
|
const j = (a) => {
|
|
110
|
-
const t = K(), n =
|
|
111
|
-
|
|
112
|
-
w((
|
|
27
|
+
const t = K(), n = M(), e = U(), o = dt(), [, w] = W(0);
|
|
28
|
+
z(() => t.subscribe(() => {
|
|
29
|
+
w((d) => d + 1);
|
|
113
30
|
}), [t]);
|
|
114
|
-
const y = a?.locales || e || [],
|
|
115
|
-
if (t.locale =
|
|
116
|
-
const
|
|
117
|
-
n.push(typeof
|
|
31
|
+
const y = a?.locales || e || [], m = a?.defaultLocale || o || t.locale, u = (r, d) => n?.resolvePath ? n.resolvePath(r, d || t.locale) : r, l = (r) => {
|
|
32
|
+
if (t.locale = r, n) {
|
|
33
|
+
const d = n.getCurrentPath(), f = u(d, r);
|
|
34
|
+
n.push(typeof f == "string" ? { path: f } : { path: f.path || "/" });
|
|
118
35
|
}
|
|
119
36
|
};
|
|
120
37
|
return {
|
|
@@ -136,103 +53,62 @@ const j = (a) => {
|
|
|
136
53
|
get currentRoute() {
|
|
137
54
|
return t.currentRoute;
|
|
138
55
|
},
|
|
139
|
-
setLocale: (
|
|
140
|
-
t.locale =
|
|
56
|
+
setLocale: (r) => {
|
|
57
|
+
t.locale = r;
|
|
141
58
|
},
|
|
142
59
|
// Route management
|
|
143
60
|
setRoute: t.setRoute.bind(t),
|
|
144
61
|
getRoute: t.getRoute.bind(t),
|
|
145
62
|
getLocales: () => y,
|
|
146
|
-
defaultLocale: () =>
|
|
147
|
-
getLocaleName: () => y.find((
|
|
63
|
+
defaultLocale: () => m,
|
|
64
|
+
getLocaleName: () => y.find((d) => d.code === t.locale)?.displayName || null,
|
|
148
65
|
// Router methods (always available, but navigation handled by components)
|
|
149
|
-
switchLocale:
|
|
150
|
-
localeRoute:
|
|
151
|
-
localePath: (
|
|
152
|
-
const
|
|
153
|
-
return typeof
|
|
66
|
+
switchLocale: l,
|
|
67
|
+
localeRoute: u,
|
|
68
|
+
localePath: (r, d) => {
|
|
69
|
+
const f = u(r, d);
|
|
70
|
+
return typeof f == "string" ? f : f.path || "/";
|
|
154
71
|
},
|
|
155
72
|
// Translation management
|
|
156
73
|
addTranslations: t.addTranslations.bind(t),
|
|
157
74
|
addRouteTranslations: t.addRouteTranslations.bind(t),
|
|
158
75
|
clearCache: t.clearCache.bind(t)
|
|
159
76
|
};
|
|
160
|
-
},
|
|
161
|
-
const { t,
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
defaultValue: d,
|
|
167
|
-
html: P = !1,
|
|
168
|
-
hideIfEmpty: x = !1,
|
|
169
|
-
customPluralRule: I,
|
|
170
|
-
number: l,
|
|
171
|
-
date: m,
|
|
172
|
-
relativeDate: C,
|
|
173
|
-
...i
|
|
174
|
-
} = a, R = g(), b = (L, p, v) => h(
|
|
175
|
-
L,
|
|
176
|
-
p,
|
|
177
|
-
v
|
|
178
|
-
);
|
|
179
|
-
if (l !== void 0) {
|
|
180
|
-
const L = Number(l), p = e(L), v = t(c, { number: p, ...f || {} }, void 0, R), _ = typeof v == "string" ? v : String(v);
|
|
181
|
-
return P ? b(o, { ...i, dangerouslySetInnerHTML: { __html: _ } }, void 0) : b(o, i, _);
|
|
182
|
-
}
|
|
183
|
-
if (m !== void 0) {
|
|
184
|
-
const L = r(m), p = t(c, { date: L, ...f || {} }, void 0, R), v = typeof p == "string" ? p : String(p);
|
|
185
|
-
return P ? b(o, { ...i, dangerouslySetInnerHTML: { __html: v } }, void 0) : b(o, i, v);
|
|
186
|
-
}
|
|
187
|
-
if (C !== void 0) {
|
|
188
|
-
const L = w(C), p = t(c, { relativeDate: L, ...f || {} }, void 0, R), v = typeof p == "string" ? p : String(p);
|
|
189
|
-
return P ? b(o, { ...i, dangerouslySetInnerHTML: { __html: v } }, void 0) : b(o, i, v);
|
|
190
|
-
}
|
|
191
|
-
if (u !== void 0) {
|
|
192
|
-
const L = Number.parseInt(u.toString());
|
|
193
|
-
let p;
|
|
194
|
-
return I ? p = I(
|
|
195
|
-
c,
|
|
196
|
-
L,
|
|
197
|
-
f || {},
|
|
198
|
-
y,
|
|
199
|
-
(_, A, B) => {
|
|
200
|
-
const E = t(_, A, B, R);
|
|
201
|
-
return typeof E == "string" ? E : String(E);
|
|
202
|
-
}
|
|
203
|
-
) || "" : p = n(c, { count: L, ...f || {} }, d), P ? b(o, { ...i, dangerouslySetInnerHTML: { __html: p } }, void 0) : b(o, i, p);
|
|
204
|
-
}
|
|
205
|
-
const D = t(c, f, d, R), N = typeof D == "string" ? D : String(D);
|
|
206
|
-
return x && !N.trim() ? d ? h(it, null, d) : null : P ? b(o, { ...i, dangerouslySetInnerHTML: { __html: N } }, void 0) : b(o, i, N);
|
|
77
|
+
}, bt = (a) => {
|
|
78
|
+
const { prefix: t, groupClass: n, children: e, ...o } = a, { t: w, getRoute: y } = j(), m = (r, d) => {
|
|
79
|
+
const f = w(`${t}.${r}`, d, void 0, y());
|
|
80
|
+
return typeof f == "string" ? f : String(f);
|
|
81
|
+
}, u = ["i18n-group", n].filter(Boolean).join(" "), l = typeof e == "function" ? e({ prefix: t, t: m }) : e;
|
|
82
|
+
return h("div", { ...o, className: u }, l);
|
|
207
83
|
}, vt = (a) => {
|
|
208
|
-
const t = j(), n =
|
|
209
|
-
if (
|
|
84
|
+
const t = j(), n = M(), { to: e, activeStyle: o, localeRoute: w, children: y, ...m } = a, u = w || t.localeRoute, l = () => typeof e == "string" ? /^(?:https?:\/\/|\/\/|[a-zA-Z0-9-]+\.[a-zA-Z]{2,})|tel:|mailto:/.test(e) : !1, r = () => {
|
|
85
|
+
if (l() && typeof e == "string")
|
|
210
86
|
return /^https?:\/\//.test(e) ? e : `https://${e}`;
|
|
211
|
-
},
|
|
212
|
-
if (
|
|
87
|
+
}, d = () => {
|
|
88
|
+
if (l())
|
|
213
89
|
return typeof e == "string" ? e : e?.path || "/";
|
|
214
|
-
if (
|
|
215
|
-
const
|
|
216
|
-
return typeof
|
|
90
|
+
if (u) {
|
|
91
|
+
const g = u(e);
|
|
92
|
+
return typeof g == "string" ? g : g.path || "/";
|
|
217
93
|
}
|
|
218
94
|
if (!n?.resolvePath)
|
|
219
95
|
return typeof e == "string" ? e : e.path || "/";
|
|
220
|
-
const
|
|
221
|
-
return typeof
|
|
96
|
+
const c = n.resolvePath(e, t.locale);
|
|
97
|
+
return typeof c == "string" ? c : c.path || "/";
|
|
222
98
|
}, P = (() => {
|
|
223
|
-
if (
|
|
99
|
+
if (l() || !n)
|
|
224
100
|
return !1;
|
|
225
|
-
const
|
|
226
|
-
return !!(C === i || C.startsWith(i
|
|
227
|
-
})() ?
|
|
228
|
-
a.onClick && a.onClick(
|
|
101
|
+
const c = n.getCurrentPath(), g = d(), C = c.replace(/\/$/, ""), i = g.replace(/\/$/, "");
|
|
102
|
+
return !!(C === i || C.startsWith(`${i}/`));
|
|
103
|
+
})() ? o || {} : {}, x = d(), I = (c) => {
|
|
104
|
+
a.onClick && a.onClick(c), !c.defaultPrevented && !c.button && !c.metaKey && !c.ctrlKey && n && !l() && (c.preventDefault(), n.push({ path: x }));
|
|
229
105
|
};
|
|
230
|
-
if (
|
|
106
|
+
if (l())
|
|
231
107
|
return h(
|
|
232
108
|
"a",
|
|
233
109
|
{
|
|
234
|
-
...
|
|
235
|
-
href:
|
|
110
|
+
...m,
|
|
111
|
+
href: r(),
|
|
236
112
|
style: P,
|
|
237
113
|
target: "_blank",
|
|
238
114
|
rel: "noopener noreferrer"
|
|
@@ -240,74 +116,70 @@ const j = (a) => {
|
|
|
240
116
|
y
|
|
241
117
|
);
|
|
242
118
|
if (n?.linkComponent) {
|
|
243
|
-
const
|
|
244
|
-
if (typeof
|
|
119
|
+
const c = n.linkComponent;
|
|
120
|
+
if (typeof c == "string")
|
|
245
121
|
return h(
|
|
246
|
-
|
|
122
|
+
c,
|
|
247
123
|
{
|
|
248
|
-
...
|
|
124
|
+
...m,
|
|
249
125
|
href: x,
|
|
250
126
|
style: P
|
|
251
127
|
},
|
|
252
128
|
y
|
|
253
129
|
);
|
|
254
|
-
const
|
|
255
|
-
...
|
|
130
|
+
const g = c, C = {
|
|
131
|
+
...m,
|
|
256
132
|
href: x,
|
|
257
133
|
style: P
|
|
258
134
|
};
|
|
259
|
-
return h(
|
|
260
|
-
m,
|
|
261
|
-
C,
|
|
262
|
-
y
|
|
263
|
-
);
|
|
135
|
+
return h(g, C, y);
|
|
264
136
|
}
|
|
265
137
|
return h(
|
|
266
138
|
"a",
|
|
267
139
|
{
|
|
268
|
-
...
|
|
140
|
+
...m,
|
|
269
141
|
href: x,
|
|
270
142
|
style: P,
|
|
271
143
|
onClick: I
|
|
272
144
|
},
|
|
273
145
|
y
|
|
274
146
|
);
|
|
275
|
-
},
|
|
147
|
+
}, Lt = (a) => {
|
|
276
148
|
const {
|
|
277
149
|
locales: t,
|
|
278
150
|
currentLocale: n,
|
|
279
151
|
getLocaleName: e,
|
|
280
|
-
switchLocale:
|
|
152
|
+
switchLocale: o,
|
|
281
153
|
localeRoute: w,
|
|
282
154
|
customLabels: y = {},
|
|
283
|
-
customWrapperStyle:
|
|
284
|
-
customButtonStyle:
|
|
285
|
-
customDropdownStyle:
|
|
286
|
-
customItemStyle:
|
|
287
|
-
customLinkStyle:
|
|
288
|
-
customActiveLinkStyle:
|
|
155
|
+
customWrapperStyle: m,
|
|
156
|
+
customButtonStyle: u,
|
|
157
|
+
customDropdownStyle: l,
|
|
158
|
+
customItemStyle: r,
|
|
159
|
+
customLinkStyle: d,
|
|
160
|
+
customActiveLinkStyle: f,
|
|
289
161
|
customIconStyle: P,
|
|
290
162
|
...x
|
|
291
|
-
} = a, I = j(),
|
|
163
|
+
} = a, I = j(), c = K(), g = M(), C = U(), [i, R] = W(!1), b = ut(null), T = t || C || I.getLocales() || [], v = typeof n == "function" ? n() : typeof n == "string" ? n : I.locale, p = e ? e() : I.getLocaleName(), L = (s) => {
|
|
292
164
|
s && (s.stopPropagation(), s.preventDefault()), R(!i);
|
|
293
165
|
}, _ = (s) => y[s.code] || s.displayName || s.code, A = () => {
|
|
294
|
-
const s =
|
|
295
|
-
return s ? _(s) : p ||
|
|
166
|
+
const s = T.find((k) => k.code === v);
|
|
167
|
+
return s ? _(s) : p || v;
|
|
296
168
|
}, B = (s) => {
|
|
297
|
-
if (R(!1),
|
|
298
|
-
|
|
169
|
+
if (R(!1), o) {
|
|
170
|
+
o(s);
|
|
299
171
|
return;
|
|
300
172
|
}
|
|
301
|
-
if (
|
|
173
|
+
if (c.locale = s, !g)
|
|
302
174
|
return;
|
|
303
|
-
const k =
|
|
175
|
+
const k = g.getCurrentPath(), D = a.localeRoute ? (() => {
|
|
304
176
|
const S = a.localeRoute(k, s);
|
|
305
177
|
return typeof S == "string" ? S : S.path || "/";
|
|
306
|
-
})() :
|
|
307
|
-
const S =
|
|
178
|
+
})() : g?.resolvePath ? (() => {
|
|
179
|
+
const S = g.resolvePath(k, s);
|
|
308
180
|
return typeof S == "string" ? S : S.path || "/";
|
|
309
181
|
})() : k;
|
|
310
|
-
|
|
182
|
+
g.push({ path: D });
|
|
311
183
|
}, E = {
|
|
312
184
|
position: "relative",
|
|
313
185
|
display: "inline-block",
|
|
@@ -354,29 +226,29 @@ const j = (a) => {
|
|
|
354
226
|
}, tt = {
|
|
355
227
|
transform: "rotate(180deg)"
|
|
356
228
|
};
|
|
357
|
-
|
|
229
|
+
z(() => {
|
|
358
230
|
if (!i) return;
|
|
359
231
|
const s = (k) => {
|
|
360
232
|
if (!i) return;
|
|
361
|
-
const
|
|
362
|
-
if (!
|
|
363
|
-
const S = b.current.contains(
|
|
364
|
-
!S && !
|
|
233
|
+
const D = k.target;
|
|
234
|
+
if (!D || !b.current) return;
|
|
235
|
+
const S = b.current.contains(D), lt = D.closest(".i18n-switcher-button") !== null;
|
|
236
|
+
!S && !lt && R(!1);
|
|
365
237
|
};
|
|
366
238
|
return document.addEventListener("click", s), () => {
|
|
367
239
|
document.removeEventListener("click", s);
|
|
368
240
|
};
|
|
369
241
|
}, [i]);
|
|
370
|
-
const et = { ...E, ...
|
|
242
|
+
const et = { ...E, ...m }, nt = { ...Z, ...u }, ot = { ...G, ...l }, rt = { ...J, ...r }, st = {
|
|
371
243
|
...Y,
|
|
372
244
|
...i ? tt : {},
|
|
373
245
|
...P
|
|
374
|
-
}, at =
|
|
375
|
-
const k = s.code ===
|
|
246
|
+
}, at = T.map((s) => {
|
|
247
|
+
const k = s.code === v, D = {
|
|
376
248
|
...Q,
|
|
377
249
|
...k ? X : {},
|
|
378
|
-
...
|
|
379
|
-
...k ?
|
|
250
|
+
...d,
|
|
251
|
+
...k ? f : {},
|
|
380
252
|
width: "100%",
|
|
381
253
|
textAlign: "left",
|
|
382
254
|
border: "none",
|
|
@@ -386,14 +258,14 @@ const j = (a) => {
|
|
|
386
258
|
"li",
|
|
387
259
|
{
|
|
388
260
|
key: s.code,
|
|
389
|
-
style:
|
|
261
|
+
style: rt
|
|
390
262
|
},
|
|
391
263
|
h(
|
|
392
264
|
"button",
|
|
393
265
|
{
|
|
394
266
|
type: "button",
|
|
395
267
|
className: `switcher-locale-${s.code}`,
|
|
396
|
-
style:
|
|
268
|
+
style: D,
|
|
397
269
|
onClick: (S) => {
|
|
398
270
|
S.preventDefault(), S.stopPropagation(), B(s.code);
|
|
399
271
|
}
|
|
@@ -417,7 +289,7 @@ const j = (a) => {
|
|
|
417
289
|
className: "i18n-switcher-button",
|
|
418
290
|
style: nt,
|
|
419
291
|
onClick: (s) => {
|
|
420
|
-
s.preventDefault(), s.stopPropagation(),
|
|
292
|
+
s.preventDefault(), s.stopPropagation(), L(s);
|
|
421
293
|
},
|
|
422
294
|
ariaHaspopup: "true",
|
|
423
295
|
ariaExpanded: i
|
|
@@ -429,40 +301,142 @@ const j = (a) => {
|
|
|
429
301
|
"ul",
|
|
430
302
|
{
|
|
431
303
|
className: "i18n-switcher-dropdown",
|
|
432
|
-
style:
|
|
304
|
+
style: ot
|
|
433
305
|
},
|
|
434
306
|
...at
|
|
435
307
|
) : null
|
|
436
308
|
);
|
|
437
|
-
},
|
|
438
|
-
const {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
309
|
+
}, wt = (a) => {
|
|
310
|
+
const { t, tc: n, tn: e, td: o, tdr: w, locale: y, getRoute: m } = j(), {
|
|
311
|
+
keypath: u,
|
|
312
|
+
params: l,
|
|
313
|
+
tag: r = "span",
|
|
314
|
+
plural: d,
|
|
315
|
+
defaultValue: f,
|
|
316
|
+
html: P = !1,
|
|
317
|
+
hideIfEmpty: x = !1,
|
|
318
|
+
customPluralRule: I,
|
|
319
|
+
number: c,
|
|
320
|
+
date: g,
|
|
321
|
+
relativeDate: C,
|
|
322
|
+
...i
|
|
323
|
+
} = a, R = m(), b = (v, p, L) => h(
|
|
324
|
+
v,
|
|
325
|
+
p,
|
|
326
|
+
L
|
|
446
327
|
);
|
|
328
|
+
if (c !== void 0) {
|
|
329
|
+
const v = Number(c), p = e(v), L = t(u, { number: p, ...l || {} }, void 0, R), _ = typeof L == "string" ? L : String(L);
|
|
330
|
+
return P ? b(r, { ...i, dangerouslySetInnerHTML: { __html: _ } }, void 0) : b(r, i, _);
|
|
331
|
+
}
|
|
332
|
+
if (g !== void 0) {
|
|
333
|
+
const v = o(g), p = t(u, { date: v, ...l || {} }, void 0, R), L = typeof p == "string" ? p : String(p);
|
|
334
|
+
return P ? b(r, { ...i, dangerouslySetInnerHTML: { __html: L } }, void 0) : b(r, i, L);
|
|
335
|
+
}
|
|
336
|
+
if (C !== void 0) {
|
|
337
|
+
const v = w(C), p = t(u, { relativeDate: v, ...l || {} }, void 0, R), L = typeof p == "string" ? p : String(p);
|
|
338
|
+
return P ? b(r, { ...i, dangerouslySetInnerHTML: { __html: L } }, void 0) : b(r, i, L);
|
|
339
|
+
}
|
|
340
|
+
if (d !== void 0) {
|
|
341
|
+
const v = Number.parseInt(d.toString(), 10);
|
|
342
|
+
let p;
|
|
343
|
+
return I ? p = I(
|
|
344
|
+
u,
|
|
345
|
+
v,
|
|
346
|
+
l || {},
|
|
347
|
+
y,
|
|
348
|
+
(_, A, B) => {
|
|
349
|
+
const E = t(_, A, B, R);
|
|
350
|
+
return typeof E == "string" ? E : String(E);
|
|
351
|
+
}
|
|
352
|
+
) || "" : p = n(u, { count: v, ...l || {} }, f), P ? b(r, { ...i, dangerouslySetInnerHTML: { __html: p } }, void 0) : b(r, i, p);
|
|
353
|
+
}
|
|
354
|
+
const T = t(u, l, f, R), N = typeof T == "string" ? T : String(T);
|
|
355
|
+
return x && !N.trim() ? f ? h(it, null, f) : null : P ? b(r, { ...i, dangerouslySetInnerHTML: { __html: N } }, void 0) : b(r, i, N);
|
|
447
356
|
};
|
|
357
|
+
class ft extends ct {
|
|
358
|
+
_locale;
|
|
359
|
+
_fallbackLocale;
|
|
360
|
+
_currentRoute = "general";
|
|
361
|
+
listeners = /* @__PURE__ */ new Set();
|
|
362
|
+
revision = 0;
|
|
363
|
+
storage;
|
|
364
|
+
constructor(t) {
|
|
365
|
+
const n = {
|
|
366
|
+
translations: /* @__PURE__ */ new Map()
|
|
367
|
+
};
|
|
368
|
+
if (super({
|
|
369
|
+
storage: n,
|
|
370
|
+
plural: t.plural,
|
|
371
|
+
missingWarn: t.missingWarn,
|
|
372
|
+
missingHandler: t.missingHandler
|
|
373
|
+
}), this.storage = n, this._locale = t.locale, this._fallbackLocale = t.fallbackLocale || t.locale, t.messages)
|
|
374
|
+
for (const [e, o] of Object.entries(t.messages))
|
|
375
|
+
this.helper.loadTranslations(e, o);
|
|
376
|
+
}
|
|
377
|
+
subscribe = (t) => (this.listeners.add(t), () => this.listeners.delete(t));
|
|
378
|
+
getSnapshot = () => `${this._locale}:${this._currentRoute}:${this.revision}`;
|
|
379
|
+
notify() {
|
|
380
|
+
this.revision++, this.listeners.forEach((t) => t());
|
|
381
|
+
}
|
|
382
|
+
get locale() {
|
|
383
|
+
return this._locale;
|
|
384
|
+
}
|
|
385
|
+
set locale(t) {
|
|
386
|
+
this._locale !== t && (this._locale = t, this.notify());
|
|
387
|
+
}
|
|
388
|
+
get fallbackLocale() {
|
|
389
|
+
return this._fallbackLocale;
|
|
390
|
+
}
|
|
391
|
+
set fallbackLocale(t) {
|
|
392
|
+
this._fallbackLocale = t;
|
|
393
|
+
}
|
|
394
|
+
get currentRoute() {
|
|
395
|
+
return this._currentRoute;
|
|
396
|
+
}
|
|
397
|
+
setRoute(t) {
|
|
398
|
+
this._currentRoute !== t && (this._currentRoute = t, this.notify());
|
|
399
|
+
}
|
|
400
|
+
getLocale() {
|
|
401
|
+
return this._locale;
|
|
402
|
+
}
|
|
403
|
+
getFallbackLocale() {
|
|
404
|
+
return this._fallbackLocale;
|
|
405
|
+
}
|
|
406
|
+
getRoute() {
|
|
407
|
+
return this._currentRoute;
|
|
408
|
+
}
|
|
409
|
+
addTranslations(t, n, e = !0) {
|
|
410
|
+
super.loadTranslationsCore(t, n, e), this.notify();
|
|
411
|
+
}
|
|
412
|
+
addRouteTranslations(t, n, e, o = !0) {
|
|
413
|
+
super.loadRouteTranslationsCore(t, n, e, o), this.notify();
|
|
414
|
+
}
|
|
415
|
+
clearCache() {
|
|
416
|
+
super.clearCache(), this.notify();
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
function Pt(a) {
|
|
420
|
+
return new ft(a);
|
|
421
|
+
}
|
|
448
422
|
function pt(a, t) {
|
|
449
|
-
const n = a.map((
|
|
450
|
-
const
|
|
451
|
-
|
|
452
|
-
const
|
|
453
|
-
return w === t ?
|
|
423
|
+
const n = a.map((o) => o.code), e = (o, w) => {
|
|
424
|
+
const m = (typeof o == "string" ? o : o.path || "/").split("/").filter(Boolean), u = m[0];
|
|
425
|
+
u !== void 0 && n.includes(u) && m.shift();
|
|
426
|
+
const l = `/${m.join("/")}`;
|
|
427
|
+
return w === t ? l : `/${w}${l === "/" ? "" : l}`;
|
|
454
428
|
};
|
|
455
429
|
return {
|
|
456
430
|
// Просто рендерим <a>, навигацию перехватит onClick в I18nLink
|
|
457
431
|
linkComponent: void 0,
|
|
458
432
|
getCurrentPath: () => typeof window < "u" ? window.location.pathname : "/",
|
|
459
|
-
push: (
|
|
460
|
-
typeof window < "u" && (window.history.pushState({}, "",
|
|
433
|
+
push: (o) => {
|
|
434
|
+
typeof window < "u" && (window.history.pushState({}, "", o.path), window.dispatchEvent(new Event("popstate")));
|
|
461
435
|
},
|
|
462
|
-
replace: (
|
|
463
|
-
typeof window < "u" && (window.history.replaceState({}, "",
|
|
436
|
+
replace: (o) => {
|
|
437
|
+
typeof window < "u" && (window.history.replaceState({}, "", o.path), window.dispatchEvent(new Event("popstate")));
|
|
464
438
|
},
|
|
465
|
-
resolvePath: (
|
|
439
|
+
resolvePath: (o, w) => e(o, w),
|
|
466
440
|
getRoute: () => typeof window < "u" ? {
|
|
467
441
|
fullPath: window.location.pathname + window.location.search,
|
|
468
442
|
query: Object.fromEntries(new URLSearchParams(window.location.search))
|
|
@@ -477,23 +451,23 @@ export {
|
|
|
477
451
|
Rt as FormatService,
|
|
478
452
|
O as I18nContext,
|
|
479
453
|
V as I18nDefaultLocaleContext,
|
|
480
|
-
|
|
454
|
+
bt as I18nGroup,
|
|
481
455
|
vt as I18nLink,
|
|
482
456
|
F as I18nLocalesContext,
|
|
483
|
-
|
|
457
|
+
yt as I18nProvider,
|
|
484
458
|
q as I18nRouterContext,
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
459
|
+
Lt as I18nSwitcher,
|
|
460
|
+
wt as I18nT,
|
|
461
|
+
ft as PreactI18n,
|
|
488
462
|
pt as createBrowserHistoryAdapter,
|
|
489
|
-
|
|
463
|
+
Pt as createI18n,
|
|
490
464
|
St as createPreactRouterAdapter,
|
|
491
465
|
xt as defaultPlural,
|
|
492
466
|
It as interpolate,
|
|
493
467
|
j as useI18n,
|
|
494
468
|
K as useI18nContext,
|
|
495
|
-
|
|
469
|
+
dt as useI18nDefaultLocale,
|
|
496
470
|
U as useI18nLocales,
|
|
497
|
-
|
|
471
|
+
M as useI18nRouter
|
|
498
472
|
};
|
|
499
473
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/i18n.ts","../src/injection.ts","../src/context.tsx","../src/components/I18nT.tsx","../src/components/I18nLink.tsx","../src/components/I18nSwitcher.tsx","../src/components/I18nGroup.tsx","../src/router/adapter.tsx"],"sourcesContent":["import {\n BaseI18n,\n type TranslationCache,\n} from '@i18n-micro/core'\nimport type {\n Translations,\n PluralFunc,\n} from '@i18n-micro/types'\n\nexport interface PreactI18nOptions {\n locale: string\n fallbackLocale?: string\n messages?: Record<string, Translations>\n plural?: PluralFunc\n missingWarn?: boolean\n missingHandler?: (locale: string, key: string, routeName: string) => void\n}\n\n/**\n * Preact I18n Adapter\n *\n * Provides a Preact-compatible i18n instance that uses the shared core logic.\n * Implements Observer pattern for reactivity with useSyncExternalStore.\n * Works with Preact through preact/compat for React compatibility.\n */\nexport class PreactI18n extends BaseI18n {\n private _locale: string\n private _fallbackLocale: string\n private _currentRoute: string = 'general'\n private listeners = new Set<() => void>()\n private revision = 0\n\n // Cache для Core (plain objects, не реактивные)\n public readonly cache: TranslationCache\n\n constructor(options: PreactI18nOptions) {\n // Create cache first\n const cache: TranslationCache = {\n generalLocaleCache: {},\n routeLocaleCache: {},\n dynamicTranslationsCaches: [],\n serverTranslationCache: {},\n }\n\n // Call parent constructor with options\n super({\n cache,\n plural: options.plural,\n missingWarn: options.missingWarn,\n missingHandler: options.missingHandler,\n })\n\n // Assign cache to public readonly property\n this.cache = cache\n\n this._locale = options.locale\n this._fallbackLocale = options.fallbackLocale || options.locale\n\n // Загружаем начальные сообщения\n if (options.messages) {\n for (const [lang, msgs] of Object.entries(options.messages)) {\n this.helper.loadTranslations(lang, msgs)\n }\n }\n }\n\n // Для useSyncExternalStore\n subscribe = (listener: () => void) => {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n getSnapshot = () => {\n // Возвращаем комбинированную строку локали и ревизии кэша\n // Это заставит компонент перерендериться при изменении\n return `${this._locale}:${this._currentRoute}:${this.revision}`\n }\n\n private notify() {\n this.revision++\n this.listeners.forEach((listener) => {\n listener()\n })\n }\n\n // Геттер/Сеттер для локали\n get locale(): string {\n return this._locale\n }\n\n set locale(val: string) {\n if (this._locale !== val) {\n this._locale = val\n this.notify()\n }\n }\n\n // Геттер/Сеттер для fallback локали\n get fallbackLocale(): string {\n return this._fallbackLocale\n }\n\n set fallbackLocale(val: string) {\n this._fallbackLocale = val\n }\n\n // Геттер/Сеттер для текущего роута\n get currentRoute(): string {\n return this._currentRoute\n }\n\n setRoute(routeName: string): void {\n if (this._currentRoute !== routeName) {\n this._currentRoute = routeName\n this.notify()\n }\n }\n\n // --- Implementation of abstract methods ---\n\n public getLocale(): string {\n return this._locale\n }\n\n public getFallbackLocale(): string {\n return this._fallbackLocale\n }\n\n public getRoute(): string {\n return this._currentRoute\n }\n\n // Translation management (uses protected methods from base class)\n public addTranslations(locale: string, translations: Translations, merge: boolean = true): void {\n super.loadTranslationsCore(locale, translations, merge)\n this.notify()\n }\n\n public addRouteTranslations(\n locale: string,\n routeName: string,\n translations: Translations,\n merge: boolean = true,\n ): void {\n super.loadRouteTranslationsCore(locale, routeName, translations, merge)\n this.notify()\n }\n\n public override clearCache(): void {\n super.clearCache()\n this.notify()\n }\n}\n\n/**\n * Create a new PreactI18n instance\n */\nexport function createI18n(options: PreactI18nOptions): PreactI18n {\n return new PreactI18n(options)\n}\n","import { createContext } from 'preact'\nimport { useContext } from 'preact/hooks'\nimport type { PreactI18n } from './i18n'\nimport type { Locale } from '@i18n-micro/types'\nimport type { I18nRoutingStrategy } from './router/types'\n\n// Context keys (analogous to Vue's InjectionKey)\nexport const I18nContext = createContext<PreactI18n | null>(null)\nexport const I18nLocalesContext = createContext<Locale[] | null>(null)\nexport const I18nDefaultLocaleContext = createContext<string | null>(null)\nexport const I18nRouterContext = createContext<I18nRoutingStrategy | null>(null)\n\n// Helper hooks (analogous to Vue's inject)\nexport const useI18nContext = () => {\n const context = useContext(I18nContext)\n if (!context) {\n throw new Error('[i18n-micro] I18nContext not found. Make sure I18nProvider is used.')\n }\n return context\n}\n\nexport const useI18nLocales = () => {\n return useContext(I18nLocalesContext)\n}\n\nexport const useI18nDefaultLocale = () => {\n return useContext(I18nDefaultLocaleContext)\n}\n\nexport const useI18nRouter = () => {\n return useContext(I18nRouterContext)\n}\n","import { h } from 'preact'\nimport { useEffect, useState } from 'preact/hooks'\nimport type { ComponentChildren } from 'preact'\nimport type { PreactI18n } from './i18n'\nimport type {\n Translations,\n Params,\n TranslationKey,\n CleanTranslation,\n Locale,\n} from '@i18n-micro/types'\nimport {\n I18nContext,\n I18nLocalesContext,\n I18nDefaultLocaleContext,\n I18nRouterContext,\n useI18nContext,\n useI18nLocales,\n useI18nDefaultLocale,\n useI18nRouter,\n} from './injection'\nimport type { I18nRoutingStrategy } from './router/types'\n\nexport interface I18nProviderProps {\n i18n: PreactI18n\n locales?: Locale[]\n defaultLocale?: string\n routingStrategy?: I18nRoutingStrategy\n children?: ComponentChildren\n}\n\nexport function I18nProvider({ i18n, locales, defaultLocale, routingStrategy, children }: I18nProviderProps) {\n return h(\n I18nContext.Provider,\n { value: i18n },\n locales\n ? h(\n I18nLocalesContext.Provider,\n { value: locales },\n defaultLocale\n ? h(\n I18nDefaultLocaleContext.Provider,\n { value: defaultLocale },\n routingStrategy\n ? h(\n I18nRouterContext.Provider,\n { value: routingStrategy },\n children,\n )\n : children,\n )\n : children,\n )\n : children,\n )\n}\n\nexport interface UseI18nOptions {\n locales?: Locale[]\n defaultLocale?: string\n}\n\nexport interface UseI18nReturn {\n // Translation methods\n t: (key: TranslationKey, params?: Params, defaultValue?: string | null, routeName?: string) => CleanTranslation\n ts: (key: TranslationKey, params?: Params, defaultValue?: string, routeName?: string) => string\n tc: (key: TranslationKey, count: number | Params, defaultValue?: string) => string\n tn: (value: number, options?: Intl.NumberFormatOptions) => string\n td: (value: Date | number | string, options?: Intl.DateTimeFormatOptions) => string\n tdr: (value: Date | number | string, options?: Intl.RelativeTimeFormatOptions) => string\n has: (key: TranslationKey, routeName?: string) => boolean\n\n // Locale management\n locale: string\n fallbackLocale: string\n currentRoute: string\n setLocale: (locale: string) => void\n\n // Route management\n setRoute: (routeName: string) => void\n getRoute: () => string\n getLocales: () => Locale[]\n defaultLocale: () => string\n getLocaleName: () => string | null\n\n // Router methods (if router is available)\n switchLocale?: (locale: string) => void\n localeRoute?: (to: string | { path?: string }, locale?: string) => string | { path?: string }\n localePath?: (to: string | { path?: string }, locale?: string) => string\n\n // Translation management\n addTranslations: (locale: string, translations: Translations, merge?: boolean) => void\n addRouteTranslations: (locale: string, routeName: string, translations: Translations, merge?: boolean) => void\n clearCache: () => void\n}\n\nexport const useI18n = (options?: UseI18nOptions): UseI18nReturn => {\n const i18n = useI18nContext()\n const router = useI18nRouter()\n const injectedLocales = useI18nLocales()\n const injectedDefaultLocale = useI18nDefaultLocale()\n\n // --- Замена useSyncExternalStore для Pure Preact ---\n // Подписываемся на изменения в i18n и форсируем ре-рендер\n const [, forceUpdate] = useState(0)\n\n useEffect(() => {\n // subscribe возвращает функцию отписки\n const unsubscribe = i18n.subscribe(() => {\n forceUpdate(n => n + 1)\n })\n return unsubscribe\n }, [i18n])\n // ---------------------------------------------------\n\n const locales = options?.locales || injectedLocales || []\n const defaultLocale = options?.defaultLocale || injectedDefaultLocale || i18n.locale\n\n const resolveLocalePath = (to: string | { path?: string }, localeCode?: string): string | { path?: string } => {\n if (!router?.resolvePath) {\n return to\n }\n return router.resolvePath(to, localeCode || i18n.locale)\n }\n\n const switchLocaleHelper = (newLocale: string): void => {\n i18n.locale = newLocale\n if (router) {\n const currentPath = router.getCurrentPath()\n const newPath = resolveLocalePath(currentPath, newLocale)\n router.push(typeof newPath === 'string' ? { path: newPath } : { path: newPath.path || '/' })\n }\n }\n\n return {\n // Translation methods\n t: i18n.t.bind(i18n),\n ts: i18n.ts.bind(i18n),\n tc: i18n.tc.bind(i18n),\n tn: i18n.tn.bind(i18n),\n td: i18n.td.bind(i18n),\n tdr: i18n.tdr.bind(i18n),\n has: i18n.has.bind(i18n),\n\n // Locale management\n get locale() {\n return i18n.locale\n },\n get fallbackLocale() {\n return i18n.fallbackLocale\n },\n get currentRoute() {\n return i18n.currentRoute\n },\n setLocale: (locale: string) => {\n i18n.locale = locale\n },\n\n // Route management\n setRoute: i18n.setRoute.bind(i18n),\n getRoute: i18n.getRoute.bind(i18n),\n getLocales: () => locales,\n defaultLocale: () => defaultLocale,\n getLocaleName: () => {\n const current = locales.find(l => l.code === i18n.locale)\n return current?.displayName || null\n },\n\n // Router methods (always available, but navigation handled by components)\n switchLocale: switchLocaleHelper,\n localeRoute: resolveLocalePath,\n localePath: (to: string | { path?: string }, locale?: string) => {\n const res = resolveLocalePath(to, locale)\n return typeof res === 'string' ? res : (res.path || '/')\n },\n\n // Translation management\n addTranslations: i18n.addTranslations.bind(i18n),\n addRouteTranslations: i18n.addRouteTranslations.bind(i18n),\n clearCache: i18n.clearCache.bind(i18n),\n }\n}\n\n// Export context for advanced usage\nexport { I18nContext } from './injection'\n","import { h, Fragment } from 'preact'\nimport type { JSX } from 'preact'\nimport { useI18n } from '../context'\nimport type { TranslationKey, PluralFunc } from '@i18n-micro/types'\n\nexport interface I18nTProps extends Omit<JSX.HTMLAttributes<HTMLElement>, 'children'> {\n keypath: TranslationKey\n params?: Record<string, string | number | boolean>\n tag?: keyof JSX.IntrinsicElements\n plural?: number | string\n defaultValue?: string\n html?: boolean\n hideIfEmpty?: boolean\n customPluralRule?: PluralFunc\n number?: number | string\n date?: Date | string | number\n relativeDate?: Date | string | number\n children?: never // I18nT doesn't support children - translation is rendered as content\n}\n\nexport const I18nT = (props: I18nTProps): JSX.Element | null => {\n const { t, tc, tn, td, tdr, locale, getRoute } = useI18n()\n const {\n keypath,\n params,\n tag = 'span',\n plural,\n defaultValue,\n html = false,\n hideIfEmpty = false,\n customPluralRule,\n number,\n date,\n relativeDate,\n ...restProps\n } = props\n\n const route = getRoute()\n\n // Helper function to create element with proper typing\n const createElement = (\n elementTag: keyof JSX.IntrinsicElements,\n elementProps: JSX.HTMLAttributes<HTMLElement>,\n children?: string,\n ): JSX.Element => {\n return h(\n elementTag as unknown as keyof JSX.IntrinsicElements,\n elementProps as unknown as JSX.HTMLAttributes<HTMLElement>,\n children,\n ) as JSX.Element\n }\n\n // Handle number formatting\n if (number !== undefined) {\n const numberValue = Number(number)\n const formattedNumber = tn(numberValue)\n const translation = t(keypath, { number: formattedNumber, ...(params || {}) }, undefined, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n return createElement(tag, restProps, content)\n }\n\n // Handle date formatting\n if (date !== undefined) {\n const formattedDate = td(date)\n const translation = t(keypath, { date: formattedDate, ...(params || {}) }, undefined, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n return createElement(tag, restProps, content)\n }\n\n // Handle relative date formatting\n if (relativeDate !== undefined) {\n const formattedRelativeDate = tdr(relativeDate)\n const translation = t(keypath, { relativeDate: formattedRelativeDate, ...(params || {}) }, undefined, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n return createElement(tag, restProps, content)\n }\n\n // Handle pluralization\n if (plural !== undefined) {\n const count = Number.parseInt(plural.toString())\n let translation: string\n if (customPluralRule) {\n const result = customPluralRule(\n keypath,\n count,\n params || {},\n locale,\n (k: TranslationKey, p?: Record<string, string | number | boolean>, dv?: string) => {\n const tResult = t(k, p, dv, route)\n return typeof tResult === 'string' ? tResult : String(tResult)\n },\n )\n translation = result || ''\n }\n else {\n translation = tc(keypath, { count, ...(params || {}) }, defaultValue)\n }\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: translation } }, undefined)\n }\n return createElement(tag, restProps, translation)\n }\n\n // Regular translation\n const translation = t(keypath, params, defaultValue, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n\n if (hideIfEmpty && !content.trim()) {\n return defaultValue ? (h(Fragment, null, defaultValue) as JSX.Element) : null\n }\n\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n\n return createElement(tag, restProps, content)\n}\n","import { h } from 'preact'\nimport type { JSX } from 'preact'\nimport { useI18n } from '../context'\nimport { useI18nRouter } from '../injection'\n\nexport interface I18nLinkProps extends JSX.AnchorHTMLAttributes<HTMLAnchorElement> {\n to: string | { path?: string }\n activeStyle?: Record<string, string | number>\n localeRoute?: (to: string | { path?: string }, locale?: string) => string | { path?: string }\n}\n\nexport const I18nLink = (props: I18nLinkProps): JSX.Element => {\n const i18n = useI18n()\n const router = useI18nRouter()\n const { to, activeStyle, localeRoute: localeRouteProp, children, ...restProps } = props\n\n // Use prop if provided, otherwise fallback to useI18n\n const localeRoute = localeRouteProp || i18n.localeRoute\n\n const isExternalLink = (): boolean => {\n if (typeof to === 'string') {\n return /^(?:https?:\\/\\/|\\/\\/|[a-zA-Z0-9-]+\\.[a-zA-Z]{2,})|tel:|mailto:/.test(to)\n }\n return false\n }\n\n const externalHref = (): string | undefined => {\n if (isExternalLink() && typeof to === 'string') {\n if (!/^https?:\\/\\//.test(to)) {\n return `https://${to}`\n }\n return to\n }\n return undefined\n }\n\n const targetPath = (): string => {\n if (isExternalLink()) {\n if (typeof to === 'string') {\n return to\n }\n const toObj = to as { path?: string }\n return toObj?.path || '/'\n }\n\n if (localeRoute) {\n const res = localeRoute(to)\n return typeof res === 'string' ? res : (res.path || '/')\n }\n\n if (!router?.resolvePath) {\n return typeof to === 'string' ? to : (to.path || '/')\n }\n\n const res = router.resolvePath(to, i18n.locale)\n return typeof res === 'string' ? res : (res.path || '/')\n }\n\n const isActive = (): boolean => {\n if (isExternalLink() || !router) {\n return false\n }\n\n const currentPath = router.getCurrentPath()\n const linkPath = targetPath()\n\n // Normalize paths (remove trailing slashes)\n const normalizedCurrent = currentPath.replace(/\\/$/, '')\n const normalizedLink = linkPath.replace(/\\/$/, '')\n\n // Exact match (ignoring query params and hash)\n if (normalizedCurrent === normalizedLink) {\n return true\n }\n\n // Partial match: check if current path starts with link path\n // This allows parent routes to be marked as active\n if (normalizedCurrent.startsWith(normalizedLink + '/')) {\n return true\n }\n\n return false\n }\n\n const computedStyle: Record<string, string | number> = isActive() ? (activeStyle || {}) : {}\n const toValue = targetPath()\n\n const handleClick = (e: JSX.TargetedMouseEvent<HTMLAnchorElement>) => {\n if (props.onClick) {\n props.onClick(e)\n }\n\n // Если это не внешний линк и нет модификаторов (ctrl/meta)\n if (!e.defaultPrevented && !e.button && !e.metaKey && !e.ctrlKey && router && !isExternalLink()) {\n e.preventDefault()\n router.push({ path: toValue })\n }\n }\n\n if (isExternalLink()) {\n return h(\n 'a',\n {\n ...restProps,\n href: externalHref(),\n style: computedStyle,\n target: '_blank',\n rel: 'noopener noreferrer',\n },\n children,\n ) as JSX.Element\n }\n\n // Use router linkComponent if available\n if (router?.linkComponent) {\n const LinkComponent = router.linkComponent\n if (typeof LinkComponent === 'string') {\n return h(\n LinkComponent,\n {\n ...restProps,\n href: toValue,\n style: computedStyle,\n },\n children,\n ) as JSX.Element\n }\n // Type assertion needed because React.ComponentType from I18nRoutingStrategy\n // is compatible with Preact components at runtime\n const Component = LinkComponent as unknown as (props: {\n href: string\n children?: JSX.Element | JSX.Element[]\n style?: Record<string, string | number>\n className?: string\n [key: string]: unknown\n }) => JSX.Element\n // Extract only the props that are compatible with the component type\n const componentProps = {\n ...restProps,\n href: toValue,\n style: computedStyle,\n } as {\n href: string\n children?: JSX.Element | JSX.Element[]\n style?: Record<string, string | number>\n className?: string\n [key: string]: unknown\n }\n return h(\n Component,\n componentProps,\n children,\n ) as JSX.Element\n }\n\n // Fallback to anchor with onClick handler\n return h(\n 'a',\n {\n ...restProps,\n href: toValue,\n style: computedStyle,\n onClick: handleClick,\n },\n children,\n ) as JSX.Element\n}\n","import { h } from 'preact'\nimport { useState, useEffect, useRef } from 'preact/hooks'\nimport type { JSX } from 'preact'\nimport { useI18n } from '../context'\nimport { useI18nRouter, useI18nLocales, useI18nContext } from '../injection'\nimport type { Locale } from '@i18n-micro/types'\n\nexport interface I18nSwitcherProps extends JSX.HTMLAttributes<HTMLDivElement> {\n locales?: Locale[]\n currentLocale?: string | (() => string)\n getLocaleName?: () => string | null\n switchLocale?: (locale: string) => void\n localeRoute?: (to: string | { path?: string }, locale?: string) => string | { path?: string }\n customLabels?: Record<string, string>\n customWrapperStyle?: Record<string, string | number>\n customButtonStyle?: Record<string, string | number>\n customDropdownStyle?: Record<string, string | number>\n customItemStyle?: Record<string, string | number>\n customLinkStyle?: Record<string, string | number>\n customActiveLinkStyle?: Record<string, string | number>\n customIconStyle?: Record<string, string | number>\n}\n\nexport const I18nSwitcher = (props: I18nSwitcherProps): JSX.Element => {\n const {\n locales: localesProp,\n currentLocale: currentLocaleProp,\n getLocaleName: getLocaleNameProp,\n switchLocale: switchLocaleProp,\n localeRoute: _localeRouteProp,\n customLabels = {},\n customWrapperStyle,\n customButtonStyle,\n customDropdownStyle,\n customItemStyle,\n customLinkStyle,\n customActiveLinkStyle,\n customIconStyle,\n ...restProps\n } = props\n\n const i18n = useI18n()\n const i18nInstance = useI18nContext()\n const router = useI18nRouter()\n const injectedLocales = useI18nLocales()\n const [dropdownOpen, setDropdownOpen] = useState(false)\n const wrapperRef = useRef<HTMLDivElement>(null)\n\n // Use props if provided, otherwise fallback to injected or useI18n\n const locales = localesProp || injectedLocales || i18n.getLocales() || []\n\n // Get current locale value (handle both string and function)\n const getCurrentLocale = (): string => {\n if (typeof currentLocaleProp === 'function') {\n return currentLocaleProp()\n }\n if (typeof currentLocaleProp === 'string') {\n return currentLocaleProp\n }\n return i18n.locale\n }\n\n const currentLocale = getCurrentLocale()\n const currentLocaleName = getLocaleNameProp ? getLocaleNameProp() : i18n.getLocaleName()\n\n const toggleDropdown = (event?: Event) => {\n if (event) {\n event.stopPropagation()\n event.preventDefault()\n }\n setDropdownOpen(!dropdownOpen)\n }\n\n const localeLabel = (localeItem: Locale): string => {\n const current = customLabels[localeItem.code] || localeItem.displayName\n return current || localeItem.code\n }\n\n const currentLocaleLabel = (): string => {\n const current = locales.find(l => l.code === currentLocale)\n return current ? localeLabel(current) : (currentLocaleName || currentLocale)\n }\n\n const handleSwitchLocale = (code: string) => {\n setDropdownOpen(false)\n if (switchLocaleProp) {\n switchLocaleProp(code)\n return\n }\n\n i18nInstance.locale = code\n\n if (!router) {\n return\n }\n\n const currentPath = router.getCurrentPath()\n const newPath = props.localeRoute\n ? (() => {\n const res = props.localeRoute(currentPath, code)\n return typeof res === 'string' ? res : (res.path || '/')\n })()\n : (router?.resolvePath\n ? (() => {\n const res = router.resolvePath(currentPath, code)\n return typeof res === 'string' ? res : (res.path || '/')\n })()\n : currentPath)\n\n router.push({ path: newPath })\n }\n\n // Default Styles\n const wrapperStyle: Record<string, string | number> = {\n position: 'relative',\n display: 'inline-block',\n verticalAlign: 'middle',\n }\n\n const buttonStyle: Record<string, string | number> = {\n padding: '4px 12px',\n fontSize: '16px',\n cursor: 'pointer',\n backgroundColor: '#fff',\n border: '1px solid #333',\n transition: 'background-color 0.3s ease',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n }\n\n const dropdownStyle: Record<string, string | number> = {\n position: 'absolute',\n top: '100%',\n left: '0',\n zIndex: 1000,\n backgroundColor: '#fff',\n border: '1px solid #333',\n listStyle: 'none',\n padding: '0',\n margin: '4px 0 0 0',\n minWidth: '150px',\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n }\n\n const itemStyle: Record<string, string | number> = {\n margin: '0',\n padding: '0',\n }\n\n const linkStyle: Record<string, string | number> = {\n display: 'block',\n padding: '8px 12px',\n color: '#333',\n textDecoration: 'none',\n transition: 'background-color 0.3s ease',\n cursor: 'pointer',\n }\n\n const activeLinkStyle: Record<string, string | number> = {\n fontWeight: 'bold',\n color: '#007bff',\n }\n\n const iconStyle: Record<string, string | number> = {\n marginLeft: '8px',\n display: 'inline-block',\n transition: 'transform 0.3s ease',\n }\n\n const openIconStyle: Record<string, string | number> = {\n transform: 'rotate(180deg)',\n }\n\n useEffect(() => {\n if (!dropdownOpen) return\n const handler = (event: MouseEvent) => {\n if (!dropdownOpen) return\n\n const target = event.target as HTMLElement\n if (!target || !wrapperRef.current) return\n\n const isClickInside = wrapperRef.current.contains(target)\n const isButtonClick = target.closest('.i18n-switcher-button') !== null\n\n if (!isClickInside && !isButtonClick) {\n setDropdownOpen(false)\n }\n }\n document.addEventListener('click', handler)\n return () => {\n document.removeEventListener('click', handler)\n }\n }, [dropdownOpen])\n\n const mergedWrapperStyle = { ...wrapperStyle, ...customWrapperStyle }\n const mergedButtonStyle = { ...buttonStyle, ...customButtonStyle }\n const mergedDropdownStyle = { ...dropdownStyle, ...customDropdownStyle }\n const mergedItemStyle = { ...itemStyle, ...customItemStyle }\n const mergedIconStyle = {\n ...iconStyle,\n ...(dropdownOpen ? openIconStyle : {}),\n ...customIconStyle,\n }\n\n const dropdownItems = locales.map((localeItem) => {\n const isActive = localeItem.code === currentLocale\n const mergedLinkStyle = {\n ...linkStyle,\n ...(isActive ? activeLinkStyle : {}),\n ...customLinkStyle,\n ...(isActive ? customActiveLinkStyle : {}),\n width: '100%',\n textAlign: 'left',\n border: 'none',\n background: 'transparent',\n }\n\n return h(\n 'li',\n {\n key: localeItem.code,\n style: mergedItemStyle,\n },\n h(\n 'button',\n {\n type: 'button',\n className: `switcher-locale-${localeItem.code}`,\n style: mergedLinkStyle,\n onClick: (e: Event) => {\n e.preventDefault()\n e.stopPropagation()\n handleSwitchLocale(localeItem.code)\n },\n },\n localeLabel(localeItem),\n ),\n )\n })\n\n return h(\n 'div',\n {\n ref: wrapperRef,\n className: 'i18n-switcher-wrapper',\n style: mergedWrapperStyle,\n ...restProps,\n },\n h(\n 'button',\n {\n type: 'button',\n className: 'i18n-switcher-button',\n style: mergedButtonStyle,\n onClick: (e: Event) => {\n e.preventDefault()\n e.stopPropagation()\n toggleDropdown(e)\n },\n ariaHaspopup: 'true',\n ariaExpanded: dropdownOpen,\n },\n h('span', null, currentLocaleLabel()),\n h('span', { style: mergedIconStyle }, '▼'),\n ),\n dropdownOpen\n ? h(\n 'ul',\n {\n className: 'i18n-switcher-dropdown',\n style: mergedDropdownStyle,\n },\n ...dropdownItems,\n )\n : null,\n ) as JSX.Element\n}\n","import { h } from 'preact'\nimport type { JSX, ComponentChildren } from 'preact'\nimport { useI18n } from '../context'\nimport type { TranslationKey } from '@i18n-micro/types'\n\nexport interface I18nGroupProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, 'children'> {\n prefix: string\n groupClass?: string\n children?: (props: { prefix: string, t: (key: string, params?: Record<string, string | number | boolean>) => string }) => ComponentChildren\n}\n\nexport const I18nGroup = (props: I18nGroupProps): JSX.Element => {\n const { prefix, groupClass, children, ...restProps } = props\n const { t, getRoute } = useI18n()\n\n const translate = (key: string, params?: Record<string, string | number | boolean>): string => {\n const result = t(`${prefix}.${key}` as TranslationKey, params, undefined, getRoute())\n return typeof result === 'string' ? result : String(result)\n }\n\n const className = ['i18n-group', groupClass].filter(Boolean).join(' ')\n\n const childrenContent: ComponentChildren = typeof children === 'function'\n ? children({ prefix, t: translate })\n : children\n\n return h(\n 'div',\n { ...restProps, className },\n childrenContent,\n ) as JSX.Element\n}\n","import type { I18nRoutingStrategy } from './types'\nimport type { Locale } from '@i18n-micro/types'\n\n/**\n * Создает адаптер для работы с History API (универсальный для Pure Preact)\n * Работает с любым роутером, который использует History API (wouter, preact-router, и т.д.)\n */\nexport function createBrowserHistoryAdapter(\n locales: Locale[],\n defaultLocale: string,\n): I18nRoutingStrategy {\n const localeCodes = locales.map(loc => loc.code)\n\n /**\n * Path resolution logic (add prefix or not)\n */\n const resolvePath = (to: string | { path?: string }, locale: string): string | { path?: string } => {\n const path = typeof to === 'string' ? to : (to.path || '/')\n const pathSegments = path.split('/').filter(Boolean)\n\n // If path already starts with a locale, remove it\n if (pathSegments.length > 0 && localeCodes.includes(pathSegments[0])) {\n pathSegments.shift()\n }\n\n const cleanPath = '/' + pathSegments.join('/')\n\n // If default locale - return clean path\n if (locale === defaultLocale) {\n return cleanPath\n }\n\n // Otherwise add prefix\n return `/${locale}${cleanPath === '/' ? '' : cleanPath}`\n }\n\n return {\n // Просто рендерим <a>, навигацию перехватит onClick в I18nLink\n linkComponent: undefined,\n\n getCurrentPath: () => {\n if (typeof window !== 'undefined') {\n return window.location.pathname\n }\n return '/'\n },\n\n push: (target) => {\n if (typeof window !== 'undefined') {\n window.history.pushState({}, '', target.path)\n // Вызываем событие, чтобы роутеры (wouter/preact-router) узнали об изменении\n window.dispatchEvent(new Event('popstate'))\n }\n },\n\n replace: (target) => {\n if (typeof window !== 'undefined') {\n window.history.replaceState({}, '', target.path)\n window.dispatchEvent(new Event('popstate'))\n }\n },\n\n resolvePath: (to, locale) => resolvePath(to, locale),\n\n getRoute: () => {\n if (typeof window !== 'undefined') {\n return {\n fullPath: window.location.pathname + window.location.search,\n query: Object.fromEntries(new URLSearchParams(window.location.search)),\n }\n }\n return {\n fullPath: '/',\n query: {},\n }\n },\n }\n}\n\n// Export for backward compatibility (old name)\nexport const createPreactRouterAdapter = createBrowserHistoryAdapter\n"],"names":["PreactI18n","BaseI18n","options","cache","lang","msgs","listener","val","routeName","locale","translations","merge","createI18n","I18nContext","createContext","I18nLocalesContext","I18nDefaultLocaleContext","I18nRouterContext","useI18nContext","context","useContext","useI18nLocales","useI18nDefaultLocale","useI18nRouter","I18nProvider","i18n","locales","defaultLocale","routingStrategy","children","useI18n","router","injectedLocales","injectedDefaultLocale","forceUpdate","useState","useEffect","n","resolveLocalePath","to","localeCode","switchLocaleHelper","newLocale","currentPath","newPath","l","res","I18nT","props","tc","tn","td","tdr","getRoute","keypath","params","tag","plural","defaultValue","html","hideIfEmpty","customPluralRule","number","date","relativeDate","restProps","route","createElement","elementTag","elementProps","numberValue","formattedNumber","translation","content","formattedDate","formattedRelativeDate","count","k","p","dv","tResult","Fragment","I18nLink","activeStyle","localeRouteProp","localeRoute","isExternalLink","externalHref","targetPath","computedStyle","linkPath","normalizedCurrent","normalizedLink","toValue","handleClick","e","LinkComponent","Component","componentProps","I18nSwitcher","localesProp","currentLocaleProp","getLocaleNameProp","switchLocaleProp","_localeRouteProp","customLabels","customWrapperStyle","customButtonStyle","customDropdownStyle","customItemStyle","customLinkStyle","customActiveLinkStyle","customIconStyle","i18nInstance","dropdownOpen","setDropdownOpen","wrapperRef","useRef","currentLocale","currentLocaleName","toggleDropdown","event","localeLabel","localeItem","currentLocaleLabel","current","handleSwitchLocale","code","wrapperStyle","buttonStyle","dropdownStyle","itemStyle","linkStyle","activeLinkStyle","iconStyle","openIconStyle","handler","target","isClickInside","isButtonClick","mergedWrapperStyle","mergedButtonStyle","mergedDropdownStyle","mergedItemStyle","mergedIconStyle","dropdownItems","isActive","mergedLinkStyle","I18nGroup","prefix","groupClass","t","translate","key","result","className","childrenContent","createBrowserHistoryAdapter","localeCodes","loc","resolvePath","pathSegments","cleanPath","createPreactRouterAdapter"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/injection.ts","../src/context.tsx","../src/components/I18nGroup.tsx","../src/components/I18nLink.tsx","../src/components/I18nSwitcher.tsx","../src/components/I18nT.tsx","../src/i18n.ts","../src/router/adapter.tsx"],"sourcesContent":["import type { Locale } from '@i18n-micro/types'\nimport { createContext } from 'preact'\nimport { useContext } from 'preact/hooks'\nimport type { PreactI18n } from './i18n'\nimport type { I18nRoutingStrategy } from './router/types'\n\n// Context keys (analogous to Vue's InjectionKey)\nexport const I18nContext = createContext<PreactI18n | null>(null)\nexport const I18nLocalesContext = createContext<Locale[] | null>(null)\nexport const I18nDefaultLocaleContext = createContext<string | null>(null)\nexport const I18nRouterContext = createContext<I18nRoutingStrategy | null>(null)\n\n// Helper hooks (analogous to Vue's inject)\nexport const useI18nContext = () => {\n const context = useContext(I18nContext)\n if (!context) {\n throw new Error('[i18n-micro] I18nContext not found. Make sure I18nProvider is used.')\n }\n return context\n}\n\nexport const useI18nLocales = () => {\n return useContext(I18nLocalesContext)\n}\n\nexport const useI18nDefaultLocale = () => {\n return useContext(I18nDefaultLocaleContext)\n}\n\nexport const useI18nRouter = () => {\n return useContext(I18nRouterContext)\n}\n","import type { CleanTranslation, Locale, Params, TranslationKey, Translations } from '@i18n-micro/types'\nimport type { ComponentChildren } from 'preact'\nimport { h } from 'preact'\nimport { useEffect, useState } from 'preact/hooks'\nimport type { PreactI18n } from './i18n'\nimport {\n I18nContext,\n I18nDefaultLocaleContext,\n I18nLocalesContext,\n I18nRouterContext,\n useI18nContext,\n useI18nDefaultLocale,\n useI18nLocales,\n useI18nRouter,\n} from './injection'\nimport type { I18nRoutingStrategy } from './router/types'\n\nexport interface I18nProviderProps {\n i18n: PreactI18n\n locales?: Locale[]\n defaultLocale?: string\n routingStrategy?: I18nRoutingStrategy\n children?: ComponentChildren\n}\n\nexport function I18nProvider({ i18n, locales, defaultLocale, routingStrategy, children }: I18nProviderProps) {\n return h(\n I18nContext.Provider,\n { value: i18n },\n locales\n ? h(\n I18nLocalesContext.Provider,\n { value: locales },\n defaultLocale\n ? h(\n I18nDefaultLocaleContext.Provider,\n { value: defaultLocale },\n routingStrategy ? h(I18nRouterContext.Provider, { value: routingStrategy }, children) : children,\n )\n : children,\n )\n : children,\n )\n}\n\nexport interface UseI18nOptions {\n locales?: Locale[]\n defaultLocale?: string\n}\n\nexport interface UseI18nReturn {\n // Translation methods\n t: (key: TranslationKey, params?: Params, defaultValue?: string | null, routeName?: string) => CleanTranslation\n ts: (key: TranslationKey, params?: Params, defaultValue?: string, routeName?: string) => string\n tc: (key: TranslationKey, count: number | Params, defaultValue?: string) => string\n tn: (value: number, options?: Intl.NumberFormatOptions) => string\n td: (value: Date | number | string, options?: Intl.DateTimeFormatOptions) => string\n tdr: (value: Date | number | string, options?: Intl.RelativeTimeFormatOptions) => string\n has: (key: TranslationKey, routeName?: string) => boolean\n\n // Locale management\n locale: string\n fallbackLocale: string\n currentRoute: string\n setLocale: (locale: string) => void\n\n // Route management\n setRoute: (routeName: string) => void\n getRoute: () => string\n getLocales: () => Locale[]\n defaultLocale: () => string\n getLocaleName: () => string | null\n\n // Router methods (if router is available)\n switchLocale?: (locale: string) => void\n localeRoute?: (to: string | { path?: string }, locale?: string) => string | { path?: string }\n localePath?: (to: string | { path?: string }, locale?: string) => string\n\n // Translation management\n addTranslations: (locale: string, translations: Translations, merge?: boolean) => void\n addRouteTranslations: (locale: string, routeName: string, translations: Translations, merge?: boolean) => void\n clearCache: () => void\n}\n\nexport const useI18n = (options?: UseI18nOptions): UseI18nReturn => {\n const i18n = useI18nContext()\n const router = useI18nRouter()\n const injectedLocales = useI18nLocales()\n const injectedDefaultLocale = useI18nDefaultLocale()\n\n // --- Замена useSyncExternalStore для Pure Preact ---\n // Подписываемся на изменения в i18n и форсируем ре-рендер\n const [, forceUpdate] = useState(0)\n\n useEffect(() => {\n // subscribe возвращает функцию отписки\n const unsubscribe = i18n.subscribe(() => {\n forceUpdate((n) => n + 1)\n })\n return unsubscribe\n }, [i18n])\n // ---------------------------------------------------\n\n const locales = options?.locales || injectedLocales || []\n const defaultLocale = options?.defaultLocale || injectedDefaultLocale || i18n.locale\n\n const resolveLocalePath = (to: string | { path?: string }, localeCode?: string): string | { path?: string } => {\n if (!router?.resolvePath) {\n return to\n }\n return router.resolvePath(to, localeCode || i18n.locale)\n }\n\n const switchLocaleHelper = (newLocale: string): void => {\n i18n.locale = newLocale\n if (router) {\n const currentPath = router.getCurrentPath()\n const newPath = resolveLocalePath(currentPath, newLocale)\n router.push(typeof newPath === 'string' ? { path: newPath } : { path: newPath.path || '/' })\n }\n }\n\n return {\n // Translation methods\n t: i18n.t.bind(i18n),\n ts: i18n.ts.bind(i18n),\n tc: i18n.tc.bind(i18n),\n tn: i18n.tn.bind(i18n),\n td: i18n.td.bind(i18n),\n tdr: i18n.tdr.bind(i18n),\n has: i18n.has.bind(i18n),\n\n // Locale management\n get locale() {\n return i18n.locale\n },\n get fallbackLocale() {\n return i18n.fallbackLocale\n },\n get currentRoute() {\n return i18n.currentRoute\n },\n setLocale: (locale: string) => {\n i18n.locale = locale\n },\n\n // Route management\n setRoute: i18n.setRoute.bind(i18n),\n getRoute: i18n.getRoute.bind(i18n),\n getLocales: () => locales,\n defaultLocale: () => defaultLocale,\n getLocaleName: () => {\n const current = locales.find((l) => l.code === i18n.locale)\n return current?.displayName || null\n },\n\n // Router methods (always available, but navigation handled by components)\n switchLocale: switchLocaleHelper,\n localeRoute: resolveLocalePath,\n localePath: (to: string | { path?: string }, locale?: string) => {\n const res = resolveLocalePath(to, locale)\n return typeof res === 'string' ? res : res.path || '/'\n },\n\n // Translation management\n addTranslations: i18n.addTranslations.bind(i18n),\n addRouteTranslations: i18n.addRouteTranslations.bind(i18n),\n clearCache: i18n.clearCache.bind(i18n),\n }\n}\n\n// Export context for advanced usage\nexport { I18nContext } from './injection'\n","import type { TranslationKey } from '@i18n-micro/types'\nimport type { ComponentChildren, JSX } from 'preact'\nimport { h } from 'preact'\nimport { useI18n } from '../context'\n\nexport interface I18nGroupProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, 'children'> {\n prefix: string\n groupClass?: string\n children?: (props: { prefix: string; t: (key: string, params?: Record<string, string | number | boolean>) => string }) => ComponentChildren\n}\n\nexport const I18nGroup = (props: I18nGroupProps): JSX.Element => {\n const { prefix, groupClass, children, ...restProps } = props\n const { t, getRoute } = useI18n()\n\n const translate = (key: string, params?: Record<string, string | number | boolean>): string => {\n const result = t(`${prefix}.${key}` as TranslationKey, params, undefined, getRoute())\n return typeof result === 'string' ? result : String(result)\n }\n\n const className = ['i18n-group', groupClass].filter(Boolean).join(' ')\n\n const childrenContent: ComponentChildren = typeof children === 'function' ? children({ prefix, t: translate }) : children\n\n return h('div', { ...restProps, className }, childrenContent) as JSX.Element\n}\n","import type { JSX } from 'preact'\nimport { h } from 'preact'\nimport { useI18n } from '../context'\nimport { useI18nRouter } from '../injection'\n\nexport interface I18nLinkProps extends JSX.AnchorHTMLAttributes<HTMLAnchorElement> {\n to: string | { path?: string }\n activeStyle?: Record<string, string | number>\n localeRoute?: (to: string | { path?: string }, locale?: string) => string | { path?: string }\n}\n\nexport const I18nLink = (props: I18nLinkProps): JSX.Element => {\n const i18n = useI18n()\n const router = useI18nRouter()\n const { to, activeStyle, localeRoute: localeRouteProp, children, ...restProps } = props\n\n // Use prop if provided, otherwise fallback to useI18n\n const localeRoute = localeRouteProp || i18n.localeRoute\n\n const isExternalLink = (): boolean => {\n if (typeof to === 'string') {\n return /^(?:https?:\\/\\/|\\/\\/|[a-zA-Z0-9-]+\\.[a-zA-Z]{2,})|tel:|mailto:/.test(to)\n }\n return false\n }\n\n const externalHref = (): string | undefined => {\n if (isExternalLink() && typeof to === 'string') {\n if (!/^https?:\\/\\//.test(to)) {\n return `https://${to}`\n }\n return to\n }\n return undefined\n }\n\n const targetPath = (): string => {\n if (isExternalLink()) {\n if (typeof to === 'string') {\n return to\n }\n const toObj = to as { path?: string }\n return toObj?.path || '/'\n }\n\n if (localeRoute) {\n const res = localeRoute(to)\n return typeof res === 'string' ? res : res.path || '/'\n }\n\n if (!router?.resolvePath) {\n return typeof to === 'string' ? to : to.path || '/'\n }\n\n const res = router.resolvePath(to, i18n.locale)\n return typeof res === 'string' ? res : res.path || '/'\n }\n\n const isActive = (): boolean => {\n if (isExternalLink() || !router) {\n return false\n }\n\n const currentPath = router.getCurrentPath()\n const linkPath = targetPath()\n\n // Normalize paths (remove trailing slashes)\n const normalizedCurrent = currentPath.replace(/\\/$/, '')\n const normalizedLink = linkPath.replace(/\\/$/, '')\n\n // Exact match (ignoring query params and hash)\n if (normalizedCurrent === normalizedLink) {\n return true\n }\n\n // Partial match: check if current path starts with link path\n // This allows parent routes to be marked as active\n if (normalizedCurrent.startsWith(`${normalizedLink}/`)) {\n return true\n }\n\n return false\n }\n\n const computedStyle: Record<string, string | number> = isActive() ? activeStyle || {} : {}\n const toValue = targetPath()\n\n const handleClick = (e: JSX.TargetedMouseEvent<HTMLAnchorElement>) => {\n if (props.onClick) {\n props.onClick(e)\n }\n\n // Если это не внешний линк и нет модификаторов (ctrl/meta)\n if (!e.defaultPrevented && !e.button && !e.metaKey && !e.ctrlKey && router && !isExternalLink()) {\n e.preventDefault()\n router.push({ path: toValue })\n }\n }\n\n if (isExternalLink()) {\n return h(\n 'a',\n {\n ...restProps,\n href: externalHref(),\n style: computedStyle,\n target: '_blank',\n rel: 'noopener noreferrer',\n },\n children,\n ) as JSX.Element\n }\n\n // Use router linkComponent if available\n if (router?.linkComponent) {\n const LinkComponent = router.linkComponent\n if (typeof LinkComponent === 'string') {\n return h(\n LinkComponent,\n {\n ...restProps,\n href: toValue,\n style: computedStyle,\n },\n children,\n ) as JSX.Element\n }\n // Type assertion needed because React.ComponentType from I18nRoutingStrategy\n // is compatible with Preact components at runtime\n const Component = LinkComponent as unknown as (props: {\n href: string\n children?: JSX.Element | JSX.Element[]\n style?: Record<string, string | number>\n className?: string\n [key: string]: unknown\n }) => JSX.Element\n // Extract only the props that are compatible with the component type\n const componentProps = {\n ...restProps,\n href: toValue,\n style: computedStyle,\n } as {\n href: string\n children?: JSX.Element | JSX.Element[]\n style?: Record<string, string | number>\n className?: string\n [key: string]: unknown\n }\n return h(Component, componentProps, children) as JSX.Element\n }\n\n // Fallback to anchor with onClick handler\n return h(\n 'a',\n {\n ...restProps,\n href: toValue,\n style: computedStyle,\n onClick: handleClick,\n },\n children,\n ) as JSX.Element\n}\n","import type { Locale } from '@i18n-micro/types'\nimport type { JSX } from 'preact'\nimport { h } from 'preact'\nimport { useEffect, useRef, useState } from 'preact/hooks'\nimport { useI18n } from '../context'\nimport { useI18nContext, useI18nLocales, useI18nRouter } from '../injection'\n\nexport interface I18nSwitcherProps extends JSX.HTMLAttributes<HTMLDivElement> {\n locales?: Locale[]\n currentLocale?: string | (() => string)\n getLocaleName?: () => string | null\n switchLocale?: (locale: string) => void\n localeRoute?: (to: string | { path?: string }, locale?: string) => string | { path?: string }\n customLabels?: Record<string, string>\n customWrapperStyle?: Record<string, string | number>\n customButtonStyle?: Record<string, string | number>\n customDropdownStyle?: Record<string, string | number>\n customItemStyle?: Record<string, string | number>\n customLinkStyle?: Record<string, string | number>\n customActiveLinkStyle?: Record<string, string | number>\n customIconStyle?: Record<string, string | number>\n}\n\nexport const I18nSwitcher = (props: I18nSwitcherProps): JSX.Element => {\n const {\n locales: localesProp,\n currentLocale: currentLocaleProp,\n getLocaleName: getLocaleNameProp,\n switchLocale: switchLocaleProp,\n localeRoute: _localeRouteProp,\n customLabels = {},\n customWrapperStyle,\n customButtonStyle,\n customDropdownStyle,\n customItemStyle,\n customLinkStyle,\n customActiveLinkStyle,\n customIconStyle,\n ...restProps\n } = props\n\n const i18n = useI18n()\n const i18nInstance = useI18nContext()\n const router = useI18nRouter()\n const injectedLocales = useI18nLocales()\n const [dropdownOpen, setDropdownOpen] = useState(false)\n const wrapperRef = useRef<HTMLDivElement>(null)\n\n // Use props if provided, otherwise fallback to injected or useI18n\n const locales = localesProp || injectedLocales || i18n.getLocales() || []\n\n // Get current locale value (handle both string and function)\n const getCurrentLocale = (): string => {\n if (typeof currentLocaleProp === 'function') {\n return currentLocaleProp()\n }\n if (typeof currentLocaleProp === 'string') {\n return currentLocaleProp\n }\n return i18n.locale\n }\n\n const currentLocale = getCurrentLocale()\n const currentLocaleName = getLocaleNameProp ? getLocaleNameProp() : i18n.getLocaleName()\n\n const toggleDropdown = (event?: Event) => {\n if (event) {\n event.stopPropagation()\n event.preventDefault()\n }\n setDropdownOpen(!dropdownOpen)\n }\n\n const localeLabel = (localeItem: Locale): string => {\n const current = customLabels[localeItem.code] || localeItem.displayName\n return current || localeItem.code\n }\n\n const currentLocaleLabel = (): string => {\n const current = locales.find((l) => l.code === currentLocale)\n return current ? localeLabel(current) : currentLocaleName || currentLocale\n }\n\n const handleSwitchLocale = (code: string) => {\n setDropdownOpen(false)\n if (switchLocaleProp) {\n switchLocaleProp(code)\n return\n }\n\n i18nInstance.locale = code\n\n if (!router) {\n return\n }\n\n const currentPath = router.getCurrentPath()\n const newPath = props.localeRoute\n ? (() => {\n const res = props.localeRoute(currentPath, code)\n return typeof res === 'string' ? res : res.path || '/'\n })()\n : router?.resolvePath\n ? (() => {\n const res = router.resolvePath(currentPath, code)\n return typeof res === 'string' ? res : res.path || '/'\n })()\n : currentPath\n\n router.push({ path: newPath })\n }\n\n // Default Styles\n const wrapperStyle: Record<string, string | number> = {\n position: 'relative',\n display: 'inline-block',\n verticalAlign: 'middle',\n }\n\n const buttonStyle: Record<string, string | number> = {\n padding: '4px 12px',\n fontSize: '16px',\n cursor: 'pointer',\n backgroundColor: '#fff',\n border: '1px solid #333',\n transition: 'background-color 0.3s ease',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n }\n\n const dropdownStyle: Record<string, string | number> = {\n position: 'absolute',\n top: '100%',\n left: '0',\n zIndex: 1000,\n backgroundColor: '#fff',\n border: '1px solid #333',\n listStyle: 'none',\n padding: '0',\n margin: '4px 0 0 0',\n minWidth: '150px',\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n }\n\n const itemStyle: Record<string, string | number> = {\n margin: '0',\n padding: '0',\n }\n\n const linkStyle: Record<string, string | number> = {\n display: 'block',\n padding: '8px 12px',\n color: '#333',\n textDecoration: 'none',\n transition: 'background-color 0.3s ease',\n cursor: 'pointer',\n }\n\n const activeLinkStyle: Record<string, string | number> = {\n fontWeight: 'bold',\n color: '#007bff',\n }\n\n const iconStyle: Record<string, string | number> = {\n marginLeft: '8px',\n display: 'inline-block',\n transition: 'transform 0.3s ease',\n }\n\n const openIconStyle: Record<string, string | number> = {\n transform: 'rotate(180deg)',\n }\n\n useEffect(() => {\n if (!dropdownOpen) return\n const handler = (event: MouseEvent) => {\n if (!dropdownOpen) return\n\n const target = event.target as HTMLElement\n if (!target || !wrapperRef.current) return\n\n const isClickInside = wrapperRef.current.contains(target)\n const isButtonClick = target.closest('.i18n-switcher-button') !== null\n\n if (!isClickInside && !isButtonClick) {\n setDropdownOpen(false)\n }\n }\n document.addEventListener('click', handler)\n return () => {\n document.removeEventListener('click', handler)\n }\n }, [dropdownOpen])\n\n const mergedWrapperStyle = { ...wrapperStyle, ...customWrapperStyle }\n const mergedButtonStyle = { ...buttonStyle, ...customButtonStyle }\n const mergedDropdownStyle = { ...dropdownStyle, ...customDropdownStyle }\n const mergedItemStyle = { ...itemStyle, ...customItemStyle }\n const mergedIconStyle = {\n ...iconStyle,\n ...(dropdownOpen ? openIconStyle : {}),\n ...customIconStyle,\n }\n\n const dropdownItems = locales.map((localeItem) => {\n const isActive = localeItem.code === currentLocale\n const mergedLinkStyle = {\n ...linkStyle,\n ...(isActive ? activeLinkStyle : {}),\n ...customLinkStyle,\n ...(isActive ? customActiveLinkStyle : {}),\n width: '100%',\n textAlign: 'left',\n border: 'none',\n background: 'transparent',\n }\n\n return h(\n 'li',\n {\n key: localeItem.code,\n style: mergedItemStyle,\n },\n h(\n 'button',\n {\n type: 'button',\n className: `switcher-locale-${localeItem.code}`,\n style: mergedLinkStyle,\n onClick: (e: Event) => {\n e.preventDefault()\n e.stopPropagation()\n handleSwitchLocale(localeItem.code)\n },\n },\n localeLabel(localeItem),\n ),\n )\n })\n\n return h(\n 'div',\n {\n ref: wrapperRef,\n className: 'i18n-switcher-wrapper',\n style: mergedWrapperStyle,\n ...restProps,\n },\n h(\n 'button',\n {\n type: 'button',\n className: 'i18n-switcher-button',\n style: mergedButtonStyle,\n onClick: (e: Event) => {\n e.preventDefault()\n e.stopPropagation()\n toggleDropdown(e)\n },\n ariaHaspopup: 'true',\n ariaExpanded: dropdownOpen,\n },\n h('span', null, currentLocaleLabel()),\n h('span', { style: mergedIconStyle }, '▼'),\n ),\n dropdownOpen\n ? h(\n 'ul',\n {\n className: 'i18n-switcher-dropdown',\n style: mergedDropdownStyle,\n },\n ...dropdownItems,\n )\n : null,\n ) as JSX.Element\n}\n","import type { PluralFunc, TranslationKey } from '@i18n-micro/types'\nimport type { JSX } from 'preact'\nimport { Fragment, h } from 'preact'\nimport { useI18n } from '../context'\n\nexport interface I18nTProps extends Omit<JSX.HTMLAttributes<HTMLElement>, 'children'> {\n keypath: TranslationKey\n params?: Record<string, string | number | boolean>\n tag?: keyof JSX.IntrinsicElements\n plural?: number | string\n defaultValue?: string\n html?: boolean\n hideIfEmpty?: boolean\n customPluralRule?: PluralFunc\n number?: number | string\n date?: Date | string | number\n relativeDate?: Date | string | number\n children?: never // I18nT doesn't support children - translation is rendered as content\n}\n\nexport const I18nT = (props: I18nTProps): JSX.Element | null => {\n const { t, tc, tn, td, tdr, locale, getRoute } = useI18n()\n const {\n keypath,\n params,\n tag = 'span',\n plural,\n defaultValue,\n html = false,\n hideIfEmpty = false,\n customPluralRule,\n number,\n date,\n relativeDate,\n ...restProps\n } = props\n\n const route = getRoute()\n\n // Helper function to create element with proper typing\n const createElement = (elementTag: keyof JSX.IntrinsicElements, elementProps: JSX.HTMLAttributes<HTMLElement>, children?: string): JSX.Element => {\n return h(\n elementTag as unknown as keyof JSX.IntrinsicElements,\n elementProps as unknown as JSX.HTMLAttributes<HTMLElement>,\n children,\n ) as JSX.Element\n }\n\n // Handle number formatting\n if (number !== undefined) {\n const numberValue = Number(number)\n const formattedNumber = tn(numberValue)\n const translation = t(keypath, { number: formattedNumber, ...(params || {}) }, undefined, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n return createElement(tag, restProps, content)\n }\n\n // Handle date formatting\n if (date !== undefined) {\n const formattedDate = td(date)\n const translation = t(keypath, { date: formattedDate, ...(params || {}) }, undefined, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n return createElement(tag, restProps, content)\n }\n\n // Handle relative date formatting\n if (relativeDate !== undefined) {\n const formattedRelativeDate = tdr(relativeDate)\n const translation = t(keypath, { relativeDate: formattedRelativeDate, ...(params || {}) }, undefined, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n return createElement(tag, restProps, content)\n }\n\n // Handle pluralization\n if (plural !== undefined) {\n const count = Number.parseInt(plural.toString(), 10)\n let translation: string\n if (customPluralRule) {\n const result = customPluralRule(\n keypath,\n count,\n params || {},\n locale,\n (k: TranslationKey, p?: Record<string, string | number | boolean>, dv?: string) => {\n const tResult = t(k, p, dv, route)\n return typeof tResult === 'string' ? tResult : String(tResult)\n },\n )\n translation = result || ''\n } else {\n translation = tc(keypath, { count, ...(params || {}) }, defaultValue)\n }\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: translation } }, undefined)\n }\n return createElement(tag, restProps, translation)\n }\n\n // Regular translation\n const translation = t(keypath, params, defaultValue, route)\n const content = typeof translation === 'string' ? translation : String(translation)\n\n if (hideIfEmpty && !content.trim()) {\n return defaultValue ? (h(Fragment, null, defaultValue) as JSX.Element) : null\n }\n\n if (html) {\n return createElement(tag, { ...restProps, dangerouslySetInnerHTML: { __html: content } }, undefined)\n }\n\n return createElement(tag, restProps, content)\n}\n","import { BaseI18n, type TranslationStorage } from '@i18n-micro/core'\nimport type { PluralFunc, Translations } from '@i18n-micro/types'\n\nexport interface PreactI18nOptions {\n locale: string\n fallbackLocale?: string\n messages?: Record<string, Translations>\n plural?: PluralFunc\n missingWarn?: boolean\n missingHandler?: (locale: string, key: string, routeName: string) => void\n}\n\nexport class PreactI18n extends BaseI18n {\n private _locale: string\n private _fallbackLocale: string\n private _currentRoute: string = 'general'\n private listeners = new Set<() => void>()\n private revision = 0\n\n public readonly storage: TranslationStorage\n\n constructor(options: PreactI18nOptions) {\n const storage: TranslationStorage = {\n translations: new Map<string, Translations>(),\n }\n\n super({\n storage,\n plural: options.plural,\n missingWarn: options.missingWarn,\n missingHandler: options.missingHandler,\n })\n\n this.storage = storage\n this._locale = options.locale\n this._fallbackLocale = options.fallbackLocale || options.locale\n\n if (options.messages) {\n for (const [lang, msgs] of Object.entries(options.messages)) {\n this.helper.loadTranslations(lang, msgs)\n }\n }\n }\n\n subscribe = (listener: () => void) => {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n getSnapshot = () => `${this._locale}:${this._currentRoute}:${this.revision}`\n\n private notify() {\n this.revision++\n this.listeners.forEach((listener) => listener())\n }\n\n get locale(): string {\n return this._locale\n }\n\n set locale(val: string) {\n if (this._locale !== val) {\n this._locale = val\n this.notify()\n }\n }\n\n get fallbackLocale(): string {\n return this._fallbackLocale\n }\n\n set fallbackLocale(val: string) {\n this._fallbackLocale = val\n }\n\n get currentRoute(): string {\n return this._currentRoute\n }\n\n setRoute(routeName: string): void {\n if (this._currentRoute !== routeName) {\n this._currentRoute = routeName\n this.notify()\n }\n }\n\n public getLocale(): string {\n return this._locale\n }\n\n public getFallbackLocale(): string {\n return this._fallbackLocale\n }\n\n public getRoute(): string {\n return this._currentRoute\n }\n\n public addTranslations(locale: string, translations: Translations, merge = true): void {\n super.loadTranslationsCore(locale, translations, merge)\n this.notify()\n }\n\n public addRouteTranslations(locale: string, routeName: string, translations: Translations, merge = true): void {\n super.loadRouteTranslationsCore(locale, routeName, translations, merge)\n this.notify()\n }\n\n public override clearCache(): void {\n super.clearCache()\n this.notify()\n }\n}\n\nexport function createI18n(options: PreactI18nOptions): PreactI18n {\n return new PreactI18n(options)\n}\n","import type { Locale } from '@i18n-micro/types'\nimport type { I18nRoutingStrategy } from './types'\n\n/**\n * Создает адаптер для работы с History API (универсальный для Pure Preact)\n * Работает с любым роутером, который использует History API (wouter, preact-router, и т.д.)\n */\nexport function createBrowserHistoryAdapter(locales: Locale[], defaultLocale: string): I18nRoutingStrategy {\n const localeCodes = locales.map((loc) => loc.code)\n\n /**\n * Path resolution logic (add prefix or not)\n */\n const resolvePath = (to: string | { path?: string }, locale: string): string | { path?: string } => {\n const path = typeof to === 'string' ? to : to.path || '/'\n const pathSegments = path.split('/').filter(Boolean)\n\n // If path already starts with a locale, remove it\n const first = pathSegments[0]\n if (first !== undefined && localeCodes.includes(first)) {\n pathSegments.shift()\n }\n\n const cleanPath = `/${pathSegments.join('/')}`\n\n // If default locale - return clean path\n if (locale === defaultLocale) {\n return cleanPath\n }\n\n // Otherwise add prefix\n return `/${locale}${cleanPath === '/' ? '' : cleanPath}`\n }\n\n return {\n // Просто рендерим <a>, навигацию перехватит onClick в I18nLink\n linkComponent: undefined,\n\n getCurrentPath: () => {\n if (typeof window !== 'undefined') {\n return window.location.pathname\n }\n return '/'\n },\n\n push: (target) => {\n if (typeof window !== 'undefined') {\n window.history.pushState({}, '', target.path)\n // Вызываем событие, чтобы роутеры (wouter/preact-router) узнали об изменении\n window.dispatchEvent(new Event('popstate'))\n }\n },\n\n replace: (target) => {\n if (typeof window !== 'undefined') {\n window.history.replaceState({}, '', target.path)\n window.dispatchEvent(new Event('popstate'))\n }\n },\n\n resolvePath: (to, locale) => resolvePath(to, locale),\n\n getRoute: () => {\n if (typeof window !== 'undefined') {\n return {\n fullPath: window.location.pathname + window.location.search,\n query: Object.fromEntries(new URLSearchParams(window.location.search)),\n }\n }\n return {\n fullPath: '/',\n query: {},\n }\n },\n }\n}\n\n// Export for backward compatibility (old name)\nexport const createPreactRouterAdapter = createBrowserHistoryAdapter\n"],"names":["I18nContext","createContext","I18nLocalesContext","I18nDefaultLocaleContext","I18nRouterContext","useI18nContext","context","useContext","useI18nLocales","useI18nDefaultLocale","useI18nRouter","I18nProvider","i18n","locales","defaultLocale","routingStrategy","children","useI18n","options","router","injectedLocales","injectedDefaultLocale","forceUpdate","useState","useEffect","n","resolveLocalePath","to","localeCode","switchLocaleHelper","newLocale","currentPath","newPath","locale","l","res","I18nGroup","props","prefix","groupClass","restProps","t","getRoute","translate","key","params","result","className","childrenContent","I18nLink","activeStyle","localeRouteProp","localeRoute","isExternalLink","externalHref","targetPath","computedStyle","linkPath","normalizedCurrent","normalizedLink","toValue","handleClick","e","LinkComponent","Component","componentProps","I18nSwitcher","localesProp","currentLocaleProp","getLocaleNameProp","switchLocaleProp","_localeRouteProp","customLabels","customWrapperStyle","customButtonStyle","customDropdownStyle","customItemStyle","customLinkStyle","customActiveLinkStyle","customIconStyle","i18nInstance","dropdownOpen","setDropdownOpen","wrapperRef","useRef","currentLocale","currentLocaleName","toggleDropdown","event","localeLabel","localeItem","currentLocaleLabel","current","handleSwitchLocale","code","wrapperStyle","buttonStyle","dropdownStyle","itemStyle","linkStyle","activeLinkStyle","iconStyle","openIconStyle","handler","target","isClickInside","isButtonClick","mergedWrapperStyle","mergedButtonStyle","mergedDropdownStyle","mergedItemStyle","mergedIconStyle","dropdownItems","isActive","mergedLinkStyle","I18nT","tc","tn","td","tdr","keypath","tag","plural","defaultValue","html","hideIfEmpty","customPluralRule","number","date","relativeDate","route","createElement","elementTag","elementProps","numberValue","formattedNumber","translation","content","formattedDate","formattedRelativeDate","count","k","p","dv","tResult","Fragment","PreactI18n","BaseI18n","storage","lang","msgs","listener","val","routeName","translations","merge","createI18n","createBrowserHistoryAdapter","localeCodes","loc","resolvePath","pathSegments","first","cleanPath","createPreactRouterAdapter"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@i18n-micro/preact",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"access": "public"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@i18n-micro/core": "1.
|
|
23
|
-
"@i18n-micro/types": "1.
|
|
22
|
+
"@i18n-micro/core": "1.1.2",
|
|
23
|
+
"@i18n-micro/types": "1.1.1"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"preact": "^10.0.0"
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"jest-environment-jsdom": "^29.7.0",
|
|
37
37
|
"preact": "^10.0.0",
|
|
38
38
|
"ts-jest": "^29.4.6",
|
|
39
|
-
"vite": "^7.
|
|
39
|
+
"vite": "^7.3.1",
|
|
40
40
|
"vite-plugin-dts": "^4.5.4"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|