@sveltekit-i18n/base 1.2.0 → 1.3.0
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 +10 -12
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +227 -0
- package/dist/index.d.ts +111 -17
- package/dist/index.js +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -82,24 +82,22 @@ const config = ({
|
|
|
82
82
|
export const { t, locale, locales, loading, loadTranslations } = new i18n(config);
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
...load your translations in
|
|
85
|
+
...load your translations in `+layout.js`...
|
|
86
86
|
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
import { locale, loadTranslations } from '$lib/translations';
|
|
87
|
+
```js
|
|
88
|
+
import { locale, loadTranslations } from '$lib/translations';
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
export const load = async ({ url }) => {
|
|
91
|
+
const { pathname } = url;
|
|
93
92
|
|
|
94
|
-
|
|
93
|
+
const defaultLocale = 'en'; // get from cookie, user session, ...
|
|
95
94
|
|
|
96
|
-
|
|
95
|
+
const initLocale = locale.get() || defaultLocale; // set default if no locale already set
|
|
97
96
|
|
|
98
|
-
|
|
97
|
+
await loadTranslations(initLocale, pathname); // keep this just before the `return`
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
</script>
|
|
99
|
+
return {};
|
|
100
|
+
}
|
|
103
101
|
```
|
|
104
102
|
|
|
105
103
|
...and include your translations within pages and components.
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
"use strict";var w=Object.defineProperty,I=Object.defineProperties,H=Object.getOwnPropertyDescriptor,q=Object.getOwnPropertyDescriptors,B=Object.getOwnPropertyNames,v=Object.getOwnPropertySymbols;var C=Object.prototype.hasOwnProperty,A=Object.prototype.propertyIsEnumerable;var j=(s,t,e)=>t in s?w(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e,l=(s,t)=>{for(var e in t||(t={}))C.call(t,e)&&j(s,e,t[e]);if(v)for(var e of v(t))A.call(t,e)&&j(s,e,t[e]);return s},u=(s,t)=>I(s,q(t));var T=(s,t)=>{var e={};for(var a in s)C.call(s,a)&&t.indexOf(a)<0&&(e[a]=s[a]);if(s!=null&&v)for(var a of v(s))t.indexOf(a)<0&&A.call(s,a)&&(e[a]=s[a]);return e};var G=(s,t)=>{for(var e in t)w(s,e,{get:t[e],enumerable:!0})},J=(s,t,e,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of B(t))!C.call(s,r)&&r!==e&&w(s,r,{get:()=>t[r],enumerable:!(a=H(t,r))||a.enumerable});return s};var M=s=>J(w({},"__esModule",{value:!0}),s);var U={};G(U,{default:()=>x});module.exports=M(U);var n=require("svelte/store");var z=["error","warn","debug"],F=({logger:s=console,level:t=z[1],prefix:e="[i18n]: "})=>z.reduce((a,r,i)=>u(l({},a),{[r]:o=>z.indexOf(t)>=i&&s[r](`${e}${o}`)}),{}),g=F({}),V=s=>{g=s};var O=c=>{var d=c,{parser:s,key:t,params:e,translations:a,locale:r,fallbackLocale:i}=d,o=T(d,["parser","key","params","translations","locale","fallbackLocale"]);if(!(t&&r))return g.warn("No translation key or locale provided. Skipping translation..."),"";let f=(a[r]||{})[t];return i&&f===void 0&&(f=(a[i]||{})[t]),o.hasOwnProperty("fallbackValue")&&f===void 0?o.fallbackValue:s.parse(f,e,r,t)},p=(...s)=>s.length?s.filter(t=>!!t).map(t=>{let e=`${t}`.toLowerCase();try{let[a]=Intl.Collator.supportedLocalesOf(t);if(!a)throw new Error;e=a}catch(a){g.warn(`'${t}' locale is non-standard.`)}return e}):[],S=(s,t,e)=>Object.keys(s||{}).reduce((a,r)=>{let i=s[r],o=e?`${e}.${r}`:`${r}`;return t&&Array.isArray(i)?u(l({},a),{[o]:i.map(c=>S(c,t))}):i&&typeof i=="object"?l(l({},a),S(i,t,o)):u(l({},a),{[o]:i})},{}),Q=s=>s.reduce((t,{key:e,data:a,locale:r})=>{if(!a)return t;let[i]=p(r),o=u(l({},t[i]||{}),{[e]:a});return u(l({},t),{[i]:o})},{}),$=async s=>{try{let t=await Promise.all(s.map(r=>{var i=r,{loader:e}=i,a=T(i,["loader"]);return new Promise(async o=>{let c;try{c=await e()}catch(d){g.error(`Failed to load translation. Verify your '${a.locale}' > '${a.key}' Loader.`),g.error(d)}o(u(l({loader:e},a),{data:c}))})}));return Q(t)}catch(t){g.error(t)}return{}},E=s=>t=>{try{if(typeof t=="string")return t===s;if(typeof t=="object")return t.test(s)}catch(e){g.error("Invalid route config!")}return!1},N=(s,t)=>{let e=!0;try{e=Object.keys(s).filter(a=>s[a]!==void 0).every(a=>s[a]===t[a])}catch(a){}return e};var W=1e3*60*60*24,x=class{constructor(t){this.cachedAt=0;this.loadedKeys={};this.currentRoute=(0,n.writable)();this.config=(0,n.writable)();this.isLoading=(0,n.writable)(!1);this.promises=new Set;this.loading={subscribe:this.isLoading.subscribe,toPromise:(t,e)=>{let a=Array.from(this.promises).filter(r=>N({locale:p(t)[0],route:e},r)).map(({promise:r})=>r);return Promise.all(a)},get:()=>(0,n.get)(this.isLoading)};this.privateRawTranslations=(0,n.writable)({});this.rawTranslations={subscribe:this.privateRawTranslations.subscribe,get:()=>(0,n.get)(this.rawTranslations)};this.privateTranslations=(0,n.writable)({});this.translations={subscribe:this.privateTranslations.subscribe,get:()=>(0,n.get)(this.translations)};this.locales=u(l({},(0,n.derived)([this.config,this.privateTranslations],([t,e])=>{if(!t)return[];let{loaders:a=[]}=t,r=a.map(({locale:o})=>o),i=Object.keys(e).map(o=>o);return Array.from(new Set([...p(...r),...p(...i)]))},[])),{get:()=>(0,n.get)(this.locales)});this.internalLocale=(0,n.writable)();this.loaderTrigger=(0,n.derived)([this.internalLocale,this.currentRoute],([t,e],a)=>{var r,i;t!==void 0&&e!==void 0&&!(t===((r=(0,n.get)(this.loaderTrigger))==null?void 0:r[0])&&e===((i=(0,n.get)(this.loaderTrigger))==null?void 0:i[1]))&&(g.debug("Triggering translation load..."),a([t,e]))},[]);this.localeHelper=(0,n.writable)();this.locale={subscribe:this.localeHelper.subscribe,forceSet:this.localeHelper.set,set:this.internalLocale.set,update:this.internalLocale.update,get:()=>(0,n.get)(this.locale)};this.initialized=(0,n.derived)([this.locale,this.currentRoute,this.privateTranslations],([t,e,a],r)=>{(0,n.get)(this.initialized)||r(t!==void 0&&e!==void 0&&!!Object.keys(a).length)});this.translation=(0,n.derived)([this.privateTranslations,this.locale,this.isLoading],([t,e,a],r)=>{let i=t[e];i&&Object.keys(i).length&&!a&&r(i)},{});this.t=u(l({},(0,n.derived)([this.config,this.translation],r=>{var[i]=r,o=i,{parser:t,fallbackLocale:e}=o,a=T(o,["parser","fallbackLocale"]);return(c,...d)=>O(l({parser:t,key:c,params:d,translations:this.translations.get(),locale:this.locale.get(),fallbackLocale:e},a.hasOwnProperty("fallbackValue")?{fallbackValue:a.fallbackValue}:{}))})),{get:(t,...e)=>(0,n.get)(this.t)(t,...e)});this.l=u(l({},(0,n.derived)([this.config,this.translations],i=>{var[o,...c]=i,d=o,{parser:t,fallbackLocale:e}=d,a=T(d,["parser","fallbackLocale"]),[r]=c;return(f,b,...R)=>O(l({parser:t,key:b,params:R,translations:r,locale:f,fallbackLocale:e},a.hasOwnProperty("fallbackValue")?{fallbackValue:a.fallbackValue}:{}))})),{get:(t,e,...a)=>(0,n.get)(this.l)(t,e,...a)});this.getLocale=t=>{let{fallbackLocale:e=""}=(0,n.get)(this.config)||{},a=t||e;if(!a)return"";let r=this.locales.get();return r.find(o=>p(a).includes(o))||r.find(o=>p(e).includes(o))||""};this.setLocale=t=>{if(t&&t!==(0,n.get)(this.internalLocale))return g.debug(`Setting '${t}' locale.`),this.internalLocale.set(t),this.loading.toPromise(t,(0,n.get)(this.currentRoute))};this.setRoute=t=>{if(t!==(0,n.get)(this.currentRoute)){g.debug(`Setting '${t}' route.`),this.currentRoute.set(t);let e=(0,n.get)(this.internalLocale);return this.loading.toPromise(e,t)}};this.loadConfig=async t=>{await this.configLoader(t)};this.getTranslationProps=async(t=this.locale.get(),e=(0,n.get)(this.currentRoute))=>{let a=(0,n.get)(this.config);if(!a||!t)return[];let r=this.translations.get(),{loaders:i,fallbackLocale:o="",cache:c=W}=a||{},d=Number.isNaN(+c)?W:+c;this.cachedAt?Date.now()>d+this.cachedAt&&(g.debug("Refreshing cache."),this.loadedKeys={},this.cachedAt=0):(g.debug("Setting cache timestamp."),this.cachedAt=Date.now());let[f,b]=p(t,o),R=r[f],D=r[b],k=(i||[]).map(K=>{var L=K,{locale:h}=L,m=T(L,["locale"]);return u(l({},m),{locale:p(h)[0]})}).filter(({routes:h})=>!h||(h||[]).some(E(e))).filter(({key:h,locale:m})=>m===f&&(!R||!(this.loadedKeys[f]||[]).includes(h))||o&&m===b&&(!D||!(this.loadedKeys[b]||[]).includes(h)));if(k.length){this.isLoading.set(!0),g.debug("Fetching translations...");let h=await $(k);this.isLoading.set(!1);let m=Object.keys(h).reduce((L,y)=>u(l({},L),{[y]:Object.keys(h[y])}),{}),K=k.filter(({key:L,locale:y})=>(m[y]||[]).some(P=>`${P}`.startsWith(L))).reduce((L,{key:y,locale:P})=>u(l({},L),{[P]:[...L[P]||[],y]}),{});return[h,K]}return[]};this.addTranslations=(t,e)=>{if(!t)return;let a=(0,n.get)(this.config),{preprocess:r}=a||{};g.debug("Adding translations...");let i=Object.keys(t||{});this.privateRawTranslations.update(o=>i.reduce((c,d)=>u(l({},c),{[d]:l(l({},c[d]||{}),t[d])}),o)),this.privateTranslations.update(o=>i.reduce((c,d)=>{let f=!0,b=t[d];return typeof r=="function"&&(b=r(b)),(typeof r=="function"||r==="none")&&(f=!1),u(l({},c),{[d]:l(l({},c[d]||{}),f?S(b,r==="preserveArrays"):b)})},o)),i.forEach(o=>{let c=Object.keys(t[o]).map(d=>`${d}`.split(".")[0]);e&&(c=e[o]),this.loadedKeys[o]=Array.from(new Set([...this.loadedKeys[o]||[],...c||[]]))})};this.loader=async([t,e])=>{let a=this.getLocale(t)||void 0;g.debug(`Adding loader promise for '${a}' locale and '${e}' route.`);let r=(async()=>{let i=await this.getTranslationProps(a,e);i.length&&this.addTranslations(...i)})();this.promises.add({locale:a,route:e,promise:r}),r.then(()=>{a&&this.locale.get()!==a&&this.locale.forceSet(a)})};this.loadTranslations=(t,e=(0,n.get)(this.currentRoute)||"")=>{let a=this.getLocale(t);if(a)return this.setRoute(e),this.setLocale(a),this.loading.toPromise(a,e)};this.loaderTrigger.subscribe(this.loader),this.isLoading.subscribe(async e=>{e&&this.promises.size&&(await this.loading.toPromise(),this.promises.clear(),g.debug("Loader promises have been purged."))}),t&&this.loadConfig(t)}async configLoader(t){if(!t)return g.error("No config provided!");let c=t,{initLocale:e,fallbackLocale:a,translations:r,log:i}=c,o=T(c,["initLocale","fallbackLocale","translations","log"]);i&&V(F(i)),[e]=p(e),[a]=p(a),g.debug("Setting config."),this.config.set(l({initLocale:e,fallbackLocale:a,translations:r},o)),r&&this.addTranslations(r),await this.loadTranslations(e)}};
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { Readable, Writable } from 'svelte/store';
|
|
2
|
+
|
|
3
|
+
type ExtendedStore<T, Get = () => T, Store = Readable<T>> = Store & {
|
|
4
|
+
get: Get;
|
|
5
|
+
};
|
|
6
|
+
type LoadingStore = Readable<boolean> & {
|
|
7
|
+
toPromise: (locale?: Config.Locale, route?: string) => Promise<void[] | void>;
|
|
8
|
+
get: () => boolean;
|
|
9
|
+
};
|
|
10
|
+
declare module DotNotation {
|
|
11
|
+
type Input = Translations.Input;
|
|
12
|
+
type Output<V = any, K extends keyof V = keyof V> = {
|
|
13
|
+
[P in K]?: V[K];
|
|
14
|
+
};
|
|
15
|
+
type T = <I = Input>(input: I, preserveArrays?: boolean, parentKey?: string) => Output<I>;
|
|
16
|
+
}
|
|
17
|
+
declare module Logger {
|
|
18
|
+
type Level = 'error' | 'warn' | 'debug';
|
|
19
|
+
type Prefix = string;
|
|
20
|
+
type T = {
|
|
21
|
+
[key in Logger.Level]: (value: any) => void;
|
|
22
|
+
};
|
|
23
|
+
type FactoryProps = {
|
|
24
|
+
/**
|
|
25
|
+
* You can setup your custom logger using this property.
|
|
26
|
+
*
|
|
27
|
+
* @default console
|
|
28
|
+
*/
|
|
29
|
+
logger?: Logger.T;
|
|
30
|
+
/**
|
|
31
|
+
* You can manage log level using this property.
|
|
32
|
+
*
|
|
33
|
+
* @default 'warn'
|
|
34
|
+
*/
|
|
35
|
+
level?: Logger.Level;
|
|
36
|
+
/**
|
|
37
|
+
* You can prefix output logs using this property.
|
|
38
|
+
*
|
|
39
|
+
* @default '[i18n]: '
|
|
40
|
+
*/
|
|
41
|
+
prefix?: Logger.Prefix;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
declare module Config {
|
|
45
|
+
type Loader = Loader.LoaderModule;
|
|
46
|
+
type Translations = Translations.T;
|
|
47
|
+
type Locale = Translations.Locales[number];
|
|
48
|
+
type InitLocale = Locale | undefined;
|
|
49
|
+
type FallbackLocale = Locale | undefined;
|
|
50
|
+
type FallbackValue = any;
|
|
51
|
+
type T<P extends Parser.Params = Parser.Params> = {
|
|
52
|
+
/**
|
|
53
|
+
* You can use loaders to define your asyncronous translation load. All loaded data are stored so loader is triggered only once – in case there is no previous version of the translation. It can get refreshed according to `config.cache`.
|
|
54
|
+
*/
|
|
55
|
+
loaders?: Loader[];
|
|
56
|
+
/**
|
|
57
|
+
* Locale-indexed translations, which should be in place before loaders will trigger. It's useful for static pages and synchronous translations – for example locally defined language names which are the same for all of the language mutations.
|
|
58
|
+
*
|
|
59
|
+
* @example {
|
|
60
|
+
* "en": {"lang": {"en": "English", "cs": "Česky"}}
|
|
61
|
+
* "cs": {"lang": {"en": "English", "cs": "Česky"}}
|
|
62
|
+
* }
|
|
63
|
+
*/
|
|
64
|
+
translations?: Translations.T;
|
|
65
|
+
/**
|
|
66
|
+
* If you set this property, translations will be initialized immediately using this locale.
|
|
67
|
+
*/
|
|
68
|
+
initLocale?: InitLocale;
|
|
69
|
+
/**
|
|
70
|
+
* If you set this property, translations are automatically loaded not for current `$locale` only, but for this locale as well. In case there is no translation for current `$locale`, fallback locale translation is used instead of translation key placeholder. This is also used as a fallback when unknown locale is set.
|
|
71
|
+
*/
|
|
72
|
+
fallbackLocale?: FallbackLocale;
|
|
73
|
+
/**
|
|
74
|
+
* By default, translation key is returned in case no translation is found for given translation key. For example, `$t('unknown.key')` will result in `'unknown.key'` output. You can set this output value using this config prop.
|
|
75
|
+
*/
|
|
76
|
+
fallbackValue?: FallbackValue;
|
|
77
|
+
/**
|
|
78
|
+
* Preprocessor strategy or a custom function. Defines, how to transform the translation data immediately after the load.
|
|
79
|
+
* @default 'full'
|
|
80
|
+
*
|
|
81
|
+
* @example 'full'
|
|
82
|
+
* {a: {b: [{c: {d: 1}}, {c: {d: 2}}]}} => {"a.b.0.c.d": 1, "a.b.1.c.d": 2}
|
|
83
|
+
*
|
|
84
|
+
* @example 'preserveArrays'
|
|
85
|
+
* {a: {b: [{c: {d: 1}}, {c: {d: 2}}]}} => {"a.b": [{"c.d": 1}, {"c.d": 2}]}
|
|
86
|
+
*
|
|
87
|
+
* @example 'none'
|
|
88
|
+
* {a: {b: [{c: {d: 1}}, {c: {d: 2}}]}} => {a: {b: [{c: {d: 1}}, {c: {d: 2}}]}}
|
|
89
|
+
*/
|
|
90
|
+
preprocess?: 'full' | 'preserveArrays' | 'none' | ((input: Translations.Input) => any);
|
|
91
|
+
/**
|
|
92
|
+
* This property defines translation syntax you want to use.
|
|
93
|
+
*/
|
|
94
|
+
parser: Parser.T<P>;
|
|
95
|
+
/**
|
|
96
|
+
* When you are running your app on Node.js server, translations are loaded only once during the SSR. This property allows you to setup a refresh period in milliseconds when your translations are refetched on the server.
|
|
97
|
+
*
|
|
98
|
+
* @default 86400000 // 24 hours
|
|
99
|
+
*
|
|
100
|
+
* @tip You can set to `Number.POSITIVE_INFINITY` to disable server-side refreshing.
|
|
101
|
+
*/
|
|
102
|
+
cache?: number;
|
|
103
|
+
/**
|
|
104
|
+
* Custom logger configuration.
|
|
105
|
+
*/
|
|
106
|
+
log?: Logger.FactoryProps;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
declare module Loader {
|
|
110
|
+
type Key = string;
|
|
111
|
+
type Locale = Config.Locale;
|
|
112
|
+
type Route = string | RegExp;
|
|
113
|
+
type IndexedKeys = Translations.LocaleIndexed<Key[]>;
|
|
114
|
+
type LoaderModule = {
|
|
115
|
+
/**
|
|
116
|
+
* Represents the translation namespace. This key is used as a translation prefix so it should be module-unique. You can access your translation later using `$t('key.yourTranslation')`. It shouldn't include `.` (dot) character.
|
|
117
|
+
*/
|
|
118
|
+
key: Key;
|
|
119
|
+
/**
|
|
120
|
+
* Locale (e.g. `en`, `de`) which is this loader for.
|
|
121
|
+
*/
|
|
122
|
+
locale: Locale;
|
|
123
|
+
/**
|
|
124
|
+
* Function returning a `Promise` with translation data. You can use it to load files locally, fetch it from your API etc...
|
|
125
|
+
*/
|
|
126
|
+
loader: T;
|
|
127
|
+
/**
|
|
128
|
+
* Define routes this loader should be triggered for. You can use Regular expressions too. For example `[/\/.ome/]` will be triggered for `/home` and `/rome` route as well (but still only once). Leave this `undefined` in case you want to load this module with any route (useful for common translations).
|
|
129
|
+
*/
|
|
130
|
+
routes?: Route[];
|
|
131
|
+
};
|
|
132
|
+
type T = () => Promise<Translations.Input>;
|
|
133
|
+
}
|
|
134
|
+
declare module Parser {
|
|
135
|
+
type Value = any;
|
|
136
|
+
type Params = Array<unknown>;
|
|
137
|
+
type Locale = Config.Locale;
|
|
138
|
+
type Key = Loader.Key;
|
|
139
|
+
type Output = any;
|
|
140
|
+
type Parse<P extends Parser.Params = Parser.Params> = (
|
|
141
|
+
/**
|
|
142
|
+
* Translation value from the definitions.
|
|
143
|
+
*/
|
|
144
|
+
value: Value,
|
|
145
|
+
/**
|
|
146
|
+
* Array of rest parameters given by user (e.g. payload variables etc...)
|
|
147
|
+
*/
|
|
148
|
+
params: P,
|
|
149
|
+
/**
|
|
150
|
+
* Locale of translated message.
|
|
151
|
+
*/
|
|
152
|
+
locale: Locale,
|
|
153
|
+
/**
|
|
154
|
+
* This key is serialized path to translation (e.g., `home.content.title`)
|
|
155
|
+
*/
|
|
156
|
+
key: Key) => Output;
|
|
157
|
+
type T<P extends Parser.Params = Parser.Params> = {
|
|
158
|
+
/**
|
|
159
|
+
* Parse function deals with interpolation of user payload and returns interpolated message.
|
|
160
|
+
*/
|
|
161
|
+
parse: Parse<P>;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
declare module Translations {
|
|
165
|
+
type Locales<T = string> = T[];
|
|
166
|
+
type SerializedTranslations = LocaleIndexed<DotNotation.Input>;
|
|
167
|
+
type TranslationData<T = any> = Loader.LoaderModule & {
|
|
168
|
+
data: T;
|
|
169
|
+
};
|
|
170
|
+
type FetchTranslations = (loaders: Loader.LoaderModule[]) => Promise<SerializedTranslations>;
|
|
171
|
+
type TranslationFunction<P extends Parser.Params = Parser.Params> = (key: string, ...restParams: P) => any;
|
|
172
|
+
type LocalTranslationFunction<P extends Parser.Params = Parser.Params> = (locale: Config.Locale, key: string, ...restParams: P) => any;
|
|
173
|
+
type Translate = <P extends Parser.Params = Parser.Params>(props: {
|
|
174
|
+
parser: Parser.T<P>;
|
|
175
|
+
key: string;
|
|
176
|
+
params: P;
|
|
177
|
+
translations: SerializedTranslations;
|
|
178
|
+
locale: Locales[number];
|
|
179
|
+
fallbackLocale?: Config.FallbackLocale;
|
|
180
|
+
fallbackValue?: Config.FallbackValue;
|
|
181
|
+
}) => string;
|
|
182
|
+
type Input<V = any> = {
|
|
183
|
+
[K in any]: Input<V> | V;
|
|
184
|
+
};
|
|
185
|
+
type LocaleIndexed<V, L extends string = string> = {
|
|
186
|
+
[locale in Locales<L>[number]]: V;
|
|
187
|
+
};
|
|
188
|
+
type T<V = any, L extends string = string> = LocaleIndexed<Input<V>, L>;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
declare class I18n<ParserParams extends Parser.Params = any> {
|
|
192
|
+
constructor(config?: Config.T<ParserParams>);
|
|
193
|
+
private cachedAt;
|
|
194
|
+
private loadedKeys;
|
|
195
|
+
private currentRoute;
|
|
196
|
+
private config;
|
|
197
|
+
private isLoading;
|
|
198
|
+
private promises;
|
|
199
|
+
loading: LoadingStore;
|
|
200
|
+
private privateRawTranslations;
|
|
201
|
+
rawTranslations: ExtendedStore<Translations.SerializedTranslations>;
|
|
202
|
+
private privateTranslations;
|
|
203
|
+
translations: ExtendedStore<Translations.SerializedTranslations>;
|
|
204
|
+
locales: ExtendedStore<Config.Locale[]>;
|
|
205
|
+
private internalLocale;
|
|
206
|
+
private loaderTrigger;
|
|
207
|
+
private localeHelper;
|
|
208
|
+
locale: ExtendedStore<Config.Locale, () => Config.Locale, Writable<string>> & {
|
|
209
|
+
forceSet: any;
|
|
210
|
+
};
|
|
211
|
+
initialized: Readable<boolean>;
|
|
212
|
+
private translation;
|
|
213
|
+
t: ExtendedStore<Translations.TranslationFunction<ParserParams>, Translations.TranslationFunction<ParserParams>>;
|
|
214
|
+
l: ExtendedStore<Translations.LocalTranslationFunction<ParserParams>, Translations.LocalTranslationFunction<ParserParams>>;
|
|
215
|
+
private getLocale;
|
|
216
|
+
setLocale: (locale?: string) => Promise<void | void[]> | undefined;
|
|
217
|
+
setRoute: (route: string) => Promise<void | void[]> | undefined;
|
|
218
|
+
configLoader(config: Config.T<ParserParams>): Promise<void>;
|
|
219
|
+
loadConfig: (config: Config.T<ParserParams>) => Promise<void>;
|
|
220
|
+
getTranslationProps: ($locale?: string, $route?: string) => Promise<[Translations.SerializedTranslations, Loader.IndexedKeys] | [
|
|
221
|
+
]>;
|
|
222
|
+
addTranslations: (translations?: Translations.SerializedTranslations, keys?: Loader.IndexedKeys) => void;
|
|
223
|
+
private loader;
|
|
224
|
+
loadTranslations: (locale: Config.Locale, route?: string) => Promise<void | void[]> | undefined;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export { Config, Loader, Logger, Parser, Translations, I18n as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Readable, Writable } from 'svelte/store';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
type ExtendedStore<T, Get = () => T, Store = Readable<T>> = Store & {
|
|
4
4
|
get: Get;
|
|
5
5
|
};
|
|
6
|
-
|
|
6
|
+
type LoadingStore = Readable<boolean> & {
|
|
7
7
|
toPromise: (locale?: Config.Locale, route?: string) => Promise<void[] | void>;
|
|
8
8
|
get: () => boolean;
|
|
9
9
|
};
|
|
@@ -12,7 +12,7 @@ declare module DotNotation {
|
|
|
12
12
|
type Output<V = any, K extends keyof V = keyof V> = {
|
|
13
13
|
[P in K]?: V[K];
|
|
14
14
|
};
|
|
15
|
-
type T = <I = Input>(input: I, parentKey?: string) => Output<I>;
|
|
15
|
+
type T = <I = Input>(input: I, preserveArrays?: boolean, parentKey?: string) => Output<I>;
|
|
16
16
|
}
|
|
17
17
|
declare module Logger {
|
|
18
18
|
type Level = 'error' | 'warn' | 'debug';
|
|
@@ -21,8 +21,23 @@ declare module Logger {
|
|
|
21
21
|
[key in Logger.Level]: (value: any) => void;
|
|
22
22
|
};
|
|
23
23
|
type FactoryProps = {
|
|
24
|
+
/**
|
|
25
|
+
* You can setup your custom logger using this property.
|
|
26
|
+
*
|
|
27
|
+
* @default console
|
|
28
|
+
*/
|
|
24
29
|
logger?: Logger.T;
|
|
30
|
+
/**
|
|
31
|
+
* You can manage log level using this property.
|
|
32
|
+
*
|
|
33
|
+
* @default 'warn'
|
|
34
|
+
*/
|
|
25
35
|
level?: Logger.Level;
|
|
36
|
+
/**
|
|
37
|
+
* You can prefix output logs using this property.
|
|
38
|
+
*
|
|
39
|
+
* @default '[i18n]: '
|
|
40
|
+
*/
|
|
26
41
|
prefix?: Logger.Prefix;
|
|
27
42
|
};
|
|
28
43
|
}
|
|
@@ -34,18 +49,61 @@ declare module Config {
|
|
|
34
49
|
type FallbackLocale = Locale | undefined;
|
|
35
50
|
type FallbackValue = any;
|
|
36
51
|
type T<P extends Parser.Params = Parser.Params> = {
|
|
52
|
+
/**
|
|
53
|
+
* You can use loaders to define your asyncronous translation load. All loaded data are stored so loader is triggered only once – in case there is no previous version of the translation. It can get refreshed according to `config.cache`.
|
|
54
|
+
*/
|
|
37
55
|
loaders?: Loader[];
|
|
56
|
+
/**
|
|
57
|
+
* Locale-indexed translations, which should be in place before loaders will trigger. It's useful for static pages and synchronous translations – for example locally defined language names which are the same for all of the language mutations.
|
|
58
|
+
*
|
|
59
|
+
* @example {
|
|
60
|
+
* "en": {"lang": {"en": "English", "cs": "Česky"}}
|
|
61
|
+
* "cs": {"lang": {"en": "English", "cs": "Česky"}}
|
|
62
|
+
* }
|
|
63
|
+
*/
|
|
38
64
|
translations?: Translations.T;
|
|
65
|
+
/**
|
|
66
|
+
* If you set this property, translations will be initialized immediately using this locale.
|
|
67
|
+
*/
|
|
39
68
|
initLocale?: InitLocale;
|
|
69
|
+
/**
|
|
70
|
+
* If you set this property, translations are automatically loaded not for current `$locale` only, but for this locale as well. In case there is no translation for current `$locale`, fallback locale translation is used instead of translation key placeholder. This is also used as a fallback when unknown locale is set.
|
|
71
|
+
*/
|
|
40
72
|
fallbackLocale?: FallbackLocale;
|
|
73
|
+
/**
|
|
74
|
+
* By default, translation key is returned in case no translation is found for given translation key. For example, `$t('unknown.key')` will result in `'unknown.key'` output. You can set this output value using this config prop.
|
|
75
|
+
*/
|
|
41
76
|
fallbackValue?: FallbackValue;
|
|
77
|
+
/**
|
|
78
|
+
* Preprocessor strategy or a custom function. Defines, how to transform the translation data immediately after the load.
|
|
79
|
+
* @default 'full'
|
|
80
|
+
*
|
|
81
|
+
* @example 'full'
|
|
82
|
+
* {a: {b: [{c: {d: 1}}, {c: {d: 2}}]}} => {"a.b.0.c.d": 1, "a.b.1.c.d": 2}
|
|
83
|
+
*
|
|
84
|
+
* @example 'preserveArrays'
|
|
85
|
+
* {a: {b: [{c: {d: 1}}, {c: {d: 2}}]}} => {"a.b": [{"c.d": 1}, {"c.d": 2}]}
|
|
86
|
+
*
|
|
87
|
+
* @example 'none'
|
|
88
|
+
* {a: {b: [{c: {d: 1}}, {c: {d: 2}}]}} => {a: {b: [{c: {d: 1}}, {c: {d: 2}}]}}
|
|
89
|
+
*/
|
|
90
|
+
preprocess?: 'full' | 'preserveArrays' | 'none' | ((input: Translations.Input) => any);
|
|
91
|
+
/**
|
|
92
|
+
* This property defines translation syntax you want to use.
|
|
93
|
+
*/
|
|
42
94
|
parser: Parser.T<P>;
|
|
95
|
+
/**
|
|
96
|
+
* When you are running your app on Node.js server, translations are loaded only once during the SSR. This property allows you to setup a refresh period in milliseconds when your translations are refetched on the server.
|
|
97
|
+
*
|
|
98
|
+
* @default 86400000 // 24 hours
|
|
99
|
+
*
|
|
100
|
+
* @tip You can set to `Number.POSITIVE_INFINITY` to disable server-side refreshing.
|
|
101
|
+
*/
|
|
43
102
|
cache?: number;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
};
|
|
103
|
+
/**
|
|
104
|
+
* Custom logger configuration.
|
|
105
|
+
*/
|
|
106
|
+
log?: Logger.FactoryProps;
|
|
49
107
|
};
|
|
50
108
|
}
|
|
51
109
|
declare module Loader {
|
|
@@ -54,10 +112,22 @@ declare module Loader {
|
|
|
54
112
|
type Route = string | RegExp;
|
|
55
113
|
type IndexedKeys = Translations.LocaleIndexed<Key[]>;
|
|
56
114
|
type LoaderModule = {
|
|
115
|
+
/**
|
|
116
|
+
* Represents the translation namespace. This key is used as a translation prefix so it should be module-unique. You can access your translation later using `$t('key.yourTranslation')`. It shouldn't include `.` (dot) character.
|
|
117
|
+
*/
|
|
57
118
|
key: Key;
|
|
119
|
+
/**
|
|
120
|
+
* Locale (e.g. `en`, `de`) which is this loader for.
|
|
121
|
+
*/
|
|
58
122
|
locale: Locale;
|
|
59
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Function returning a `Promise` with translation data. You can use it to load files locally, fetch it from your API etc...
|
|
125
|
+
*/
|
|
60
126
|
loader: T;
|
|
127
|
+
/**
|
|
128
|
+
* Define routes this loader should be triggered for. You can use Regular expressions too. For example `[/\/.ome/]` will be triggered for `/home` and `/rome` route as well (but still only once). Leave this `undefined` in case you want to load this module with any route (useful for common translations).
|
|
129
|
+
*/
|
|
130
|
+
routes?: Route[];
|
|
61
131
|
};
|
|
62
132
|
type T = () => Promise<Translations.Input>;
|
|
63
133
|
}
|
|
@@ -67,14 +137,36 @@ declare module Parser {
|
|
|
67
137
|
type Locale = Config.Locale;
|
|
68
138
|
type Key = Loader.Key;
|
|
69
139
|
type Output = any;
|
|
70
|
-
type Parse<P extends Parser.Params = Parser.Params> = (
|
|
140
|
+
type Parse<P extends Parser.Params = Parser.Params> = (
|
|
141
|
+
/**
|
|
142
|
+
* Translation value from the definitions.
|
|
143
|
+
*/
|
|
144
|
+
value: Value,
|
|
145
|
+
/**
|
|
146
|
+
* Array of rest parameters given by user (e.g. payload variables etc...)
|
|
147
|
+
*/
|
|
148
|
+
params: P,
|
|
149
|
+
/**
|
|
150
|
+
* Locale of translated message.
|
|
151
|
+
*/
|
|
152
|
+
locale: Locale,
|
|
153
|
+
/**
|
|
154
|
+
* This key is serialized path to translation (e.g., `home.content.title`)
|
|
155
|
+
*/
|
|
156
|
+
key: Key) => Output;
|
|
71
157
|
type T<P extends Parser.Params = Parser.Params> = {
|
|
158
|
+
/**
|
|
159
|
+
* Parse function deals with interpolation of user payload and returns interpolated message.
|
|
160
|
+
*/
|
|
72
161
|
parse: Parse<P>;
|
|
73
162
|
};
|
|
74
163
|
}
|
|
75
164
|
declare module Translations {
|
|
76
|
-
type Locales = string[];
|
|
77
|
-
type SerializedTranslations = LocaleIndexed<DotNotation.
|
|
165
|
+
type Locales<T = string> = T[];
|
|
166
|
+
type SerializedTranslations = LocaleIndexed<DotNotation.Input>;
|
|
167
|
+
type TranslationData<T = any> = Loader.LoaderModule & {
|
|
168
|
+
data: T;
|
|
169
|
+
};
|
|
78
170
|
type FetchTranslations = (loaders: Loader.LoaderModule[]) => Promise<SerializedTranslations>;
|
|
79
171
|
type TranslationFunction<P extends Parser.Params = Parser.Params> = (key: string, ...restParams: P) => any;
|
|
80
172
|
type LocalTranslationFunction<P extends Parser.Params = Parser.Params> = (locale: Config.Locale, key: string, ...restParams: P) => any;
|
|
@@ -90,10 +182,10 @@ declare module Translations {
|
|
|
90
182
|
type Input<V = any> = {
|
|
91
183
|
[K in any]: Input<V> | V;
|
|
92
184
|
};
|
|
93
|
-
type LocaleIndexed<V> = {
|
|
94
|
-
[locale in Locales[number]]: V;
|
|
185
|
+
type LocaleIndexed<V, L extends string = string> = {
|
|
186
|
+
[locale in Locales<L>[number]]: V;
|
|
95
187
|
};
|
|
96
|
-
type T<V = any> = LocaleIndexed<Input<V
|
|
188
|
+
type T<V = any, L extends string = string> = LocaleIndexed<Input<V>, L>;
|
|
97
189
|
}
|
|
98
190
|
|
|
99
191
|
declare class I18n<ParserParams extends Parser.Params = any> {
|
|
@@ -105,6 +197,8 @@ declare class I18n<ParserParams extends Parser.Params = any> {
|
|
|
105
197
|
private isLoading;
|
|
106
198
|
private promises;
|
|
107
199
|
loading: LoadingStore;
|
|
200
|
+
private privateRawTranslations;
|
|
201
|
+
rawTranslations: ExtendedStore<Translations.SerializedTranslations>;
|
|
108
202
|
private privateTranslations;
|
|
109
203
|
translations: ExtendedStore<Translations.SerializedTranslations>;
|
|
110
204
|
locales: ExtendedStore<Config.Locale[]>;
|
|
@@ -119,13 +213,13 @@ declare class I18n<ParserParams extends Parser.Params = any> {
|
|
|
119
213
|
t: ExtendedStore<Translations.TranslationFunction<ParserParams>, Translations.TranslationFunction<ParserParams>>;
|
|
120
214
|
l: ExtendedStore<Translations.LocalTranslationFunction<ParserParams>, Translations.LocalTranslationFunction<ParserParams>>;
|
|
121
215
|
private getLocale;
|
|
122
|
-
setLocale: (locale?: string
|
|
216
|
+
setLocale: (locale?: string) => Promise<void | void[]> | undefined;
|
|
123
217
|
setRoute: (route: string) => Promise<void | void[]> | undefined;
|
|
124
218
|
configLoader(config: Config.T<ParserParams>): Promise<void>;
|
|
125
219
|
loadConfig: (config: Config.T<ParserParams>) => Promise<void>;
|
|
126
220
|
getTranslationProps: ($locale?: string, $route?: string) => Promise<[Translations.SerializedTranslations, Loader.IndexedKeys] | [
|
|
127
221
|
]>;
|
|
128
|
-
addTranslations: (translations?: Translations.SerializedTranslations
|
|
222
|
+
addTranslations: (translations?: Translations.SerializedTranslations, keys?: Loader.IndexedKeys) => void;
|
|
129
223
|
private loader;
|
|
130
224
|
loadTranslations: (locale: Config.Locale, route?: string) => Promise<void | void[]> | undefined;
|
|
131
225
|
}
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var H=Object.defineProperty,q=Object.defineProperties;var B=Object.getOwnPropertyDescriptors;var S=Object.getOwnPropertySymbols;var A=Object.prototype.hasOwnProperty,V=Object.prototype.propertyIsEnumerable;var j=(s,t,e)=>t in s?H(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e,n=(s,t)=>{for(var e in t||(t={}))A.call(t,e)&&j(s,e,t[e]);if(S)for(var e of S(t))V.call(t,e)&&j(s,e,t[e]);return s},u=(s,t)=>q(s,B(t));var T=(s,t)=>{var e={};for(var a in s)A.call(s,a)&&t.indexOf(a)<0&&(e[a]=s[a]);if(s!=null&&S)for(var a of S(s))t.indexOf(a)<0&&V.call(s,a)&&(e[a]=s[a]);return e};import{derived as v,get as g,writable as m}from"svelte/store";var C=["error","warn","debug"],z=({logger:s=console,level:t=C[1],prefix:e="[i18n]: "})=>C.reduce((a,r,i)=>u(n({},a),{[r]:o=>C.indexOf(t)>=i&&s[r](`${e}${o}`)}),{}),d=z({}),$=s=>{d=s};var F=l=>{var c=l,{parser:s,key:t,params:e,translations:a,locale:r,fallbackLocale:i}=c,o=T(c,["parser","key","params","translations","locale","fallbackLocale"]);if(!(t&&r))return d.warn("No translation key or locale provided. Skipping translation..."),"";let f=(a[r]||{})[t];return i&&f===void 0&&(f=(a[i]||{})[t]),o.hasOwnProperty("fallbackValue")&&f===void 0?o.fallbackValue:s.parse(f,e,r,t)},p=(...s)=>s.length?s.filter(t=>!!t).map(t=>{let e=`${t}`.toLowerCase();try{let[a]=Intl.Collator.supportedLocalesOf(t);if(!a)throw new Error;e=a}catch(a){d.warn(`'${t}' locale is non-standard.`)}return e}):[],x=(s,t,e)=>Object.keys(s||{}).reduce((a,r)=>{let i=s[r],o=e?`${e}.${r}`:`${r}`;return t&&Array.isArray(i)?u(n({},a),{[o]:i.map(l=>x(l,t))}):i&&typeof i=="object"?n(n({},a),x(i,t,o)):u(n({},a),{[o]:i})},{}),G=s=>s.reduce((t,{key:e,data:a,locale:r})=>{if(!a)return t;let[i]=p(r),o=u(n({},t[i]||{}),{[e]:a});return u(n({},t),{[i]:o})},{}),E=async s=>{try{let t=await Promise.all(s.map(r=>{var i=r,{loader:e}=i,a=T(i,["loader"]);return new Promise(async o=>{let l;try{l=await e()}catch(c){d.error(`Failed to load translation. Verify your '${a.locale}' > '${a.key}' Loader.`),d.error(c)}o(u(n({loader:e},a),{data:l}))})}));return G(t)}catch(t){d.error(t)}return{}},N=s=>t=>{try{if(typeof t=="string")return t===s;if(typeof t=="object")return t.test(s)}catch(e){d.error("Invalid route config!")}return!1},W=(s,t)=>{let e=!0;try{e=Object.keys(s).filter(a=>s[a]!==void 0).every(a=>s[a]===t[a])}catch(a){}return e};var D=1e3*60*60*24,O=class{constructor(t){this.cachedAt=0;this.loadedKeys={};this.currentRoute=m();this.config=m();this.isLoading=m(!1);this.promises=new Set;this.loading={subscribe:this.isLoading.subscribe,toPromise:(t,e)=>{let a=Array.from(this.promises).filter(r=>W({locale:p(t)[0],route:e},r)).map(({promise:r})=>r);return Promise.all(a)},get:()=>g(this.isLoading)};this.privateRawTranslations=m({});this.rawTranslations={subscribe:this.privateRawTranslations.subscribe,get:()=>g(this.rawTranslations)};this.privateTranslations=m({});this.translations={subscribe:this.privateTranslations.subscribe,get:()=>g(this.translations)};this.locales=u(n({},v([this.config,this.privateTranslations],([t,e])=>{if(!t)return[];let{loaders:a=[]}=t,r=a.map(({locale:o})=>o),i=Object.keys(e).map(o=>o);return Array.from(new Set([...p(...r),...p(...i)]))},[])),{get:()=>g(this.locales)});this.internalLocale=m();this.loaderTrigger=v([this.internalLocale,this.currentRoute],([t,e],a)=>{var r,i;t!==void 0&&e!==void 0&&!(t===((r=g(this.loaderTrigger))==null?void 0:r[0])&&e===((i=g(this.loaderTrigger))==null?void 0:i[1]))&&(d.debug("Triggering translation load..."),a([t,e]))},[]);this.localeHelper=m();this.locale={subscribe:this.localeHelper.subscribe,forceSet:this.localeHelper.set,set:this.internalLocale.set,update:this.internalLocale.update,get:()=>g(this.locale)};this.initialized=v([this.locale,this.currentRoute,this.privateTranslations],([t,e,a],r)=>{g(this.initialized)||r(t!==void 0&&e!==void 0&&!!Object.keys(a).length)});this.translation=v([this.privateTranslations,this.locale,this.isLoading],([t,e,a],r)=>{let i=t[e];i&&Object.keys(i).length&&!a&&r(i)},{});this.t=u(n({},v([this.config,this.translation],r=>{var[i]=r,o=i,{parser:t,fallbackLocale:e}=o,a=T(o,["parser","fallbackLocale"]);return(l,...c)=>F(n({parser:t,key:l,params:c,translations:this.translations.get(),locale:this.locale.get(),fallbackLocale:e},a.hasOwnProperty("fallbackValue")?{fallbackValue:a.fallbackValue}:{}))})),{get:(t,...e)=>g(this.t)(t,...e)});this.l=u(n({},v([this.config,this.translations],i=>{var[o,...l]=i,c=o,{parser:t,fallbackLocale:e}=c,a=T(c,["parser","fallbackLocale"]),[r]=l;return(f,b,...R)=>F(n({parser:t,key:b,params:R,translations:r,locale:f,fallbackLocale:e},a.hasOwnProperty("fallbackValue")?{fallbackValue:a.fallbackValue}:{}))})),{get:(t,e,...a)=>g(this.l)(t,e,...a)});this.getLocale=t=>{let{fallbackLocale:e=""}=g(this.config)||{},a=t||e;if(!a)return"";let r=this.locales.get();return r.find(o=>p(a).includes(o))||r.find(o=>p(e).includes(o))||""};this.setLocale=t=>{if(t&&t!==g(this.internalLocale))return d.debug(`Setting '${t}' locale.`),this.internalLocale.set(t),this.loading.toPromise(t,g(this.currentRoute))};this.setRoute=t=>{if(t!==g(this.currentRoute)){d.debug(`Setting '${t}' route.`),this.currentRoute.set(t);let e=g(this.internalLocale);return this.loading.toPromise(e,t)}};this.loadConfig=async t=>{await this.configLoader(t)};this.getTranslationProps=async(t=this.locale.get(),e=g(this.currentRoute))=>{let a=g(this.config);if(!a||!t)return[];let r=this.translations.get(),{loaders:i,fallbackLocale:o="",cache:l=D}=a||{},c=Number.isNaN(+l)?D:+l;this.cachedAt?Date.now()>c+this.cachedAt&&(d.debug("Refreshing cache."),this.loadedKeys={},this.cachedAt=0):(d.debug("Setting cache timestamp."),this.cachedAt=Date.now());let[f,b]=p(t,o),R=r[f],I=r[b],k=(i||[]).map(K=>{var L=K,{locale:h}=L,y=T(L,["locale"]);return u(n({},y),{locale:p(h)[0]})}).filter(({routes:h})=>!h||(h||[]).some(N(e))).filter(({key:h,locale:y})=>y===f&&(!R||!(this.loadedKeys[f]||[]).includes(h))||o&&y===b&&(!I||!(this.loadedKeys[b]||[]).includes(h)));if(k.length){this.isLoading.set(!0),d.debug("Fetching translations...");let h=await E(k);this.isLoading.set(!1);let y=Object.keys(h).reduce((L,P)=>u(n({},L),{[P]:Object.keys(h[P])}),{}),K=k.filter(({key:L,locale:P})=>(y[P]||[]).some(w=>`${w}`.startsWith(L))).reduce((L,{key:P,locale:w})=>u(n({},L),{[w]:[...L[w]||[],P]}),{});return[h,K]}return[]};this.addTranslations=(t,e)=>{if(!t)return;let a=g(this.config),{preprocess:r}=a||{};d.debug("Adding translations...");let i=Object.keys(t||{});this.privateRawTranslations.update(o=>i.reduce((l,c)=>u(n({},l),{[c]:n(n({},l[c]||{}),t[c])}),o)),this.privateTranslations.update(o=>i.reduce((l,c)=>{let f=!0,b=t[c];return typeof r=="function"&&(b=r(b)),(typeof r=="function"||r==="none")&&(f=!1),u(n({},l),{[c]:n(n({},l[c]||{}),f?x(b,r==="preserveArrays"):b)})},o)),i.forEach(o=>{let l=Object.keys(t[o]).map(c=>`${c}`.split(".")[0]);e&&(l=e[o]),this.loadedKeys[o]=Array.from(new Set([...this.loadedKeys[o]||[],...l||[]]))})};this.loader=async([t,e])=>{let a=this.getLocale(t)||void 0;d.debug(`Adding loader promise for '${a}' locale and '${e}' route.`);let r=(async()=>{let i=await this.getTranslationProps(a,e);i.length&&this.addTranslations(...i)})();this.promises.add({locale:a,route:e,promise:r}),r.then(()=>{a&&this.locale.get()!==a&&this.locale.forceSet(a)})};this.loadTranslations=(t,e=g(this.currentRoute)||"")=>{let a=this.getLocale(t);if(a)return this.setRoute(e),this.setLocale(a),this.loading.toPromise(a,e)};this.loaderTrigger.subscribe(this.loader),this.isLoading.subscribe(async e=>{e&&this.promises.size&&(await this.loading.toPromise(),this.promises.clear(),d.debug("Loader promises have been purged."))}),t&&this.loadConfig(t)}async configLoader(t){if(!t)return d.error("No config provided!");let l=t,{initLocale:e,fallbackLocale:a,translations:r,log:i}=l,o=T(l,["initLocale","fallbackLocale","translations","log"]);i&&$(z(i)),[e]=p(e),[a]=p(a),d.debug("Setting config."),this.config.set(n({initLocale:e,fallbackLocale:a,translations:r},o)),r&&this.addTranslations(r),await this.loadTranslations(e)}};export{O as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltekit-i18n/base",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
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",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
18
|
"dev": "tsup --watch",
|
|
19
|
-
"test": "jest",
|
|
19
|
+
"test": "npx cross-env NODE_OPTIONS=--experimental-vm-modules jest",
|
|
20
20
|
"build": "tsup",
|
|
21
21
|
"prepublishOnly": "npm run build",
|
|
22
22
|
"lint": "eslint --fix --ext .ts,.js --ignore-path .gitignore ."
|
|
@@ -47,22 +47,22 @@
|
|
|
47
47
|
},
|
|
48
48
|
"homepage": "https://github.com/sveltekit-i18n/base#readme",
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"svelte": "
|
|
50
|
+
"svelte": ">=3.49.0"
|
|
51
51
|
},
|
|
52
52
|
"optionalDependencies": {
|
|
53
|
-
"@sveltekit-i18n/parser-default": "
|
|
53
|
+
"@sveltekit-i18n/parser-default": ">=1.0.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@types/jest": "^
|
|
56
|
+
"@types/jest": "^29.5.2",
|
|
57
57
|
"@typescript-eslint/eslint-plugin": "^5.7.0",
|
|
58
58
|
"@typescript-eslint/parser": "^5.7.0",
|
|
59
59
|
"eslint": "^8.4.1",
|
|
60
60
|
"eslint-config-airbnb-typescript": "^17.0.0",
|
|
61
61
|
"eslint-plugin-import": "^2.25.3",
|
|
62
|
-
"jest": "^
|
|
62
|
+
"jest": "^29.6.0",
|
|
63
63
|
"pre-commit": "^1.2.2",
|
|
64
|
-
"ts-jest": "^
|
|
65
|
-
"tsup": "^
|
|
66
|
-
"typescript": "^
|
|
64
|
+
"ts-jest": "^29.1.1",
|
|
65
|
+
"tsup": "^7.1.0",
|
|
66
|
+
"typescript": "^5.1.6"
|
|
67
67
|
}
|
|
68
68
|
}
|