MobX i18n
    Preparing search index...

    MobX i18n

    MobX i18n

    Responsive Translation utility based on TypeScript & MobX

    MobX compatibility NPM Dependency CI & CD

    NPM

    • [x] Type hinting of Text keys
    • [x] Lambda Expression values
    • [x] Space utility for CJK & other characters
    • [x] Responsive re-rendering
    • [x] Async loading of Language packages
    • [x] support HTTP protocol for Server-side rendering
    • [x] support BOM/DOM language API for Client-side rendering
    • [x] Speech Synthesis API for Text-to-Speech (TTS)
    SemVer branch status ES decorator MobX
    >=0.5.0 main ✅developing stage-3 >=6.11
    <0.5.0 master ❌deprecated stage-2 >=4 <6.11

    Original from https://github.com/idea2app/React-MobX-Bootstrap-ts

    npm i mobx mobx-react mobx-i18n
    
    {
    "compilerOptions": {
    "target": "ES6",
    "useDefineForClassFields": true,
    "experimentalDecorators": false
    }
    }
    import { textJoin } from 'mobx-i18n';

    export default {
    open_source: '开源',
    project: '项目',
    love: ({ a, b }: Record<'a' | 'b', string>) => textJoin(a, '爱', b)
    } as const;
    import { textJoin } from 'mobx-i18n';

    export default {
    open_source: 'Open Source',
    project: 'project',
    love: ({ a, b }: Record<'a' | 'b', string>) => textJoin(a, 'love', b)
    } as const;
    export const i18n = new TranslationModel({
    'zh-CN': zhCN,
    'en-US': () => import('../translation/en-US')
    });

    export const LanguageName: Record<(typeof i18n)['currentLanguage'], string> = {
    'zh-CN': '简体中文',
    'en-US': 'English'
    };
    import { textJoin } from 'mobx-i18n';
    import { observer } from 'mobx-react';

    import { i18n, LanguageName } from '../model/Translation';

    export const HomePage = observer(() => {
    const { currentLanguage, t } = i18n;

    return (
    <>
    <select
    value={currentLanguage}
    onChange={({ currentTarget: { value } }) =>
    i18n.loadLanguages(value as typeof currentLanguage)
    }
    >
    {Object.entries(LanguageName).map(([code, name]) => (
    <option key={code} value={code}>
    {name}
    </option>
    ))}
    </select>
    <p>
    {t('love', {
    a: '我',
    b: textJoin(t('open_source'), t('project'))
    })}
    </p>
    </>
    );
    });

    You can use React Context API to share the TranslationModel instance cross Class & Function components in Client & Server runtimes, which has been all set in an One-key Template Repository.

    If you use React server components with Next.js app router, you should share Translation Data between server and client as below, which is from another One-key Template Repository.

    export default {
    i18nKey1: 'i18nValue1',
    i18nKey2: ({ someKey }: { someKey: string }) => `i18nValue2: ${someKey}`
    // ...
    } as const;
    'use client';

    import { TranslationModel, decodeFunctions } from 'mobx-i18n';
    import { createContext, FC, PropsWithChildren } from 'react';

    import enUS from './en-US';

    export const I18nContext = createContext(
    new TranslationModel({ 'en-US': enUS })
    );

    export type I18nProviderProps = PropsWithChildren<
    Record<'language' | 'languageMap', string>
    >;

    export const I18nProvider: FC<I18nProviderProps> = ({
    language,
    languageMap,
    children
    }) => {
    const i18n = new TranslationModel({
    [language]: JSON.parse(languageMap, decodeFunctions)
    });
    return <I18nContext.Provider value={i18n}>{children}</I18nContext.Provider>;
    };
    import { PropsWithChildren } from 'react';
    import { encodeFunctions } from 'mobx-i18n';

    import { I18nProvider } from '../translation/context';
    import enUS from '../translation/en-US';

    export default async function RootLayout({ children }: PropsWithChildren) {
    const language = 'en-US';
    const languageMap = JSON.stringify(enUS, encodeFunctions);

    return (
    <html lang={language}>
    <head />
    <body>
    <I18nProvider language={language} languageMap={languageMap}>
    {children}
    </I18nProvider>
    </body>
    </html>
    );
    }
    import { component, observer } from 'web-cell';
    import { SpeechSynthesisModel, SpeechSynthesisState } from 'mobx-i18n';

    @component({ tagName: 'article-page' })
    @observer
    export class ArticlePage extends HTMLElement {
    storeTTS = new SpeechSynthesisModel();

    toggleSpeaking = () => {
    const { storeTTS } = this;

    if (storeTTS.state !== SpeechSynthesisState.Clear)
    return storeTTS.toggle();

    const text = SpeechSynthesisModel.getReadableText(
    this.querySelector('article')
    );
    storeTTS.speak(text);
    };

    render() {
    const speaking = this.storeTTS.state === SpeechSynthesisState.Speaking;

    return (
    <>
    <button
    style={{ background: speaking ? 'red' : 'blue' }}
    onClick={this.toggleSpeaking}
    >
    {speaking ? '🔇' : '📢'}
    </button>
    <article>
    <h1>The Four Freedoms</h1>
    <ol>
    <li>Freedom of speech and expression</li>
    <li>Freedom of worship</li>
    <li>Freedom from want</li>
    <li>Freedom from fear</li>
    </ol>
    </article>
    </>
    );
    }
    }
    1. https://github.com/infinum/react-mobx-translatable
    2. https://github.com/jverhoelen/react-mobx-i18n
    3. https://github.com/QuiiBz/next-international