Skip to content

Commit

Permalink
Add hindi translation in Volto (plone#6016)
Browse files Browse the repository at this point in the history
Co-authored-by: Steve Piercy <[email protected]>
Co-authored-by: Victor Fernandez de Alba <[email protected]>
  • Loading branch information
3 people authored May 20, 2024
1 parent 015658f commit bc9417a
Show file tree
Hide file tree
Showing 7 changed files with 5,046 additions and 70 deletions.
2 changes: 1 addition & 1 deletion docs/source/addons/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ myst:
# Add-on Internationalization

The internationalization workflow is the same as in main Volto: you develop your add-on, then add the translations to your code.
See {ref}`creating-i18n-strings` for how to mark strings and phrases as translatable.
See {ref}`create-i18n-strings` for how to mark strings and phrases as translatable.

Your add-on has a `locales` folder with a `.pot` file.

Expand Down
3 changes: 3 additions & 0 deletions docs/source/contributing/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ For every feature or component, a unit test is mandatory in Volto core.

Jest is configured in `package.json` under the `jest` key.


(run-jest-tests-on-volto-core-label)=

## Run Jest tests on Volto core

```{note}
Expand Down
128 changes: 59 additions & 69 deletions docs/source/development/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,72 +9,58 @@ myst:

# Internationalization

Internationalization (i18n) is the process of creating user interfaces which are suitable for different languages and cultural contexts.
Volto uses the library [react-intl](https://www.npmjs.com/package/react-intl) to provide translations for any potential language.
Anything you can read in the [official documentation of react-intl](https://formatjs.io/docs/react-intl/) also applies for Volto.

However this section teaches you about the most common use cases relating to i18n you probably will have when developing your {doc}`../addons/index` or contributing to the Volto core itself.
{term}`Internationalization` (i18n) is the process of creating user interfaces which are suitable for different languages and cultural contexts.
This chapter describes the most common use cases for internationalization when developing your {doc}`../addons/index` or contributing to the Volto core itself.


## Process and file structure overview

## Broad overview
Volto uses the library [react-intl](https://www.npmjs.com/package/react-intl) to provide translations for any potential language.
Anything in the [official documentation of react-intl](https://formatjs.io/docs/react-intl/) also applies to Volto.

The workflow for creating *new* translatable texts is as follows:
The workflow for creating *new* translatable text strings is as follows:

1. Create translatable i18n strings in your code
2. Extract all i18n strings from your code with a script and create artifacts like `.po` and `.pot` files
3. Use your favorite editor to translate all i18n strings (i.e. edit the `.po` files)
4. Re-run the script, which then moves the translations from the `.po` files into for Volto usable `.json` files
1. Create translatable i18n strings in your code.
1. Extract all i18n strings from your code with a script and create artifacts, like `.po` and `.pot` files.
1. Use your favorite editor to translate all i18n strings by editing the `.po` files.
1. Re-run the script, which then moves the translations from the `.po` files into `.json` files for Volto to use.
1. Edit [`packages/volto/src/constants/Languages.js`](https://github.com/plone/volto/blob/main/packages/volto/src/constants/Languages.js), adding your new language's locale code, as defined in {ref}`i18n-l10n-locale-and-language-tag-conventions-label`.
1. Run the unit tests as described in {ref}`run-jest-tests-on-volto-core-label`, following the prompt to update the snapshot when the test fails.

This way of organizing translations relies on [gettext](https://en.wikipedia.org/wiki/Gettext), a proven and established system with great tool support.
`.json` files in react-intl are equivalent to `.mo` files in gettext.

All translation files are located under the directory [`packages/volto/locales`](https://github.com/plone/volto/tree/main/packages/volto/locales).

All translation files are located under the directory `locales`.
This might look like this:
The file {file}`packages/volto/locales/volto.pot` holds all extracted i18n strings, and acts as the source template for all the `.po` files.
A translation for each language is stored in two files, both with their language code in the file name or path.
Using English as an example, the `.po` file is stored at {file}`packages/volto/locales/en/LC_MESSAGES/volto.po`, and the `.json` file is stored at {file}`packages/volto/locales/en.json`.
The abridged file structure for English would appear as follows.

```shell
$ tree locales/
```text
locales/
├── de
│ └── LC_MESSAGES
│ └── volto.po
├── de.json
├── en
│ └── LC_MESSAGES
│ └── volto.po
├── en.json
├── es
│ └── LC_MESSAGES
│ └── volto.po
├── es.json
├── it
│ └── LC_MESSAGES
│ └── volto.po
├── it.json
├── ja
│ └── LC_MESSAGES
│ └── volto.po
├── ja.json
├── nl
│ └── LC_MESSAGES
│ └── volto.po
├── nl.json
└── volto.pot

12 directories, 13 files
```

The file `volto.pot` holds all extracted i18n strings and acts as master template for all the `*.po` files.
The translation for each language is stored within a dedicated sub-directory (like `en` for English, `it` for Italian, etc.) and are stored as `*.po` file and separately stored directly under `locales` as `*.json` file.

(create-i18n-strings)=

## Create i18n strings

(creating-i18n-strings)=
In this section, you can learn how to translate HTML elements and attributes.

## Creating i18n Strings

### Translating Text Within HTML Elements
### Translate text in HTML elements

`react-intl` can identify translatable texts with the `FormattedMessage` components.
As the name of this component suggests, it is also possible to format your messages as your liking.
As the name of this component suggests, it's also possible to format your messages as your prefer.

This is an example of how you can write a text with contents `Hello World`, which can be identified via `hello_world`:
The following code snippet is an example of how you can write a text with the content `Hello World`, which can be identified via `hello_world`.

```jsx
import { FormattedMessage } from 'react-intl';
Expand All @@ -91,26 +77,27 @@ function HelloWorld(props) {
}
```

The identifier `hello_world` is then commonly used between all the translations.
There are also more features available such as using placeholders.
See the docs for all features in the [FormattedMessage component](https://formatjs.io/docs/react-intl/components#formattedmessage).
The identifier `hello_world` is then commonly used across all the translations.
There are more features available, such as using placeholders.
See the documentation for all features in the [`FormattedMessage` component](https://formatjs.io/docs/react-intl/components#formattedmessage).

### Translating Attributes

As `FormatMessage` is only suitable for creating text within HTML elements, it cannot be used for translating individual attributes.
But with the method [formatMessage](https://formatjs.io/docs/react-intl/api/#formatmessage) there exists another way to translate primitive strings.
### Translate attributes

This approach can be best explained with an example: Assume you have a component called `TeaserImage` which contains an image that has for accessibility reasons the `alt` attribute.
As `FormatMessage` is only suitable for creating text within HTML elements, it cannot be used for translating individual attributes.
But with the method [`formatMessage`](https://formatjs.io/docs/react-intl/api/#formatmessage), there is another way to translate primitive strings.

This approach can be best explained with an example.
Assume you have a component called `TeaserImage` which contains an image that has, for accessibility reasons, the `alt` attribute.
To translate the `alt` attribute, you have to do the following steps:

1. Import the following necessary methods:
1. Import the following required methods.

```js
import { defineMessages, injectIntl, intlShape } from 'react-intl';
```

2. Define a message (or more) via [defineMessages](https://formatjs.io/docs/react-intl/api/#definemessagesdefinemessage):
2. Define a message (or more) via [`defineMessages`](https://formatjs.io/docs/react-intl/api/#definemessagesdefinemessage):

```js
const messages = defineMessages({
Expand All @@ -121,40 +108,41 @@ To translate the `alt` attribute, you have to do the following steps:
});
```

3. As the method `formatMessage` in our component class/function is needed, there is a special propery `intl`, that needs to be injected with *either* the following ways:
3. Because your component class or function needs the method `formatMessage`, there is a special property `intl` that you need to inject in one of the two following ways.

```text
```js
// When using a pure function:
export default injectIntl(TeaserImage);
```

// OR when using a component:
```js
// When using a component:
@injectIntl
class TeaserImage extends Component {
...
// ...
}
```
Since you now have another prop available, it has to be to properly defined in the propTypes:
Because you now have another prop available, you need to define it in the `propTypes`:
```jsx
TeaserImage.propTypes = {
intl: intlShape.isRequired,
...
// ...
};
```
4. As last step, the method can be used like this:
4. As the final last step, you can use the method as follows:
```jsx
<img src="..." alt={intl.formatMessage(messages.teaserAltText)}>
```
## Extracting i18n Strings
## Extract i18n strings
Volto provides an i18n extraction script to get all translatable strings from your application.
This script can be invoked by this command:
You can invoke this script with the following command.
```sh
yarn i18n
Expand All @@ -170,12 +158,12 @@ Generating the json files...
done!
```
As the output suggests it will first extract all messages from the source files into `.json` files.
Then it will synchronize the extracted messages with the `.pot` master template and with all the `.po` files found in the project.
As the output suggests, it will first extract all messages from the source files into `.json` files.
Then it will synchronize the extracted messages with the `.pot` main template and with all the `.po` files found in the project.
This script will combine the messages located in Volto itself and the current project, and combine them into the `.json` files.
## Overriding i18n messages
## Override i18n messages
If you want to override an existing translation, you should declare the original message again somewhere else in your project.
For example in `src/config.js`:
Expand All @@ -194,13 +182,13 @@ defineMessages({
Then run `yarn i18n`.
You will find the translation ready to override in your `locales` directory, such as `locales/de/LC_MESSAGES/volto.po`.
```
```text
#: src/config
msgid "Back"
msgstr "My overridden translation"
```
After setting the override, then run `yarn i18n` again to create the `de.json` translation files.
After you set the override, then run `yarn i18n` again to create the `de.json` translation files.
Restart Volto to see the changes applied.
```{note}
Expand All @@ -209,8 +197,10 @@ Shadowed components do _not_ override translations.
Thus the `customizations` folder is excluded from the i18n build.
```
## Contributing translations for an unsupported language
## Contribute translations for an unsupported language
The Volto project welcomes all speakers from the world to include any language, which is not supported yet.
If your language's po file is not available in Volto, [open an issue in GitHub](https://github.com/plone/volto/issues) so we can create it for you, and after that you can start contributing your translations!
If your language's `.po` file is not available in Volto, [open an issue in GitHub](https://github.com/plone/volto/issues).
Either you can create the `.po` file or we can do it for you.
After that, you can start contributing your translations.
Loading

0 comments on commit bc9417a

Please sign in to comment.