See the examples below, as well as Home.js and Carousel.js
All you need to do is to encode your component and open a PR. You should not see any changes at this step - please, check the text and links - everything should work as it was before. If so - open a PR, add a note that this PR is internationalisation of a component.
Produce unique message ids in a format component.id (e.g. home.welcome or carousel.title) in <FormattedMessage id="<ID>" defaultMessage=<ENGLISH LINE AS IT WAS BEFORE>/>
Some things require a bit more work, see examples. This is when a line includes some parts which do no need to be translated (like tags or links, example 2) Or where a property of another component needs to be translated (like alt of an img, example3)
You should not add anything to intl/en.json file - this will be done automatically. If you want to test this locally - you need to run
npm run build,
wait the build to be finished, then exit and run
npm run langs
(This is not very convinient, I'm working on improving that, but this is minor issue and this is how they do it in howTOs)
[React Intl] Missing message: "home.3.step_1" for locale: "ru", using default message as fallback. ← This is OK - those messages will go away as soon as we translate the elements.
If you do not know, what to do - first, look at the examples below. If you still have troubles - add a code as the next example at the end of this page with the lines you need to encode (as is) and I will provide you the code (to be)
For each of your components you should do the following:
Step 1. Include the libraries:
import {FormattedMessage, defineMessages} from 'react-intl';
Step 2. (If necessary) Include those to the end of the component, right before export default (see example 3 below): This is needed only if you use example 3 somewhere!
<Component>.contextTypes = { //instead of Component - the name of your component, e.g. Home or Carousel intl: React.PropTypes.object.isRequired };
Step 3. Encode all strings to be collected for translation:
# | As Is | To Be |
---|---|---|
1 | Plain text line <h2 className="ui center aligned grey header"> SlideWiki revolutionises ... </h2> | Plain text line <h2 className="ui center aligned grey header"> <FormattedMessage id='home.slogan' defaultMessage='SlideWiki revolutionises...' /> </h2> OR: Plain text line (optional) class Home extends React.Component { render() { ... const messages = defineMessages({ slogan:{ id: 'home.slogan', defaultMessage: 'SlideWiki revolutionises...' } }); return ( ... <FormattedMessage {...messages.slogan} /> ... ) } } Note: the first way is recommended |
2 | A fragment with links <p> If ... follow us on <a target="_blank" href="https://twitter.com/SlideWiki">Twitter</a> or visit the <a href="https://slidewiki.eu">SlideWiki project website</a>. </p> | A fragment with links <p> <FormattedMessage id='home.welcome12' values={{ link_1: <a target="_blank" href="https://twitter.com/SlideWiki">Twitter</a>, link_2: <a href="https://slidewiki.eu"> <FormattedMessage id="home.welcome12.1" defaultMessage="SlideWiki project website"/> </a> }} defaultMessage={'If ... follow us on {link_1} or visit the {link_2}.'} /> </p> Note: The text inside the first link ('Twitter') will not be translated, while the text inside the second link ('SlideWiki project website') will be translated |
3 | Text from component/tag property <img className="ui centered image" src="/assets/images/logo_full.png" alt="SlideWiki beta logo" /> | Text from component/tag property: Using a function <FormattedMessage id="home.logo_alt" defaultMessage='SlideWiki beta logo'> { (alt) => <img className="ui centered image" src="/assets/images/logo_full.png" alt={alt} /> } </FormattedMessage> OR (as we probably will have this situation a lot): Text from component/tag property: Using a lower-level intl API class Home extends React.Component { render() { ... const messages = defineMessages({ logo_alt: { id: 'home.logo_alt', defaultMessage: 'SlideWiki beta logo', } }); return ( ... <img className="ui centered image" src="/assets/images/logo_full.png" alt={this.context.intl.formatMessage(messages.logo_alt)} /> ... ) } } Home.contextTypes = { intl: React.PropTypes.object.isRequired }; export default Home; Note: The second way is recommended, however if there is only 1-2 cases in your component, the first way is better. |
4 | function with swal function1(provider){ swal({ title: 'blub', text: 'see '+provider, type: 'error', confirmButtonText: 'Confirm', confirmButtonClass: 'negative ui button', buttonsStyling: false }).then().catch(); } | swal in components function1(provider){ const messages = defineMessages({ swal_text:{ id: '<Component>.function1.swal_text', defaultMessage: 'see' + provider, }, confirm_text:{ id: '<Component>.function1.confirm_text', defaultMessage: 'Confirm', } }); swal({ title: 'blub', text: this.context.intl.formatMessage(messages.swal_text), type: 'error', confirmButtonText: this.context.intl.formatMessage(messages.confirm_text), confirmButtonClass: 'negative ui button', buttonsStyling: false }).then().catch(); } ... ComponentName.contextTypes = { intl: React.PropTypes.object.isRequired }; And thanks, Soledad Valero : swal in actions constructor(){ super(props); this.messages = defineMessages({ swal_text:{ id: 'componentName.swal_text', defaultMessage:'see '+ provider }, } swal({ title: 'blub', text: this.context.intl.formatMessage( this.messages.swal_text), type: 'error', confirmButtonText: 'Confirm', confirmButtonClass: 'negative ui button', buttonsStyling: false }).then().catch(); ComponentName.contextTypes = { intl: React.PropTypes.object.isRequired }; The two solutions above throwing an error: SyntaxError: [React Intl] Messages must be statically evaluate-able for extraction. My solution: Solution for dynamic texts with parameters let messages = defineMessages({ swal_text:{ id: 'LoginModal.text.incompleteProviderData', defaultMessage: 'The data from {provider} was incomplete. In case you want to use this provider, please add an e-mail address at the provider itself and try again at SlideWiki.' }, }); swal({ title: this.context.intl.formatMessage({ id: 'LoginModal.title.error', defaultMessage: 'Error', }), text: this.context.intl.formatMessage(messages.swal_text, { provider: provider }), type: 'error', confirmButtonText: this.context.intl.formatMessage({ id: 'LoginModal.button.confirm', defaultMessage: 'Confirm', }), confirmButtonClass: 'negative ui button', buttonsStyling: false }).then().catch(); |
5 | Your input here | My output here =) Note: or if you've solved your issue on your own, share it with others! |
Related / todo after this (not part of dev task) → update the multilingual interface when new components have been encoded