@singleton-i18n/js-core-sdk
Version:
A JavaScript Singleton client library for internationalization and localization that leverage data from Singleton service. The library works both for the browser and as a Node.js module.
325 lines (324 loc) • 13.8 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CoreService = void 0;
const constants_1 = require("../constants");
const cache_1 = require("../cache");
const utils_1 = require("../utils");
const logger_1 = require("../logger");
const exceptions_1 = require("../exceptions");
const configuration_1 = require("../configuration");
class CoreService {
constructor(coreLoader, resParser) {
this.coreLoader = coreLoader;
this.resParser = resParser;
this.cacheManager = cache_1.CacheManager.createTranslationCacheManager();
this.logger = logger_1.basedLogger.create('CoreService');
}
init(config) {
const vipConfig = Object.assign(Object.assign({}, (0, configuration_1.getDefaultConfig)()), config);
this.validateConfig(vipConfig);
this.config = vipConfig;
this.config.sourceBundle = this.resetSourceBundle();
this.currentLanguage = vipConfig.language;
this.currentRegion = vipConfig.region;
this.httpOptions = vipConfig.httpOptions;
}
/**
* Load resource prior to perform callback.
* @param callback
*/
loadI18nData(callback) {
return __awaiter(this, void 0, void 0, function* () {
const scope = this.config.i18nScope ? this.config.i18nScope.join(',') : '';
// callback should be performed always
try {
// for translations
if (!this.isSourceLanguage(this.currentLanguage) && scope === '') {
return yield this.loadTranslations(this.currentLanguage);
}
// for translations and formatting patterns
if (!this.isSourceLocale(this.currentLanguage, this.currentRegion) && scope !== '') {
return yield this.loadTranslationsAndPattern(this.currentLanguage, this.currentRegion);
}
}
catch (error) {
this.logger.error('Load i18n resources failed.', error.message);
}
finally {
if (callback && typeof callback === 'function') {
callback();
}
}
/**
* Only when language or region as belew, it returns Promise with {} Object,
* on which some products might rely to handle .then() method
1. language = 'en-US'
2. language = 'en', region = 'US'
3. language = 'en'
*/
return Promise.resolve({});
});
}
validateConfig(config) {
if (!(0, utils_1.isDefined)(config.productID) || !config.productID.length) {
throw (0, exceptions_1.ParamaterError)('CoreService', 'ProductID');
}
if (!(0, utils_1.isDefined)(config.version) || !config.version.length) {
throw (0, exceptions_1.ParamaterError)('CoreService', 'Version');
}
if (!(0, utils_1.isDefined)(config.host) || !config.host.length) {
throw (0, exceptions_1.ParamaterError)('CoreService', 'Host');
}
if (!(0, utils_1.isDefined)(config.language) || !config.language.length) {
config.language = constants_1.Constants.SOURCE_LANGUAGE;
}
}
getHost() {
return this.config.host;
}
getProductID() {
return this.config.productID;
}
getVersion() {
return this.config.version;
}
getComponent() {
return this.config.component;
}
getLanguage() {
return this.currentLanguage;
}
getRegion() {
return this.currentRegion;
}
getIsPseudo() {
return this.config.isPseudo;
}
getI18nScope() {
return this.config.i18nScope;
}
getSourceBundle() {
return this.config.sourceBundle || undefined;
}
resetSourceBundle() {
if (this.config.sourceBundle && Object.keys(this.config.sourceBundle).length > 0) {
return this.config.sourceBundle;
}
if (this.config.sourceBundles) {
if (Array.isArray(this.config.sourceBundles)) {
return (0, utils_1.assign)({}, this.config.sourceBundles);
}
}
return undefined;
}
/**
* Identify the locale from specified language and region is source locale or not.
* @param language
* @param region
*/
isSourceLocale(language, region) {
return this.isSourceLanguage(language)
&& (0, utils_1.isDefined)(region)
&& region.toUpperCase() === constants_1.Constants.SOURCE_REGION ? true
: this.isSourceLanguage(language) && !(0, utils_1.isDefined)(region) ? true
: false;
}
/**
* Identify specified language is source language or not.
* @param language
*/
isSourceLanguage(language) {
return language.toLowerCase() === constants_1.Constants.SOURCE_LANGUAGE ? true
: constants_1.Constants.SOURCE_LOCALE.toLowerCase() === (0, utils_1.resolveLanguageTag)(language) ? true
: false;
}
getComponentTransUrl(language) {
if ((0, utils_1.isDefined)(this.config.i18nAssets)) {
const path = `${this.config.i18nAssets}${constants_1.Constants.L10N_ASSETS_PREFIX}${language}${constants_1.Constants.ASSETS_SUFFIX}`;
return path;
}
return this.config.host
.concat(constants_1.Constants.L10N_COMPONENT_API_ENDPOINT)
.concat('/products/' + this.config.productID)
.concat('/versions/' + this.config.version)
.concat('/locales/' + language)
.concat('/components/' + this.config.component)
.concat('?pseudo=' + this.config.isPseudo);
}
getI18nResourceUrl(language, region) {
if ((0, utils_1.isDefined)(this.config.i18nAssets)) {
const path = `${this.config.i18nAssets}${language}${constants_1.Constants.ASSETS_SUFFIX}`;
return path;
}
return this.config.host
.concat(constants_1.Constants.TRANSLATION_PATTERN)
.concat('?productName=' + this.config.productID)
.concat('&components=' + this.config.component)
.concat('&version=' + this.config.version)
.concat('&language=' + language)
.concat(region ? `®ion=${region}` : '')
.concat('&scope=' + this.config.i18nScope.join(','))
.concat('&pseudo=' + this.config.isPseudo)
.concat('&combine=' + (region ? 1 : 2));
}
/**
* return promise with processed result.
* @param language
*/
loadTranslations(language) {
const cache = this.cacheManager.lookforTranslationByComponent(this.getComponent(), language);
if (typeof cache !== 'undefined') {
return Promise.resolve(cache);
}
const componentTransUrl = this.getComponentTransUrl(language);
const promise = this.coreLoader.getI18nResource(componentTransUrl, this.httpOptions);
return promise.then((result) => {
const translations = this.resParser.getTranslations(result);
if (translations) {
this.setTranslations(language, translations);
return translations;
}
}).catch((err) => { this.logger.error('Load translations failed.', err.message); });
}
loadTranslationsAndPattern(language, region) {
const cachePattern = this.cacheManager.lookforPattern(language, region);
const cacheTranslation = this.cacheManager.lookforTranslationByComponent(this.config.component, language);
if (typeof cachePattern !== 'undefined' && typeof cacheTranslation !== 'undefined') {
return Promise.resolve({
components: [cacheTranslation],
pattern: cachePattern
});
}
const url = this.getI18nResourceUrl(language, region);
const promise = this.coreLoader.getI18nResource(url, this.httpOptions);
return promise.then((result) => {
const translations = this.resParser.getTranslations(result);
if (translations) {
this.setTranslations(language, translations);
}
const patterns = this.resParser.getPatterns(result);
if (patterns) {
this.setPatterns(patterns, language, region);
}
return result && result.data;
}).catch((err) => { this.logger.error('Load I18n Resouorce failed.', err.message); });
}
getPatternUrl(region, language) {
if ((0, utils_1.isDefined)(this.config.i18nAssets)) {
const path = `${this.config.i18nAssets}${constants_1.Constants.I18N_ASSETS_PREFIX}${region}${constants_1.Constants.ASSETS_SUFFIX}`;
return path;
}
const categories = this.config.i18nScope.join(',');
// When only set language, the language will be treated as a locale with default region.
const endpoint = (0, utils_1.isDefined)(region)
? `?language=${language}®ion=${region}`
: `/locales/${language}`;
let url = this.config.host
.concat(constants_1.Constants.I18N_API_ENDPOINT)
.concat(endpoint);
if (categories) {
const character = (0, utils_1.isDefined)(region) ? '&' : '?';
url = url.concat(character + 'scope=' + categories);
}
return url;
}
loadPatterns(region, language) {
const cache = this.cacheManager.lookforPattern(language, region);
if (typeof cache !== 'undefined') {
return Promise.resolve(cache);
}
if (!this.config.i18nScope || this.config.i18nScope.length < 1) {
return;
}
const url = this.getPatternUrl(region, language);
const getPatternPromise = this.coreLoader.getI18nResource(url, this.httpOptions);
return getPatternPromise.then((result) => {
const patterns = this.resParser.getPatterns(result);
if (patterns) {
this.setPatterns(patterns, language, region);
return patterns;
}
}).catch((err) => { this.logger.error('Load formatting patterns failed.', err.message); });
}
getSupportedLanguagesUrl(displayLang) {
let url = this.config.host
.concat(constants_1.Constants.L10N_LOCAL_API_ENDPOINT)
.concat('/supportedLanguageList?')
.concat('productName=' + this.config.productID)
.concat('&version=' + this.config.version);
if (displayLang) {
url = `${url}&displayLanguage=${displayLang}`;
}
return url;
}
getSupportedLanguages(displayLang) {
const requestUrl = this.getSupportedLanguagesUrl(displayLang);
const promise = this.coreLoader.getI18nResource(requestUrl, this.httpOptions).then((result) => {
const languages = this.resParser.getSupportedLanguages(result);
return languages;
}).catch((err) => {
this.logger.error(err.message);
});
return promise;
}
getSupportedRegionsUrl(language) {
const url = this.config.host
.concat(constants_1.Constants.L10N_LOCAL_API_ENDPOINT)
.concat('/regionList?')
.concat('supportedLanguageList=' + language);
return url;
}
getSupportedRegions(language) {
if (!(0, utils_1.isDefined)(language)) {
throw (0, exceptions_1.ParamaterError)('CoreService', 'language');
}
const supportedRegionsUrl = this.getSupportedRegionsUrl(language);
const promise = this.coreLoader.getI18nResource(supportedRegionsUrl, this.httpOptions).then((result) => {
const regions = this.resParser.getSupportedRegions(result);
return regions;
}).catch((err) => {
this.logger.error(err.message);
});
return promise;
}
setTranslations(language, translations) {
if (!(0, utils_1.isDefined)(language)) {
throw (0, exceptions_1.ParamaterError)('setTranslation', 'language');
}
if (!(0, utils_1.isDefined)(translations)) {
return;
}
this.cacheManager.addTranslationByComponent(this.getComponent(), this.currentLanguage, translations);
}
setPatterns(patterns, language, region) {
if (!(0, utils_1.isDefined)(language)) {
throw (0, exceptions_1.ParamaterError)('setPattern', 'language');
}
if (!(0, utils_1.isDefined)(patterns)) {
return;
}
this.cacheManager.addPatternByLocale(patterns, language, region);
}
setCurrentLanguage(language) {
this.currentLanguage = language;
}
setCurrentRegion(region) {
this.currentRegion = region;
}
getCurrentLanguage() {
return this.currentLanguage ? this.currentLanguage : undefined;
}
getCurrentRegion() {
return this.currentRegion ? this.currentRegion : undefined;
}
}
exports.CoreService = CoreService;