{"id":13515369,"url":"https://github.com/lukeed/rosetta","last_synced_at":"2025-10-09T18:23:26.022Z","repository":{"id":39999018,"uuid":"248382483","full_name":"lukeed/rosetta","owner":"lukeed","description":"A general purpose internationalization library in 292 bytes","archived":false,"fork":false,"pushed_at":"2024-01-20T17:17:37.000Z","size":207,"stargazers_count":792,"open_issues_count":4,"forks_count":16,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-25T13:42:59.828Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/lukeed.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license","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}},"created_at":"2020-03-19T01:29:35.000Z","updated_at":"2025-03-20T12:39:41.000Z","dependencies_parsed_at":"2022-06-26T07:07:31.650Z","dependency_job_id":"770ba7df-2fe0-40a6-bb30-7651b8d9e95a","html_url":"https://github.com/lukeed/rosetta","commit_stats":{"total_commits":29,"total_committers":3,"mean_commits":9.666666666666666,"dds":0.06896551724137934,"last_synced_commit":"0c6d10f2785a59c963ee8557c817b6c5b6c27fed"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Frosetta","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Frosetta/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Frosetta/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Frosetta/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lukeed","download_url":"https://codeload.github.com/lukeed/rosetta/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246418657,"owners_count":20773934,"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":[],"created_at":"2024-08-01T05:01:10.282Z","updated_at":"2025-10-09T18:23:20.969Z","avatar_url":"https://github.com/lukeed.png","language":"JavaScript","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"logo.jpg\" alt=\"rosetta\" height=\"130\" /\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://npmjs.org/package/rosetta\"\u003e\n    \u003cimg src=\"https://badgen.now.sh/npm/v/rosetta\" alt=\"version\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/lukeed/rosetta/actions\"\u003e\n    \u003cimg src=\"https://github.com/lukeed/rosetta/workflows/CI/badge.svg\" alt=\"CI\" /\u003e\n  \u003c/a\u003e\n\t\u003ca href=\"https://licenses.dev/npm/rosetta\"\u003e\n\t\t\u003cimg src=\"https://licenses.dev/b/npm/rosetta\" alt=\"licenses\" /\u003e\n\t\u003c/a\u003e\n\t\u003ca href=\"https://npmjs.org/package/rosetta\"\u003e\n    \u003cimg src=\"https://badgen.now.sh/npm/dm/rosetta\" alt=\"downloads\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/lukeed/rosetta\"\u003e\n    \u003cimg src=\"https://badgen.net/codecov/c/github/lukeed/rosetta\" alt=\"codecov\" /\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003eA general purpose internationalization library in 298 bytes!\u003c/div\u003e\n\n## Features\n\n* Simple and Familiar API\n* Unobstrusive and Unopinionated\n* Less than 300 bytes – including dependencies!\n\n\n## Install\n\n```\n$ npm install --save rosetta\n```\n\n\n## Usage\n\n```js\nimport rosetta from 'rosetta';\n\nconst i18n = rosetta({\n  en: {\n    intro: {\n      welcome: 'Welcome, {{username}}!',\n      text: 'I hope you find this useful.',\n    },\n    support(obj) {\n      let hour = Math.floor(Math.random() * 3) + 9;\n      let str = `For questions, I'm available on ${obj.date.toLocaleDateString()}`;\n      str += `, any time after ${hour}:00.`\n      return str;\n    }\n  }\n});\n\n// set default language\ni18n.locale('en');\n\n// add new language\ni18n.set('pt', {\n  intro: {\n    welcome: obj =\u003e `Benvind${obj.feminine ? 'a' : 'o'}, ${obj.username}!`,\n    text: 'Espero que você ache isso útil.'\n  }\n});\n\n// append extra key(s) to existing language\ni18n.set('pt', {\n  support(obj) {\n    let hour = Math.floor(Math.random() * 3) + 9;\n    let str = `Se tiver perguntas, estou disponível em ${obj.date.toLocaleDateString()}`;\n    str += `, qualquer hora depois às ${hour}:00.`\n    return str;\n  }\n});\n\nconst data = {\n  feminine: false,\n  username: 'lukeed',\n  date: new Date()\n};\n\n// Retrieve translations\n// NOTE: Relies on \"en\" default\ni18n.t('intro.welcome', data); //=\u003e 'Welcome, lukeed!'\ni18n.t('intro.text', data); //=\u003e 'I hope you find this useful.'\ni18n.t('support', data); //=\u003e 'For questions, I'm available on 4/8/2020, any time after 11:00.'\n\n// Retrieve translations w/ lang override\ni18n.t('intro.welcome', data, 'pt'); //=\u003e 'Benvindo, lukeed!'\n\n// Change default language key\ni18n.locale('pt');\n\n// Retrieve translations w/ new defaults\ni18n.t('intro.text', data); //=\u003e 'Espero que você ache isso útil.'\ni18n.t('intro.text', data, 'en'); //=\u003e 'I hope you find this useful.'\n```\n\n\n## API\n\n### rosetta(dict?)\nReturns: `Rosetta`\n\nInitializes a new `Rosetta` instance.\u003cbr\u003eYou may optionally provide an initial translation object.\n\n### rosetta.locale(lang?)\nReturns: `String`\n\nSets the language code for the `Rosetta` instance.\u003cbr\u003eThis will cause all [`rossetta.t()`](#rosettatkey-params-lang) lookups to assume this `lang` code.\n\nThe function will return the currently active `lang` code. This means that a setting a new value will reply with the same value. Additionally, calling `locale()` without any argument will return the `lang` code that the `Rosetta` instance was last given.\n\n#### lang\nType: `String`\u003cbr\u003e\nRequired: `false`\n\nThe language code to choose.\u003cbr\u003e\nIf `locale()` is called without an argument (or with a falsey value), then the current `lang` code is returned.\n\n### rosetta.set(lang, table)\n\nMerge (or override) translation keys into the `lang` collection.\n\n#### lang\nType: `String`\n\nThe language code to target.\n\n#### table\nType: `Object`\n\nA new record of key-values to merge into the `lang`'s dictionary.\n\nEach key within the `table` can correspond to a function or a string template.\n\nWhen using a function, it will receive the entire data input (see [`params`](#params)).\u003cbr\u003eYou are required to ensure the function returns a (string) value of your liking.\n\nWhen using a string template, anything within double curly brackets (`{{ example }}`) will be interpreted as a key path and interpolated via [`templite`](https://github.com/lukeed/templite). The key path can use dot-notation to access nested values from the data input (see [`params`](#params)). Additionally, if a key path did not resolve to a value, an empty string is injected.\n\n```js\nconst ctx = rosetta({\n  en: {\n    foo: (obj) =\u003e `function sees \"${obj.value || '~DEFAULT~'}\"`,\n    bar: 'template sees \"{{value}}\"'\n  }\n});\n\nctx.t('foo', {}, 'en');\n//=\u003e 'function sees \"~DEFAULT~\"\nctx.t('foo', { value: 123 }, 'en');\n//=\u003e 'function sees \"123\"\n\nctx.t('bar', {}, 'en');\n//=\u003e 'template sees \"\"\nctx.t('bar', { value: 123 }, 'en');\n//=\u003e 'template sees \"123\"\n```\n\n### rosetta.table(lang)\nReturns: `Object` or `undefined`\n\nRetrieve the the `lang`'s full dictionary/table of translation keys.\n\nIf the language does not exist (aka, no translations have been provided for it), you'll receive `undefined`.\u003cbr\u003eOtherwise, you'll receive the full object as it exists within the `Rosetta` instance. See [`table`](#table).\n\n\u003e **Important:** Manipulating this object is any way will mutate and affect your `Rosetta` instance. Be careful!\n\n#### lang\nType: `String`\n\nThe language code's table to retrieve.\n\n\n### rosetta.t(key, params?, lang?)\nReturns: `String`\n\nRetrieve the value for a given `key`.\n\n\u003e **Important:** In the normal/default mode, an empty string will be returned for unknown keys.\u003cbr\u003eConversely, in [\"debug\" mode](#debugging), an error message will be printed and `undefined` will be returned for unknown keys.\n\n#### key\nType: `String` or `Array\u003cString|Number\u003e`\n\nThe identifier to retrieve.\n\nA `key` can access nested properties via:\n\n* a string that with dot notation \u0026mdash; `'foo.bar.1.baz'`\n* an array of individual key segments \u0026mdash; `['foo', 'bar', 1, 'baz']`\n\n\u003e **Important:** You are expected to know \u0026 traverse your own dictionary structure correctly.\n\n```js\nconst ctx = rosetta({\n  en: {\n    fruits: {\n      apple: 'apple',\n    }\n  }\n});\n\nctx.locale('en');\n\nctx.t('fruits.apple'); //=\u003e 'apple'\nctx.t(['fruits', 'apple']); //=\u003e 'apple'\n```\n\n### params\nType: `any`\u003cbr\u003e\nOptional: `true`\n\nThe data object argument to pass your dictionary keys' string templates and/or functions.\n\n\u003e **Note:** If your *string template* tries to access a key that doesn't exist, an empty string is injected.\n\n```js\nconst ctx = rosetta({\n  es: {\n    hello: '¡Hola {{name}}!'\n  },\n  en: {\n    hello(obj) {\n      return obj.name === 'lukeed' ? 'wazzzuppp' : `Hello, ${obj.name}!`;\n    },\n  },\n  pt: {\n    hello: 'Oi {{person}}, tudo bem?' // \u003c-- key is wrong\n  },\n});\n\nconst user1 = { name: 'lukeed' };\nconst user2 = { name: 'Billy' };\n\nctx.t('hello', user1, 'es'); //=\u003e '¡Hola lukeed!'\n\nctx.t('hello', user1, 'en'); //=\u003e 'wazzzuppp'\nctx.t('hello', user2, 'en'); //=\u003e 'Hello, Billy!'\n\nctx.t('hello', user1, 'pt'); //=\u003e 'Oi , tudo bem?'\n```\n\n### lang\nType: `String`\u003cbr\u003e\nOptional: `true`\n\nA language code override without changing the entire `Rosetta` instance's default language.\n\n```js\nconst ctx = rosetta();\n\nctx.locale('en'); //=\u003e set default\n\nctx.t('greeting', 'lukeed');\n//=\u003e (en) 'Hello lukeed!'\nctx.t('greeting', 'lukeed', 'es');\n//=\u003e (es) '¡Hola lukeed!'\nctx.t('bye');\n//=\u003e (en) 'Cya'\n```\n\n## Debugging\n\nThere is a \"debug\" mode included for **development** environments.\n\nThe **only** difference with \"debug\" mode is that [`rossetta.t()`](#rosettatkey-params-lang) will log an error to the console when attempting to access a `key` that does not exist. Conversely, the main/default runtime will quietly return an an empty string for consistent output.\n\nOtherwise, the [API](#api) is _exactly_ the same as the main/default export!\u003cbr\u003eThis makes it easy to alias or swap the versions for development vs production bundles. Checkout the [Configuration](#configuration) section below for recipes.\n\n```js\n// debug mode\nimport rosetta from 'rosetta/debug';\n\nconst i18n = rosetta({\n  en: {\n    hello: 'hello'\n  }\n});\n\ni18n.locale('en');\n\ni18n.t('hello');\n//=\u003e 'hello'\n\ni18n.t('foobar');\n// [rosetta] Missing the \"foobar\" key within the \"en\" dictionary\n//=\u003e undefined\n```\n\n\u003e **Note:** With the non-\"debug\" runtime, an empty string would be returned for the `foobar` key.\n\n#### Configuration\n\nHere are quick configuration recipes for Rollup and webpack that allow you to choose the right version of `rosetta` for your current environment _without changing you application code_.\n\nWith both recipes, you will import `rosetta` like this:\n\n```js\nimport rosetta from 'rosetta';\n```\n\nIt is up to the bundler to change what `'rosetta'` resolves to...\n\n***Rollup***\n\nYou will need to install [`@rollup/plugin-alias`](https://github.com/rollup/plugins/tree/master/packages/alias) before continuing.\n\n```js\nconst isDev = /*custom logic*/ || !!process.env.ROLLUP_WATCH;\n\nexport default {\n  // ...,\n  plugins: [\n    // ...\n    require('@rollup/plugin-alias')({\n      entries: {\n        rosetta: isDev ? 'rosetta/debug' : 'rosetta'\n      }\n    })\n  ]\n}\n```\n\n***webpack***\n\nThe ability to add aliases within webpack comes by default.\u003cbr\u003eOne simply needs to add a [`resolve.alias`](https://webpack.js.org/configuration/resolve/#resolvealias) value depending on the environment:\n\n```js\nconst isDev = /*specific to your config*/;\n\nmodule.exports = {\n  //...,\n  resolve: {\n    alias: {\n      // ...,\n      rosetta: isDev ? 'rosetta/debug' : 'rosetta'\n    }\n  }\n}\n```\n\n\n## Runtime Support\n\nThe library makes use of [Object shorthand methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions#Browser_compatibility) and [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Browser_compatibility).\u003cbr\u003eThis yields the following support matrix:\n\n| Chrome | Safari | Firefox | Edge | IE | Node.js |\n|:---:|:--:|:---:|:---:|:---:|:----:|\n| 45+ | 9+ | 34+ | 12+ | :x: | 4.0+ |\n\nIf you need to support older platforms, simply attach `rosetta` to your project's Babel (or similar) configuration.\n\n## Examples\n\n* [**Using Next.js**](https://github.com/zeit/next.js/tree/canary/examples/with-i18n-rosetta) \u0026mdash; Thank you [@StarpTech](https://github.com/StarpTech)\u003cbr\u003e_Official Next.js example using React Hooks and Context to provide SSR, SSG, CSR compatible i18n solutions._\n* [**Localization solution for Next.js**](https://github.com/StarpTech/next-localization) \u0026mdash; \u003cbr\u003e_Lightweight Internationalization (i18n) library for Next.js 10+_\n\n## Credits\n\nThank you [@7sempra](https://github.com/7sempra) for gifting the `rosetta` name on npm.\n\n## License\n\nMIT © [Luke Edwards](https://lukeed.com)\n","funding_links":[],"categories":["JavaScript","📦 Libraries","Packages","I18N"],"sub_categories":["JavaScript / TypeScript","i18n","Reactive Programming"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukeed%2Frosetta","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flukeed%2Frosetta","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukeed%2Frosetta/lists"}