diff options
Diffstat (limited to 'doc/development/i18n/externalization.md')
-rw-r--r-- | doc/development/i18n/externalization.md | 128 |
1 files changed, 73 insertions, 55 deletions
diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md index 796a1f44ccd..53825f0904a 100644 --- a/doc/development/i18n/externalization.md +++ b/doc/development/i18n/externalization.md @@ -131,40 +131,70 @@ You can mark that content for translation with: ### JavaScript files -In JavaScript we added the `__()` (double underscore parenthesis) function that -you can import from the `~/locale` file. For instance: +The `~/locale` module exports the following key functions for externalization: + +- `__()` (double underscore parenthesis) +- `s__()` (namespaced double underscore parenthesis) +- `__()` Mark content for translation (note the double underscore). +- `s__()` Mark namespaced content for translation +- `n__()` Mark pluralized content for translation ```javascript -import { __ } from '~/locale'; +import { __, s__, n__ } from '~/locale'; + +const defaultErrorMessage = s__('Branches|Create branch failed.'); const label = __('Subscribe'); +const message = n__('Apple', 'Apples', 3) ``` -To test JavaScript translations you must: - -- Change the GitLab localization to a language other than English. -- Generate JSON files by using `bin/rake gettext:po_to_json` or `bin/rake gettext:compile`. +To test JavaScript translations, learn about [manually testing translations from the UI](#manually-test-translations-from-the-ui). ### Vue files -In Vue files, we make the following functions available: +In Vue files, we make the following functions available to Vue templates using the `translate` mixin: -- `__()` (double underscore parenthesis) -- `s__()` (namespaced double underscore parenthesis) +- `__()` +- `s__()` +- `n__()` +- `sprintf` -You can therefore import from the `~/locale` file. -For example: +This means you can externalize strings in Vue templates without having to import these functions from the `~/locale` file: -```javascript -import { __, s__ } from '~/locale'; -const label = __('Subscribe'); -const nameSpacedlabel = __('Plan|Subscribe'); +```html +<template> + <h1>{{ s__('Branches|Create a new branch') }}</h1> + <gl-button>{{ __('Create branch') }}</gl-button> +</template> ``` -For the static text strings we suggest two patterns for using these translations in Vue files: +If you need to translate strings in the Vue component's JavaScript, you can import the necessary externalization function from the `~/locale` file as described in the [JavaScript files](#javascript-files) section. -- External constants file: +To test Vue translations, learn about [manually testing translations from the UI](#manually-test-translations-from-the-ui). - ```javascript +#### Recommendations + +If strings are reused throughout a component, it can be useful to define these strings as variables. We recommend defining an `i18n` property on the component's `$options` object. If there is a mixture of many-use and single-use strings in the component, consider using this approach to create a local [Single Source of Truth](https://about.gitlab.com/handbook/values/#single-source-of-truth) for externalized strings. + +```javascript +<script> + export default { + i18n: { + buttonLabel: s__('Plan|Button Label') + } + }, +</script> + +<template> + <gl-button :aria-label="$options.i18n.buttonLabel"> + {{ $options.i18n.buttonLabel }} + </gl-button> +</template> +``` + +Also consider defining these strings in a `constants.js` file, especially if they need +to be shared across different modules. + +```javascript javascripts │ └───alert_settings @@ -179,60 +209,41 @@ For the static text strings we suggest two patterns for using these translations /* Integration constants */ - export const I18N_ALERT_SETTINGS_FORM = { - saveBtnLabel: __('Save changes'), - }; + export const MSG_ALERT_SETTINGS_FORM_ERROR = __('Failed to save alert settings.') // alert_settings_form.vue import { - I18N_ALERT_SETTINGS_FORM, + MSG_ALERT_SETTINGS_FORM_ERROR, } from '../constants'; <script> export default { - i18n: { - I18N_ALERT_SETTINGS_FORM, - } + MSG_ALERT_SETTINGS_FROM_ERROR, } </script> <template> - <gl-button - ref="submitBtn" - variant="success" - type="submit" - > - {{ $options.i18n.I18N_ALERT_SETTINGS_FORM }} - </gl-button> + <gl-alert v-if="showAlert"> + {{ $options.MSG_ALERT_SETTINGS_FORM_ERROR }} + </gl-alert> </template> - ``` - - When possible, you should opt for this pattern, as this allows you to import these strings directly into your component specs for re-use during testing. - -- Internal component `$options` object: +``` - ```javascript - <script> - export default { - i18n: { - buttonLabel: s__('Plan|Button Label') - } - }, - </script> +Using either `constants` or `$options.i18n` allows us to reference messages directly in specs: - <template> - <gl-button :aria-label="$options.i18n.buttonLabel"> - {{ $options.i18n.buttonLabel }} - </gl-button> - </template> - ``` +```javascript +import { MSG_ALERT_SETTINGS_FORM_ERROR } from 'path/to/constants.js'; -To visually test the Vue translations: +// okay +expect(wrapper.text()).toEqual('this test will fail just from button text changing!'); -1. Change the GitLab localization to another language than English. -1. Generate JSON files using `bin/rake gettext:po_to_json` or `bin/rake gettext:compile`. +// better +expect(wrapper.text()).toEqual(MyComponent.i18n.buttonLabel); +// also better +expect(wrapper.text()).toEqual(MSG_ALERT_SETTINGS_FORM_ERROR); +``` ### Dynamic translations @@ -853,3 +864,10 @@ Suppose you want to add translations for a new language, for example, French: git add locale/fr/ app/assets/javascripts/locale/fr/ git commit -m "Add French translations for Value Stream Analytics page" ``` + +## Manually test translations from the UI + +To manually test Vue translations: + +1. Change the GitLab localization to another language than English. +1. Generate JSON files using `bin/rake gettext:po_to_json` or `bin/rake gettext:compile`. |