The Right Approach to Exceptions
a at a.a
Mon Feb 20 15:33:08 PST 2012
"Jose Armando Garcia" <jsancio at gmail.com> wrote in message
news:mailman.672.1329758926.20196.digitalmars-d at puremagic.com...
> This may not be D. Gettext says to solve it as follow:
> throw new Exception(gettext("Cool English message at
> The gettext "compiler" goes through the code an generates all the strings
> that need to be localized. The translation teams modifies those string and
> you store them in file/map for that language. At runtime the i18n library
> turns gettext(...) into a query into that map and returns the actual
> localized string. There is a map for the entire process.
> Localization can also be disable at compile time by making gettext a
> template and generating a "noop" for that operation.
> I have been thinking of making a module for i18n model after gettext but
> taking advantage of D's language features. Is there some interest in this?
I have some comments on that, but first a little story:
At a previous job with a company that shall remain unnamed, our flagship
product was this VB6 thing that handled i18n by wrapping all strings
intended to be seen by the user like this:
XLate("Hello, all ") + (UBound(customerArr)-LBound(customerArr)) + XLate("
of you suckers!")
For non-english users, that XLate function would then lookup the right
localization for the given message. IIRC, any missing translation just
returned the original english text.
This was the first time I had actually dealt with i18n, and yet I was pretty
certain that was a completely moronic approach (not that it was a stretch to
believe: there wasn't much going on at main sequence techn...errmm...I mean
at unnamed company, that wasn't completely moronic).
I always felt it would be far better ("better" == "won't screw up everytime
someone sneezes near the code" and "doesn't make certain things impossible
to translate correctly") to have a statically-checked *identifier* that
represented a particular message (and not message fragments, either). And
then the user-facing string would be looked up via identifier and any
appropriate values substituted in. A fairly obvious way to improve^Wfix the
Ok, end of story.
Your mention of gettext, and specifically a "gettext 'compiler'", does
introduce a way that the same basic idea could be made to actually work:
Obviously, the big problems with XLate above are:
1. No way to make sure all messages actually *are* translated (or to prune
2. Changing the english text embedded in the code will automatically break
3. It fails to handle cases where two inserted values need to be rearranged.
4. If two messages happen to have a common message fragments, the fragments
will always be translated the same even if their differing context dictates
they be translated differently
The issues #3 and #4 can obviously be solved by using only full messages
with named placeholders and passing the substitution data into xlate(). So
those issues are alredy out of the way.
By "gettext 'compiler'" I assume you're taking about some preprocessor.
Probably appropriate for C/C++, but seems kinda sloppy, potentially error
prone, and inefficient. Fortunately, D has kick-ass metaprogramming, so if
you require all translations be compiled in (not sure how realistic that is
in general), you could do:
And then generate a compile-time error (or a mere notice) for all messages
that are unhandled. Of course, if you're loading localizations at runtime,
you could still do something similar and just throw a runtime error, or log
a warning, etc., that lists all unhandled messages upon loading a
localization. Or, hell, a hybrid approach: Compile-time errors for built-in
localizations and runtime for the rest. Or generate a list of all messages
when compiled with a special version(), which is then handed off to the
translation team. All sorts of possibilities. That's all sufficient to solve
#1 and #2.
Although there is still the other problem Andrei mentioned of over-eagerness
(not an issue in the compile-time case, though).
More information about the Digitalmars-d