Progress towards 0.1.0 #1
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es6": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 2018,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"indent": [
|
||||||
|
"error",
|
||||||
|
"tab"
|
||||||
|
],
|
||||||
|
"linebreak-style": [
|
||||||
|
"error",
|
||||||
|
"unix"
|
||||||
|
],
|
||||||
|
"quotes": [
|
||||||
|
"error",
|
||||||
|
"single"
|
||||||
|
],
|
||||||
|
"semi": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
*.ts text eol=lf
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/node_modules
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<title>i18n-js - Sample</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header class="header">
|
||||||
|
<select id="language">
|
||||||
|
</select>
|
||||||
|
</header>
|
||||||
|
<div class="content">
|
||||||
|
<h1 class="title" data-i18n="title"></h1>
|
||||||
|
<p data-i18n="p1"></p>
|
||||||
|
<p data-i18n="p2"></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script src='../i18n.js'></script>
|
||||||
|
<script>
|
||||||
|
let languages = {
|
||||||
|
enUS: 'English (American)',
|
||||||
|
enGB: 'English (British)',
|
||||||
|
deDE: 'Deutsch',
|
||||||
|
};
|
||||||
|
let translations = {
|
||||||
|
enUS: {
|
||||||
|
title: 'Hello World',
|
||||||
|
p1: 'This is a sample of the capabilities of i18n.js by Xaymar. It can translate any kind of data in real time, as long as some kind of key value system is enough.',
|
||||||
|
p2: 'In case you were wondering, you can change the language with the dropdown.',
|
||||||
|
language: 'Language',
|
||||||
|
},
|
||||||
|
enGB: {
|
||||||
|
_base: 'enUS',
|
||||||
|
},
|
||||||
|
deDE: {
|
||||||
|
_base: 'enGB',
|
||||||
|
title: 'Hallo Welt',
|
||||||
|
p1: 'Dies ist ein Beispiel der Fähigkeiten von i18n.js, geschrieben von Xaymar. Es kann alle möglichen Daten in Echtzeitübersetzen, sofern ein Schlüssel-Wert-System genug ist.',
|
||||||
|
p2: 'Du kannst die Sprache mit dem Drop-Down ändern, falls du dich gewundert hattest.',
|
||||||
|
language: 'Sprache',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let defaultLang = 'enUS';
|
||||||
|
let i18n = {
|
||||||
|
language: new I18n('default'),
|
||||||
|
content: new I18n(defaultLang)
|
||||||
|
};
|
||||||
|
|
||||||
|
async function contentSwitchLanguage(language) {
|
||||||
|
if (!i18n.content.hasLanguage(language)) {
|
||||||
|
await i18n.content.loadLanguage(language, translations[language]);
|
||||||
|
console.log('loaded language %s', language);
|
||||||
|
}
|
||||||
|
await i18n.content.domTranslate(language);
|
||||||
|
console.log('translated page to language %s', language);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load default language
|
||||||
|
let contentPromise = i18n.content.loadLanguage(defaultLang, translations[defaultLang]);
|
||||||
|
let languagePromise = i18n.language.loadLanguage('default', languages);
|
||||||
|
|
||||||
|
// Fill Language Input with values, and hook it up to change the site language
|
||||||
|
let languageInput = document.getElementById('language');
|
||||||
|
for (let language in languages) {
|
||||||
|
let el = document.createElement('option');
|
||||||
|
el.dataset['language'] = language;
|
||||||
|
if (language == defaultLang) {
|
||||||
|
el.defaultSelected = true;
|
||||||
|
}
|
||||||
|
languageInput.appendChild(el);
|
||||||
|
}
|
||||||
|
languageInput.onchange = async (ev) => {
|
||||||
|
languageInput.disabled = true;
|
||||||
|
await contentSwitchLanguage(ev.target.selectedOptions[0].dataset['language']);
|
||||||
|
languageInput.disabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Log language promise completion.
|
||||||
|
languagePromise.then(async (result) => {
|
||||||
|
console.log('I18n for Language field loaded.');
|
||||||
|
await i18n.language.domTranslate('default', 'data-language');
|
||||||
|
console.log('I18n for Language field ready.');
|
||||||
|
});
|
||||||
|
contentPromise.then(async (result) => {
|
||||||
|
await i18n.content.domTranslate(defaultLang);
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -15,152 +15,493 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let group = "i18n";
|
/*
|
||||||
let group_style = "font-weight: bold;";
|
Dead Simple I18n Library
|
||||||
let text_style = "font-weight: inherit;";
|
|
||||||
|
|
||||||
class I18n {
|
Languages are stored in a Map() to allow for any kind of name to be used. In
|
||||||
/** Create a new object, ready to be used.
|
addition to that there is a global base language, and each language can
|
||||||
*
|
specify an override base language which will be used only if that language
|
||||||
* @param {string} urlFormat URL from which to asynchronously load translation data from in the format 'url/file{0}.extension' ({0} is replaced by the lowercase language name).
|
is actually loaded during translation. The base language can be an array
|
||||||
*/
|
instead of a string, in which each language is tested in order of appearance.
|
||||||
constructor(urlFormat) {
|
|
||||||
console.log("%c[%s]%c Initializing ...", group_style, group, text_style);
|
|
||||||
if (typeof(urlFormat) != "string") {
|
|
||||||
throw "urlFormat must be of type string";
|
|
||||||
}
|
|
||||||
this.url = urlFormat;
|
|
||||||
this.languages = {};
|
|
||||||
this.languages.base = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
_sanitizeLanguage(language) {
|
The key can only be a string, while the Value is allowed to be anything. In
|
||||||
if (typeof(language) != "string") {
|
case you want to implement pluralization in your translation layer, you would
|
||||||
throw "language must be of type string";
|
be doing it with an object value or similar. This creates a simple structure
|
||||||
}
|
that can be used for various kinds of translations, and is as fast as the
|
||||||
return language.toLowerCase();
|
underlying Map implementation.
|
||||||
}
|
|
||||||
|
|
||||||
/** Load a new language.
|
# Example: Evaluation of the language chain [en-US < en-GB < de-DE < de-BE]
|
||||||
*
|
Searching for the key will first happen in de-BE, then in de-DE, then in en-GB
|
||||||
* @param {string} language Name of the language file.
|
and finally in en-US. If de-BE, de-DE or en-GB is not loaded, that specific
|
||||||
* @param {boolean} isBaseLanguage Use this language as the new base language.
|
lookup step skips straight to the global base language, in this case en-US. If
|
||||||
* @returns {Promise}
|
en-US is not loaded, the original i18n key is returned instead.
|
||||||
*/
|
|
||||||
load(language, isBaseLanguage) {
|
|
||||||
language = this._sanitizeLanguage(language);
|
|
||||||
if (isBaseLanguage == true) {
|
|
||||||
this.languages.base = language;
|
|
||||||
}
|
|
||||||
if (this.languages[language] == undefined) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let self = this;
|
|
||||||
let url = this.url.replace('{0}', language);
|
|
||||||
console.debug("%c[%s]%c Loading language '%s' from url '%s'...",
|
|
||||||
group_style, group, text_style,
|
|
||||||
language, url);
|
|
||||||
|
|
||||||
let req = new XMLHttpRequest();
|
# Example: Evaluation of the language chain [en-US < en-GB < de-DE, en-GB < de-BE]
|
||||||
req.addEventListener("error", function (event) {
|
Checks first happen in de-BE, if de-BE does not have the key checks move on to
|
||||||
console.log("%c[%s]%c Failed to load language '%s': ",
|
de-DE. If de-DE is not loaded, en-GB is instead checked. If de-DE does not
|
||||||
group_style, group, text_style,
|
have the key, checks progress to en-GB. If en-GB does not have the key, checks
|
||||||
language, event);
|
progress to en-US. If any of them are not loaded or does not have the key, the
|
||||||
|
next language in the base languages is checked, until the base languages are
|
||||||
|
exhausted, in which case the i18n key is returned.
|
||||||
|
|
||||||
});
|
# Structure
|
||||||
req.addEventListener("progress", function (event) {
|
Map{
|
||||||
let prc = event.loaded / event.total;
|
languageName: Map{
|
||||||
if (event.loaded == event.total) {
|
// Base language override (optional)
|
||||||
prc = 100.0;
|
_base: {string},
|
||||||
}
|
// Key Value storage for lookup
|
||||||
if (event.total == 0) {
|
{string key}: {any value},
|
||||||
prc = 0.0;
|
|
||||||
}
|
|
||||||
console.debug("%c[%s]%c Loading language '%s'... [%6.2f%%]",
|
|
||||||
group_style, group, text_style,
|
|
||||||
language, prc);
|
|
||||||
});
|
|
||||||
req.addEventListener("load", function (event) {
|
|
||||||
console.debug("%c[%s]%c Parsing language '%s'...",
|
|
||||||
group_style, group, text_style,
|
|
||||||
language);
|
|
||||||
try {
|
|
||||||
self.languages[language] = JSON.parse(req.responseText);
|
|
||||||
} catch (e) {
|
|
||||||
console.log("%c[%s]%c Failed to load language '%s': ",
|
|
||||||
group_style, group, text_style,
|
|
||||||
language, e);
|
|
||||||
reject(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resolve(true);
|
|
||||||
console.log("%c[%s]%c Loaded language '%s'.",
|
|
||||||
group_style, group, text_style,
|
|
||||||
language);
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
req.open("GET", url);
|
|
||||||
req.overrideMimeType("text/plain; charset=utf-8");
|
|
||||||
req.send();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.log("%c[%s]%c Loaded language '%s'...",
|
|
||||||
group_style, group, text_style, language);
|
|
||||||
return new Promise((resolve, reject) => { resolve(true); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Translate a single string to any loaded language.
|
|
||||||
*
|
|
||||||
* @param {string} string String to translate
|
|
||||||
* @param {string} language Language to translate to
|
|
||||||
* @return {string} Translated string, or if failed the string plus the language appended.
|
|
||||||
*/
|
|
||||||
translate(string, language) {
|
|
||||||
language = this._sanitizeLanguage(language);
|
|
||||||
if (typeof(string) != "string") {
|
|
||||||
throw "string must be of type string";
|
|
||||||
}
|
|
||||||
let str = this.languages[language][string];
|
|
||||||
if (str == undefined) {
|
|
||||||
let str = this.languages[this.languages.base][string];
|
|
||||||
if (str == undefined) {
|
|
||||||
console.error("%c[%s]%c Language '%s' and base language '%s' contain no translation for '%s'.",
|
|
||||||
group_style, group, text_style,
|
|
||||||
language, this.languages.base, string
|
|
||||||
)
|
|
||||||
return string + language;
|
|
||||||
} else {
|
|
||||||
console.debug("%c[%s]%c Language '%s' contains no translation for '%s', falling back to base language '%s'.",
|
|
||||||
group_style, group, text_style,
|
|
||||||
language, string, this.languages.base
|
|
||||||
)
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Automatically translate the entire page using the specified property on elements.
|
|
||||||
*
|
|
||||||
* @param {*} language Language to translate to
|
|
||||||
* @param {*} property Property to search for (default 'data-i18n')
|
|
||||||
*/
|
|
||||||
autoTranslate(language, property = 'data-i18n') {
|
|
||||||
language = this._sanitizeLanguage(language);
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
console.debug("%c[%s]%c Starting automatic translation to language '%s'...",
|
|
||||||
group_style, group, text_style,
|
|
||||||
language);
|
|
||||||
let els = document.querySelectorAll(`[${property}]`);
|
|
||||||
for (let el of els) {
|
|
||||||
let string = el.getAttribute(property);
|
|
||||||
el.textContent = string;
|
|
||||||
el.textContent = this.translate(string, language);
|
|
||||||
}
|
|
||||||
console.log("%c[%s]%c Translated to language '%s'.",
|
|
||||||
group_style, group, text_style,
|
|
||||||
language);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Internal behavior
|
||||||
|
The library will build a chain of languages to check in a loop for, to avoid
|
||||||
|
costly recursive calls that aren't well protected against loops in base
|
||||||
|
language definitions (i.e. de-DE depends on en-GB, en-GB depends on de-DE).
|
||||||
|
This cache is refreshed when first attempting to translate to that language,
|
||||||
|
and flagged as dirty every time a language is loaded or a base language is
|
||||||
|
changed.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
class I18n {
|
||||||
|
/** Create a new object, ready to be used.
|
||||||
|
*
|
||||||
|
* @param {string} defaultLanguage Initial base language to base all translations on.
|
||||||
|
* @param {string} baseLanguageKey Key to use for base language overrides. (Default = _base)
|
||||||
|
* @throws Exception on invalid parameters.
|
||||||
|
*/
|
||||||
|
constructor(defaultLanguage, baseLanguageKey = '_base') {
|
||||||
|
this._sanitizeLanguage(defaultLanguage);
|
||||||
|
this._verifyKey(baseLanguageKey);
|
||||||
|
|
||||||
|
this.languages = new Map();
|
||||||
|
this.chains = new Map();
|
||||||
|
this.baseLanguage = defaultLanguage;
|
||||||
|
this.baseLanguageKey = baseLanguageKey;
|
||||||
|
|
||||||
|
this.dirtyTs = performance.now();
|
||||||
|
this.chainsTs = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
_verifyLanguageKnown(language) {
|
||||||
|
if (!this.languages.has(language)) {
|
||||||
|
throw 'language unknown';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_verifyKey(key) {
|
||||||
|
if (typeof (key) == 'string') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw 'key must be of type string';
|
||||||
|
}
|
||||||
|
|
||||||
|
_verifyKeyKnown(language, key) {
|
||||||
|
this._verifyLanguageKnown(language);
|
||||||
|
this._verifyKey(key);
|
||||||
|
|
||||||
|
if (!this.languages.get(language).has(key)) {
|
||||||
|
throw 'key unknown in language';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_verifyData(data) {
|
||||||
|
if (typeof (data) == 'string') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof (data) == 'object') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data instanceof File) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data instanceof Blob) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw 'data must be of type string, object, File or Blob';
|
||||||
|
}
|
||||||
|
|
||||||
|
_sanitizeLanguage(language) {
|
||||||
|
try {
|
||||||
|
this._verifyKey(language);
|
||||||
|
} catch (e) {
|
||||||
|
throw 'language must be of type string';
|
||||||
|
}
|
||||||
|
return language.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
_defaultResolver(language, key, element) {
|
||||||
|
element;
|
||||||
|
return this.translate(key, language);
|
||||||
|
}
|
||||||
|
|
||||||
|
_defaultApplier(language, key, translation, element) {
|
||||||
|
try {
|
||||||
|
element.textContent = translation;
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Caches the necessary language chain for translation.
|
||||||
|
*
|
||||||
|
* Creates and returns a language chain required for translation, avoiding
|
||||||
|
* recursive loops that never end in the process. The chain will not
|
||||||
|
* evalute the entire branch first, instead it will check all branches
|
||||||
|
* and then list the childs of those branches. This is an expensive
|
||||||
|
* operation and should only be done once on every language update.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* de-DE +- en-GB - en-US - de-DE (- en-GB, en-US, ... [recursive])
|
||||||
|
* \- en-US - de-DE (- en-GB, en-US, ... [recursive])
|
||||||
|
* Result: [de-DE, en-GB, en-US]
|
||||||
|
* Explanation: de-DE depends on both en-GB and en-US, and will check both
|
||||||
|
* before considering the next branch. Since all dependencies are resolved
|
||||||
|
* early, a recursive lookup is prevented here.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param {string} language
|
||||||
|
* @returns {array} Translation chain
|
||||||
|
*/
|
||||||
|
_cacheChain(language) {
|
||||||
|
// This caches a chain so that we do not have to rebuild this every
|
||||||
|
// lookup. It is important that there are no recursive loops in this
|
||||||
|
// code, which means we can't rely on this function to work until the
|
||||||
|
// cache is completed.
|
||||||
|
|
||||||
|
// Have there been changes to the timestamp?
|
||||||
|
if (this.chainsTs < this.dirtyTs) {
|
||||||
|
// If yes, clear all chains for rebuilding.
|
||||||
|
this.chainsTs = this.dirtyTs;
|
||||||
|
this.chains.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we have a chain cached?
|
||||||
|
if (this.chains.has(language)) {
|
||||||
|
// Yes, return the cached chain and go back to translation.
|
||||||
|
return this.chains.get(language);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new chain without relying on our own function.
|
||||||
|
let chain = new Array();
|
||||||
|
chain.push(language); // Chains always contain the language itself.
|
||||||
|
|
||||||
|
// Now we walk through the chain manually, modifying it as we go.
|
||||||
|
for (let pos = 0; pos < chain.length; pos++) {
|
||||||
|
// Check if the language is loaded, if not skip it.
|
||||||
|
if (!this.languages.has(chain[pos])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let languageMap = this.languages.get(chain[pos]);
|
||||||
|
|
||||||
|
// Check if there is a base language override.
|
||||||
|
if (!languageMap.has(this.baseLanguageKey)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let baseLanguages = languageMap.get(this.baseLanguageKey);
|
||||||
|
|
||||||
|
// Convert to array for for...in.
|
||||||
|
if (typeof (baseLanguages) == 'string') {
|
||||||
|
baseLanguages = [baseLanguages];
|
||||||
|
} else if (!(baseLanguages instanceof Array)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let base of baseLanguages) {
|
||||||
|
base = this._sanitizeLanguage(base);
|
||||||
|
if (!chain.includes(base) && (this.languages.has(base))) {
|
||||||
|
chain.push(base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the global base languages if there are no other languages left.
|
||||||
|
if (pos == (chain.length - 1)) {
|
||||||
|
let baseLanguages = this.baseLanguage;
|
||||||
|
if (typeof(this.baseLanguage) == 'string') {
|
||||||
|
baseLanguages = [this.baseLanguage];
|
||||||
|
}
|
||||||
|
for (let base of baseLanguages) {
|
||||||
|
if (!chain.includes(base) && (this.languages.has(base))) {
|
||||||
|
chain.push(base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store.
|
||||||
|
this.chains.set(language, chain);
|
||||||
|
|
||||||
|
// Return.
|
||||||
|
return chain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if a language is known.
|
||||||
|
*
|
||||||
|
* @param {string} language Name of the language
|
||||||
|
* @returns {bool} true if known.
|
||||||
|
*/
|
||||||
|
hasLanguage(language) {
|
||||||
|
language = this._sanitizeLanguage(language);
|
||||||
|
return this.languages.has(language);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a new language.
|
||||||
|
*
|
||||||
|
* @param {string} language Name of the language.
|
||||||
|
* @throws Exception on invalid parameters.
|
||||||
|
*/
|
||||||
|
createLanguage(language) {
|
||||||
|
language = this._sanitizeLanguage(language);
|
||||||
|
this.languages.set(language, new Map());
|
||||||
|
this.dirtyTs = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Load a new language.
|
||||||
|
*
|
||||||
|
* @param {string} language Name of the language.
|
||||||
|
* @param {File/Blob/object/string} data Data containing a JSON representation of the language.
|
||||||
|
* @param {string} encoding (Optional) Encoding to use when reading File or Blob.
|
||||||
|
* @returns {Promise}
|
||||||
|
* @throws Exception on invalid parameters or invalid data.
|
||||||
|
*/
|
||||||
|
loadLanguage(language, data, encoding = 'utf-8') {
|
||||||
|
// Verify input.
|
||||||
|
language = this._sanitizeLanguage(language);
|
||||||
|
this._verifyData(data);
|
||||||
|
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
let json_data;
|
||||||
|
|
||||||
|
// Decode File, Blob and string to JSON object.
|
||||||
|
if ((data instanceof File) || (data instanceof Blob)) {
|
||||||
|
let freader = new FileReader();
|
||||||
|
await new Promise((resolve2, reject2) => {
|
||||||
|
freader.onload(() => {
|
||||||
|
resolve2();
|
||||||
|
});
|
||||||
|
freader.onabort((ev) => {
|
||||||
|
reject2(ev);
|
||||||
|
});
|
||||||
|
freader.onerror((ev) => {
|
||||||
|
reject2(ev);
|
||||||
|
});
|
||||||
|
freader.readAsText(data, encoding);
|
||||||
|
});
|
||||||
|
json_data = JSON.parse(freader.result);
|
||||||
|
} else if (typeof (data) == 'string') {
|
||||||
|
json_data = JSON.parse(data);
|
||||||
|
} else if (typeof (data) == 'object') {
|
||||||
|
json_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
let language_map = new Map();
|
||||||
|
for (let key in json_data) {
|
||||||
|
language_map.set(key, json_data[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.languages.set(language, language_map);
|
||||||
|
this.dirtyTs = performance.now();
|
||||||
|
resolve(language);
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Save a language.
|
||||||
|
*
|
||||||
|
* @param {string} language Name of the language.
|
||||||
|
* @returns {Promise} Promise that eventually returns the JSON data of the language.
|
||||||
|
* @throws Exception on invalid parameters and missing language.
|
||||||
|
*/
|
||||||
|
saveLanguage(language) {
|
||||||
|
language = this._sanitizeLanguage(language);
|
||||||
|
this._verifyLanguageKnown(language);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
reject;
|
||||||
|
this._verifyLanguageKnown(language);
|
||||||
|
|
||||||
|
let language_data = {};
|
||||||
|
let language_map = this.languages.get(language);
|
||||||
|
language_map.forEach((value, key, map) => {
|
||||||
|
map;
|
||||||
|
language_data[key] = value;
|
||||||
|
});
|
||||||
|
let json_data = JSON.stringify(language_data);
|
||||||
|
resolve(json_data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Destroy/unload a language.
|
||||||
|
*
|
||||||
|
* @param {string} language Name of the language.
|
||||||
|
* @throws Exception on invalid parameters and missing language.
|
||||||
|
*/
|
||||||
|
destroyLanguage(language) {
|
||||||
|
language = this._sanitizeLanguage(language);
|
||||||
|
this._verifyLanguageKnown(language);
|
||||||
|
|
||||||
|
this.languages.delete(language);
|
||||||
|
this.dirtyTs = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Clear a key from a language.
|
||||||
|
*
|
||||||
|
* @param {string} language Language to edit.
|
||||||
|
* @param {string} key Key to clear.
|
||||||
|
* @return {bool} true on success.
|
||||||
|
* @throws Exception on invalid parameters and missing language.
|
||||||
|
*/
|
||||||
|
clearKey(language, key) {
|
||||||
|
// Verify and sanitize input.
|
||||||
|
language = this._sanitizeLanguage(language);
|
||||||
|
this._verifyKey(key);
|
||||||
|
|
||||||
|
// Check if language exists.
|
||||||
|
this._verifyLanguageKnown(language);
|
||||||
|
|
||||||
|
// Delete key if exists.
|
||||||
|
let language_map = this.languages.get(language);
|
||||||
|
if (!language_map.has(key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
language_map.delete(key);
|
||||||
|
|
||||||
|
// If the key was the base language key, set dirty timestamp.
|
||||||
|
if (key == this.baseLanguageKey) {
|
||||||
|
this.dirtyTs = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set a key in a language
|
||||||
|
*
|
||||||
|
* @param {string} language Language to edit.
|
||||||
|
* @param {string} key Key to set.
|
||||||
|
* @param {*} value New value to set.
|
||||||
|
* @param {bool} force Force the update if the key exists. (Default = true)
|
||||||
|
* @return {bool} true on success.
|
||||||
|
* @throws Exception on invalid parameters and missing language.
|
||||||
|
*/
|
||||||
|
setKey(language, key, value, force = true) {
|
||||||
|
// Verify and sanitize input.
|
||||||
|
language = this._sanitizeLanguage(language);
|
||||||
|
this._verifyKey(key);
|
||||||
|
|
||||||
|
// Check if language exists.
|
||||||
|
this._verifyLanguageKnown(language);
|
||||||
|
|
||||||
|
// Set key.
|
||||||
|
let language_map = this.languages.get(language);
|
||||||
|
if ((language_map.has(key)) && !force) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
language_map.set(key, value);
|
||||||
|
|
||||||
|
// If the key was the base language key, set dirty timestamp.
|
||||||
|
if (key == this.baseLanguageKey) {
|
||||||
|
this.dirtyTs = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a key in a language
|
||||||
|
*
|
||||||
|
* @param {string} language
|
||||||
|
* @param {string} key
|
||||||
|
* @return {*} the value
|
||||||
|
* @throws Exception on invalid parameters, missing language and missing key.
|
||||||
|
*/
|
||||||
|
getKey(language, key) {
|
||||||
|
// Verify and sanitize input.
|
||||||
|
language = this._sanitizeLanguage(language);
|
||||||
|
this._verifyKeyKnown(language, key);
|
||||||
|
|
||||||
|
// Get Key
|
||||||
|
let language_map = this.languages.get(language);
|
||||||
|
return language_map.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Translate a single string to any loaded language.
|
||||||
|
*
|
||||||
|
* @param {string} key String to translate
|
||||||
|
* @param {string} language Language to translate to
|
||||||
|
* @return {string} Translated string, or if failed the string plus the language appended.
|
||||||
|
* @throws Exception on invalid parameters.
|
||||||
|
*/
|
||||||
|
translate(key, language) {
|
||||||
|
// Verify and sanitize input.
|
||||||
|
language = this._sanitizeLanguage(language);
|
||||||
|
this._verifyKey(key);
|
||||||
|
|
||||||
|
// Translate using the translation chain.
|
||||||
|
let chain = this._cacheChain(language);
|
||||||
|
let translated = key;
|
||||||
|
for (let language of chain) {
|
||||||
|
let languageMap = this.languages.get(language);
|
||||||
|
if (languageMap.has(key)) {
|
||||||
|
translated = languageMap.get(key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return translated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Automatically translate the entire page using the specified property on elements.
|
||||||
|
*
|
||||||
|
* @param {string} language Language to translate to
|
||||||
|
* @param {string} property Property to search for (default 'data-i18n')
|
||||||
|
* @param {function} resolver Function to call to find the proper translation, called with parameters ({string}language, {string}key, {Node}element) and must return a string.
|
||||||
|
* @param {function} applier Function to call to apply the proper translation, called with parameters ({string}language, {string}key, {string}translation, {Node}element) and must return a boolean.
|
||||||
|
* @returns {Promise} resolved when successful, rejected if applier returns false.
|
||||||
|
* @throws Exception on invalid parameters.
|
||||||
|
*/
|
||||||
|
domTranslate(language, property = 'data-i18n', resolver = undefined, applier = undefined) {
|
||||||
|
language = this._sanitizeLanguage(language);
|
||||||
|
if ((resolver != undefined) && (typeof (resolver) != 'function')) {
|
||||||
|
throw 'resolver must be a function';
|
||||||
|
} else if (resolver == undefined) {
|
||||||
|
let self = this;
|
||||||
|
resolver = (language, key, el) => {
|
||||||
|
return self._defaultResolver(language, key, el);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if ((applier != undefined) && (typeof (applier) != 'function')) {
|
||||||
|
throw 'applier must be a function';
|
||||||
|
} else if (applier == undefined) {
|
||||||
|
let self = this;
|
||||||
|
applier = (language, key, translation, el) => {
|
||||||
|
return self._defaultApplier(language, key, translation, el);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let els = document.querySelectorAll(`[${property}]`);
|
||||||
|
for (let el of els) {
|
||||||
|
let key = el.getAttribute(property);
|
||||||
|
if (!applier(language, key, resolver(language, key, el), el)) {
|
||||||
|
reject();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compatible with Node.js and Browsers
|
||||||
|
if (typeof (module) != 'undefined') {
|
||||||
|
module.exports = exports = {
|
||||||
|
'I18n': I18n
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
Generated
+928
@@ -0,0 +1,928 @@
|
|||||||
|
{
|
||||||
|
"name": "i18n",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/code-frame": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/highlight": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@babel/highlight": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chalk": "^2.0.0",
|
||||||
|
"esutils": "^2.0.2",
|
||||||
|
"js-tokens": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"acorn": {
|
||||||
|
"version": "6.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz",
|
||||||
|
"integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"acorn-jsx": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"ajv": {
|
||||||
|
"version": "6.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz",
|
||||||
|
"integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fast-deep-equal": "^2.0.1",
|
||||||
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
"json-schema-traverse": "^0.4.1",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ansi-escapes": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"ansi-regex": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"ansi-styles": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"color-convert": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"argparse": {
|
||||||
|
"version": "1.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"sprintf-js": "~1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"balanced-match": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"brace-expansion": {
|
||||||
|
"version": "1.1.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"caller-path": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
|
||||||
|
"integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"callsites": "^0.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"callsites": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "http://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
|
||||||
|
"integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"chalk": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-styles": "^3.2.1",
|
||||||
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
"supports-color": "^5.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chardet": {
|
||||||
|
"version": "0.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
||||||
|
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"circular-json": {
|
||||||
|
"version": "0.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
|
||||||
|
"integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"cli-cursor": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
|
||||||
|
"integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"restore-cursor": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cli-width": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
|
||||||
|
"integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"color-convert": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"color-name": "1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color-name": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||||
|
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"cross-spawn": {
|
||||||
|
"version": "6.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
|
||||||
|
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"nice-try": "^1.0.4",
|
||||||
|
"path-key": "^2.0.1",
|
||||||
|
"semver": "^5.5.0",
|
||||||
|
"shebang-command": "^1.2.0",
|
||||||
|
"which": "^1.2.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deep-is": {
|
||||||
|
"version": "0.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
||||||
|
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"doctrine": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"esutils": "^2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"escape-string-regexp": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
|
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"eslint": {
|
||||||
|
"version": "5.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-5.9.0.tgz",
|
||||||
|
"integrity": "sha512-g4KWpPdqN0nth+goDNICNXGfJF7nNnepthp46CAlJoJtC5K/cLu3NgCM3AHu1CkJ5Hzt9V0Y0PBAO6Ay/gGb+w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/code-frame": "^7.0.0",
|
||||||
|
"ajv": "^6.5.3",
|
||||||
|
"chalk": "^2.1.0",
|
||||||
|
"cross-spawn": "^6.0.5",
|
||||||
|
"debug": "^4.0.1",
|
||||||
|
"doctrine": "^2.1.0",
|
||||||
|
"eslint-scope": "^4.0.0",
|
||||||
|
"eslint-utils": "^1.3.1",
|
||||||
|
"eslint-visitor-keys": "^1.0.0",
|
||||||
|
"espree": "^4.0.0",
|
||||||
|
"esquery": "^1.0.1",
|
||||||
|
"esutils": "^2.0.2",
|
||||||
|
"file-entry-cache": "^2.0.0",
|
||||||
|
"functional-red-black-tree": "^1.0.1",
|
||||||
|
"glob": "^7.1.2",
|
||||||
|
"globals": "^11.7.0",
|
||||||
|
"ignore": "^4.0.6",
|
||||||
|
"imurmurhash": "^0.1.4",
|
||||||
|
"inquirer": "^6.1.0",
|
||||||
|
"is-resolvable": "^1.1.0",
|
||||||
|
"js-yaml": "^3.12.0",
|
||||||
|
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||||
|
"levn": "^0.3.0",
|
||||||
|
"lodash": "^4.17.5",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
|
"mkdirp": "^0.5.1",
|
||||||
|
"natural-compare": "^1.4.0",
|
||||||
|
"optionator": "^0.8.2",
|
||||||
|
"path-is-inside": "^1.0.2",
|
||||||
|
"pluralize": "^7.0.0",
|
||||||
|
"progress": "^2.0.0",
|
||||||
|
"regexpp": "^2.0.1",
|
||||||
|
"require-uncached": "^1.0.3",
|
||||||
|
"semver": "^5.5.1",
|
||||||
|
"strip-ansi": "^4.0.0",
|
||||||
|
"strip-json-comments": "^2.0.1",
|
||||||
|
"table": "^5.0.2",
|
||||||
|
"text-table": "^0.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"eslint-scope": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"esrecurse": "^4.1.0",
|
||||||
|
"estraverse": "^4.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"eslint-utils": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"eslint-visitor-keys": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"espree": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"acorn": "^6.0.2",
|
||||||
|
"acorn-jsx": "^5.0.0",
|
||||||
|
"eslint-visitor-keys": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"esprima": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"esquery": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"estraverse": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"esrecurse": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"estraverse": "^4.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"estraverse": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
|
||||||
|
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"esutils": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
|
||||||
|
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"external-editor": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chardet": "^0.7.0",
|
||||||
|
"iconv-lite": "^0.4.24",
|
||||||
|
"tmp": "^0.0.33"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fast-deep-equal": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"fast-json-stable-stringify": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"fast-levenshtein": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||||
|
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"figures": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"escape-string-regexp": "^1.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"file-entry-cache": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"flat-cache": "^1.2.1",
|
||||||
|
"object-assign": "^4.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flat-cache": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"circular-json": "^0.3.1",
|
||||||
|
"graceful-fs": "^4.1.2",
|
||||||
|
"rimraf": "~2.6.2",
|
||||||
|
"write": "^0.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fs.realpath": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"functional-red-black-tree": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"glob": {
|
||||||
|
"version": "7.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
|
||||||
|
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fs.realpath": "^1.0.0",
|
||||||
|
"inflight": "^1.0.4",
|
||||||
|
"inherits": "2",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"path-is-absolute": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"version": "11.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz",
|
||||||
|
"integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"graceful-fs": {
|
||||||
|
"version": "4.1.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
|
||||||
|
"integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"has-flag": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"iconv-lite": {
|
||||||
|
"version": "0.4.24",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
|
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ignore": {
|
||||||
|
"version": "4.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||||
|
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"imurmurhash": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||||
|
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"inflight": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
|
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
|
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"inquirer": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-escapes": "^3.0.0",
|
||||||
|
"chalk": "^2.0.0",
|
||||||
|
"cli-cursor": "^2.1.0",
|
||||||
|
"cli-width": "^2.0.0",
|
||||||
|
"external-editor": "^3.0.0",
|
||||||
|
"figures": "^2.0.0",
|
||||||
|
"lodash": "^4.17.10",
|
||||||
|
"mute-stream": "0.0.7",
|
||||||
|
"run-async": "^2.2.0",
|
||||||
|
"rxjs": "^6.1.0",
|
||||||
|
"string-width": "^2.1.0",
|
||||||
|
"strip-ansi": "^4.0.0",
|
||||||
|
"through": "^2.3.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-fullwidth-code-point": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"is-promise": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
|
||||||
|
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"is-resolvable": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"isexe": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"js-tokens": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"js-yaml": {
|
||||||
|
"version": "3.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
|
||||||
|
"integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"argparse": "^1.0.7",
|
||||||
|
"esprima": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"json-schema-traverse": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"json-stable-stringify-without-jsonify": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"levn": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
|
||||||
|
"integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"prelude-ls": "~1.1.2",
|
||||||
|
"type-check": "~0.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lodash": {
|
||||||
|
"version": "4.17.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||||
|
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"mimic-fn": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"minimatch": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minimist": {
|
||||||
|
"version": "0.0.8",
|
||||||
|
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||||
|
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"mkdirp": {
|
||||||
|
"version": "0.5.1",
|
||||||
|
"resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||||
|
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"minimist": "0.0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"mute-stream": {
|
||||||
|
"version": "0.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
|
||||||
|
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"natural-compare": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||||
|
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"nice-try": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"object-assign": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
|
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"onetime": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"mimic-fn": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"optionator": {
|
||||||
|
"version": "0.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
|
||||||
|
"integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"deep-is": "~0.1.3",
|
||||||
|
"fast-levenshtein": "~2.0.4",
|
||||||
|
"levn": "~0.3.0",
|
||||||
|
"prelude-ls": "~1.1.2",
|
||||||
|
"type-check": "~0.3.2",
|
||||||
|
"wordwrap": "~1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"os-tmpdir": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"path-is-absolute": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"path-is-inside": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"path-key": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"pluralize": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"prelude-ls": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
|
||||||
|
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"progress": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"punycode": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"regexpp": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"require-uncached": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"caller-path": "^0.1.0",
|
||||||
|
"resolve-from": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resolve-from": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"restore-cursor": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"onetime": "^2.0.0",
|
||||||
|
"signal-exit": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rimraf": {
|
||||||
|
"version": "2.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
|
||||||
|
"integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"glob": "^7.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"run-async": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
|
||||||
|
"integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-promise": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rxjs": {
|
||||||
|
"version": "6.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz",
|
||||||
|
"integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
|
||||||
|
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"shebang-command": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
|
||||||
|
"integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"shebang-regex": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"shebang-regex": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"signal-exit": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
||||||
|
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"slice-ansi": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-fullwidth-code-point": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sprintf-js": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"string-width": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-fullwidth-code-point": "^2.0.0",
|
||||||
|
"strip-ansi": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"strip-ansi": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||||
|
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-regex": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"strip-json-comments": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"supports-color": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"table": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/table/-/table-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ajv": "^6.5.3",
|
||||||
|
"lodash": "^4.17.10",
|
||||||
|
"slice-ansi": "1.0.0",
|
||||||
|
"string-width": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"text-table": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||||
|
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"through": {
|
||||||
|
"version": "2.3.8",
|
||||||
|
"resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
|
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"tmp": {
|
||||||
|
"version": "0.0.33",
|
||||||
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||||
|
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"os-tmpdir": "~1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"type-check": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
|
||||||
|
"integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"prelude-ls": "~1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uri-js": {
|
||||||
|
"version": "4.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||||
|
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"punycode": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"which": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"isexe": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wordwrap": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"write": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
|
||||||
|
"integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"mkdirp": "^0.5.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "i18n",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Simple Internationalization provider for JavaScript",
|
||||||
|
"main": "i18n.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/Xaymar/i18n-js.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"i18n",
|
||||||
|
"internationalization",
|
||||||
|
"translation",
|
||||||
|
"translate"
|
||||||
|
],
|
||||||
|
"author": "Michael Fabian 'Xaymar' Dirks <info@xaymar.com>",
|
||||||
|
"license": "AGPL-3.0",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/Xaymar/i18n-js/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/Xaymar/i18n-js#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^5.9.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,52 @@
|
|||||||
# I18n (JavaScript)
|
# I18n (JavaScript)
|
||||||
|
Very simple JavaScript library for handling translations. Supports Node.js, Electron and other JavaScript based code runners.
|
||||||
|
|
||||||
Simple JavaScript library to load translation data in the browser and apply translations automatically to a full page.
|
# Features:
|
||||||
|
* Simple modern API with Promises and full Documentation.
|
||||||
|
* Support for languages with more than one base language and per language base language overrides.
|
||||||
|
* Cached translation chains for quick and recursion free key lookups.
|
||||||
|
|
||||||
|
# Maintenance, Donations, etc.
|
||||||
|
This codes maintenance is funded through [Patreon](https://www.patreon.com/Xaymar). If you think this code is useful to you, consider donating a few bucks.
|
||||||
|
|
||||||
# License
|
# License
|
||||||
Licensed under Affero GNU GPLv3. See license.txt for more information.
|
Licensed under Affero GNU GPLv3. See license.txt for more information.
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
`i18n.js` is fully documented using JSDoc, a format IDEs should be able to display. If in any case your IDE is not showing this information, your first reference should be `i18n.js`, not this readme.
|
||||||
|
|
||||||
|
### I18n
|
||||||
|
The class that contains all the translation data.
|
||||||
|
|
||||||
|
##### constructor(string defaultLanguage, string baseLanguageKey = '\_base')
|
||||||
|
Creates a new I18n object when called with `new I18n('mylanguage')`. Will set up internal structures and variables for later use. Throws exceptions.
|
||||||
|
|
||||||
|
##### bool hasLanguage(string language)
|
||||||
|
Check if a language is known to this I18n object. Returns true if known. Throws exceptions.
|
||||||
|
|
||||||
|
##### createLanguage(string language)
|
||||||
|
Create a new empty language, or replaces a loaded one with an empty one. Throws exceptions.
|
||||||
|
|
||||||
|
##### Promise(string) loadLanguage(string language, File|Blob|object|string data, string encoding = 'utf-8')
|
||||||
|
Load a language from a File, Blob, object or string as JSON data, and store it as the language. Returns a Promise, which will resolve once it is done loading and parsing and the result will contain the loaded language name. Throws exceptions.
|
||||||
|
|
||||||
|
##### Promise(string) saveLanguage(string language)
|
||||||
|
Save a language to a string as JSON data. Returns a Promise which will resolve with the JSON data string once done. Modifying the language before the returned Promise is done can result in corrupt data. Throws exceptions.
|
||||||
|
|
||||||
|
##### destroyLanguage(string language)
|
||||||
|
Destroy a language, thus clearing any references to data in it. Throws exceptions.
|
||||||
|
|
||||||
|
##### bool clearKey(string language, string key)
|
||||||
|
Remove a key from a language. Returns true if the key was removed. Throws exceptions.
|
||||||
|
|
||||||
|
##### bool setKey(string language, string key, any value, bool force = true)
|
||||||
|
Set a key in a language to a new value, optionally overwriting the previous content (defaults to true). Returns true if successful. Throws exceptions.
|
||||||
|
|
||||||
|
##### any getKey(string language, string key)
|
||||||
|
Get the value of a key in a language. Returns the value of the key if known, otherwise throws an exception.
|
||||||
|
|
||||||
|
##### string translate(string key, string language)
|
||||||
|
Translate a given key to the language selected. Returns the translated string or the original key if it was not found. Throws exceptions.
|
||||||
|
|
||||||
|
##### Promise domTranslate(string language, string property = 'data-i18n', function resolver = string function(string language, string key, Node element), function applier = bool function(string language, string key, string translated, Node element))
|
||||||
|
Automatically translate all elements in the current DOM which have the attribute `property`. Returns a Promise which resolves when the translation is complete. Throws exceptions.
|
||||||
|
|||||||
Reference in New Issue
Block a user