@nanostores/i18n
Advanced tools
Comparing version 0.2.1 to 0.3.0
@@ -1,2 +0,6 @@ | ||
import { TranslationJSON, TranslationFunction } from '../create-i18n/index.js' | ||
import { | ||
TranslationJSON, | ||
TranslationFunction, | ||
TranslationFunctionAlternatives | ||
} from '../create-i18n/index.js' | ||
@@ -9,30 +13,34 @@ export type CountInput = { | ||
/** | ||
* Add pluralization variants to translation. | ||
* | ||
* ```ts | ||
* import { count } from '@nanostores/i18n' | ||
* import { i18n } from '../stores/i18n' | ||
* | ||
* export const messages = i18n('pagination', { | ||
* pages: count({ | ||
* one: 'One page', | ||
* many: '{count} pages' | ||
* }) | ||
* }) | ||
* ``` | ||
* | ||
* ```js | ||
* t.count(5) | ||
* ``` | ||
* | ||
* @param input Pluralization variants. | ||
* @return Transform for translation. | ||
*/ | ||
export function count<Input extends CountInput>( | ||
input: Input | ||
): TranslationFunction< | ||
[number], | ||
// @ts-ignore | ||
Input[keyof Input] | ||
> | ||
interface Count { | ||
/** | ||
* Add pluralization variants to translation. | ||
* | ||
* ```ts | ||
* import { count } from '@nanostores/i18n' | ||
* import { i18n } from '../stores/i18n' | ||
* | ||
* export const messages = i18n('pagination', { | ||
* pages: count({ | ||
* one: 'One page', | ||
* many: '{count} pages' | ||
* }) | ||
* }) | ||
* ``` | ||
* | ||
* ```js | ||
* t.count(5) | ||
* ``` | ||
* | ||
* @param input Pluralization variants. | ||
* @return Transform for translation. | ||
*/ | ||
<Parameters extends Record<string, string | number>>( | ||
input: TranslationFunction<[Parameters], string> | ||
): TranslationFunctionAlternatives<Parameters> | ||
<Input extends CountInput>(input: Input): TranslationFunction< | ||
[number], | ||
Input[keyof Input] | ||
> | ||
} | ||
export const count: Count |
@@ -18,3 +18,3 @@ import { ReadableAtom } from 'nanostores' | ||
Arguments extends any[] = any[], | ||
Output extends TranslationJSON = TranslationJSON | ||
Output = TranslationJSON | Translation | ||
> { | ||
@@ -24,2 +24,9 @@ (...args: Arguments): Output | ||
export type TranslationFunctionAlternatives< | ||
Parameters extends Record<string, unknown> | ||
> = { | ||
(input: number): TranslationFunction<[Parameters], string> | ||
(input: Parameters): TranslationFunction<[number], string> | ||
} | ||
export type Translation = string | TranslationFunction | ||
@@ -48,4 +55,9 @@ | ||
export interface TranslationLoader<Locale extends string = string> { | ||
(code: Locale): Promise<ComponentsJSON> | ||
export interface TranslationLoader< | ||
Locale extends string = string, | ||
ComponentsNames extends string[] = string[] | ||
> { | ||
(code: Locale, components: ComponentsNames): | ||
| Promise<ComponentsJSON[]> | ||
| Promise<ComponentsJSON> | ||
} | ||
@@ -52,0 +64,0 @@ |
@@ -7,2 +7,4 @@ import { atom, onMount } from 'nanostores' | ||
let loading = atom(true) | ||
let mounted = new Set() | ||
let fetched = new Set() | ||
@@ -36,3 +38,2 @@ let define = (componentName, base) => { | ||
let waiting = false | ||
function setTranslation(code) { | ||
@@ -49,3 +50,2 @@ let translations = { | ||
t.set(translations) | ||
waiting = false | ||
} | ||
@@ -55,27 +55,33 @@ setTranslation(baseLocale) | ||
onMount(t, () => { | ||
let unbindLocale = locale.subscribe(code => { | ||
if (define.cache[code]) { | ||
setTranslation(code) | ||
waiting = false | ||
} else { | ||
waiting = true | ||
mounted.add(t.component) | ||
let code = locale.get() | ||
let isCached = | ||
code === baseLocale || | ||
(define.cache[code] && define.cache[code][t.component]) | ||
if (isCached) { | ||
setTranslation(code) | ||
} else { | ||
let prefix = t.component.split('/')[0] | ||
if (!fetched.has(prefix)) { | ||
fetched.add(prefix) | ||
getTranslation(code, [t.component]).then(() => { | ||
fetched.delete(prefix) | ||
}) | ||
} | ||
}) | ||
let unbindLoading = loading.subscribe(isLoading => { | ||
if (waiting && !isLoading) { | ||
setTranslation(locale.get()) | ||
waiting = false | ||
} | ||
}) | ||
} | ||
for (let i in processors) { | ||
processors[i].from.listen(() => { | ||
setTranslation(locale.get()) | ||
setTranslation(code) | ||
}) | ||
} | ||
let unbindLoading = loading.listen(isLoading => { | ||
if (!isLoading) { | ||
setTranslation(locale.get()) | ||
} | ||
}) | ||
return () => { | ||
unbindLocale() | ||
mounted.delete(t.component) | ||
unbindLoading() | ||
} | ||
}) | ||
return t | ||
@@ -89,15 +95,27 @@ } | ||
locale.subscribe(code => { | ||
if (define.cache[code]) { | ||
async function getTranslation(code, components) { | ||
loading.set(true) | ||
let translations = await opts.get(code, components) | ||
if (Array.isArray(translations)) { | ||
translations = translations.reduce((obj, item) => | ||
Object.assign(obj, item) | ||
) | ||
} | ||
define.cache[code] = { ...define.cache[code], ...translations } | ||
if (code === locale.get()) loading.set(false) | ||
} | ||
locale.listen(code => { | ||
let nonCached = Array.from(mounted).filter( | ||
component => !(define.cache[code] && define.cache[code][component]) | ||
) | ||
if (nonCached.length) { | ||
getTranslation(code, nonCached) | ||
} else { | ||
loading.set(false) | ||
} else { | ||
loading.set(true) | ||
opts.get(code).then(translation => { | ||
define.cache[code] = translation | ||
if (code === locale.get()) loading.set(false) | ||
}) | ||
} | ||
}) | ||
loading.set(false) | ||
return define | ||
} |
{ | ||
"name": "@nanostores/i18n", | ||
"version": "0.2.1", | ||
"description": "A tiny (≈500 bytes) i18n library for React/Preact/Vue/Svelte", | ||
"version": "0.3.0", | ||
"description": "A tiny (≈600 bytes) i18n library for React/Preact/Vue/Svelte", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "nano", |
@@ -1,3 +0,5 @@ | ||
import { TranslationFunction } from '../create-i18n/index.js' | ||
import { CountInput } from '../count/index.js' | ||
import { | ||
TranslationFunctionAlternatives, | ||
TranslationFunction | ||
} from '../create-i18n/index.js' | ||
@@ -18,2 +20,3 @@ interface Params { | ||
* ```js | ||
* const t = useStore(messages); | ||
* t.page({ page: 1, all: 10 }) | ||
@@ -29,4 +32,4 @@ * ``` | ||
<Parameters extends Record<string, string | number>>( | ||
input: CountInput | ||
): TranslationFunction<[Parameters], CountInput> | ||
input: TranslationFunction<[number], string> | ||
): TranslationFunctionAlternatives<Parameters> | ||
<Parameters extends Record<string, string | number>>( | ||
@@ -33,0 +36,0 @@ input: any |
@@ -7,7 +7,5 @@ import { ReadableAtom } from 'nanostores' | ||
from: ReadableAtom<Key> | ||
(input: Record<Key, TranslationJSON>): TranslationFunction< | ||
[], | ||
// @ts-ignore | ||
Input[keyof Input] | ||
> | ||
<Input extends Record<Key, TranslationJSON>>( | ||
input: Input | ||
): TranslationFunction<[], Input[keyof Input]> | ||
} | ||
@@ -14,0 +12,0 @@ |
@@ -9,3 +9,3 @@ # Nano Stores I18n | ||
* **Small.** Between 448 and 844 bytes (minified and gzipped). | ||
* **Small.** Between 673 and 1106 bytes (minified and gzipped). | ||
Zero dependencies. | ||
@@ -12,0 +12,0 @@ * Works with **React**, **Preact**, **Vue**, **Svelte**, and plain JS. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
22774
631