Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion app/electron/i18next-parser.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ module.exports = {
lexers: {
default: ['JsxLexer'],
},
namespaceSeparator: '|',
namespaceSeparator: false,
keySeparator: false,
defaultNamespace: 'app',
contextSeparator: sharedConfig?.contextSeparator || '//context:',
Expand Down
195 changes: 164 additions & 31 deletions docs/development/i18n/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,116 @@ title: Contributing to Internationalization
sidebar_label: Contributing
---

This section introduces some concepts for contributing translations and is
especially important when submitting a new language.
Welcome! This guide will help you contribute translations to Headlamp.

**Important:** If you add a new language, keep in mind that while all
## Quick Start

### Where to Edit Translations

**⚠️ IMPORTANT:** All translations should be edited in:
```
frontend/src/i18n/locales/
```

This is the **single source of truth** for all translations. Do not edit translation files in other locations (like `plugins/headlamp-plugin/src/i18n/locales/`) as they are auto-generated during the build process.

### Translation File Structure

Each language has its own directory with three JSON files:

```
locales/
├── en/ # English (reference language)
│ ├── translation.json # Main translations
│ ├── glossary.json # Kubernetes technical terms
│ └── app.json # Desktop app specific strings
├── de/ # German
│ ├── translation.json
│ ├── glossary.json
│ └── app.json
├── fr/ # French
...
```

**Important:** When adding a new language, keep in mind that while all
the specific Kubernetes components' names are translatable, not all of them
will have a corresponding name in your language. Please refer to the
[Kubernetes localized docs](https://kubernetes.io/docs/home/) in your
language (if they exist) to understand which components should
be translated and which should be left in their original form.

## Helper Commands

We provide several commands to make translation easier:

### Check Translation Status

See which languages need translation work:

```bash
npm run i18n:status
```

This shows a colorful table with:
- Translation completion percentage for each language
- Number of translated vs. missing strings
- Visual progress bars

### List Translation Files

See all translation files with their completion status:

```bash
# List all languages
npm run i18n:list

# List specific language (note the -- before language code)
npm run i18n:list -- de
```

This shows:
- All translation files for each language
- Completion percentage for each file
- Missing files (if any)
- File paths

### Extract Empty Translations

Extract untranslated strings to a separate file for easier translation:

```bash
npm run i18n:extract -- frontend/src/i18n/locales/de/translation.json
```

This creates a file (e.g., `translation_empty.json`) containing only the empty translations. You can:
1. Translate the strings in this smaller file
2. Use the copy command (below) to merge them back

Optional: Specify output filename:
```bash
npm run i18n:extract -- frontend/src/i18n/locales/de/translation.json my_translations.json
```

### Copy Translations Between Files

Copy translations from one file to another:

```bash
# Basic usage - only copy missing translations
npm run i18n:copy -- source.json dest.json

# Force overwrite all translations (including non-empty ones)
npm run i18n:copy -- source.json dest.json --force

# Copy all keys from source, even if they don't exist in destination
npm run i18n:copy -- source.json dest.json --all
```

This is useful for:
- Merging completed translations back from an extracted file
- Copying translations between language files
- Updating translations selectively

## Namespaces

We have only two main [i18next namespaces](https://www.i18next.com/principles/namespaces):
Expand Down Expand Up @@ -86,39 +186,72 @@ Here's an example of using date formatting:
});
```

## Adding a new language
## Translation Workflow

### For Updating Existing Languages

Create a folder using the locale code in:
`frontend/src/i18n/locales/`
1. **Check translation status:**
```bash
npm run i18n:status
```

Then run `npm run i18n`. This command parses the translatable strings in
the project and creates the corresponding catalog files.
2. **Open the JSON files directly** in `frontend/src/i18n/locales/<lang>/`
- `translation.json` - UI strings
- `glossary.json` - Kubernetes technical terms
- `app.json` - App-specific strings

3. **Find empty strings** (these need translation):
```json
{
"Some key": "", ← Needs translation
"Another key": "Translated text" ← Already done
}
```

4. **Add translations** for empty strings:
```json
{
"Some key": "Your translation here",
"Another key": "Translated text"
}
```

5. **Verify your work:**
```bash
npm run i18n:status
```

6. **Submit a pull request** with your changes

### For Adding a New Language

1. **Create the language directory:**
```bash
mkdir frontend/src/i18n/locales/<lang-code>
```

Language codes should follow the [ISO 639-1 standard](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).

2. **Generate translation files:**
```bash
# From the project root
npm run i18n
```

This will create empty translation files for your new language.

3. **Follow the update workflow above** to translate the strings

Integrated components may need to be adjusted (MaterialUI/Monaco etc).

## Translating missing strings

Technical development happens more frequently than translations. Thus, chances
are that developers introduce new strings that need to be translated and will
be stored as empty strings (defaulting to English) in the translation files.

In order to more easily spot and translate the missing strings, we have two CLI
tools:

- _extract-empty-translations.js_: This script (in ./frontend/src/i18n/tools/)
will extract the strings without a corresponding translation from the translation
files, and copy them into a new file.
E.g. `$ node copy-empty-translations.js ../locales/de/translation.json` will
by default create a `../locales/de/translation_empty.json`. This file can be
used to translate the strings in a more isolated way.
- _copy-translations.js_: This script (in ./frontend/src/i18n/tools/)
by default copies any existing translations from one source translation file to
a target one, if the same key is not translated in the destination file.
E.g. `$ node copy-translations.js ../locales/de/translation_no_longer_empty.json ../locales/de/translation.json` will
copy any new translations from the file given as the first argument to the one
given as the second argument, if the same key is not translated in the second.
There are some options to this script, which can be seen by running it with the
`--help` flag.
## Deprecated Tools

**⚠️ DEPRECATED:** The old CLI tools in `frontend/src/i18n/tools/` are deprecated and should no longer be used:

- `extract-empty-translations.js` → Use `npm run i18n:extract` instead
- `copy-translations.js` → Use `npm run i18n:copy` instead

The new i18n tool (see Helper Commands above) provides the same functionality with better error handling and a more consistent interface.

## Material UI

Expand Down
28 changes: 27 additions & 1 deletion frontend/src/i18n/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,30 @@

We try and keep all the i18n related things in here.

See the [i18n docs](../../docs/development/i18n.md) for full details.
## For Translators

See the [i18n contributing guide](../../../docs/development/i18n/contributing.md) for a complete guide on how to contribute translations.

### Quick Commands

```bash
npm run i18n:status # Show translation status for all languages
npm run i18n:list # List all translation files with completion status
npm run i18n:list -- de # List translation files for German with completion status
```

**Note:** These commands are run from the project root directory.

## Translation File Location

**⚠️ IMPORTANT:** All translations should be edited in:

```
frontend/src/i18n/locales/
```

This is the **single source of truth** for all Headlamp translations. Do not edit translation files in other locations (like `plugins/headlamp-plugin/src/i18n/locales/`) as they are auto-generated.

## For Developers

See the [i18n docs](../../docs/development/i18n.md) for full technical details.
3 changes: 3 additions & 0 deletions frontend/src/i18n/tools/copy-translations.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
* limitations under the License.
*/

// ⚠️ DEPRECATED: This script is deprecated. Use the new i18n tool instead:
// npm run i18n:copy -- <srcFile> <destFile> [--force] [--all]
//
// This script copies the translations from a translations file to an existing file.
// By default, it 1) only overwrites translations that are missing or are empty, in the destination file,
// and 2) only copies translations that are in the destination file.
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/i18n/tools/extract-empty-translations.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
* limitations under the License.
*/

// ⚠️ DEPRECATED: This script is deprecated. Use the new i18n tool instead:
// npm run i18n:extract -- <translationsFile> [outputFile]
//
// This script copies the empty translations from a translations file to a new file. So they can
// be easily spotted and translated.
//
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,12 @@
"frontend:start": "cd frontend && npm start",
"frontend:storybook": "cd frontend && npm run storybook",
"docs": "cd frontend && npm run build-typedoc",
"i18n": "cd frontend && npm run i18n",
"i18n": "cd frontend && npm run i18n && cd ../app && npm run i18n",
"i18n:check": "cd frontend && npm run i18n -- --fail-on-update",
"i18n:status": "cd tools/i18n && npm run status",
"i18n:list": "cd tools/i18n && npm run list",
"i18n:extract": "cd tools/i18n && npm run extract --",
"i18n:copy": "cd tools/i18n && npm run copy --",
"app:install": "cd app && npm install",
"app:build": "npm run frontend:build && cd app && node ./scripts/setup-plugins.js && npm run build",
"app:build:dir": "npm run frontend:build && cd app && node ./scripts/setup-plugins.js && npm run build -- --dir",
Expand Down
89 changes: 89 additions & 0 deletions tools/i18n/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# I18n Tool

A TypeScript tool to help translators work with Headlamp's internationalization files.

## Features

- **Status**: View translation completion status for all languages with progress bars
- **List**: Show all translation files with completion percentages and detect missing files
- **Extract**: Extract empty translations to a separate file for easy translation
- **Copy**: Copy translations from one file to another (with options to force overwrite or copy all)

## Usage from Project Root

From the Headlamp project root, use the npm scripts:

```bash
# View translation status
npm run i18n:status

# List translation files
npm run i18n:list # All languages
npm run i18n:list -- es # Specific language (e.g., Spanish)

# Extract empty translations for easier translation
npm run i18n:extract -- frontend/src/i18n/locales/de/translation.json

# Copy translations between files
npm run i18n:copy -- source.json dest.json # Copy only missing translations
npm run i18n:copy -- source.json dest.json --force # Overwrite all translations
npm run i18n:copy -- source.json dest.json --all # Copy even keys not in dest
```

## Development

### Running Locally

```bash
# From tools/i18n directory
npm run status
npm run list # All languages
npm run list -- zh # Specific language
npm run extract -- ../../../frontend/src/i18n/locales/de/translation.json
npm run copy -- source.json dest.json
```

The tool runs directly with ts-node, no build step needed.

### Running Tests

```bash
# From tools/i18n directory
npm install # Install dependencies first

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage
```

The test suite includes comprehensive end-to-end tests for:
- All CLI commands (status, list, extract, copy)
- Command options (--force, --all)
- Error handling (missing files, malformed JSON)
- Edge cases (empty files, path resolution)
- Help and usage documentation

Tests run the CLI as a subprocess to test the real user experience.

## Translation File Location

All translation files are located in: `frontend/src/i18n/locales/`

This is the single source of truth for all translations. Translation files in other locations (like `plugins/headlamp-plugin/`) are auto-generated during the build process.

## Deprecation of Old Tools

This tool replaces the old scripts in `frontend/src/i18n/tools/`:
- `copy-translations.js` → Use `npm run i18n:copy`
- `extract-empty-translations.js` → Use `npm run i18n:extract`

The old scripts are deprecated and should no longer be used.

## For More Information

See `docs/development/i18n/contributing.md` for complete translator documentation.
Loading
Loading