--- myst: html_meta: "description": "" "property=og:description": "" "property=og:title": "" "keywords": "" --- (i18n-label)= # Internationalization ## Making Text Translatable Volto uses `react-intl` to translate strings. We start by importing the component: ```jsx import { FormattedMessage } from 'react-intl'; ``` Then we can use the `FormattedMessage` component to translate a string: ```jsx ``` ## Extracting i18n Strings Volto provides an i18n extraction script to get all translatable strings from your application. Run the following: ```shell yarn i18n ``` This will generate the following output: ```console Extracting messages from source files... Synchronizing messages to pot file... Synchronizing messages to po files... Generating the json files... done! ``` As the description suggests it will first extract all messages from the source files into a `.json` file. Then it will synchronize the extracted messages with the `.pot` master file and with all the `.po` files found in the project. After that it will generate the final `.json` files which are used in the application. If you want to translate the strings edit the `.po` files and run the script again. This script will combine the messages located in Volto itself and the current project, and combine them into the `.json` files. ## Exercise Translate the `Tags:` label which was added in the previous chapter to Dutch and German. ````{dropdown} Solution :animate: fade-in-slide-down :icon: question ```jsx /** * Tags component. * @module components/theme/Tags/Tags */ import React from 'react'; import { Link } from 'react-router-dom'; import PropTypes from 'prop-types'; import { Container } from 'semantic-ui-react'; import { FormattedMessage } from 'react-intl'; /** * Tags component class. * @function Tags * @param {array} tags Array of tags. * @returns {string} Markup of the component. */ const Tags = ({ tags }) => tags && tags.length > 0 ? ( : {tags.map(tag => ( {tag} ))} ) : ( ); /** * Property types. * @property {Object} propTypes Property types. * @static */ Tags.propTypes = { tags: PropTypes.arrayOf(PropTypes.string), }; /** * Default properties. * @property {Object} defaultProps Default properties. * @static */ Tags.defaultProps = { tags: null, }; export default Tags; ``` ```` ## Translate Attributes When you want to translate attributes you can't use the `FormattedMessage` component since it will generate markup. In order to translate a normal string or attribute you can use the `formatMessage` method of `react-intl`. First you need to import all the required methods: ```jsx import { defineMessages, injectIntl, intlShape } from 'react-intl'; ``` Then you can use the `defineMessages` method to define your messages: ```jsx const messages = defineMessages({ site: { id: 'Site', defaultMessage: 'Site', }, }); ``` In order to use the `formatMessage` method you have to inject the `intl` object into your class or function. For pure functions you can use: ```jsx export default injectIntl(Logo); ``` And for classes you can use: ```jsx @injectIntl class Logo extends Component { } ``` You can use the provided `PropType` as follows: ```{code-block} jsx :emphasize-lines: 3 Tags.propTypes = { tags: PropTypes.arrayOf(PropTypes.string), intl: intlShape.isRequired, }; ``` Now we can use the method like this: ```jsx ``` ## Exercise Add a title to the tag links with the message `Search for tag {tag}`. ````{dropdown} Solution :animate: fade-in-slide-down :icon: question ```jsx /** * Tags component. * @module components/theme/Tags/Tags */ import React from 'react'; import { Link } from 'react-router-dom'; import PropTypes from 'prop-types'; import { Container } from 'semantic-ui-react'; import { defineMessages, injectIntl, intlShape, FormattedMessage, } from 'react-intl'; const messages = defineMessages({ searchTag: { id: 'Search for tag {tag}', defaultMessage: 'Search for tag {tag}', }, }); /** * Tags component class. * @function Tags * @param {array} tags Array of tags. * @returns {string} Markup of the component. */ const Tags = ({ tags, intl }) => tags && tags.length > 0 ? ( : {tags.map(tag => ( {tag} ))} ) : ( ); /** * Property types. * @property {Object} propTypes Property types. * @static */ Tags.propTypes = { tags: PropTypes.arrayOf(PropTypes.string), intl: intlShape.isRequired, }; /** * Default properties. * @property {Object} defaultProps Default properties. * @static */ Tags.defaultProps = { tags: null, }; export default injectIntl(Tags); ``` ````