C++ and translations

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

C++ and translations

Geert Janssens-4
Hi,

While dabbling in the c++ conversion work of gnucash it occurred to me most of
our translatable strings are gettext wrapped char*'s.

However the native string format for c++ is std::string. And that got me
wondering...

So here's a few questions that came up in this regard:

1. is there a c++ way to handle translations ? As far as I'm aware gettext
can't handle std::string objects directly, so we have to pass it the ->c_str()
function result. This is not always very nice.

2. c++ makes it very easy to compose strings by either summing them (strA +
strB) or streaming them (strA << strB).
This is much easier than c's string formatting using %s, %d and related format
macros. However
gettext ("In sentence %d, we need number %i")
gives a full sentence in our po file whereas
gettext ("In sentence ") + varA + gettext (", we need number ") + varB
results in two separate and essentially untranslatable strings instead.
What's the c++ answer to this ?

3. Our current c code includes <glib/gi18n.h> to get a couple of useful
shorthand macros to the most common gettext functions (N_, _, C_, Q_). However
that file is from glib, which we're trying to eliminate. I found some c++
files include <libintl.h> instead, which brings in gettext, but not the
convenience macros. I'm not a fan of redefining the same macros over and over
again. Should be instead create a gnc equivalent of the glib/gi18n.h but that
omits the glib.h inclusion and reference that file in all c++ files needing
translation support ? Perhaps not needed of course if there's a better c++
alternative.

4. When we throw exceptions, we pass a message explaining the reason the
exception was thrown. I have been leveraging these messages to inform the
users directly of why a certain action failed. That of course requires the
exception messages are translatable. I note none of the exception reasons in
the qof/engine c++ work is marked as such. So I'd like to have some discussion
on this. Relative merits/drawbacks of either concept. Things like that.
Personally I think it's nice if internal error messages can be reused towards
user feedback. But perhaps that's not always a good idea ?

Geert
_______________________________________________
gnucash-devel mailing list
[hidden email]
https://lists.gnucash.org/mailman/listinfo/gnucash-devel
Reply | Threaded
Open this post in threaded view
|

Fwd: C++ and translations

David Raker
This should have gone to the list.

On Apr 22, 2017 13:28, "David Raker" <[hidden email]> wrote:

Not sure if you've looked at it, but I think Boost.Locale might be what you
are looking for.  It uses gettext as so:

cout << translate("Hello World") << endl;

I haven't actually used it,  but the documentation is here:

http://www.boost.org/doc/libs/1_61_0/libs/locale/doc/html/me
ssages_formatting.html

On Apr 22, 2017 12:43, "Geert Janssens" <[hidden email]> wrote:

> Hi,
>
> While dabbling in the c++ conversion work of gnucash it occurred to me
> most of
> our translatable strings are gettext wrapped char*'s.
>
> However the native string format for c++ is std::string. And that got me
> wondering...
>
> So here's a few questions that came up in this regard:
>
> 1. is there a c++ way to handle translations ? As far as I'm aware gettext
> can't handle std::string objects directly, so we have to pass it the
> ->c_str()
> function result. This is not always very nice.
>
> 2. c++ makes it very easy to compose strings by either summing them (strA +
> strB) or streaming them (strA << strB).
> This is much easier than c's string formatting using %s, %d and related
> format
> macros. However
> gettext ("In sentence %d, we need number %i")
> gives a full sentence in our po file whereas
> gettext ("In sentence ") + varA + gettext (", we need number ") + varB
> results in two separate and essentially untranslatable strings instead.
> What's the c++ answer to this ?
>
> 3. Our current c code includes <glib/gi18n.h> to get a couple of useful
> shorthand macros to the most common gettext functions (N_, _, C_, Q_).
> However
> that file is from glib, which we're trying to eliminate. I found some c++
> files include <libintl.h> instead, which brings in gettext, but not the
> convenience macros. I'm not a fan of redefining the same macros over and
> over
> again. Should be instead create a gnc equivalent of the glib/gi18n.h but
> that
> omits the glib.h inclusion and reference that file in all c++ files needing
> translation support ? Perhaps not needed of course if there's a better c++
> alternative.
>
> 4. When we throw exceptions, we pass a message explaining the reason the
> exception was thrown. I have been leveraging these messages to inform the
> users directly of why a certain action failed. That of course requires the
> exception messages are translatable. I note none of the exception reasons
> in
> the qof/engine c++ work is marked as such. So I'd like to have some
> discussion
> on this. Relative merits/drawbacks of either concept. Things like that.
> Personally I think it's nice if internal error messages can be reused
> towards
> user feedback. But perhaps that's not always a good idea ?
>
> Geert
> _______________________________________________
> gnucash-devel mailing list
> [hidden email]
> https://lists.gnucash.org/mailman/listinfo/gnucash-devel
>
_______________________________________________
gnucash-devel mailing list
[hidden email]
https://lists.gnucash.org/mailman/listinfo/gnucash-devel
Reply | Threaded
Open this post in threaded view
|

Re: C++ and translations

Graham Menhennitt-3
In reply to this post by Geert Janssens-4
Hi Geert,

I have some experience in this area. I'm not fully up to date since I
haven't done it for a while.

Please see below.

Graham

