@sveltekit-i18n/base 1.0.0-rc.2 → 1.0.0-rc.6

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/README.md CHANGED
@@ -3,9 +3,9 @@
3
3
  [![npm version](https://badge.fury.io/js/@sveltekit-i18n%2Fbase.svg)](https://badge.fury.io/js/@sveltekit-i18n%2Fbase) ![](https://github.com/sveltekit-i18n/base/workflows/Tests/badge.svg)
4
4
 
5
5
  # @sveltekit-i18n/base
6
- This repository contains a base functionality of [sveltekit-i18n](https://github.com/sveltekit-i18n/lib) and provides support for external message parsers.
6
+ This repository contains the base functionality of [sveltekit-i18n](https://github.com/sveltekit-i18n/lib) and provides support for external message parsers.
7
7
 
8
- __IMPORTANT: THIS PACKAGE IS STILL IN DEVELOPMENT - API MAY VARY UNTIL 1.0.0__
8
+ __IMPORTANT: THIS PACKAGE IS STILL UNDER DEVELOPMENT - API MAY VARY UNTIL 1.0.0__
9
9
 
10
10
  ## Key features
11
11
 
@@ -23,11 +23,13 @@ __IMPORTANT: THIS PACKAGE IS STILL IN DEVELOPMENT - API MAY VARY UNTIL 1.0.0__
23
23
  Setup `translations.js` in your lib folder...
24
24
  ```javascript
25
25
  import i18n from '@sveltekit-i18n/base';
26
- import parser from '@sveltekit-i18n/parser-default'; // use your preferred parser (or create your own)
26
+ // use your preferred parser (or create your own)
27
+ import parser from '@sveltekit-i18n/parser-default';
28
+ // import parser from '@sveltekit-i18n/parser-icu';
27
29
 
28
- /** @namespace {import('@sveltekit-i18n/parser-default').Config} */
30
+ /** @type {import('@sveltekit-i18n/parser-default').Config} */
29
31
  const config = ({
30
- parser: parser({}),
32
+ parser: parser({/* Parser options */}),
31
33
  loaders: [
32
34
  {
33
35
  locale: 'en',
@@ -94,7 +96,7 @@ export const { t, locale, locales, loading, loadTranslations } = new i18n(config
94
96
 
95
97
  const initLocale = locale.get() || defaultLocale; // set default if no locale already set
96
98
 
97
- await loadTranslations(initLocale, pathname);
99
+ await loadTranslations(initLocale, pathname); // keep this just before the `return`
98
100
 
99
101
  return {};
100
102
  }
@@ -111,7 +113,6 @@ export const { t, locale, locales, loading, loadTranslations } = new i18n(config
111
113
  </script>
112
114
 
113
115
  <div>
114
- <!-- you can use `placeholders` and `modifiers` in your definitions (see docs) -->
115
116
  <h2>{$t('common.page', { pageName })}</h2>
116
117
  <p>{$t('home.content')}</p>
117
118
  </div>
@@ -119,6 +120,7 @@ export const { t, locale, locales, loading, loadTranslations } = new i18n(config
119
120
 
120
121
 
121
122
  ## More info
123
+ [Parsers](https://github.com/sveltekit-i18n/parsers)\
122
124
  [Docs](https://github.com/sveltekit-i18n/base/tree/master/docs/README.md)\
123
125
  [Examples](https://github.com/sveltekit-i18n/lib/tree/master/examples#parsers)\
124
126
  [Changelog](https://github.com/sveltekit-i18n/base/releases)
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- var m=Object.defineProperty,j=Object.defineProperties,K=Object.getOwnPropertyDescriptor,N=Object.getOwnPropertyDescriptors,O=Object.getOwnPropertyNames,T=Object.getOwnPropertySymbols;var w=Object.prototype.hasOwnProperty,C=Object.prototype.propertyIsEnumerable;var R=(r,t,s)=>t in r?m(r,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):r[t]=s,l=(r,t)=>{for(var s in t||(t={}))w.call(t,s)&&R(r,s,t[s]);if(T)for(var s of T(t))C.call(t,s)&&R(r,s,t[s]);return r},c=(r,t)=>j(r,N(t)),W=r=>m(r,"__esModule",{value:!0});var y=(r,t)=>{var s={};for(var e in r)w.call(r,e)&&t.indexOf(e)<0&&(s[e]=r[e]);if(r!=null&&T)for(var e of T(r))t.indexOf(e)<0&&C.call(r,e)&&(s[e]=r[e]);return s};var k=(r,t)=>{for(var s in t)m(r,s,{get:t[s],enumerable:!0})},D=(r,t,s,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of O(t))!w.call(r,a)&&(s||a!=="default")&&m(r,a,{get:()=>t[a],enumerable:!(e=K(t,a))||e.enumerable});return r};var z=(r=>(t,s)=>r&&r.get(t)||(s=D(W({}),t,1),r&&r.set(t,s),s))(typeof WeakMap!="undefined"?new WeakMap:0);var A={};k(A,{default:()=>F});var i=require("svelte/store");var P=(r,t)=>Object.keys(r||{}).reduce((s,e)=>{let a=r[e],o=t?`${t}.${e}`:`${e}`;return a&&typeof a=="object"?l(l({},s),P(a,o)):c(l({},s),{[o]:a})},{}),$=async r=>{try{return(await Promise.all(r.map(a=>{var o=a,{loader:s}=o,e=y(o,["loader"]);return new Promise(async n=>{let h;try{h=await s()}catch(p){console.error(`Failed to load translation. Verify your '${e.locale}' > '${e.key}' Loader.`),console.error(p)}n(c(l({loader:s},e),{data:h}))})}))).reduce((s,{key:e,data:a,locale:o})=>a?c(l({},s),{[o]:P(c(l({},s[o]||{}),{[e]:a}))}):s,{})}catch(t){console.error(t)}return{}},x=r=>t=>{try{if(typeof t=="string")return t===r;if(typeof t=="object")return t.test(r)}catch{throw new Error("Invalid route config!")}return!1};var F=class{constructor(t){this.loadedKeys={};this.currentRoute=(0,i.writable)();this.config=(0,i.writable)();this.isLoading=(0,i.writable)(!1);this.promises=[];this.loading={subscribe:this.isLoading.subscribe,toPromise:()=>Promise.all(this.promises),get:()=>(0,i.get)(this.isLoading)};this.privateTranslations=(0,i.writable)({});this.translations={subscribe:this.privateTranslations.subscribe,get:()=>(0,i.get)(this.translations)};this.locales=c(l({},(0,i.derived)([this.config,this.privateTranslations],([t,s])=>{if(!t)return[];let{loaders:e=[]}=t,a=e.map(({locale:n})=>`${n}`.toLowerCase()),o=Object.keys(s).map(n=>`${n}`.toLowerCase());return[...new Set([...a,...o])]},[])),{get:()=>(0,i.get)(this.locales)});this.internalLocale=(0,i.writable)();this.locale=c(l({set:this.internalLocale.set,update:this.internalLocale.update},(0,i.derived)(this.internalLocale,(t,s)=>{let e=t&&`${t}`.toLowerCase(),a=this.getLocale(e);a&&a!==this.locale.get()&&s(a)})),{get:()=>(0,i.get)(this.locale)});this.loaderTrigger=(0,i.derived)([this.internalLocale,this.currentRoute],([t,s],e)=>{t!==void 0&&s!==void 0&&e([t,s])},[]);this.initialized=(0,i.derived)([this.locale,this.currentRoute,this.privateTranslations],([t,s,e],a)=>{(0,i.get)(this.initialized)||a(t!==void 0&&s!==void 0&&!!Object.keys(e).length)});this.translation=(0,i.derived)([this.privateTranslations,this.locale,this.isLoading],([t,s,e],a)=>{let o=t[s];o&&Object.keys(o).length&&!e&&a(o)},{});this.translate=({parser:t,key:s,params:e,translations:a,locale:o,fallbackLocale:n})=>{if(!s)throw new Error("No key provided to $t()");if(!o)throw new Error("No locale set!");let h=(a[o]||{})[s];return n&&h===void 0&&(h=(a[n]||{})[s]),t.parse(h,e,o,s)};this.t=c(l({},(0,i.derived)([this.config,this.translation],([{parser:t,fallbackLocale:s}])=>(e,...a)=>this.translate({parser:t,key:e,params:a,translations:this.translations.get(),locale:this.locale.get(),fallbackLocale:s}))),{get:(t,...s)=>(0,i.get)(this.t)(t,...s)});this.l=c(l({},(0,i.derived)([this.config,this.translations],([{parser:t,fallbackLocale:s},e])=>(a,o,...n)=>this.translate({parser:t,key:o,params:n,translations:e,locale:a,fallbackLocale:s}))),{get:(t,s,...e)=>(0,i.get)(this.l)(t,s,...e)});this.getLocale=t=>t?`${this.locales.get().find(a=>`${a}`.toLowerCase()===`${t}`.toLowerCase())||""}`.toLowerCase():"";this.setLocale=async t=>{!t||(this.internalLocale.set(t),await this.loading.toPromise())};this.setRoute=async t=>{t!==(0,i.get)(this.currentRoute)&&this.currentRoute.set(t),await this.loading.toPromise()};this.loadConfig=async t=>{await this.configLoader(t)};this.addTranslations=(t,s)=>{if(!t)return;let e=Object.keys(t||{});this.privateTranslations.update(a=>e.reduce((o,n)=>c(l({},o),{[n]:l(l({},o[n]||{}),P(t[n]))}),a)),e.forEach(a=>{let o=Object.keys(t[a]).map(n=>`${n}`.split(".")[0]);s&&(o=s[a]),this.loadedKeys[a]=Array.from(new Set([...this.loadedKeys[a]||[],...o||[]]))})};this.getTranslationProps=async(t=this.locale.get(),s=(0,i.get)(this.currentRoute))=>{let e=(0,i.get)(this.config);if(!e||!t)return[];let a=this.translations.get(),{loaders:o,fallbackLocale:n=""}=e||{},h=`${t}`.toLowerCase(),p=n&&`${n}`.toLowerCase(),S=a[h],E=a[p],b=(o||[]).map(v=>{var g=v,{locale:d}=g,u=y(g,["locale"]);return c(l({},u),{locale:`${d}`.toLowerCase()})}).filter(({routes:d})=>!d||(d||[]).some(x(s))).filter(({key:d,locale:u})=>u===h&&(!S||!(this.loadedKeys[h]||[]).includes(d))||n&&u===p&&(!E||!(this.loadedKeys[p]||[]).includes(d)));if(b.length){this.isLoading.set(!0);let d=await $(b);this.isLoading.set(!1);let u=Object.keys(d).reduce((g,f)=>c(l({},g),{[f]:Object.keys(d[f])}),{}),v=b.filter(({key:g,locale:f})=>(u[f]||[]).some(L=>`${L}`.startsWith(g))).reduce((g,{key:f,locale:L})=>c(l({},g),{[L]:[...g[L]||[],f]}),{});return[d,v]}return[]};this.translationLoader=async t=>{this.promises.push(new Promise(async s=>{let e=await this.getTranslationProps(t);e.length&&this.addTranslations(...e),s()})),await this.loading.toPromise()};this.loadTranslations=async(t,s=(0,i.get)(this.currentRoute)||"")=>{!t||(this.setRoute(s),this.setLocale(t),await this.loading.toPromise())};t&&this.loadConfig(t),this.loaderTrigger.subscribe(()=>this.translationLoader())}async configLoader(t){if(!t)throw new Error("No config!");this.config.set(t);let{initLocale:s="",translations:e}=t;e&&this.addTranslations(e),await this.loadTranslations(s)}};module.exports=z(A);0&&(module.exports={});
1
+ var m=Object.defineProperty,O=Object.defineProperties,$=Object.getOwnPropertyDescriptor,A=Object.getOwnPropertyDescriptors,W=Object.getOwnPropertyNames,T=Object.getOwnPropertySymbols;var x=Object.prototype.hasOwnProperty,K=Object.prototype.propertyIsEnumerable;var F=(s,t,e)=>t in s?m(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e,l=(s,t)=>{for(var e in t||(t={}))x.call(t,e)&&F(s,e,t[e]);if(T)for(var e of T(t))K.call(t,e)&&F(s,e,t[e]);return s},c=(s,t)=>O(s,A(t)),D=s=>m(s,"__esModule",{value:!0});var L=(s,t)=>{var e={};for(var a in s)x.call(s,a)&&t.indexOf(a)<0&&(e[a]=s[a]);if(s!=null&&T)for(var a of T(s))t.indexOf(a)<0&&K.call(s,a)&&(e[a]=s[a]);return e};var I=(s,t)=>{for(var e in t)m(s,e,{get:t[e],enumerable:!0})},V=(s,t,e,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of W(t))!x.call(s,r)&&(e||r!=="default")&&m(s,r,{get:()=>t[r],enumerable:!(a=$(t,r))||a.enumerable});return s};var M=(s=>(t,e)=>s&&s.get(t)||(e=V(D({}),t,1),s&&s.set(t,e),e))(typeof WeakMap!="undefined"?new WeakMap:0);var B={};I(B,{default:()=>R});var o=require("svelte/store");var h=s=>{if(!s||!s.length)return[];let t=s;return Array.isArray(t)||(t=[t]),t.filter(e=>!!e).map(e=>{let a=`${e}`.toLowerCase();try{[a]=Intl.Collator.supportedLocalesOf(e)}catch{console.warn(`Non-standard locale provided: '${s}' => '${t}'. Check your 'translations' and 'loaders' in i18n config...`)}return a})},P=(s,t)=>Object.keys(s||{}).reduce((e,a)=>{let r=s[a],i=t?`${t}.${a}`:`${a}`;return r&&typeof r=="object"?l(l({},e),P(r,i)):c(l({},e),{[i]:r})},{}),N=async s=>{try{return(await Promise.all(s.map(r=>{var i=r,{loader:e}=i,a=L(i,["loader"]);return new Promise(async n=>{let f;try{f=await e()}catch(b){console.error(`Failed to load translation. Verify your '${a.locale}' > '${a.key}' Loader.`),console.error(b)}n(c(l({loader:e},a),{data:f}))})}))).reduce((e,{key:a,data:r,locale:i})=>{if(!r)return e;let n=h(i)[0];return c(l({},e),{[n]:P(c(l({},e[n]||{}),{[a]:r}))})},{})}catch(t){console.error(t)}return{}},j=s=>t=>{try{if(typeof t=="string")return t===s;if(typeof t=="object")return t.test(s)}catch{throw new Error("Invalid route config!")}return!1};var z=1e3*60*60*24,R=class{constructor(t){this.cachedAt=0;this.loadedKeys={};this.currentRoute=(0,o.writable)();this.config=(0,o.writable)();this.isLoading=(0,o.writable)(!1);this.promises=[];this.loading={subscribe:this.isLoading.subscribe,toPromise:()=>Promise.all(this.promises),get:()=>(0,o.get)(this.isLoading)};this.privateTranslations=(0,o.writable)({});this.translations={subscribe:this.privateTranslations.subscribe,get:()=>(0,o.get)(this.translations)};this.locales=c(l({},(0,o.derived)([this.config,this.privateTranslations],([t,e])=>{if(!t)return[];let{loaders:a=[]}=t,r=a.map(({locale:n})=>h(n)[0]),i=Object.keys(e).map(n=>h(n)[0]);return[...new Set([...r,...i])]},[])),{get:()=>(0,o.get)(this.locales)});this.internalLocale=(0,o.writable)();this.locale=c(l({set:this.internalLocale.set,update:this.internalLocale.update},(0,o.derived)(this.internalLocale,(t,e)=>{let a=this.getLocale(t);a&&a!==this.locale.get()&&e(a)})),{get:()=>(0,o.get)(this.locale)});this.loaderTrigger=(0,o.derived)([this.internalLocale,this.currentRoute],([t,e],a)=>{t!==void 0&&e!==void 0&&a([t,e])},[]);this.initialized=(0,o.derived)([this.locale,this.currentRoute,this.privateTranslations],([t,e,a],r)=>{(0,o.get)(this.initialized)||r(t!==void 0&&e!==void 0&&!!Object.keys(a).length)});this.translation=(0,o.derived)([this.privateTranslations,this.locale,this.isLoading],([t,e,a],r)=>{let i=t[e];i&&Object.keys(i).length&&!a&&r(i)},{});this.translate=({parser:t,key:e,params:a,translations:r,locale:i,fallbackLocale:n})=>{if(!(e&&i))return console.warn("No translation key or locale provided. Skipping translation..."),"";let f=(r[i]||{})[e];return n&&f===void 0&&(f=(r[n]||{})[e]),t.parse(f,a,i,e)};this.t=c(l({},(0,o.derived)([this.config,this.translation],([{parser:t,fallbackLocale:e}])=>(a,...r)=>this.translate({parser:t,key:a,params:r,translations:this.translations.get(),locale:this.locale.get(),fallbackLocale:e}))),{get:(t,...e)=>(0,o.get)(this.t)(t,...e)});this.l=c(l({},(0,o.derived)([this.config,this.translations],([{parser:t,fallbackLocale:e},a])=>(r,i,...n)=>this.translate({parser:t,key:i,params:n,translations:a,locale:r,fallbackLocale:e}))),{get:(t,e,...a)=>(0,o.get)(this.l)(t,e,...a)});this.getLocale=t=>{if(!t)return"";let a=this.locales.get().find(r=>r===h(t)[0])||"";return`${h(a)[0]}`};this.setLocale=async t=>{!t||(this.internalLocale.set(`${h(t)[0]}`),await this.loading.toPromise())};this.setRoute=async t=>{t!==(0,o.get)(this.currentRoute)&&this.currentRoute.set(t),await this.loading.toPromise()};this.loadConfig=async t=>{await this.configLoader(t)};this.getTranslationProps=async(t=this.locale.get(),e=(0,o.get)(this.currentRoute))=>{let a=(0,o.get)(this.config);if(!a||!t)return[];let r=this.translations.get(),{loaders:i,fallbackLocale:n="",cache:f=z}=a||{},b=Number.isNaN(+f)?z:+f;this.cachedAt?Date.now()>b+this.cachedAt&&(this.loadedKeys={},this.cachedAt=0):this.cachedAt=Date.now();let[v,w]=h([t,n]),k=r[v],E=r[w],C=(i||[]).map(S=>{var u=S,{locale:d}=u,g=L(u,["locale"]);return c(l({},g),{locale:h(d)[0]})}).filter(({routes:d})=>!d||(d||[]).some(j(e))).filter(({key:d,locale:g})=>g===v&&(!k||!(this.loadedKeys[v]||[]).includes(d))||n&&g===w&&(!E||!(this.loadedKeys[w]||[]).includes(d)));if(C.length){this.isLoading.set(!0);let d=await N(C);this.isLoading.set(!1);let g=Object.keys(d).reduce((u,p)=>c(l({},u),{[p]:Object.keys(d[p])}),{}),S=C.filter(({key:u,locale:p})=>(g[p]||[]).some(y=>`${y}`.startsWith(u))).reduce((u,{key:p,locale:y})=>c(l({},u),{[y]:[...u[y]||[],p]}),{});return[d,S]}return[]};this.addTranslations=(t,e)=>{if(!t)return;let a=Object.keys(t||{});this.privateTranslations.update(r=>a.reduce((i,n)=>c(l({},i),{[n]:l(l({},i[n]||{}),P(t[n]))}),r)),a.forEach(r=>{let i=Object.keys(t[r]).map(n=>`${n}`.split(".")[0]);e&&(i=e[r]),this.loadedKeys[r]=Array.from(new Set([...this.loadedKeys[r]||[],...i||[]]))})};this.translationLoader=async t=>{this.promises.push(new Promise(async e=>{let a=await this.getTranslationProps(t);a.length&&this.addTranslations(...a),e()})),await this.loading.toPromise()};this.loadTranslations=async(t,e=(0,o.get)(this.currentRoute)||"")=>{!t||(this.setRoute(e),this.setLocale(t),await this.loading.toPromise())};t&&this.loadConfig(t),this.loaderTrigger.subscribe(([e])=>this.translationLoader(e))}async configLoader(t){if(!t)throw new Error("No config provided!");let n=t,{initLocale:e,fallbackLocale:a,translations:r}=n,i=L(n,["initLocale","fallbackLocale","translations"]);e=h(e)[0],a=h(a)[0],this.config.set(l({initLocale:e,fallbackLocale:a,translations:r},i)),r&&this.addTranslations(r),await this.loadTranslations(e)}};module.exports=M(B);0&&(module.exports={});
package/dist/index.d.ts CHANGED
@@ -8,37 +8,39 @@ declare type LoadingStore = Readable<boolean> & {
8
8
  get: () => boolean;
9
9
  };
10
10
  declare module DotNotation {
11
- type Input = any;
11
+ type Input = Translations.Input;
12
12
  type Output<V = any, K extends keyof V = keyof V> = {
13
13
  [P in K]?: V[K];
14
- } | null;
14
+ };
15
15
  type T = <I = Input>(input: I, parentKey?: string) => Output<I>;
16
16
  }
17
17
  declare module Config {
18
- type Loaders = Loader.LoaderModule[] | undefined;
19
- type Translations = Translations.T | undefined;
20
- type Locale = string;
18
+ type Loader = Loader.LoaderModule;
19
+ type Translations = Translations.T;
20
+ type Locale = Translations.Locales[number];
21
21
  type InitLocale = Locale | undefined;
22
22
  type FallbackLocale = Locale | undefined;
23
- type T<P extends Parser.Params = any> = {
24
- loaders?: Loaders;
25
- translations?: Translations;
23
+ type T<P extends Parser.Params = Parser.Params> = {
24
+ loaders?: Loader[];
25
+ translations?: Translations.T;
26
26
  initLocale?: InitLocale;
27
27
  fallbackLocale?: FallbackLocale;
28
28
  parser: Parser.T<P>;
29
+ cache?: number;
29
30
  };
30
31
  }
31
32
  declare module Loader {
32
33
  type Key = string;
33
34
  type Locale = Config.Locale;
34
35
  type Route = string | RegExp;
36
+ type IndexedKeys = Translations.LocaleIndexed<Key[]>;
35
37
  type LoaderModule = {
36
38
  key: Key;
37
39
  locale: Locale;
38
40
  routes?: Route[];
39
41
  loader: T;
40
42
  };
41
- type T = () => Promise<Record<any, any>>;
43
+ type T = () => Promise<Translations.Input>;
42
44
  }
43
45
  declare module Parser {
44
46
  type Value = any;
@@ -46,32 +48,37 @@ declare module Parser {
46
48
  type Locale = Config.Locale;
47
49
  type Key = Loader.Key;
48
50
  type Output = any;
49
- type Parse<P extends Parser.Params = any> = (value: Value, params: P, locale: Locale, key: Key) => Output;
50
- type ParserFactory<ParserConfig = any, P extends Parser.Params = any> = (config?: ParserConfig) => Parser.T<P>;
51
- type T<P extends Parser.Params = any> = {
51
+ type Parse<P extends Parser.Params = Parser.Params> = (value: Value, params: P, locale: Locale, key: Key) => Output;
52
+ type T<P extends Parser.Params = Parser.Params> = {
52
53
  parse: Parse<P>;
53
54
  };
54
55
  }
55
56
  declare module Translations {
56
- type SerializedTranslations = T<DotNotation.Output>;
57
+ type Locales = string[];
58
+ type SerializedTranslations = LocaleIndexed<DotNotation.Output>;
57
59
  type FetchTranslations = (loaders: Loader.LoaderModule[]) => Promise<SerializedTranslations>;
58
- type TranslationFunction<P extends Parser.Params = any> = (key: string, ...restParams: P) => string;
59
- type LocalTranslationFunction<P extends Parser.Params = any> = (locale: string, key: string, ...restParams: P) => string;
60
- type Translate<P extends Parser.Params = any> = (props: {
60
+ type TranslationFunction<P extends Parser.Params = Parser.Params> = (key: string, ...restParams: P) => any;
61
+ type LocalTranslationFunction<P extends Parser.Params = Parser.Params> = (locale: Config.Locale, key: string, ...restParams: P) => any;
62
+ type Translate<P extends Parser.Params = Parser.Params> = (props: {
61
63
  parser: Parser.T<P>;
62
64
  key: string;
63
65
  params: P;
64
66
  translations: SerializedTranslations;
65
- locale: string;
67
+ locale: Locales[number];
66
68
  fallbackLocale?: string;
67
69
  }) => string;
68
- type T<T = any> = {
69
- [locale: string]: Record<string, T>;
70
+ type Input<V = any> = {
71
+ [K in any]: Input<V> | V;
72
+ };
73
+ type LocaleIndexed<V> = {
74
+ [locale in Locales[number]]: V;
70
75
  };
76
+ type T<V = any> = LocaleIndexed<Input<V>>;
71
77
  }
72
78
 
73
79
  declare class I18n<ParserParams extends Parser.Params = any> {
74
80
  constructor(config?: Config.T<ParserParams>);
81
+ private cachedAt;
75
82
  private loadedKeys;
76
83
  private currentRoute;
77
84
  private config;
@@ -80,9 +87,9 @@ declare class I18n<ParserParams extends Parser.Params = any> {
80
87
  loading: LoadingStore;
81
88
  private privateTranslations;
82
89
  translations: ExtendedStore<Translations.SerializedTranslations>;
83
- locales: ExtendedStore<string[]>;
90
+ locales: ExtendedStore<Config.Locale[]>;
84
91
  private internalLocale;
85
- locale: ExtendedStore<string, () => string, Writable<string>>;
92
+ locale: ExtendedStore<Config.Locale, () => Config.Locale, Writable<string>>;
86
93
  private loaderTrigger;
87
94
  initialized: Readable<boolean>;
88
95
  private translation;
@@ -94,11 +101,11 @@ declare class I18n<ParserParams extends Parser.Params = any> {
94
101
  setRoute: (route: string) => Promise<void>;
95
102
  configLoader(config: Config.T<ParserParams>): Promise<void>;
96
103
  loadConfig: (config: Config.T<ParserParams>) => Promise<void>;
97
- addTranslations: (translations?: Config.Translations, keys?: Record<string, string[]> | undefined) => void;
98
- getTranslationProps: ($locale?: string, $route?: string) => Promise<[Config.Translations, Record<string, string[]>] | [
104
+ getTranslationProps: ($locale?: string, $route?: string) => Promise<[Translations.SerializedTranslations, Loader.IndexedKeys] | [
99
105
  ]>;
106
+ addTranslations: (translations?: Translations.SerializedTranslations | undefined, keys?: Loader.IndexedKeys | undefined) => void;
100
107
  private translationLoader;
101
- loadTranslations: (locale: string, route?: string) => Promise<void>;
108
+ loadTranslations: (locale: Config.Locale, route?: string) => Promise<void>;
102
109
  }
103
110
 
104
111
  export { Config, Loader, Parser, Translations, I18n as default };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- var j=Object.defineProperty,K=Object.defineProperties;var N=Object.getOwnPropertyDescriptors;var y=Object.getOwnPropertySymbols;var C=Object.prototype.hasOwnProperty,$=Object.prototype.propertyIsEnumerable;var R=(o,t,s)=>t in o?j(o,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):o[t]=s,n=(o,t)=>{for(var s in t||(t={}))C.call(t,s)&&R(o,s,t[s]);if(y)for(var s of y(t))$.call(t,s)&&R(o,s,t[s]);return o},l=(o,t)=>K(o,N(t));var P=(o,t)=>{var s={};for(var e in o)C.call(o,e)&&t.indexOf(e)<0&&(s[e]=o[e]);if(o!=null&&y)for(var e of y(o))t.indexOf(e)<0&&$.call(o,e)&&(s[e]=o[e]);return s};import{derived as u,get as d,writable as T}from"svelte/store";var b=(o,t)=>Object.keys(o||{}).reduce((s,e)=>{let a=o[e],r=t?`${t}.${e}`:`${e}`;return a&&typeof a=="object"?n(n({},s),b(a,r)):l(n({},s),{[r]:a})},{}),x=async o=>{try{return(await Promise.all(o.map(a=>{var r=a,{loader:s}=r,e=P(r,["loader"]);return new Promise(async i=>{let h;try{h=await s()}catch(L){console.error(`Failed to load translation. Verify your '${e.locale}' > '${e.key}' Loader.`),console.error(L)}i(l(n({loader:s},e),{data:h}))})}))).reduce((s,{key:e,data:a,locale:r})=>a?l(n({},s),{[r]:b(l(n({},s[r]||{}),{[e]:a}))}):s,{})}catch(t){console.error(t)}return{}},F=o=>t=>{try{if(typeof t=="string")return t===o;if(typeof t=="object")return t.test(o)}catch{throw new Error("Invalid route config!")}return!1};var k=class{constructor(t){this.loadedKeys={};this.currentRoute=T();this.config=T();this.isLoading=T(!1);this.promises=[];this.loading={subscribe:this.isLoading.subscribe,toPromise:()=>Promise.all(this.promises),get:()=>d(this.isLoading)};this.privateTranslations=T({});this.translations={subscribe:this.privateTranslations.subscribe,get:()=>d(this.translations)};this.locales=l(n({},u([this.config,this.privateTranslations],([t,s])=>{if(!t)return[];let{loaders:e=[]}=t,a=e.map(({locale:i})=>`${i}`.toLowerCase()),r=Object.keys(s).map(i=>`${i}`.toLowerCase());return[...new Set([...a,...r])]},[])),{get:()=>d(this.locales)});this.internalLocale=T();this.locale=l(n({set:this.internalLocale.set,update:this.internalLocale.update},u(this.internalLocale,(t,s)=>{let e=t&&`${t}`.toLowerCase(),a=this.getLocale(e);a&&a!==this.locale.get()&&s(a)})),{get:()=>d(this.locale)});this.loaderTrigger=u([this.internalLocale,this.currentRoute],([t,s],e)=>{t!==void 0&&s!==void 0&&e([t,s])},[]);this.initialized=u([this.locale,this.currentRoute,this.privateTranslations],([t,s,e],a)=>{d(this.initialized)||a(t!==void 0&&s!==void 0&&!!Object.keys(e).length)});this.translation=u([this.privateTranslations,this.locale,this.isLoading],([t,s,e],a)=>{let r=t[s];r&&Object.keys(r).length&&!e&&a(r)},{});this.translate=({parser:t,key:s,params:e,translations:a,locale:r,fallbackLocale:i})=>{if(!s)throw new Error("No key provided to $t()");if(!r)throw new Error("No locale set!");let h=(a[r]||{})[s];return i&&h===void 0&&(h=(a[i]||{})[s]),t.parse(h,e,r,s)};this.t=l(n({},u([this.config,this.translation],([{parser:t,fallbackLocale:s}])=>(e,...a)=>this.translate({parser:t,key:e,params:a,translations:this.translations.get(),locale:this.locale.get(),fallbackLocale:s}))),{get:(t,...s)=>d(this.t)(t,...s)});this.l=l(n({},u([this.config,this.translations],([{parser:t,fallbackLocale:s},e])=>(a,r,...i)=>this.translate({parser:t,key:r,params:i,translations:e,locale:a,fallbackLocale:s}))),{get:(t,s,...e)=>d(this.l)(t,s,...e)});this.getLocale=t=>t?`${this.locales.get().find(a=>`${a}`.toLowerCase()===`${t}`.toLowerCase())||""}`.toLowerCase():"";this.setLocale=async t=>{!t||(this.internalLocale.set(t),await this.loading.toPromise())};this.setRoute=async t=>{t!==d(this.currentRoute)&&this.currentRoute.set(t),await this.loading.toPromise()};this.loadConfig=async t=>{await this.configLoader(t)};this.addTranslations=(t,s)=>{if(!t)return;let e=Object.keys(t||{});this.privateTranslations.update(a=>e.reduce((r,i)=>l(n({},r),{[i]:n(n({},r[i]||{}),b(t[i]))}),a)),e.forEach(a=>{let r=Object.keys(t[a]).map(i=>`${i}`.split(".")[0]);s&&(r=s[a]),this.loadedKeys[a]=Array.from(new Set([...this.loadedKeys[a]||[],...r||[]]))})};this.getTranslationProps=async(t=this.locale.get(),s=d(this.currentRoute))=>{let e=d(this.config);if(!e||!t)return[];let a=this.translations.get(),{loaders:r,fallbackLocale:i=""}=e||{},h=`${t}`.toLowerCase(),L=i&&`${i}`.toLowerCase(),S=a[h],E=a[L],w=(r||[]).map(v=>{var g=v,{locale:c}=g,f=P(g,["locale"]);return l(n({},f),{locale:`${c}`.toLowerCase()})}).filter(({routes:c})=>!c||(c||[]).some(F(s))).filter(({key:c,locale:f})=>f===h&&(!S||!(this.loadedKeys[h]||[]).includes(c))||i&&f===L&&(!E||!(this.loadedKeys[L]||[]).includes(c)));if(w.length){this.isLoading.set(!0);let c=await x(w);this.isLoading.set(!1);let f=Object.keys(c).reduce((g,p)=>l(n({},g),{[p]:Object.keys(c[p])}),{}),v=w.filter(({key:g,locale:p})=>(f[p]||[]).some(m=>`${m}`.startsWith(g))).reduce((g,{key:p,locale:m})=>l(n({},g),{[m]:[...g[m]||[],p]}),{});return[c,v]}return[]};this.translationLoader=async t=>{this.promises.push(new Promise(async s=>{let e=await this.getTranslationProps(t);e.length&&this.addTranslations(...e),s()})),await this.loading.toPromise()};this.loadTranslations=async(t,s=d(this.currentRoute)||"")=>{!t||(this.setRoute(s),this.setLocale(t),await this.loading.toPromise())};t&&this.loadConfig(t),this.loaderTrigger.subscribe(()=>this.translationLoader())}async configLoader(t){if(!t)throw new Error("No config!");this.config.set(t);let{initLocale:s="",translations:e}=t;e&&this.addTranslations(e),await this.loadTranslations(s)}};export{k as default};
1
+ var $=Object.defineProperty,A=Object.defineProperties;var W=Object.getOwnPropertyDescriptors;var P=Object.getOwnPropertySymbols;var F=Object.prototype.hasOwnProperty,K=Object.prototype.propertyIsEnumerable;var S=(r,t,e)=>t in r?$(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e,n=(r,t)=>{for(var e in t||(t={}))F.call(t,e)&&S(r,e,t[e]);if(P)for(var e of P(t))K.call(t,e)&&S(r,e,t[e]);return r},l=(r,t)=>A(r,W(t));var y=(r,t)=>{var e={};for(var a in r)F.call(r,a)&&t.indexOf(a)<0&&(e[a]=r[a]);if(r!=null&&P)for(var a of P(r))t.indexOf(a)<0&&K.call(r,a)&&(e[a]=r[a]);return e};import{derived as g,get as h,writable as T}from"svelte/store";var d=r=>{if(!r||!r.length)return[];let t=r;return Array.isArray(t)||(t=[t]),t.filter(e=>!!e).map(e=>{let a=`${e}`.toLowerCase();try{[a]=Intl.Collator.supportedLocalesOf(e)}catch{console.warn(`Non-standard locale provided: '${r}' => '${t}'. Check your 'translations' and 'loaders' in i18n config...`)}return a})},b=(r,t)=>Object.keys(r||{}).reduce((e,a)=>{let s=r[a],i=t?`${t}.${a}`:`${a}`;return s&&typeof s=="object"?n(n({},e),b(s,i)):l(n({},e),{[i]:s})},{}),N=async r=>{try{return(await Promise.all(r.map(s=>{var i=s,{loader:e}=i,a=y(i,["loader"]);return new Promise(async o=>{let f;try{f=await e()}catch(v){console.error(`Failed to load translation. Verify your '${a.locale}' > '${a.key}' Loader.`),console.error(v)}o(l(n({loader:e},a),{data:f}))})}))).reduce((e,{key:a,data:s,locale:i})=>{if(!s)return e;let o=d(i)[0];return l(n({},e),{[o]:b(l(n({},e[o]||{}),{[a]:s}))})},{})}catch(t){console.error(t)}return{}},j=r=>t=>{try{if(typeof t=="string")return t===r;if(typeof t=="object")return t.test(r)}catch{throw new Error("Invalid route config!")}return!1};var z=1e3*60*60*24,k=class{constructor(t){this.cachedAt=0;this.loadedKeys={};this.currentRoute=T();this.config=T();this.isLoading=T(!1);this.promises=[];this.loading={subscribe:this.isLoading.subscribe,toPromise:()=>Promise.all(this.promises),get:()=>h(this.isLoading)};this.privateTranslations=T({});this.translations={subscribe:this.privateTranslations.subscribe,get:()=>h(this.translations)};this.locales=l(n({},g([this.config,this.privateTranslations],([t,e])=>{if(!t)return[];let{loaders:a=[]}=t,s=a.map(({locale:o})=>d(o)[0]),i=Object.keys(e).map(o=>d(o)[0]);return[...new Set([...s,...i])]},[])),{get:()=>h(this.locales)});this.internalLocale=T();this.locale=l(n({set:this.internalLocale.set,update:this.internalLocale.update},g(this.internalLocale,(t,e)=>{let a=this.getLocale(t);a&&a!==this.locale.get()&&e(a)})),{get:()=>h(this.locale)});this.loaderTrigger=g([this.internalLocale,this.currentRoute],([t,e],a)=>{t!==void 0&&e!==void 0&&a([t,e])},[]);this.initialized=g([this.locale,this.currentRoute,this.privateTranslations],([t,e,a],s)=>{h(this.initialized)||s(t!==void 0&&e!==void 0&&!!Object.keys(a).length)});this.translation=g([this.privateTranslations,this.locale,this.isLoading],([t,e,a],s)=>{let i=t[e];i&&Object.keys(i).length&&!a&&s(i)},{});this.translate=({parser:t,key:e,params:a,translations:s,locale:i,fallbackLocale:o})=>{if(!(e&&i))return console.warn("No translation key or locale provided. Skipping translation..."),"";let f=(s[i]||{})[e];return o&&f===void 0&&(f=(s[o]||{})[e]),t.parse(f,a,i,e)};this.t=l(n({},g([this.config,this.translation],([{parser:t,fallbackLocale:e}])=>(a,...s)=>this.translate({parser:t,key:a,params:s,translations:this.translations.get(),locale:this.locale.get(),fallbackLocale:e}))),{get:(t,...e)=>h(this.t)(t,...e)});this.l=l(n({},g([this.config,this.translations],([{parser:t,fallbackLocale:e},a])=>(s,i,...o)=>this.translate({parser:t,key:i,params:o,translations:a,locale:s,fallbackLocale:e}))),{get:(t,e,...a)=>h(this.l)(t,e,...a)});this.getLocale=t=>{if(!t)return"";let a=this.locales.get().find(s=>s===d(t)[0])||"";return`${d(a)[0]}`};this.setLocale=async t=>{!t||(this.internalLocale.set(`${d(t)[0]}`),await this.loading.toPromise())};this.setRoute=async t=>{t!==h(this.currentRoute)&&this.currentRoute.set(t),await this.loading.toPromise()};this.loadConfig=async t=>{await this.configLoader(t)};this.getTranslationProps=async(t=this.locale.get(),e=h(this.currentRoute))=>{let a=h(this.config);if(!a||!t)return[];let s=this.translations.get(),{loaders:i,fallbackLocale:o="",cache:f=z}=a||{},v=Number.isNaN(+f)?z:+f;this.cachedAt?Date.now()>v+this.cachedAt&&(this.loadedKeys={},this.cachedAt=0):this.cachedAt=Date.now();let[w,C]=d([t,o]),E=s[w],O=s[C],x=(i||[]).map(R=>{var u=R,{locale:c}=u,p=y(u,["locale"]);return l(n({},p),{locale:d(c)[0]})}).filter(({routes:c})=>!c||(c||[]).some(j(e))).filter(({key:c,locale:p})=>p===w&&(!E||!(this.loadedKeys[w]||[]).includes(c))||o&&p===C&&(!O||!(this.loadedKeys[C]||[]).includes(c)));if(x.length){this.isLoading.set(!0);let c=await N(x);this.isLoading.set(!1);let p=Object.keys(c).reduce((u,L)=>l(n({},u),{[L]:Object.keys(c[L])}),{}),R=x.filter(({key:u,locale:L})=>(p[L]||[]).some(m=>`${m}`.startsWith(u))).reduce((u,{key:L,locale:m})=>l(n({},u),{[m]:[...u[m]||[],L]}),{});return[c,R]}return[]};this.addTranslations=(t,e)=>{if(!t)return;let a=Object.keys(t||{});this.privateTranslations.update(s=>a.reduce((i,o)=>l(n({},i),{[o]:n(n({},i[o]||{}),b(t[o]))}),s)),a.forEach(s=>{let i=Object.keys(t[s]).map(o=>`${o}`.split(".")[0]);e&&(i=e[s]),this.loadedKeys[s]=Array.from(new Set([...this.loadedKeys[s]||[],...i||[]]))})};this.translationLoader=async t=>{this.promises.push(new Promise(async e=>{let a=await this.getTranslationProps(t);a.length&&this.addTranslations(...a),e()})),await this.loading.toPromise()};this.loadTranslations=async(t,e=h(this.currentRoute)||"")=>{!t||(this.setRoute(e),this.setLocale(t),await this.loading.toPromise())};t&&this.loadConfig(t),this.loaderTrigger.subscribe(([e])=>this.translationLoader(e))}async configLoader(t){if(!t)throw new Error("No config provided!");let o=t,{initLocale:e,fallbackLocale:a,translations:s}=o,i=y(o,["initLocale","fallbackLocale","translations"]);e=d(e)[0],a=d(a)[0],this.config.set(n({initLocale:e,fallbackLocale:a,translations:s},i)),s&&this.addTranslations(s),await this.loadTranslations(e)}};export{k as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltekit-i18n/base",
3
- "version": "1.0.0-rc.2",
3
+ "version": "1.0.0-rc.6",
4
4
  "description": "Base functionality of sveltekit-i18n library with a support for external message parsers.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -65,4 +65,4 @@
65
65
  "tsup": "^5.11.13",
66
66
  "typescript": "^4.5.4"
67
67
  }
68
- }
68
+ }