How to do localization in Google Closure

元气小坏坏 提交于 2021-02-07 20:25:56

问题


Currently I am using just plain text in my Closure application. I want to add localizations to those text. I just found several articles about goog.getMsg function which is used to do this kind of localization. As far as I understood it is done in compile time. How can we change language in run-time when user clicks a button? What is the easiest way to do this using Closure?


回答1:


I have actually achieved a runtime i18n. I use .soy templates with {msg} tags in them. When you compile .soy to .js, these calls get compiled to goog.getMsg calls. What I had to do was:

  1. Find all .js files that had goog.getMsg( in them
  2. Prepend goog.require("myApp.i18n");\n
  3. Replace all goog.getMsg( calls with myApp.i18n.translate(
  4. Replace all MSG_* property names with myprefix_MSG_*

Why all this: One cannot override goog.getMsg directly, because it is considered a compiler primitive and does not allow any manipulation whatsoever. Same applies for MSG_* properties.

myApp.i18n.translate is a function that accepts string, tries to look it up in a locale map (which is passed in runtime) and returns goog.getMsg result using the localized string (goog.getMsg does some handy placeholder replacements).

While this is not a very pretty solution, it works and allows me to change language in runtime, using only one compiled file for all languages.

The actual code includes a few hacks that allows me to use the generated description and use JSON files instead of the strange-looking closure file format, but the gist is the same.

However!

What you really should do is to compile several files from your app and load different .js file for every language.

I had to use this solution, because I need to support hundreds of different configurations and several languages: it would be insane to compile thousands of .js files, when one compilation takes 30+ seconds.




回答2:


Although this is not a single click language switch solution, I find it very comfortable as it allows to use same source of localized texts for both Soy templates and goog.getMsg() in JS code. It is sort of undocumented way of using Googles own XML format of translations called XTB.

You will end up with different compiled .js file for each language, so to switch locale you have to reload different JS file.

Apart from standard Closure tools there is 3rd party tool called XtbGenerator, which can be found here: https://github.com/kuzmisin/xtbgenerator.


Now the workflow:

  1. Compile your templates using SoyToJsSrcCompiler.jar with --shouldGenerateGoogMsgDefs --bidiGlobalDir 1 options. No locale yet.

  2. Create dependecies file using calcdeps.py

  3. Run closurebuilder.py with --compiler_jar set to XtbGenerator.jar file and with --compiler_flags="--xtb_output_file=origin.xtb" parameter.

    This will create a file called origin.xtb, which you can then use as a base for your translations. It will contain all texts both from Soy templates (in {msg} blocks) and your JS files (where var MSG_TEST = goog.getMsg('Text'); is used).

  4. Copy origin.xtb to for example translated.cs_CZ.xtb, change the lang attribute in the file and translate all the texts there.

  5. Compile the app for given locale the standard way using closurebuilder.py and compiler.jar. Use parameters:

    --compiler_flags="--translations_file=translated.cs_CZ.xtb"

    --compiler_flags="--define=goog.LOCALE='cs_CZ'"

    This will create you compiled version for single locale.

Nice examples of all these steps are here: http://www.closurecheatsheet.com/skeleton

It is unfortunate that there is almost no official documentation for this.


XTB format:

The format is following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE translationbundle>
<translationbundle lang="cs">
    <translation id="4127240967364168948" key="MSG_6LRZ706911HM" source="..\test.soy.js" desc="description">test</translation>
</translationbundle>

id and for soy templates also key attribute is autogenerated by compiler/extractor

This is most probably some Google internal format with tools for this not yet open-sourced.


Note about XtbGenerator:

It internally uses the Closure Compiler code to go through your JS codes and extract the messages. The dowloadable version however is built with older version of Closure Compiler, so it was throwing some errors for me.

I did a quick and dirty hack by copying goog directories from current version of compiler.jar to XtbGenerator.jar.



来源:https://stackoverflow.com/questions/18645568/how-to-do-localization-in-google-closure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!