diff --git a/README.md b/README.md index b37f998..d24bcbc 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ type TranslationLanguages = { } // create a translation object with your translations -const translate = createTranslations({ +const translate = createTranslations()({ homeScreen:{ signIn: { nl: 'yes', @@ -119,7 +119,7 @@ function getBestLanguage(): typeof availableLanguages[number] | typeof fallback return availableLanguages.find(al => deviceLanguage.startsWith(al)) || fallback } -const translate = createTranslations({ +const translate = createTranslations()({ // ........translations }, { language: getBestLanguage(), @@ -145,7 +145,7 @@ const fallback = 'en' function getBestLanguage(): typeof availableLanguages[number] | typeof fallback { return availableLanguages.find(al => deviceLanguage.startsWith(al)) || fallback } -const translate = createTranslations({ +const translate = createTranslations()({ // ........translations }, { language: getBestLanguage(), diff --git a/dist/index.d.ts b/dist/index.d.ts index de71e1a..7871033 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -1,24 +1,29 @@ -declare type val = (...params: any[]) => T; -declare type val1 = T; -declare type Translations = { - [group: string]: { - [key: string]: val | val1; +declare type CopyFunction = TFn extends (...a: infer A) => any ? (...a: A) => TR : string; +declare type ValueOf = T[keyof T]; +declare type Translations = { + [group in keyof TGroup]: { + [key in keyof ValueOf]: CopyFunction[key], string>; }; }; -declare type EasierTranslations = { +declare type Options = { + language: keyof TValue; + fallback: keyof TValue; +}; +declare type TranslationsObject = { + translations: Translations; + use: () => Translations; + setOptions: (options: Options) => any; + getOptions: () => Options; +}; +declare type val = (...params: any[]) => T; +declare type val1 = T; +declare type TranslationInput = { [group: string]: { - [key: string]: val | val1; + [key: string]: val | val1; }; }; -declare type Options = { - language: keyof T; - fallback: keyof T; -}; -declare type TranslationsObject = { - translations: EasierTranslations; - use: () => EasierTranslations; - setOptions: (options: Options) => any; - getOptions: () => Options; +declare type TranslationLanguagesInput = { + [language: string]: string; }; -export declare function createTranslations(t: Translations, po: Options): TranslationsObject; +export declare function createTranslations(): >(t: TGroup, po: Options) => TranslationsObject; export {}; diff --git a/dist/index.js b/dist/index.js index f6751d9..fa12e06 100644 --- a/dist/index.js +++ b/dist/index.js @@ -2,43 +2,45 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.createTranslations = void 0; const R = require("react"); -function createTranslations(t, po) { - let sb = []; - let o = po; - let et = {}; - function gen() { - Object.keys(t).forEach(g => { - et[g] = {}; - Object.keys(t[g]).forEach(k => { - let tv = t[g][k]; - et[g][k] = tv instanceof Function ? (...p) => { - let z = tv(...p); - return z[o.language] || z[o.fallback]; - } : tv[o.language] || tv[o.fallback]; +function createTranslations() { + return function (t, po) { + let sb = []; + let o = po; + let et = {}; + function gen() { + Object.keys(t).forEach(g => { + et[g] = {}; + Object.keys(t[g]).forEach(k => { + let tv = t[g][k]; + et[g][k] = tv instanceof Function ? (...p) => { + let z = tv(...p); + return z[o.language] || z[o.fallback]; + } : tv[o.language] || tv[o.fallback]; + }); }); - }); - } - function setOptions(op) { - o = op; + } + function setOptions(op) { + o = op; + gen(); + sb.forEach((c) => c((p) => p + 1)); + } + function use() { + let [, s] = R.useState(0); + R.useEffect(() => { + sb.push(s); + return () => { + sb = sb.filter((f) => f !== s); + }; + }, [s]); + return et; + } gen(); - sb.forEach((c) => c(p => p + 1)); - } - function use() { - let [, s] = R.useState(0); - R.useEffect(() => { - sb.push(s); - return () => { - sb = sb.filter((f) => f !== s); - }; - }, [s]); - return et; - } - gen(); - return { - translations: et, - getOptions: () => o, - setOptions, - use, + return { + translations: et, + getOptions: () => o, + setOptions, + use, + }; }; } exports.createTranslations = createTranslations; diff --git a/example/src/translate.ts b/example/src/translate.ts index 1cb94f8..f6b7e7a 100644 --- a/example/src/translate.ts +++ b/example/src/translate.ts @@ -1,117 +1,4 @@ -import * as R from "react"; - -type CopyFunction = TFn extends (...a: infer A) => any ? (...a:A) => TR: string -type ValueOf = T[keyof T]; - -type Translations = { - [group in keyof TGroup]: { - [key in keyof ValueOf]: CopyFunction[key], string> - } -} - -type Options = { - language: keyof TValue, - fallback: keyof TValue, -} - -type TranslationsObject = { - translations: Translations, - use: () => Translations; - setOptions: (options: Options) => any; - getOptions: () => Options, -} - - -type SubscriberFunc = (n:number) => any; -type val = (...params: any[]) => T -type val1 = T -type TranslationInput = { - [group: string]: { - [key: string]: val | val1 - }, -} - -export function createTranslations(){ - return function >(t: TGroup, po: Options): TranslationsObject { - // subscribers with callbacks for external updates - let sb: SubscriberFunc[] = []; - - let o = po - // empty map for easier translations - let et: any = {} - - // convert - // { - // homeScreen:{ - // loginButton:{ - // nl: 'Inloggen, - // en: 'Sign in', - // } - // } - // } - // - // to =>> based on the current language - // - // homeScreen:{ - // loginButton:'Sign in', - // } - // } - - function gen() { - // loop translations groups - Object.keys(t).forEach(g => { - // easierTranslation map with the group in the key - et[g] = {} - - // loop translations inside group - // @ts-ignore - Object.keys(t[g]).forEach(k => { - // e.g. 'Sign in' - // @ts-ignore - let tv = t[g][k] - - // map them in easier translation map - et[g][k] = tv instanceof Function ? (...p: any) => { - let z = (tv as Function)(...p) - return z[o.language] || z[o.fallback] - } : tv[o.language] || tv[o.fallback] - }) - }) - } - - function setOptions(op: Options) { - o = op - gen() - - // call subscribers - sb.forEach((c: any) => c((p: number) => p + 1)); - } - - // use hook - function use(): any { - let [, s] = R.useState(0); - - // subscribe to changes - R.useEffect(() => { - sb.push(s); - return () => { - sb = sb.filter((f) => f !== s); - }; - }, [s]); - - // return easier translations object - return et; - } - - gen() - return { - translations: et, - getOptions: () => o, - setOptions, - use, - }; - } -} +import {createTranslations} from 'react-ridge-translations' // first describe which languages are allowed/required (Typescript) type TranslationLanguages = { @@ -128,17 +15,15 @@ function getBestLanguage(): typeof availableLanguages[number] | typeof fallback return availableLanguages.find(al => deviceLanguage.startsWith(al)) || fallback } - - - // create a translation object with your translations - const translate = createTranslations()({ appScreen:{ yesText: { nl: 'Ja', fr: 'Oui', en: 'Yes', + yes: '', + why: '???', }, welcomeText: ({ firstName }: { firstName: string }) => ({ nl: `Hallo ${firstName}`, diff --git a/package.json b/package.json index edb96ff..e8e75ef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-ridge-translations", - "version": "0.0.2", + "version": "0.0.3", "description": "react-ridge-translations is a type safe translation library without the struggle", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/index.ts b/src/index.ts index 033d39c..4895be0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,83 +23,97 @@ type TranslationsObject = { type SubscriberFunc = (n:number) => any; +type val = (...params: any[]) => T +type val1 = T -export function createTranslations(t: TGroup, po: Options): TranslationsObject { - // subscribers with callbacks for external updates - let sb: SubscriberFunc[] = []; - - let o = po - // empty map for easier translations - let et = {} - - // convert - // { - // homeScreen:{ - // loginButton:{ - // nl: 'Inloggen, - // en: 'Sign in', - // } - // } - // } - // - // to =>> based on the current language - // - // homeScreen:{ - // loginButton:'Sign in', - // } - // } - - function gen() { - // loop translations groups - Object.keys(t).forEach(g => { - // easierTranslation map with the group in the key - et[g] = {} - - // loop translations inside group - Object.keys(t[g]).forEach(k => { - // e.g. 'Sign in' - let tv = t[g][k] - - // map them in easier translation map - et[g][k] = tv instanceof Function ? (...p) => { +type TranslationInput = { + [group: string]: { + [key: string]: val | val1 + }, +} + +type TranslationLanguagesInput = { + [language: string]: string, +} + +export function createTranslations(){ + return function >(t: TGroup, po: Options): TranslationsObject { + // subscribers with callbacks for external updates + let sb: SubscriberFunc[] = []; + + let o = po + // empty map for easier translations + let et: any = {} + + // convert + // { + // homeScreen:{ + // loginButton:{ + // nl: 'Inloggen, + // en: 'Sign in', + // } + // } + // } + // + // to =>> based on the current language + // + // homeScreen:{ + // loginButton:'Sign in', + // } + // } + + function gen() { + // loop translations groups + Object.keys(t).forEach(g => { + // easierTranslation map with the group in the key + et[g] = {} + + // loop translations inside group + // @ts-ignore + Object.keys(t[g]).forEach(k => { + // e.g. 'Sign in' + // @ts-ignore + let tv = t[g][k] + + // map them in easier translation map + et[g][k] = tv instanceof Function ? (...p: any) => { let z = (tv as Function)(...p) return z[o.language] || z[o.fallback] } : tv[o.language] || tv[o.fallback] + }) }) - }) - } + } - function setOptions(op: Options) { + function setOptions(op: Options) { o = op gen() // call subscribers - sb.forEach((c: any) => c(p => p + 1)); + sb.forEach((c: any) => c((p: number) => p + 1)); + } + + // use hook + function use(): any { + let [, s] = R.useState(0); + + // subscribe to changes + R.useEffect(() => { + sb.push(s); + return () => { + sb = sb.filter((f) => f !== s); + }; + }, [s]); + + // return easier translations object + return et; + } + + gen() + return { + translations: et, + getOptions: () => o, + setOptions, + use, + }; } - - // use hook - function use(): any { - let [, s] = R.useState(0); - - // subscribe to changes - R.useEffect(() => { - sb.push(s); - return () => { - sb = sb.filter((f) => f !== s); - }; - }, [s]); - - // return easier translations object - return et; - } - - // generate translations for current language - gen() - - return { - translations: et as Translations, - getOptions: () => o, - setOptions, - use, - }; }