Move translation machinery into a separate module
This commit is contained in:
parent
dffc6fbb50
commit
f73075d20a
1
3rdparty/moment_locales.js
vendored
1
3rdparty/moment_locales.js
vendored
@ -10,6 +10,7 @@
|
|||||||
define("moment_with_locales", [
|
define("moment_with_locales", [
|
||||||
'moment', // Everything below can be removed except for moment itself.
|
'moment', // Everything below can be removed except for moment itself.
|
||||||
'moment/locale/af',
|
'moment/locale/af',
|
||||||
|
'moment/locale/ca',
|
||||||
'moment/locale/de',
|
'moment/locale/de',
|
||||||
'moment/locale/es',
|
'moment/locale/es',
|
||||||
'moment/locale/fr',
|
'moment/locale/fr',
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
smaller filesize but means that the translations you want to provide need to
|
smaller filesize but means that the translations you want to provide need to
|
||||||
be available. See the [locales_url](https://conversejs.org/docs/html/configurations.html#locales-url)
|
be available. See the [locales_url](https://conversejs.org/docs/html/configurations.html#locales-url)
|
||||||
configuration setting for more info.
|
configuration setting for more info.
|
||||||
|
- The translation machinery has now been moved to a separate module in `src/i18n.js`.
|
||||||
|
|
||||||
## 3.2.1 (2017-08-29)
|
## 3.2.1 (2017-08-29)
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ require.config({
|
|||||||
"es6-promise": "node_modules/es6-promise/dist/es6-promise.auto",
|
"es6-promise": "node_modules/es6-promise/dist/es6-promise.auto",
|
||||||
"eventemitter": "node_modules/otr/build/dep/eventemitter",
|
"eventemitter": "node_modules/otr/build/dep/eventemitter",
|
||||||
"form-utils": "src/form-utils",
|
"form-utils": "src/form-utils",
|
||||||
|
"i18n": "src/i18n",
|
||||||
"jed": "node_modules/jed/jed",
|
"jed": "node_modules/jed/jed",
|
||||||
"jquery": "node_modules/jquery/dist/jquery",
|
"jquery": "node_modules/jquery/dist/jquery",
|
||||||
"jquery.browser": "node_modules/jquery.browser/dist/jquery.browser",
|
"jquery.browser": "node_modules/jquery.browser/dist/jquery.browser",
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"es6-promise",
|
"es6-promise",
|
||||||
"lodash.noconflict",
|
"lodash.noconflict",
|
||||||
"polyfill",
|
"polyfill",
|
||||||
"jed",
|
"i18n",
|
||||||
"utils",
|
"utils",
|
||||||
"moment_with_locales",
|
"moment_with_locales",
|
||||||
"strophe",
|
"strophe",
|
||||||
@ -19,7 +19,7 @@
|
|||||||
"backbone.browserStorage",
|
"backbone.browserStorage",
|
||||||
"backbone.overview",
|
"backbone.overview",
|
||||||
], factory);
|
], factory);
|
||||||
}(this, function (sizzle, Promise, _, polyfill, Jed, utils, moment, Strophe, pluggable, Backbone) {
|
}(this, function (sizzle, Promise, _, polyfill, i18n, utils, moment, Strophe, pluggable, Backbone) {
|
||||||
|
|
||||||
/* Cannot use this due to Safari bug.
|
/* Cannot use this due to Safari bug.
|
||||||
* See https://github.com/jcbrand/converse.js/issues/196
|
* See https://github.com/jcbrand/converse.js/issues/196
|
||||||
@ -137,11 +137,11 @@
|
|||||||
* (String) message - The message to be logged.
|
* (String) message - The message to be logged.
|
||||||
* (Integer) level - The loglevel which allows for filtering of log
|
* (Integer) level - The loglevel which allows for filtering of log
|
||||||
* messages.
|
* messages.
|
||||||
*
|
*
|
||||||
* Available loglevels are 0 for 'debug', 1 for 'info', 2 for 'warn',
|
* Available loglevels are 0 for 'debug', 1 for 'info', 2 for 'warn',
|
||||||
* 3 for 'error' and 4 for 'fatal'.
|
* 3 for 'error' and 4 for 'fatal'.
|
||||||
*
|
*
|
||||||
* When using the 'error' or 'warn' loglevels, a full stacktrace will be
|
* When using the 'error' or 'warn' loglevels, a full stacktrace will be
|
||||||
* logged as well.
|
* logged as well.
|
||||||
*/
|
*/
|
||||||
if (message instanceof Error) {
|
if (message instanceof Error) {
|
||||||
@ -176,133 +176,19 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------
|
|
||||||
// Translation machinery
|
|
||||||
// ---------------------
|
|
||||||
_converse.__ = function (str) {
|
_converse.__ = function (str) {
|
||||||
/* Translate the given string based on the current locale.
|
/* Translate the given string based on the current locale.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* (String) str - The string to translate.
|
* (String) str - The string to translate.
|
||||||
*/
|
*/
|
||||||
if (_.isUndefined(Jed)) {
|
if (_.isUndefined(i18n)) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
if (_.isUndefined(_converse.jed)) {
|
return i18n.translate.apply(i18n, arguments);
|
||||||
return Jed.sprintf.apply(Jed, arguments);
|
|
||||||
}
|
|
||||||
var t = _converse.jed.translate(str);
|
|
||||||
if (arguments.length>1) {
|
|
||||||
return t.fetch.apply(t, [].slice.call(arguments, 1));
|
|
||||||
} else {
|
|
||||||
return t.fetch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function detectLocale (library_check) {
|
const __ = _converse.__;
|
||||||
/* Determine which locale is supported by the user's system as well
|
|
||||||
* as by the relevant library (e.g. converse.js or moment.js).
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* (Function) library_check - Returns a boolean indicating whether
|
|
||||||
* the locale is supported.
|
|
||||||
*/
|
|
||||||
var locale, i;
|
|
||||||
if (window.navigator.userLanguage) {
|
|
||||||
locale = isLocaleAvailable(window.navigator.userLanguage, library_check);
|
|
||||||
}
|
|
||||||
if (window.navigator.languages && !locale) {
|
|
||||||
for (i=0; i<window.navigator.languages.length && !locale; i++) {
|
|
||||||
locale = isLocaleAvailable(window.navigator.languages[i], library_check);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (window.navigator.browserLanguage && !locale) {
|
|
||||||
locale = isLocaleAvailable(window.navigator.browserLanguage, library_check);
|
|
||||||
}
|
|
||||||
if (window.navigator.language && !locale) {
|
|
||||||
locale = isLocaleAvailable(window.navigator.language, library_check);
|
|
||||||
}
|
|
||||||
if (window.navigator.systemLanguage && !locale) {
|
|
||||||
locale = isLocaleAvailable(window.navigator.systemLanguage, library_check);
|
|
||||||
}
|
|
||||||
return locale || 'en';
|
|
||||||
}
|
|
||||||
|
|
||||||
function isMomentLocale (locale) {
|
|
||||||
if (!_.isString(locale)) { return false; }
|
|
||||||
return moment.locale() !== moment.locale(locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLocale (preferred_locale, isSupportedByLibrary) {
|
|
||||||
if (_.isString(preferred_locale)) {
|
|
||||||
if (preferred_locale === 'en' || isSupportedByLibrary(preferred_locale)) {
|
|
||||||
return preferred_locale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return detectLocale(isSupportedByLibrary) || 'en';
|
|
||||||
}
|
|
||||||
|
|
||||||
function isLocaleAvailable (locale, available) {
|
|
||||||
/* Check whether the locale or sub locale (e.g. en-US, en) is supported.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* (String) locale - The locale to check for
|
|
||||||
* (Function) available - returns a boolean indicating whether the locale is supported
|
|
||||||
*/
|
|
||||||
if (available(locale)) {
|
|
||||||
return locale;
|
|
||||||
} else {
|
|
||||||
var sublocale = locale.split("-")[0];
|
|
||||||
if (sublocale !== locale && available(sublocale)) {
|
|
||||||
return sublocale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isLocaleSupported (locale) {
|
|
||||||
/* Check whether the passed in locale is supported by Converse
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* (String) locale: The given i18n locale
|
|
||||||
*/
|
|
||||||
if (!_.isString(locale)) { return false; }
|
|
||||||
return _.includes(_converse.locales, locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
function fetchTranslations (locale, locale_url) {
|
|
||||||
/* Fetch the translations for the given local at the given URL.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* (String) locale: The given i18n locale
|
|
||||||
* (String) locale_url: The URL from which the translations should be fetched
|
|
||||||
*/
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (!isLocaleSupported(locale) || locale === 'en') {
|
|
||||||
return resolve();
|
|
||||||
}
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('GET', locale_url, true);
|
|
||||||
xhr.setRequestHeader(
|
|
||||||
'Accept',
|
|
||||||
"application/json, text/javascript"
|
|
||||||
);
|
|
||||||
xhr.onload = function () {
|
|
||||||
if (xhr.status >= 200 && xhr.status < 400) {
|
|
||||||
resolve(new Jed(window.JSON.parse(xhr.responseText)));
|
|
||||||
} else {
|
|
||||||
xhr.onerror();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xhr.onerror = function () {
|
|
||||||
reject(xhr.statusText);
|
|
||||||
};
|
|
||||||
xhr.send();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// --------------------------
|
|
||||||
// END: Translation machinery
|
|
||||||
// --------------------------
|
|
||||||
|
|
||||||
|
|
||||||
const PROMISES = [
|
const PROMISES = [
|
||||||
'initialized',
|
'initialized',
|
||||||
@ -445,10 +331,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internationalization */
|
/* Localisation */
|
||||||
moment.locale(getLocale(settings.i18n, isMomentLocale));
|
if (!_.isUndefined(i18n)) {
|
||||||
_converse.locale = getLocale(settings.i18n, isLocaleSupported);
|
i18n.setLocales(settings.i18n, _converse);
|
||||||
const __ = _converse.__;
|
} else {
|
||||||
|
_converse.locale = 'en';
|
||||||
|
}
|
||||||
|
|
||||||
// Module-level variables
|
// Module-level variables
|
||||||
// ----------------------
|
// ----------------------
|
||||||
@ -2026,23 +1914,24 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!_.isUndefined(_converse.connection) &&
|
if (!_.isUndefined(_converse.connection) &&
|
||||||
_converse.connection.service === 'jasmine tests') {
|
_converse.connection.service === 'jasmine tests') {
|
||||||
|
|
||||||
finishInitialization();
|
finishInitialization();
|
||||||
return _converse;
|
return _converse;
|
||||||
|
} else if (_.isUndefined(i18n)) {
|
||||||
|
finishInitialization();
|
||||||
} else {
|
} else {
|
||||||
fetchTranslations(
|
i18n.fetchTranslations(
|
||||||
_converse.locale,
|
_converse.locale,
|
||||||
|
_converse.locales,
|
||||||
_.template(_converse.locales_url)({'locale': _converse.locale})
|
_.template(_converse.locales_url)({'locale': _converse.locale})
|
||||||
).then((jed) => {
|
).then(() => {
|
||||||
_converse.jed = jed;
|
|
||||||
finishInitialization();
|
finishInitialization();
|
||||||
}).catch((reason) => {
|
}).catch((reason) => {
|
||||||
finishInitialization();
|
finishInitialization();
|
||||||
_converse.log(reason, Strophe.LogLevel.ERROR);
|
_converse.log(reason, Strophe.LogLevel.ERROR);
|
||||||
});
|
});
|
||||||
return init_promise.promise;
|
|
||||||
}
|
}
|
||||||
|
return init_promise.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
// API methods only available to plugins
|
// API methods only available to plugins
|
||||||
|
142
src/i18n.js
Normal file
142
src/i18n.js
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
// Converse.js (A browser based XMPP chat client)
|
||||||
|
// http://conversejs.org
|
||||||
|
//
|
||||||
|
// This is the internationalization module.
|
||||||
|
//
|
||||||
|
// Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
|
||||||
|
// Licensed under the Mozilla Public License (MPLv2)
|
||||||
|
//
|
||||||
|
/*global define */
|
||||||
|
|
||||||
|
(function (root, factory) {
|
||||||
|
define([
|
||||||
|
"es6-promise",
|
||||||
|
"jed",
|
||||||
|
"lodash.noconflict",
|
||||||
|
"moment_with_locales"
|
||||||
|
], factory);
|
||||||
|
}(this, function (Promise, Jed, _, moment) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function detectLocale (library_check) {
|
||||||
|
/* Determine which locale is supported by the user's system as well
|
||||||
|
* as by the relevant library (e.g. converse.js or moment.js).
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (Function) library_check - Returns a boolean indicating whether
|
||||||
|
* the locale is supported.
|
||||||
|
*/
|
||||||
|
var locale, i;
|
||||||
|
if (window.navigator.userLanguage) {
|
||||||
|
locale = isLocaleAvailable(window.navigator.userLanguage, library_check);
|
||||||
|
}
|
||||||
|
if (window.navigator.languages && !locale) {
|
||||||
|
for (i=0; i<window.navigator.languages.length && !locale; i++) {
|
||||||
|
locale = isLocaleAvailable(window.navigator.languages[i], library_check);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (window.navigator.browserLanguage && !locale) {
|
||||||
|
locale = isLocaleAvailable(window.navigator.browserLanguage, library_check);
|
||||||
|
}
|
||||||
|
if (window.navigator.language && !locale) {
|
||||||
|
locale = isLocaleAvailable(window.navigator.language, library_check);
|
||||||
|
}
|
||||||
|
if (window.navigator.systemLanguage && !locale) {
|
||||||
|
locale = isLocaleAvailable(window.navigator.systemLanguage, library_check);
|
||||||
|
}
|
||||||
|
return locale || 'en';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMomentLocale (locale) {
|
||||||
|
return _.isString(locale) && moment.locale() === moment.locale(locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isConverseLocale (locale, supported_locales) {
|
||||||
|
return _.isString(locale) && _.includes(supported_locales, locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLocale (preferred_locale, isSupportedByLibrary) {
|
||||||
|
if (_.isString(preferred_locale)) {
|
||||||
|
if (preferred_locale === 'en' || isSupportedByLibrary(preferred_locale)) {
|
||||||
|
return preferred_locale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return detectLocale(isSupportedByLibrary) || 'en';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLocaleAvailable (locale, available) {
|
||||||
|
/* Check whether the locale or sub locale (e.g. en-US, en) is supported.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (String) locale - The locale to check for
|
||||||
|
* (Function) available - returns a boolean indicating whether the locale is supported
|
||||||
|
*/
|
||||||
|
if (available(locale)) {
|
||||||
|
return locale;
|
||||||
|
} else {
|
||||||
|
var sublocale = locale.split("-")[0];
|
||||||
|
if (sublocale !== locale && available(sublocale)) {
|
||||||
|
return sublocale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let jed_instance;
|
||||||
|
|
||||||
|
return {
|
||||||
|
|
||||||
|
setLocales (preferred_locale, _converse) {
|
||||||
|
_converse.locale = getLocale(
|
||||||
|
preferred_locale,
|
||||||
|
_.partial(isConverseLocale, _, _converse.locales)
|
||||||
|
);
|
||||||
|
moment.locale(getLocale(preferred_locale, isMomentLocale));
|
||||||
|
},
|
||||||
|
|
||||||
|
translate (str) {
|
||||||
|
if (_.isNil(jed_instance)) {
|
||||||
|
return Jed.sprintf.apply(Jed, arguments);
|
||||||
|
}
|
||||||
|
var t = jed_instance.translate(str);
|
||||||
|
if (arguments.length>1) {
|
||||||
|
return t.fetch.apply(t, [].slice.call(arguments, 1));
|
||||||
|
} else {
|
||||||
|
return t.fetch();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchTranslations (locale, supported_locales, locale_url) {
|
||||||
|
/* Fetch the translations for the given local at the given URL.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (String) locale: The given i18n locale
|
||||||
|
* (Array) supported_locales: List of locales supported
|
||||||
|
* (String) locale_url: The URL from which the translations
|
||||||
|
* should be fetched.
|
||||||
|
*/
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!isConverseLocale(locale, supported_locales) || locale === 'en') {
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', locale_url, true);
|
||||||
|
xhr.setRequestHeader(
|
||||||
|
'Accept',
|
||||||
|
"application/json, text/javascript"
|
||||||
|
);
|
||||||
|
xhr.onload = function () {
|
||||||
|
if (xhr.status >= 200 && xhr.status < 400) {
|
||||||
|
jed_instance = new Jed(window.JSON.parse(xhr.responseText));
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
xhr.onerror();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = function () {
|
||||||
|
reject(xhr.statusText);
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}));
|
@ -13,7 +13,6 @@
|
|||||||
"es6-promise",
|
"es6-promise",
|
||||||
"jquery.browser",
|
"jquery.browser",
|
||||||
"lodash.noconflict",
|
"lodash.noconflict",
|
||||||
"moment_with_locales",
|
|
||||||
"strophe",
|
"strophe",
|
||||||
], factory);
|
], factory);
|
||||||
}(this, function (
|
}(this, function (
|
||||||
@ -21,7 +20,6 @@
|
|||||||
Promise,
|
Promise,
|
||||||
jQBrowser,
|
jQBrowser,
|
||||||
_,
|
_,
|
||||||
moment,
|
|
||||||
Strophe
|
Strophe
|
||||||
) {
|
) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
Loading…
Reference in New Issue
Block a user