CoastalCommitsPastes/server/node_modules/strong-globalize/lib/globalize.js
2022-03-06 16:46:59 -08:00

533 lines
No EOL
19 KiB
JavaScript

"use strict";
// Copyright IBM Corp. 2018,2020. All Rights Reserved.
// Node module: strong-globalize
// This file is licensed under the Artistic License 2.0.
// License text available at https://opensource.org/licenses/Artistic-2.0
Object.defineProperty(exports, "__esModule", { value: true });
exports.logPersistent = exports.setPersistentLogging = exports.consoleEnabled = exports.loadGlobalize = exports.formatCurrency = exports.formatDate = exports.formatNumber = exports.silly = exports.input = exports.verbose = exports.prompt = exports.data = exports.help = exports.log = exports.info = exports.warn = exports.debug = exports.informational = exports.notice = exports.warning = exports.error = exports.critical = exports.alert = exports.emergency = exports.rfc5424 = exports.packMessage = exports.formatJson = exports.formatMessage = exports.setAppLanguages = exports.setDefaultLanguage = exports.STRONGLOOP_GLB = exports.m = exports.t = exports.n = exports.d = exports.c = exports.setRootDir = void 0;
//tslint:disable:no-any
const assert = require("assert");
const debugModule = require("debug");
const fs = require("fs");
const Globalize = require("globalize");
const yamljs_1 = require("yamljs");
const config_1 = require("./config");
const helper = require("./helper");
const helper_1 = require("./helper");
const dbg = debugModule('strong-globalize');
const osLocale = require('os-locale');
const MapCache = require('lodash/_MapCache');
const md5 = require('md5');
const memoize = require('lodash/memoize');
const pathUtil = require('path');
const util = require('util');
var helper_2 = require("./helper");
Object.defineProperty(exports, "setRootDir", { enumerable: true, get: function () { return helper_2.setRootDir; } });
exports.c = formatCurrency;
exports.d = formatDate;
exports.n = formatNumber;
exports.t = formatMessage;
exports.m = formatMessage;
var config_2 = require("./config");
Object.defineProperty(exports, "STRONGLOOP_GLB", { enumerable: true, get: function () { return config_2.STRONGLOOP_GLB; } });
/**
* StrongLoop Defaults
*/
const SL_DEFAULT_DATETIME = { datetime: 'medium' };
const SL_DEFAULT_NUMBER = { round: 'floor' };
const SL_DEFAULT_CURRENCY = { style: 'name' };
const OS_LANG = osLanguage();
let MY_APP_LANG = process.env.STRONGLOOP_GLOBALIZE_APP_LANGUAGE;
MY_APP_LANG = helper.isSupportedLanguage(MY_APP_LANG) ? MY_APP_LANG : null;
function osLanguage() {
const locale = osLocale.sync();
const lang = locale.substring(0, 2);
if (helper.isSupportedLanguage(lang))
return lang;
if (lang === 'zh') {
const region = locale.substring(3);
if (region === 'CN')
return 'zh-Hans';
if (region === 'TW')
return 'zh-Hant';
if (region === 'Hans')
return 'zh-Hans';
if (region === 'Hant')
return 'zh-Hant';
}
}
/**
* setDefaultLanguage
*
* @param {string} (optional, default: `'en'`) Language ID.
* It tries to use OS language, then falls back to 'en'
*/
function setDefaultLanguage(lang) {
if (lang)
lang = helper_1.getLangAlias(lang);
lang = helper.isSupportedLanguage(lang) ? lang : undefined;
lang = lang || MY_APP_LANG || OS_LANG || helper.ENGLISH;
loadGlobalize(lang);
if (lang !== helper.ENGLISH) {
loadGlobalize(helper.ENGLISH);
}
config_1.STRONGLOOP_GLB.locale(lang);
config_1.STRONGLOOP_GLB.DEFAULT_LANG = lang;
return lang;
}
exports.setDefaultLanguage = setDefaultLanguage;
/**
* setAppLanguages
*
* @param {string} (optional, default: `[...]`) [].
* Sets the supported languages for the application.
* These should be a subset of the languages within the intl
* directory.
*
* If no argument is passed, the function uses the contents of
* the intl directory to determine the application languages.
*
*/
function setAppLanguages(langs) {
langs = langs || readAppLanguagesSync() || [];
config_1.STRONGLOOP_GLB.APP_LANGS = langs;
return langs;
}
exports.setAppLanguages = setAppLanguages;
function readAppLanguagesSync() {
try {
const langs = fs.readdirSync(pathUtil.join(config_1.STRONGLOOP_GLB.MASTER_ROOT_DIR, 'intl'));
return langs;
}
catch (ex) {
return null;
}
}
/**
* Globalize.formatMessage wrapper returns a string.
*
* @param {string} path The message key
* @param {object} variables List of placeholder key and content value pair.
* @param {string} variables.<phXXX> The placeholder key.
* @param {string} variables.<string> The content value.
* If the system locale is undefined, falls back to 'en'
*/
function formatMessage(path, variables, lang) {
assert(path);
if (!config_1.STRONGLOOP_GLB.DEFAULT_LANG)
setDefaultLanguage();
let message = path;
if (helper.hashKeys(path)) {
if (!config_1.STRONGLOOP_GLB.getHash) {
config_1.STRONGLOOP_GLB.getHash = memoize(md5);
}
path = config_1.STRONGLOOP_GLB.getHash(path);
}
lang = lang || config_1.STRONGLOOP_GLB.DEFAULT_LANG;
dbg('~~~ lang = %s %s %j %s', lang, path, variables, __filename);
const trailer = helper.getTrailerAfterDot(path);
if (trailer === 'json' || trailer === 'yml' || trailer === 'yaml') {
const fullPath = pathUtil.join(helper.getRootDir(), path);
return formatJson(fullPath, JSON.parse(variables), lang);
}
function formatMsgInline(language) {
const g = config_1.STRONGLOOP_GLB.bundles[language];
if (!config_1.STRONGLOOP_GLB.formatters) {
config_1.STRONGLOOP_GLB.formatters = new MapCache();
}
const allFormatters = config_1.STRONGLOOP_GLB.formatters;
let langFormatters;
if (allFormatters.has(language)) {
langFormatters = allFormatters.get(language);
}
else {
langFormatters = new MapCache();
allFormatters.set(language, langFormatters);
}
if (langFormatters.has(path))
return langFormatters.get(path)(variables || {});
const format = g.messageFormatter(path);
langFormatters.set(path, format);
return format(variables || {});
}
try {
message = formatMsgInline(lang);
}
catch (e) {
if (lang === helper.ENGLISH) {
message = sanitizeMsg(message, variables);
dbg('*** %s not found for %s. Fall back to: "%s" *** %s', path, lang, message, e);
}
else {
dbg('*** %s for %s not localized. Fall back to English. *** %s', path, lang, e);
try {
message = formatMsgInline(helper.ENGLISH);
}
catch (e) {
message = sanitizeMsg(message, variables);
dbg('*** %s not found for %s. Fall back to: "%s" *** %s', path, lang, message, e);
}
}
}
if (config_1.STRONGLOOP_GLB.PSEUDO_LOC_PREAMBLE) {
message = config_1.STRONGLOOP_GLB.PSEUDO_LOC_PREAMBLE + message;
}
return message;
}
exports.formatMessage = formatMessage;
function formatJson(fullPath, variables, lang) {
assert(fullPath === pathUtil.resolve(helper.getRootDir(), fullPath), '*** full path is required to format json/yaml file: ' + fullPath);
const fileType = helper.getTrailerAfterDot(fullPath);
let jsonData = null;
try {
const contentStr = fs.readFileSync(fullPath, 'utf8');
if (fileType === 'json')
jsonData = JSON.parse(contentStr);
if (fileType === 'yml' || fileType === 'yaml')
jsonData = yamljs_1.parse(contentStr);
}
catch (_e) {
return '*** read failure: ' + fullPath;
}
const msgs = helper.scanJson(variables, jsonData);
const transMsgs = [];
msgs.forEach(function (msg) {
const transMsg = formatMessage(msg, undefined, lang);
transMsgs.push(transMsg);
});
helper.replaceJson(variables, jsonData, transMsgs);
return jsonData;
}
exports.formatJson = formatJson;
function sanitizeMsg(message, variables) {
message = message.replace(/}}/g, '').replace(/{{/g, '');
if (typeof variables === 'string' ||
(Array.isArray(variables) && variables.length > 0)) {
const sanitizedMsg = message.replace(/%[sdj]/g, '%s');
message = util.format.apply(util, [sanitizedMsg].concat(variables));
}
return message;
}
function packMessage(args, fn, withOriginalMsg, lang) {
const path = args[0];
const percentInKey = helper.percent(path);
const txtWithTwoOrMoreArgs = helper.getTrailerAfterDot(path) === 'txt' && args.length > 2;
// If it comes from *.txt, there are no percent in the path,
// but there can be one or more %s in the message value.
const variables = percentInKey
? helper.mapArgs(path, args)
: txtWithTwoOrMoreArgs
? helper.repackArgs(args, 1)
: args[1];
let message = formatMessage(path, variables, lang);
if (withOriginalMsg)
message = {
language: lang,
message: message,
orig: path,
vars: variables,
};
if (fn)
return fn(message);
return message;
}
exports.packMessage = packMessage;
/* RFC 5424 Syslog Message Severities
* 0 Emergency: system is unusable
* 1 Alert: action must be taken immediately
* 2 Critical: critical conditions
* 3 Error: error conditions
* 4 Warning: warning conditions
* 5 Notice: normal but significant condition
* 6 Informational: informational messages
* 7 Debug: debug-level messages
*/
function rfc5424(level, args, print, lang) {
return packMessage(args, (msg) => {
logPersistent(level, msg);
if (consoleEnabled())
print(msg.message);
return msg;
}, true, lang);
}
exports.rfc5424 = rfc5424;
function myError(...args) {
const msg = packMessage(args, null, true);
logPersistent('error', msg);
return new Error(msg.message);
}
module.exports.Error = myError;
// RFC 5424 Syslog Message Severities
function emergency(...args) {
return rfc5424('emergency', args, console.error);
}
exports.emergency = emergency;
function alert(...args) {
return rfc5424('alert', args, console.error);
}
exports.alert = alert;
function critical(...args) {
return rfc5424('critical', args, console.error);
}
exports.critical = critical;
function error(...args) {
return rfc5424('error', args, console.error);
}
exports.error = error;
function warning(...args) {
return rfc5424('warning', args, console.error);
}
exports.warning = warning;
function notice(...args) {
return rfc5424('notice', args, console.log);
}
exports.notice = notice;
function informational(...args) {
return rfc5424('informational', args, console.log);
}
exports.informational = informational;
function debug(...args) {
return rfc5424('debug', args, console.log);
}
exports.debug = debug;
function warn(...args) {
return rfc5424('warn', args, console.error);
}
exports.warn = warn;
function info(...args) {
return rfc5424('info', args, console.log);
}
exports.info = info;
function log(...args) {
return rfc5424('log', args, console.log);
}
exports.log = log;
function help(...args) {
return rfc5424('help', args, console.log);
}
exports.help = help;
function data(...args) {
return rfc5424('data', args, console.log);
}
exports.data = data;
function prompt(...args) {
return rfc5424('prompt', args, console.log);
}
exports.prompt = prompt;
function verbose(...args) {
return rfc5424('verbose', args, console.log);
}
exports.verbose = verbose;
function input(...args) {
return rfc5424('input', args, console.log);
}
exports.input = input;
function silly(...args) {
return rfc5424('silly', args, console.log);
}
exports.silly = silly;
/**
* Globalize.formatNumber wrapper returns a string.
*
* @param {value} integer or float
* @param {object} The options (optional); if null, use the StrongLoop default.
* Strongly recommended to set NO options and let strong-globalize use
* the StrongLoop default for consistency across StrongLoop products.
* See https://www.npmjs.com/package/globalize#number-module
*/
function formatNumber(value, options, lang) {
assert(value);
if (!config_1.STRONGLOOP_GLB.DEFAULT_LANG)
setDefaultLanguage(lang);
lang = (lang || config_1.STRONGLOOP_GLB.DEFAULT_LANG);
options = options || SL_DEFAULT_NUMBER;
const G = config_1.STRONGLOOP_GLB.bundles[lang];
let msg = null;
try {
msg = G.formatNumber(value, options);
}
catch (e) {
msg = value.toString();
dbg('*** formatNumber error: value:%s', msg);
}
return msg;
}
exports.formatNumber = formatNumber;
/**
* Globalize.formatDate wrapper returns a string.
*
* @param {Date object} such as new Date()
* @param {object} The options (optional); if null, use the StrongLoop default.
* Strongly recommended to set NO options and let strong-globalize use
* the StrongLoop default for consistency across StrongLoop products.
* See https://www.npmjs.com/package/globalize#date-module
*/
function formatDate(value, options, lang) {
assert(value);
if (!config_1.STRONGLOOP_GLB.DEFAULT_LANG)
setDefaultLanguage(lang);
lang = (lang || config_1.STRONGLOOP_GLB.DEFAULT_LANG);
options = options || SL_DEFAULT_DATETIME;
const G = config_1.STRONGLOOP_GLB.bundles[lang];
let msg = null;
try {
msg = G.formatDate(value, options);
}
catch (e) {
msg = value.toString();
dbg('*** formatDate error: value:%s', msg);
}
return msg;
}
exports.formatDate = formatDate;
/**
* Globalize.formatCurrency wrapper returns a string.
*
* @param {value} integer or float
* @param {string} three-letter currency symbol, ISO 4217 Currency Code
* @param {object} The options (optional); if null, use the StrongLoop default.
* Strongly recommended to set NO options and let strong-globalize use
* the StrongLoop default for consistency across StrongLoop products.
* See https://www.npmjs.com/package/globalize#curency-module
*/
function formatCurrency(value, currencySymbol, options, lang) {
assert(value && currencySymbol);
if (!config_1.STRONGLOOP_GLB.DEFAULT_LANG)
setDefaultLanguage(lang);
lang = lang || config_1.STRONGLOOP_GLB.DEFAULT_LANG;
options = options || SL_DEFAULT_CURRENCY;
const G = config_1.STRONGLOOP_GLB.bundles[lang];
let msg = null;
try {
msg = G.formatCurrency(value, currencySymbol, options);
}
catch (e) {
msg = currencySymbol.toString() + value.toString();
dbg('*** formatCurrency error: value:%s, currencySymbol:%s', value, currencySymbol);
}
return msg;
}
exports.formatCurrency = formatCurrency;
function loadGlobalize(lang, enumerateNodeModules) {
assert(helper.isSupportedLanguage(lang), 'Not supported: ' + lang);
if (!config_1.STRONGLOOP_GLB.versionSG) {
const versionSG = helper.getPackageVersion(pathUtil.join(__dirname, '..'));
const versionG = helper.getPackageVersion(pathUtil.join(__dirname, '..', 'node_modules', 'globalize'));
Object.assign(config_1.STRONGLOOP_GLB, {
versionSG: versionSG,
versionG: versionG,
bundles: {},
formatters: new MapCache(),
getHash: memoize(md5),
load: Globalize.load,
locale: Globalize.locale,
loadMessages: Globalize.loadMessages,
DEFAULT_LANG: helper.ENGLISH,
APP_LANGS: readAppLanguagesSync(),
LOG_FN: null,
DISABLE_CONSOLE: false,
MASTER_ROOT_DIR: helper.getRootDir(),
MSG_RES_LOADED: [],
AUTO_MSG_LOADING: helper.AML_DEFAULT,
PSEUDO_LOC_PREAMBLE: process.env.STRONG_GLOBALIZE_PSEUDO_LOC_PREAMBLE || '',
});
loadCldr(helper.ENGLISH);
config_1.STRONGLOOP_GLB.bundles[helper.ENGLISH] = new Globalize(helper.ENGLISH);
config_1.STRONGLOOP_GLB.locale(helper.ENGLISH);
helper.loadMsgFromFile(helper.ENGLISH, helper.getRootDir(), enumerateNodeModules);
}
if (!(lang in config_1.STRONGLOOP_GLB.bundles)) {
loadCldr(lang);
config_1.STRONGLOOP_GLB.bundles[lang] = new Globalize(lang);
config_1.STRONGLOOP_GLB.locale(lang);
helper.loadMsgFromFile(lang, helper.getRootDir(), enumerateNodeModules);
}
return config_1.STRONGLOOP_GLB.bundles[lang];
}
exports.loadGlobalize = loadGlobalize;
function loadCldr(lang) {
assert(config_1.STRONGLOOP_GLB &&
(!config_1.STRONGLOOP_GLB.bundles || !config_1.STRONGLOOP_GLB.bundles[lang]), 'CLDR already loaded for ' + lang);
const cldrDir = pathUtil.join(__dirname, '..', 'cldr');
helper.enumerateFilesSync(cldrDir, null, ['json'], false, false, function (content, filePath) {
let cldr = null;
try {
cldr = JSON.parse(content);
}
catch (e) {
throw new Error('*** CLDR read error on ' + process.platform);
}
const cldrMain = { main: {} };
cldrMain.main[lang] = cldr.main[lang];
config_1.STRONGLOOP_GLB.load(cldrMain);
if (lang === helper.ENGLISH) {
const cldrSupplemental = { supplemental: cldr.supplemental };
config_1.STRONGLOOP_GLB.load(cldrSupplemental);
}
});
}
/**
*
* Persistent logging
*
*/
// const syslogLevels = { // RFC5424
// emerg: 0,
// alert: 1,
// crit: 2,
// error: 3,
// warning: 4,
// notice: 5,
// info: 6,
// debug: 7,
// };
// const npmLevels = {
// error: 0,
// warn: 1,
// info: 2,
// verbose: 3,
// debug: 4,
// silly: 5,
// };
function consoleEnabled() {
if (!config_1.STRONGLOOP_GLB.DEFAULT_LANG)
setDefaultLanguage();
return !config_1.STRONGLOOP_GLB.DISABLE_CONSOLE;
}
exports.consoleEnabled = consoleEnabled;
/**
*
*/
function setPersistentLogging(logFn, disableConsole) {
assert(logFn);
assert(typeof logFn === 'function');
if (!config_1.STRONGLOOP_GLB.DEFAULT_LANG)
setDefaultLanguage();
config_1.STRONGLOOP_GLB.DISABLE_CONSOLE = !!disableConsole;
try {
const message = 'StrongGlobalize persistent logging started at ' + new Date();
logFn('info', {
language: helper.ENGLISH,
message: message,
orig: message,
vars: [],
});
config_1.STRONGLOOP_GLB.LOG_FN = logFn;
}
catch (e) {
config_1.STRONGLOOP_GLB.LOG_FN = undefined;
}
}
exports.setPersistentLogging = setPersistentLogging;
function logPersistent(level = 'info', message) {
if (!config_1.STRONGLOOP_GLB.DEFAULT_LANG)
setDefaultLanguage();
if (!config_1.STRONGLOOP_GLB.LOG_FN)
return;
level = level || 'info';
if (typeof config_1.STRONGLOOP_GLB.LOG_FN === 'function') {
config_1.STRONGLOOP_GLB.LOG_FN(level, message);
}
}
exports.logPersistent = logPersistent;
//# sourceMappingURL=globalize.js.map