|
| 1 | +--- |
| 2 | +layout: default |
| 3 | +--- |
| 4 | +# Writing Code for Translation |
| 5 | + |
| 6 | +How to write code with strings that should be translated |
| 7 | + |
| 8 | +In most cases, any user-visible text in FreeCAD should be made translatable. Exceptions to this general rule are: |
| 9 | +1. Text that only appears as log-level messages in the Report View |
| 10 | +2. Names of Workbenches (e.g. "Start", "Part", "Path") |
| 11 | +3. Names of Python commands, etc. |
| 12 | + |
| 13 | +Some general guidelines when constructing strings for translation: |
| 14 | +* Not all languages use the same word order, so it's best to write complete sentences (and sometimes complete paragraphs), using the `Qtring::args()` function, or the Python `format()` function to do replacements where necessary. |
| 15 | +* The script that extracts translatable strings from Python does not currently (as of Qt 6.4) support Python string concatenation, so to follow the above guideline you *must* write your translatable string on a single line of code. |
| 16 | +* The NOOP-versions of the Qt translation functions extract the string for translation purposes, but *do not* replace the string in place with its translated equivalent. They should generally only be used in classes derived from Gui::Command for things like the menu entry and tooltip. The Command class handles actually loading the translated string. |
| 17 | +* In a non-QObject-derived class, use `Q_DECLARE_TR_FUNCTIONS(MyClass)` to give your class access to the `tr()` function. See also [the Qt documentation](https://doc.qt.io/qt-5/i18n-source-translation.html). |
| 18 | + |
| 19 | +## Translating plurals |
| 20 | + |
| 21 | +Many languages have complex pluralization rules. To support this, you can write strings that are designed for pluralization, including in English, by specifying a parameter that indicates how many of a thing there are. The translation system will dynamically select the correct translation (assuming translators wrote one), even for English. For example |
| 22 | +``` |
| 23 | +int nErrors = getNumberOfErrors(); // Might be zero, might be one, might be some other number. |
| 24 | +tr("There were %n errors.", "", nErrors); |
| 25 | +``` |
| 26 | +Translators will be given the opportunity to translate this string in several variants (depending on the language they are translating for). For example, in English we would have: |
| 27 | +``` |
| 28 | +There were 0 errors. |
| 29 | +There was 1 error. |
| 30 | +There were 2 errors. |
| 31 | +``` |
| 32 | +In other languages there might be more than two variants, the sentence structure might change completely, etc. Qt and the CrowdIn translation platform support this structure. |
| 33 | + |
| 34 | +## Testing your strings |
| 35 | + |
| 36 | +The translation process has several steps, each of which you can examine during the development process. |
| 37 | + |
| 38 | +### String extraction |
| 39 | + |
| 40 | +To determine whether your strings are being correctly extracted, you can directly run the `lupdate` command on the file you are working on, using a dummy TS output file. `lupdate` is included in your Qt installation (note that internally we use lupdate from Qt 6.4 -- this is particularly important if you are testing Python code, as several major problems were address by a patch we submitted to Qt 6.4). |
| 41 | +``` |
| 42 | +lupdate MySourceCodeFile.cpp --ts test.ts |
| 43 | +``` |
| 44 | +will generate the file test.ts -- you can examine it to ensure your string appears with the expected context in that file. In particular, make sure that each string makes sense alone: otherwise, without context, translators will not know what they should replace it with. |
| 45 | + |
| 46 | +### String replacement |
| 47 | + |
| 48 | +To determine whether the string is being replaced correctly, you can create a dummy language file from the above test.ts file, and inject it into your FreeCAD instance. To do this you must know the name of the file that the finished translations will be put into. In general this is the name of the module you are working on, an underscore, the language code, and ".ts". For example, "PartDesign_es-ES.ts" is the Spanish (Spain) translation file for the Part Design workbench. An exception is the code in `src/Gui`, which is FreeCAD_xx.ts (where xx is the language code). |
| 49 | + |
| 50 | +For testing purposes, choose a language you are familiar with (or at least, can navigate well enough to deactivate when you are done testing!), and copy the file generated by lupdate into the appropriate filename. Locate the string you want to test: |
| 51 | +``` |
| 52 | + <message> |
| 53 | + <location filename="../CommandDoc.cpp" line="1649"/> |
| 54 | + <source>Activates or Deactivates the selected object's edit mode</source> |
| 55 | + <translation type="unfinished"></translation> |
| 56 | + </message> |
| 57 | +``` |
| 58 | +Edit this to eliminate the "unfinished" and to add a translation, e.g. |
| 59 | +``` |
| 60 | + <message> |
| 61 | + <location filename="../CommandDoc.cpp" line="1649"/> |
| 62 | + <source>Activates or Deactivates the selected object's edit mode</source> |
| 63 | + <translation>Activa o desactiva el modo de edición del objeto seleccionado</translation> |
| 64 | + </message> |
| 65 | +``` |
| 66 | +Next, this file must be converted to a `*.qm` file using the `lrelease` tool (distributed with Qt). Finally, place the generated QM file in the same location as your user.cfg file, in a subdirectory called "translations", then switch FreeCAD to the language you chose to test with. Your translated string should appear. |
0 commit comments