Translation System
From WinMerge
Contents |
[edit] Introduction
Beginning from WinMerge 2.7.5.4 (experimental) we use a new translation system. It uses PO files as translation files in runtime. WinMerge reads (using a helper DLL file) the [language name].po file from the Languages/ subfolder and uses strings from it to replace strings in English resources.
The old system of compiling satellite DLLs from per-language RC files was a lot of work developers to maintain, update and merge changes. RC files are also hard to translate. For example in dialog resources, the translated strings are in middle of other resource data and it is easy to miss strings.
[edit] Advantages
- The developers don't need to merge changes at
Merge.rcto all translations. (This was dull and error-prone work!)- This was many times a blocker to do GUI improvements! It simply was too much work to do e.g. dialog layout changes without a real good reasons.
- The translators can use the great tool poEdit or a simple text editor for the translation.
- No extra step to compile the
.langfiles needed anymore. - Easier statistics creation about the translations status.
[edit] Disadvantages
- We currently don't support context specific translations. That means there is one translatable string for every unique English string. For example there is one string for every "Browse" button caption text. Usually this is not a problem, but sometimes translation could be different in different contexts.
- Collecting the line numbers in PO files creates much noise in SVN.
- Note that you can use
"^#"
-linefilter in WinMerge to filter out those changes
- Note that you can use
[edit] Working with the new system
All the resource changes are done to Src/Merge.rc file (and to Src/resource.h when needed). Strings are propagated to the Src/Languages/English.pot file when building WinMerge. And to all .po files either by the script or by translators or tools.
So to make a resource change:
- edit the
Src/Merge.rc(andSrc/resource.h) files - build WinMerge in Visual Studio (or update
Src/Languages/English.potfile with the script) - use the script to update all
.pofiles
[edit] Using Resource Strings in the Code
There are several functions declared in Src/stdafx.h:
/** @brief Load string from string resources; shortcut for CString::LoadString */ String LoadResString(UINT id); /** @brief Wrapper around CMergeApp::TranslateDialog() */ void NTAPI LangTranslateDialog(HWND); /** @brief Lang aware version of AfxFormatStrings() */ void NTAPI LangFormatStrings(CString &, UINT, LPCTSTR const *, int); /** @brief Lang aware version of AfxFormatString1() */ void NTAPI LangFormatString1(CString &, UINT, LPCTSTR); /** @brief Lang aware version of AfxFormatString2() */ void NTAPI LangFormatString2(CString &, UINT, LPCTSTR, LPCTSTR); /** @brief Lang aware version of AfxMessageBox() */ int NTAPI LangMessageBox(UINT, UINT nType = MB_OK, UINT nIDHelp = (UINT)-1); /** @brief Format single-argument resource string and display via AfxMessageBox */ int ResMsgBox1(UINT msgid, LPCTSTR arg, UINT nType = MB_OK, UINT nIDHelp = 0);
Usage of these functions is like their MFC counterparts (as mentioned in the comments). So to load a single string from resource, you write a code like this:
#include "stdafx.h" // [...] String myStr = LoadResString(IDS_MYSTRING);
CString-class has a constructor accepting resource ID as a parameter, and it loads the resource string. It is a handy way to load resource strings. And CString has also a LoadString() method for the same purpose. But unfortunately they do not work with WinMerge's translation system.
[edit] Implementing Translation Aware Dialog
You need to call the CMergeApp::TranslateDialog(HWND h) in the dialog's initialization code.
For example:
/** * @brief Dialog initialisation. Make dialog translatable. */ BOOL CMyDialog::OnInitDialog() { theApp.TranslateDialog(m_hWnd); CDialog::OnInitDialog(); return TRUE; }
[edit] Editing Merge.rc
Src/Merge.rc contains English resources. All resource changes are done to this file. The translation system does not require anything special, the file is normal Windows resource file.
Some notes about editing Src/Merge.rc:
- You can't split strings over multiple lines:
IDS_TEST "This is a short string\nis wrong
with a line break"IDS_TEST "This is a short string\nwith a line break"is right- (Didn't Jochen already fix this?)
- You can use "
//#." comments to add extracted comments to the POT file:IDS_STATUSBAR_READONLY "RO" //#. Abbreviation from "Read Only"
- You can use "
//msgctxt" comments to add a context to the string in the POT file:POPUP "&Move" //msgctxt File/folder move- You need at least poEdit 1.3.8 to edit PO(T) files with
msgctxtstrings
[edit] The Format of PO Files
A PO file, which is a textual and editable file, is made up of many entries, each entry holding the relation between an original untranslated string and its corresponding translation. And all translations are expressed in a single target language. One PO file entry has the following schematic structure:
white-space # translator-comments #. extracted-comments #: reference... #, flag... msgctxt context msgid untranslated-string msgstr translated-string
For more details look at chapter 3 from the gettext manual.
[edit] Implementation of the Translation System
- Tim's first patch: #1771319 Generate language resource files from PO files created POT and PO files and scripts to create
.rcfiles from.potand.pofiles. - Jochen's patch: #1804762 UI translation without compiled lang files converted WinMerge to load translated strings from
.pofiles in runtime
Jochen explains it in the patch item:
Alongside with English.pot, CreateMasterPotFile.vbs creates MergeLang.rc, which contains Merge.rc line number references in place of texts. Compiling MergeLang.rc yields MergeLang.dll, which WinMerge loads in place of current lang files. Then, after loading resources from MergeLang.dll, WinMerge knows line number references, which lead it the way to translated strings in .po files.
All mentioned files are in Src/Languages/.
[edit] Merging PO Files
PO files from translators can be merged with WinMerge.
Do not merge line number changes! Line numbers must match to current version for system to work.
Line number changes are easy to ignore by using line filter like this:
^#
[edit] Todo
- Update and improve documentation!
-
Remove files from the old translation system (including resource compiler, MakeResDll). - Create a translation page like TortoiseSVN it has?
-
Add syntax highlighting for PO and POT files

