Edgewall Software

Changes between Version 21 and Version 22 of CookBook/PluginL10N


Ignore:
Timestamp:
Jun 13, 2010, 8:55:39 PM (14 years ago)
Author:
Christian Boos
Comment:

#Javascript brand new section on adding i18n support to Javascript code

Legend:

Unmodified
Added
Removed
Modified
  • CookBook/PluginL10N

    v21 v22  
    8181==== Preset configuration for i18n/l10n helper programs ====
    8282Add some lines to `setup.cfg` or, if it doesn't exist by now, create it with the following content:
    83 {{{
     83{{{#!ini
    8484[extract_messages]
    8585add_comments = TRANSLATOR:
     
    118118
    119119==== Mark text for extraction ====
    120 In python scripts you'll have to wrap text with the translation function `_()` to get it handled by translation helper programs. Some code, that was
    121 {{{
    122     msg = 'This is a msg text.'
    123 }}}
    124 before, will read like
    125 {{{
    126     msg = _("This is a msg text.")
    127 }}}
    128 afterwards.
     120In python scripts you'll have to wrap text with the translation function `_()` to get it handled by translation helper programs.
     121{{{#!diff
     122--- a/<path>/api.py
     123+++ b/<path>/api.py
     124@@ -1,1 +1,1 @@
     125-    msg = 'This is a msg text.'
     126+    msg = _("This is a msg text.")
     127}}}
    129128
    130129Note, that quoting of (i18n) message texts should really be done in double quotes. Single quotes are reserved for string constants (see commit note for r9751).
     
    186185}}}
    187186
    188 ==== Text extraction from Javascript code ====
    189 
    190 
     187==== Text extraction from Javascript code ==== #Javascript
     188
     189Adding support for translating the marked strings in the Javascript code is a bit more involved, but if you made it to this point, that shouldn't scare you away...
     190
     191We currently support only statically deployed Javascript files, which means they can't be translated like template files on the server, but that the translation has to happen dynamically on the client side. To this end, we want to send an additional `.js` file containing a dictionary of the messages that have to be translated, and only those. In order to clearly identify which strings have to be present in this dictionary, we'll extract the messages marked for translation (the usual `_(...)` ways) from the Javascript code into a dedicated catalog template, and from there, we'll create dedicated catalogs for each locale. In the end, the translations present in each compiled catalog will be extracted and placed into a `.js` file containing the messages dictionary and some setup code.
     192
     193The first change is to use `get_l10n_js_cmdclass` in lieu of `get_l10n_cmdclass`. The former adds a few more setup commands for extracting messages strings from Javascript `.js` files and `<script type="text/javascript">` snippets in `.html` files, initialization and updating of dedicated catalog files, and finally compiling that catalog and creating a `.js` file containing the dictionary of strings, ready to be used by the `babel.js` support code already present in Trac pages.
     194
     195The change to `setup.py` looks like this:
     196{{{#!diff
     197diff -u a/setup.py b/setup.py
     198--- a/setup.py
     199+++ b/setup.py
     200@@ -5,8 +5,8 @@ from setuptools import setup
     201 extra = {}
     202 
     203-from trac.util.dist import get_l10n_cmdclass
     204-cmdclass = get_l10n_cmdclass()
     205+from trac.util.dist import get_l10n_js_cmdclass
     206+cmdclass = get_l10n_js_cmdclass()
     207 if cmdclass:
     208     extra['cmdclass'] = cmdclass
     209     extra['message_extractors'] = {
     210}}}
     211
     212That was the easiest part.
     213
     214Now, as you need to actually send that `.js` file containing the messages dictionary, call `add_script()` as appropriate in the `process_request()` method from your module:
     215
     216{{{#!diff
     217--- a/<path>/api.py
     218+++ b/<path>/api.py
     219@@ -243,6 +243,8 @@ class FooTracPlugin(Component):
     220         builds = self._extract_builds(self._get_info(start, stop))
     221         data = {'builds': list(builds)}
     222         add_script(req, '<path>/hudsontrac.js')
     223+        if req.locale is not None:
     224+            add_script(req, '<path>/foo/%s.js' % req.locale)
     225         add_stylesheet(req, '<path>/foo.css')
     226         return 'foo-build.html', data, None
     227 
     228}}}
     229
     230Now, you need to expand the `setup.cfg` file with the configuration that the new `cmdclass` dedicated to Javascript translation need. Those classes all end with an `_js` suffix.
     231
     232{{{#!ini
     233[extract_messages_js]
     234add_comments = TRANSLATOR:
     235copyright_holder = <Your Name>
     236msgid_bugs_address = <Your E-Mail>
     237output_file = <path>/locale/messages-js.pot
     238keywords = _ ngettext:1,2 N_
     239mapping_file = messages-js.cfg
     240
     241[init_catalog_js]
     242domain = foo-js
     243input_file = <path>/locale/messages-js.pot
     244output_dir = <path>/locale
     245
     246[compile_catalog_js]
     247domain = foo-js
     248directory = <path>/locale
     249
     250[update_catalog_js]
     251domain = foo-js
     252input_file = <path>/locale/messages-js.pot
     253output_dir = <path>/locale
     254
     255[generate_messages_js]
     256domain = foo-js
     257input_dir = <path>/locale
     258output_dir = <path>/htdocs/foo
     259}}}
     260
     261As before, replace `<path>` with what's appropriate for your plugin. Note that the domain name is now `foo-js`, not just `foo` as before. This is necessary as we want to have only the strings actually needed Javascript to be stored in the `.js` file containing the messages dictionary.
     262
     263We're nearly done yet... noticed the `mapping_file = messages-js.cfg` line?
     264We need to configure separately how to do the extraction for this `messages-js.pot` catalog template.
     265The `messages-js.cfg` file has the following content:
     266{{{#!ini
     267# mapping file for extracting messages from javascript files into
     268# <path>/locale/messages-js.pot (see setup.cfg)
     269[javascript: **.js]
     270
     271[extractors]
     272javascript_script = trac.util.dist:extract_javascript_script
     273
     274[javascript_script: **.html]
     275}}}
     276
     277Bonus points for anyone who will manage to //simplify// a bit this procedure ;-)
    191278
    192279==== Register message catalog files for packaging ====