The Right Approach to Exceptions

Jose Armando Garcia jsancio at
Mon Feb 20 16:41:28 PST 2012

On Mon, Feb 20, 2012 at 9:33 PM, Nick Sabalausky <a at a.a> wrote:
> "Jose Armando Garcia" <jsancio at> wrote in message
> news:mailman.672.1329758926.20196.digitalmars-d at
> >
> > This may not be D. Gettext says to solve it as follow:
> >
> > throw new Exception(gettext("Cool English message at
> > %s.").format(
> >
> > 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
> system, really.

I used to work a large engineering firm that used a different system
but had similar problems to the ones you mentioned below. Instead of
using a human readable string they would use an assumed to be unique
key. My main problem with this is that the person reading the code has
no idea what the message is suppose to say. They would have to look it
up in this translation database. One of the cool things of the system
was that it used "run-time" reflection to look up the parameter.
"Run-time" reflection worked in our C++ environment because a lot of
the abstract classes (interfaces) were generated from an IDL.

Another interesting part of the system was that it can do recursive
translation but if my memory serves me correctly they they needed it
because of other limitations in the system.

I think the basic problem with both system is that the set of keys in
the translation table is decouple from the code. This "gettext
compiler" is a way of making this connection.

> 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
> unused translations).
> 2. Changing the english text embedded in the code will automatically break
> all translations.
> 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.

These are some really good observations and suggestion. Lets move the
conversation to I18N module thread.

> 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:
> xlate!"Hello world"
> 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 mailing list