@i18n-micro/preact 1.2.11 → 1.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@i18n-micro/core"),t=require("preact"),n=require("preact/hooks");var r=(0,t.createContext)(null),i=(0,t.createContext)(null),a=(0,t.createContext)(null),o=(0,t.createContext)(null),s=()=>{let e=(0,n.useContext)(r);if(!e)throw Error(`[i18n-micro] I18nContext not found. Make sure I18nProvider is used.`);return e},c=()=>(0,n.useContext)(i),l=()=>(0,n.useContext)(a),u=()=>(0,n.useContext)(o);function d({i18n:e,locales:n,defaultLocale:s,routingStrategy:c,children:l}){return(0,t.h)(r.Provider,{value:e},n?(0,t.h)(i.Provider,{value:n},s?(0,t.h)(a.Provider,{value:s},c?(0,t.h)(o.Provider,{value:c},l):l):l):l)}var f=e=>{let t=s(),r=u(),i=c(),a=l(),[,o]=(0,n.useState)(0);(0,n.useEffect)(()=>t.subscribe(()=>{o(e=>e+1)}),[t]);let d=e?.locales||i||[],f=e?.defaultLocale||a||t.locale,p=(e,n)=>r?.resolvePath?r.resolvePath(e,n||t.locale):e;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:e=>{t.locale=e},setRoute:t.setRoute.bind(t),getRoute:t.getRoute.bind(t),getLocales:()=>d,defaultLocale:()=>f,getLocaleName:()=>d.find(e=>e.code===t.locale)?.displayName||null,switchLocale:e=>{if(t.locale=e,r){let t=r.getCurrentPath(),n=p(t,e);r.push(typeof n==`string`?{path:n}:{path:n.path||`/`})}},localeRoute:p,localePath:(e,t)=>{let n=p(e,t);return typeof n==`string`?n:n.path||`/`},addTranslations:t.addTranslations.bind(t),addRouteTranslations:t.addRouteTranslations.bind(t),clearCache:t.clearCache.bind(t)}},p=e=>{let{prefix:n,groupClass:r,children:i,...a}=e,{t:o,getRoute:s}=f(),c=(e,t)=>{let r=o(`${n}.${e}`,t,void 0,s());return typeof r==`string`?r:String(r)},l=[`i18n-group`,r].filter(Boolean).join(` `),u=typeof i==`function`?i({prefix:n,t:c}):i;return(0,t.h)(`div`,{...a,className:l},u)},m=e=>{let n=f(),r=u(),{to:i,activeStyle:a,localeRoute:o,children:s,...c}=e,l=o||n.localeRoute,d=()=>typeof i==`string`&&/^(?:https?:\/\/|\/\/|[a-zA-Z0-9-]+\.[a-zA-Z]{2,})|tel:|mailto:/.test(i),p=()=>{if(d()&&typeof i==`string`)return/^https?:\/\//.test(i)?i:`https://${i}`},m=()=>{if(d())return typeof i==`string`?i:i?.path||`/`;if(l){let e=l(i);return typeof e==`string`?e:e.path||`/`}if(!r?.resolvePath)return typeof i==`string`?i:i.path||`/`;let e=r.resolvePath(i,n.locale);return typeof e==`string`?e:e.path||`/`},h=(()=>{if(d()||!r)return!1;let e=r.getCurrentPath(),t=m(),n=e.replace(/\/$/,``),i=t.replace(/\/$/,``);return!!(n===i||n.startsWith(`${i}/`))})()&&a||{},g=m(),_=t=>{e.onClick&&e.onClick(t),!t.defaultPrevented&&!t.button&&!t.metaKey&&!t.ctrlKey&&r&&!d()&&(t.preventDefault(),r.push({path:g}))};if(d())return(0,t.h)(`a`,{...c,href:p(),style:h,target:`_blank`,rel:`noopener noreferrer`},s);if(r?.linkComponent){let e=r.linkComponent;if(typeof e==`string`)return(0,t.h)(e,{...c,href:g,style:h},s);let n=e,i={...c,href:g,style:h};return(0,t.h)(n,i,s)}return(0,t.h)(`a`,{...c,href:g,style:h,onClick:_},s)};function h(e,t){return typeof e==`function`?e():typeof e==`string`?e:t}var g=e=>{let{locales:r,currentLocale:i,getLocaleName:a,switchLocale:o,localeRoute:l,customLabels:d={},customWrapperStyle:p,customButtonStyle:m,customDropdownStyle:g,customItemStyle:_,customLinkStyle:v,customActiveLinkStyle:y,customDisabledLinkStyle:b={},customIconStyle:x,...S}=e,C=f(),w=s(),T=u(),E=c(),[D,O]=(0,n.useState)(!1),k=(0,n.useRef)(null),A=r||E||C.getLocales()||[],j=A.filter(e=>!e.disabled),M=h(i,C.locale),N=A.some(e=>e.code===M&&e.disabled),P=a?a():C.getLocaleName(),F=e=>{e&&(e.stopPropagation(),e.preventDefault()),O(!D)},I=e=>d[e.code]||e.displayName||e.code,L=()=>{let e=j.find(e=>e.code===M);return e?I(e):P||M},R=t=>{if(O(!1),o){o(t);return}if(w.locale=t,!T)return;let n=T.getCurrentPath(),r=e.localeRoute?(()=>{let r=e.localeRoute(n,t);return typeof r==`string`?r:r.path||`/`})():T?.resolvePath?(()=>{let e=T.resolvePath(n,t);return typeof e==`string`?e:e.path||`/`})():n;T.push({path:r})},z={position:`relative`,display:`inline-block`,verticalAlign:`middle`},B={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`},V={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)`},H={margin:`0`,padding:`0`},U={display:`block`,padding:`8px 12px`,color:`#333`,textDecoration:`none`,transition:`background-color 0.3s ease`,cursor:`pointer`},W={fontWeight:`bold`,color:`#007bff`,cursor:`not-allowed`},G={marginLeft:`8px`,display:`inline-block`,transition:`transform 0.3s ease`},K={transform:`rotate(180deg)`};(0,n.useEffect)(()=>{if(!D)return;let e=e=>{if(!D)return;let t=e.target;if(!t||!k.current)return;let n=k.current.contains(t),r=t.closest(`.i18n-switcher-button`)!==null;!n&&!r&&O(!1)};return document.addEventListener(`click`,e),()=>{document.removeEventListener(`click`,e)}},[D]);let q={...z,...p},J={...B,...m,...N?b:{}},Y={...V,...g},X={...H,..._},Z={...G,...D?K:{},...x},Q=j.map(e=>{let n=e.code===M,r={...U,...n?W:{},...v,...n?y:{},width:`100%`,textAlign:`left`,border:`none`,background:`transparent`};return(0,t.h)(`li`,{key:e.code,style:X},(0,t.h)(`button`,{type:`button`,className:`switcher-locale-${e.code}`,style:r,onClick:t=>{t.preventDefault(),t.stopPropagation(),R(e.code)}},I(e)))});return(0,t.h)(`div`,{ref:k,className:`i18n-switcher-wrapper`,style:q,...S},(0,t.h)(`button`,{type:`button`,className:`i18n-switcher-button`,style:J,onClick:e=>{e.preventDefault(),e.stopPropagation(),F(e)},"aria-haspopup":`true`,"aria-expanded":D},(0,t.h)(`span`,null,L()),(0,t.h)(`span`,{style:Z},`▼`)),D?(0,t.h)(`ul`,{className:`i18n-switcher-dropdown`,style:Y},...Q):null)},_=e=>{let{t:n,tc:r,tn:i,td:a,tdr:o,locale:s,getRoute:c}=f(),{keypath:l,params:u,tag:d=`span`,plural:p,defaultValue:m,html:h=!1,hideIfEmpty:g=!1,customPluralRule:_,number:v,date:y,relativeDate:b,...x}=e,S=c(),C=(e,n,r)=>(0,t.h)(e,n,r);if(v!==void 0){let e=n(l,{number:i(Number(v)),...u||{}},void 0,S),t=typeof e==`string`?e:String(e);return h?C(d,{...x,dangerouslySetInnerHTML:{__html:t}},void 0):C(d,x,t)}if(y!==void 0){let e=n(l,{date:a(y),...u||{}},void 0,S),t=typeof e==`string`?e:String(e);return h?C(d,{...x,dangerouslySetInnerHTML:{__html:t}},void 0):C(d,x,t)}if(b!==void 0){let e=n(l,{relativeDate:o(b),...u||{}},void 0,S),t=typeof e==`string`?e:String(e);return h?C(d,{...x,dangerouslySetInnerHTML:{__html:t}},void 0):C(d,x,t)}if(p!==void 0){let e=Number.parseInt(p.toString(),10),t;return t=_?_(l,e,u||{},s,(e,t,r)=>{let i=n(e,t,r,S);return typeof i==`string`?i:String(i)})||``:r(l,{count:e,...u||{}},m),h?C(d,{...x,dangerouslySetInnerHTML:{__html:t}},void 0):C(d,x,t)}let w=n(l,u,m,S),T=typeof w==`string`?w:String(w);return g&&!T.trim()?m?(0,t.h)(t.Fragment,null,m):null:h?C(d,{...x,dangerouslySetInnerHTML:{__html:T}},void 0):C(d,x,T)},v=class extends e.BaseI18n{store;storage;constructor(t){let n={translations:new Map};if(super({storage:n,plural:t.plural,missingWarn:t.missingWarn,missingHandler:t.missingHandler}),this.storage=n,this.store=(0,e.createReactiveI18nStore)({locale:t.locale,fallbackLocale:t.fallbackLocale||t.locale}),t.messages)for(let[e,n]of Object.entries(t.messages))this.helper.loadTranslations(e,n)}subscribe=e=>this.store.subscribe(e);getSnapshot=()=>this.store.getSnapshot();get locale(){return this.store.getLocale()}set locale(e){this.store.setLocale(e)}get fallbackLocale(){return this.store.getFallbackLocale()}set fallbackLocale(e){this.store.setFallbackLocale(e)}get currentRoute(){return this.store.getRoute()}setRoute(e){this.store.setRoute(e)}getLocale(){return this.store.getLocale()}getFallbackLocale(){return this.store.getFallbackLocale()}getRoute(){return this.store.getRoute()}addTranslations(e,t,n=!0){super.loadTranslationsCore(e,t,n),this.store.notify()}addRouteTranslations(e,t,n,r=!0){super.loadRouteTranslationsCore(e,t,n,r),this.store.notify()}clearCache(){super.clearCache(),this.store.notify()}onTranslationsChanged(){this.store.notify()}};function y(e){return new v(e)}function b(e,t){let n=e.map(e=>e.code),r=(e,r)=>{let i=(typeof e==`string`?e:e.path||`/`).split(`/`).filter(Boolean),a=i[0];a!==void 0&&n.includes(a)&&i.shift();let o=`/${i.join(`/`)}`;return r===t?o:`/${r}${o===`/`?``:o}`};return{linkComponent:void 0,getCurrentPath:()=>typeof window<`u`?window.location.pathname:`/`,push:e=>{typeof window<`u`&&(window.history.pushState({},``,e.path),window.dispatchEvent(new Event(`popstate`)))},replace:e=>{typeof window<`u`&&(window.history.replaceState({},``,e.path),window.dispatchEvent(new Event(`popstate`)))},resolvePath:(e,t)=>r(e,t),getRoute:()=>typeof window<`u`?{fullPath:window.location.pathname+window.location.search,query:Object.fromEntries(new URLSearchParams(window.location.search))}:{fullPath:`/`,query:{}}}}var x=b;Object.defineProperty(exports,"FormatService",{enumerable:!0,get:function(){return e.FormatService}}),exports.I18nContext=r,exports.I18nDefaultLocaleContext=a,exports.I18nGroup=p,exports.I18nLink=m,exports.I18nLocalesContext=i,exports.I18nProvider=d,exports.I18nRouterContext=o,exports.I18nSwitcher=g,exports.I18nT=_,exports.PreactI18n=v,exports.createBrowserHistoryAdapter=b,exports.createI18n=y,exports.createPreactRouterAdapter=x,Object.defineProperty(exports,"defaultPlural",{enumerable:!0,get:function(){return e.defaultPlural}}),Object.defineProperty(exports,"interpolate",{enumerable:!0,get:function(){return e.interpolate}}),exports.useI18n=f,exports.useI18nContext=s,exports.useI18nDefaultLocale=l,exports.useI18nLocales=c,exports.useI18nRouter=u;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@i18n-micro/core"),t=require("preact"),n=require("preact/hooks"),r=require("@i18n-micro/runtime");var i=(0,t.createContext)(null),a=(0,t.createContext)(null),o=(0,t.createContext)(null),s=(0,t.createContext)(null),c=()=>{let e=(0,n.useContext)(i);if(!e)throw Error(`[i18n-micro] I18nContext not found. Make sure I18nProvider is used.`);return e},l=()=>(0,n.useContext)(a),u=()=>(0,n.useContext)(o),d=()=>(0,n.useContext)(s);function f({i18n:e,locales:n,defaultLocale:r,routingStrategy:c,children:l}){return(0,t.h)(i.Provider,{value:e},n?(0,t.h)(a.Provider,{value:n},r?(0,t.h)(o.Provider,{value:r},c?(0,t.h)(s.Provider,{value:c},l):l):l):l)}var p=e=>{let t=c(),r=d(),i=l(),a=u(),[,o]=(0,n.useState)(0);(0,n.useEffect)(()=>t.subscribe(()=>{o(e=>e+1)}),[t]);let s=e?.locales||i||[],f=e?.defaultLocale||a||t.locale,p=(e,n)=>r?.resolvePath?r.resolvePath(e,n||t.locale):e;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:e=>{t.locale=e},setRoute:t.setRoute.bind(t),getRoute:t.getRoute.bind(t),getLocales:()=>s,defaultLocale:()=>f,getLocaleName:()=>s.find(e=>e.code===t.locale)?.displayName||null,switchLocale:e=>{if(t.locale=e,r){let t=r.getCurrentPath(),n=p(t,e);r.push(typeof n==`string`?{path:n}:{path:n.path||`/`})}},localeRoute:p,localePath:(e,t)=>{let n=p(e,t);return typeof n==`string`?n:n.path||`/`},addTranslations:t.addTranslations.bind(t),addRouteTranslations:t.addRouteTranslations.bind(t),clearCache:t.clearCache.bind(t)}},m=e=>{let{prefix:n,groupClass:r,children:i,...a}=e,{t:o,getRoute:s}=p(),c=(e,t)=>{let r=o(`${n}.${e}`,t,void 0,s());return typeof r==`string`?r:String(r)},l=[`i18n-group`,r].filter(Boolean).join(` `),u=typeof i==`function`?i({prefix:n,t:c}):i;return(0,t.h)(`div`,{...a,className:l},u)},h=e=>{let n=p(),r=d(),{to:i,activeStyle:a,localeRoute:o,children:s,...c}=e,l=o||n.localeRoute,u=()=>typeof i==`string`&&/^(?:https?:\/\/|\/\/|[a-zA-Z0-9-]+\.[a-zA-Z]{2,})|tel:|mailto:/.test(i),f=()=>{if(u()&&typeof i==`string`)return/^https?:\/\//.test(i)?i:`https://${i}`},m=()=>{if(u())return typeof i==`string`?i:i?.path||`/`;if(l){let e=l(i);return typeof e==`string`?e:e.path||`/`}if(!r?.resolvePath)return typeof i==`string`?i:i.path||`/`;let e=r.resolvePath(i,n.locale);return typeof e==`string`?e:e.path||`/`},h=(()=>{if(u()||!r)return!1;let e=r.getCurrentPath(),t=m(),n=e.replace(/\/$/,``),i=t.replace(/\/$/,``);return!!(n===i||n.startsWith(`${i}/`))})()&&a||{},g=m(),_=t=>{e.onClick&&e.onClick(t),!t.defaultPrevented&&!t.button&&!t.metaKey&&!t.ctrlKey&&r&&!u()&&(t.preventDefault(),r.push({path:g}))};if(u())return(0,t.h)(`a`,{...c,href:f(),style:h,target:`_blank`,rel:`noopener noreferrer`},s);if(r?.linkComponent){let e=r.linkComponent;if(typeof e==`string`)return(0,t.h)(e,{...c,href:g,style:h},s);let n=e,i={...c,href:g,style:h};return(0,t.h)(n,i,s)}return(0,t.h)(`a`,{...c,href:g,style:h,onClick:_},s)};function g(e,t){return typeof e==`function`?e():typeof e==`string`?e:t}var _=e=>{let{locales:r,currentLocale:i,getLocaleName:a,switchLocale:o,localeRoute:s,customLabels:u={},customWrapperStyle:f,customButtonStyle:m,customDropdownStyle:h,customItemStyle:_,customLinkStyle:v,customActiveLinkStyle:y,customDisabledLinkStyle:b={},customIconStyle:x,...S}=e,C=p(),w=c(),T=d(),E=l(),[D,O]=(0,n.useState)(!1),k=(0,n.useRef)(null),A=r||E||C.getLocales()||[],j=A.filter(e=>!e.disabled),M=g(i,C.locale),N=A.some(e=>e.code===M&&e.disabled),P=a?a():C.getLocaleName(),F=e=>{e&&(e.stopPropagation(),e.preventDefault()),O(!D)},I=e=>u[e.code]||e.displayName||e.code,L=()=>{let e=j.find(e=>e.code===M);return e?I(e):P||M},R=t=>{if(O(!1),o){o(t);return}if(w.locale=t,!T)return;let n=T.getCurrentPath(),r=e.localeRoute?(()=>{let r=e.localeRoute(n,t);return typeof r==`string`?r:r.path||`/`})():T?.resolvePath?(()=>{let e=T.resolvePath(n,t);return typeof e==`string`?e:e.path||`/`})():n;T.push({path:r})},z={position:`relative`,display:`inline-block`,verticalAlign:`middle`},B={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`},V={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)`},H={margin:`0`,padding:`0`},U={display:`block`,padding:`8px 12px`,color:`#333`,textDecoration:`none`,transition:`background-color 0.3s ease`,cursor:`pointer`},W={fontWeight:`bold`,color:`#007bff`,cursor:`not-allowed`},G={marginLeft:`8px`,display:`inline-block`,transition:`transform 0.3s ease`},K={transform:`rotate(180deg)`};(0,n.useEffect)(()=>{if(!D)return;let e=e=>{if(!D)return;let t=e.target;if(!t||!k.current)return;let n=k.current.contains(t),r=t.closest(`.i18n-switcher-button`)!==null;!n&&!r&&O(!1)};return document.addEventListener(`click`,e),()=>{document.removeEventListener(`click`,e)}},[D]);let q={...z,...f},J={...B,...m,...N?b:{}},Y={...V,...h},X={...H,..._},Z={...G,...D?K:{},...x},Q=j.map(e=>{let n=e.code===M,r={...U,...n?W:{},...v,...n?y:{},width:`100%`,textAlign:`left`,border:`none`,background:`transparent`};return(0,t.h)(`li`,{key:e.code,style:X},(0,t.h)(`button`,{type:`button`,className:`switcher-locale-${e.code}`,style:r,onClick:t=>{t.preventDefault(),t.stopPropagation(),R(e.code)}},I(e)))});return(0,t.h)(`div`,{ref:k,className:`i18n-switcher-wrapper`,style:q,...S},(0,t.h)(`button`,{type:`button`,className:`i18n-switcher-button`,style:J,onClick:e=>{e.preventDefault(),e.stopPropagation(),F(e)},"aria-haspopup":`true`,"aria-expanded":D},(0,t.h)(`span`,null,L()),(0,t.h)(`span`,{style:Z},`▼`)),D?(0,t.h)(`ul`,{className:`i18n-switcher-dropdown`,style:Y},...Q):null)},v=e=>{let{t:n,tc:r,tn:i,td:a,tdr:o,locale:s,getRoute:c}=p(),{keypath:l,params:u,tag:d=`span`,plural:f,defaultValue:m,html:h=!1,hideIfEmpty:g=!1,customPluralRule:_,number:v,date:y,relativeDate:b,...x}=e,S=c(),C=(e,n,r)=>(0,t.h)(e,n,r);if(v!==void 0){let e=n(l,{number:i(Number(v)),...u||{}},void 0,S),t=typeof e==`string`?e:String(e);return h?C(d,{...x,dangerouslySetInnerHTML:{__html:t}},void 0):C(d,x,t)}if(y!==void 0){let e=n(l,{date:a(y),...u||{}},void 0,S),t=typeof e==`string`?e:String(e);return h?C(d,{...x,dangerouslySetInnerHTML:{__html:t}},void 0):C(d,x,t)}if(b!==void 0){let e=n(l,{relativeDate:o(b),...u||{}},void 0,S),t=typeof e==`string`?e:String(e);return h?C(d,{...x,dangerouslySetInnerHTML:{__html:t}},void 0):C(d,x,t)}if(f!==void 0){let e=Number.parseInt(f.toString(),10),t;return t=_?_(l,e,u||{},s,(e,t,r)=>{let i=n(e,t,r,S);return typeof i==`string`?i:String(i)})||``:r(l,{count:e,...u||{}},m),h?C(d,{...x,dangerouslySetInnerHTML:{__html:t}},void 0):C(d,x,t)}let w=n(l,u,m,S),T=typeof w==`string`?w:String(w);return g&&!T.trim()?m?(0,t.h)(t.Fragment,null,m):null:h?C(d,{...x,dangerouslySetInnerHTML:{__html:T}},void 0):C(d,x,T)},y=class extends r.I18n{};function b(e){return new y(e)}function x(e,t){let n=e.map(e=>e.code),r=(e,r)=>{let i=(typeof e==`string`?e:e.path||`/`).split(`/`).filter(Boolean),a=i[0];a!==void 0&&n.includes(a)&&i.shift();let o=`/${i.join(`/`)}`;return r===t?o:`/${r}${o===`/`?``:o}`};return{linkComponent:void 0,getCurrentPath:()=>typeof window<`u`?window.location.pathname:`/`,push:e=>{typeof window<`u`&&(window.history.pushState({},``,e.path),window.dispatchEvent(new Event(`popstate`)))},replace:e=>{typeof window<`u`&&(window.history.replaceState({},``,e.path),window.dispatchEvent(new Event(`popstate`)))},resolvePath:(e,t)=>r(e,t),getRoute:()=>typeof window<`u`?{fullPath:window.location.pathname+window.location.search,query:Object.fromEntries(new URLSearchParams(window.location.search))}:{fullPath:`/`,query:{}}}}var S=x;Object.defineProperty(exports,"FormatService",{enumerable:!0,get:function(){return e.FormatService}}),exports.I18nContext=i,exports.I18nDefaultLocaleContext=o,exports.I18nGroup=m,exports.I18nLink=h,exports.I18nLocalesContext=a,exports.I18nProvider=f,exports.I18nRouterContext=s,exports.I18nSwitcher=_,exports.I18nT=v,exports.PreactI18n=y,exports.createBrowserHistoryAdapter=x,exports.createI18n=b,exports.createPreactRouterAdapter=S,Object.defineProperty(exports,"defaultPlural",{enumerable:!0,get:function(){return e.defaultPlural}}),Object.defineProperty(exports,"interpolate",{enumerable:!0,get:function(){return e.interpolate}}),exports.useI18n=p,exports.useI18nContext=c,exports.useI18nDefaultLocale=u,exports.useI18nLocales=l,exports.useI18nRouter=d;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"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\nfunction resolveCurrentLocale(prop: string | (() => string) | undefined, fallback: string): string {\n if (typeof prop === 'function') return prop()\n if (typeof prop === 'string') return prop\n return fallback\n}\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 /**\n * Inline style applied to the main switcher button when the current locale is\n * marked as `disabled: true` in locale config.\n *\n * Disabled locales are omitted from dropdown items.\n */\n customDisabledLinkStyle?: 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 customDisabledLinkStyle = {},\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 // Exclude `disabled: true` locales from the UI switcher (keep them available via getLocales for SEO).\n const allLocales = localesProp || injectedLocales || i18n.getLocales() || []\n const locales = allLocales.filter((locale) => !locale.disabled)\n\n // Get current locale value (handle both string and function)\n const currentLocale = resolveCurrentLocale(currentLocaleProp, i18n.locale)\n const currentLocaleDisabled = allLocales.some((l) => l.code === currentLocale && l.disabled)\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 cursor: 'not-allowed',\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 = {\n ...buttonStyle,\n ...customButtonStyle,\n ...(currentLocaleDisabled ? customDisabledLinkStyle : {}),\n }\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 'aria-haspopup': 'true',\n 'aria-expanded': 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, createReactiveI18nStore, type ReactiveI18nStore, 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 readonly store: ReactiveI18nStore\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.store = createReactiveI18nStore({\n locale: options.locale,\n 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 subscribe = (listener: () => void) => this.store.subscribe(listener)\n\n getSnapshot = () => this.store.getSnapshot()\n\n get locale(): string {\n return this.store.getLocale()\n }\n\n set locale(val: string) {\n this.store.setLocale(val)\n }\n\n get fallbackLocale(): string {\n return this.store.getFallbackLocale()\n }\n\n set fallbackLocale(val: string) {\n this.store.setFallbackLocale(val)\n }\n\n get currentRoute(): string {\n return this.store.getRoute()\n }\n\n setRoute(routeName: string): void {\n this.store.setRoute(routeName)\n }\n\n public getLocale(): string {\n return this.store.getLocale()\n }\n\n public getFallbackLocale(): string {\n return this.store.getFallbackLocale()\n }\n\n public getRoute(): string {\n return this.store.getRoute()\n }\n\n public addTranslations(locale: string, translations: Translations, merge = true): void {\n super.loadTranslationsCore(locale, translations, merge)\n this.store.notify()\n }\n\n public addRouteTranslations(locale: string, routeName: string, translations: Translations, merge = true): void {\n super.loadRouteTranslationsCore(locale, routeName, translations, merge)\n this.store.notify()\n }\n\n public override clearCache(): void {\n super.clearCache()\n this.store.notify()\n }\n\n protected override onTranslationsChanged(): void {\n this.store.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"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"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\nfunction resolveCurrentLocale(prop: string | (() => string) | undefined, fallback: string): string {\n if (typeof prop === 'function') return prop()\n if (typeof prop === 'string') return prop\n return fallback\n}\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 /**\n * Inline style applied to the main switcher button when the current locale is\n * marked as `disabled: true` in locale config.\n *\n * Disabled locales are omitted from dropdown items.\n */\n customDisabledLinkStyle?: 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 customDisabledLinkStyle = {},\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 // Exclude `disabled: true` locales from the UI switcher (keep them available via getLocales for SEO).\n const allLocales = localesProp || injectedLocales || i18n.getLocales() || []\n const locales = allLocales.filter((locale) => !locale.disabled)\n\n // Get current locale value (handle both string and function)\n const currentLocale = resolveCurrentLocale(currentLocaleProp, i18n.locale)\n const currentLocaleDisabled = allLocales.some((l) => l.code === currentLocale && l.disabled)\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 cursor: 'not-allowed',\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 = {\n ...buttonStyle,\n ...customButtonStyle,\n ...(currentLocaleDisabled ? customDisabledLinkStyle : {}),\n }\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 'aria-haspopup': 'true',\n 'aria-expanded': 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 { I18n as RuntimeI18n, type I18nOptions as RuntimeI18nOptions } from '@i18n-micro/runtime'\n\nexport interface PreactI18nOptions extends RuntimeI18nOptions {}\n\n/**\n * Preact-facing i18n instance. Same surface as `@i18n-micro/runtime`, kept as a\n * named subclass so `instanceof PreactI18n` and context typing stay stable.\n */\nexport class PreactI18n extends RuntimeI18n {}\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"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Attributes } from 'preact';
2
- import { BaseI18n } from '@i18n-micro/core';
3
2
  import { CleanTranslation } from '@i18n-micro/types';
4
3
  import { ComponentChildren } from 'preact';
5
4
  import { Context } from 'preact';
@@ -7,6 +6,8 @@ import { default as default_2 } from 'react';
7
6
  import { defaultPlural } from '@i18n-micro/core';
8
7
  import { FormatService } from '@i18n-micro/core';
9
8
  import { Getter } from '@i18n-micro/types';
9
+ import { I18n } from '@i18n-micro/runtime';
10
+ import { I18nOptions } from '@i18n-micro/runtime';
10
11
  import { interpolate } from '@i18n-micro/core';
11
12
  import { JSX as JSX_2 } from 'preact';
12
13
  import { Locale } from '@i18n-micro/types';
@@ -16,7 +17,6 @@ import { Params } from '@i18n-micro/types';
16
17
  import { PluralFunc } from '@i18n-micro/types';
17
18
  import { TranslationKey } from '@i18n-micro/types';
18
19
  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 }
@@ -191,34 +191,14 @@ export { Params }
191
191
 
192
192
  export { PluralFunc }
193
193
 
194
- export declare class PreactI18n extends BaseI18n {
195
- private readonly store;
196
- readonly storage: TranslationStorage;
197
- constructor(options: PreactI18nOptions);
198
- subscribe: (listener: () => void) => () => void;
199
- getSnapshot: () => string;
200
- get locale(): string;
201
- set locale(val: string);
202
- get fallbackLocale(): string;
203
- set fallbackLocale(val: string);
204
- get currentRoute(): string;
205
- setRoute(routeName: string): void;
206
- getLocale(): string;
207
- getFallbackLocale(): string;
208
- getRoute(): string;
209
- addTranslations(locale: string, translations: Translations, merge?: boolean): void;
210
- addRouteTranslations(locale: string, routeName: string, translations: Translations, merge?: boolean): void;
211
- clearCache(): void;
212
- protected onTranslationsChanged(): void;
194
+ /**
195
+ * Preact-facing i18n instance. Same surface as `@i18n-micro/runtime`, kept as a
196
+ * named subclass so `instanceof PreactI18n` and context typing stay stable.
197
+ */
198
+ export declare class PreactI18n extends I18n {
213
199
  }
214
200
 
215
- export declare interface PreactI18nOptions {
216
- locale: string;
217
- fallbackLocale?: string;
218
- messages?: Record<string, Translations>;
219
- plural?: PluralFunc;
220
- missingWarn?: boolean;
221
- missingHandler?: (locale: string, key: string, routeName: string) => void;
201
+ export declare interface PreactI18nOptions extends I18nOptions {
222
202
  }
223
203
 
224
204
  export { TranslationKey }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Attributes } from 'preact';
2
- import { BaseI18n } from '@i18n-micro/core';
3
2
  import { CleanTranslation } from '@i18n-micro/types';
4
3
  import { ComponentChildren } from 'preact';
5
4
  import { Context } from 'preact';
@@ -7,6 +6,8 @@ import { default as default_2 } from 'react';
7
6
  import { defaultPlural } from '@i18n-micro/core';
8
7
  import { FormatService } from '@i18n-micro/core';
9
8
  import { Getter } from '@i18n-micro/types';
9
+ import { I18n } from '@i18n-micro/runtime';
10
+ import { I18nOptions } from '@i18n-micro/runtime';
10
11
  import { interpolate } from '@i18n-micro/core';
11
12
  import { JSX as JSX_2 } from 'preact';
12
13
  import { Locale } from '@i18n-micro/types';
@@ -16,7 +17,6 @@ import { Params } from '@i18n-micro/types';
16
17
  import { PluralFunc } from '@i18n-micro/types';
17
18
  import { TranslationKey } from '@i18n-micro/types';
18
19
  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 }
@@ -191,34 +191,14 @@ export { Params }
191
191
 
192
192
  export { PluralFunc }
193
193
 
194
- export declare class PreactI18n extends BaseI18n {
195
- private readonly store;
196
- readonly storage: TranslationStorage;
197
- constructor(options: PreactI18nOptions);
198
- subscribe: (listener: () => void) => () => void;
199
- getSnapshot: () => string;
200
- get locale(): string;
201
- set locale(val: string);
202
- get fallbackLocale(): string;
203
- set fallbackLocale(val: string);
204
- get currentRoute(): string;
205
- setRoute(routeName: string): void;
206
- getLocale(): string;
207
- getFallbackLocale(): string;
208
- getRoute(): string;
209
- addTranslations(locale: string, translations: Translations, merge?: boolean): void;
210
- addRouteTranslations(locale: string, routeName: string, translations: Translations, merge?: boolean): void;
211
- clearCache(): void;
212
- protected onTranslationsChanged(): void;
194
+ /**
195
+ * Preact-facing i18n instance. Same surface as `@i18n-micro/runtime`, kept as a
196
+ * named subclass so `instanceof PreactI18n` and context typing stay stable.
197
+ */
198
+ export declare class PreactI18n extends I18n {
213
199
  }
214
200
 
215
- export declare interface PreactI18nOptions {
216
- locale: string;
217
- fallbackLocale?: string;
218
- messages?: Record<string, Translations>;
219
- plural?: PluralFunc;
220
- missingWarn?: boolean;
221
- missingHandler?: (locale: string, key: string, routeName: string) => void;
201
+ export declare interface PreactI18nOptions extends I18nOptions {
222
202
  }
223
203
 
224
204
  export { TranslationKey }
package/dist/index.mjs CHANGED
@@ -1,23 +1,24 @@
1
- import { BaseI18n as e, FormatService as t, createReactiveI18nStore as n, defaultPlural as r, interpolate as i } from "@i18n-micro/core";
2
- import { Fragment as a, createContext as o, h as s } from "preact";
3
- import { useContext as c, useEffect as l, useRef as u, useState as d } from "preact/hooks";
1
+ import { FormatService as e, defaultPlural as t, interpolate as n } from "@i18n-micro/core";
2
+ import { Fragment as r, createContext as i, h as a } from "preact";
3
+ import { useContext as o, useEffect as s, useRef as c, useState as l } from "preact/hooks";
4
+ import { I18n as u } from "@i18n-micro/runtime";
4
5
  //#region src/injection.ts
5
- var f = o(null), p = o(null), m = o(null), h = o(null), g = () => {
6
- let e = c(f);
6
+ var d = i(null), f = i(null), p = i(null), m = i(null), h = () => {
7
+ let e = o(d);
7
8
  if (!e) throw Error("[i18n-micro] I18nContext not found. Make sure I18nProvider is used.");
8
9
  return e;
9
- }, _ = () => c(p), v = () => c(m), y = () => c(h);
10
+ }, g = () => o(f), _ = () => o(p), v = () => o(m);
10
11
  //#endregion
11
12
  //#region src/context.tsx
12
- function b({ i18n: e, locales: t, defaultLocale: n, routingStrategy: r, children: i }) {
13
- return s(f.Provider, { value: e }, t ? s(p.Provider, { value: t }, n ? s(m.Provider, { value: n }, r ? s(h.Provider, { value: r }, i) : i) : i) : i);
13
+ function y({ i18n: e, locales: t, defaultLocale: n, routingStrategy: r, children: i }) {
14
+ return a(d.Provider, { value: e }, t ? a(f.Provider, { value: t }, n ? a(p.Provider, { value: n }, r ? a(m.Provider, { value: r }, i) : i) : i) : i);
14
15
  }
15
- var x = (e) => {
16
- let t = g(), n = y(), r = _(), i = v(), [, a] = d(0);
17
- l(() => t.subscribe(() => {
16
+ var b = (e) => {
17
+ let t = h(), n = v(), r = g(), i = _(), [, a] = l(0);
18
+ s(() => t.subscribe(() => {
18
19
  a((e) => e + 1);
19
20
  }), [t]);
20
- let o = e?.locales || r || [], s = e?.defaultLocale || i || t.locale, c = (e, r) => n?.resolvePath ? n.resolvePath(e, r || t.locale) : e;
21
+ let o = e?.locales || r || [], c = e?.defaultLocale || i || t.locale, u = (e, r) => n?.resolvePath ? n.resolvePath(e, r || t.locale) : e;
21
22
  return {
22
23
  t: t.t.bind(t),
23
24
  ts: t.ts.bind(t),
@@ -41,37 +42,37 @@ var x = (e) => {
41
42
  setRoute: t.setRoute.bind(t),
42
43
  getRoute: t.getRoute.bind(t),
43
44
  getLocales: () => o,
44
- defaultLocale: () => s,
45
+ defaultLocale: () => c,
45
46
  getLocaleName: () => o.find((e) => e.code === t.locale)?.displayName || null,
46
47
  switchLocale: (e) => {
47
48
  if (t.locale = e, n) {
48
- let t = n.getCurrentPath(), r = c(t, e);
49
+ let t = n.getCurrentPath(), r = u(t, e);
49
50
  n.push(typeof r == "string" ? { path: r } : { path: r.path || "/" });
50
51
  }
51
52
  },
52
- localeRoute: c,
53
+ localeRoute: u,
53
54
  localePath: (e, t) => {
54
- let n = c(e, t);
55
+ let n = u(e, t);
55
56
  return typeof n == "string" ? n : n.path || "/";
56
57
  },
57
58
  addTranslations: t.addTranslations.bind(t),
58
59
  addRouteTranslations: t.addRouteTranslations.bind(t),
59
60
  clearCache: t.clearCache.bind(t)
60
61
  };
61
- }, S = (e) => {
62
- let { prefix: t, groupClass: n, children: r, ...i } = e, { t: a, getRoute: o } = x(), c = (e, n) => {
63
- let r = a(`${t}.${e}`, n, void 0, o());
62
+ }, x = (e) => {
63
+ let { prefix: t, groupClass: n, children: r, ...i } = e, { t: o, getRoute: s } = b(), c = (e, n) => {
64
+ let r = o(`${t}.${e}`, n, void 0, s());
64
65
  return typeof r == "string" ? r : String(r);
65
66
  }, l = ["i18n-group", n].filter(Boolean).join(" "), u = typeof r == "function" ? r({
66
67
  prefix: t,
67
68
  t: c
68
69
  }) : r;
69
- return s("div", {
70
+ return a("div", {
70
71
  ...i,
71
72
  className: l
72
73
  }, u);
73
- }, C = (e) => {
74
- let t = x(), n = y(), { to: r, activeStyle: i, localeRoute: a, children: o, ...c } = e, l = a || t.localeRoute, u = () => typeof r == "string" && /^(?:https?:\/\/|\/\/|[a-zA-Z0-9-]+\.[a-zA-Z]{2,})|tel:|mailto:/.test(r), d = () => {
74
+ }, S = (e) => {
75
+ let t = b(), n = v(), { to: r, activeStyle: i, localeRoute: o, children: s, ...c } = e, l = o || t.localeRoute, u = () => typeof r == "string" && /^(?:https?:\/\/|\/\/|[a-zA-Z0-9-]+\.[a-zA-Z]{2,})|tel:|mailto:/.test(r), d = () => {
75
76
  if (u() && typeof r == "string") return /^https?:\/\//.test(r) ? r : `https://${r}`;
76
77
  }, f = () => {
77
78
  if (u()) return typeof r == "string" ? r : r?.path || "/";
@@ -89,43 +90,43 @@ var x = (e) => {
89
90
  })() && i || {}, m = f(), h = (t) => {
90
91
  e.onClick && e.onClick(t), !t.defaultPrevented && !t.button && !t.metaKey && !t.ctrlKey && n && !u() && (t.preventDefault(), n.push({ path: m }));
91
92
  };
92
- if (u()) return s("a", {
93
+ if (u()) return a("a", {
93
94
  ...c,
94
95
  href: d(),
95
96
  style: p,
96
97
  target: "_blank",
97
98
  rel: "noopener noreferrer"
98
- }, o);
99
+ }, s);
99
100
  if (n?.linkComponent) {
100
101
  let e = n.linkComponent;
101
- if (typeof e == "string") return s(e, {
102
+ if (typeof e == "string") return a(e, {
102
103
  ...c,
103
104
  href: m,
104
105
  style: p
105
- }, o);
106
+ }, s);
106
107
  let t = e, r = {
107
108
  ...c,
108
109
  href: m,
109
110
  style: p
110
111
  };
111
- return s(t, r, o);
112
+ return a(t, r, s);
112
113
  }
113
- return s("a", {
114
+ return a("a", {
114
115
  ...c,
115
116
  href: m,
116
117
  style: p,
117
118
  onClick: h
118
- }, o);
119
+ }, s);
119
120
  };
120
121
  //#endregion
121
122
  //#region src/components/I18nSwitcher.tsx
122
- function w(e, t) {
123
+ function C(e, t) {
123
124
  return typeof e == "function" ? e() : typeof e == "string" ? e : t;
124
125
  }
125
- var T = (e) => {
126
- let { locales: t, currentLocale: n, getLocaleName: r, switchLocale: i, localeRoute: a, customLabels: o = {}, customWrapperStyle: c, customButtonStyle: f, customDropdownStyle: p, customItemStyle: m, customLinkStyle: h, customActiveLinkStyle: v, customDisabledLinkStyle: b = {}, customIconStyle: S, ...C } = e, T = x(), E = g(), D = y(), O = _(), [k, A] = d(!1), j = u(null), M = t || O || T.getLocales() || [], N = M.filter((e) => !e.disabled), P = w(n, T.locale), F = M.some((e) => e.code === P && e.disabled), I = r ? r() : T.getLocaleName(), L = (e) => {
126
+ var w = (e) => {
127
+ let { locales: t, currentLocale: n, getLocaleName: r, switchLocale: i, localeRoute: o, customLabels: u = {}, customWrapperStyle: d, customButtonStyle: f, customDropdownStyle: p, customItemStyle: m, customLinkStyle: _, customActiveLinkStyle: y, customDisabledLinkStyle: x = {}, customIconStyle: S, ...w } = e, T = b(), E = h(), D = v(), O = g(), [k, A] = l(!1), j = c(null), M = t || O || T.getLocales() || [], N = M.filter((e) => !e.disabled), P = C(n, T.locale), F = M.some((e) => e.code === P && e.disabled), I = r ? r() : T.getLocaleName(), L = (e) => {
127
128
  e && (e.stopPropagation(), e.preventDefault()), A(!k);
128
- }, R = (e) => o[e.code] || e.displayName || e.code, z = () => {
129
+ }, R = (e) => u[e.code] || e.displayName || e.code, z = () => {
129
130
  let e = N.find((e) => e.code === P);
130
131
  return e ? R(e) : I || P;
131
132
  }, B = (t) => {
@@ -187,7 +188,7 @@ var T = (e) => {
187
188
  display: "inline-block",
188
189
  transition: "transform 0.3s ease"
189
190
  }, J = { transform: "rotate(180deg)" };
190
- l(() => {
191
+ s(() => {
191
192
  if (!k) return;
192
193
  let e = (e) => {
193
194
  if (!k) return;
@@ -202,11 +203,11 @@ var T = (e) => {
202
203
  }, [k]);
203
204
  let Y = {
204
205
  ...V,
205
- ...c
206
+ ...d
206
207
  }, X = {
207
208
  ...H,
208
209
  ...f,
209
- ...F ? b : {}
210
+ ...F ? x : {}
210
211
  }, Z = {
211
212
  ...U,
212
213
  ...p
@@ -221,17 +222,17 @@ var T = (e) => {
221
222
  let t = e.code === P, n = {
222
223
  ...G,
223
224
  ...t ? K : {},
224
- ...h,
225
- ...t ? v : {},
225
+ ..._,
226
+ ...t ? y : {},
226
227
  width: "100%",
227
228
  textAlign: "left",
228
229
  border: "none",
229
230
  background: "transparent"
230
231
  };
231
- return s("li", {
232
+ return a("li", {
232
233
  key: e.code,
233
234
  style: Q
234
- }, s("button", {
235
+ }, a("button", {
235
236
  type: "button",
236
237
  className: `switcher-locale-${e.code}`,
237
238
  style: n,
@@ -240,12 +241,12 @@ var T = (e) => {
240
241
  }
241
242
  }, R(e)));
242
243
  });
243
- return s("div", {
244
+ return a("div", {
244
245
  ref: j,
245
246
  className: "i18n-switcher-wrapper",
246
247
  style: Y,
247
- ...C
248
- }, s("button", {
248
+ ...w
249
+ }, a("button", {
249
250
  type: "button",
250
251
  className: "i18n-switcher-button",
251
252
  style: X,
@@ -254,15 +255,15 @@ var T = (e) => {
254
255
  },
255
256
  "aria-haspopup": "true",
256
257
  "aria-expanded": k
257
- }, s("span", null, z()), s("span", { style: $ }, "▼")), k ? s("ul", {
258
+ }, a("span", null, z()), a("span", { style: $ }, "▼")), k ? a("ul", {
258
259
  className: "i18n-switcher-dropdown",
259
260
  style: Z
260
261
  }, ...ee) : null);
261
- }, E = (e) => {
262
- let { t, tc: n, tn: r, td: i, tdr: o, locale: c, getRoute: l } = x(), { keypath: u, params: d, tag: f = "span", plural: p, defaultValue: m, html: h = !1, hideIfEmpty: g = !1, customPluralRule: _, number: v, date: y, relativeDate: b, ...S } = e, C = l(), w = (e, t, n) => s(e, t, n);
262
+ }, T = (e) => {
263
+ let { t, tc: n, tn: i, td: o, tdr: s, locale: c, getRoute: l } = b(), { keypath: u, params: d, tag: f = "span", plural: p, defaultValue: m, html: h = !1, hideIfEmpty: g = !1, customPluralRule: _, number: v, date: y, relativeDate: x, ...S } = e, C = l(), w = (e, t, n) => a(e, t, n);
263
264
  if (v !== void 0) {
264
265
  let e = t(u, {
265
- number: r(Number(v)),
266
+ number: i(Number(v)),
266
267
  ...d || {}
267
268
  }, void 0, C), n = typeof e == "string" ? e : String(e);
268
269
  return h ? w(f, {
@@ -272,7 +273,7 @@ var T = (e) => {
272
273
  }
273
274
  if (y !== void 0) {
274
275
  let e = t(u, {
275
- date: i(y),
276
+ date: o(y),
276
277
  ...d || {}
277
278
  }, void 0, C), n = typeof e == "string" ? e : String(e);
278
279
  return h ? w(f, {
@@ -280,9 +281,9 @@ var T = (e) => {
280
281
  dangerouslySetInnerHTML: { __html: n }
281
282
  }, void 0) : w(f, S, n);
282
283
  }
283
- if (b !== void 0) {
284
+ if (x !== void 0) {
284
285
  let e = t(u, {
285
- relativeDate: o(b),
286
+ relativeDate: s(x),
286
287
  ...d || {}
287
288
  }, void 0, C), n = typeof e == "string" ? e : String(e);
288
289
  return h ? w(f, {
@@ -304,73 +305,17 @@ var T = (e) => {
304
305
  }, void 0) : w(f, S, r);
305
306
  }
306
307
  let T = t(u, d, m, C), E = typeof T == "string" ? T : String(T);
307
- return g && !E.trim() ? m ? s(a, null, m) : null : h ? w(f, {
308
+ return g && !E.trim() ? m ? a(r, null, m) : null : h ? w(f, {
308
309
  ...S,
309
310
  dangerouslySetInnerHTML: { __html: E }
310
311
  }, void 0) : w(f, S, E);
311
- }, D = class extends e {
312
- store;
313
- storage;
314
- constructor(e) {
315
- let t = { translations: /* @__PURE__ */ new Map() };
316
- if (super({
317
- storage: t,
318
- plural: e.plural,
319
- missingWarn: e.missingWarn,
320
- missingHandler: e.missingHandler
321
- }), this.storage = t, this.store = n({
322
- locale: e.locale,
323
- fallbackLocale: e.fallbackLocale || e.locale
324
- }), e.messages) for (let [t, n] of Object.entries(e.messages)) this.helper.loadTranslations(t, n);
325
- }
326
- subscribe = (e) => this.store.subscribe(e);
327
- getSnapshot = () => this.store.getSnapshot();
328
- get locale() {
329
- return this.store.getLocale();
330
- }
331
- set locale(e) {
332
- this.store.setLocale(e);
333
- }
334
- get fallbackLocale() {
335
- return this.store.getFallbackLocale();
336
- }
337
- set fallbackLocale(e) {
338
- this.store.setFallbackLocale(e);
339
- }
340
- get currentRoute() {
341
- return this.store.getRoute();
342
- }
343
- setRoute(e) {
344
- this.store.setRoute(e);
345
- }
346
- getLocale() {
347
- return this.store.getLocale();
348
- }
349
- getFallbackLocale() {
350
- return this.store.getFallbackLocale();
351
- }
352
- getRoute() {
353
- return this.store.getRoute();
354
- }
355
- addTranslations(e, t, n = !0) {
356
- super.loadTranslationsCore(e, t, n), this.store.notify();
357
- }
358
- addRouteTranslations(e, t, n, r = !0) {
359
- super.loadRouteTranslationsCore(e, t, n, r), this.store.notify();
360
- }
361
- clearCache() {
362
- super.clearCache(), this.store.notify();
363
- }
364
- onTranslationsChanged() {
365
- this.store.notify();
366
- }
367
- };
368
- function O(e) {
369
- return new D(e);
312
+ }, E = class extends u {};
313
+ function D(e) {
314
+ return new E(e);
370
315
  }
371
316
  //#endregion
372
317
  //#region src/router/adapter.tsx
373
- function k(e, t) {
318
+ function O(e, t) {
374
319
  let n = e.map((e) => e.code), r = (e, r) => {
375
320
  let i = (typeof e == "string" ? e : e.path || "/").split("/").filter(Boolean), a = i[0];
376
321
  a !== void 0 && n.includes(a) && i.shift();
@@ -396,8 +341,8 @@ function k(e, t) {
396
341
  }
397
342
  };
398
343
  }
399
- var A = k;
344
+ var k = O;
400
345
  //#endregion
401
- export { t as FormatService, f as I18nContext, m as I18nDefaultLocaleContext, S as I18nGroup, C as I18nLink, p as I18nLocalesContext, b as I18nProvider, h as I18nRouterContext, T as I18nSwitcher, E as I18nT, D as PreactI18n, k as createBrowserHistoryAdapter, O as createI18n, A as createPreactRouterAdapter, r as defaultPlural, i as interpolate, x as useI18n, g as useI18nContext, v as useI18nDefaultLocale, _ as useI18nLocales, y as useI18nRouter };
346
+ export { e as FormatService, d as I18nContext, p as I18nDefaultLocaleContext, x as I18nGroup, S as I18nLink, f as I18nLocalesContext, y as I18nProvider, m as I18nRouterContext, w as I18nSwitcher, T as I18nT, E as PreactI18n, O as createBrowserHistoryAdapter, D as createI18n, k as createPreactRouterAdapter, t as defaultPlural, n as interpolate, b as useI18n, h as useI18nContext, _ as useI18nDefaultLocale, g as useI18nLocales, v as useI18nRouter };
402
347
 
403
348
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"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\nfunction resolveCurrentLocale(prop: string | (() => string) | undefined, fallback: string): string {\n if (typeof prop === 'function') return prop()\n if (typeof prop === 'string') return prop\n return fallback\n}\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 /**\n * Inline style applied to the main switcher button when the current locale is\n * marked as `disabled: true` in locale config.\n *\n * Disabled locales are omitted from dropdown items.\n */\n customDisabledLinkStyle?: 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 customDisabledLinkStyle = {},\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 // Exclude `disabled: true` locales from the UI switcher (keep them available via getLocales for SEO).\n const allLocales = localesProp || injectedLocales || i18n.getLocales() || []\n const locales = allLocales.filter((locale) => !locale.disabled)\n\n // Get current locale value (handle both string and function)\n const currentLocale = resolveCurrentLocale(currentLocaleProp, i18n.locale)\n const currentLocaleDisabled = allLocales.some((l) => l.code === currentLocale && l.disabled)\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 cursor: 'not-allowed',\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 = {\n ...buttonStyle,\n ...customButtonStyle,\n ...(currentLocaleDisabled ? customDisabledLinkStyle : {}),\n }\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 'aria-haspopup': 'true',\n 'aria-expanded': 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, createReactiveI18nStore, type ReactiveI18nStore, 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 readonly store: ReactiveI18nStore\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.store = createReactiveI18nStore({\n locale: options.locale,\n 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 subscribe = (listener: () => void) => this.store.subscribe(listener)\n\n getSnapshot = () => this.store.getSnapshot()\n\n get locale(): string {\n return this.store.getLocale()\n }\n\n set locale(val: string) {\n this.store.setLocale(val)\n }\n\n get fallbackLocale(): string {\n return this.store.getFallbackLocale()\n }\n\n set fallbackLocale(val: string) {\n this.store.setFallbackLocale(val)\n }\n\n get currentRoute(): string {\n return this.store.getRoute()\n }\n\n setRoute(routeName: string): void {\n this.store.setRoute(routeName)\n }\n\n public getLocale(): string {\n return this.store.getLocale()\n }\n\n public getFallbackLocale(): string {\n return this.store.getFallbackLocale()\n }\n\n public getRoute(): string {\n return this.store.getRoute()\n }\n\n public addTranslations(locale: string, translations: Translations, merge = true): void {\n super.loadTranslationsCore(locale, translations, merge)\n this.store.notify()\n }\n\n public addRouteTranslations(locale: string, routeName: string, translations: Translations, merge = true): void {\n super.loadRouteTranslationsCore(locale, routeName, translations, merge)\n this.store.notify()\n }\n\n public override clearCache(): void {\n super.clearCache()\n this.store.notify()\n }\n\n protected override onTranslationsChanged(): void {\n this.store.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"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"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\nfunction resolveCurrentLocale(prop: string | (() => string) | undefined, fallback: string): string {\n if (typeof prop === 'function') return prop()\n if (typeof prop === 'string') return prop\n return fallback\n}\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 /**\n * Inline style applied to the main switcher button when the current locale is\n * marked as `disabled: true` in locale config.\n *\n * Disabled locales are omitted from dropdown items.\n */\n customDisabledLinkStyle?: 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 customDisabledLinkStyle = {},\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 // Exclude `disabled: true` locales from the UI switcher (keep them available via getLocales for SEO).\n const allLocales = localesProp || injectedLocales || i18n.getLocales() || []\n const locales = allLocales.filter((locale) => !locale.disabled)\n\n // Get current locale value (handle both string and function)\n const currentLocale = resolveCurrentLocale(currentLocaleProp, i18n.locale)\n const currentLocaleDisabled = allLocales.some((l) => l.code === currentLocale && l.disabled)\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 cursor: 'not-allowed',\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 = {\n ...buttonStyle,\n ...customButtonStyle,\n ...(currentLocaleDisabled ? customDisabledLinkStyle : {}),\n }\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 'aria-haspopup': 'true',\n 'aria-expanded': 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 { I18n as RuntimeI18n, type I18nOptions as RuntimeI18nOptions } from '@i18n-micro/runtime'\n\nexport interface PreactI18nOptions extends RuntimeI18nOptions {}\n\n/**\n * Preact-facing i18n instance. Same surface as `@i18n-micro/runtime`, kept as a\n * named subclass so `instanceof PreactI18n` and context typing stay stable.\n */\nexport class PreactI18n extends RuntimeI18n {}\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"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@i18n-micro/preact",
3
- "version": "1.2.11",
3
+ "version": "1.2.13",
4
4
  "description": "Preact bindings for i18n-micro — hooks, context, and UI components.",
5
5
  "keywords": [
6
6
  "i18n",
@@ -45,8 +45,9 @@
45
45
  "access": "public"
46
46
  },
47
47
  "dependencies": {
48
- "@i18n-micro/core": "^1.3.18",
49
- "@i18n-micro/types": "^1.2.15"
48
+ "@i18n-micro/core": "^1.3.19",
49
+ "@i18n-micro/runtime": "^1.0.1",
50
+ "@i18n-micro/types": "^1.2.16"
50
51
  },
51
52
  "devDependencies": {
52
53
  "@testing-library/jest-dom": "^6.9.1",