RFC: Translating Wine's dialogs with PO files

Francois Gouget fgouget at free.fr
Mon Sep 12 12:28:04 CDT 2011


This is the next step in making full use of the PO files for translating 
Wine. But how to get there is unclear, hence this RFC.

The issue with dialogs is that in RC files all the dialog and control 
sizes are hardcoded. For instance in the line below '208, 6, 56, 14' 
represent the x-left, y-top, width and height of the button:

   DEFPUSHBUTTON "Save As", IDOK, 208, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP

The problem is that once translated to French, for instance, the label 
becomes 'Enregistrer sous' which is much longer and may require 
enlarging the button. But RC files do not contain the information needed 
to do that automatically. For instance they don't specify enlarging this 
button requires enlarging the 'Cancel' and 'Help' buttons below too.

So how do we solve this problem?


Option 1 - Automatically layout the dialogs at compile time
-----------------------------------------------------------

Gtk applications solve this problem by storing all the information 
needed to automatically layout dialogs in an XML file. The size and 
location of all the controls is then computed at runtime, after the 
dialog has been translated.

We could do something similar, it would go something like this:
 * Use some format that lets us store all the layout information as the 
   primary definition for Wine's dialogs.
 * At compile time translate the dialogs.
 * For each translation, layout the dialog and generate an RC file 
   containing the computed control coordinates and sizes.
 * Then compile the RC files as usual.
   (alternatively the last two steps could be merged)

Questions:
 * Which format should we use to define the layout?
   - Glade is the format used by Gtk. However it seems pretty Gtk 
     centric and the set of controls/properties it supports may not 
     match the Windows ones. It's possible to add libraries of custom 
     widgets so that may be a solution.
     http://en.wikipedia.org/wiki/Glade_Interface_Designer

   - It looks like Microsoft added support for auto-layout in WPF 
     (Windows Presentation Foundation) for .Net applications. This 
     information can be stored in XAML XML files.
     http://msdn.microsoft.com/en-us/library/ms750441.aspx
     https://github.com/yadyn/WPF-Task-Dialog/blob/master/TaskDialog/CommandLink.xaml

     Does anyone know how this works?
     Is it something we would need to implement in Wine anyway?
     Does some project already have support for it? Mono maybe?

   - For completeness I'll also mention that WxWidget also has a 
     cross-platform layout engine.
     http://docs.wxwidgets.org/2.9.2/overview_xrc.html

   However as far as I know, none of them has tools that can 
   generate RC files.

 * How can we do the layout?
   - Can we reuse a third-party layout engine? Like the one used for 
     Glade files?
   - Wouldn't that introduce troublesome build dependencies?
   - Would it be ok if these dependencies are needed only when in 
     maintainer mode?
     (In maintainer mode a change to a PO file could trigger an update 
     to the corresponding RC files which would then be committed with 
     the PO file change.)
   - Should we instead implement it all by ourselves?

 * How can we mesure the size that strings will take at run time?
   We probably have all the code we need in Wine. But can we use it are 
   compile time?
   Will the computed layout depend on the fonts that are installed on 
   the system where Wine is compiled? This is particularly important for 
   languages with non-latin characters such as Japanese, Hebrew or 
   Telugu.

Pros:
 * We would not have to manually layout dialogs ever again. Yay!

 * We might be able to reuse the graphical dialog design tools of 
   the system we adopt, like Glade or possibly some .Net tools.

 * There would be no risk of the translation and layout getting out of 
   sync.

 * We would no longer need one RC file per language, thus eliminating 
   the risk that they become out of sync (e.g. adding a given window 
   style to some but not all languages).

Cons:
 * Just integrating support for the layout engine and generating RC 
   files seems like a lot of work.

 * Potential for additional build-time third-party dependencies for the 
   layout engine.

 * Would require rewritting all our dialogs so they have all the needed 
   layout information. That is definitely a lot of work.



Option 2 - Add layout information to RC files
---------------------------------------------

