ohif-viewer/docs/latest/essentials/translating.md

318 lines
8.3 KiB
Markdown
Raw Normal View History

2019-06-06 23:57:19 +02:00
# Translating
2019-06-08 00:53:30 +02:00
OHIF supports internationalization using [i18next](https://www.i18next.com/)
through the npm package [@ohif/i18n](https://www.npmjs.com/package/@ohif/i18n),
where is the main instance of i18n containing several languages and tools.
2019-06-06 23:57:19 +02:00
<div class='row'>
<div class='column'>
<p>Our translation management is powered by <a href="https://locize.com/" target="_blank" rel="noopener noreferrer">Locize</a> through their generous support of open source.</p>
</div>
<div class='column'>
<a href="https://locize.com/" target="_blank" rel="noopener noreferrer" style='padding: 20px'>
<img src="../assets/img/locizeSponsor.svg" alt="Locize Translation Management Logo">
</a>
</div>
</div>
2019-06-06 23:57:19 +02:00
### Installing
2019-06-08 00:53:30 +02:00
2019-06-06 23:57:19 +02:00
```bash
2019-06-08 00:53:30 +02:00
yarn add @ohif/i18n
2019-06-06 23:57:19 +02:00
# OR
2019-06-08 00:53:30 +02:00
npm install --save @ohif/i18n
2019-06-06 23:57:19 +02:00
```
### How it works
2019-06-08 00:53:30 +02:00
After installing `@ohif/i18n` npm package, the translation function
[t](https://www.i18next.com/overview/api#t) can be used [with](#with-react) or
[without](#without-react) React.
2019-06-06 23:57:19 +02:00
2019-06-08 00:53:30 +02:00
A translation will occur every time a text match happens in a
[t](https://www.i18next.com/overview/api#t) function.
The [t](https://www.i18next.com/overview/api#t) function is responsible for
getting translations using all the power of i18next.
2019-06-06 23:57:19 +02:00
E.g.
Before:
2019-06-08 00:53:30 +02:00
```html
2019-06-06 23:57:19 +02:00
<div>my translated text</div>
2019-06-08 00:53:30 +02:00
```
2019-06-06 23:57:19 +02:00
After:
2019-06-08 00:53:30 +02:00
```html
2019-06-06 23:57:19 +02:00
<div>{t('my translated text')}</div>
2019-06-08 00:53:30 +02:00
```
2019-06-06 23:57:19 +02:00
2019-06-08 00:53:30 +02:00
If the translation.json file contains a key that matches the HTML content e.g.
`my translated text`, it will be replaced automatically by the
[t](https://www.i18next.com/overview/api#t) function.
2019-06-06 23:57:19 +02:00
---
2019-06-08 00:53:30 +02:00
2019-06-06 23:57:19 +02:00
#### With React
2019-06-08 00:53:30 +02:00
This section will introduce you to [react-i18next](https://react.i18next.com/)
basics and show how to implement the [t](https://www.i18next.com/overview/api#t)
function easily.
2019-06-06 23:57:19 +02:00
##### Using HOCs
2019-06-08 00:53:30 +02:00
In most cases we used
[High Order Components](https://react.i18next.com/latest/withtranslation-hoc) to
2019-06-12 08:35:17 +02:00
share the `t` function among OHIF's components.
2019-06-08 00:53:30 +02:00
E.g.
2019-06-06 23:57:19 +02:00
```js
import React from 'react';
2019-06-08 00:53:30 +02:00
import { withTranslation } from '@ohif/i18n';
2019-06-06 23:57:19 +02:00
function MyComponent({ t, i18n }) {
2019-06-08 00:53:30 +02:00
return <p>{t('my translated text')}</p>;
2019-06-06 23:57:19 +02:00
}
export default withTranslation('MyNameSpace')(MyComponent);
```
2019-06-08 00:53:30 +02:00
> Important: if you are using React outside the OHIF Viewer, check the
> [I18nextProvider](#using-outside-of-ohif-viewer) section, `withTranslation`
> HOC doesnt works without a I18nextProvider
2019-06-06 23:57:19 +02:00
##### Using Hooks
2019-06-08 00:53:30 +02:00
Also, it's possible to get the `t` tool using
[React Hooks](https://react.i18next.com/latest/usetranslation-hook), but it
2019-06-12 08:35:17 +02:00
requires at least React > 16.8 😉
2019-06-08 00:53:30 +02:00
#### Using outside of OHIF viewer
2019-06-06 23:57:19 +02:00
2019-06-08 00:53:30 +02:00
OHIF Viewer already sets a main
[I18nextProvider](https://react.i18next.com/latest/i18nextprovider) connected to
2019-06-12 08:35:17 +02:00
the shared i18n instance from `@ohif/i18n`, all extensions inside OHIF Viewer
will share this same provider at the end, you don't need to set new providers at
all.
2019-06-06 23:57:19 +02:00
2019-06-08 00:53:30 +02:00
But, if you need to use it completely outside of OHIF viewer, you can set the
I18nextProvider this way:
2019-06-06 23:57:19 +02:00
```js
import i18n from '@ohif/i18n';
import { I18nextProvider } from 'react-i18next';
2019-06-06 23:57:19 +02:00
import App from './App';
<I18nextProvider i18n={i18n}>
<App />
2019-06-08 00:53:30 +02:00
</I18nextProvider>;
2019-06-06 23:57:19 +02:00
```
2019-06-08 00:53:30 +02:00
After setting `I18nextProvider` in your React App, all translations from
`@ohif/i18n` should be available following the basic [With React](#with-react)
usage.
2019-06-08 00:53:30 +02:00
---
2019-06-06 23:57:19 +02:00
#### Without React
2019-06-08 00:53:30 +02:00
When needed, you can also use available translations _without React_.
2019-06-06 23:57:19 +02:00
E.g.
```js
import { T } from '@ohif/i18n';
console.log(T('my translated text'));
console.log(T('$t(Common:Play) my translated text'));
2019-06-06 23:57:19 +02:00
```
---
# Main Concepts While Translating
2019-06-12 08:35:17 +02:00
## - Namespaces
2019-06-06 23:57:19 +02:00
2019-06-08 00:53:30 +02:00
Namespaces are being used to organize translations in smaller portions, combined
semantically or by use. Each `.json` file inside `@ohif/i18n` npm package
becomes a new namespace automatically.
2019-06-06 23:57:19 +02:00
- Buttons: All buttons translations
- CineDialog: Translations for the toll tips inside the Cine Player Dialog
2019-06-12 08:35:17 +02:00
- Common: all common jargons that can be reused like `t('$t(common:image)')`
2019-06-06 23:57:19 +02:00
- Header: translations related to OHIF's Header Top Bar
- MeasurementTable - Translations for the `@ohif/ui` Measurement Table
- UserPreferencesModal - Translations for the `@ohif/ui` Preferences Modal
2019-06-06 23:57:19 +02:00
2019-06-12 08:35:17 +02:00
### How to use another NameSpace inside the current NameSpace?
i18next provides a parsing feature able to get translations strings from any
NameSpace, like this following example getting data from `Common` NameSpace:
2019-06-12 08:35:17 +02:00
```
$t(Common:Reset)
```
## - Extending Languages in @ohif/i18n
2019-06-06 23:57:19 +02:00
Sometimes, even using the same language, some nouns or jargons can change
according to the country, states or even from Hospital to Hospital.
2019-06-06 23:57:19 +02:00
In this cases, you don't need to set an entire language again, you can extend
languages creating a new folder inside a pre existent language folder and
@ohif/i18n will do the hard work.
2019-06-12 08:35:17 +02:00
This new folder must to be called with a double character name, like the `UK` in
the following file tree:
2019-06-06 23:57:19 +02:00
```bash
|-- src
|-- locales
index.js
|-- en
|-- Buttons.json
index.js
| UK
|-- Buttons.js
indes.js
| US
|-- Buttons.js
index.js
...
```
2019-06-06 23:57:19 +02:00
All properties inside a Namespace will be merged in the new sub language, e.g
`en-US` and `en-UK` will merge the props with `en`, using i18next's fallback
languages tool.
2019-06-12 08:35:17 +02:00
You will need to export all Json files in your `index.js` file, mounting an
object like this:
```js
{
en: {
NameSpace: {
keyWord1: 'keyWord1Translation',
keyWord2: 'keyWord2Translation',
keyWord3: 'keyWord3Translation',
}
},
'en-UK': {
NameSpace: {
keyWord1: 'keyWord1DifferentTranslation',
}
}
}
```
Please check the `index.js` files inside locales folder for an example of this
exporting structure.
2019-06-06 23:57:19 +02:00
2019-06-12 08:35:17 +02:00
### - Extending languages dynamically
2019-06-06 23:57:19 +02:00
You have access to the i18next instance, so you can use the
2019-06-08 00:53:30 +02:00
[addResourceBundle](https://www.i18next.com/how-to/add-or-load-translations#add-after-init)
method to add and change language resources as needed.
2019-06-06 23:57:19 +02:00
E.g.
2019-06-08 00:53:30 +02:00
2019-06-06 23:57:19 +02:00
```js
2019-06-08 00:53:30 +02:00
import { i18n } from '@ohif/i18n';
2019-06-06 23:57:19 +02:00
i18next.addResourceBundle('pt-BR', 'Buttons', {
2019-06-08 00:53:30 +02:00
Angle: 'Ângulo',
2019-06-06 23:57:19 +02:00
});
```
2019-06-08 00:53:30 +02:00
---
2019-06-06 23:57:19 +02:00
### How to set a whole new language
2019-06-08 00:53:30 +02:00
2019-06-06 23:57:19 +02:00
To set a brand new language you can do it in two different ways:
2019-06-08 00:53:30 +02:00
- Opening a pull request for `@ohif/i18n` and sharing the translation with the
community. 😍 Please see [Contributing](#contributing-with-new-languages)
section for further information.
2019-06-12 08:35:17 +02:00
- Setting it only in your project or extension:
You'll need a a final object like the following, what is setting French as
language, and send it to `addLocales` method.
2019-06-12 08:35:17 +02:00
```js
const newLanguage =
{
fr: {
Commons: {
"Reset": "Réinitialiser",
"Previous": "Précédent",
},
Buttons: {
"Rectangle": "Rectangle",
"Circle": "Cercle",
}
}
2019-06-06 23:57:19 +02:00
```
To make it easier to translate, you can copy the .json files in the /locales
folder and theirs index.js exporters, keeping same keys and NameSpaces.
Importing the main index.js file, will provide you an Object as expected by the
method `addlocales`;
2019-06-12 08:35:17 +02:00
E.g. of `addLocales` usage
2019-06-06 23:57:19 +02:00
```js
2019-06-12 08:35:17 +02:00
import { addLocales } from '@ohif/i18n';
import locales from './locales/index.js';
addLocales(locales);
2019-06-06 23:57:19 +02:00
```
2019-06-12 08:35:17 +02:00
You can also set them manually, one by one, using this
[method](#extending-languages-dynamically).
2019-06-12 08:35:17 +02:00
---
## Language Detections
@ohif/i18n uses
[i18next-browser-languageDetector](https://github.com/i18next/i18next-browser-languageDetector)
to manage detections, also exports a method called initI18n that accepts a new
detector config as parameter.
2019-06-12 08:35:17 +02:00
### Changing the language
OHIF Viewer accepts a query param called `lng` in the url to change the
language.
E.g.
2019-06-12 08:35:17 +02:00
```
https://docs.ohif.org/demo/?lng=es-MX
```
### Language Persistence
The user's language preference is kept automatically by the detector and stored
at a cookie called 'i18next', and in a localstorage key called 'i18nextLng'.
These names can be changed with a new
[Detector Config](https://github.com/i18next/i18next-browser-languageDetector).
2019-06-06 23:57:19 +02:00
2019-06-08 00:53:30 +02:00
## Debugging translations
There is an environment variable responsible for debugging the translations,
called `REACT_APP_I18N_DEBUG`.
2019-06-07 00:13:16 +02:00
2019-06-12 08:35:17 +02:00
Run the project as following to get full debug information:
2019-06-08 00:53:30 +02:00
```bash
2019-06-12 08:35:17 +02:00
REACT_APP_I18N_DEBUG=true yarn run dev
2019-06-08 00:53:30 +02:00
```
2019-06-07 00:13:16 +02:00
2019-06-06 23:57:19 +02:00
### Contributing with new languages
2019-06-08 00:53:30 +02:00
Contributions of any kind are welcome! Please check the
[instructions](https://docs.ohif.org/contributing.html).