{"id":13422504,"url":"https://github.com/martinandert/react-translate-component","last_synced_at":"2025-04-04T18:07:19.681Z","repository":{"id":14427629,"uuid":"17138797","full_name":"martinandert/react-translate-component","owner":"martinandert","description":"A component for React that utilizes the Counterpart module to provide multi-lingual/localized text content.","archived":false,"fork":false,"pushed_at":"2018-02-28T07:47:41.000Z","size":72,"stargazers_count":322,"open_issues_count":9,"forks_count":31,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-28T17:07:53.342Z","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/martinandert.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}},"created_at":"2014-02-24T14:33:51.000Z","updated_at":"2024-07-10T15:44:52.000Z","dependencies_parsed_at":"2022-08-31T18:10:54.915Z","dependency_job_id":null,"html_url":"https://github.com/martinandert/react-translate-component","commit_stats":null,"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinandert%2Freact-translate-component","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinandert%2Freact-translate-component/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinandert%2Freact-translate-component/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinandert%2Freact-translate-component/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/martinandert","download_url":"https://codeload.github.com/martinandert/react-translate-component/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247226213,"owners_count":20904465,"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-07-30T23:00:46.386Z","updated_at":"2025-04-04T18:07:19.657Z","avatar_url":"https://github.com/martinandert.png","language":"JavaScript","funding_links":[],"categories":["Utilities","Uncategorized","Awesome React","📦 Libraries"],"sub_categories":["Miscellaneous","Uncategorized","Tools","React / React Native"],"readme":"# React Translate Component\n\nTranslate is a component for [React][1] that utilizes the [Counterpart module][2] and the [Interpolate component][3] to provide multi-lingual/localized text content. It allows switching locales without a page reload.\n\n\n## Installation\n\nInstall via npm:\n\n```bash\n% npm install react-translate-component\n```\n\n\n## Usage\n\nHere is a quick-start tutorial to get you up and running with Translate. It's a step-by-step guide on how to build a simple app that uses the Translate component from scratch. We assume you have recent versions of [Node.js][5] and [npm][6] installed.\n\nFirst, let's create a new project:\n\n```bash\n$ mkdir translate-example\n$ cd translate-example\n$ touch client.js\n$ npm init                   # accept all defaults here\n```\n\nNext, add the dependencies our little project requires:\n\n```bash\n$ npm install react counterpart react-interpolate-component react-translate-component --save\n```\n\nThe `react`, `counterpart` and `react-interpolate-component` packages are peer dependencies of `react-translate-component` and need to be installed along-side of it.\n\nWe will put our application logic into `client.js`. Open the file in your favorite editor and add the following lines:\n\n```js\n'use strict';\n\nvar counterpart = require('counterpart');\nvar React       = require('react');\nvar ReactDOM    = require('react-dom');\nvar Translate   = require('react-translate-component');\n```\n\nThis loads the localization library, React and our Translate component.\n\nLet's write our entry-point React component. Add the following code to the file:\n\n```jsx\nclass MyApp extends React.Component {\n  render() {\n    return (\n      \u003chtml\u003e\n        \u003chead\u003e\n          \u003cmeta charSet=\"utf-8\" /\u003e\n          \u003ctitle\u003eReact Translate Quick-Start\u003c/title\u003e\n          \u003cscript src=\"/bundle.js\" /\u003e\n        \u003c/head\u003e\n\n        \u003cbody\u003e\n          --\u003e body content will be added soon \u003c--\n        \u003c/body\u003e\n      \u003c/html\u003e\n    );\n  }\n}\n\nif (typeof window !== 'undefined') {\n  window.onload = function() {\n    ReactDOM.render(\u003cMyApp /\u003e, document);\n  };\n}\n\nmodule.exports = MyApp;\n```\n\nNow we have the basic HTML chrome for our tiny little app.\n\nNext, we will create a LocaleSwitcher component which will be used to, well, switch locales. Here is the code to append to `client.js`:\n\n```jsx\nclass LocaleSwitcher extends React.Component {\n  handleChange(e) {\n    counterpart.setLocale(e.target.value);\n  }\n\n  render() {\n    return (\n      \u003cp\u003e\n        \u003cspan\u003eSwitch Locale:\u003c/span\u003e\n\n        \u003cselect defaultValue={counterpart.getLocale()} onChange={this.handleChange}\u003e\n          \u003coption\u003een\u003c/option\u003e\n          \u003coption\u003ede\u003c/option\u003e\n        \u003c/select\u003e\n      \u003c/p\u003e\n    );\n  }\n}\n```\n\nFor demonstration purposes, we don't bother and hard-code the available locales.\n\nWhenever the user selects a different locale from the drop-down, we correspondingly set the new drop-down's value as locale in the Counterpart library, which in turn triggers an event that our (soon to be integrated) Translate component listens to. As initially active value for the select element we specify Counterpart's current locale (\"en\" by default).\n\nNow add LocaleSwitcher as child of the empty body element of our MyApp component:\n\n```jsx\n        \u003cbody\u003e\n          \u003cLocaleSwitcher /\u003e\n        \u003c/body\u003e\n```\n\nNext, we create a Greeter component that is going to display a localized message which will greet you:\n\n```jsx\nclass Greeter extends React.Component {\n  render() {\n    return \u003cTranslate {...this.props} content=\"example.greeting\" /\u003e;\n  }\n}\n```\n\nIn the component's render function, we simply transfer all incoming props to Translate (the component this repo is all about). As `content` property we specify the string \"example.greeting\" which acts as the key into the translations dictionary of Counterpart.\n\nNow add the new Greeter component to the body element, provide a `with` prop holding the interpolations (your first name in this case) and a `component` prop which is set to \"h1\":\n\n```jsx\n        \u003cbody\u003e\n          \u003cLocaleSwitcher /\u003e\n          \u003cGreeter with={{ name: \"Martin\" }} component=\"h1\" /\u003e\n        \u003c/body\u003e\n```\n\nThe value of the `name` key will be interpolated into the translation result. The `component` prop tells Translate which HTML tag to render as container element (a `\u003cspan\u003e` by default).\n\nAll that's left to do is to add the actual translations. You do so by calling the `registerTranslations` function of Counterpart. Add this to `client.js`:\n\n```js\ncounterpart.registerTranslations('en', {\n  example: {\n    greeting: 'Hello %(name)s! How are you today?'\n  }\n});\n\ncounterpart.registerTranslations('de', {\n  example: {\n    greeting: 'Hallo, %(name)s! Wie geht\\'s dir heute so?'\n  }\n});\n```\n\nIn the translations above we defined placeholders (in sprintf's named arguments syntax) which will be interpolated with the value of the `name` key we gave to the Greeter component via the `with` prop.\n\nThat's it for the application logic. To eventually see this working in a browser, we need to create the server-side code that will be executed by Node.js.\n\nFirst, let's install some required dependencies and create a `server.js` file:\n\n```bash\n$ npm install express connect-browserify reactify node-jsx --save\n$ touch server.js\n```\n\nNow open up `server.js` and add the following lines:\n\n```js\n'use strict';\n\nvar express     = require('express');\nvar browserify  = require('connect-browserify');\nvar reactify    = require('reactify');\nvar React       = require('react');\n\nrequire('node-jsx').install();\n\nvar App = React.createFactory(require('./client'));\n\nexpress()\n  .use('/bundle.js', browserify.serve({\n    entry: __dirname + '/client',\n    debug: true, watch: true,\n    transforms: [reactify]\n  }))\n  .get('/', function(req, res, next) {\n    res.send(React.renderToString(App()));\n  })\n  .listen(3000, function() {\n    console.log('Point your browser to http://localhost:3000');\n  });\n```\n\nNote that you shouldn't use this code in production as the `bundle.js` file will be compiled on every request.\n\nLast but not least, start the application:\n\n```bash\n$ node server.js\n```\n\nIt should tell you to point your browser to [http://localhost:3000][8]. There you will find the page greeting you. Observe that when switching locales the greeting message adjusts its text to the new locale without ever reloading the page or doing any ajax magic.\n\nPlease take a look at this repo's `spec.js` file to see some more nice tricks like translating HTML element attributes (title, placeholder etc.). To become a master craftsman we encourage you to also read [Counterpart's README][7].\n\n\n## Asynchronous Rendering on the Server-side\n\nThe above example for `server.js` will not work when you're calling `ReactDOMServer.renderToString(...)` within the callback of an async function and calling `counterpart.setLocale(...)` synchronously outside of that callback. This is because the Counterpart module is used as a singleton instance inside of the Translate component. See PR [#6] for details.\n\nTo fix this, create a wrapper component (or extend your root component) and pass an instance of Counterpart as React context. Here's an example:\n\n```js\nvar http = require('http');\nvar Translator = require('counterpart').Instance;\nvar React = require('react');\nvar ReactDOMServer = require('react-dom/server');\nvar Translate = require('react-translate-component');\nvar MyApp = require('./my/components/App');\n\nvar en = require('./my/locales/en');\nvar de = require('./my/locales/de');\n\nclass Wrapper extends React.Component {\n  getChildContext() {\n    return {\n      translator: this.props.translator\n    };\n  }\n\n  render() {\n    return \u003cMyApp data={this.props.data} /\u003e;\n  }\n}\n\nWrapper.childContextTypes = {\n  translator: Translate.translatorType\n};\n\nhttp.createServer(function(req, res) {\n  var queryData = url.parse(req.url, true).query;\n\n  var translator = new Translator();\n  translator.registerTranslations('en', en);\n  translator.registerTranslations('de', de);\n  translator.setLocale(req.locale || 'en');\n\n  doAsyncStuffHere(function(err, data) {\n    if (err) { return err; }\n\n    var html = ReactDOMServer.renderToString(\n      \u003cWrapper data={data} translator={translator} /\u003e\n    );\n\n    res.write(html);\n  });\n}).listen(3000);\n```\n\n## An Advanced Example\n\nThe code for a more sophisticated example can be found in the repo's `example` directory. You can clone this repository and run `make install example` and point your web browser to `http://localhost:3000`. In case you are too lazy for that, we also have a [live demo of the example app][4].\n\n\n## Contributing\n\nHere's a quick guide:\n\n1. Fork the repo and `make install`.\n\n2. Run the tests. We only take pull requests with passing tests, and it's great to know that you have a clean slate: `make test`.\n\n3. Add a test for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or are fixing a bug, we need a test!\n\n4. Make the test pass.\n\n5. Push to your fork and submit a pull request.\n\n\n## Licence\n\nReleased under The MIT License.\n\n\n\n[1]: http://facebook.github.io/react/\n[2]: https://github.com/martinandert/counterpart\n[3]: https://github.com/martinandert/react-interpolate-component\n[4]: http://react-translate-demo.andert.io/\n[5]: http://nodejs.org/\n[6]: https://www.npmjs.org/\n[7]: https://github.com/martinandert/counterpart#readme\n[8]: http://localhost:3000\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinandert%2Freact-translate-component","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartinandert%2Freact-translate-component","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinandert%2Freact-translate-component/lists"}