[program_options] Translating messages to another language
Hi to all! I am writing some application that uses program_options. This application interacts with user using non-english language. Is there any way to translate "what" messages from exceptions to another language? At now I found only one way (rather hack :) ): static void store(const basic_parsed_options<char> &options, variables_map &variables) { try { program_options::store(options, variables); } catch(unknown_option &error) { const char *what = error.what(); static const char prefix[] = "unknown option "; if(!strncmp(what, prefix, sizeof(prefix) - 1)) throw logic_error("Неизвестная опция: " + string(what + sizeof(prefix) - 1)); throw logic_error("Неверный формат командной строки"); } } Another way is to redefine function invalid_command_line_syntax::error_message(), but in such case we can translate only some messages.
Pavel Syomin wrote:
Hi to all!
I am writing some application that uses program_options. This application interacts with user using non-english language. Is there any way to translate "what" messages from exceptions to another language? At now I found only one way (rather hack :) ):
No, sorry. The classic solution would be to wrap all english texts with "i18n", and then use gettext or similar to extract such strings, prepare translations and then use it. But, this requires changing Boost build process to actually run gettext. I suspect somebody will surely object, since gettext is not portable ;-) - Volodya
On Wed, Oct 24, 2007 at 11:12:28AM +0400, Vladimir Prus wrote:
Pavel Syomin wrote:
I am writing some application that uses program_options. This application interacts with user using non-english language. Is there any way to translate "what" messages from exceptions to another language? At now I found only one way (rather hack :) ):
No, sorry.
The classic solution would be to wrap all english texts with "i18n", and then use gettext or similar to extract such strings, prepare translations and then use it. But, this requires changing Boost build process to actually run gettext. I suspect somebody will surely object, since gettext is not portable ;-)
But a gettext approach uses nearly always macros such as _("") and N_(""). If Boost would at least mark all translatable texts using _() or N_() a user who wishs i18n support could define these macros (e.g. by including first a new boost/i18n.h file) and have messages translatable. Of course this would also require that xgettext scans not only users source code but also Boost's one but Boost could at least provide PO files containing translations so that users can merge these with own files. Since most Boost libraries are header only, it makes no sense to ship binary .mo files and the user has to care about Boost's message translation himself. At least it would be possible ... Jens
Jens Seidel wrote:
On Wed, Oct 24, 2007 at 11:12:28AM +0400, Vladimir Prus wrote:
Pavel Syomin wrote:
I am writing some application that uses program_options. This application interacts with user using non-english language. Is there any way to translate "what" messages from exceptions to another language? At now I found only one way (rather hack :) ):
No, sorry.
The classic solution would be to wrap all english texts with "i18n", and then use gettext or similar to extract such strings, prepare translations and then use it. But, this requires changing Boost build process to actually run gettext. I suspect somebody will surely object, since gettext is not portable ;-)
But a gettext approach uses nearly always macros such as _("") and N_(""). If Boost would at least mark all translatable texts using _() or N_() a user who wishs i18n support could define these macros (e.g. by including first a new boost/i18n.h file) and have messages translatable.
Of course this would also require that xgettext scans not only users source code but also Boost's one
Yes, that's the apparent problem.
but Boost could at least provide PO files containing translations so that users can merge these with own files.
That's what I have in mind. It's not particularly hard, either, since Boost.Build has support for gettext already. The question is whether the will be objections to using tool that is mostly only available on Linux. And, the model of _("") is somewhat specific to Linux, I think on windows one has to make integer ids.
Since most Boost libraries are header only, it makes no sense to ship binary .mo files and the user has to care about Boost's message translation himself.
Well, before .mo file you need to have translated .po. Clearly, translated .po would be of value. Actually, .mo might be of use, too, assuming _("") expands to dgettext("boost", ...) as opposed to gettext(...) which is a good idea anyway. Of course, the main application will be responsible for install .mo files and hooking them in. And given that, .mo is indeed little advantage over translated .po. - Volodya
Vladimir Prus wrote:
Since most Boost libraries are header only, it makes no sense to ship binary .mo files and the user has to care about Boost's message translation himself.
Well, before .mo file you need to have translated .po. Clearly, translated .po would be of value. Actually, .mo might be of use, too, assuming _("") expands to
dgettext("boost", ...)
as opposed to
gettext(...)
which is a good idea anyway. Of course, the main application will be responsible for install .mo files and hooking them in. And given that, .mo is indeed little advantage over translated .po.
In fact, scratch all the above -- it was written having "shrink-wrapped" applications grabbing all dependencies with them in mind. It's totally fine to have boost install boost.mo into /usr/share/locale/xxx/LC_MESSAGES. Assuming boost code uses: dgettext("boost", ...) to get translations, it will work transparently, without any work for application's developer. - Volodya
On Wed, Oct 24, 2007 at 01:31:46PM +0400, Vladimir Prus wrote:
Jens Seidel wrote:
On Wed, Oct 24, 2007 at 11:12:28AM +0400, Vladimir Prus wrote: But a gettext approach uses nearly always macros such as _("") and N_(""). If Boost would at least mark all translatable texts using _() or N_() a user who wishs i18n support could define these macros (e.g. by including first a new boost/i18n.h file) and have messages translatable.
but Boost could at least provide PO files containing translations so that users can merge these with own files.
That's what I have in mind. It's not particularly hard, either, since Boost.Build has support for gettext already. The question is whether the will be objections to using tool that is mostly only available on Linux. And, the model of _("") is somewhat
Only available on Linux? Probably you refer to the gettext system call in glibc but isn't/wasn't there also a external library of gettext. (I think a separate copy of gettext is part of many packages using autotools.)
specific to Linux, I think on windows one has to make integer ids.
Not if a const char* gettext(const char*) function is used there too (or are there license issues which make this not possible?).
Actually, .mo might be of use, too, assuming _("") expands to
dgettext("boost", ...)
as opposed to
gettext(...)
which is a good idea anyway. Of course, the main application will be responsible for install .mo files and hooking them in. And given that, .mo is indeed little advantage over translated .po.
I'm not sure whether an application can use multiple message catalogs ... PS: I could provide the German translation if wanted. Jens
Jens Seidel wrote:
On Wed, Oct 24, 2007 at 01:31:46PM +0400, Vladimir Prus wrote:
Jens Seidel wrote:
On Wed, Oct 24, 2007 at 11:12:28AM +0400, Vladimir Prus wrote: But a gettext approach uses nearly always macros such as _("") and N_(""). If Boost would at least mark all translatable texts using _() or N_() a user who wishs i18n support could define these macros (e.g. by including first a new boost/i18n.h file) and have messages translatable.
but Boost could at least provide PO files containing translations so that users can merge these with own files.
That's what I have in mind. It's not particularly hard, either, since Boost.Build has support for gettext already. The question is whether the will be objections to using tool that is mostly only available on Linux. And, the model of _("") is somewhat
Only available on Linux? Probably you refer to the gettext system call in glibc but isn't/wasn't there also a external library of gettext. (I think a separate copy of gettext is part of many packages using autotools.)
I mean "by default". On Linux, gettext is pretty much everywhere. On Windows, developers might be more accustomed to other mechanisms. Personally, I think that a solution using gettext is better than no solution.
specific to Linux, I think on windows one has to make integer ids.
Not if a const char* gettext(const char*) function is used there too (or are there license issues which make this not possible?).
Actually, .mo might be of use, too, assuming _("") expands to
dgettext("boost", ...)
as opposed to
gettext(...)
which is a good idea anyway. Of course, the main application will be responsible for install .mo files and hooking them in. And given that, .mo is indeed little advantage over translated .po.
I'm not sure whether an application can use multiple message catalogs ...
It surely can, when using dgettext to explicitly specify which domain to grab messages from.
PS: I could provide the German translation if wanted.
Okay, if we decide to try this, I'll ask you for German translation for program_options messages ;-) - Volodya
I think, that optional integration with gettext is very good idea. In spite of the fact that using gettext on windows can lead to additional movements with building boost on this platform.
participants (3)
-
Jens Seidel
-
Pavel Syomin
-
Vladimir Prus