i18n-behavior
Version:
Instant and Modular I18N engine for lit-html and Polymer
240 lines (182 loc) • 8.42 kB
Markdown
[](https://travis-ci.org/t2ym/i18n-behavior)
[](https://coveralls.io/github/t2ym/i18n-behavior?branch=master)
[](https://www.npmjs.com/package/i18n-behavior)
[](https://www.webcomponents.org/element/t2ym/i18n-behavior)
# i18n-behavior
Instant and Modular I18N engine for [`lit-html`](https://lit-html.polymer-project.org/) and [Polymer](https://polymer-library.polymer-project.org/)
`html`\`\` tagged template literal API is provided by [`i18n-element`](https://github.com/t2ym/i18n-element)
## Compatible Versions
- Polymer library (`@polymer/polymer` NPM package) is configured as a **peer** dependency since 4.0.0
- Polymer elements using `I18nBehavior` must depend on `@polymer/polymer` NPM package themselves
| i18n-behavior | i18n-element | Polymer | lit-html |
|:---------------|:---------------|:--------|:---------|
| 5.x | 5.x | 3.x (optional) | 2.x |
| 4.x | 4.x | 3.x (optional) | 1.x |
| 3.x | 3.x | 3.x (mandatory) | 1.x |
| 2.x | 2.x | 1.x-2.x | - |
| 1.x | - | 1.x | - |
- [Changelog](https://github.com/t2ym/i18n-behavior/blob/master/CHANGELOG.md)
## Browser Compatibility
TODO: To be updated
| Browser | Chrome | Firefox | Edge 13+ | IE 11 | Safari 10+ | Chrome Android | Mobile Safari | Opera |
|:----------|:-------:|:--------:|:---------:|:------:|:---------:|:---------------:|:--------------:|:------:|
| Supported | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
- Polyfilled by `@webcomponents/webcomponentsjs/webcomponents-{bundle|loader}.js`
## Conceptual Workflow
- `demo/gulpfile.js` provides support for extracting UI strings from `html` tagged template literals in JavaScript sources as well as Polymer HTML templates in HTML Imports
<img src="https://raw.githubusercontent.com/wiki/t2ym/i18n-behavior/PolymerI18nFlow.gif" width="768px">
## Install
```sh
npm install i18n-behavior
```
## Import for Polymer elements
```js
import { I18nBehavior } from 'i18n-behavior/i18n-behavior.js'
```
## Quick Tour
[I18N-ready `pwa-starter-kit`](https://github.com/t2ym/pwa-starter-kit)
```sh
npm install -g polymer-cli
git clone https://github.com/t2ym/pwa-starter-kit
cd pwa-starter-kit
npm ci
# Add Locales
gulp locales --targets="de es fr ja zh-Hans"
# I18N Process
gulp
# Translate XLIFF ./xliff/bundle.*.xlf
# Merge Translation
gulp
# Dev build on http://localhost:8080
polymer serve
# Static build
polymer build
# Static build on http://localhost:8080
cd build/{esm-unbundled|esm-bundled|es6-bundled|es5-bundled}
python -m SimpleHTTPServer -p 8080
```
## Usage in Polymer legacy syntax
- [API Docs](https://t2ym.github.io/i18n-behavior/)
- [Demo](https://t2ym.github.io/i18n-behavior/demo/preprocess/)
- ES6 class syntax support is provided by [`i18n-element`](https://github.com/t2ym/i18n-element)
### Run-time Automatic I18N
Apply `BehaviorsStore.I18nBehavior` or imported `I18nBehavior`
#### Source Code
```js
// Legacy Polymer syntax
Polymer({
importMeta: import.meta,
is: 'custom-element',
_template: html`
<span id="label">UI text label</span> <!-- no need to touch UI text strings -->
`,
behaviors: [
I18nBehavior // Add this line for I18N
]
});
```
#### I18N-ready preprocessed DOM at element registration
Hard-coded UI text strings are automatically extracted and replaced with annotations bound to `text` object.
`lang` attribute specifies the current locale. By default, `<html lang>` attribute is observed and
mirrored to those for I18N-ready element instances.
```html
<html lang="en"><!-- html lang attribute is observed and mirrored -->
...
<custom-element lang="en">
<span id="label">{{text.label}}</span><!-- UI texts are bound to text object -->
</custom-element>
...
</html>
```
If the containing element of the target text has `id` attribute, the string id is named with the `id` value.
If not, the string id is automatically generated. It is recommended to put meaningful `id` to each string
for robustness. When attaching `id` attribute is too much for the containing element, `text-id` attribute can be used instead.
```html
<span text-id="label">{{text.label}}</span>
```
#### `text` dynamic property
`this.text` dynamic object property represents an object with UI text strings for the current locale.
```javascript
this.text = {
"label": "UI Text Label"
}
```
`this.text` dynamic object is SHARED among all the instances of the same custom element.
#### `model` dynamic property
`this.model` is deepcopied from `this.text.model` per instance to store I18N target attribute values.
UI text strings in I18N target attributes are automatically extracted and replaced with annotations
according to the shared repository (`i18n-attr-repo`) of I18N target attributes per elements
(like `placeholder` attribute of `input` element).
On `lang-updated` event, `this.text.model` is updated but `this.model` is NOT automatically updated
and needs explicit update like this.
```javascript
listeners: {
'lang-updated': '_langUpdated'
},
_langUpdated: function (event) {
if (Polymer.dom(event).rootTarget === this) {
this.model = deepcopy(this.text.model);
}
}
```
#### `<json-data>` for manual text definitions
Optionally, any JSON data can be manually added to I18N target strings via `<json-data>` element.
This option is effective for manual extraction of hard-coded UI text strings in JavaScript literals.
```html
<dom-module id="my-element">
<template>
... <!-- ordinary template for rendering -->
<template><!-- containing template element to avoid rendering -->
<json-data id="items">[
"Responsive Web App boilerplate",
"Iron Elements and Paper Elements",
"End-to-end Build Tooling (including Vulcanize)",
"Unit testing with Web Component Tester",
"Routing with Page.js",
"Offline support with the Platinum Service Worker Elements"
]</json-data>
<json-data id="sender">{ "name": "Sam", "gender": "male" }</json-data>
</template>
</template>
<script>
...
this.text.items[0] === 'Responsive Web App boilerplate'
this.text.sender.name === 'Sam'
...
</script>
</dom-module>
```
#### Localized text strings fetched from JSON
While default text strings are extracted from the hard-coded strings in HTML template,
localized text strings are asynchronously fetched from JSON files under `locales` directory at the server.
```
/bundle.json
/locales/bundle.ja.json
/bundle.fr.json
/bundle.zh-Hans.json
/elements/my-list/my-list.json
/locales/my-list.ja.json
/my-list.zh-Hans.json
/google-chart-demo/google-chart-demo.json
/locales/google-chart-demo.ja.json
/google-chart-demo.fr.json
```
### Build-time Automatic I18N
[`gulp-i18n-preprocess`](https://github.com/t2ym/gulp-i18n-preprocess) filter performs build-time automatic I18N and embeds UI texts as JSON.
I18N-ready Source Code preprocessed by [`gulp-i18n-preprocess`](https://github.com/t2ym/gulp-i18n-preprocess):
```html
<dom-module id="custom-element">
<template localizable-text="embedded">
<span id="label">{{text.label}}</span>
<template id="localizable-text">
<json-data>{
"label": "UI Text Label"
}</json-data>
</template>
</template>
</dom-module>
```
Default text values are immediately extracted from the embedded JSON
without overheads of run-time traversal into the whole template.
## License
[BSD-2-Clause](https://github.com/t2ym/i18n-behavior/blob/master/LICENSE.md)