translations and option definitions

Christian Stimming stimming at
Sat Sep 3 17:34:51 EDT 2005

Am Samstag, 3. September 2005 21:13 schrieb Neil Williams:
> > Wait a second. When reading your original description again
> >
> > The names are chosen by your #defines, i.e. they are string constants in
> > the C file, and the types are chosen by the respective kvp_frame_set_xy
> > functions. In other words, the creation of your kvp_frame has to manually
> > duplicate the things that are written in the XML file. Did I understand
> > this correctly? That is, errr, probably not so good.
> This is leading to generating the XML from the C, somehow, maybe during the
> build. That's what I tried first with the perl and it isn't easy because
> the translations happen at runtime, not compile time. Generating the XML
> from the library can be done, of course, but to handle the translations as
> well involves perl modules that most users simply won't have installed.

Ok, now let's clear up this translation problem. Here's what I understood 
about these obnoxious :-) data-store-backend options: Eventually, the backend 
options should be passed as a kvp_frame. The collection of all options is a 
kvp_frame with all options as sub-kvp_frames. For each option, there is a 
name which is the path to that kvp_value. Each option has a type which is 
implicitly defined by the type of that kvp_value. (Note: You really need to 
do something about boolean options! Either add a "gboolean" kvp_value or 
decide on a fixed convention.) Each option has a human-readable string 
containing the description of it. And an option also has a human-readable 
tooltip string.

So let's say you get that kvp_frame with all options from somewhere:

  kvp_frame *my_options = from_somewhere(blabla);

The human-readable strings are english. Now let's translate them. If I already 
know that the string is located at "firstoption/description", then this is 
done by

  kvp_frame_set_string(my_options, "firstoption/description", 
    gettext(kvp_frame_get_string(my_options, "firstoption/description") ) );

and that's it. Conveniently the macro _() is defined as an alias for 
gettext(), so writing _(kvp_frame_get_string...) is just the same. It should 
be clear how to achieve this in a generic form by kvp_frame_for_each_slot() 
and so on. You really don't have to do anything else at runtime or in your 
source code. That is really all there is. gettext(3) will do all the magic it 
has to get the translations from the necessary po files.

The only other part that has to be ensured is that *at compile time* the 
original english strings need to be found by the xgettext program so that 
they will appear in po/gnucash.pot as a so-called "msgid". *If* a string is 
in a C source file *and* it is enclosed by _() then xgettext will 
automatically add that string as msgid. But if that is not the case we still 
have plenty of options on how to ensure those strings will appear as msgids 
in the gnucash.pot file. For example, all strings from scheme source files 
are treated as follows: In gnucash, the file intl-scm/xgettext.scm is a 
scheme script which will process *all* scheme source files. That scheme 
script will retrieve all strings marked as msgids, and it will write them 
into a file that *looks like* a C source file, although it really isn't one. 
That resulting file is intl-scm/guile-strings.c . Then, xgettext is run as 
usual, and it will pick up all strings from intl-scm/guile-strings.c so that 
these appear as msgids in po/gnucash.pot, just as intended.

Back to the option definition and translations. If the option definition is 
done inside a C source file, very well, then the msgids will simply be 
retrieved by xgettext from that C source file. However, if the options are 
defined by an XML file and some magic will create the kvp_frame at runtime, 
then we just need to add an additional step just like with the scheme source 
code. For example you could add a xslt stylesheet that reads your option 
definition XML file and will produce a file similar to 
intl-scm/guile-strings.c (say xml-strings.c), and then you can add a manual 
build rule to the for producing that file xml-strings.c . And 
everything is done. No need to worry about translations anymore. Could you 
follow so far?

There is only one open question: Which package should have these strings in 
its .pot file, i.e. in which pot file should the msgids eventually be 
located? That question is easily answered: If the string will be displayed in 
the Gnucash GUI, then it *has* to appear in gnucash's own pot file. Gnucash 
has so much more translators and translations than any other involved 
project. Any translations of strings in Gnucash simply *have* to be located 
in gnucash's own gnucash.pot. So if these option strings are to be displayed 
in a gnucash GUI dialog then they have to be translated by the gnucash pot 
file as well. However, this only means that the msgid somehow have to appear 
in the gnucash pot file -- this doesn't add any other restrictions on the 
placement of the actual gettext() call. (At least not any restrictions that 
can't easily be solved.)



More information about the gnucash-devel mailing list