{"id":15024735,"url":"https://github.com/muetze42/translator-js","last_synced_at":"2025-07-16T16:32:47.981Z","repository":{"id":254626581,"uuid":"846700474","full_name":"Muetze42/translator-js","owner":"Muetze42","description":"JavaScript (JSON) Translator based on Laravel™ Translator","archived":false,"fork":false,"pushed_at":"2024-09-19T08:14:43.000Z","size":70,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-14T08:22:43.510Z","etag":null,"topics":["javascript","laravel","localization","react","translator","typescript","vuejs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Muetze42.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","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},"funding":{"github":["Muetze42"],"patreon":null,"open_collective":null,"ko_fi":"normanhuth","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":["https://huth.it/coffee"]}},"created_at":"2024-08-23T19:07:54.000Z","updated_at":"2024-09-19T08:13:30.000Z","dependencies_parsed_at":"2024-08-28T23:43:52.307Z","dependency_job_id":null,"html_url":"https://github.com/Muetze42/translator-js","commit_stats":null,"previous_names":["muetze42/translator-js"],"tags_count":9,"template":false,"template_full_name":"Muetze42/repository-skeleton","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Muetze42%2Ftranslator-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Muetze42%2Ftranslator-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Muetze42%2Ftranslator-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Muetze42%2Ftranslator-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Muetze42","download_url":"https://codeload.github.com/Muetze42/translator-js/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219847662,"owners_count":16556349,"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","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":["javascript","laravel","localization","react","translator","typescript","vuejs"],"created_at":"2024-09-24T20:00:48.860Z","updated_at":"2024-10-14T08:22:51.518Z","avatar_url":"https://github.com/Muetze42.png","language":"TypeScript","funding_links":["https://github.com/sponsors/Muetze42","https://ko-fi.com/normanhuth","https://huth.it/coffee"],"categories":[],"sub_categories":[],"readme":"# TranslatorJs\n\nJavaScript (JSON) Translator based on [Laravel™ Translator](https://laravel.com/docs/localization).\nThe Translator supports variables (optional with first charakter uppercase or complete uppercase) and pluralization.\n\n## Installation\n\nUsing PNPM\n\n```shell\npnpm add -D @norman-huth/translator-js\n```\n\nUsing NPM\n\n```shell\nnpm i -D @norman-huth/translator-js\n```\n\n---\n\n## Contents\n\n* [Example](#example)\n* [Usage](#usage)\n  * [Simple VanillaJs](#simple-vanillajs)\n  * [Laravel™ Inertia.js](#laravel-with-inertiajs)\n    * [Vue.js / React / VanillaJs etc](#vuejs--react--vanillajs-etc)\n      * [Vue.js](#vuejs)\n    * [Optional: TypeScript](#optional-typescript)\n    * [Optional: ESLint](#optional-eslint)\n* [Digging Deeper](#digging-deeper)\n  * [The Translator Constructor](#the-translator-constructor)\n  * [`Translator.setTranslations()`](#translatorsettranslations)\n  * [`Translator.setLocale()`](#translatorsetlocale)\n  * [`Translator.bootstrap()`](#translatorbootstrap)\n  * [Example: Other Inertia.js Share Key](#example-other-inertiajs-share-key)\n\n## Example:\n\nExample JSON-File with translations:\n\n```json\n{\n  \"Hello\": \"Hallo\",\n  \"Welcome, :name\": \"Willkommen :name\",\n  \"Good morning :name\": \"Guten Morgen :Name\",\n  \"Good evening :name\": \"Guten Abend :NAME\",\n  \"There is one apple|There are many apples\": \"Hay una manzana|Hay muchas manzanas\",\n  \"apples\": \"{0} There are none|[1,19] There are some|[20,*] There are many\",\n  \"minutes_ago\": \"{1} :value minute ago|[2,*] :value minutes ago\"\n}\n```\n\n| Usage                                                          | Result              | Note    |\n|----------------------------------------------------------------|---------------------|---------|\n| `trans('Hello')`                                               | Hallo               |         |\n| `trans('Welcome, :name', {name: 'Norman'})`                    | Willkommen Norman   |         |\n| `trans('Good morning :name', {name: 'norman'})`                | Guten Morgen Norman | `:Name` |\n| `trans('Good evening :name', {name: 'norman'})`                | Guten Abend NORMAN  | `:NAME` |\n| `trans_choice('There is one apple\\|There are many apples', 1)` | Hay una manzana     |         |\n| `trans_choice('There is one apple\\|There are many apples', 5)` | Hay muchas manzanas |         |\n| `trans_choice('apples', 0)`                                    | There are none      |         |\n| `trans_choice('apples', 12)`                                   | There are some      |         |\n| `trans_choice('apples', 22)`                                   | There are many      |         |\n| `trans_choice('minutes_ago', 1, {value: 1})`                   | 1 minute ago        |         |\n| `trans_choice('minutes_ago', 5, {value: 5})`                   | 5 minutes ago       |         |\n\n## Usage\n\n### Simple VanillaJs\n\n```javascript\nimport Translator from '@norman-huth/translator-js'\n\nconst Trans = new Translator()\n\nreturn Trans.trans('Hello')\n```\n\nOr create alternativ an \"empty\" instance:\n\n```javascript\nTranslator.factory()\nTranslator.factory(translations)\n```\n\n### Laravel™ with Inertia.js\n\nShare the App JSON-Translations via `HandleInertiaRequests` middleware.\n\n```php\nclass HandleInertiaRequests extends Middleware\n{\n    // --\n\n    /**\n     * Define the props that are shared by default.\n     *\n     * @return array\u003cstring, mixed\u003e\n     */\n    public function share(Request $request): array\n    {\n        return [\n            ...parent::share($request),\n            'translations' =\u003e $this-\u003ejsonTranslations(),\n        ];\n    }\n\n    /**\n     * Load the messages for the given locale.\n     *\n     * @return array\u003cstring, string\u003e\n     */\n    protected function jsonTranslations(): array\n    {\n        return app('translator')\n            -\u003egetLoader()\n            -\u003eload(app()-\u003egetLocale(), '*', '*');\n    }\n}\n```\n\n#### Vue.js / React / VanillaJs etc\n\nAdd the Translator to the `/resources/js/bootstrap.{js|ts}`.\nThis example add the alias `__()` for `trans()`. This makes it possible to use `trans()` or `__()` for translation well\nas in Laravel™.\n\n```javascript\nimport Translator from '@norman-huth/translator-js'\n\nconst JsonTranslator = new Translator()\n\nwindow.__ = function(key, replace = {}) {\n  return JsonTranslator.trans(key, replace)\n}\nwindow.trans = function(key, replace = {}) {\n  return JsonTranslator.trans(key, replace)\n}\nwindow.trans_choice = function(key, number, replace = {}) {\n  return JsonTranslator.trans_choice(key, number, replace)\n}\n```\n\nTypeScript:\n\n```javascript\n//...\nwindow.__ = function(key: string, replace = {}) {\n  return JsonTranslator.trans(key, replace)\n}\nwindow.trans = function(key: string, replace = {}) {\n  return JsonTranslator.trans(key, replace)\n}\nwindow.trans_choice = function(key: string, number: number, replace = {}) {\n  return JsonTranslator.trans_choice(key, number, replace)\n}\n```\n\n##### Vue.js\n\nTo have the functions also available in the `\u003ctemplate\u003e`, edit the `/resources/js/app.{js|ts}` and add the functions as\nmixin:\n\n```javascript\ncreateInertiaApp({\n  //...\n  setup({ el, App, props, plugin }) {\n    return createApp({ render: () =\u003e h(App, props) })\n      .use(plugin)\n      .mixin({\n        methods: {\n          __: function(key, replace = {}) {\n            return __(key, replace)\n          },\n          trans: function(key, replace = {}) {\n            return trans(key, replace)\n          },\n          trans_choice: function(key, number, replace = {}) {\n            return trans_choice(key, number, replace)\n          }\n        }\n      })\n      .mount(el);\n  },\n  //...\n})\n```\n\nTypeScript:\n\n```javascript\n//..\n__: function(key: string, replace = {}) {\n  return __(key, replace)\n},\ntrans: function(key: string, replace = {}) {\n  return trans(key, replace)\n},\ntrans_choice: function(key: string, number: number, replace = {}) {\n  return trans_choice(key, number, replace)\n}\n```\n\n##### Optional: TypeScript\n\nExtend the `/resources/js/types/global.d.ts` file.\n\n```typescript\n//...\nconst JsonTranslator = new Translator()\nconst __ = (key: string, replace = {}) =\u003e {\n  return JsonTranslator.translator(key, replace)\n}\nconst trans = (key: string, replace = {}) =\u003e {\n  return JsonTranslator.translator(key, replace)\n}\nconst trans_choice = (key, number, replace = {}) =\u003e {\n  return JsonTranslator.trans_choice(key, number, replace)\n}\n\ndeclare global {\n  interface Window {\n    axios: AxiosInstance;\n    __: typeof __\n    trans: typeof trans\n    trans_choice: typeof trans_choice\n  }\n\n  let __ = function(key: string, replace = {}) {\n    return JsonTranslator.trans(key, replace)\n  }\n  let trans = function(key: string, replace = {}) {\n    return JsonTranslator.trans(key, replace)\n  }\n  let trans_choice = function(key, number, replace = {}) {\n    return JsonTranslator.trans_choice(key, number, replace)\n  }\n  //..\n}\n\n// And for Vue.js \u003ctemplate\u003e\ndeclare module 'vue' {\n  interface ComponentCustomProperties {\n    // ...\n    __: typeof __\n    trans: typeof trans\n    trans_choice: typeof trans_choice\n  }\n}\n```\n\n##### Optional: ESLint\n\n`.eslintrc.cjs`\n\n```javascript\nmodule.exports = {\n  globals: {\n    __: true,\n    trans: true,\n    trans_choice: true,\n  },\n}\n```\n\n---\n\n### Digging Deeper\n\nThe locale is only used from the pluralizer.\n\n#### The Translator Constructor\n\nThis script is oriented towards Inertia.js and determines the translation from the JSON (`{\"translations\": {}}`) of\nthe `data-page` attribute in the `div id=\"app\".` and the locale by `\u003chtml lang=\"en\"\u003e` tag.\nBy default the class bootstrap the translations data.\n\nThe Constructor with defaults:\n\n```javascript\nconstructor(\n  prop: string = 'translations',\n  elementId: string = 'app',\n  dataAttribute: string = 'page',\n  locale: string | null = null,\n  translations: Translations | null = null,\n  bootstrap: boolean = true\n)\n```\n\n| Argument      | Default      | Description                                                  |\n|---------------|--------------|--------------------------------------------------------------|\n| prop          | translations | The page props key with the translations                     |\n| elementId     | app          | The ID of the described div                                  |\n| dataAttribute | page         | The div data-* attribute                                     |\n| locale        | `null`       | Initialize the class with locale (override on bootrap)       |\n| translations  | `null`       | Initialize the class with translations (override on bootrap) |\n| bootstrap     | `true`       | Bootrap the translations' data.                              |\n\n#### Translator.setTranslations\n\nManually set the translations.\n\n```javascript\nTranslator.setTranslations(\n  { \"Foo\": \"Bar\" }\n)\n```\n\n#### Translator.setLocale\n\nManually set the locale.\n\n```javascript\nTranslator.setLocale('en')\n```\n\n#### Translator.bootstrap\n\nBootrap the translations' data (again).\n\n```javascript\nTranslator.bootstrap()\n```\n\n#### Example: Other Inertia.js Share Key\n\nChange the array for the translations.\n\n```php\nclass HandleInertiaRequests extends Middleware\n{\n    public function share(Request $request): array\n    {\n        return [\n            ...parent::share($request),\n            'app' =\u003e [\n                'translations' =\u003e $this-\u003ejsonTranslations(),\n            ],\n        ];\n    }\n}\n```\n\nSet nested array by using \"dot\" notation in the Translator script:\n\n```javascript\nimport Translator from '@norman-huth/translator-js'\n\nconst JsonTranslator = new Translator('app.translations')\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmuetze42%2Ftranslator-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmuetze42%2Ftranslator-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmuetze42%2Ftranslator-js/lists"}