You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Please try the solution in #1227 (comment) and let us know if it works well for you.
Hi all,
I'm following this tutorial https://medium.freecodecamp.com/internationalization-in-react-7264738274a0#.pgfd03878 to use internationalization in my app.
Apparently the integreation is done by modifying the .babelrc file but to do so I have to eject, and I prefer not to.
Is there any way to use React-Intl without ejecting create-react-app?
You only need the Babel plugin to generate the translate files which you can do as part of your production build without ejecting although it's a little messy. I'll post how later.
You should be able to run both npm start/npm run build for running/building the project, and npm run translate for generating the translations.
Reacted by Rob Caldecott, Dave Draper, Mohamed Elbou, Stephan, firaskrichi, Torbjørn Hundseth, Yossi Jacob, Vincent Ahrend, nik, Jerry Duke and 17 more
Reacted by Ashley Connor, Artyom Stepanishchev, stereobooster, martinkelly23, Michael Vessia and Ricardo da Silva Girardi
@firaskrichi it works as intended by react-intl, by using babel's AST to catch translations and replace them (I suggest you to look it up, it's really interesting, if you like to know how exactly it - and in general babel plugins - works!).
The > /dev/null part is there simply to discharge the babel parsed output.
Moreover what I suggested is simply what the official doc tells to do ;)
@arshmakker being that it's easily pluggable, not everybody wants to use i18n, and the specific tool (format.js) is not that reliable if you want to do substantial i18n (@see), I'm not sure at all it would be possible.
This is a really useful discussion and the information provided by @EnoahNetzach has really helped get react-intl into my create-react-app application. I think it would be exceptionally valuable to have i18n working out-of-the-box with create-react-app (or at least some good documentation explaining how to use it).
The main thing that I don't quite understand is how this works with a production build. I've followed the various scripts to combine individual component message files into a single JSON file for the default locale, I've then added a different locale (with translated messages) and updated the IntlProvider locale to be the new locale.
When you use npm run build the new locale translations are lost (probably because the translate scripts provided by the blogs combine the component messages into locale files in the build directory).
If anyone can shed any light on the correct approach to combining the information provided so far in a production story I'd be very grateful.
@draperd, as a non English native speaker, I find that unfortunately no i18n instrument in js is a "catch all" solution.
I've used a couple and always ended up tweaking them to my needs (e.g. subject/direct object gender and numerosity, probably @gaearon could say something about Russian desinences, I don't know if there is someone from Iceland here, and so on and so forth..).
Whichever translation package we could add, it's going to solve only a limited set of cases and needs, so I'm against adding them in altogether, specially when the integration is not "that" painful.
@EnoahNetzach Thanks for your response... I wasn't suggesting that there is a one-size fits all solution, but it would seem that React-Intl is a pretty good fit. I can understand the rationale of not wanting to tie "create-react-app" to a single solution, however a solution of some kind is almost going to be required. Any serious application is going to want to support i18n so I'm simply suggesting that either something is provided by default, or that documentation is provided to assist people in achieving a solution.
The information you have previously provided has been invaluable but only as far as the development experience goes. My point is that when I'm ready to ship my finished application I need translation to work in production for multiple locales and I've not been able to find that information anywhere so far.
I'll continue to experiment and hopefully find a working solution which I'll then write up, I was just hoping that someone may have already encountered and solved this problem using react-intl.
Just to follow up my previous comment... what I actually need is a per component solution which I've now managed to achieve using the higher order component pattern. I will write this solution up as soon as I can for anyone that comes across this thread as it might be useful.
For everyone that the suggestion from @EnoahNetzach is not working out of the box I had to put following in my package.json, probably as I'm working on windows
If you don't want to have to npm install --save-dev babel-cli or create the babel.rc file, or worry about issues on Windows, you can use the babel API:
// scripts/translate.jsprocess.env.NODE_ENV='development';constfs=require('fs');constpath=require('path');constglobSync=require('glob').sync;constmkdirpSync=require('mkdirp').sync;consttransformFileSync=require('babel-core').transformFileSync;constpaths=require('../config/paths');//////////////////////////////// Add to `/config/paths.js`:// appBuildMessages: .. where to output the messages//////////////////////////////globSync(path.join(paths.appSrc,'/**/*.js')).map((filename)=>{constresult=transformFileSync(filename,{plugins: ['react-intl']});constmessages=result.metadata["react-intl"]["messages"];if(messages.length>0){constrelFn=path.relative(paths.appSrc,filename);constoutFilename=path.join(paths.appBuildMessages,path.dirname(relFn),`${path.basename(relFn,".js")}.json`);mkdirpSync(path.dirname(outFilename));constoutFd=fs.openSync(outFilename,'w');fs.write(outFd,JSON.stringify(messages));}});
// Component.js
-import {defineMessages} from 'react-Intl';+import { defineMessages } from 'react-intl.macro';
const messages = defineMessages({
'Component.greet': {
id: 'Component.greet',
defaultMessage: 'Hello, {name}!',
description: 'Greeting to welcome the user to the app',
},
});
The react-intl-cra CLI is pretty easy to use, but it only works with CRA project.
The react-intl.macro is more flexible even working with others (e.g.,Next.js).
May I know why does react-intl-cra and other examples here generate in
[
{
"id": "...",
"defaultMessage": "..."
}
]
format?
If you do import translations from './i18n/messages.json'; and <IntlProvider locale="en" messages={translations}> it won't work. It accepts key value paris like
{
"...": "..."
}
Thanks.
Reacted by Dimitri KOPRIWA, jeromemalot, Henry Huck, Fintan and Anatolii Krivchenko
Personnaly, I use the internal script extract-intl from react-boilerplate.
No need of babel-plugin-react-intl or react-intl-cra, just some adaptations according the project, like changing paths and install needed modules (mainly babel-cli) and voila. :D
I'm following up on the questions asked by @dachinat and @kopax
From what I understand, there are two steps:
Extract all the strings that need to be translated
Generate a file that will store the translations for each language
In the gettext universe, the first step is the equivalent of generating the (single) .pot file while the second step is the generation of the (multiple) .po files.
The "messageId": "value" syntax would apply to the result of the second step, while babel-plugin-react-intl only does the first step.
I didn't think the second step would be so complicated to implement.
So far all I've found (outside of this discussion) is this software that provides a GUI to do it. I don't know what it is based on.
I was expecting the guys behind react-intl would provide a command such as translations-update -i build/**/*.json -o src/messages/fr.json.
Did I miss something here or is it really that complicated to have a translations file for each language?
I only need bash to be installed and everything works fine so far. I can run npm run i18n:extract in a CI environment to generate the file with the translations in the default language, and in another CI process, when deploying to staging/production I can retrieve the translation files (from wherever they are), put them at src/src-lang/ and call npm run i18n:compile to generate the final (compiled) translation files at src/lang/ (the files in these folders aren't versioned).
In smaller projects you can run npm run i18n:extract locally, put the generated file (default language) in a versioned folder and apply the translation on the other files in the folder based on the changes in the default language. Then when deploying in a CI environment you can just move the files from the versioned folder to src/src-lang/ and run npm run i18n:compile to generate the compiled translation files at src/lang/.
In development I just run npm run i18n:dev to create an empty json file ({}) so as to not receive errors when trying to import the file (the default language messages are already in the code, so the file doesn't need to have translations in the default language).
The only thing I haven't achieved was to be able to generate ids (https://formatjs.io/docs/guides/bundler-plugins), and use the generated ids in development (I don't know if this is possible without ejecting and stop using create-react-app, because it would need to transpile the source files to generate the ids). So, for now, I'm using static ids (if there is the same id for different messages I receive an error, so it's ok).
Activity
robcaldecott commentedon Dec 10, 2016
You only need the Babel plugin to generate the translate files which you can do as part of your production build without ejecting although it's a little messy. I'll post how later.
EnoahNetzach commentedon Dec 10, 2016
You can just install the required dependencies, add your own
.babelrc, and add your"script": "translation"to yourpackage.json.E.g.:
add to the root folder:
{ "presets": ["react-app"], "plugins": [ [ "react-intl", { "messagesDir": "translations/messages", "enforceDescriptions": false } ] ] }then add to your
package.json's"scripts"this line:You should be able to run both
npm start/npm run buildfor running/building the project, andnpm run translatefor generating the translations.firaskrichi commentedon Jan 20, 2017
@EnoahNetzach thanks for the answer!
How does : "NODE_ENV=production babel ./src >/dev/null" generate the translation? How does it work exactly?
Thank you 🙏
arshmakker commentedon Jan 20, 2017
hi,
Internationlization is a pretty important feature for mobile apps these days. Could we have react-intl inbuilt in the create-react flow?
Regards
Arsh
EnoahNetzach commentedon Jan 20, 2017
@firaskrichi it works as intended by react-intl, by using babel's AST to catch translations and replace them (I suggest you to look it up, it's really interesting, if you like to know how exactly it - and in general babel plugins - works!).
The
> /dev/nullpart is there simply to discharge the babel parsed output.Moreover what I suggested is simply what the official doc tells to do ;)
@arshmakker being that it's easily pluggable, not everybody wants to use i18n, and the specific tool (format.js) is not that reliable if you want to do substantial i18n (@see), I'm not sure at all it would be possible.
draperd commentedon Feb 10, 2017
This is a really useful discussion and the information provided by @EnoahNetzach has really helped get react-intl into my create-react-app application. I think it would be exceptionally valuable to have i18n working out-of-the-box with create-react-app (or at least some good documentation explaining how to use it).
The main thing that I don't quite understand is how this works with a production build. I've followed the various scripts to combine individual component message files into a single JSON file for the default locale, I've then added a different locale (with translated messages) and updated the IntlProvider locale to be the new locale.
When you use
npm run buildthe new locale translations are lost (probably because the translate scripts provided by the blogs combine the component messages into locale files in the build directory).If anyone can shed any light on the correct approach to combining the information provided so far in a production story I'd be very grateful.
EnoahNetzach commentedon Feb 10, 2017
@draperd, as a non English native speaker, I find that unfortunately no i18n instrument in js is a "catch all" solution.
I've used a couple and always ended up tweaking them to my needs (e.g. subject/direct object gender and numerosity, probably @gaearon could say something about Russian desinences, I don't know if there is someone from Iceland here, and so on and so forth..).
Whichever translation package we could add, it's going to solve only a limited set of cases and needs, so I'm against adding them in altogether, specially when the integration is not "that" painful.
draperd commentedon Feb 10, 2017
@EnoahNetzach Thanks for your response... I wasn't suggesting that there is a one-size fits all solution, but it would seem that React-Intl is a pretty good fit. I can understand the rationale of not wanting to tie "create-react-app" to a single solution, however a solution of some kind is almost going to be required. Any serious application is going to want to support i18n so I'm simply suggesting that either something is provided by default, or that documentation is provided to assist people in achieving a solution.
The information you have previously provided has been invaluable but only as far as the development experience goes. My point is that when I'm ready to ship my finished application I need translation to work in production for multiple locales and I've not been able to find that information anywhere so far.
I'll continue to experiment and hopefully find a working solution which I'll then write up, I was just hoping that someone may have already encountered and solved this problem using react-intl.
draperd commentedon Feb 13, 2017
Just to follow up my previous comment... what I actually need is a per component solution which I've now managed to achieve using the higher order component pattern. I will write this solution up as soon as I can for anyone that comes across this thread as it might be useful.
EnoahNetzach commentedon Feb 13, 2017
@draperd good!
draperd commentedon Feb 13, 2017
As promised... hopefully this might be of use to some people: https://medium.com/@dave.draper20/i18n-per-component-in-react-using-the-higher-order-component-pattern-b04f32e7cd6a#.ewrplesd7
sthuber90 commentedon Mar 10, 2017
For everyone that the suggestion from @EnoahNetzach is not working out of the box I had to put following in my
package.json, probably as I'm working on windows"translate": "cross-env NODE_ENV=production ./node_modules/.bin/babel ./src > NUL",EnoahNetzach commentedon Mar 10, 2017
Yep, env var definition and the output indirection to
/dev/nullwork only in Linux/Mac.cross-env solves the first part, for the second sincerely I have no idea how to accomplish that on Windows..
cwalv commentedon Mar 18, 2017
If you don't want to have to
npm install --save-dev babel-clior create thebabel.rcfile, or worry about issues on Windows, you can use the babel API:14 remaining items
gaearon commentedon Jan 10, 2018
Nice, thanks.
arshmakker commentedon Jan 11, 2018
Currently I am using the
react-intl-crain production at our end and have not face any issues so far.evenchange4 commentedon Jan 25, 2018
Here is the macro solution POC:
Your code
Extract messages
// package.json "scripts": { "start": "react-scripts start", "build": "react-scripts build", + "extract": "MESSAGE_DIR='./.messages' react-scripts build" },Pros and Cons
The
react-intl-craCLI is pretty easy to use, but it only works with CRA project.The
react-intl.macrois more flexible even working with others (e.g.,Next.js).References
GitHub: https://github.com/evenchange4/react-intl.macro
Example: https://github.com/evenchange4/react-intl.macro-example
Demo: https://react-intlmacro.netlify.com
dachinat commentedon Mar 31, 2018
May I know why does
react-intl-craand other examples here generate informat?
If you do
import translations from './i18n/messages.json';and<IntlProvider locale="en" messages={translations}>it won't work. It accepts key value paris likeThanks.
kopax commentedon Apr 9, 2018
@EnoahNetzach I have tried with your solution and
Should I install anything else in my project ? What plugin can I reuse and where are they stored ?
Did anybody made a workaround ? I dont' get why
react-intl-cra './src/**/*.js' -o messages.jsongenerated me this file :[ { "id": "test.action.resetViews", "defaultMessage": "Reset views", "filepath": "./src/messages.js" } ]While I expect
I want to use react-intl. As @dachinat pointed oput, we need
key:valuepair.How can I do without ejecting?
noliiva commentedon May 7, 2018
Personnaly, I use the internal script
extract-intlfrom react-boilerplate.No need of babel-plugin-react-intl or react-intl-cra, just some adaptations according the project, like changing paths and install needed modules (mainly babel-cli) and voila. :D
kopax commentedon May 7, 2018
@noliiva I have placed this react-boilerplate script in a program that you can run through
npxand it work without any dependency :You must have in your
package.json+ "declinationId": "intl"Then run
This will create in your
package.jsonYou can now extract what's in
srcdirectory with :You can add the following scripts to your
package.jsonto keep the snippet for any project:+ "extract-intl": "NODE_ENV=production npx rollup-umd-scripts intl extract --target=src/i18n/translation",--targetis for changing the destination path for the generated json files.It's basically the same as evenchange4 except with the standard format for json and without any install.
arnaudriegert commentedon Aug 22, 2018
I'm following up on the questions asked by @dachinat and @kopax
From what I understand, there are two steps:
In the
gettextuniverse, the first step is the equivalent of generating the (single).potfile while the second step is the generation of the (multiple).pofiles.The
"messageId": "value"syntax would apply to the result of the second step, whilebabel-plugin-react-intlonly does the first step.I didn't think the second step would be so complicated to implement.
So far all I've found (outside of this discussion) is this software that provides a GUI to do it. I don't know what it is based on.
I was expecting the guys behind
react-intlwould provide a command such astranslations-update -i build/**/*.json -o src/messages/fr.json.Did I miss something here or is it really that complicated to have a translations file for each language?
sunknudsen commentedon Feb 16, 2019
Looking for a way to extract messages from components localized using react-intl and manage translations effortlessly?
The following worked for me: formatjs/babel-plugin-react-intl#108 (comment)
jamieallen59 commentedon Mar 18, 2019
I was using the same tutorial and couldn't find a tutorial from start => finish without ejecting so wrote one here: https://medium.com/@jamieallen59/using-react-intl-with-create-react-app-6667ee3e19f3. Hope it helps.
shsunmoonlee commentedon Apr 26, 2019
Hey I get error saying ' You must use a intl declination to use this command!'
kopax commentedon Apr 26, 2019
@SeunghunSunmoonLee sorry I did a change in that script, you must have in your
package.json+ "declinationId": "intl"It wont break anymore, otherwise you can fix to an older version.
erikhansen commentedon Jun 25, 2019
@jamieallen59 Your tutorial worked great for me. Thanks.
mihanizm56 commentedon Aug 11, 2019
@jamieallen59
You use react-intl v2 version in your guide. Nowadays in v3 there are a lot of APIs have breaking changes
lucasbasquerotto commentedon Sep 28, 2020
In my case I'm able to use
react-intlwithcreate-react-appby just including 2 simple scripts to extract and compile the translation files:scripts/i18n-extract.sh:
* I define the extension as
ts*because I'm using typescript, if you are using javascript just change it tojs*scripts/i18n-compile.sh:
* In this case I'm considering the languages
en,frandar(enbeing the default), you can change it to your use case.And in package.json:
I only need bash to be installed and everything works fine so far. I can run
npm run i18n:extractin a CI environment to generate the file with the translations in the default language, and in another CI process, when deploying to staging/production I can retrieve the translation files (from wherever they are), put them atsrc/src-lang/and callnpm run i18n:compileto generate the final (compiled) translation files atsrc/lang/(the files in these folders aren't versioned).In smaller projects you can run
npm run i18n:extractlocally, put the generated file (default language) in a versioned folder and apply the translation on the other files in the folder based on the changes in the default language. Then when deploying in a CI environment you can just move the files from the versioned folder tosrc/src-lang/and runnpm run i18n:compileto generate the compiled translation files atsrc/lang/.In development I just run
npm run i18n:devto create an empty json file ({}) so as to not receive errors when trying to import the file (the default language messages are already in the code, so the file doesn't need to have translations in the default language).The only thing I haven't achieved was to be able to generate ids (https://formatjs.io/docs/guides/bundler-plugins), and use the generated ids in development (I don't know if this is possible without ejecting and stop using
create-react-app, because it would need to transpile the source files to generate the ids). So, for now, I'm using static ids (if there is the same id for different messages I receive an error, so it's ok).