data-i18n
data-i18n is the most powerful translations manager for javascript applications on the web.
- Easy to integrate: min to no effort
- No external dependencies: only javascript and html ?
- Blazing fast: it is a web component
- Works with any framework (React, Angular, Stencil, … even with plain Javascript)
- Automatic language detection from naviagator user preferences
- The key is the fallback: if no translation is found, the application will show the texts as defined
- Local translations with intelligent update system
- Versioning of translations with local cache in localstorage
- Supports interpolation
- Privacy friendly: local values can be opted-in/out
- Small footprint: < 400 kB (3.4 kB minified and gzipped)
- Free to use
Gold sponsors
From the creators of data-i18n: translations as a service – blablatec.com
Move your application to the next level: the premium translations service. With blablatec.com you can focus on what you do best: add value to your application, surrounding with valuable partners.
Blablatec.com helps you to manage the translations with an easy and intuitive system.
Local values and Cookie Policies
This library uses cookie lang
which must be opted in setting isLocalValuesAllowed: true
on initialization.
It also uses localstorage to keep the last version of the translation of each language in local storage. It must be opted in in the same way as cookie.
Configuration
Place the translations at assets/i18n/all.json
.
For every language, create an all-${langCode}.json
where langCode is the 2 letters code for the language. Also create the default all.json
:
all.json
all-en.json
all-ca.json
- …
Every file is in the form:
type TypeTData = {
[key: string]: string;
};
An example file could be:
{
"some text that should be translated": "this is the translation",
"[MAIN.TITLE]": "An important title",
"translation (% interpolated %)": "(% interpolated %) translation",
"translation interpolated object (% interp.someKey %)": "(% interp.someKey %) interpolated"
}
Quick examples
See examples in examples folder.
Example of use with plain Javascript
index.html
<!doctype html>
<html>
<head>
<script type="module" src="https://unpkg.com/data-i18n/dist/data-i18n/data-i18n.esm.js"></script>
<script nomodule src="https://unpkg.com/data-i18n/dist/data-i18n/data-i18n.js"></script>
</head>
<body>
<h1><i18n-t>The title of the page</i18n-t></h1>
<p><i18n-t data-i18n='{"name": "i18n Babel!", "url": "https://data-i18n.com"}'>Visit us: <a href="(%url)">(%name)</a></i18n-t></p>
<script>
Translator.init({ isLocalValuesAllowed: true });
</script>
</body>
</html>
Example of use with stencil.js app
Install
npm install data-i18n
Usage
app.ts
config file:
import { Translator } from 'data-i18n';
import './app.deps';
const envConfig: IEnvironmentConfig = {
env: 'production',
};
export default () => {
Translator.init({ isLocalValuesAllowed: true });
};
app.deps.ts
:
import 'data-i18n';
your-awesome-component.ts
:
import { Component, h, State, Prop } from '@stencil/core';
@Component({
tag: 'app-home',
styleUrl: 'app-home.css',
})
export class AppHome {
render() {
const tData = {
url: 'https://data-i18n.com',
name: 'i18n Babel!',
};
return <p><i18n-t data-i18n={JSON.stringify(tData)}>Visit us: <a href="(%url)">(%name)</a></i18n-t></p>;
}
}
API
Events
Event | Description | Type |
---|---|---|
i18n-translator-ready |
Event emitted when translator is ready to be initialized | CustomEvent<void> |
i18n-update-translations |
Event emitted when translations has been changed Mainly for internal purposes, ev.detail contains language |
CustomEvent<string> |
i18n-missing-translation |
Event emitted when missing (empty) translation is foundev.detail contains original textOnly emitted when isShowMissing is set to true |
CustomEvent<string> |
i18n-new-translation |
Event emitted when new translation is foundev.detail contains original textOnly emitted when isShowMissing is set to true |
CustomEvent<string> |
Example:
document.addEventListener('i18n-missing-translation', ev => console.log('Missing translation for:', ev.detail));
Translator
Translator is the main object. It is a singleton class and thus it cannot be instantiated. Use Translator.init(options)
to initialize translations. It also supports getInstance()
to get an instance to the object at any time of lifecycle.
All public methods of Translator
can be used as static or instance method.
init(options: ITranslatorOptions) => Translator
Initializes the translator object. Must be called before using data-i18n. When called after a previous call, it will overwrite the singleton object with the new options.
options
: initialization options- returns: an instance to the
Translator
object
const translator = Translator.init({
availableLangs: ['en', 'ca'],
defaultLanguage: 'en',
userLanguage: 'ca',
isShowMissing: true,
isLocalValuesAllowed: true,
apiUrl: `https://data-i18n.com/api/v1/application/5f7...`,
appId: 'an-app-id',
appSecret: 't8GTsNsd...',
missingTag: 'app',
tags: [],
});
It accepts an ITranslatorOptions options object with the following parameters:
interface ITranslatorOptions {
/** Allowed languages array, if found language is not in this array, will fall back to default, defaults to ['en'] */
availableLangs: string[];
/** The default language to select when the selected one is not found in availableLangs, defaults to 'en' */
defaultLanguage?: string;
/** Will take precedence over navigator language, defaults to 'en' */
userLanguage?: string;
/** Show missing translations in console, defaults to false */
isShowMissing?: boolean;
/** Allow the use of cookie `lang` to save the language and localstorage to save translations and versions, defaults to false */
isLocalValuesAllowed?: boolean;
/** Api url to get remote updates, defailts to null */
apiUrl?: string;
/** App id to get remote updates, defailts to null */
appId?: string;
/** App secret to get remote updates, defailts to null */
appSecret?: string;
/** The tag that will be sent to server when missing string is found, defaults to 'app' */
missingTag?: string;
/** The tags to filter strings on server side, defaults [] */
tags?: string[];
/** Path to the location of assets files */
assetsLocation: string;
/**
* Names of the translations and version files. Define it as:
* ```
* { "--": "filename1.json", "ca": "filename2.json", "en": "filename3.json", ..., "versions": "filename.json" }
* ```
* defaults: For every language, the default file is located at `all-${langCode}.json`:
* ```
* { "--": "all.json", "ca": "all-ca.json", "en": "all-en.json", ..., "versions": "versions.json" }
* ```
*/
fileNames: { [key: string]: string };
}
getInstance() => Translator
Translator is a static object.
- returns: an instance to the
Translator
object
const translator = Translator.getInstance();
setLocalValuesAllowed(isLocalValuesAllowed = false) => void
Opts in/out the use of local values.
isLocalValuesAllowed
boolean value indicating if local values are allowed or not
WARNING: calling this function with false
will remove all local values.
Translator.setLocalValuesAllowed(true);
t(originalText: string, tData?: TypeTData, lang?: string) => Promise<string>
Translates a text, returns the text itself if no translation is found.
originalText
: text to translatetData
: Interpolation parameterslang
: Translation language- returns: Translated text
const translation = await Translator.t('Hello from (% name %)!', { name: 'data-i18n' }, 'ca');
Given an all-ca.json
like the following one:
{
"Hello from (% name %)!": "(% name %) et saluda!"
}
The variable translation
will become: data-i18n et saluda!
guessLanguage(isSkipCookie = false, resetCookie = false) => string
This method may never be used, use getCurrentLanguage()
instead.
Guess the language. First look at the lang
cookie.
If it’s not available, it looks for the language in these places (in this order of precedence):
-
options.userLanguage
-
navigator.userLanguage
-
options.defaultLanguage
-
isSkipCookie
: does not read from cookie -
resetCookie
: saves the favorite language tolang
cookie -
returns: 2 letters favorite language
Translator.guessLanguage();
Use case: get the language in which the user would like to see the application.
getDefaultLanguage() => string
This method may never be used, use getCurrentLanguage()
instead.
Guesses the language (see guessLanguage()
) and filters it with availableLangs
.
If the language is not present in availableLangs
the options.defaultLanguage
will be returned.
- returns: 2 letters default language
Translator.getDefaultLanguage();
Use case: get the language in which the application will be displayed the first time it is opened.
getCurrentLanguage() => string
Gets the current language of the application.
- returns: 2 letters current language
Translator.getCurrentLanguage();
setLanguage(lang) => boolean
Changes the language of the application.
Must be one of availableLangs otherwise the favorite language will be selected.
lang
: new language- returns: the selected language
Translator.setLanguage('es');
cacheClear() => void
Clears the translations cache and tries to download again the translations.
Translator.cacheClear();
window.newTranslations => { [key: string]: string }
Contains an array with all new translations found. Only available when isShowMissing
is set to true
.
Backend API
The backend API must implement the following routes:
- GET
${apiUrl}/lang
: return an array with available languages - GET
${apiUrl}/lang/loc-version?lang=${lang}
: return a float number with the version of the requested language - GET
${apiUrl}/locale/all.json?lang=${lang}&tags=app,server
: return a json with the translations for the language- lang: the language in format
'en'
- tags: optional coma separated tags
- lang: the language in format
- POST
${apiUrl}/locale/missing
: saves missing string, body contains the data for the missing string:- lang: the language of the translation,
- tag: the tag for this translation, in order to filter translations ing GET
all.json
- text: the missing translation
- extra: (window as any).location.href
License
MIT