|
| 1 | +--- |
| 2 | +title: App Translation and Localization Guide |
| 3 | +sidebar_label: App Translation |
| 4 | +description: A step-by-step guide for contributors to translate the Time Management App interface into different languages. |
| 5 | +--- |
| 6 | + |
| 7 | +# App Translation and Localization Guide |
| 8 | + |
| 9 | +This guide provides step-by-step instructions for translating the **Time Management App** interface itself (the client application built with QML and Python) into your language. |
| 10 | + |
| 11 | +The app's translation system is based on **gettext**. Translators edit `.po` (Portable Object) files containing key-value translation pairs, which are automatically compiled into binary `.mo`/`.gmo` files during the build process. |
| 12 | + |
| 13 | +--- |
| 14 | + |
| 15 | +## 1. Directory Structure and Translation Files |
| 16 | + |
| 17 | +All translation-related files are located in the `po/` directory at the root of the repository: |
| 18 | + |
| 19 | +```text |
| 20 | +timemanagement/ |
| 21 | +├── po/ |
| 22 | +│ ├── CMakeLists.txt # Build system integration for translations |
| 23 | +│ ├── ubtms.pot # Portable Object Template (contains all untranslated strings) |
| 24 | +│ └── nl.po # Dutch translation source file (example of current translation) |
| 25 | +``` |
| 26 | + |
| 27 | +* **`ubtms.pot`**: The central template file extracted directly from the codebase. It contains all original English strings. |
| 28 | +* **`<locale_code>.po`**: Language-specific translation files (e.g., `nl.po` for Dutch, `es.po` for Spanish). This is the file you will create or modify. |
| 29 | + |
| 30 | +--- |
| 31 | + |
| 32 | +## 2. Prerequisites |
| 33 | + |
| 34 | +To contribute to translations, you should have the following tools installed: |
| 35 | + |
| 36 | +1. **Gettext Utilities**: Command-line tools to initialize, merge, and compile translations. |
| 37 | + * **Ubuntu/Debian**: |
| 38 | + ```bash |
| 39 | + sudo apt update && sudo apt install gettext |
| 40 | + ``` |
| 41 | +2. **Text Editor**: A standard text editor of your choice (such as VS Code, Vim, Gedit, etc.) to edit the translation files. |
| 42 | +3. **Clickable**: The build tool for the application, used to compile and test your translation locally. See the **Getting Started** guide for setup details. |
| 43 | + |
| 44 | +--- |
| 45 | + |
| 46 | +## 3. Translation Workflow |
| 47 | + |
| 48 | +### Step 1: Update the Translation Template (`ubtms.pot`) |
| 49 | +Before starting your translation, compile the project once to ensure the translation template `po/ubtms.pot` is updated with the latest strings from the source code: |
| 50 | + |
| 51 | +```bash |
| 52 | +clickable build |
| 53 | +``` |
| 54 | +*Note: The CMake build system automatically runs the translation extraction target, parsing all QML and desktop entry files to update `po/ubtms.pot`.* |
| 55 | + |
| 56 | +### Step 2: Initialize or Update your Translation File |
| 57 | + |
| 58 | +#### Option A: Starting a New Language |
| 59 | +Determine your 2-letter language code (and optional region, e.g., `fr` for French, `es` for Spanish, `pt_BR` for Brazilian Portuguese). |
| 60 | +Navigate to the `po/` directory and initialize the translation file using `msginit`: |
| 61 | + |
| 62 | +```bash |
| 63 | +cd po |
| 64 | +msginit --locale=<locale_code> --input=ubtms.pot --output=<locale_code>.po |
| 65 | +``` |
| 66 | +*Example for Spanish:* |
| 67 | +```bash |
| 68 | +msginit --locale=es --input=ubtms.pot --output=es.po |
| 69 | +``` |
| 70 | + |
| 71 | +#### Option B: Updating an Existing Language |
| 72 | +If you are translating new strings added to an existing translation (e.g., Dutch `nl.po`), merge the updated template into the translation file using `msgmerge`: |
| 73 | + |
| 74 | +```bash |
| 75 | +cd po |
| 76 | +msgmerge --update <locale_code>.po ubtms.pot |
| 77 | +``` |
| 78 | +*Example for Dutch:* |
| 79 | +```bash |
| 80 | +msgmerge --update nl.po ubtms.pot |
| 81 | +``` |
| 82 | +This adds any new strings, marks deleted strings as obsolete, and flags altered strings as `#, fuzzy` for your review. |
| 83 | + |
| 84 | +--- |
| 85 | + |
| 86 | +### Step 3: Translating the Strings |
| 87 | +Open your `<locale_code>.po` file in your text editor. |
| 88 | + |
| 89 | +For each entry, translate the source string (`msgid`) to the translation string (`msgstr`): |
| 90 | + |
| 91 | +```po |
| 92 | +msgid "Time Manager - Time Management Dashboard" |
| 93 | +msgstr "Tijdbeheer - Dashboard Tijdbeheer" |
| 94 | +``` |
| 95 | + |
| 96 | +#### Key Rules & Best Practices: |
| 97 | +1. **Preserve Placeholders**: Keep parameters like `%1`, `%2`, or `%3` intact. They represent dynamic values substituted at runtime. |
| 98 | + * *Example*: `i18n.dtr("ubtms", "You have %1 new notification(s)")` -> `Je hebt %1 nieuwe melding(en)` |
| 99 | +2. **Preserve Escape Sequences**: Characters like `\n` (newlines) or `\t` (tabs) must remain in the translated string. |
| 100 | +3. **Remove Fuzzy Flags**: If you update a string marked with `#, fuzzy`, remove the `# fuzzy` comment line after verifying the translation is correct. Otherwise, it won't compile. |
| 101 | +
|
| 102 | +--- |
| 103 | +
|
| 104 | +### Step 4: Testing Your Translation Locally |
| 105 | +
|
| 106 | +1. Build the application with Clickable to compile the `.po` translation file to a binary `.mo` catalog: |
| 107 | + ```bash |
| 108 | + clickable build |
| 109 | + ``` |
| 110 | +2. Run the desktop version of the application with your target language configured in the environment: |
| 111 | + ```bash |
| 112 | + LANG=<locale_code>.UTF-8 clickable desktop |
| 113 | + ``` |
| 114 | + *Example for Dutch:* |
| 115 | + ```bash |
| 116 | + LANG=nl_NL.UTF-8 clickable desktop |
| 117 | + ``` |
| 118 | +3. Verify that all translated elements show up correctly in the UI and that there are no layout or text clipping issues. |
| 119 | +
|
| 120 | +--- |
| 121 | +
|
| 122 | +## 4. Code Guidelines for Developers (Marking Strings) |
| 123 | +
|
| 124 | +If you are writing code (QML) and want to ensure your text can be translated, use the following patterns: |
| 125 | +
|
| 126 | +### In QML / JavaScript |
| 127 | +* **Standard Translations**: |
| 128 | + ```qml |
| 129 | + title: i18n.dtr("ubtms", "Settings") |
| 130 | + ``` |
| 131 | +* **Translating with Arguments**: |
| 132 | + ```qml |
| 133 | + text: i18n.dtr("ubtms", "Account [%1]").arg(accountName) |
| 134 | + ``` |
| 135 | +* **Plural Forms**: |
| 136 | + Use `i18n.tr` with plural forms when displaying quantities: |
| 137 | + ```qml |
| 138 | + // Syntax: i18n.tr(singular, plural, count) |
| 139 | + text: i18n.tr("You have %1 task", "You have %1 tasks", count).arg(count) |
| 140 | + ``` |
| 141 | +
|
| 142 | +### In Desktop Entries (`ubtms.desktop.in`) |
| 143 | +For system-level desktop configurations, prefix the translatable keys with an underscore: |
| 144 | +```desktop |
| 145 | +_Name=Time Management |
| 146 | +``` |
| 147 | +*The build system uses `intltool` to extract these desktop keys into `ubtms.pot`.* |
| 148 | +
|
| 149 | +--- |
| 150 | +
|
| 151 | +## 5. Submitting Your Contribution (Creating the PR) |
| 152 | +
|
| 153 | +Once you've tested your translations and verified that the `.po` file is correct, you are ready to submit a Pull Request (PR): |
| 154 | + |
| 155 | +1. **Clean up backup files**: Some editors create temporary backup files (e.g., `nl.po~` or `nl.po.bak`). Delete these before committing. |
| 156 | +2. **Create a Git Branch**: |
| 157 | + ```bash |
| 158 | + git checkout -b translation/add-<locale_code> |
| 159 | + ``` |
| 160 | +3. **Stage and Commit**: |
| 161 | + ```bash |
| 162 | + git add po/<locale_code>.po |
| 163 | + git commit -m "translation: Add <Language_Name> translation" |
| 164 | + ``` |
| 165 | +4. **Push the Branch**: |
| 166 | + ```bash |
| 167 | + git push origin translation/add-<locale_code> |
| 168 | + ``` |
| 169 | +5. **Open the Pull Request**: |
| 170 | + * Navigate to the original repository on GitHub. |
| 171 | + * Click **Compare & pull request**. |
| 172 | + * Fill out the PR template, ensuring you describe the language you added or updated, and confirm that you built and tested it locally. |
0 commit comments