[jsword-devel] I18N

Joe Walker jsword-devel@crosswire.org
Mon, 29 Dec 2003 23:06:16 +0000


Andy - this is well worth reading - JSword does something very similar 
in looking up strings.

The one difference is that where Sword uses "const char*" as the type to 
look up JSword has a "static final Msg" which lets us add type safety in 
some places.

So JSword code looks like this:

   throw new BlahException(Msg.WRITE_FAIL);

Note you can't throw unless you take note of I18N. This is not a system 
for sloppy programmers.
And in the local Msg class

   static final Msg WRITE_FAIL = new Msg("Failed to write");

And in the French resource file:

   Failed to read=N'ecrire pas

(or something)

Hope this helps.

Joe.

Troy A. Griffitts wrote:
> Hey guys.  I also had a tough time deciding how to handle i18n in the 
> windows frontend.  As well, we are building an i18n mechanism for our 
> website.  Here are some of my thoughts.
> 
>     I agree 100% that I hate keeping string files up to date.  I hate 
> looking at DEFINE_TOKENS instead of the actual string, and I hate going 
> somewhere to have to change the string other than right where I'm at in 
> the code.
> 
>     Here was my solution in the Windows client: Since Borland's VCL GUI 
> classes provide programmatic methods to change all the 'Caption' or 
> 'Text' properties of a control, we have 1 function called i12ize(const 
> char *lang), which is where all the stupid monolithic calls to EVERY 
> control exist to change it's text.  There are also classes in the SWORD 
> engine called SWLocale and LocaleMgr which manage locales and do simple 
> lookups from a basic .conf file formatted like:
> 
> My English Text=My Alternate Language Text
> 
> Here are excerpts from the code:
> 
> ____________________
> 
> #define _tr(text) LocaleMgr::systemLocaleMgr.translate(text)
> 
> void TForm1::i12ize(const char *lang) {
>      LocaleMgr::systemLocaleMgr.setDefaultLocaleName(lang);
> 
>      File1->Caption = _tr("&File");
>      SaveLayout1->Caption = _tr("S&ave Layout");
>      Print1->Caption = _tr("&Print...");
>      ...
> ____________________
> 
> translate() looks up the English phrase in the current locale.conf file, 
> and returns the translation, if it finds it; otherwise, it just returns 
> back the English phrase.
> 
> Benefits:
> 
> o You can code normally, without worrying about i18n.
> o Worst case is the English will show up on the control
> o And my favourite part: You can declare, "This is an open source 
> project!  If you want your language supported, then test it, look for 
> english strings, and update your lang.conf file!"
> 
> Those lines should probably be changed to:
> -     File1->Caption = _tr("&File");
> +     File1->Caption = _tr(File1->Caption);
> 
> And better yet a programmatic walk of the control tree, instead of 
> naming each control individually, would be IDEAL.
> 
> ____
> 
> For the web interface, we're working on a taglib that adds functionality 
> like:
> 
> <table>
> <tr><td><t>My text</t></td></tr>
> </table>
> 
> (Example above, set in a table to just show that it's not extremely 
> intrusive)
> 
> The <t> tag does a lookup and replace of the string in much the same way 
> as LocaleMgr.  It will also allow someone to log in as an admin, set a 
> session variable admin to true, then a link at the bottom of each page 
> will appear that says: Administrate I18n
> 
> While browsing the website, if an administrator sees an English word, 
> they may click this link, and be taken to a page where they are 
> presented with all the <t>English Text Strings</t> and the existing 
> translations, and are able to update any that are wrong or missing.
> 
> Benefits: It only has one evil tag addition, <t> around all text, and 
> still allows me to make the coveted Open Source Declaration mentioned 
> above.
> 
>     :)
> 
> Hope this, at least, gives some ideas to throw around from someone who's 
> struggling with the same issues.
> 
>     -Troy.
> 
> 
> 
> 
> Joe Walker wrote:
> 
>>
>> JSword used to use a method very similar to yours, and I found that 
>> the message file was constantly getting out of date with respect to 
>> the source.
>> There were 3 problems:
>> - editing properties files was a hassle
>> - unused messages would not be purged
>> - lazy developers (me!) would add an i18n key thinking "i'll add it to 
>> the message file later" and never do it.
>>
>> The Msg system solves these problems by making the I18N type-safe - 
>> Exceptions take a Msg and not a String and so on.
>>
>> You can now navigate to the message with a single key press in any 
>> decent IDE (in eclipse I just press F3)
>> You can detect if the message is used without lengthy search 
>> procedures with your IDE (ctrl+shift+g in eclipse)
>> The english developer can ignore message files completely because the 
>> messages are in the source
>> JSword can sill be internationalized simply by adding message files
>>
>> To clear up some of the points you made:
>> Does this scheme waste space?
>> We use extra static space for a few objects that wrap strings. Only 
>> one copy of MsgBase is needed, and the strings themselves (the things 
>> that take up the real space) would exist anyway.
>> So yes this does waste some space, but I think that is a reasonable 
>> price to pay.
>>
>> Joe.
>>
>>
>> _______________________________________________
>> jsword-devel mailing list
>> jsword-devel@crosswire.org
>> http://www.crosswire.org/mailman/listinfo/jsword-devel
> 
> 
> _______________________________________________
> jsword-devel mailing list
> jsword-devel@crosswire.org
> http://www.crosswire.org/mailman/listinfo/jsword-devel