mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-19 16:48:42 +02:00
Current file header is : /*! showdown v 2.0.0-alpha1 - 25-09-2018 */ Official 2.0.0-alpha doesn't match neither on content nor date :( Considering date we would be at 1.8.7, but it is also quite different (and has vulnerabilities) In consequence switching to 2.0.0.
175 lines
6.1 KiB
JavaScript
175 lines
6.1 KiB
JavaScript
let shim;
|
|
class Y18N {
|
|
constructor(opts) {
|
|
// configurable options.
|
|
opts = opts || {};
|
|
this.directory = opts.directory || './locales';
|
|
this.updateFiles = typeof opts.updateFiles === 'boolean' ? opts.updateFiles : true;
|
|
this.locale = opts.locale || 'en';
|
|
this.fallbackToLanguage = typeof opts.fallbackToLanguage === 'boolean' ? opts.fallbackToLanguage : true;
|
|
// internal stuff.
|
|
this.cache = Object.create(null);
|
|
this.writeQueue = [];
|
|
}
|
|
__(...args) {
|
|
if (typeof arguments[0] !== 'string') {
|
|
return this._taggedLiteral(arguments[0], ...arguments);
|
|
}
|
|
const str = args.shift();
|
|
let cb = function () { }; // start with noop.
|
|
if (typeof args[args.length - 1] === 'function')
|
|
cb = args.pop();
|
|
cb = cb || function () { }; // noop.
|
|
if (!this.cache[this.locale])
|
|
this._readLocaleFile();
|
|
// we've observed a new string, update the language file.
|
|
if (!this.cache[this.locale][str] && this.updateFiles) {
|
|
this.cache[this.locale][str] = str;
|
|
// include the current directory and locale,
|
|
// since these values could change before the
|
|
// write is performed.
|
|
this._enqueueWrite({
|
|
directory: this.directory,
|
|
locale: this.locale,
|
|
cb
|
|
});
|
|
}
|
|
else {
|
|
cb();
|
|
}
|
|
return shim.format.apply(shim.format, [this.cache[this.locale][str] || str].concat(args));
|
|
}
|
|
__n() {
|
|
const args = Array.prototype.slice.call(arguments);
|
|
const singular = args.shift();
|
|
const plural = args.shift();
|
|
const quantity = args.shift();
|
|
let cb = function () { }; // start with noop.
|
|
if (typeof args[args.length - 1] === 'function')
|
|
cb = args.pop();
|
|
if (!this.cache[this.locale])
|
|
this._readLocaleFile();
|
|
let str = quantity === 1 ? singular : plural;
|
|
if (this.cache[this.locale][singular]) {
|
|
const entry = this.cache[this.locale][singular];
|
|
str = entry[quantity === 1 ? 'one' : 'other'];
|
|
}
|
|
// we've observed a new string, update the language file.
|
|
if (!this.cache[this.locale][singular] && this.updateFiles) {
|
|
this.cache[this.locale][singular] = {
|
|
one: singular,
|
|
other: plural
|
|
};
|
|
// include the current directory and locale,
|
|
// since these values could change before the
|
|
// write is performed.
|
|
this._enqueueWrite({
|
|
directory: this.directory,
|
|
locale: this.locale,
|
|
cb
|
|
});
|
|
}
|
|
else {
|
|
cb();
|
|
}
|
|
// if a %d placeholder is provided, add quantity
|
|
// to the arguments expanded by util.format.
|
|
const values = [str];
|
|
if (~str.indexOf('%d'))
|
|
values.push(quantity);
|
|
return shim.format.apply(shim.format, values.concat(args));
|
|
}
|
|
setLocale(locale) {
|
|
this.locale = locale;
|
|
}
|
|
getLocale() {
|
|
return this.locale;
|
|
}
|
|
updateLocale(obj) {
|
|
if (!this.cache[this.locale])
|
|
this._readLocaleFile();
|
|
for (const key in obj) {
|
|
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
this.cache[this.locale][key] = obj[key];
|
|
}
|
|
}
|
|
}
|
|
_taggedLiteral(parts, ...args) {
|
|
let str = '';
|
|
parts.forEach(function (part, i) {
|
|
const arg = args[i + 1];
|
|
str += part;
|
|
if (typeof arg !== 'undefined') {
|
|
str += '%s';
|
|
}
|
|
});
|
|
return this.__.apply(this, [str].concat([].slice.call(args, 1)));
|
|
}
|
|
_enqueueWrite(work) {
|
|
this.writeQueue.push(work);
|
|
if (this.writeQueue.length === 1)
|
|
this._processWriteQueue();
|
|
}
|
|
_processWriteQueue() {
|
|
const _this = this;
|
|
const work = this.writeQueue[0];
|
|
// destructure the enqueued work.
|
|
const directory = work.directory;
|
|
const locale = work.locale;
|
|
const cb = work.cb;
|
|
const languageFile = this._resolveLocaleFile(directory, locale);
|
|
const serializedLocale = JSON.stringify(this.cache[locale], null, 2);
|
|
shim.fs.writeFile(languageFile, serializedLocale, 'utf-8', function (err) {
|
|
_this.writeQueue.shift();
|
|
if (_this.writeQueue.length > 0)
|
|
_this._processWriteQueue();
|
|
cb(err);
|
|
});
|
|
}
|
|
_readLocaleFile() {
|
|
let localeLookup = {};
|
|
const languageFile = this._resolveLocaleFile(this.directory, this.locale);
|
|
try {
|
|
// When using a bundler such as webpack, readFileSync may not be defined:
|
|
if (shim.fs.readFileSync) {
|
|
localeLookup = JSON.parse(shim.fs.readFileSync(languageFile, 'utf-8'));
|
|
}
|
|
}
|
|
catch (err) {
|
|
if (err instanceof SyntaxError) {
|
|
err.message = 'syntax error in ' + languageFile;
|
|
}
|
|
if (err.code === 'ENOENT')
|
|
localeLookup = {};
|
|
else
|
|
throw err;
|
|
}
|
|
this.cache[this.locale] = localeLookup;
|
|
}
|
|
_resolveLocaleFile(directory, locale) {
|
|
let file = shim.resolve(directory, './', locale + '.json');
|
|
if (this.fallbackToLanguage && !this._fileExistsSync(file) && ~locale.lastIndexOf('_')) {
|
|
// attempt fallback to language only
|
|
const languageFile = shim.resolve(directory, './', locale.split('_')[0] + '.json');
|
|
if (this._fileExistsSync(languageFile))
|
|
file = languageFile;
|
|
}
|
|
return file;
|
|
}
|
|
_fileExistsSync(file) {
|
|
return shim.exists(file);
|
|
}
|
|
}
|
|
export function y18n(opts, _shim) {
|
|
shim = _shim;
|
|
const y18n = new Y18N(opts);
|
|
return {
|
|
__: y18n.__.bind(y18n),
|
|
__n: y18n.__n.bind(y18n),
|
|
setLocale: y18n.setLocale.bind(y18n),
|
|
getLocale: y18n.getLocale.bind(y18n),
|
|
updateLocale: y18n.updateLocale.bind(y18n),
|
|
locale: y18n.locale
|
|
};
|
|
}
|