A macro driven internationalization/localization toolkit for Haxe

197 views
Skip to first unread message

Rocks Wang

unread,
Jun 19, 2013, 10:45:30 AM6/19/13
to haxe...@googlegroups.com
On Github: https://github.com/rockswang/i18n

Currently only works in Haxe 2.10. Haxe 3 support is planned.

===========================================

Localization quick tour

  1. Call macro method I18n.init() at the entry point of your code.
  2. Enclose all string literals to be externalized with macro method I18n.str().
  3. Build your project, strings will be extracted to "i18n_work/default/strings.xml", under your project root directory.
  4. Then you can do translating based on strings.xml and store the translations into "i18n_work/<locale>/" folders.
  5. Specify the target locale with macro compiler option I18n.locale(), e.g.: "--macro com.roxstudio.i18n.I18n.locale('zh')".
  6. Rebuild the project, this time I18n will look up the corresponding translation and replace the original string literals with the translated version.

Internationalization quick tour:

Almost the same procedure with localization, except in step 5, simply use 'global' for the locale argument. This will build a multilingual application.

Macro compiler options

I18n.locale(loc: String): set target locale, 'default', 'global' & arbitary custom locales e.g. 'zh', 'fr', can be used.

I18n.assets(path: String): set the output assets folder, by default it's "assets/i18n". The folder is for storing all locale sensitive resource files.

To set compiler options in NME project, simply add two lines in NMML file, e.g.:

    <compilerflag name="--macro com.roxstudio.i18n.I18n.locale('zh')" />
    <compilerflag name="--macro com.roxstudio.i18n.I18n.assets('res/i18n')" />

The underneath code substitution

Assume I have original "i18n_work/default/strings.xml" like this:

<strings>
  <file path="Main.hx">
    <t id="Hello">Hello</t><!--line 12-->
  </file>
</strings>

And the Chinese translation is ready at "i18n_work/zh/strings.xml", like this:

<strings>
  <file path="Main.hx">
    <t id="Hello">你好</t>
  </file>
</strings>

When I target 'zh' locale and build the project, the original haxe code in Main.hx:

textfield.text = I18n.str("Hello");

will be transformed to (at compile-time):

textfield.text = "你好";

When I target 'global' locale and build the project, the code will be transformed to:

textfield.text = I18n._str(0);

I18n._str() is a run-time method for accessing the string mapping.

The multilingual application

While using 'global' locale, your app will gain the capability of launch-time locale switching. E.g.:

    I18n.init();
    I18n.currentLocale = nme.system.Capabilities.language;

If the desired locale is not supported, then it will fallback to 'default'.

Next step

  • Add Haxe 3 support
  • Sample projects, including a StablexUI sample
  • Support run-time locale-switching

TopHattedCoder

unread,
Jun 19, 2013, 11:35:50 AM6/19/13
to haxe...@googlegroups.com
Nice! I'm sure this will be useful in lots of Haxe applications, games and the like.

Tarwin Stroh-Spijer

unread,
Jun 19, 2013, 2:17:19 PM6/19/13
to haxe...@googlegroups.com
Looks very interesting. Great to see interest in haxe all over the map.



Tarwin Stroh-Spijer
_______________________

Touch My Pixel
http://www.touchmypixel.com/
cell: +1 650 842 0920
_______________________


--
To post to this group haxe...@googlegroups.com
http://groups.google.com/group/haxelang?hl=en
---
You received this message because you are subscribed to the Google Groups "Haxe" group.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Marcelo de Moraes Serpa

unread,
Jun 19, 2013, 2:24:00 PM6/19/13
to haxe...@googlegroups.com
Nice!


