UNPKG

@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
"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 ? `&region=${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}&region=${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;