{"id":15020338,"url":"https://github.com/zfletch/react-router-i18n","last_synced_at":"2025-10-25T17:30:34.541Z","repository":{"id":52613459,"uuid":"174363142","full_name":"zfletch/react-router-i18n","owner":"zfletch","description":"Internationalization library built on top of React Router","archived":false,"fork":false,"pushed_at":"2021-11-23T16:23:51.000Z","size":1861,"stargazers_count":28,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-31T09:23:43.992Z","etag":null,"topics":["i18n","internationalization","react","react-router"],"latest_commit_sha":null,"homepage":"https://zfletch.github.io/react-router-i18n/","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/zfletch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-03-07T14:44:00.000Z","updated_at":"2023-08-24T22:33:06.000Z","dependencies_parsed_at":"2022-09-26T22:00:37.066Z","dependency_job_id":null,"html_url":"https://github.com/zfletch/react-router-i18n","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zfletch%2Freact-router-i18n","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zfletch%2Freact-router-i18n/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zfletch%2Freact-router-i18n/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zfletch%2Freact-router-i18n/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zfletch","download_url":"https://codeload.github.com/zfletch/react-router-i18n/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238183649,"owners_count":19430162,"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":["i18n","internationalization","react","react-router"],"created_at":"2024-09-24T19:54:56.234Z","updated_at":"2025-10-25T17:30:34.041Z","avatar_url":"https://github.com/zfletch.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Router I18n\n\nThis is a small opinionated library for I18n (internationalization) using React Router.\n\n## Demo\n\n[https://zfletch.github.io/react-router-i18n/](https://zfletch.github.io/react-router-i18n/)\n\n## Installation\n\n`yarn add react-router-i18n`\n\nNote that this package has the following peer dependencies:\n\n```json\n{\n  \"react\": \"^16.8.4\",\n  \"react-dom\": \"^16.8.1\",\n  \"react-router-dom\": \"^4.3.0 || ^5.0.0\"\n}\n```\n\n(See project on [npm](https://www.npmjs.com/package/react-router-i18n))\n\n## How to use\n\n### Demo\n\nSee the demo [App.js](/src/demo/App.js) and [I18n.js](/src/demo/I18n.js).\n\n### Setup\n\nFirst, create a component called `I18n`. It should look like this:\n\n```jsx\nimport { createI18n } from 'react-router-i18n';\n\n// Array of supported locales\n// The first in the array is treated as the default locale\nconst locales = ['en', 'fr'];\n\n// Dictionary of translations\nconst translations = {\n  en: {\n    hello: 'Hello',\n  },\n  fr: {\n    hello: 'Bonjour',\n  }\n}\n\nconst I18n = createI18n(\n  locales,\n  translations,\n);\n\nexport default I18n;\n```\n\nThen make the following changes to your routes:\n\n```jsx\nimport React from 'react';\nimport { BrowserRouter as Router, Route } from 'react-router-dom';\n\n// Match locales with regular expression containing each locale separated by `|`\nconst base = '/:locale(en|fr)?';\n\nconst App = () =\u003e (\n  \u003cRouter\u003e\n    \u003c\u003e\n      {/* \u003cRoute exact path=\"/\" component={Home} /\u003e */}\n      \u003cRoute exact path={base} component={Home} /\u003e\n\n      {/* \u003cRoute path=\"/hello\" component={Hello} /\u003e */}\n      \u003cRoute path={`${base}/hello`} component={Hello} /\u003e\n    \u003c/\u003e\n  \u003c/Router\u003e\n);\n\nexport default App;\n```\n\n### Usage\n\nOnce you have everything set up, you can use the `I18n` component for localization:\n\n```jsx\nimport React from 'react';\n\nimport I18n from './I18n';\n\nconst Hello = () =\u003e (\n  \u003cdiv\u003e\n    \u003cI18n t=\"hello\" /\u003e\n  \u003c/div\u003e\n)\n\nexport default Hello;\n```\n\nSince we defined `\"hello\"` in the `translations` object above,\nthis component will display \"Hello\" when the user visits `/hello`, or `/en/hello`.\nIt will display \"Bonjour\" when the user visits `/fr/hello`.\n\n#### Links\n\nTo preserve the locale in links, the library provides `Link`, `NavLink`, and `Redirect` components.\nThese can be used anywhere the React Router component with the same name is used:\n\n```jsx\nimport React from 'react';\nimport { Link, NavLink, Redirect } from 'react-router-i18n';\n\nimport I18n from './I18n';\n\nconst Hello = () =\u003e (\n  \u003cdiv\u003e\n    \u003cI18n t=\"hello\" /\u003e\n\n    \u003cLink to=\"/\"\u003e\n      \u003cI18n t=\"homepage\" /\u003e\n    \u003c/Link\u003e\n  \u003c/div\u003e\n);\n\nexport default Hello;\n```\n\nTo create a link that does not preserve the locale, use `ignoreLocale`:\n\n```jsx\nimport React from 'react';\nimport { Link, NavLink, Redirect } from 'react-router-i18n';\n\nimport I18n from './I18n';\n\nconst Hello = () =\u003e (\n  \u003cdiv\u003e\n    \u003cI18n t=\"hello\" /\u003e\n\n    \u003cNavLink ignoreLocale to=\"/en/hello\"\u003e\n      English\n    \u003c/NavLink\u003e\n    \u003cNavLink ignoreLocale to=\"/fr/hello\"\u003e\n      French\n    \u003c/NavLink\u003e\n  \u003c/div\u003e\n);\n\nexport default Hello;\n```\n\n##### Note\n\nA `Link` must be used inside of a route that receives the `locale` param. For example:\n\n```jsx\nimport React from 'react';\nimport { BrowserRouter as Router, Route } from 'react-router-dom';\nimport { Link } from 'react-router-i18n';\n\nconst base = '/:locale(en|fr)?';\n\nconst App = () =\u003e (\n  \u003cRouter\u003e\n    \u003c\u003e\n      {/* This will not work because it does not receive `locale` */}\n      {/* \u003cLink to=\"/home\"\u003eHome\u003c/Link\u003e */}\n\n      {/* Use code like this instead */}\n      \u003cRoute path={base} render={() =\u003e \u003cLink to=\"/home\"\u003eHome\u003c/Link\u003e} /\u003e\n\n      \u003cRoute exact path={base} component={Home} /\u003e\n      \u003cRoute path={`${base}/hello`} component={Hello} /\u003e\n    \u003c/\u003e\n  \u003c/Router\u003e\n);\n\nexport default App;\n```\n\n#### Other functionality\n\n##### Nested translations\n\nThe `translations` object can have objects inside of it. For example:\n\n```javascript\nconst translations = {\n  en: {\n    home: {\n      title: 'Home',\n    }\n  },\n  fr: {\n    home: {\n      title: 'Accueil',\n    }\n  },\n};\n```\n\nThese can be used by giving the `I18n` component `t=\"home.title\"`:\n\n```jsx\n\u003cI18n t=\"home.title\" /\u003e\n```\n\n##### Function translations\n\nThe `translations` object can have a function as the translation. For example:\n\n```javascript\nconst translations = {\n  en: {\n    time: ({ hour, minute }) =\u003e `${hour}:${minute}`,\n  },\n  fr: {\n    time: ({ hour, minute }) =\u003e `${hour}h${minute}`,\n  },\n};\n```\n\nAn argument can be passed to the function by giving the `I18n` component `args`:\n\n```jsx\n\u003cI18n t=\"time\" args={{ hour: '12', minute: '30' }}  /\u003e\n```\n\n##### Translations outside of \u0026lt;I18n\u0026gt;\n\nTranslation text can also be retrieved outside of an `I18n` component using the `getTranslation` function. For example:\n\n```javascript\nconst translations = {\n  en: {\n    search: 'Search...'\n  },\n  fr: {\n    search: 'Rechercher...',\n  },\n}\n```\n\n```jsx\nconst { location } = this.props;\n\n\u003cinput placeholder={I18n.getTranslation(location, 'search')} /\u003e\n```\n\nNote that\n[location](https://github.com/ReactTraining/react-router/blob/0f5d701648568cf95bef66c9be0798c15eef6d50/packages/react-router/docs/api/location.md)\nneeds to be passed in as the first argument.\nThe `location` prop is passed to a component from React Router.\n\nThe `getTranslation` function takes an optional third argument that corresponds to the `args` attribute of the I18n component:\n\n```jsx\nconst { location } = this.props;\n\n\u003cinput placeholder={I18n.getTranslation(location, 'time', { hour: '12', minute: '30' })} /\u003e\n```\n\n##### Default translation\n\nIf there is no translation found for the given locale, the library will look in the following places:\n\n1. The same `t` in the default locale (i.e. the first locale in the locales array).\n2. The children of the `\u003cI18n\u003e` component.\n3. The `missingText` passed to the `createI18n` function. By default this is `false`, so if no translation text is found, the `\u003cI18n\u003e` component will simply not render.\n\nFor example, given the following `I18n` component:\n\n```jsx\nimport { createI18n } from 'react-router-i18n';\n\n// Array of supported locales\n// The first in the array is treated as the default locale\nconst locales = ['en', 'fr'];\n\n// Dictionary of translations\nconst translations = {\n  en: {\n    hello: 'Hello',\n  },\n  fr: {\n    goodbye: 'Au revoir',\n  }\n};\n\nconst I18n = createI18n(\n  locales,\n  translations,\n  'Unknown text',\n);\n\nexport default I18n;\n```\n\nUsed in this way:\n\n```jsx\n\u003c\u003e\n  \u003cI18n t=\"hello\" /\u003e\n  \u003cI18n t=\"goodbye\"\u003e\n    Goodbye\n  \u003c/I18n\u003e\n  \u003cI18n t=\"other\" /\u003e\n\u003c/\u003e\n```\n\nThe page when viewed with `/fr` will show:\n\n```\nHello\nAu revoir\nUnknown text\n```\n\nWith `/en` it will show:\n\n```\nHello\nGoodbye\nUnknown text\n```\n\n## Development\n\n### Installation\n\n`yarn install`\n\n### Running tests\n\n`yarn test`\n\n### Running demo application\n\n`yarn start`\n\n### Deploying demo application\n\n`yarn deploy`\n\n### Building\n\n`yarn build`\n\n### Publishing\n\n```\nyarn build\nnpm publish\n```\n\n(Make sure to update the `version` in `package.json` before publishing a new release.)\n\n## Upgrading Notes\n\nThis library is build on top of [DimiMikadze/create-react-library](https://github.com/DimiMikadze/create-react-library).\nTo upgrade to the latest version of `create-react-library`:\n\n* In `package.json`, everything above `devDependencies` should not be updated,\n  but everything below it should be replaced by the new versions in `create-react-library`.\n* Add back the dependencies for the project\n* All of the files in `./scripts` should be replaced with new versions in `create-react-library`.\n* All of the files in `./config` should be replaced with new versions in `create-react-library`.\n* Test to make sure that building and deploying demo application still work\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzfletch%2Freact-router-i18n","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzfletch%2Freact-router-i18n","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzfletch%2Freact-router-i18n/lists"}