{"id":17268978,"url":"https://github.com/janek26/i18n","last_synced_at":"2026-02-17T02:32:25.584Z","repository":{"id":41795515,"uuid":"181963321","full_name":"janek26/i18n","owner":"janek26","description":"i18n for modern JS developer","archived":false,"fork":false,"pushed_at":"2023-01-03T19:53:46.000Z","size":1506,"stargazers_count":0,"open_issues_count":16,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-21T12:46:04.274Z","etag":null,"topics":["i18n","internationalization","l10n","language","localization","template-literals","translation"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/janek26.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"janek26","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":"paypal.me/jrahrt"}},"created_at":"2019-04-17T20:25:52.000Z","updated_at":"2019-06-06T14:32:53.000Z","dependencies_parsed_at":"2023-02-01T09:32:14.535Z","dependency_job_id":null,"html_url":"https://github.com/janek26/i18n","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/janek26/i18n","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janek26%2Fi18n","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janek26%2Fi18n/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janek26%2Fi18n/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janek26%2Fi18n/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/janek26","download_url":"https://codeload.github.com/janek26/i18n/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janek26%2Fi18n/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29531019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-17T00:57:22.232Z","status":"online","status_checked_at":"2026-02-17T02:00:08.105Z","response_time":100,"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","internationalization","l10n","language","localization","template-literals","translation"],"created_at":"2024-10-15T08:14:57.571Z","updated_at":"2026-02-17T02:32:25.548Z","avatar_url":"https://github.com/janek26.png","language":"JavaScript","funding_links":["https://github.com/sponsors/janek26","paypal.me/jrahrt"],"categories":[],"sub_categories":[],"readme":"@janek26/i18n\n===\n![Picture of a simple usecase](https://raw.githubusercontent.com/janek26/i18n/master/images/carbon.png \"Simple usecase\")\nThat's it. The rest is optional. \n\n[![Build Status](https://travis-ci.org/janek26/i18n.svg?branch=master)](https://travis-ci.org/janek26/i18n)\n[![NPM Version](https://img.shields.io/npm/v/@janek26\\/i18n.svg)](https://www.npmjs.com/package/@janek26/i18n)\n![Size](https://img.shields.io/bundlephobia/min/@janek26/i18n.svg)\n![Issues](https://img.shields.io/github/issues/janek26/i18n.svg)\n\nThis way you can use i18n today and implement the details another time!\n\n# Getting started with i18n\n\n```js\nimport { t, p, mod, setConfig } from '.'\n\n// (optional) Init resources\nsetConfig({\n  lng: ['de', 'en'],  // sorted by priority (fallback)\n  resources: {\n    // async resources needs to be a function returning a promise\n    // the function will just be called when the resource is needed (in lng)\n    en: () =\u003e returnsPromiseWhichResolvesToTheSameFormatAsBelow(),\n    // sync resource\n    de: {\n      translation: {\n        'Hello ${1}!': 'Moin ${1}!',\n      },\n      modifier: {\n        int: int =\u003e int * 10,\n      },\n      plural: {\n        '${1} tree': c =\u003e (c === 1 ? `ein Baum` : `${c} Bäume`),\n      },\n    },\n  },\n  // Could be used to extract (unknown) keys\n  onKey: ({ key, type, lng }) =\u003e {}, \n})\n\nt`Hello ${'Username'}!`\n// =\u003e Moin Username!\np`${1} tree`\n// =\u003e 1 Baum\np`${5} tree`\n// =\u003e 5 Bäume\nmod(int)(5)\n// =\u003e 50\n```\n\n# API\nThe module exports 5 properties: `t, p, mod, setConfig, getConfig`\n## Methods\n### `setConfig(config: ConfigObject): Promise\u003cvoid\u003e`\nThe functions `t, p \u0026 mod` will use the new config after the returned Promise resolves.\nYou don't need to set the whole config as `setConfig` will copy missing keys from the old or default config. You can also add new resources without commiting all old ones again.\n\nIn practice this means you can simply do:\n```js\n// call setConfig to set resources and default language\n\n//User wants to change UI language\nawait setConfig({ lng: 'de' })\n```\nto set a new language. If the resource for `de` is a function returning a promise it will call the function now and resolve as soon as the resource does.\n\nTo add resources after the first init just do:\n```js\nawait setConfig({\n  resources: {\n    'nl': \u003cResourceObject\u003e\n  }\n})\n```\nIt will keep all initinal resources and add the new one. \n\nIf the new one has the same key as an old one it will override it. This process **will not** keep your old translation, plural and modifier keys!\n\n### `` t`\u003cString\u003e`: String ``\nt will calculate a key based on the provided string. All variables should be used using the `${}` syntax.\n\nUsing this key it will lookup in the resource maps prioritized by the provided `config.lng` array. If some key in one resource map matches it will use the provided value by this key and insert the values to it.\n\nTo find the used key use `onKey` in `config`.\n\nExample usage:\n```js\n  t`Hallo` // =\u003e Hallo (if not defined in used resources)\n```\n\n### `` p`\u003cString\u003e`: String ``\np will also calculate a key based on the provided string. Only one variable is accepted using `${}` syntax. This variable should be `count: Int`. You can use this variable in your resource plural function to determine if it is plural or not.\n\nExample usage:\n```js\nsetConfig({\n  lng: ['en'],\n  resources: {\n    en: {\n      plural: {\n        \u003cPluralKey\u003e: (count: Int) =\u003e (count*10).toString()\n      }\n    }\n  }\n})\n\np`${5} drinks` // =\u003e '50', if PluralKey is matched\n```\n\n### `mod(\u003cModifierKey\u003e): Function(...args): String`\nYou can apply any modifier function from a resource to any value(s). Define which modifier to use from the resource using the ModifierKey. `mod` will return another function then.\n\nYou can provide as many arguments to the returned function as you want to. Your modifier defined in your resource then can handle the arguments.\n\nExample usage: \n```js\nsetConfig({\n  lng: ['en'],\n  resources: {\n    en: {\n      modifier: {\n        \u003cModifierKey\u003e: (arg1, arg2) =\u003e (arg1 * arg2).toString()\n      }\n    }\n  }\n})\n\n// mod(\u003cModifierKey\u003e)(arg1, arg2)\nmod(\u003cModifierKey\u003e)(7, 5) // =\u003e 35\n```\n\n### `getConfig(): ConfigObject`\nthat's it.\n## Objects\n### `ConfigObject`\nA ConfigObject has a shape like this:\n```js\n{\n  lng: Array\u003cResourceId\u003e,\n  resources: {\n    \u003cResourceId\u003e: \u003cResourceObject\u003e,\n  },\n  onKey: ({\n    key: TranslationKey|PluralKey|ModifierKey, \n    type: 'translation'|'plural'|'modifier'|'unknown_translation'|'unknown_plural'|'unknown_modifier', \n    lng: ResourceId\n  }) =\u003e void\n}\n```\n\n### `ResourceObject`\nA ResourceObject contains the `translation, plural \u0026 modifier` key for a ResourceId. It looks like this:\n```js\n{\n  translation: {\n    \u003cTranslationKey\u003e: \u003cTranslationTemplate\u003e\n  },\n  plural: {\n    \u003cPluralKey\u003e: (count: Int) =\u003e String\n  },\n  modifier: {\n    \u003cModifierKey\u003e: (...args) =\u003e String\n  }\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanek26%2Fi18n","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjanek26%2Fi18n","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanek26%2Fi18n/lists"}