Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NAS-130369 / 24.10 / Clarify how to add translations #10387

Merged
merged 4 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 0 additions & 50 deletions .github/workflows/main-release-engineering.yml

This file was deleted.

12 changes: 0 additions & 12 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,6 @@ jobs:
- name: Build
run: yarn lint

lint-translations:
name: Validate translation strings
needs: [install]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install
uses: ./.github/actions/prepare
- name: Validate
run: yarn run validate-translations

test:
name: Run tests
needs: [install]
Expand Down
25 changes: 25 additions & 0 deletions .github/workflows/validate-translations.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: WebUI
on:
push:
branches:
- master
paths:
- 'src/assets/i18n/**'
pull_request:
branches:
- '**'
paths:
- 'src/assets/i18n/**'

jobs:
lint-translations:
name: Validate translation strings
needs: [install]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install
uses: ./.github/actions/prepare
- name: Validate
run: yarn run validate-translations
10 changes: 1 addition & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,7 @@ ESLint is set up to ensure that the code is up to the format standards that we w

### Translating the UI

If you want to contribute to the translation of our UI, you can do so by editing one of the `[language_name].json` files under `src\assets\i18n\`. In each of those files, text strings and their translations in the relevant language are kept as key/value pairs e.g.,

`
{
...,
"Translate this text": "[Translation]",
...
}
`
See the [TRANSLATING.md](https://github.com/truenas/webui/blob/master/TRANSLATING.md) for more information on how to translate the UI.

## Tests

Expand Down
30 changes: 2 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,35 +104,9 @@ yarn install

This should bring the yarn environment back to a usable state.

# Translating Text to Other Languages
# Translating UI

All JSON files for translating TrueNAS's web interface are included in this repository under [src/assets/i18n](https://github.com/truenas/webui/tree/master/src/assets/i18n). \
These can be edited using your editor of choice or directly via the GitHub Web based code editing system.

Translation needs to be added to the right part of the string. For example:

```
"1 day": "1 jour",
```

Some strings may use [ICU Message Format](https://formatjs.io/docs/core-concepts/icu-syntax/#plural-format) for pluralization.\
You can move tokens around and adjust them for your language.

For example:

```
Deleted {n, plural, one {# snapshot} other {# snapshots}}
```

can be translated in Russian as:

```
{n, plural, =1 {Снимок удален} few{# снимка удалено} other {# снимков удалено}}
```

You can test your strings in an [online editor](http://format-message.github.io/icu-message-format-for-translators/editor.html).

String files are often changed by developers and other contributors, so it's better to make multiple smaller PRs instead of trying to translate everything at once.
See the [TRANSLATING.md](https://github.com/truenas/webui/blob/master/TRANSLATING.md) for more information on how to translate the UI.

# Contributing

Expand Down
95 changes: 95 additions & 0 deletions TRANSLATING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Translating TrueNAS UI

All JSON files for translating TrueNAS web interface are included in this repository under [src/assets/i18n](https://github.com/truenas/webui/tree/master/src/assets/i18n). \
These can be edited using your editor of choice or directly via the GitHub Web based code editing system.

Translation needs to be added to the right part of the string. For example:

```
"1 day": "",
```

becomes

```
"1 day": "1 jour",
```

### Branches

Different branches correspond to different versions of TrueNAS.

It's easiest to make changes to the `master` branch, which corresponds to the most recent unreleased version of TrueNAS SCALE.

Once changes to `master` are merged, they will appear in next nightly build.

### General Recommendations

- Source files may often change, so it's better to make multiple smaller PRs instead of trying to translate everything at once.
- CI job will validate your changes and will fail if there are any issues.
- If you want to validate translation strings locally, you need to have Node.js and `yarn` installed, do `yarn install` and execute `yarn validate-translations` in the root of the project.

### Placeholder Tokens

Some strings may contain placeholder tokens in `{curly braces}`.

For example:

```
"Delete {file}?": "",
```

In the UI `{file}` will be replaced with the name of the file, resulting in a string like `"Delete file.txt?"`.

You should keep these tokens as is in the translated string, but you can move them around if needed.

```
"Delete {file}?": "Supprimer {file}?",
```

### Plural Forms

Some strings may use [ICU Message Format](https://formatjs.io/docs/core-concepts/icu-syntax/#plural-format) for pluralization.

For example,

```
{n, plural, one {User} other {# users}} deleted
```

may show either `User deleted` or `5 users deleted` depending on the value of `n`.

Everything inside the curly braces is a part of the ICU Message Format.

This particular example can be read as:

1. Look at the value of `n`.
2. If `n` is `1`, print `User`.
3. If `n` is anything else, print `# users`, where `#` is replaced with the value of `n`.
4. Add `deleted` at the end.

#### Translating Plural Forms

Different languages have different ways of expressing plural forms.

In English plurality is expressed by changing the form of the noun: `User -> users`.

In Spanish, both noun and verb may change: `Usuario eliminado -> Usuarios eliminados`.

You can express it in the following way:

```
{n, plural, one {Usuario eliminado} other {# usuarios eliminados}}
```

Russian is an example of a language that has more than just singular and plural form of the word. It has one word for 1 item, another for 2 to 4 items and yet another for 5 items and more: `Пользователь -> пользователя -> пользователей`.

This can be expressed via:

```
{n, plural, =1 {Пользователь удален} few{# пользователя удалено} other {# пользователей удалено}}
```

You would have to research ICU Message Format for your language to find out how to express plural forms.

Plural strings can be tested in an [online editor](http://format-message.github.io/icu-message-format-for-translators/editor.html).
8 changes: 6 additions & 2 deletions scripts/validate_translations.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ fs.readdir(translationDir, function (err, files) {
parse(translation);
} catch (error) {
hadErrors = true;
console.error("Error parsing translation string. You may need to escape { } to '{' '}'. Offending string:");
console.error(`${language}: "${key}"`, JSON.stringify(error));

if (error.location) {
console.error(`${language}.json, line ${error.location.start.line}: ${error.message}`);
} else {
console.error(`${language}.json: ${error.message}`);
}
}
});
});
Expand Down
3 changes: 3 additions & 0 deletions src/app/helptext/system/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ export const helptextSystemGeneral = {
stg_language: {
placeholder: T('Language'),
tooltip: T('Select a language from the drop-down menu.'),
hint: T('Languages other than <i>English</i> are provided by \
the community and may be incomplete. \
<a href="https://github.com/truenas/webui/blob/master/TRANSLATING.md" target="_blank">Learn how to contribute.</a>'),
},

stg_kbdmap: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
[provider]="language.provider"
[required]="true"
></ix-combobox>

@if (!(isEnterprise$ | async) || true) {
<p class="language-hint" [innerHtml]="language.hint | translate"></p>
}

<ix-select
[label]="kbdMap.label | translate"
[tooltip]="kbdMap.tooltip | translate"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
}
}

.language-hint {
font-size: 12px;
margin-top: -12px;
}

.divider {
margin: 16px 0 !important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { AppState } from 'app/store';
import { localizationFormSubmitted } from 'app/store/preferences/preferences.actions';
import { generalConfigUpdated } from 'app/store/system-config/system-config.actions';
import { systemInfoUpdated } from 'app/store/system-info/system-info.actions';
import { selectIsEnterprise } from 'app/store/system-info/system-info.selectors';

@UntilDestroy()
@Component({
Expand Down Expand Up @@ -53,11 +54,13 @@ export class LocalizationFormComponent implements OnInit {
readonly fcName: 'language';
label: string;
tooltip: string;
hint: string;
provider: SimpleAsyncComboboxProvider;
} = {
fcName: 'language',
label: helptext.stg_language.placeholder,
tooltip: helptext.stg_language.tooltip,
hint: helptext.stg_language.hint,
provider: new SimpleAsyncComboboxProvider(this.sysGeneralService.languageOptions(this.sortLanguagesByName)),
};

Expand Down Expand Up @@ -109,6 +112,8 @@ export class LocalizationFormComponent implements OnInit {
tooltip: helptext.time_format.tooltip,
};

protected isEnterprise$ = this.store$.select(selectIsEnterprise);

constructor(
private sysGeneralService: SystemGeneralService,
private fb: FormBuilder,
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/af.json
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,7 @@
"LUN RPM": "",
"Lan": "",
"Language": "",
"Languages other than <i>English</i> are provided by the community and may be incomplete. <a href=\"https://github.com/truenas/webui/blob/master/TRANSLATING.md\" target=\"_blank\">Learn how to contribute.</a>": "",
"Last 24 hours": "",
"Last 3 days": "",
"Last Page": "",
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,7 @@
"LUN RPM": "",
"Lan": "",
"Language": "",
"Languages other than <i>English</i> are provided by the community and may be incomplete. <a href=\"https://github.com/truenas/webui/blob/master/TRANSLATING.md\" target=\"_blank\">Learn how to contribute.</a>": "",
"Last 24 hours": "",
"Last 3 days": "",
"Last Page": "",
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/ast.json
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,7 @@
"LUN RPM": "",
"Lan": "",
"Language": "",
"Languages other than <i>English</i> are provided by the community and may be incomplete. <a href=\"https://github.com/truenas/webui/blob/master/TRANSLATING.md\" target=\"_blank\">Learn how to contribute.</a>": "",
"Last 24 hours": "",
"Last 3 days": "",
"Last Page": "",
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/az.json
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,7 @@
"LUN RPM": "",
"Lan": "",
"Language": "",
"Languages other than <i>English</i> are provided by the community and may be incomplete. <a href=\"https://github.com/truenas/webui/blob/master/TRANSLATING.md\" target=\"_blank\">Learn how to contribute.</a>": "",
"Last 24 hours": "",
"Last 3 days": "",
"Last Page": "",
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/be.json
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,7 @@
"LUN RPM": "",
"Lan": "",
"Language": "",
"Languages other than <i>English</i> are provided by the community and may be incomplete. <a href=\"https://github.com/truenas/webui/blob/master/TRANSLATING.md\" target=\"_blank\">Learn how to contribute.</a>": "",
"Last 24 hours": "",
"Last 3 days": "",
"Last Page": "",
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/bg.json
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,7 @@
"LUN RPM": "",
"Lan": "",
"Language": "",
"Languages other than <i>English</i> are provided by the community and may be incomplete. <a href=\"https://github.com/truenas/webui/blob/master/TRANSLATING.md\" target=\"_blank\">Learn how to contribute.</a>": "",
"Last 24 hours": "",
"Last 3 days": "",
"Last Page": "",
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/bn.json
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,7 @@
"LUN RPM": "",
"Lan": "",
"Language": "",
"Languages other than <i>English</i> are provided by the community and may be incomplete. <a href=\"https://github.com/truenas/webui/blob/master/TRANSLATING.md\" target=\"_blank\">Learn how to contribute.</a>": "",
"Last 24 hours": "",
"Last 3 days": "",
"Last Page": "",
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/br.json
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,7 @@
"LUN RPM": "",
"Lan": "",
"Language": "",
"Languages other than <i>English</i> are provided by the community and may be incomplete. <a href=\"https://github.com/truenas/webui/blob/master/TRANSLATING.md\" target=\"_blank\">Learn how to contribute.</a>": "",
"Last 24 hours": "",
"Last 3 days": "",
"Last Page": "",
Expand Down
1 change: 1 addition & 0 deletions src/assets/i18n/bs.json
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,7 @@
"LUN RPM": "",
"Lan": "",
"Language": "",
"Languages other than <i>English</i> are provided by the community and may be incomplete. <a href=\"https://github.com/truenas/webui/blob/master/TRANSLATING.md\" target=\"_blank\">Learn how to contribute.</a>": "",
"Last 24 hours": "",
"Last 3 days": "",
"Last Page": "",
Expand Down
Loading
Loading