zpt
Version:
Zenon Page Templates - JS (ZPT-JS)
292 lines (267 loc) • 16.3 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8">
<title>I18n</title>
<script type="module" src="../js/zpt.js"></script>
<script type="text/javascript" src="../lib/syntaxHighlighter/lib.js"></script>
<link rel="stylesheet" type="text/css" href="../docs.css">
<link rel="stylesheet" type="text/css" href="../lib/syntaxHighlighter/theme.css">
</head>
<body>
<div data-use-macro="'page@templates.html'">
<div data-fill-slot="'page-header'">
<h1>ZPT-JS tutorial - I18n</h1>
<ul>
<li><a href="#intro">Intro to i18n</a>.</li>
<li><a href="#examples">Some examples</a>.</li>
<li><a href="#domains">Working with domains</a>.</li>
<li><a href="#json">Loading messages from JSON files</a>.</li>
<li><a href="#numbers">Numbers</a>.</li>
<li><a href="#currencies">Currencies</a>.</li>
<li><a href="#datesAndTimes">Dates and times</a>.</li>
</ul>
</div>
<article data-fill-slot="'article'">
<h2 data-attributes="id 'intro'">Intro to i18n</h2>
<p>
Nowadays ZPT-JS has some i18n capabilities. How do they work? Let's see an example:
</p>
<strong>i18n.js</strong>
<pre class="brush: js">
import { zpt } from './zpt-esm.js';
var I18n = zpt.I18n;
var I18nBundle = zpt.I18nBundle;
/* I18n maps init */
var msg = {
en : {},
es : {}
};
/* English i18n messages */
msg.en[ '/CONF/' ] = {
language: 'en',
locale: 'en-US'
};
msg.en[ 'Hello world!' ] = 'Hello world!';
msg.en[ 'Results msg' ] = '{GENDER, select, male{He} female{She} other{They} }' +
' found ' +
'{RES, plural, =0{no results} one{1 result} other{# results} }';
/* Spanish i18n messages */
msg.es[ '/CONF/' ] = {
language: 'es',
locale: 'es-ES'
};
msg.es[ 'Hello world!' ] = '¡Hola mundo!';
msg.es[ 'Results msg' ] = '{ GENDER, select, male{Él} female{Ella} other{Ellos} }' +
' ' +
'{ RES, plural, =0{no } other{} }' +
'{ GENDER, select, male{ha} female{ha} other{han} }' +
' encontrado ' +
'{ RES, plural, =0{ningún resultado} one{un único resultado} other{# resultados} }';
// Create I18n and i18nBundle instances
var i18nES = new I18n( 'es', msg[ 'es' ] );
var i18nEN = new I18n( 'en', msg[ 'en' ] );
var i18nBundle = new I18nBundle( i18nES, i18nEN );
// Init dictionary
var dictionary = {
'i18nBundle': i18nBundle
};
// Parse template
zpt.run({
root: document.body,
dictionary: dictionary
});
</pre>
<strong>i18n.html</strong>
<pre class="brush: html">
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Some I18n examples</title>
<script src="i18n.js"></script>
</head>
<body>
<h1>Some I18n expressions</h1>
<ol data-language="'en'" data-domain="i18nBundle">
<li>
¡Hola mundo! =
<span data-content="tr: 'Hello world!'">Must be ¡Hola mundo!</span>
</li>
<li>
Él ha encontrado 10 resultados =
<span data-content="tr: 'Results msg' ( GENDER 'male'; RES 10 )">Must be 'Él ha encontrado 10 resultados'</span>
</li>
</ol>
</body>
</html>
</pre>
<p>
Some remarks about this:
</p>
<ul>
<li>The dictionary must contain a source of i18n resources. ZPT-JS supports these types:
<ul>
<li>An instance of <code>I18n</code> class. Each instance includes all i18n strings in an i18n file in JSON format. The constructor of <code>I18n</code> class accepts 2 arguments; the first is the language of the messages and the second is a map (keys are the id of the messages and values the message themselves). The format of the messages must complain <a href="http://userguide.icu-project.org/formatparse/messages">ICU standards</a>.</li>
<li>An array of instances of <code>I18n</code> classes.</li>
<li>An instance of <code>I18nBundle</code> class. An instance of this class groups an instance of <code>I18n</code> class per supported language. They are useful to support using several languages in a template.</li>
</ul>
</li>
<li>The <code>data-domain</code> attribute defines the source of i18n resources to use. It can be one or several instances of <code>I18n</code> or <code>I18nBundle</code> classes or an array of them.</li>
<li>The <code>data-language</code> attribute defines the current language to use. It is needed when <code>data-domain</code> contains a <code>I18nBundle</code> instance, it is useless when we use <code>I18n</code> instances.</li>
<li>The <code>tr</code> expression evaluates an expression but then it searches that value into the messages.</li>
<li>The expression <code>'Hello world!'</code> is a literal, but <code>'Results msg' ( GENDER 'male'; RES 10 )</code> is a little more complex:
<ol>
<li>The first item is the message id: <code>'Results msg'</code>.</li>
<li>The rest are variables used to build the message: <code>GENDER 'male'</code> defines a <code>GENDER</code> variable with <code>'male'</code> as value.</li>
<li><code>RES 10</code> defines a <code>RES</code> variable with <code>10</code> as value.</li>
</ol>
</li>
</ul>
<h2 data-attributes="id 'examples'">Some examples</h2>
<p>
Some examples of i18n tags in action:
</p>
<ul>
<li>
<code><img src="image.png" data-attributes="title tr: 'Hello world!'"></code> adds an i18n title to the image.
</li>
<li>
<code><li data-define="msg tr: 'Hello world!'"></code> defines a <code>msg</code> variable with the i18n message of <code>'Hello world!'</code>.
</li>
<li>
<code><body data-on-error="tr: 'Oh, noooo!'"></code> sets the i18n message of <code>'Oh, noooo!'</code> as the message to show if an error occurs.
</li>
<li><code><span data-replace="tr: 'Hello world!'"></code> replaces the <code>span</code> tag by the i18n message of <code>'Hello world!'</code>.</li>
</ul>
<p>
Some examples of valid <code>data-domain</code> attributes:
</p>
<ul>
<li><code>data-domain="i18nES1"</code> Defines an instance of <code>I18n</code> class as the source of i18n strings.</li>
<li><code>data-domain="i18nES2 i18nES1"</code> Defines 2 instances of <code>I18n</code> class as the source of i18n strings. ZPT will use the <em>i18nES2</em> instance first; if the string is not found will be use <em>i18nES1</em> instance.</li>
<li><code>data-domain="i18nBundle1"</code> Defines an instance of <code>I18nBundle</code> class as the source of i18n strings.</li>
<li><code>data-domain="i18nBundle2 i18nBundle1"</code>Defines 2 instances of <code>I18nBundle</code> class as the source of i18n strings.</li>
<li><code>data-domain="i18nESArray"</code> Defines an array of instances of <code>I18n</code> class as the source of i18n strings. ZPT will use the first instance in the array; if the string is not found will be use the next instance until it is found.</li>
</ul>
<h2 data-attributes="id 'domains'">Working with domains</h2>
<p>
In the previous example the domain was a simple <code>I18nBundle</code> instance. This forces to use big maps with all the messages of one language. This can be awful if the amount of messages is big. <code>data-domain</code> tag supports also a list of <code>I18nBundle</code> instances, so the messages will be searched in the same order.
</p>
<p>
Therefore, <code>data-domain="i18nBundle1 i18nBundle2"</code> allows to organise your i18n messages in 2 maps. The first one can contain general messages and the second one more particular messages (for example).
</p>
<p>
<code>data-domain</code> also supports nested definitions:
</p>
<pre class="brush: html">
<div data-domain="i18nBundle1">
<span data-content="tr: 'Hello world!'">
¡Hola mundo!
</span>
<span data-domain="i18nBundle2" data-content="tr: 'Hello world!'">
¡¡¡Hola mundo 2!!!
</span>
</div>
</pre>
<p>
The first <code>data-content</code> will search only in <code>i18nBundle1</code>. The second one will search first in <code>i18nBundle2</code> and if it is not found will search in <code>i18nBundle1</code>.
</p>
<h2 data-attributes="id 'json'">Loading messages from JSON files</h2>
<p>
ZPT-JS makes it easy loading i18n messages from JSON files:
</p>
<pre class="brush: js">
zpt.run({
command: 'preload',
root: document.body,
dictionary: dictionary,
i18n: {
urlPrefix: './i18n/',
files: {
'es': [ 'es1.json', 'es2.json' ],
'en': [ 'en1.json', 'en2.json' ]
}
},
callback: function(){
// Add I18nBundle instances to dictionary
dictionary.i18nBundle1 = new I18nBundle( dictionary.i18nES1, dictionary.i18nEN1 );
dictionary.i18nBundle2 = new I18nBundle( dictionary.i18nES2, dictionary.i18nEN2 );
// Run ZPT
zpt.run();
}
});
</pre>
<p>
ZPT will add to dictionary these vars:
</p>
<ul>
<li><em>i18nES1</em>. Includes all texts from <em>es1.json</em> file.</li>
<li><em>i18nES2</em>. Includes all texts from <em>es2.json</em> file.</li>
<li><em>i18nEN1</em>. Includes all texts from <em>en1.json</em> file.</li>
<li><em>i18nEN2</em>. Includes all texts from <em>en2.json</em> file.</li>
<li><em>i18nESArray</em>. An array with all spanish texts, in this example <em>[ i18nES2, i18nES1 ]</em>.</li>
<li><em>i18nENArray</em>. An array with all english texts, in this example <em>[ i18nEN2, i18nEN1 ]</em>.</li>
<li><em>i18nArray</em>. An array with all texts defined only if only one language is present. In this example it would not be defined, there are 2 languages.</li>
</ul>
<p>
The order in arrays is inverted: first the last files, then the first.
</p>
<p>
The bundles (<em>i18nBundle1</em> and <em>i18nBundle2</em>) are not required, add to the dictionary if you need them.
</p>
<h2 data-attributes="id 'numbers'">Numbers</h2>
<p>
ZPT-JS uses <a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Intl">Intl</a> as i18n API for numbers. Let's see some examples:
</p>
<ul>
<li>
<code><span data-content="trNumber: 1355.23"></code> formats that number depending on the active i18n domain (<em>1,355.23</em> in english, <em>1.355,23</em> in spanish...).
</li>
<li>
<code><span data-content="trNumber: 1355.23643 ( maximumFractionDigits 3 )"></code> formats that number depending on the active i18n domain and using a maximum of 3 fraction digits (<em>1,355.236</em> in english, <em>1.355,236</em> in spanish...).
</li>
<li>
<code><span data-content="trNumber: 1355.23643 ( maximumFractionDigits 3; minimumIntegerDigits 6 )"></code> formats that number depending on the active i18n domain and using a maximum of 3 fraction digits and a minimum of 6 integer digits (<em>001,355.236</em> in english, <em>001.355,236</em> in spanish...).
</li>
</ul>
<p>
Take a look on <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat">NumberFormat options</a> to see all available options.
</p>
<h2 data-attributes="id 'currencies'">Currencies</h2>
<p>
ZPT-JS uses <a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Intl">Intl</a> as i18n API for currencies. Let's see some examples:
</p>
<ul>
<li>
<code><span data-content="trCurrency: 'EUR' 1355.23"></code> formats that number depending on the active i18n domain and using that currency (<em>€ 1,355.23</em> in english, <em>1.355,23 €</em> in spanish...).
</li>
<li>
<code><span data-content="trCurrency: 'USD' 1355.23 ( currencyDisplay 'name' )"></code> uses the name of the currency (<em>1,355.23 US dollars</em> in english, <em>1.355,23 € dólares estadounidenses</em> in spanish...).
</li>
</ul>
<p>
Options are the same as numbers (<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat">NumberFormat options</a>) plus some specific options of currencies.
</p>
<h2 data-attributes="id 'datesAndTimes'">Dates and times</h2>
<p>
ZPT-JS uses <a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Intl">Intl</a> as i18n API for date and times. Let's see some examples:
</p>
<ul>
<li>
<code><span data-content="trDate: ( js: new Date( Date.UTC( 2012, 11, 21, 3, 0, 0 ) ) )"></code> formats that date depending on the active i18n domain (<em>12/21/2012</em> in english, <em>21/12/2012</em> in spanish...).
</li>
<li>
<code><span data-content="trDate: ( js: new Date( Date.UTC( 2012, 11, 21, 3, 0, 0 ) ) ) ( weekday 'long'; year 'numeric'; month 'long'; day 'numeric' )"></code> formats that date with some options (<em>Friday, December 21, 2012</em> in english, <em>viernes, 21 de diciembre de 2012</em> in spanish...).
</li>
<li>
<code><span data-content="trDate: ( js: new Date( Date.UTC( 2012, 11, 21, 3, 0, 0 ) ) ) ( hour 'numeric'; minute 'numeric'; second 'numeric' )"></code> formats that date with some options (<em>4:00:00 AM</em> in english, <em>4:00:00</em> in spanish...).
</li>
</ul>
<p>
Take a look on <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat">DateTimeFormat options</a> to see all available options.
</p>
</article>
</div>
</body>
</html>