On 23/04/2017 02:43, Geert Janssens wrote:
> 1. is there a c++ way to handle translations ? As far as I'm aware gettext
> can't handle std::string objects directly, so we have to pass it the ->c_str()
> function result. This is not always very nice.

Agreed - not nice. As David says, Boost.Locale is what you want. It
handles std::string and, more importantly, std::wstring. There are
others too.

> 2. c++ makes it very easy to compose strings by either summing them (strA +
> strB) or streaming them (strA << strB).

Don't do this! Some things we say in English are idiomatically
structured in a different way in other languages. As a very simple
example, in English we might say "There are %d items in this %s". In
another language, they would say "in this %s there are %d items". If you
concatenate strings, this doesn't work.

> 4. When we throw exceptions, we pass a message explaining the reason the
> exception was thrown. I have been leveraging these messages to inform the

I wouldn't worry about translating exception messages. Firstly, users
should never see them. Secondly, even if they do see them, it's usually
easy enough to get their meaning - most people (especially ones likely
to be using GnuCash) have at least a rudimentary understanding of
English. Lastly, it makes reporting of bugs more difficult. If a German
user reports that they've seen error "XXX", it won't match any reports
of English users seeing "YYY" even though it's the same error.

Another consideration is the set of tools to allow translations by third
parties. As a developer, you want to be able to ship a set of
translatable strings to a native speaker who isn't familiar with
software development or GnuCash. They have to translate using some tool
and ship the translated strings back to you. There are third party (some
non-free) tools to do this but I can't give any recommendations there.
_______________________________________________
gnucash-devel mailing list
[hidden email]
https://lists.gnucash.org/mailman/listinfo/gnucash-devel
Reply | Threaded
Open this post in threaded view
|

Re: Fwd: C++ and translations

Geert Janssens-4
In reply to this post by David Raker
On Apr 22, 2017 13:28, "David Raker" <[hidden email]> wrote:
>
> Not sure if you've looked at it, but I think Boost.Locale might be what you
> are looking for.  It uses gettext as so:
>
> cout << translate("Hello World") << endl;
>
> I haven't actually used it,  but the documentation is here:
>
> http://www.boost.org/doc/libs/1_61_0/libs/locale/doc/html/
messages_formatting.html

That's a great pointer, thanks!

Geert
_______________________________________________
gnucash-devel mailing list
[hidden email]
https://lists.gnucash.org/mailman/listinfo/gnucash-devel
Reply | Threaded
Open this post in threaded view
|

Re: C++ and translations

Geert Janssens-4
In reply to this post by Graham Menhennitt-3
Hi Graham,

Thanks for your feedback. It's most welcome.

On zondag 23 april 2017 01:32:33 CEST Graham Menhennitt wrote:
> > 2. c++ makes it very easy to compose strings by either summing them (strA
> > +
> > strB) or streaming them (strA << strB).
>
> Don't do this! Some things we say in English are idiomatically
> structured in a different way in other languages. As a very simple
> example, in English we might say "There are %d items in this %s". In
> another language, they would say "in this %s there are %d items". If you
> concatenate strings, this doesn't work.

Obviously. I'm well aware of this and was mostly trying to express that what I
had imagined so far wasn't satisfactory. Boost::Locale is clearly the better
answer.

>
> > 4. When we throw exceptions, we pass a message explaining the reason the
> > exception was thrown. I have been leveraging these messages to inform the
>
> I wouldn't worry about translating exception messages. Firstly, users
> should never see them. Secondly, even if they do see them, it's usually
> easy enough to get their meaning - most people (especially ones likely
> to be using GnuCash) have at least a rudimentary understanding of
> English. Lastly, it makes reporting of bugs more difficult. If a German
> user reports that they've seen error "XXX", it won't match any reports
> of English users seeing "YYY" even though it's the same error.
>
Hmm. I'm in two minds about this.

If the German user reports a (low level) exception message in German, we can
look it up in our message catalog as well. This is no different from them
reporting the contents of a high level (user oriented) message right now in
German.

On the other hand I wasn't considering low level error messages, that at best
would go into our log file. We're also leveraging exceptions at a much higher
level in our code. When such an exception is thrown the direct result is
informing the user via a dialog window. It only seems convenient  to use the
exception message straight away there because the point where it's thrown has
more detailed context and state than the catch block may have, depending on
how close it is to the throw in the call chain.

> Another consideration is the set of tools to allow translations by third
> parties. As a developer, you want to be able to ship a set of
> translatable strings to a native speaker who isn't familiar with
> software development or GnuCash. They have to translate using some tool
> and ship the translated strings back to you. There are third party (some
> non-free) tools to do this but I can't give any recommendations there.

True. This issue is not c++ specific though. Our current c/guile code mix is
in the same situation. What we have now is not optimal but won't be better or
worse either for our c++ translations. That is, our message catalog is
published on the gnu translation project from where translators can download
and translate it. Updates can be posted in our bugzilla database. We have a
complete wiki page with guidelines and suggestions on this topic:
http://wiki.gnucash.org/wiki/Translation

As said this is not optimal but more or less works. One day I'd love to have a
discussion on how this could be brought into the modern age. Unfortunately I
have currently too many other things to finish to initiate/moderate such a
discussion at this point. :( If others want to pick this up that would be
great.

Geert
_______________________________________________
gnucash-devel mailing list
[hidden email]
https://lists.gnucash.org/mailman/listinfo/gnucash-devel