@i18n-micro/vue 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { PropType, CSSProperties } from 'vue';
1
+ import { CSSProperties, PropType } from 'vue';
2
2
  export declare const I18nLink: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
3
3
  to: {
4
4
  type: PropType<string | {
@@ -1,5 +1,5 @@
1
- import { PropType, CSSProperties, VNode } from 'vue';
2
1
  import { Locale } from '@i18n-micro/types';
2
+ import { CSSProperties, PropType, VNode } from 'vue';
3
3
  export declare const I18nSwitcher: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
4
4
  customLabels: {
5
5
  type: PropType<Record<string, string>>;
@@ -1,5 +1,5 @@
1
- import { PropType, VNode } from 'vue';
2
1
  import { PluralFunc, TranslationKey } from '@i18n-micro/types';
2
+ import { PropType, VNode } from 'vue';
3
3
  export declare const I18nT: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
4
4
  keypath: {
5
5
  type: PropType<TranslationKey>;
@@ -85,10 +85,10 @@ export declare const I18nT: import('vue').DefineComponent<import('vue').ExtractP
85
85
  type: PropType<Date | string | number>;
86
86
  };
87
87
  }>> & Readonly<{}>, {
88
+ html: boolean;
88
89
  tag: string;
89
90
  params: Record<string, string | number | boolean>;
90
91
  defaultValue: string;
91
- html: boolean;
92
92
  hideIfEmpty: boolean;
93
93
  customPluralRule: PluralFunc;
94
94
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
@@ -1,6 +1,6 @@
1
+ import { BaseI18n, TranslationStorage } from '@i18n-micro/core';
2
+ import { PluralFunc, Translations } from '@i18n-micro/types';
1
3
  import { Ref } from 'vue';
2
- import { BaseI18n, TranslationCache } from '@i18n-micro/core';
3
- import { Translations, PluralFunc } from '@i18n-micro/types';
4
4
  export interface VueI18nOptions {
5
5
  locale: string;
6
6
  fallbackLocale?: string;
@@ -13,7 +13,8 @@ export declare class VueI18n extends BaseI18n {
13
13
  private _locale;
14
14
  private _fallbackLocale;
15
15
  private _currentRoute;
16
- readonly cache: TranslationCache;
16
+ private _revision;
17
+ readonly storage: TranslationStorage;
17
18
  private listeners;
18
19
  constructor(options: VueI18nOptions);
19
20
  get locale(): Ref<string>;
@@ -33,5 +34,7 @@ export declare class VueI18n extends BaseI18n {
33
34
  subscribeToChanges(cb: () => void): () => void;
34
35
  private notifyListeners;
35
36
  getAllTranslations(): Record<string, Translations>;
36
- getCache(): TranslationCache;
37
+ getStorage(): TranslationStorage;
38
+ getGeneralCache(): Record<string, Translations>;
39
+ getRouteCache(): Record<string, Translations>;
37
40
  }
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("vue"),N=require("@i18n-micro/core"),Z=require("vue-router");class F extends N.BaseI18n{constructor(e){const r={generalLocaleCache:n.shallowRef({}),routeLocaleCache:n.shallowRef({}),dynamicTranslationsCaches:n.shallowRef([]),serverTranslationCache:n.shallowRef({})};if(super({cache:r,plural:e.plural,missingWarn:e.missingWarn,missingHandler:e.missingHandler}),this.listeners=new Set,this.cache=r,this._locale=n.ref(e.locale),this._fallbackLocale=n.ref(e.fallbackLocale||e.locale),this._currentRoute=n.ref("general"),e.messages)for(const[l,u]of Object.entries(e.messages))this.helper.loadTranslations(l,u)}get locale(){return this._locale}set locale(e){typeof e=="string"?this._locale.value=e:this._locale=e}get fallbackLocale(){return this._fallbackLocale}set fallbackLocale(e){typeof e=="string"?this._fallbackLocale.value=e:this._fallbackLocale=e}get currentRoute(){return this._currentRoute}setRoute(e){this._currentRoute.value=e}getLocale(){return this._locale.value}getFallbackLocale(){return this._fallbackLocale.value}getRoute(){return this._currentRoute.value}addTranslations(e,r,l=!0){super.loadTranslationsCore(e,r,l),n.triggerRef(this.cache.generalLocaleCache),this.notifyListeners()}addRouteTranslations(e,r,l,u=!0){super.loadRouteTranslationsCore(e,r,l,u),n.triggerRef(this.cache.routeLocaleCache),this.notifyListeners()}mergeTranslations(e,r,l){this.helper.mergeTranslation(e,r,l,!0),n.triggerRef(this.cache.routeLocaleCache),this.notifyListeners()}mergeGlobalTranslations(e,r){this.helper.mergeGlobalTranslation(e,r,!0),n.triggerRef(this.cache.generalLocaleCache),this.notifyListeners()}clearCache(){super.clearCache(),n.triggerRef(this.cache.generalLocaleCache),n.triggerRef(this.cache.routeLocaleCache),n.triggerRef(this.cache.dynamicTranslationsCaches),n.triggerRef(this.cache.serverTranslationCache),this.notifyListeners()}subscribeToChanges(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}notifyListeners(){this.listeners.forEach(e=>{e()})}getAllTranslations(){const e={},r=this.cache.generalLocaleCache.value||{},l=this.cache.routeLocaleCache.value||{};for(const[u,o]of Object.entries(r))e[u]||(e[u]={}),Object.assign(e[u],o);for(const[u,o]of Object.entries(l))if(o&&typeof o=="object"&&!Array.isArray(o))for(const[f,d]of Object.entries(o))e[f]||(e[f]={}),d&&typeof d=="object"&&!Array.isArray(d)&&Object.assign(e[f],d);return e}getCache(){return this.cache}}const C=Symbol("i18n"),_=Symbol("i18n-locales"),U=Symbol("i18n-default-locale"),O=Symbol("i18n-router-strategy"),W=n.defineComponent({name:"I18nT",props:{keypath:{type:String,required:!0},plural:{type:[Number,String]},tag:{type:String,default:"span"},params:{type:Object,default:()=>({})},defaultValue:{type:String,default:""},html:{type:Boolean,default:!1},hideIfEmpty:{type:Boolean,default:!1},customPluralRule:{type:Function,default:null},number:{type:[Number,String]},date:{type:[Date,String,Number]},relativeDate:{type:[Date,String,Number]}},setup(t,{slots:e,attrs:r}){const l=n.inject(C);if(!l)throw new Error("[i18n-micro] I18nT: i18n instance not found. Make sure i18n plugin is installed.");return()=>{const u={},o=l.getRoute();if(t.number!==void 0){const a=Number(t.number),c=l.tn(a),h=l.t(t.keypath,{number:c,...t.params},void 0,o);return n.h(t.tag,{...r,innerHTML:h})}if(t.date!==void 0){const a=l.td(t.date),c=l.t(t.keypath,{date:a,...t.params},void 0,o);return n.h(t.tag,{...r,innerHTML:c})}if(t.relativeDate!==void 0){const a=l.tdr(t.relativeDate),c=l.t(t.keypath,{relativeDate:a,...t.params},void 0,o);return n.h(t.tag,{...r,innerHTML:c})}if(t.plural!==void 0){const a=Number.parseInt(t.plural.toString());if(t.customPluralRule){const c=t.customPluralRule(t.keypath,a,t.params,l.locale.value,(h,p,k)=>l.t(h,p,k,o));return n.h(t.tag,{...r,innerHTML:c||""})}else{const c=l.tc(t.keypath,{count:a,...t.params});return n.h(t.tag,{...r,innerHTML:c})}}const f=(l.t(t.keypath,{...t.params,...u},void 0,o)??"").toString();if(t.hideIfEmpty&&!f.trim())return t.defaultValue??null;if(t.html)return n.h(t.tag,{...r,innerHTML:f});if(e.default)return n.h(t.tag,r,e.default({translation:f}));const d=[];let i=0;for(const[a,c]of Object.entries(e)){if(a==="default")continue;const h=`{${a}}`,p=f.indexOf(h,i);p!==-1&&(p>i&&d.push(f.slice(i,p)),c&&d.push(n.h(c)),i=p+h.length)}return i<f.length&&d.push(f.slice(i)),e.default?n.h(t.tag,r,e.default({children:d})):d.length>0?n.h(t.tag,r,d):n.h(t.tag,r,f)}}}),G=n.defineComponent({name:"I18nLink",props:{to:{type:[String,Object],required:!0},activeStyle:{type:Object,default:()=>({})},localeRoute:{type:Function,default:void 0}},setup(t,{slots:e}){const r=n.inject(C),l=n.inject(O,void 0);if(!r)throw new Error("[i18n-micro] I18nLink: i18n instance not found. Make sure i18n plugin is installed.");const u=n.computed(()=>typeof t.to=="string"?/^(?:https?:\/\/|\/\/|[a-zA-Z0-9-]+\.[a-zA-Z]{2,})|tel:|mailto:/.test(t.to):!1),o=n.computed(()=>{if(u.value)return t.to;if(t.localeRoute){const a=t.localeRoute(t.to);return typeof a=="string"?a:a.path||"/"}if(!l?.resolvePath)return typeof t.to=="string"?t.to:t.to.path||"/";const i=l.resolvePath(t.to,r.locale.value);return typeof i=="string"?i:i.path||"/"}),f=n.computed(()=>{if(u.value||!l)return!1;const i=l.getCurrentPath().replace(/\/$/,""),a=o.value.replace(/\/$/,"");return i===a}),d=n.computed(()=>f.value?t.activeStyle:{});return()=>u.value?n.h("a",{href:o.value,target:"_blank",rel:"noopener noreferrer",style:d.value},e.default?.()):l?.linkComponent?n.h(l.linkComponent,{to:o.value,style:d.value},{default:e.default}):n.h("a",{href:o.value,style:d.value,onClick:i=>{i.preventDefault(),l?l.push({path:o.value}):window.location.href=o.value}},e.default?.())}}),q=n.defineComponent({name:"I18nGroup",props:{prefix:{type:String,required:!0},groupClass:{type:String,default:""}},setup(t,{slots:e}){const r=n.inject(C);if(!r)throw new Error("[i18n-micro] I18nGroup: i18n instance not found. Make sure i18n plugin is installed.");const l=(u,o)=>r.t(`${t.prefix}.${u}`,o,void 0,r.getRoute());return()=>n.h("div",{class:["i18n-group",t.groupClass]},e.default?.({prefix:t.prefix,t:l}))}}),B=n.defineComponent({name:"I18nSwitcher",props:{customLabels:{type:Object,default:()=>({})},customWrapperStyle:{type:Object,default:()=>({})},customButtonStyle:{type:Object,default:()=>({})},customDropdownStyle:{type:Object,default:()=>({})},customItemStyle:{type:Object,default:()=>({})},customLinkStyle:{type:Object,default:()=>({})},customActiveLinkStyle:{type:Object,default:()=>({})},customDisabledLinkStyle:{type:Object,default:()=>({})},customIconStyle:{type:Object,default:()=>({})},locales:{type:Array,default:void 0},currentLocale:{type:[String,Function],default:void 0},getLocaleName:{type:Function,default:void 0},switchLocale:{type:Function,default:void 0},localeRoute:{type:Function,default:void 0}},setup(t,{slots:e}){const r=n.inject(C),l=n.inject(O,void 0),u=n.inject(_,void 0);if(!r)throw new Error("[i18n-micro] I18nSwitcher: i18n instance not found. Make sure i18n plugin is installed.");if(!u&&!t.locales)throw new Error("[i18n-micro] I18nSwitcher: locales not provided. Make sure app.provide(I18nLocalesKey, locales) is called or pass locales prop.");const o=n.computed(()=>t.locales||u||[]),f=n.computed(()=>t.currentLocale!==void 0?typeof t.currentLocale=="function"?t.currentLocale():t.currentLocale:r.locale.value),d=n.computed(()=>t.getLocaleName?t.getLocaleName()||null:o.value.find(y=>y.code===r.locale.value)?.displayName||null),i=n.ref(!1),a=n.ref(null),c=s=>{s&&(s.stopPropagation(),s.preventDefault()),i.value=!i.value},h=s=>t.customLabels[s.code]||s.displayName||s.code,p=n.computed(()=>{const s=o.value.find(y=>y.code===f.value);return s?h(s):d.value||f.value}),k=async s=>{if(i.value=!1,await n.nextTick(),t.switchLocale){t.switchLocale(s);return}if(r.locale.value=s,!l)return;const y=l.getCurrentPath(),v=t.localeRoute?(()=>{const g=t.localeRoute(y,s);return typeof g=="string"?g:g.path||"/"})():l?.resolvePath?(()=>{const g=l.resolvePath(y,s);return typeof g=="string"?g:g.path||"/"})():y;l.push({path:v})},S={position:"relative",display:"inline-block",verticalAlign:"middle"},P={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"},R={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)"},j={margin:"0",padding:"0"},L={display:"block",padding:"8px 12px",color:"#333",textDecoration:"none",transition:"background-color 0.3s ease",cursor:"pointer"},K={fontWeight:"bold",color:"#007bff"},D={marginLeft:"8px",display:"inline-block",transition:"transform 0.3s ease"},A={transform:"rotate(180deg)"},b=s=>s?Array.isArray(s)?s:[s]:[],H=s=>{if(!i.value)return;const y=s.target;if(!y||!a.value)return;const v=a.value.contains(y),g=y.closest(".i18n-switcher-button")!==null;!v&&!g&&(i.value=!1)};return n.onMounted(()=>{document.addEventListener("click",H)}),n.onUnmounted(()=>{document.removeEventListener("click",H)}),()=>{const s=[];e["before-button"]&&s.push(...b(e["before-button"]()));const y=[];if(e["before-selected-locale"]&&y.push(...b(e["before-selected-locale"]())),y.push(n.h("span",p.value)),e["after-selected-locale"]&&y.push(...b(e["after-selected-locale"]())),y.push(n.h("span",{style:{...D,...i.value?A:{},...t.customIconStyle}},"▼")),s.push(n.h("button",{class:"i18n-switcher-button",style:{...P,...t.customButtonStyle},onClick:v=>{v.preventDefault(),v.stopPropagation(),c(v)},type:"button",ariaHaspopup:!0,ariaExpanded:i.value},y)),e["before-dropdown"]&&s.push(...b(e["before-dropdown"]())),i.value){const v=[];e["before-dropdown-items"]&&v.push(...b(e["before-dropdown-items"]())),o.value.forEach(g=>{const I=[];e["before-item"]&&I.push(...b(e["before-item"]({locale:g})));const T=[];e["before-link-content"]&&T.push(...b(e["before-link-content"]({locale:g}))),T.push(h(g)),e["after-link-content"]&&T.push(...b(e["after-link-content"]({locale:g})));const $=typeof window<"u"?window.location.pathname:"/",m=t.localeRoute?t.localeRoute($,g.code):l?.resolvePath?l.resolvePath($,g.code):$,M=typeof m=="string"?m:m.path||"#",x=g.code===f.value;I.push(n.h("a",{class:`switcher-locale-${g.code}`,href:typeof M=="string"?M:"#",style:{...L,...x?K:{},...t.customLinkStyle},onClick:w=>{w.preventDefault(),w.stopPropagation(),k(g.code)}},T)),e["after-item"]&&I.push(...b(e["after-item"]({locale:g}))),v.push(n.h("li",{key:g.code,style:{...j,...t.customItemStyle}},I))}),e["after-dropdown-items"]&&v.push(...b(e["after-dropdown-items"]())),s.push(n.h("ul",{class:"i18n-switcher-dropdown",style:{...R,...t.customDropdownStyle}},v))}return e["after-dropdown"]&&s.push(...b(e["after-dropdown"]())),n.h("div",{ref:a,class:"i18n-switcher-wrapper",style:{...S,...t.customWrapperStyle}},s)}}});function J(t){const{routingStrategy:e,locales:r,defaultLocale:l,...u}=t,o=new F(u);let f=null,d=e||null;return{global:o,setRoutingStrategy:a=>{d=a,f&&f.provide(O,a)},install(a){f=a,a.provide(C,o),d&&a.provide(O,d),r&&a.provide(_,r),l&&a.provide(U,l),a.config.globalProperties.$t=(c,h,p,k)=>o.t(c,h,p,k),a.config.globalProperties.$ts=(c,h,p,k)=>o.ts(c,h,p,k),a.config.globalProperties.$tc=(c,h,p)=>o.tc(c,h,p),a.config.globalProperties.$tn=(c,h)=>o.tn(c,h),a.config.globalProperties.$td=(c,h)=>o.td(c,h),a.config.globalProperties.$tdr=(c,h)=>o.tdr(c,h),a.config.globalProperties.$has=(c,h)=>o.has(c,h),a.config.globalProperties.$i18n=o,a.component("I18nT",W),a.component("I18nLink",G),a.component("I18nGroup",q),a.component("I18nSwitcher",B)}}}function z(t){const e=n.inject(C),r=n.inject(O,void 0),l=n.inject(_,void 0),u=n.inject(U,void 0);if(!e)throw new Error("[i18n-micro] useI18n() must be called after app.use(i18n). Make sure i18n plugin is installed.");if(!l)throw new Error("[i18n-micro] I18nLocalesKey not provided. Make sure app.provide(I18nLocalesKey, locales) is called.");if(!u)throw new Error("[i18n-micro] I18nDefaultLocaleKey not provided. Make sure app.provide(I18nDefaultLocaleKey, defaultLocale) is called.");const o=t?.locales||l,f=t?.defaultLocale||u,d=(i,a)=>r?.resolvePath?r.resolvePath(i,a||e.locale.value):i;return{instance:e,locale:n.computed({get:()=>e.locale.value,set:i=>{e.locale.value=i}}),getLocales:()=>o,defaultLocale:()=>f,getLocaleName:()=>o.find(a=>a.code===e.locale.value)?.displayName||null,localeRoute:d,localePath:(i,a)=>{const c=d(i,a);return typeof c=="string"?c:c.path||"/"},switchLocale:i=>{if(e.locale.value=i,r){const a=r.getCurrentPath(),c=d(a,i);r.push(typeof c=="string"?{path:c}:{path:c.path||"/"})}},t:e.t.bind(e),ts:e.ts.bind(e),tc:e.tc.bind(e),tn:e.tn.bind(e),td:e.td.bind(e),tdr:e.tdr.bind(e),has:e.has.bind(e),setRoute:e.setRoute.bind(e),getRoute:e.getRoute.bind(e),getLocale:()=>e.locale.value,addTranslations:e.addTranslations.bind(e),addRouteTranslations:e.addRouteTranslations.bind(e),mergeTranslations:e.mergeTranslations.bind(e),mergeGlobalTranslations:e.mergeGlobalTranslations.bind(e),clearCache:e.clearCache.bind(e)}}function Q(t={}){const{addDirAttribute:e=!0,identifierAttribute:r="id",addSeoAttributes:l=!0,baseUrl:u="/"}=t,{getLocale:o,getLocales:f,localeRoute:d}=z(),i=n.inject(O,void 0),a=n.ref({htmlAttrs:{},link:[],meta:[]});function c(p,k){const S=new URL(p,"http://localhost"),P=new URLSearchParams(S.search),R={};for(const L of k)P.has(L)&&(R[L]=P.get(L));const j=new URLSearchParams(R);return j.toString()?`${S.pathname}?${j.toString()}`:S.pathname}function h(p=[]){if(!i){a.value={htmlAttrs:{},link:[],meta:[]};return}const k=o(),S=f(),P=S.find(m=>m.code===k);if(!P)return;const R=P.iso||k,j=P.dir||"auto";let L=i.getCurrentPath();L.startsWith("/")||(L=`/${L}`);const K=L.split("/").filter(Boolean),D=S.find(m=>K[0]===m.code);let A=L,b;D?(A=L.slice(D.code.length+1)||"/",b=c(A,p)):b=c(L,p);const s=`${typeof u=="function"?u():u}${b.startsWith("/")?"":"/"}${b}`;if(a.value={htmlAttrs:{lang:R,...e?{dir:j}:{}},link:[],meta:[]},!l)return;const y=S,v={[r]:"i18n-og",property:"og:locale",content:R},g={[r]:"i18n-og-url",property:"og:url",content:s},I=y.map(m=>({[r]:`i18n-og-alt-${m.iso||m.code}`,property:"og:locale:alternate",content:m.iso||m.code})),T={[r]:"i18n-can",rel:"canonical",href:s},$=y.flatMap(m=>{if(!d||!i)return[];const M=i.getCurrentPath(),x=d(M,m.code),w=typeof x=="string"?x:x?.path||"/";if(!w)return[];let E;w.startsWith("http://")||w.startsWith("https://")?E=w:E=`${typeof u=="function"?u():u}${w.startsWith("/")?"":"/"}${w}`;const V=[{[r]:`i18n-alternate-${m.code}`,rel:"alternate",href:E,hreflang:m.code}];return m.iso&&m.iso!==m.code&&V.push({[r]:`i18n-alternate-${m.iso}`,rel:"alternate",href:E,hreflang:m.iso}),V});a.value.meta=[v,g,...I],a.value.link=[T,...$]}return{metaObject:a,updateMeta:h}}function X(t,e,r){const l=e.map(o=>o.code),u=(o,f)=>{const i=(typeof o=="string"?o:o.path||"/").split("/").filter(Boolean);i.length>0&&l.includes(i[0])&&i.shift();const a="/"+i.join("/");return f===r?a:`/${f}${a==="/"?"":a}`};return{linkComponent:Z.RouterLink,getCurrentPath:()=>t.currentRoute.value.path,push:o=>{t.push(o.path).catch(()=>{})},replace:o=>{t.replace(o.path).catch(()=>{})},resolvePath:(o,f)=>u(o,f),getRoute:()=>({fullPath:t.currentRoute.value.fullPath,query:t.currentRoute.value.query})}}Object.defineProperty(exports,"FormatService",{enumerable:!0,get:()=>N.FormatService});Object.defineProperty(exports,"defaultPlural",{enumerable:!0,get:()=>N.defaultPlural});Object.defineProperty(exports,"interpolate",{enumerable:!0,get:()=>N.interpolate});exports.I18nDefaultLocaleKey=U;exports.I18nGroup=q;exports.I18nInjectionKey=C;exports.I18nLink=G;exports.I18nLocalesKey=_;exports.I18nSwitcher=B;exports.I18nT=W;exports.VueI18n=F;exports.createI18n=J;exports.createVueRouterAdapter=X;exports.useI18n=z;exports.useLocaleHead=Q;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("vue"),E=require("@i18n-micro/core"),Z=require("vue-router"),I=Symbol("i18n"),N=Symbol("i18n-locales"),U=Symbol("i18n-default-locale"),$=Symbol("i18n-router-strategy"),F=r.defineComponent({name:"I18nGroup",props:{prefix:{type:String,required:!0},groupClass:{type:String,default:""}},setup(t,{slots:e}){const n=r.inject(I);if(!n)throw new Error("[i18n-micro] I18nGroup: i18n instance not found. Make sure i18n plugin is installed.");const o=(u,l)=>n.t(`${t.prefix}.${u}`,l,void 0,n.getRoute());return()=>r.h("div",{class:["i18n-group",t.groupClass]},e.default?.({prefix:t.prefix,t:o}))}}),G=r.defineComponent({name:"I18nLink",props:{to:{type:[String,Object],required:!0},activeStyle:{type:Object,default:()=>({})},localeRoute:{type:Function,default:void 0}},setup(t,{slots:e}){const n=r.inject(I),o=r.inject($,void 0);if(!n)throw new Error("[i18n-micro] I18nLink: i18n instance not found. Make sure i18n plugin is installed.");const u=r.computed(()=>typeof t.to=="string"?/^(?:https?:\/\/|\/\/|[a-zA-Z0-9-]+\.[a-zA-Z]{2,})|tel:|mailto:/.test(t.to):!1),l=r.computed(()=>{if(u.value)return t.to;if(t.localeRoute){const a=t.localeRoute(t.to);return typeof a=="string"?a:a.path||"/"}if(!o?.resolvePath)return typeof t.to=="string"?t.to:t.to.path||"/";const i=o.resolvePath(t.to,n.locale.value);return typeof i=="string"?i:i.path||"/"}),d=r.computed(()=>{if(u.value||!o)return!1;const i=o.getCurrentPath().replace(/\/$/,""),a=l.value.replace(/\/$/,"");return i===a}),h=r.computed(()=>d.value?t.activeStyle:{});return()=>u.value?r.h("a",{href:l.value,target:"_blank",rel:"noopener noreferrer",style:h.value},e.default?.()):o?.linkComponent?r.h(o.linkComponent,{to:l.value,style:h.value},{default:e.default}):r.h("a",{href:l.value,style:h.value,onClick:i=>{i.preventDefault(),o?o.push({path:l.value}):window.location.href=l.value}},e.default?.())}}),W=r.defineComponent({name:"I18nSwitcher",props:{customLabels:{type:Object,default:()=>({})},customWrapperStyle:{type:Object,default:()=>({})},customButtonStyle:{type:Object,default:()=>({})},customDropdownStyle:{type:Object,default:()=>({})},customItemStyle:{type:Object,default:()=>({})},customLinkStyle:{type:Object,default:()=>({})},customActiveLinkStyle:{type:Object,default:()=>({})},customDisabledLinkStyle:{type:Object,default:()=>({})},customIconStyle:{type:Object,default:()=>({})},locales:{type:Array,default:void 0},currentLocale:{type:[String,Function],default:void 0},getLocaleName:{type:Function,default:void 0},switchLocale:{type:Function,default:void 0},localeRoute:{type:Function,default:void 0}},setup(t,{slots:e}){const n=r.inject(I),o=r.inject($,void 0),u=r.inject(N,void 0);if(!n)throw new Error("[i18n-micro] I18nSwitcher: i18n instance not found. Make sure i18n plugin is installed.");if(!u&&!t.locales)throw new Error("[i18n-micro] I18nSwitcher: locales not provided. Make sure app.provide(I18nLocalesKey, locales) is called or pass locales prop.");const l=r.computed(()=>t.locales||u||[]),d=r.computed(()=>t.currentLocale!==void 0?typeof t.currentLocale=="function"?t.currentLocale():t.currentLocale:n.locale.value),h=r.computed(()=>t.getLocaleName?t.getLocaleName()||null:l.value.find(m=>m.code===n.locale.value)?.displayName||null),i=r.ref(!1),a=r.ref(null),c=s=>{s&&(s.stopPropagation(),s.preventDefault()),i.value=!i.value},f=s=>t.customLabels[s.code]||s.displayName||s.code,p=r.computed(()=>{const s=l.value.find(m=>m.code===d.value);return s?f(s):h.value||d.value}),k=async s=>{if(i.value=!1,await r.nextTick(),t.switchLocale){t.switchLocale(s);return}if(n.locale.value=s,!o)return;const m=o.getCurrentPath(),b=t.localeRoute?(()=>{const g=t.localeRoute(m,s);return typeof g=="string"?g:g.path||"/"})():o?.resolvePath?(()=>{const g=o.resolvePath(m,s);return typeof g=="string"?g:g.path||"/"})():m;o.push({path:b})},S={position:"relative",display:"inline-block",verticalAlign:"middle"},P={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"},R={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)"},j={margin:"0",padding:"0"},L={display:"block",padding:"8px 12px",color:"#333",textDecoration:"none",transition:"background-color 0.3s ease",cursor:"pointer"},K={fontWeight:"bold",color:"#007bff"},D={marginLeft:"8px",display:"inline-block",transition:"transform 0.3s ease"},M={transform:"rotate(180deg)"},v=s=>s?Array.isArray(s)?s:[s]:[],H=s=>{if(!i.value)return;const m=s.target;if(!m||!a.value)return;const b=a.value.contains(m),g=m.closest(".i18n-switcher-button")!==null;!b&&!g&&(i.value=!1)};return r.onMounted(()=>{document.addEventListener("click",H)}),r.onUnmounted(()=>{document.removeEventListener("click",H)}),()=>{const s=[];e["before-button"]&&s.push(...v(e["before-button"]()));const m=[];if(e["before-selected-locale"]&&m.push(...v(e["before-selected-locale"]())),m.push(r.h("span",p.value)),e["after-selected-locale"]&&m.push(...v(e["after-selected-locale"]())),m.push(r.h("span",{style:{...D,...i.value?M:{},...t.customIconStyle}},"▼")),s.push(r.h("button",{class:"i18n-switcher-button",style:{...P,...t.customButtonStyle},onClick:b=>{b.preventDefault(),b.stopPropagation(),c(b)},type:"button",ariaHaspopup:!0,ariaExpanded:i.value},m)),e["before-dropdown"]&&s.push(...v(e["before-dropdown"]())),i.value){const b=[];e["before-dropdown-items"]&&b.push(...v(e["before-dropdown-items"]())),l.value.forEach(g=>{const C=[];e["before-item"]&&C.push(...v(e["before-item"]({locale:g})));const T=[];e["before-link-content"]&&T.push(...v(e["before-link-content"]({locale:g}))),T.push(f(g)),e["after-link-content"]&&T.push(...v(e["after-link-content"]({locale:g})));const x=typeof window<"u"?window.location.pathname:"/",y=t.localeRoute?t.localeRoute(x,g.code):o?.resolvePath?o.resolvePath(x,g.code):x,_=typeof y=="string"?y:y.path||"#",O=g.code===d.value;C.push(r.h("a",{class:`switcher-locale-${g.code}`,href:typeof _=="string"?_:"#",style:{...L,...O?K:{},...t.customLinkStyle},onClick:w=>{w.preventDefault(),w.stopPropagation(),k(g.code)}},T)),e["after-item"]&&C.push(...v(e["after-item"]({locale:g}))),b.push(r.h("li",{key:g.code,style:{...j,...t.customItemStyle}},C))}),e["after-dropdown-items"]&&b.push(...v(e["after-dropdown-items"]())),s.push(r.h("ul",{class:"i18n-switcher-dropdown",style:{...R,...t.customDropdownStyle}},b))}return e["after-dropdown"]&&s.push(...v(e["after-dropdown"]())),r.h("div",{ref:a,class:"i18n-switcher-wrapper",style:{...S,...t.customWrapperStyle}},s)}}}),q=r.defineComponent({name:"I18nT",props:{keypath:{type:String,required:!0},plural:{type:[Number,String]},tag:{type:String,default:"span"},params:{type:Object,default:()=>({})},defaultValue:{type:String,default:""},html:{type:Boolean,default:!1},hideIfEmpty:{type:Boolean,default:!1},customPluralRule:{type:Function,default:null},number:{type:[Number,String]},date:{type:[Date,String,Number]},relativeDate:{type:[Date,String,Number]}},setup(t,{slots:e,attrs:n}){const o=r.inject(I);if(!o)throw new Error("[i18n-micro] I18nT: i18n instance not found. Make sure i18n plugin is installed.");return()=>{const u={},l=o.getRoute();if(t.number!==void 0){const a=Number(t.number),c=o.tn(a),f=o.t(t.keypath,{number:c,...t.params},void 0,l);return r.h(t.tag,{...n,innerHTML:f})}if(t.date!==void 0){const a=o.td(t.date),c=o.t(t.keypath,{date:a,...t.params},void 0,l);return r.h(t.tag,{...n,innerHTML:c})}if(t.relativeDate!==void 0){const a=o.tdr(t.relativeDate),c=o.t(t.keypath,{relativeDate:a,...t.params},void 0,l);return r.h(t.tag,{...n,innerHTML:c})}if(t.plural!==void 0){const a=Number.parseInt(t.plural.toString(),10);if(t.customPluralRule){const c=t.customPluralRule(t.keypath,a,t.params,o.locale.value,(f,p,k)=>o.t(f,p,k,l));return r.h(t.tag,{...n,innerHTML:c||""})}else{const c=o.tc(t.keypath,{count:a,...t.params});return r.h(t.tag,{...n,innerHTML:c})}}const d=(o.t(t.keypath,{...t.params,...u},void 0,l)??"").toString();if(t.hideIfEmpty&&!d.trim())return t.defaultValue??null;if(t.html)return r.h(t.tag,{...n,innerHTML:d});if(e.default)return r.h(t.tag,n,e.default({translation:d}));const h=[];let i=0;for(const[a,c]of Object.entries(e)){if(a==="default")continue;const f=`{${a}}`,p=d.indexOf(f,i);p!==-1&&(p>i&&h.push(d.slice(i,p)),c&&h.push(r.h(c)),i=p+f.length)}return i<d.length&&h.push(d.slice(i)),e.default?r.h(t.tag,n,e.default({children:h})):h.length>0?r.h(t.tag,n,h):r.h(t.tag,n,d)}}});function B(t){const e=r.inject(I),n=r.inject($,void 0),o=r.inject(N,void 0),u=r.inject(U,void 0);if(!e)throw new Error("[i18n-micro] useI18n() must be called after app.use(i18n). Make sure i18n plugin is installed.");if(!o)throw new Error("[i18n-micro] I18nLocalesKey not provided. Make sure app.provide(I18nLocalesKey, locales) is called.");if(!u)throw new Error("[i18n-micro] I18nDefaultLocaleKey not provided. Make sure app.provide(I18nDefaultLocaleKey, defaultLocale) is called.");const l=t?.locales||o,d=t?.defaultLocale||u,h=(i,a)=>n?.resolvePath?n.resolvePath(i,a||e.locale.value):i;return{instance:e,locale:r.computed({get:()=>e.locale.value,set:i=>{e.locale.value=i}}),getLocales:()=>l,defaultLocale:()=>d,getLocaleName:()=>l.find(a=>a.code===e.locale.value)?.displayName||null,localeRoute:h,localePath:(i,a)=>{const c=h(i,a);return typeof c=="string"?c:c.path||"/"},switchLocale:i=>{if(e.locale.value=i,n){const a=n.getCurrentPath(),c=h(a,i);n.push(typeof c=="string"?{path:c}:{path:c.path||"/"})}},t:e.t.bind(e),ts:e.ts.bind(e),tc:e.tc.bind(e),tn:e.tn.bind(e),td:e.td.bind(e),tdr:e.tdr.bind(e),has:e.has.bind(e),setRoute:e.setRoute.bind(e),getRoute:e.getRoute.bind(e),getLocale:()=>e.locale.value,addTranslations:e.addTranslations.bind(e),addRouteTranslations:e.addRouteTranslations.bind(e),mergeTranslations:e.mergeTranslations.bind(e),mergeGlobalTranslations:e.mergeGlobalTranslations.bind(e),clearCache:e.clearCache.bind(e)}}function J(t={}){const{addDirAttribute:e=!0,identifierAttribute:n="id",addSeoAttributes:o=!0,baseUrl:u="/"}=t,{getLocale:l,getLocales:d,localeRoute:h}=B(),i=r.inject($,void 0),a=r.ref({htmlAttrs:{},link:[],meta:[]});function c(p,k){const S=new URL(p,"http://localhost"),P=new URLSearchParams(S.search),R={};for(const L of k)P.has(L)&&(R[L]=P.get(L));const j=new URLSearchParams(R);return j.toString()?`${S.pathname}?${j.toString()}`:S.pathname}function f(p=[]){if(!i){a.value={htmlAttrs:{},link:[],meta:[]};return}const k=l(),S=d(),P=S.find(y=>y.code===k);if(!P)return;const R=P.iso||k,j=P.dir||"auto";let L=i.getCurrentPath();L.startsWith("/")||(L=`/${L}`);const K=L.split("/").filter(Boolean),D=S.find(y=>K[0]===y.code);let M=L,v;D?(M=L.slice(D.code.length+1)||"/",v=c(M,p)):v=c(L,p);const s=`${typeof u=="function"?u():u}${v.startsWith("/")?"":"/"}${v}`;if(a.value={htmlAttrs:{lang:R,...e?{dir:j}:{}},link:[],meta:[]},!o)return;const m=S,b={[n]:"i18n-og",property:"og:locale",content:R},g={[n]:"i18n-og-url",property:"og:url",content:s},C=m.map(y=>({[n]:`i18n-og-alt-${y.iso||y.code}`,property:"og:locale:alternate",content:y.iso||y.code})),T={[n]:"i18n-can",rel:"canonical",href:s},x=m.flatMap(y=>{if(!h||!i)return[];const _=i.getCurrentPath(),O=h(_,y.code),w=typeof O=="string"?O:O?.path||"/";if(!w)return[];let A;w.startsWith("http://")||w.startsWith("https://")?A=w:A=`${typeof u=="function"?u():u}${w.startsWith("/")?"":"/"}${w}`;const V=[{[n]:`i18n-alternate-${y.code}`,rel:"alternate",href:A,hreflang:y.code}];return y.iso&&y.iso!==y.code&&V.push({[n]:`i18n-alternate-${y.iso}`,rel:"alternate",href:A,hreflang:y.iso}),V});a.value.meta=[b,g,...C],a.value.link=[T,...x]}return{metaObject:a,updateMeta:f}}class z extends E.BaseI18n{constructor(e){const n={translations:new Map};if(super({storage:n,plural:e.plural,missingWarn:e.missingWarn,missingHandler:e.missingHandler}),this.listeners=new Set,this.storage=n,this._locale=r.shallowRef(e.locale),this._fallbackLocale=r.shallowRef(e.fallbackLocale||e.locale),this._currentRoute=r.shallowRef("general"),this._revision=r.shallowRef(0),e.messages)for(const[o,u]of Object.entries(e.messages))this.helper.loadTranslations(o,u)}get locale(){return this._locale}set locale(e){typeof e=="string"?this._locale.value=e:this._locale=e}get fallbackLocale(){return this._fallbackLocale}set fallbackLocale(e){typeof e=="string"?this._fallbackLocale.value=e:this._fallbackLocale=e}get currentRoute(){return this._currentRoute}setRoute(e){this._currentRoute.value=e}getLocale(){return this._locale.value}getFallbackLocale(){return this._fallbackLocale.value}getRoute(){return this._currentRoute.value}addTranslations(e,n,o=!0){super.loadTranslationsCore(e,n,o),this._revision.value++,this.notifyListeners()}addRouteTranslations(e,n,o,u=!0){super.loadRouteTranslationsCore(e,n,o,u),this._revision.value++,this.notifyListeners()}mergeTranslations(e,n,o){this.helper.mergeTranslation(e,n,o,!0),this._revision.value++,this.notifyListeners()}mergeGlobalTranslations(e,n){this.helper.mergeGlobalTranslation(e,n,!0),this._revision.value++,this.notifyListeners()}clearCache(){super.clearCache(),this._revision.value++,this.notifyListeners()}subscribeToChanges(e){return this.listeners.add(e),()=>this.listeners.delete(e)}notifyListeners(){this.listeners.forEach(e=>e())}getAllTranslations(){const e={};for(const[n,o]of this.storage.translations)if(!n.includes(":"))e[n]=o;else{const u=n.split(":")[0];u&&(e[u]||(e[u]={}),Object.assign(e[u],o))}return e}getStorage(){return this.storage}getGeneralCache(){const e={};for(const[n,o]of this.storage.translations)n.includes(":")||(e[n]=o);return e}getRouteCache(){const e={};for(const[n,o]of this.storage.translations)n.includes(":")&&(e[n]=o);return e}}function Q(t){const{routingStrategy:e,locales:n,defaultLocale:o,...u}=t,l=new z(u);let d=null,h=e||null;return{global:l,setRoutingStrategy:a=>{h=a,d&&d.provide($,a)},install(a){d=a,a.provide(I,l),h&&a.provide($,h),n&&a.provide(N,n),o&&a.provide(U,o),a.config.globalProperties.$t=(c,f,p,k)=>l.t(c,f,p,k),a.config.globalProperties.$ts=(c,f,p,k)=>l.ts(c,f,p,k),a.config.globalProperties.$tc=(c,f,p)=>l.tc(c,f,p),a.config.globalProperties.$tn=(c,f)=>l.tn(c,f),a.config.globalProperties.$td=(c,f)=>l.td(c,f),a.config.globalProperties.$tdr=(c,f)=>l.tdr(c,f),a.config.globalProperties.$has=(c,f)=>l.has(c,f),a.config.globalProperties.$i18n=l,a.component("I18nT",q),a.component("I18nLink",G),a.component("I18nGroup",F),a.component("I18nSwitcher",W)}}}function X(t,e,n){const o=e.map(l=>l.code),u=(l,d)=>{const i=(typeof l=="string"?l:l.path||"/").split("/").filter(Boolean),a=i[0];a!==void 0&&o.includes(a)&&i.shift();const c=`/${i.join("/")}`;return d===n?c:`/${d}${c==="/"?"":c}`};return{linkComponent:Z.RouterLink,getCurrentPath:()=>t.currentRoute.value.path,push:l=>{t.push(l.path).catch(()=>{})},replace:l=>{t.replace(l.path).catch(()=>{})},resolvePath:(l,d)=>u(l,d),getRoute:()=>({fullPath:t.currentRoute.value.fullPath,query:t.currentRoute.value.query})}}Object.defineProperty(exports,"FormatService",{enumerable:!0,get:()=>E.FormatService});Object.defineProperty(exports,"defaultPlural",{enumerable:!0,get:()=>E.defaultPlural});Object.defineProperty(exports,"interpolate",{enumerable:!0,get:()=>E.interpolate});exports.I18nDefaultLocaleKey=U;exports.I18nGroup=F;exports.I18nInjectionKey=I;exports.I18nLink=G;exports.I18nLocalesKey=N;exports.I18nSwitcher=W;exports.I18nT=q;exports.VueI18n=z;exports.createI18n=Q;exports.createVueRouterAdapter=X;exports.useI18n=B;exports.useLocaleHead=J;
package/dist/index.d.ts CHANGED
@@ -1,15 +1,15 @@
1
- export { createI18n } from './plugin';
2
- export type { I18nPlugin } from './plugin';
3
- export { useI18n, type UseI18nOptions } from './use-i18n';
4
- export { VueI18n, type VueI18nOptions } from './composer';
5
- export { I18nT } from './components/i18n-t';
6
- export { I18nLink } from './components/i18n-link';
7
1
  export { I18nGroup } from './components/i18n-group';
2
+ export { I18nLink } from './components/i18n-link';
8
3
  export { I18nSwitcher } from './components/i18n-switcher';
9
- export { I18nInjectionKey, I18nLocalesKey, I18nDefaultLocaleKey } from './injection';
10
- export { useLocaleHead } from './composables/use-locale-head';
4
+ export { I18nT } from './components/i18n-t';
11
5
  export type { UseLocaleHeadOptions } from './composables/use-locale-head';
12
- export type { I18nRoutingStrategy } from './router/types';
6
+ export { useLocaleHead } from './composables/use-locale-head';
7
+ export { VueI18n, type VueI18nOptions } from './composer';
8
+ export { I18nDefaultLocaleKey, I18nInjectionKey, I18nLocalesKey } from './injection';
9
+ export type { I18nPlugin } from './plugin';
10
+ export { createI18n } from './plugin';
11
+ export { type UseI18nOptions, useI18n } from './use-i18n';
12
+ export { defaultPlural, FormatService, interpolate } from '@i18n-micro/core';
13
+ export type { CleanTranslation, Getter, Locale, LocaleCode, Params, PluralFunc, Translations, } from '@i18n-micro/types';
13
14
  export { createVueRouterAdapter } from './router/adapter';
14
- export type { Translations, Params, PluralFunc, Getter, Locale, LocaleCode, CleanTranslation, } from '@i18n-micro/types';
15
- export { interpolate, FormatService, defaultPlural } from '@i18n-micro/core';
15
+ export type { I18nRoutingStrategy } from './router/types';
package/dist/index.mjs CHANGED
@@ -1,203 +1,33 @@
1
- import { shallowRef as W, ref as O, triggerRef as T, defineComponent as F, inject as S, h as g, computed as C, onMounted as q, onUnmounted as Z, nextTick as J } from "vue";
2
- import { BaseI18n as Q } from "@i18n-micro/core";
3
- import { FormatService as ge, defaultPlural as ye, interpolate as me } from "@i18n-micro/core";
4
- import { RouterLink as X } from "vue-router";
5
- class Y extends Q {
6
- constructor(e) {
7
- const a = {
8
- generalLocaleCache: W({}),
9
- routeLocaleCache: W({}),
10
- dynamicTranslationsCaches: W([]),
11
- serverTranslationCache: W({})
12
- };
13
- if (super({
14
- cache: a,
15
- plural: e.plural,
16
- missingWarn: e.missingWarn,
17
- missingHandler: e.missingHandler
18
- }), this.listeners = /* @__PURE__ */ new Set(), this.cache = a, this._locale = O(e.locale), this._fallbackLocale = O(e.fallbackLocale || e.locale), this._currentRoute = O("general"), e.messages)
19
- for (const [o, c] of Object.entries(e.messages))
20
- this.helper.loadTranslations(o, c);
21
- }
22
- // Геттер/Сеттер для локали
23
- get locale() {
24
- return this._locale;
25
- }
26
- set locale(e) {
27
- typeof e == "string" ? this._locale.value = e : this._locale = e;
28
- }
29
- // Геттер/Сеттер для fallback локали
30
- get fallbackLocale() {
31
- return this._fallbackLocale;
32
- }
33
- set fallbackLocale(e) {
34
- typeof e == "string" ? this._fallbackLocale.value = e : this._fallbackLocale = e;
35
- }
36
- // Геттер/Сеттер для текущего роута
37
- get currentRoute() {
38
- return this._currentRoute;
39
- }
40
- setRoute(e) {
41
- this._currentRoute.value = e;
42
- }
43
- // --- Implementation of abstract methods ---
44
- getLocale() {
45
- return this._locale.value;
46
- }
47
- getFallbackLocale() {
48
- return this._fallbackLocale.value;
49
- }
50
- getRoute() {
51
- return this._currentRoute.value;
52
- }
53
- // Методы для добавления переводов (реактивно) - uses protected methods from base class
54
- addTranslations(e, a, o = !0) {
55
- super.loadTranslationsCore(e, a, o), T(this.cache.generalLocaleCache), this.notifyListeners();
56
- }
57
- addRouteTranslations(e, a, o, c = !0) {
58
- super.loadRouteTranslationsCore(e, a, o, c), T(this.cache.routeLocaleCache), this.notifyListeners();
59
- }
60
- mergeTranslations(e, a, o) {
61
- this.helper.mergeTranslation(e, a, o, !0), T(this.cache.routeLocaleCache), this.notifyListeners();
62
- }
63
- mergeGlobalTranslations(e, a) {
64
- this.helper.mergeGlobalTranslation(e, a, !0), T(this.cache.generalLocaleCache), this.notifyListeners();
65
- }
66
- clearCache() {
67
- super.clearCache(), T(this.cache.generalLocaleCache), T(this.cache.routeLocaleCache), T(this.cache.dynamicTranslationsCaches), T(this.cache.serverTranslationCache), this.notifyListeners();
68
- }
69
- // Подписка на изменения для DevTools
70
- subscribeToChanges(e) {
71
- return this.listeners.add(e), () => {
72
- this.listeners.delete(e);
73
- };
74
- }
75
- // Уведомление подписчиков об изменениях
76
- notifyListeners() {
77
- this.listeners.forEach((e) => {
78
- e();
79
- });
80
- }
81
- // Method for devtools: get all translations from cache
82
- getAllTranslations() {
83
- const e = {}, a = this.cache.generalLocaleCache.value || {}, o = this.cache.routeLocaleCache.value || {};
84
- for (const [c, r] of Object.entries(a))
85
- e[c] || (e[c] = {}), Object.assign(e[c], r);
86
- for (const [c, r] of Object.entries(o))
87
- if (r && typeof r == "object" && !Array.isArray(r))
88
- for (const [u, f] of Object.entries(r))
89
- e[u] || (e[u] = {}), f && typeof f == "object" && !Array.isArray(f) && Object.assign(e[u], f);
90
- return e;
91
- }
92
- // Method for devtools: get cache (for direct access if needed)
93
- getCache() {
94
- return this.cache;
95
- }
96
- }
97
- const A = Symbol("i18n"), B = Symbol("i18n-locales"), z = Symbol("i18n-default-locale"), D = Symbol("i18n-router-strategy"), ee = F({
98
- name: "I18nT",
1
+ import { defineComponent as H, inject as S, h as g, computed as R, ref as G, onMounted as z, onUnmounted as q, nextTick as Z, shallowRef as U } from "vue";
2
+ import { BaseI18n as J } from "@i18n-micro/core";
3
+ import { FormatService as he, defaultPlural as ge, interpolate as ye } from "@i18n-micro/core";
4
+ import { RouterLink as Q } from "vue-router";
5
+ const D = /* @__PURE__ */ Symbol("i18n"), K = /* @__PURE__ */ Symbol("i18n-locales"), B = /* @__PURE__ */ Symbol("i18n-default-locale"), j = /* @__PURE__ */ Symbol("i18n-router-strategy"), X = H({
6
+ name: "I18nGroup",
99
7
  props: {
100
- keypath: {
8
+ prefix: {
101
9
  type: String,
102
10
  required: !0
103
11
  },
104
- plural: {
105
- type: [Number, String]
106
- },
107
- tag: {
108
- type: String,
109
- default: "span"
110
- },
111
- params: {
112
- type: Object,
113
- default: () => ({})
114
- },
115
- defaultValue: {
12
+ groupClass: {
116
13
  type: String,
117
14
  default: ""
118
- },
119
- html: {
120
- type: Boolean,
121
- default: !1
122
- },
123
- hideIfEmpty: {
124
- type: Boolean,
125
- default: !1
126
- },
127
- customPluralRule: {
128
- type: Function,
129
- default: null
130
- },
131
- number: {
132
- type: [Number, String]
133
- },
134
- date: {
135
- type: [Date, String, Number]
136
- },
137
- relativeDate: {
138
- type: [Date, String, Number]
139
15
  }
140
16
  },
141
- setup(t, { slots: e, attrs: a }) {
142
- const o = S(A);
143
- if (!o)
144
- throw new Error("[i18n-micro] I18nT: i18n instance not found. Make sure i18n plugin is installed.");
145
- return () => {
146
- const c = {}, r = o.getRoute();
147
- if (t.number !== void 0) {
148
- const n = Number(t.number), i = o.tn(n), d = o.t(t.keypath, { number: i, ...t.params }, void 0, r);
149
- return g(t.tag, { ...a, innerHTML: d });
150
- }
151
- if (t.date !== void 0) {
152
- const n = o.td(t.date), i = o.t(t.keypath, { date: n, ...t.params }, void 0, r);
153
- return g(t.tag, { ...a, innerHTML: i });
154
- }
155
- if (t.relativeDate !== void 0) {
156
- const n = o.tdr(t.relativeDate), i = o.t(t.keypath, { relativeDate: n, ...t.params }, void 0, r);
157
- return g(t.tag, { ...a, innerHTML: i });
158
- }
159
- if (t.plural !== void 0) {
160
- const n = Number.parseInt(t.plural.toString());
161
- if (t.customPluralRule) {
162
- const i = t.customPluralRule(
163
- t.keypath,
164
- n,
165
- t.params,
166
- o.locale.value,
167
- (d, p, k) => o.t(d, p, k, r)
168
- );
169
- return g(t.tag, { ...a, innerHTML: i || "" });
170
- } else {
171
- const i = o.tc(t.keypath, { count: n, ...t.params });
172
- return g(t.tag, { ...a, innerHTML: i });
173
- }
174
- }
175
- const u = (o.t(t.keypath, { ...t.params, ...c }, void 0, r) ?? "").toString();
176
- if (t.hideIfEmpty && !u.trim())
177
- return t.defaultValue ?? null;
178
- if (t.html)
179
- return g(t.tag, { ...a, innerHTML: u });
180
- if (e.default)
181
- return g(
182
- t.tag,
183
- a,
184
- e.default({ translation: u })
185
- );
186
- const f = [];
187
- let l = 0;
188
- for (const [n, i] of Object.entries(e)) {
189
- if (n === "default") continue;
190
- const d = `{${n}}`, p = u.indexOf(d, l);
191
- p !== -1 && (p > l && f.push(u.slice(l, p)), i && f.push(g(i)), l = p + d.length);
192
- }
193
- return l < u.length && f.push(u.slice(l)), e.default ? g(
194
- t.tag,
195
- a,
196
- e.default({ children: f })
197
- ) : f.length > 0 ? g(t.tag, a, f) : g(t.tag, a, u);
198
- };
17
+ setup(t, { slots: e }) {
18
+ const n = S(D);
19
+ if (!n)
20
+ throw new Error("[i18n-micro] I18nGroup: i18n instance not found. Make sure i18n plugin is installed.");
21
+ const r = (c, o) => n.t(`${t.prefix}.${c}`, o, void 0, n.getRoute());
22
+ return () => g(
23
+ "div",
24
+ {
25
+ class: ["i18n-group", t.groupClass]
26
+ },
27
+ e.default?.({ prefix: t.prefix, t: r })
28
+ );
199
29
  }
200
- }), te = F({
30
+ }), Y = H({
201
31
  name: "I18nLink",
202
32
  props: {
203
33
  to: {
@@ -214,64 +44,55 @@ const A = Symbol("i18n"), B = Symbol("i18n-locales"), z = Symbol("i18n-default-l
214
44
  }
215
45
  },
216
46
  setup(t, { slots: e }) {
217
- const a = S(A), o = S(D, void 0);
218
- if (!a)
47
+ const n = S(D), r = S(j, void 0);
48
+ if (!n)
219
49
  throw new Error("[i18n-micro] I18nLink: i18n instance not found. Make sure i18n plugin is installed.");
220
- const c = C(() => typeof t.to == "string" ? /^(?:https?:\/\/|\/\/|[a-zA-Z0-9-]+\.[a-zA-Z]{2,})|tel:|mailto:/.test(t.to) : !1), r = C(() => {
50
+ const c = R(() => typeof t.to == "string" ? /^(?:https?:\/\/|\/\/|[a-zA-Z0-9-]+\.[a-zA-Z]{2,})|tel:|mailto:/.test(t.to) : !1), o = R(() => {
221
51
  if (c.value)
222
52
  return t.to;
223
53
  if (t.localeRoute) {
224
- const n = t.localeRoute(t.to);
225
- return typeof n == "string" ? n : n.path || "/";
54
+ const a = t.localeRoute(t.to);
55
+ return typeof a == "string" ? a : a.path || "/";
226
56
  }
227
- if (!o?.resolvePath)
57
+ if (!r?.resolvePath)
228
58
  return typeof t.to == "string" ? t.to : t.to.path || "/";
229
- const l = o.resolvePath(t.to, a.locale.value);
59
+ const l = r.resolvePath(t.to, n.locale.value);
230
60
  return typeof l == "string" ? l : l.path || "/";
231
- }), u = C(() => {
232
- if (c.value || !o)
61
+ }), u = R(() => {
62
+ if (c.value || !r)
233
63
  return !1;
234
- const l = o.getCurrentPath().replace(/\/$/, ""), n = r.value.replace(/\/$/, "");
235
- return l === n;
236
- }), f = C(() => u.value ? t.activeStyle : {});
237
- return () => c.value ? g("a", {
238
- href: r.value,
239
- target: "_blank",
240
- rel: "noopener noreferrer",
241
- style: f.value
242
- }, e.default?.()) : o?.linkComponent ? g(o.linkComponent, {
243
- to: r.value,
244
- style: f.value
245
- }, { default: e.default }) : g("a", {
246
- href: r.value,
247
- style: f.value,
248
- onClick: (l) => {
249
- l.preventDefault(), o ? o.push({ path: r.value }) : window.location.href = r.value;
250
- }
251
- }, e.default?.());
252
- }
253
- }), ne = F({
254
- name: "I18nGroup",
255
- props: {
256
- prefix: {
257
- type: String,
258
- required: !0
259
- },
260
- groupClass: {
261
- type: String,
262
- default: ""
263
- }
264
- },
265
- setup(t, { slots: e }) {
266
- const a = S(A);
267
- if (!a)
268
- throw new Error("[i18n-micro] I18nGroup: i18n instance not found. Make sure i18n plugin is installed.");
269
- const o = (c, r) => a.t(`${t.prefix}.${c}`, r, void 0, a.getRoute());
270
- return () => g("div", {
271
- class: ["i18n-group", t.groupClass]
272
- }, e.default?.({ prefix: t.prefix, t: o }));
64
+ const l = r.getCurrentPath().replace(/\/$/, ""), a = o.value.replace(/\/$/, "");
65
+ return l === a;
66
+ }), f = R(() => u.value ? t.activeStyle : {});
67
+ return () => c.value ? g(
68
+ "a",
69
+ {
70
+ href: o.value,
71
+ target: "_blank",
72
+ rel: "noopener noreferrer",
73
+ style: f.value
74
+ },
75
+ e.default?.()
76
+ ) : r?.linkComponent ? g(
77
+ r.linkComponent,
78
+ {
79
+ to: o.value,
80
+ style: f.value
81
+ },
82
+ { default: e.default }
83
+ ) : g(
84
+ "a",
85
+ {
86
+ href: o.value,
87
+ style: f.value,
88
+ onClick: (l) => {
89
+ l.preventDefault(), r ? r.push({ path: o.value }) : window.location.href = o.value;
90
+ }
91
+ },
92
+ e.default?.()
93
+ );
273
94
  }
274
- }), ae = F({
95
+ }), ee = H({
275
96
  name: "I18nSwitcher",
276
97
  props: {
277
98
  customLabels: {
@@ -332,36 +153,38 @@ const A = Symbol("i18n"), B = Symbol("i18n-locales"), z = Symbol("i18n-default-l
332
153
  }
333
154
  },
334
155
  setup(t, { slots: e }) {
335
- const a = S(A), o = S(D, void 0), c = S(B, void 0);
336
- if (!a)
156
+ const n = S(D), r = S(j, void 0), c = S(K, void 0);
157
+ if (!n)
337
158
  throw new Error("[i18n-micro] I18nSwitcher: i18n instance not found. Make sure i18n plugin is installed.");
338
159
  if (!c && !t.locales)
339
- throw new Error("[i18n-micro] I18nSwitcher: locales not provided. Make sure app.provide(I18nLocalesKey, locales) is called or pass locales prop.");
340
- const r = C(() => t.locales || c || []), u = C(() => t.currentLocale !== void 0 ? typeof t.currentLocale == "function" ? t.currentLocale() : t.currentLocale : a.locale.value), f = C(() => t.getLocaleName ? t.getLocaleName() || null : r.value.find((y) => y.code === a.locale.value)?.displayName || null), l = O(!1), n = O(null), i = (s) => {
160
+ throw new Error(
161
+ "[i18n-micro] I18nSwitcher: locales not provided. Make sure app.provide(I18nLocalesKey, locales) is called or pass locales prop."
162
+ );
163
+ const o = R(() => t.locales || c || []), u = R(() => t.currentLocale !== void 0 ? typeof t.currentLocale == "function" ? t.currentLocale() : t.currentLocale : n.locale.value), f = R(() => t.getLocaleName ? t.getLocaleName() || null : o.value.find((y) => y.code === n.locale.value)?.displayName || null), l = G(!1), a = G(null), i = (s) => {
341
164
  s && (s.stopPropagation(), s.preventDefault()), l.value = !l.value;
342
- }, d = (s) => t.customLabels[s.code] || s.displayName || s.code, p = C(() => {
343
- const s = r.value.find((y) => y.code === u.value);
165
+ }, d = (s) => t.customLabels[s.code] || s.displayName || s.code, p = R(() => {
166
+ const s = o.value.find((y) => y.code === u.value);
344
167
  return s ? d(s) : f.value || u.value;
345
168
  }), k = async (s) => {
346
- if (l.value = !1, await J(), t.switchLocale) {
169
+ if (l.value = !1, await Z(), t.switchLocale) {
347
170
  t.switchLocale(s);
348
171
  return;
349
172
  }
350
- if (a.locale.value = s, !o)
173
+ if (n.locale.value = s, !r)
351
174
  return;
352
- const y = o.getCurrentPath(), v = t.localeRoute ? (() => {
175
+ const y = r.getCurrentPath(), b = t.localeRoute ? (() => {
353
176
  const h = t.localeRoute(y, s);
354
177
  return typeof h == "string" ? h : h.path || "/";
355
- })() : o?.resolvePath ? (() => {
356
- const h = o.resolvePath(y, s);
178
+ })() : r?.resolvePath ? (() => {
179
+ const h = r.resolvePath(y, s);
357
180
  return typeof h == "string" ? h : h.path || "/";
358
181
  })() : y;
359
- o.push({ path: v });
182
+ r.push({ path: b });
360
183
  }, w = {
361
184
  position: "relative",
362
185
  display: "inline-block",
363
186
  verticalAlign: "middle"
364
- }, R = {
187
+ }, C = {
365
188
  padding: "4px 12px",
366
189
  fontSize: "16px",
367
190
  cursor: "pointer",
@@ -383,7 +206,7 @@ const A = Symbol("i18n"), B = Symbol("i18n-locales"), z = Symbol("i18n-default-l
383
206
  margin: "4px 0 0 0",
384
207
  minWidth: "150px",
385
208
  boxShadow: "0 2px 8px rgba(0,0,0,0.15)"
386
- }, j = {
209
+ }, T = {
387
210
  margin: "0",
388
211
  padding: "0"
389
212
  }, L = {
@@ -393,140 +216,244 @@ const A = Symbol("i18n"), B = Symbol("i18n-locales"), z = Symbol("i18n-default-l
393
216
  textDecoration: "none",
394
217
  transition: "background-color 0.3s ease",
395
218
  cursor: "pointer"
396
- }, K = {
219
+ }, W = {
397
220
  fontWeight: "bold",
398
221
  color: "#007bff"
399
- }, N = {
222
+ }, _ = {
400
223
  marginLeft: "8px",
401
224
  display: "inline-block",
402
225
  transition: "transform 0.3s ease"
403
- }, _ = {
226
+ }, A = {
404
227
  transform: "rotate(180deg)"
405
- }, b = (s) => s ? Array.isArray(s) ? s : [s] : [], V = (s) => {
228
+ }, v = (s) => s ? Array.isArray(s) ? s : [s] : [], F = (s) => {
406
229
  if (!l.value) return;
407
230
  const y = s.target;
408
- if (!y || !n.value) return;
409
- const v = n.value.contains(y), h = y.closest(".i18n-switcher-button") !== null;
410
- !v && !h && (l.value = !1);
231
+ if (!y || !a.value) return;
232
+ const b = a.value.contains(y), h = y.closest(".i18n-switcher-button") !== null;
233
+ !b && !h && (l.value = !1);
411
234
  };
412
- return q(() => {
413
- document.addEventListener("click", V);
414
- }), Z(() => {
415
- document.removeEventListener("click", V);
235
+ return z(() => {
236
+ document.addEventListener("click", F);
237
+ }), q(() => {
238
+ document.removeEventListener("click", F);
416
239
  }), () => {
417
240
  const s = [];
418
- e["before-button"] && s.push(...b(e["before-button"]()));
241
+ e["before-button"] && s.push(...v(e["before-button"]()));
419
242
  const y = [];
420
- if (e["before-selected-locale"] && y.push(...b(e["before-selected-locale"]())), y.push(g("span", p.value)), e["after-selected-locale"] && y.push(...b(e["after-selected-locale"]())), y.push(
421
- g("span", {
422
- style: {
423
- ...N,
424
- ...l.value ? _ : {},
425
- ...t.customIconStyle
426
- }
427
- }, "▼")
243
+ if (e["before-selected-locale"] && y.push(...v(e["before-selected-locale"]())), y.push(g("span", p.value)), e["after-selected-locale"] && y.push(...v(e["after-selected-locale"]())), y.push(
244
+ g(
245
+ "span",
246
+ {
247
+ style: {
248
+ ..._,
249
+ ...l.value ? A : {},
250
+ ...t.customIconStyle
251
+ }
252
+ },
253
+ "▼"
254
+ )
428
255
  ), s.push(
429
- g("button", {
430
- class: "i18n-switcher-button",
431
- style: { ...R, ...t.customButtonStyle },
432
- onClick: (v) => {
433
- v.preventDefault(), v.stopPropagation(), i(v);
256
+ g(
257
+ "button",
258
+ {
259
+ class: "i18n-switcher-button",
260
+ style: { ...C, ...t.customButtonStyle },
261
+ onClick: (b) => {
262
+ b.preventDefault(), b.stopPropagation(), i(b);
263
+ },
264
+ type: "button",
265
+ ariaHaspopup: !0,
266
+ ariaExpanded: l.value
434
267
  },
435
- type: "button",
436
- ariaHaspopup: !0,
437
- ariaExpanded: l.value
438
- }, y)
439
- ), e["before-dropdown"] && s.push(...b(e["before-dropdown"]())), l.value) {
440
- const v = [];
441
- e["before-dropdown-items"] && v.push(...b(e["before-dropdown-items"]())), r.value.forEach((h) => {
268
+ y
269
+ )
270
+ ), e["before-dropdown"] && s.push(...v(e["before-dropdown"]())), l.value) {
271
+ const b = [];
272
+ e["before-dropdown-items"] && b.push(...v(e["before-dropdown-items"]())), o.value.forEach((h) => {
442
273
  const x = [];
443
- e["before-item"] && x.push(...b(e["before-item"]({ locale: h })));
274
+ e["before-item"] && x.push(...v(e["before-item"]({ locale: h })));
444
275
  const $ = [];
445
- e["before-link-content"] && $.push(...b(e["before-link-content"]({ locale: h }))), $.push(d(h)), e["after-link-content"] && $.push(...b(e["after-link-content"]({ locale: h })));
446
- const M = typeof window < "u" ? window.location.pathname : "/", m = t.localeRoute ? t.localeRoute(M, h.code) : o?.resolvePath ? o.resolvePath(M, h.code) : M, U = typeof m == "string" ? m : m.path || "#", E = h.code === u.value;
276
+ e["before-link-content"] && $.push(...v(e["before-link-content"]({ locale: h }))), $.push(d(h)), e["after-link-content"] && $.push(...v(e["after-link-content"]({ locale: h })));
277
+ const O = typeof window < "u" ? window.location.pathname : "/", m = t.localeRoute ? t.localeRoute(O, h.code) : r?.resolvePath ? r.resolvePath(O, h.code) : O, E = typeof m == "string" ? m : m.path || "#", M = h.code === u.value;
447
278
  x.push(
448
- g("a", {
449
- class: `switcher-locale-${h.code}`,
450
- href: typeof U == "string" ? U : "#",
451
- style: {
452
- ...L,
453
- ...E ? K : {},
454
- ...t.customLinkStyle
279
+ g(
280
+ "a",
281
+ {
282
+ class: `switcher-locale-${h.code}`,
283
+ href: typeof E == "string" ? E : "#",
284
+ style: {
285
+ ...L,
286
+ ...M ? W : {},
287
+ ...t.customLinkStyle
288
+ },
289
+ // Предотвращаем стандартную навигацию, используем только handleSwitchLocale
290
+ onClick: (P) => {
291
+ P.preventDefault(), P.stopPropagation(), k(h.code);
292
+ }
293
+ },
294
+ $
295
+ )
296
+ ), e["after-item"] && x.push(...v(e["after-item"]({ locale: h }))), b.push(
297
+ g(
298
+ "li",
299
+ {
300
+ key: h.code,
301
+ style: { ...T, ...t.customItemStyle }
455
302
  },
456
- // Предотвращаем стандартную навигацию, используем только handleSwitchLocale
457
- onClick: (P) => {
458
- P.preventDefault(), P.stopPropagation(), k(h.code);
459
- }
460
- }, $)
461
- ), e["after-item"] && x.push(...b(e["after-item"]({ locale: h }))), v.push(
462
- g("li", {
463
- key: h.code,
464
- style: { ...j, ...t.customItemStyle }
465
- }, x)
303
+ x
304
+ )
466
305
  );
467
- }), e["after-dropdown-items"] && v.push(...b(e["after-dropdown-items"]())), s.push(
468
- g("ul", {
469
- class: "i18n-switcher-dropdown",
470
- style: { ...I, ...t.customDropdownStyle }
471
- }, v)
306
+ }), e["after-dropdown-items"] && b.push(...v(e["after-dropdown-items"]())), s.push(
307
+ g(
308
+ "ul",
309
+ {
310
+ class: "i18n-switcher-dropdown",
311
+ style: { ...I, ...t.customDropdownStyle }
312
+ },
313
+ b
314
+ )
472
315
  );
473
316
  }
474
- return e["after-dropdown"] && s.push(...b(e["after-dropdown"]())), g("div", {
475
- ref: n,
476
- class: "i18n-switcher-wrapper",
477
- style: { ...w, ...t.customWrapperStyle }
478
- }, s);
317
+ return e["after-dropdown"] && s.push(...v(e["after-dropdown"]())), g(
318
+ "div",
319
+ {
320
+ ref: a,
321
+ class: "i18n-switcher-wrapper",
322
+ style: { ...w, ...t.customWrapperStyle }
323
+ },
324
+ s
325
+ );
479
326
  };
480
327
  }
481
- });
482
- function se(t) {
483
- const { routingStrategy: e, locales: a, defaultLocale: o, ...c } = t, r = new Y(c);
484
- let u = null, f = e || null;
485
- return {
486
- global: r,
487
- // Доступ к инстансу вне компонентов
488
- setRoutingStrategy: (n) => {
489
- f = n, u && u.provide(D, n);
328
+ }), te = H({
329
+ name: "I18nT",
330
+ props: {
331
+ keypath: {
332
+ type: String,
333
+ required: !0
490
334
  },
491
- // Метод для установки адаптера после создания
492
- install(n) {
493
- u = n, n.provide(A, r), f && n.provide(D, f), a && n.provide(B, a), o && n.provide(z, o), n.config.globalProperties.$t = (i, d, p, k) => r.t(i, d, p, k), n.config.globalProperties.$ts = (i, d, p, k) => r.ts(i, d, p, k), n.config.globalProperties.$tc = (i, d, p) => r.tc(i, d, p), n.config.globalProperties.$tn = (i, d) => r.tn(i, d), n.config.globalProperties.$td = (i, d) => r.td(i, d), n.config.globalProperties.$tdr = (i, d) => r.tdr(i, d), n.config.globalProperties.$has = (i, d) => r.has(i, d), n.config.globalProperties.$i18n = r, n.component("I18nT", ee), n.component("I18nLink", te), n.component("I18nGroup", ne), n.component("I18nSwitcher", ae);
335
+ plural: {
336
+ type: [Number, String]
337
+ },
338
+ tag: {
339
+ type: String,
340
+ default: "span"
341
+ },
342
+ params: {
343
+ type: Object,
344
+ default: () => ({})
345
+ },
346
+ defaultValue: {
347
+ type: String,
348
+ default: ""
349
+ },
350
+ html: {
351
+ type: Boolean,
352
+ default: !1
353
+ },
354
+ hideIfEmpty: {
355
+ type: Boolean,
356
+ default: !1
357
+ },
358
+ customPluralRule: {
359
+ type: Function,
360
+ default: null
361
+ },
362
+ number: {
363
+ type: [Number, String]
364
+ },
365
+ date: {
366
+ type: [Date, String, Number]
367
+ },
368
+ relativeDate: {
369
+ type: [Date, String, Number]
494
370
  }
495
- };
496
- }
497
- function re(t) {
498
- const e = S(A), a = S(D, void 0), o = S(B, void 0), c = S(z, void 0);
371
+ },
372
+ setup(t, { slots: e, attrs: n }) {
373
+ const r = S(D);
374
+ if (!r)
375
+ throw new Error("[i18n-micro] I18nT: i18n instance not found. Make sure i18n plugin is installed.");
376
+ return () => {
377
+ const c = {}, o = r.getRoute();
378
+ if (t.number !== void 0) {
379
+ const a = Number(t.number), i = r.tn(a), d = r.t(t.keypath, { number: i, ...t.params }, void 0, o);
380
+ return g(t.tag, { ...n, innerHTML: d });
381
+ }
382
+ if (t.date !== void 0) {
383
+ const a = r.td(t.date), i = r.t(t.keypath, { date: a, ...t.params }, void 0, o);
384
+ return g(t.tag, { ...n, innerHTML: i });
385
+ }
386
+ if (t.relativeDate !== void 0) {
387
+ const a = r.tdr(t.relativeDate), i = r.t(t.keypath, { relativeDate: a, ...t.params }, void 0, o);
388
+ return g(t.tag, { ...n, innerHTML: i });
389
+ }
390
+ if (t.plural !== void 0) {
391
+ const a = Number.parseInt(t.plural.toString(), 10);
392
+ if (t.customPluralRule) {
393
+ const i = t.customPluralRule(
394
+ t.keypath,
395
+ a,
396
+ t.params,
397
+ r.locale.value,
398
+ (d, p, k) => r.t(d, p, k, o)
399
+ );
400
+ return g(t.tag, { ...n, innerHTML: i || "" });
401
+ } else {
402
+ const i = r.tc(t.keypath, { count: a, ...t.params });
403
+ return g(t.tag, { ...n, innerHTML: i });
404
+ }
405
+ }
406
+ const u = (r.t(t.keypath, { ...t.params, ...c }, void 0, o) ?? "").toString();
407
+ if (t.hideIfEmpty && !u.trim())
408
+ return t.defaultValue ?? null;
409
+ if (t.html)
410
+ return g(t.tag, { ...n, innerHTML: u });
411
+ if (e.default)
412
+ return g(t.tag, n, e.default({ translation: u }));
413
+ const f = [];
414
+ let l = 0;
415
+ for (const [a, i] of Object.entries(e)) {
416
+ if (a === "default") continue;
417
+ const d = `{${a}}`, p = u.indexOf(d, l);
418
+ p !== -1 && (p > l && f.push(u.slice(l, p)), i && f.push(g(i)), l = p + d.length);
419
+ }
420
+ return l < u.length && f.push(u.slice(l)), e.default ? g(t.tag, n, e.default({ children: f })) : f.length > 0 ? g(t.tag, n, f) : g(t.tag, n, u);
421
+ };
422
+ }
423
+ });
424
+ function ne(t) {
425
+ const e = S(D), n = S(j, void 0), r = S(K, void 0), c = S(B, void 0);
499
426
  if (!e)
500
427
  throw new Error("[i18n-micro] useI18n() must be called after app.use(i18n). Make sure i18n plugin is installed.");
501
- if (!o)
428
+ if (!r)
502
429
  throw new Error("[i18n-micro] I18nLocalesKey not provided. Make sure app.provide(I18nLocalesKey, locales) is called.");
503
430
  if (!c)
504
431
  throw new Error("[i18n-micro] I18nDefaultLocaleKey not provided. Make sure app.provide(I18nDefaultLocaleKey, defaultLocale) is called.");
505
- const r = t?.locales || o, u = t?.defaultLocale || c, f = (l, n) => a?.resolvePath ? a.resolvePath(l, n || e.locale.value) : l;
432
+ const o = t?.locales || r, u = t?.defaultLocale || c, f = (l, a) => n?.resolvePath ? n.resolvePath(l, a || e.locale.value) : l;
506
433
  return {
507
434
  // Direct access to instance
508
435
  instance: e,
509
436
  // Locale (reactive)
510
- locale: C({
437
+ locale: R({
511
438
  get: () => e.locale.value,
512
439
  set: (l) => {
513
440
  e.locale.value = l;
514
441
  }
515
442
  }),
516
443
  // Locale helpers
517
- getLocales: () => r,
444
+ getLocales: () => o,
518
445
  defaultLocale: () => u,
519
- getLocaleName: () => r.find((n) => n.code === e.locale.value)?.displayName || null,
446
+ getLocaleName: () => o.find((a) => a.code === e.locale.value)?.displayName || null,
520
447
  // Routing helpers
521
448
  localeRoute: f,
522
- localePath: (l, n) => {
523
- const i = f(l, n);
449
+ localePath: (l, a) => {
450
+ const i = f(l, a);
524
451
  return typeof i == "string" ? i : i.path || "/";
525
452
  },
526
453
  switchLocale: (l) => {
527
- if (e.locale.value = l, a) {
528
- const n = a.getCurrentPath(), i = f(n, l);
529
- a.push(typeof i == "string" ? { path: i } : { path: i.path || "/" });
454
+ if (e.locale.value = l, n) {
455
+ const a = n.getCurrentPath(), i = f(a, l);
456
+ n.push(typeof i == "string" ? { path: i } : { path: i.path || "/" });
530
457
  }
531
458
  },
532
459
  // Translation methods (delegate to instance)
@@ -549,111 +476,212 @@ function re(t) {
549
476
  clearCache: e.clearCache.bind(e)
550
477
  };
551
478
  }
552
- function ue(t = {}) {
553
- const {
554
- addDirAttribute: e = !0,
555
- identifierAttribute: a = "id",
556
- addSeoAttributes: o = !0,
557
- baseUrl: c = "/"
558
- } = t, { getLocale: r, getLocales: u, localeRoute: f } = re(), l = S(D, void 0), n = O({
479
+ function ce(t = {}) {
480
+ const { addDirAttribute: e = !0, identifierAttribute: n = "id", addSeoAttributes: r = !0, baseUrl: c = "/" } = t, { getLocale: o, getLocales: u, localeRoute: f } = ne(), l = S(j, void 0), a = G({
559
481
  htmlAttrs: {},
560
482
  link: [],
561
483
  meta: []
562
484
  });
563
485
  function i(p, k) {
564
- const w = new URL(p, "http://localhost"), R = new URLSearchParams(w.search), I = {};
486
+ const w = new URL(p, "http://localhost"), C = new URLSearchParams(w.search), I = {};
565
487
  for (const L of k)
566
- R.has(L) && (I[L] = R.get(L));
567
- const j = new URLSearchParams(I);
568
- return j.toString() ? `${w.pathname}?${j.toString()}` : w.pathname;
488
+ C.has(L) && (I[L] = C.get(L));
489
+ const T = new URLSearchParams(I);
490
+ return T.toString() ? `${w.pathname}?${T.toString()}` : w.pathname;
569
491
  }
570
492
  function d(p = []) {
571
493
  if (!l) {
572
- n.value = { htmlAttrs: {}, link: [], meta: [] };
494
+ a.value = { htmlAttrs: {}, link: [], meta: [] };
573
495
  return;
574
496
  }
575
- const k = r(), w = u(), R = w.find((m) => m.code === k);
576
- if (!R)
497
+ const k = o(), w = u(), C = w.find((m) => m.code === k);
498
+ if (!C)
577
499
  return;
578
- const I = R.iso || k, j = R.dir || "auto";
500
+ const I = C.iso || k, T = C.dir || "auto";
579
501
  let L = l.getCurrentPath();
580
502
  L.startsWith("/") || (L = `/${L}`);
581
- const K = L.split("/").filter(Boolean), N = w.find((m) => K[0] === m.code);
582
- let _ = L, b;
583
- N ? (_ = L.slice(N.code.length + 1) || "/", b = i(_, p)) : b = i(L, p);
584
- const s = `${typeof c == "function" ? c() : c}${b.startsWith("/") ? "" : "/"}${b}`;
585
- if (n.value = {
503
+ const W = L.split("/").filter(Boolean), _ = w.find((m) => W[0] === m.code);
504
+ let A = L, v;
505
+ _ ? (A = L.slice(_.code.length + 1) || "/", v = i(A, p)) : v = i(L, p);
506
+ const s = `${typeof c == "function" ? c() : c}${v.startsWith("/") ? "" : "/"}${v}`;
507
+ if (a.value = {
586
508
  htmlAttrs: {
587
509
  lang: I,
588
- ...e ? { dir: j } : {}
510
+ ...e ? { dir: T } : {}
589
511
  },
590
512
  link: [],
591
513
  meta: []
592
- }, !o)
514
+ }, !r)
593
515
  return;
594
- const y = w, v = {
595
- [a]: "i18n-og",
516
+ const y = w, b = {
517
+ [n]: "i18n-og",
596
518
  property: "og:locale",
597
519
  content: I
598
520
  }, h = {
599
- [a]: "i18n-og-url",
521
+ [n]: "i18n-og-url",
600
522
  property: "og:url",
601
523
  content: s
602
524
  }, x = y.map((m) => ({
603
- [a]: `i18n-og-alt-${m.iso || m.code}`,
525
+ [n]: `i18n-og-alt-${m.iso || m.code}`,
604
526
  property: "og:locale:alternate",
605
527
  content: m.iso || m.code
606
528
  })), $ = {
607
- [a]: "i18n-can",
529
+ [n]: "i18n-can",
608
530
  rel: "canonical",
609
531
  href: s
610
- }, M = y.flatMap((m) => {
532
+ }, O = y.flatMap((m) => {
611
533
  if (!f || !l)
612
534
  return [];
613
- const U = l.getCurrentPath(), E = f(U, m.code), P = typeof E == "string" ? E : E?.path || "/";
535
+ const E = l.getCurrentPath(), M = f(E, m.code), P = typeof M == "string" ? M : M?.path || "/";
614
536
  if (!P)
615
537
  return [];
616
- let H;
617
- P.startsWith("http://") || P.startsWith("https://") ? H = P : H = `${typeof c == "function" ? c() : c}${P.startsWith("/") ? "" : "/"}${P}`;
618
- const G = [{
619
- [a]: `i18n-alternate-${m.code}`,
620
- rel: "alternate",
621
- href: H,
622
- hreflang: m.code
623
- }];
624
- return m.iso && m.iso !== m.code && G.push({
625
- [a]: `i18n-alternate-${m.iso}`,
538
+ let N;
539
+ P.startsWith("http://") || P.startsWith("https://") ? N = P : N = `${typeof c == "function" ? c() : c}${P.startsWith("/") ? "" : "/"}${P}`;
540
+ const V = [
541
+ {
542
+ [n]: `i18n-alternate-${m.code}`,
543
+ rel: "alternate",
544
+ href: N,
545
+ hreflang: m.code
546
+ }
547
+ ];
548
+ return m.iso && m.iso !== m.code && V.push({
549
+ [n]: `i18n-alternate-${m.iso}`,
626
550
  rel: "alternate",
627
- href: H,
551
+ href: N,
628
552
  hreflang: m.iso
629
- }), G;
553
+ }), V;
630
554
  });
631
- n.value.meta = [v, h, ...x], n.value.link = [$, ...M];
555
+ a.value.meta = [b, h, ...x], a.value.link = [$, ...O];
632
556
  }
633
557
  return {
634
- metaObject: n,
558
+ metaObject: a,
635
559
  updateMeta: d
636
560
  };
637
561
  }
638
- function fe(t, e, a) {
639
- const o = e.map((r) => r.code), c = (r, u) => {
640
- const l = (typeof r == "string" ? r : r.path || "/").split("/").filter(Boolean);
641
- l.length > 0 && o.includes(l[0]) && l.shift();
642
- const n = "/" + l.join("/");
643
- return u === a ? n : `/${u}${n === "/" ? "" : n}`;
562
+ class ae extends J {
563
+ constructor(e) {
564
+ const n = {
565
+ translations: /* @__PURE__ */ new Map()
566
+ };
567
+ if (super({
568
+ storage: n,
569
+ plural: e.plural,
570
+ missingWarn: e.missingWarn,
571
+ missingHandler: e.missingHandler
572
+ }), this.listeners = /* @__PURE__ */ new Set(), this.storage = n, this._locale = U(e.locale), this._fallbackLocale = U(e.fallbackLocale || e.locale), this._currentRoute = U("general"), this._revision = U(0), e.messages)
573
+ for (const [r, c] of Object.entries(e.messages))
574
+ this.helper.loadTranslations(r, c);
575
+ }
576
+ get locale() {
577
+ return this._locale;
578
+ }
579
+ set locale(e) {
580
+ typeof e == "string" ? this._locale.value = e : this._locale = e;
581
+ }
582
+ get fallbackLocale() {
583
+ return this._fallbackLocale;
584
+ }
585
+ set fallbackLocale(e) {
586
+ typeof e == "string" ? this._fallbackLocale.value = e : this._fallbackLocale = e;
587
+ }
588
+ get currentRoute() {
589
+ return this._currentRoute;
590
+ }
591
+ setRoute(e) {
592
+ this._currentRoute.value = e;
593
+ }
594
+ getLocale() {
595
+ return this._locale.value;
596
+ }
597
+ getFallbackLocale() {
598
+ return this._fallbackLocale.value;
599
+ }
600
+ getRoute() {
601
+ return this._currentRoute.value;
602
+ }
603
+ addTranslations(e, n, r = !0) {
604
+ super.loadTranslationsCore(e, n, r), this._revision.value++, this.notifyListeners();
605
+ }
606
+ addRouteTranslations(e, n, r, c = !0) {
607
+ super.loadRouteTranslationsCore(e, n, r, c), this._revision.value++, this.notifyListeners();
608
+ }
609
+ mergeTranslations(e, n, r) {
610
+ this.helper.mergeTranslation(e, n, r, !0), this._revision.value++, this.notifyListeners();
611
+ }
612
+ mergeGlobalTranslations(e, n) {
613
+ this.helper.mergeGlobalTranslation(e, n, !0), this._revision.value++, this.notifyListeners();
614
+ }
615
+ clearCache() {
616
+ super.clearCache(), this._revision.value++, this.notifyListeners();
617
+ }
618
+ subscribeToChanges(e) {
619
+ return this.listeners.add(e), () => this.listeners.delete(e);
620
+ }
621
+ notifyListeners() {
622
+ this.listeners.forEach((e) => e());
623
+ }
624
+ getAllTranslations() {
625
+ const e = {};
626
+ for (const [n, r] of this.storage.translations)
627
+ if (!n.includes(":"))
628
+ e[n] = r;
629
+ else {
630
+ const c = n.split(":")[0];
631
+ c && (e[c] || (e[c] = {}), Object.assign(e[c], r));
632
+ }
633
+ return e;
634
+ }
635
+ getStorage() {
636
+ return this.storage;
637
+ }
638
+ getGeneralCache() {
639
+ const e = {};
640
+ for (const [n, r] of this.storage.translations)
641
+ n.includes(":") || (e[n] = r);
642
+ return e;
643
+ }
644
+ getRouteCache() {
645
+ const e = {};
646
+ for (const [n, r] of this.storage.translations)
647
+ n.includes(":") && (e[n] = r);
648
+ return e;
649
+ }
650
+ }
651
+ function se(t) {
652
+ const { routingStrategy: e, locales: n, defaultLocale: r, ...c } = t, o = new ae(c);
653
+ let u = null, f = e || null;
654
+ return {
655
+ global: o,
656
+ // Доступ к инстансу вне компонентов
657
+ setRoutingStrategy: (a) => {
658
+ f = a, u && u.provide(j, a);
659
+ },
660
+ // Метод для установки адаптера после создания
661
+ install(a) {
662
+ u = a, a.provide(D, o), f && a.provide(j, f), n && a.provide(K, n), r && a.provide(B, r), a.config.globalProperties.$t = (i, d, p, k) => o.t(i, d, p, k), a.config.globalProperties.$ts = (i, d, p, k) => o.ts(i, d, p, k), a.config.globalProperties.$tc = (i, d, p) => o.tc(i, d, p), a.config.globalProperties.$tn = (i, d) => o.tn(i, d), a.config.globalProperties.$td = (i, d) => o.td(i, d), a.config.globalProperties.$tdr = (i, d) => o.tdr(i, d), a.config.globalProperties.$has = (i, d) => o.has(i, d), a.config.globalProperties.$i18n = o, a.component("I18nT", te), a.component("I18nLink", Y), a.component("I18nGroup", X), a.component("I18nSwitcher", ee);
663
+ }
664
+ };
665
+ }
666
+ function ue(t, e, n) {
667
+ const r = e.map((o) => o.code), c = (o, u) => {
668
+ const l = (typeof o == "string" ? o : o.path || "/").split("/").filter(Boolean), a = l[0];
669
+ a !== void 0 && r.includes(a) && l.shift();
670
+ const i = `/${l.join("/")}`;
671
+ return u === n ? i : `/${u}${i === "/" ? "" : i}`;
644
672
  };
645
673
  return {
646
- linkComponent: X,
674
+ linkComponent: Q,
647
675
  getCurrentPath: () => t.currentRoute.value.path,
648
- push: (r) => {
649
- t.push(r.path).catch(() => {
676
+ push: (o) => {
677
+ t.push(o.path).catch(() => {
650
678
  });
651
679
  },
652
- replace: (r) => {
653
- t.replace(r.path).catch(() => {
680
+ replace: (o) => {
681
+ t.replace(o.path).catch(() => {
654
682
  });
655
683
  },
656
- resolvePath: (r, u) => c(r, u),
684
+ resolvePath: (o, u) => c(o, u),
657
685
  getRoute: () => ({
658
686
  fullPath: t.currentRoute.value.fullPath,
659
687
  query: t.currentRoute.value.query
@@ -661,19 +689,19 @@ function fe(t, e, a) {
661
689
  };
662
690
  }
663
691
  export {
664
- ge as FormatService,
665
- z as I18nDefaultLocaleKey,
666
- ne as I18nGroup,
667
- A as I18nInjectionKey,
668
- te as I18nLink,
669
- B as I18nLocalesKey,
670
- ae as I18nSwitcher,
671
- ee as I18nT,
672
- Y as VueI18n,
692
+ he as FormatService,
693
+ B as I18nDefaultLocaleKey,
694
+ X as I18nGroup,
695
+ D as I18nInjectionKey,
696
+ Y as I18nLink,
697
+ K as I18nLocalesKey,
698
+ ee as I18nSwitcher,
699
+ te as I18nT,
700
+ ae as VueI18n,
673
701
  se as createI18n,
674
- fe as createVueRouterAdapter,
675
- ye as defaultPlural,
676
- me as interpolate,
677
- re as useI18n,
678
- ue as useLocaleHead
702
+ ue as createVueRouterAdapter,
703
+ ge as defaultPlural,
704
+ ye as interpolate,
705
+ ne as useI18n,
706
+ ce as useLocaleHead
679
707
  };
@@ -1,6 +1,6 @@
1
+ import { Locale } from '@i18n-micro/types';
1
2
  import { InjectionKey } from 'vue';
2
3
  import { VueI18n } from './composer';
3
- import { Locale } from '@i18n-micro/types';
4
4
  import { I18nRoutingStrategy } from './router/types';
5
5
  export declare const I18nInjectionKey: InjectionKey<VueI18n>;
6
6
  export declare const I18nLocalesKey: InjectionKey<Locale[]>;
package/dist/plugin.d.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { Locale } from '@i18n-micro/types';
1
2
  import { Plugin } from 'vue';
2
3
  import { VueI18n, VueI18nOptions } from './composer';
3
- import { Locale } from '@i18n-micro/types';
4
4
  import { I18nRoutingStrategy } from './router/types';
5
5
  export interface CreateI18nOptions extends VueI18nOptions {
6
6
  routingStrategy?: I18nRoutingStrategy;
@@ -1,6 +1,6 @@
1
+ import { Locale } from '@i18n-micro/types';
1
2
  import { Router } from 'vue-router';
2
3
  import { I18nRoutingStrategy } from './types';
3
- import { Locale } from '@i18n-micro/types';
4
4
  /**
5
5
  * Factory for Vue Router adapter
6
6
  * Implements routing utilities for Vue Router
@@ -1,5 +1,5 @@
1
- import { VueI18n } from './composer';
2
1
  import { Locale } from '@i18n-micro/types';
2
+ import { VueI18n } from './composer';
3
3
  export interface UseI18nOptions {
4
4
  locales?: Locale[];
5
5
  defaultLocale?: string;
@@ -9,9 +9,6 @@ declare module '@vue/runtime-core' {
9
9
  $td: (value: Date | number | string, options?: Intl.DateTimeFormatOptions) => string
10
10
  $tdr: (value: Date | number | string, options?: Intl.RelativeTimeFormatOptions) => string
11
11
  $has: (key: TranslationKey, routeName?: string) => boolean
12
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
12
  $i18n: any
14
13
  }
15
14
  }
16
-
17
- export {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@i18n-micro/vue",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -19,12 +19,12 @@
19
19
  "access": "public"
20
20
  },
21
21
  "dependencies": {
22
- "@i18n-micro/types": "1.0.16",
23
- "@i18n-micro/core": "1.0.28"
22
+ "@i18n-micro/core": "1.1.2",
23
+ "@i18n-micro/types": "1.1.1"
24
24
  },
25
25
  "peerDependencies": {
26
- "vue": "^3.3.0",
27
- "vue-router": "^4.0.0"
26
+ "vue": "^3.5.25",
27
+ "vue-router": "^4.6.3"
28
28
  },
29
29
  "peerDependenciesMeta": {
30
30
  "vue-router": {
@@ -34,7 +34,7 @@
34
34
  "devDependencies": {
35
35
  "vue": "^3.5.25",
36
36
  "vue-router": "^4.6.3",
37
- "vite": "^7.2.7",
37
+ "vite": "^7.3.1",
38
38
  "vite-plugin-dts": "^4.5.4",
39
39
  "jest": "^29.7.0",
40
40
  "ts-jest": "^29.4.6",