{"id":21291882,"url":"https://github.com/idea2app/mobx-i18n","last_synced_at":"2025-10-14T13:41:51.062Z","repository":{"id":63487723,"uuid":"567933097","full_name":"idea2app/MobX-i18n","owner":"idea2app","description":"Responsive Translation utility based on TypeScript \u0026 MobX, which is much easier to learn \u0026 use than other i18n solutions of React, Vue \u0026 Angular.","archived":false,"fork":false,"pushed_at":"2025-05-06T23:52:29.000Z","size":236,"stargazers_count":4,"open_issues_count":3,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-11T06:24:46.426Z","etag":null,"topics":["i18n","international","mobx","responsive","toolkit","translate","typescript","utility"],"latest_commit_sha":null,"homepage":"https://idea2app.github.io/MobX-i18n/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/idea2app.png","metadata":{"files":{"readme":"ReadMe.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-18T23:48:27.000Z","updated_at":"2025-05-06T23:51:58.000Z","dependencies_parsed_at":"2024-06-21T15:22:00.271Z","dependency_job_id":"ef112816-fb27-4b66-bf2e-b84744376cc0","html_url":"https://github.com/idea2app/MobX-i18n","commit_stats":{"total_commits":13,"total_committers":1,"mean_commits":13.0,"dds":0.0,"last_synced_commit":"a33c9316bba06f3a4037a7a32edb258aacb2d2b3"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/idea2app/MobX-i18n","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idea2app%2FMobX-i18n","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idea2app%2FMobX-i18n/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idea2app%2FMobX-i18n/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idea2app%2FMobX-i18n/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/idea2app","download_url":"https://codeload.github.com/idea2app/MobX-i18n/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idea2app%2FMobX-i18n/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270005591,"owners_count":24510939,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["i18n","international","mobx","responsive","toolkit","translate","typescript","utility"],"created_at":"2024-11-21T13:46:34.246Z","updated_at":"2025-10-14T13:41:46.030Z","avatar_url":"https://github.com/idea2app.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MobX i18n\n\nResponsive **Translation** utility based on [TypeScript][1] \u0026 [MobX][2]\n\n[![MobX compatibility](https://img.shields.io/badge/Compatible-1?logo=mobx\u0026label=MobX%206%2F7)][2]\n[![NPM Dependency](https://img.shields.io/librariesio/github/idea2app/MobX-i18n.svg)][3]\n[![CI \u0026 CD](https://github.com/idea2app/MobX-i18n/actions/workflows/main.yml/badge.svg)][4]\n\n[![NPM](https://nodei.co/npm/mobx-i18n.png?downloads=true\u0026downloadRank=true\u0026stars=true)][5]\n\n## Features\n\n- [x] **Type hinting** of Text keys\n- [x] **Lambda Expression** values\n- [x] Space utility for CJK \u0026 other characters\n- [x] **Responsive re-rendering**\n- [x] **Async loading** of Language packages\n- [x] support **HTTP protocol** for **Server-side rendering**\n- [x] support BOM/DOM language API for Client-side rendering\n- [x] [Speech Synthesis API][6] for **Text-to-Speech** (TTS)\n\n## Versions\n\n|  SemVer   |  branch  |    status    | ES decorator |    MobX     |\n| :-------: | :------: | :----------: | :----------: | :---------: |\n| `\u003e=0.5.0` |  `main`  | ✅developing |   stage-3    |  `\u003e=6.11`   |\n| `\u003c0.5.0`  | `master` | ❌deprecated |   stage-2    | `\u003e=4 \u003c6.11` |\n\n## Text internationalization (React example)\n\nOriginal from https://github.com/idea2app/React-MobX-Bootstrap-ts\n\n### Installation\n\n```shell\nnpm i mobx mobx-react mobx-i18n\n```\n\n### Configuration\n\n#### `tsconfig.json`\n\n```json\n{\n    \"compilerOptions\": {\n        \"target\": \"ES6\",\n        \"useDefineForClassFields\": true,\n        \"experimentalDecorators\": false\n    }\n}\n```\n\n### Translation\n\n#### `translation/zh-CN.ts`\n\n```typescript\nimport { textJoin } from 'mobx-i18n';\n\nexport default {\n    open_source: '开源',\n    project: '项目',\n    love: ({ a, b }: Record\u003c'a' | 'b', string\u003e) =\u003e textJoin(a, '爱', b)\n} as const;\n```\n\n#### `translation/en-US.ts`\n\n```typescript\nimport { textJoin } from 'mobx-i18n';\n\nexport default {\n    open_source: 'Open Source',\n    project: 'project',\n    love: ({ a, b }: Record\u003c'a' | 'b', string\u003e) =\u003e textJoin(a, 'love', b)\n} as const;\n```\n\n### Initialization\n\n#### `model/Translation.ts`\n\n```typescript\nexport const i18n = new TranslationModel({\n    'zh-CN': zhCN,\n    'en-US': () =\u003e import('../translation/en-US')\n});\n\nexport const LanguageName: Record\u003c(typeof i18n)['currentLanguage'], string\u003e = {\n    'zh-CN': '简体中文',\n    'en-US': 'English'\n};\n```\n\n#### `page/index.tsx`\n\n```tsx\nimport { textJoin } from 'mobx-i18n';\nimport { observer } from 'mobx-react';\n\nimport { i18n, LanguageName } from '../model/Translation';\n\nexport const HomePage = observer(() =\u003e {\n    const { currentLanguage, t } = i18n;\n\n    return (\n        \u003c\u003e\n            \u003cselect\n                value={currentLanguage}\n                onChange={({ currentTarget: { value } }) =\u003e\n                    i18n.loadLanguages(value as typeof currentLanguage)\n                }\n            \u003e\n                {Object.entries(LanguageName).map(([code, name]) =\u003e (\n                    \u003coption key={code} value={code}\u003e\n                        {name}\n                    \u003c/option\u003e\n                ))}\n            \u003c/select\u003e\n            \u003cp\u003e\n                {t('love', {\n                    a: '我',\n                    b: textJoin(t('open_source'), t('project'))\n                })}\n            \u003c/p\u003e\n        \u003c/\u003e\n    );\n});\n```\n\n### Server Side Rendering (Next.js example)\n\nYou can use [React Context API][7] to share the `TranslationModel` instance cross Class \u0026 Function components in Client \u0026 Server runtimes, which has been all set in an [One-key Template Repository][8].\n\n## Text to Speech (WebCell example)\n\n### `pages/article.tsx`\n\n```tsx\nimport { component, observer } from 'web-cell';\nimport { SpeechSynthesisModel, SpeechSynthesisState } from 'mobx-i18n';\n\n@component({ tagName: 'article-page' })\n@observer\nexport class ArticlePage extends HTMLElement {\n    storeTTS = new SpeechSynthesisModel();\n\n    toggleSpeaking = () =\u003e {\n        const { storeTTS } = this;\n\n        if (storeTTS.state !== SpeechSynthesisState.Clear)\n            return storeTTS.toggle();\n\n        const text = SpeechSynthesisModel.getReadableText(\n            this.querySelector('article')\n        );\n        storeTTS.speak(text);\n    };\n\n    render() {\n        const speaking = this.storeTTS.state === SpeechSynthesisState.Speaking;\n\n        return (\n            \u003c\u003e\n                \u003cbutton\n                    style={{ background: speaking ? 'red' : 'blue' }}\n                    onClick={this.toggleSpeaking}\n                \u003e\n                    {speaking ? '🔇' : '📢'}\n                \u003c/button\u003e\n                \u003carticle\u003e\n                    \u003ch1\u003eThe Four Freedoms\u003c/h1\u003e\n                    \u003col\u003e\n                        \u003cli\u003eFreedom of speech and expression\u003c/li\u003e\n                        \u003cli\u003eFreedom of worship\u003c/li\u003e\n                        \u003cli\u003eFreedom from want\u003c/li\u003e\n                        \u003cli\u003eFreedom from fear\u003c/li\u003e\n                    \u003c/ol\u003e\n                \u003c/article\u003e\n            \u003c/\u003e\n        );\n    }\n}\n```\n\n## Inspired by\n\n1. https://github.com/infinum/react-mobx-translatable\n2. https://github.com/jverhoelen/react-mobx-i18n\n3. https://github.com/QuiiBz/next-international\n\n[1]: https://www.typescriptlang.org/\n[2]: https://mobx.js.org/\n[3]: https://libraries.io/npm/mobx-i18n\n[4]: https://github.com/idea2app/MobX-i18n/actions/workflows/main.yml\n[5]: https://nodei.co/npm/mobx-i18n/\n[6]: https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis\n[7]: https://legacy.reactjs.org/docs/context.html#passing-info-automatically-through-a-tree\n[8]: https://github.com/idea2app/Next-Bootstrap-ts\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidea2app%2Fmobx-i18n","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fidea2app%2Fmobx-i18n","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidea2app%2Fmobx-i18n/lists"}