--
Marcelo de Moraes Serpa
Sent with Sparrow (http://www.sparrowmailapp.com/?sig)


On Wednesday, June 19, 2013 at 1:17 PM, Tarwin Stroh-Spijer wrote:

> Looks very interesting. Great to see interest in haxe all over the map.
>
>
>
> Tarwin Stroh-Spijer
> _______________________
>
> Touch My Pixel
> http://www.touchmypixel.com/
> cell: +1 650 842 0920
> _______________________
>
> > To post to this group haxe...@googlegroups.com (mailto:haxe...@googlegroups.com)
> > http://groups.google.com/group/haxelang?hl=en
> > ---
> > You received this message because you are subscribed to the Google Groups "Haxe" group.
> > For more options, visit https://groups.google.com/groups/opt_out.
> >
> >
>
>
> --
> To post to this group haxe...@googlegroups.com (mailto:haxe...@googlegroups.com)

Francois Nicaise

unread,
Jun 19, 2013, 2:46:46 PM6/19/13
to haxe...@googlegroups.com
Cool!

Thinkslow 
Cross- platform gaming experiments 
--
To post to this group haxe...@googlegroups.com

Cristian Baluta

unread,
Jun 19, 2013, 4:43:30 PM6/19/13
to haxe...@googlegroups.com
Are there any advantages over using the Proxy method or is just for the sake of using macros?
--
Băluță Cristian
http://ralcr.com
http://imagin.ro

Jason O'Neil

unread,
Jun 19, 2013, 9:25:49 PM6/19/13
to haxe...@googlegroups.com
Very cool!  Really well thought out approach, I like having the option to have both compile-time translation and run-time translation.

It would be cool to have a 'using' shortcut:
using I18n;
...
textfield.text
= "Hello".i18n();
I'm on Haxe 3 already, but would love to try this on my next project whenever that is.  Let me know if you need help getting it Haxe 3 ready.

p.s. what licence do you plan to release this under?

Jason

Rocks Wang

unread,
Jun 20, 2013, 3:36:30 AM6/20/13
to haxe...@googlegroups.com
I've evaluated Proxy method before I start I18n, it's good solution but does not 100% cover my requirements. Here's some comparisons: 
1. With Proxy, you have to externalize string literals to an XML file by hand, at the mean time assigning a valid Haxe identifiers for each literal, you cannot use the original strings themselves as the id since they are not valid Haxe identifier. With the help of I18n tool, simply enclose every strings to be externalized with I18n.str(), then they'll be extracted and ordered to an external xml aumatically, use the original literals as the key.
2. Proxy provides compile-time id check, but no compile-time optimization. While with I18n, in localization mode, the translated strings are injected to the source at compile-time as constant, that means no performance cost at all; in i18n mode, the String->String mapping is converted to Int->String mapping at compile-time, so at the runtime the app supports multi-languages with very low cost.
3. I18n also provides the management of locale-sensitive resource files.
4. I18n support out-of-box launch-time locale switching facility.

在 2013年6月20日星期四UTC+8上午4时43分30秒,Cristian Baluta写道:

Rocks Wang

unread,
Jun 20, 2013, 3:53:57 AM6/20/13
to haxe...@googlegroups.com
Hi, add a "using" shortcut is a good idea! I just updated the readme and added the license part, thanks for the comments!

在 2013年6月20日星期四UTC+8上午9时25分49秒,Jason O'Neil写道:

Rocks Wang

unread,
Jun 24, 2013, 5:03:21 AM6/24/13
to haxe...@googlegroups.com
Hi folks,
1. I18n now works with Haxe3;
2. I18n.str() has been changed to I18n.i18n() so you can write "Hello".i18n() as Jason suggested.
3. Now provides a run-time locale-switching approach, the usage is still very simple. Examples:
  i. textfield.text = "Hello"; ==> I18n.onChange(textfield.text = "Hello".i18n());
  ii. StablexUI xml:  <Bmp src="'logo.png'" /> ==> <Bmp src="'logo.png'" on-create="I18n.onChange({ $this.src = 'logo.png'.i18nRes(); $this.refresh(); });" />

在 2013年6月19日星期三UTC+8下午10时45分30秒,Rocks Wang写道:

Jason O'Neil

unread,
Jun 24, 2013, 11:32:58 AM6/24/13
to haxe...@googlegroups.com
Again, fantastic work.  I really like your API design.  And well done on getting the Haxe 3 release working!


--
Reply all
Reply to author
Forward
0 new messages