1e484b35bSopenharmony_ci/* 2e484b35bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 3e484b35bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e484b35bSopenharmony_ci * you may not use this file except in compliance with the License. 5e484b35bSopenharmony_ci * You may obtain a copy of the License at 6e484b35bSopenharmony_ci * 7e484b35bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e484b35bSopenharmony_ci * 9e484b35bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e484b35bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e484b35bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e484b35bSopenharmony_ci * See the License for the specific language governing permissions and 13e484b35bSopenharmony_ci * limitations under the License. 14e484b35bSopenharmony_ci */ 15e484b35bSopenharmony_ci 16e484b35bSopenharmony_ciimport { 17e484b35bSopenharmony_ci isNull, 18e484b35bSopenharmony_ci getValue, 19e484b35bSopenharmony_ci Log 20e484b35bSopenharmony_ci} from '../../../utils/index'; 21e484b35bSopenharmony_ci 22e484b35bSopenharmony_ciinterface I18nConstructor { 23e484b35bSopenharmony_ci new(options: object): I18n; 24e484b35bSopenharmony_ci} 25e484b35bSopenharmony_ci 26e484b35bSopenharmony_ciexport interface I18nInterface { 27e484b35bSopenharmony_ci instance?: { I18n: I18nConstructor }; 28e484b35bSopenharmony_ci} 29e484b35bSopenharmony_ci 30e484b35bSopenharmony_ciinterface VMInterface { 31e484b35bSopenharmony_ci $t: Function; 32e484b35bSopenharmony_ci $tc: Function; 33e484b35bSopenharmony_ci _i18n: Function; 34e484b35bSopenharmony_ci} 35e484b35bSopenharmony_ci 36e484b35bSopenharmony_ciconst instances = {}; 37e484b35bSopenharmony_ci 38e484b35bSopenharmony_ci/** 39e484b35bSopenharmony_ci * This class provide internationalization support. 40e484b35bSopenharmony_ci */ 41e484b35bSopenharmony_ciclass I18n { 42e484b35bSopenharmony_ci public locale: string; 43e484b35bSopenharmony_ci public messages: any; 44e484b35bSopenharmony_ci 45e484b35bSopenharmony_ci constructor(options) { 46e484b35bSopenharmony_ci this.locale = options.locale || language; 47e484b35bSopenharmony_ci this.messages = options.messages; 48e484b35bSopenharmony_ci } 49e484b35bSopenharmony_ci 50e484b35bSopenharmony_ci /** 51e484b35bSopenharmony_ci * Provide the '$t' method to import simple resources. 52e484b35bSopenharmony_ci * @param {string} path - The path of language resources which to be translated. 53e484b35bSopenharmony_ci * @param {*} [params] - The values of placeholder. 54e484b35bSopenharmony_ci * @return {*} The translated result. 55e484b35bSopenharmony_ci */ 56e484b35bSopenharmony_ci public $t(path: string, params?: any): any { 57e484b35bSopenharmony_ci if (typeof path !== 'string') { 58e484b35bSopenharmony_ci Log.warn(`Invalid parameter type: The type of 'path' should be string, not ${typeof path}.`); 59e484b35bSopenharmony_ci return; 60e484b35bSopenharmony_ci } 61e484b35bSopenharmony_ci if (!this._hasMessage(this.messages)) { 62e484b35bSopenharmony_ci return path; 63e484b35bSopenharmony_ci } 64e484b35bSopenharmony_ci let value = this._getMessage(this.messages, path); 65e484b35bSopenharmony_ci if (isNull(value)) { 66e484b35bSopenharmony_ci return path; 67e484b35bSopenharmony_ci } 68e484b35bSopenharmony_ci if (Object.prototype.toString.call(value) === '[object Object]' || 69e484b35bSopenharmony_ci Object.prototype.toString.call(value) === '[object Array]') { 70e484b35bSopenharmony_ci return value; 71e484b35bSopenharmony_ci } 72e484b35bSopenharmony_ci value = this._translate(path, value, params); 73e484b35bSopenharmony_ci return value; 74e484b35bSopenharmony_ci } 75e484b35bSopenharmony_ci 76e484b35bSopenharmony_ci /** 77e484b35bSopenharmony_ci * Provide the '$tc' method to import singular and plural resources. 78e484b35bSopenharmony_ci * @param {string} path - The path of language resources which to be translated. 79e484b35bSopenharmony_ci * @param {number} [count] - The number which to be translated. 80e484b35bSopenharmony_ci * @return {*} The translated result. 81e484b35bSopenharmony_ci */ 82e484b35bSopenharmony_ci public $tc(path: string, count?: number): any { 83e484b35bSopenharmony_ci if (typeof path !== 'string') { 84e484b35bSopenharmony_ci Log.warn(`Invalid parameter type: The type of 'path' should be string, not ${typeof path}.`); 85e484b35bSopenharmony_ci return; 86e484b35bSopenharmony_ci } 87e484b35bSopenharmony_ci if (typeof count !== 'number' && !isNull(count)) { 88e484b35bSopenharmony_ci Log.warn(`Invalid parameter type: The type of 'count' should be number, not ${typeof count}.`); 89e484b35bSopenharmony_ci return; 90e484b35bSopenharmony_ci } 91e484b35bSopenharmony_ci if (!this._hasMessage(this.messages)) { 92e484b35bSopenharmony_ci return path; 93e484b35bSopenharmony_ci } 94e484b35bSopenharmony_ci let value = this._getMessage(this.messages, path); 95e484b35bSopenharmony_ci if (isNull(value)) { 96e484b35bSopenharmony_ci return path; 97e484b35bSopenharmony_ci } 98e484b35bSopenharmony_ci if (isNull(count)) { 99e484b35bSopenharmony_ci count = 1; 100e484b35bSopenharmony_ci } 101e484b35bSopenharmony_ci value = this._getChoice(count, path, value); 102e484b35bSopenharmony_ci value = this._translate(path, value, count); 103e484b35bSopenharmony_ci return value; 104e484b35bSopenharmony_ci } 105e484b35bSopenharmony_ci 106e484b35bSopenharmony_ci /** 107e484b35bSopenharmony_ci * Extend _i18n to Vm. 108e484b35bSopenharmony_ci * @param {VMInterface} Vm - The Vm. 109e484b35bSopenharmony_ci */ 110e484b35bSopenharmony_ci public extend(Vm: VMInterface): void { 111e484b35bSopenharmony_ci Object.defineProperty(Vm, '_i18n', { 112e484b35bSopenharmony_ci configurable: true, 113e484b35bSopenharmony_ci enumerable: true, 114e484b35bSopenharmony_ci get: function proxyGetter() { 115e484b35bSopenharmony_ci return this.i18n ? this.i18n : global.aceapp.i18n; 116e484b35bSopenharmony_ci } 117e484b35bSopenharmony_ci }); 118e484b35bSopenharmony_ci Vm.$t = function(path, params) { 119e484b35bSopenharmony_ci const i18n = this._i18n; 120e484b35bSopenharmony_ci return i18n.$t(path, params); 121e484b35bSopenharmony_ci }; 122e484b35bSopenharmony_ci Vm.$tc = function(path, count) { 123e484b35bSopenharmony_ci const i18n = this._i18n; 124e484b35bSopenharmony_ci return i18n.$tc(path, count); 125e484b35bSopenharmony_ci }; 126e484b35bSopenharmony_ci } 127e484b35bSopenharmony_ci 128e484b35bSopenharmony_ci private _hasMessage(message: object[]): boolean { 129e484b35bSopenharmony_ci if (!message || message.length === 0) { 130e484b35bSopenharmony_ci Log.debug('I18n message is null.'); 131e484b35bSopenharmony_ci return false; 132e484b35bSopenharmony_ci } 133e484b35bSopenharmony_ci return true; 134e484b35bSopenharmony_ci } 135e484b35bSopenharmony_ci 136e484b35bSopenharmony_ci private _getMessage(messages: any[], path: string): any { 137e484b35bSopenharmony_ci for (const i in messages) { 138e484b35bSopenharmony_ci const value = getValue(path, messages[i]); 139e484b35bSopenharmony_ci if (!isNull(value)) { 140e484b35bSopenharmony_ci return value; 141e484b35bSopenharmony_ci } 142e484b35bSopenharmony_ci } 143e484b35bSopenharmony_ci return null; 144e484b35bSopenharmony_ci } 145e484b35bSopenharmony_ci 146e484b35bSopenharmony_ci private _getChoice(count: number, path: string, message: any): any { 147e484b35bSopenharmony_ci const pluralChoice = i18nPluralRules.select(count); 148e484b35bSopenharmony_ci if (!pluralChoice) { 149e484b35bSopenharmony_ci Log.debug('PluralChoice is null.'); 150e484b35bSopenharmony_ci return path; 151e484b35bSopenharmony_ci } 152e484b35bSopenharmony_ci return getValue(pluralChoice, message); 153e484b35bSopenharmony_ci } 154e484b35bSopenharmony_ci 155e484b35bSopenharmony_ci private _translate(path: string, value: any, params: any): any { 156e484b35bSopenharmony_ci if (isNull(value)) { 157e484b35bSopenharmony_ci return path; 158e484b35bSopenharmony_ci } 159e484b35bSopenharmony_ci if (Object.prototype.toString.call(params) === '[object Array]') { 160e484b35bSopenharmony_ci value = value.replace(/\{(\d+)\}/g, (_, index) => { 161e484b35bSopenharmony_ci if (index > params.length - 1 || index < 0) { 162e484b35bSopenharmony_ci return ''; 163e484b35bSopenharmony_ci } 164e484b35bSopenharmony_ci return params[index]; 165e484b35bSopenharmony_ci }); 166e484b35bSopenharmony_ci } else if (Object.prototype.toString.call(params) === '[object Object]') { 167e484b35bSopenharmony_ci value = value.replace(/\{(\w+)\}/g, (_, name) => { 168e484b35bSopenharmony_ci if (name in params) { 169e484b35bSopenharmony_ci return params[name]; 170e484b35bSopenharmony_ci } 171e484b35bSopenharmony_ci return ''; 172e484b35bSopenharmony_ci }); 173e484b35bSopenharmony_ci } else if (Object.prototype.toString.call(params) === '[object Number]') { 174e484b35bSopenharmony_ci value = value.replace(/\{count\}/g, params.toLocaleString(this.locale.replace('_', '-'))); 175e484b35bSopenharmony_ci } else { 176e484b35bSopenharmony_ci return value; 177e484b35bSopenharmony_ci } 178e484b35bSopenharmony_ci return value; 179e484b35bSopenharmony_ci } 180e484b35bSopenharmony_ci} 181e484b35bSopenharmony_ci 182e484b35bSopenharmony_ci/** 183e484b35bSopenharmony_ci * Init the i18n object. 184e484b35bSopenharmony_ci */ 185e484b35bSopenharmony_ciexport default { 186e484b35bSopenharmony_ci create: (id: number): I18nInterface | null => { 187e484b35bSopenharmony_ci instances[id] = []; 188e484b35bSopenharmony_ci if (typeof global.I18n === 'function') { 189e484b35bSopenharmony_ci return {}; 190e484b35bSopenharmony_ci } 191e484b35bSopenharmony_ci const i18nObject = { 192e484b35bSopenharmony_ci I18n: class extends I18n { 193e484b35bSopenharmony_ci constructor(options) { 194e484b35bSopenharmony_ci super(options); 195e484b35bSopenharmony_ci instances[id].push(this); 196e484b35bSopenharmony_ci } 197e484b35bSopenharmony_ci } 198e484b35bSopenharmony_ci }; 199e484b35bSopenharmony_ci return { 200e484b35bSopenharmony_ci instance: i18nObject 201e484b35bSopenharmony_ci }; 202e484b35bSopenharmony_ci }, 203e484b35bSopenharmony_ci destroy: (id: number): void => { 204e484b35bSopenharmony_ci delete instances[id]; 205e484b35bSopenharmony_ci } 206e484b35bSopenharmony_ci}; 207