The idea here is the same as for option 1 except that we would add the 
layout information as comments in the existing RC files. As a very 
rough exemple it could look something like this:

  #layout# start box(orientation = vertical, padding = 8)
  #layout#   start button(expand = true, fill = true)
  DEFPUSHBUTTON "Save As", IDOK, 208, 6, 56, 14, BS_DEFPUSHBUTTON | 
WS_GROUP | WS_TABSTOP
  #layout#   end button
  ...
  #layout# end box


Pros:
 * Same as for option 1.


Cons:
 * We would be inventing our own syntax.

 * Not as clean as option 1.

 * The comments would risk becoming out of sync with the dialogs (e.g. 
   if a developper adds a button but not the comment specifying how it 
   is to be layed out). wrc might be able to check that things are 
   consistent though.

 * It would be as much work as option 1.

 * We would have no chance of leveraging an existing layout engine.



Option 3 - Use per-language RC files to store hardcoded dialog layouts
----------------------------------------------------------------------

This solution would reuse the existing per-language RC files but would 
refresh their labels using the PO files. Here is how it would work:

 * Every control of a given dialog would need to have a unique id. This 
   should only be an issue for static labels which currently tend to all 
   have -1 as their id. So we would first have to reassign them 
   different ids like -1, -2, -3 or stc1, stc2, stc3, etc.

 * For each control that has a label in a language-specific RC file, 
   look for the corresponding '<dialog-id>+<control-id>' combination in 
   the English RC file. If no match is found that's an error.

 * Take corresponding English label and use the PO file to translate it.

 * Use the translated label instead of the, potentially outdated, one 
   that was in the language-specific RC file.

 * This could be done by wrc when generating a .res file. This way any 
   PO file change would immediately be reflected in the build.
   Alternatively this could be a maintainer-only task that updates 
   the language-specific RC files whenever a PO file patch is committed.
   We could even do both so the labels in the language-specific RC files 
   don't become too out of date.

 * If a given dialog is missing from a language-specific RC file, we 
   would do as if the English dialog data was present instead and
   proceed as described above.

Pros:
 * The current RC files would not need extensive modifications.

 * In fact we could progressively simplify them by removing all the 
   translated dialogs that don't change the layout.

 * This solution feels like it should be easier to put in place than an 
   automatic layout one.

Cons:
 * We would still need to manually layout or verify the layout of every 
   single dialog for every single language :-(

 * The translators would have no idea that there is a dialog whose 
   layout may need to be changed as a result of their changes to the PO 
   file. Developpers would similarly be hard pressed to make the 
   connection and would likely lack the motivation to update the dialog 
   layouts. So the dialog layouts would likely continue to be rarely 
   updated and possibly incorrect. Exactly like today.

 * For every dialog with a customized dialog the translations would be 
   stored both in the language-specific RC file and in the PO file. This 
   could be confusing.



Option 4 - Put the sizes in special PO files
--------------------------------------------

This would really be a very ugly hack.
Like option 2 it requires that every control of a given dialog have a 
unique id. Then for each of them we would create PO file entries of 
the form:

   msgctxt "<rc-filename>:<dialog-id>:<control-id>"
   msgid "<x>:<y>:<width>:<height>"
   msgstr ""

We then put all these 'messages' in a sizes-<lang>.po file. Whenever a 
control needs to be resized a 'translation' would be provided in the 
relevant sizes-<lang>.po file.

We would only keep the English RC file and when compiling the resources 
for a given language wrc would check whether the sizes-<lang>.po file 
contains a translation of the size data for the current control.

Pros:
 * Maybe the easiest solution to put in place.

Cons:
 * Totally ugly.

 * Probably awful to work with to change the layout of a dialog.

 * All the drawbacks of Option 2.


-- 
Francois Gouget <fgouget at free.fr>              http://fgouget.free.fr/
                     f u kn rd ts, ur wy 2 gky 4 ur wn gd.





More information about the wine-devel mailing list