The Lang framework is one of possible ways to achieve i18n aware UIs - UIs that can be rendered in multiple human languages. It provides following features:
UI of the application is presented as one or set of HTML files. These files are the same for all supported languages.
Each supported language gets so called translation map file (TMF).
Each TMF file is a tiscript file that defines mapping of translatable item ID to its textual representation in given human language.
TMF is an ordinary script file that gets eval() 'ed upon loading.
Result of TMF file shall be an object - map of "translatable ID" to either another string (st) or a function that provides translated/composed string (e.g. pluralized text of some value).
Example of simple translation map file for English language:
({ "Matchboxes":"Match boxes", // static text entry "There are # matches in the box" : // simple pluralization entry function(n) { return n == 0 ? "The matchbox is empty" : n == 1 ? "There is just one match in the box" : String.printf("There are %d matches in the box",n); }, ... })
As you see the value of such map file is a simple map containing items to be translated for the given language.
To attach the Lang framework you just need to include lang.css from sciter-sdk/+lang/ folder in your styles. For example as this:
<style> @import url(../lang.css); </style>
the Lang assumes that translation map files are included as special <link> elements in the head of html document:
<html lang="en"> <head> <!-- these two links define two translation files for en and ru languages. --> <link href="lang/ru.tis" hreflang="ru" rel="translation" > <link href="lang/en.tis" hreflang="en" rel="translation" > ...
At load time the Lang will pickup one of TMFs that matches <html lang="..."> attribute. So the UI will be presented in defult language defined by lang attribute on <html> element.
Portions of (static) text that needs to be translated in your UI can be marked using one of these ways:
<dfn>
elements, example: <dfn>Text to be translated</dfn>
"Text to be translated" : "Translated text"
<dfn>
element;<label>
elements. <label> elements are treated exactly as <dfn> elements by the Lang;dfn
class to any other elements containing text only, for example <li class="dfn">Text to be translated</li>
;ul#options > li { aspect:"Lang.Label"; }
There are cases when text needs to be formatted or composed for correct representation. For example consider pluralization task: "1 cactus" but "2 cactii", "1 match" but "2 matches", etc. Pluralization rules are very language specific and in general cannot be generailzed well. So instead of trying to cover all cases for any language in current use by generic routines the Lang propose to deal with pluralization on case by case basis.
Portions of text that are subject of language specific formatting can be marked in your markup in one of these ways:
<var>
elements, example: <var>There are # matches in the box</var>
. <var>
element is getting value
property redefined by the Lang. So in code if you assign some numeric value to such <var>
element the Lang will call corresponding formatting function defined in the map. For an example see translation map file sample above.<li class="var">There are # matches in the box</li>
;ul#options > li { aspect:"Lang.Formatter"; }
Lang.x()
function.Lang namespace defines Lang.x(text[,value])
function that can be used in code to explicitly translate the text. That function uses the same translation table and rules as <dfn>
s and <var>
s. If text maps to function defined in translation file and value is provided then that function gets called for the translation.
I'd suggest to use following sequence of actions:
({ })
and save it as, say, /lang/en.tis file. For now it contains empty translation table.
Let's assume that it will be English for now. Here is how your markup with Lang attached may look like:
<html lang="en"> <head> <link href="lang/en.tis" hreflang="en" rel="translation" > <style> @import url(../lang.css); /* enabling the Lang */ </style> <script type="text/tiscript"> include "../lang.tis"; // the Lang itself. include "../lang-tool.tis"; // the Lang tool - translation map generator. </script> </head> <body> <label>MATCHES</label> <var id="nmatches">MATCHES-PLURALIZED</var></p> </body> </html>
Note include "../lang-tool.tis";
statement above . It includes special translate map generator tool.
After loading the UI press CTRL+SHIFT+F11 inside your application. It will invoke translation map generator that will place its report into the clipboard.
Paste clipboard content into some file. With empty translation map and on markup above you should get content like this:
// items not found: { "MATCHES-PLURALIZED":"function (v){ return \"?\" }", "MATCHES":"?" } // OK, no unused items
First section will give you full list of items that need to be translated and appear in your final translation map:
({ "MATCHES-PLURALIZED": function (v){ return ... }, "MATCHES": "Matches" })
You can repeat this procedure time to time in app development life cycle - some items will be added, some removed (you will see them in second section). Review these items before moving all this to QA/testing.
Then ready to production just comment out that map generation tool invocation: // include "../lang-tool.tis";
so it will not take space and keyboard shortcut handler.
Done.