"use strict";
/**
 * 国际化模块
 */
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
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());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.$t = exports.t = exports.getLang = exports.getParkLang = exports.translate = exports.$translate = exports.init = exports.i18n = exports.DEFAULT_LANG = exports.GlobalService = void 0;
var typescript_ioc_1 = require("typescript-ioc");
var mslib_1 = require("mslib");
var TyGlobalApi_1 = require("./TyGlobalApi");
var Redis_1 = require("./Redis");
var Contants_1 = require("./Contants");
var Config_1 = require("./Config");
/**
 * 国际化服务类
 */
var GlobalService = /** @class */ (function () {
    function GlobalService() {
    }
    /**
     * 获取语言包
     *
     * 返回值为什么没有使用Map来做?
     *
     * 1.Map直接转json是个空对象{}，可以使用Object.fromEntries转换(map的key变成属性，map的value变成属性值)再转json;
     *
     * 2.js弱语言可以使用key作为属性名，但使用数据结构{ key: string, value: string }来存储具有通用性;
     */
    GlobalService.prototype.getLanguagePacks = function (args) {
        var _a;
        return __awaiter(this, void 0, void 0, function () {
            var apiResponse, packs, cn_pack, _i, _b, item, key;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0: return [4 /*yield*/, this.tyGlobalApiClient.get({
                            token: args.token,
                            type: 1
                        })];
                    case 1:
                        apiResponse = _c.sent();
                        packs = {};
                        packs['zh_CN'] = [];
                        cn_pack = {};
                        /**
                         统一接口返回的语言包数据是平铺的格式:{language,key,value,cn},且每条条目中都包含他的中文翻译
                         */
                        for (_i = 0, _b = (_a = apiResponse.data) === null || _a === void 0 ? void 0 : _a.data; _i < _b.length; _i++) {
                            item = _b[_i];
                            if (!packs[item.language])
                                packs[item.language] = [];
                            packs[item.language].push({ key: item.key, value: item.value });
                            if (!Reflect.has(cn_pack, item.key))
                                cn_pack[item.key] = item.cn;
                        }
                        for (key in cn_pack) {
                            packs['zh_CN'].push({ key: key, value: cn_pack[key] });
                        }
                        if (Contants_1.default.IS_LOCAL_DEBUG) {
                            packs['en_US'].push({ key: 'config_alert_offlineAlertThresholdTime2', value: '1111111111111111111111111111111' });
                            packs['zh_CN'].push({ key: 'config_alert_offlineAlertThresholdTime2', value: '这是中文翻译后的结果' });
                        }
                        return [2 /*return*/, packs];
                }
            });
        });
    };
    __decorate([
        typescript_ioc_1.Inject,
        __metadata("design:type", TyGlobalApi_1.TyGlobalApiClient)
    ], GlobalService.prototype, "tyGlobalApiClient", void 0);
    GlobalService = __decorate([
        typescript_ioc_1.Singleton
    ], GlobalService);
    return GlobalService;
}());
exports.GlobalService = GlobalService;
/**
 * 默认语种：zh_CN
 */
exports.DEFAULT_LANG = 'zh_CN';
/**
 * i18n国际化实例
 *
 * 当config.global.mode=PARK时，从场端redis加载语言包
 *
 * 当config.global.mode=CLOUD时，从云端redis加载语言包
 *
 * 基本用法：
 *
 * i18n.__('(主相机)') //根据默认语种进行翻译
 *
 * i18n.__('Hello %s', 'Keytop') //根据默认语种翻译短语，带占位符%s
 *
 * i18n.__('Hello {0}', ['Keytop']) //根据默认语种翻译短语，带占位符{0}
 *
 * i18n.__('Hello {name}', { name: 'Keytop' }) //根据默认语种翻译短语，带属性占位符{name}
 *
 * i18n.__({ phrase: 'Hello %s', locale: 'en_US' }, 'Keytop1')
 *
 * i18n.__({ phrase: 'Hello {0}', locale: 'en_US' }, ['Keytop1'])
 *
 * i18n.__({ phrase: 'Hello {name}', locale: 'en_US' }, { name: 'Keytop1' })
 *
 * https://www.npmjs.com/package/i18n
 */
exports.i18n = null;
var config = Config_1.IocConfigProvider.getGlobalConfig();
function init() {
    return __awaiter(this, void 0, void 0, function () {
        var I18n, error_1;
        var _this = this;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    if ((config === null || config === void 0 ? void 0 : config.enabled) !== true)
                        return [2 /*return*/];
                    _a.label = 1;
                case 1:
                    _a.trys.push([1, 3, , 4]);
                    I18n = require('i18n').I18n;
                    exports.i18n = new I18n();
                    setInterval(function () { return __awaiter(_this, void 0, void 0, function () {
                        var error_2;
                        return __generator(this, function (_a) {
                            switch (_a.label) {
                                case 0:
                                    _a.trys.push([0, 2, , 3]);
                                    return [4 /*yield*/, configure_i18n()];
                                case 1:
                                    _a.sent();
                                    mslib_1.logger.info('i18n刷新语言包成功');
                                    return [3 /*break*/, 3];
                                case 2:
                                    error_2 = _a.sent();
                                    mslib_1.logger.error('i18n刷新语言包失败', error_2);
                                    return [3 /*break*/, 3];
                                case 3: return [2 /*return*/];
                            }
                        });
                    }); }, Contants_1.IS_PROD ? 1000 * 60 * 10 : 1000 * 60 * 5);
                    return [4 /*yield*/, configure_i18n()];
                case 2:
                    _a.sent();
                    mslib_1.logger.info('i18n初始化成功');
                    return [3 /*break*/, 4];
                case 3:
                    error_1 = _a.sent();
                    mslib_1.logger.error('i18n初始化失败', error_1);
                    return [3 /*break*/, 4];
                case 4: return [2 /*return*/];
            }
        });
    });
}
exports.init = init;
function configure_i18n() {
    return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    if (!Contants_1.default.IS_PARK) return [3 /*break*/, 2];
                    return [4 /*yield*/, configure_i18n_park()];
                case 1:
                    _a.sent();
                    return [3 /*break*/, 4];
                case 2: return [4 /*yield*/, configure_i18n_cloud()];
                case 3:
                    _a.sent();
                    _a.label = 4;
                case 4: return [2 /*return*/];
            }
        });
    });
}
function configure_i18n_cloud() {
    return __awaiter(this, void 0, void 0, function () {
        var packs, staticCatalog, _loop_1, key;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, Redis_1.redisClient.hgetall('translation_1102011')];
                case 1:
                    packs = _a.sent();
                    staticCatalog = {};
                    _loop_1 = function (key) {
                        try {
                            var pack_1 = {};
                            JSON.parse(packs[key]).forEach(function (s) {
                                pack_1[s.key] = s.value;
                            });
                            staticCatalog[key] = pack_1;
                        }
                        catch (error) {
                            mslib_1.logger.error("\u52A0\u8F7D\u4E91\u7AEFredis\u8BED\u8A00\u5305\u5931\u8D25,lang:" + key, error);
                        }
                    };
                    for (key in packs) {
                        _loop_1(key);
                    }
                    mslib_1.logger.info("\u52A0\u8F7D\u4E91\u7AEFredis\u8BED\u8A00\u5305\u6210\u529F,langs:" + Reflect.ownKeys(staticCatalog).join(','));
                    exports.i18n.configure({
                        locales: Reflect.ownKeys(staticCatalog),
                        //不存在的语种默认按照中文翻译
                        fallbacks: { '*': 'zh_CN' },
                        staticCatalog: staticCatalog,
                        mustacheConfig: {
                            tags: ['{', '}'],
                            disable: false
                        },
                        logDebugFn: function (msg) {
                            mslib_1.logger.debug(msg);
                        },
                        logWarnFn: function (msg) {
                            mslib_1.logger.warn(msg);
                        },
                        logErrorFn: function (msg) {
                            mslib_1.logger.error(msg);
                        },
                        missingKeyFn: function (locale, value) {
                            return value;
                        },
                    });
                    return [2 /*return*/];
            }
        });
    });
}
function configure_i18n_park() {
    return __awaiter(this, void 0, void 0, function () {
        var staticCatalog, fields, lang_fields, _loop_2, _i, lang_fields_1, field;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    staticCatalog = {};
                    return [4 /*yield*/, Redis_1.redisClient.hkeys('t_realtime_data')];
                case 1:
                    fields = _a.sent();
                    lang_fields = fields.filter(function (s) { return s.startsWith("translation_1102011"); });
                    _loop_2 = function (field) {
                        var _a, lang, current_lang, json;
                        return __generator(this, function (_b) {
                            switch (_b.label) {
                                case 0:
                                    _a = field.split(':'), lang = _a[1];
                                    current_lang = lang.substring(0, lang.lastIndexOf('_'));
                                    if (!staticCatalog[current_lang])
                                        staticCatalog[current_lang] = {};
                                    return [4 /*yield*/, Redis_1.redisClient.hget('t_realtime_data', field)];
                                case 1:
                                    json = _b.sent();
                                    JSON.parse(json).forEach(function (s) {
                                        staticCatalog[current_lang][s.key] = s.value;
                                    });
                                    return [2 /*return*/];
                            }
                        });
                    };
                    _i = 0, lang_fields_1 = lang_fields;
                    _a.label = 2;
                case 2:
                    if (!(_i < lang_fields_1.length)) return [3 /*break*/, 5];
                    field = lang_fields_1[_i];
                    return [5 /*yield**/, _loop_2(field)];
                case 3:
                    _a.sent();
                    _a.label = 4;
                case 4:
                    _i++;
                    return [3 /*break*/, 2];
                case 5:
                    mslib_1.logger.info("\u52A0\u8F7D\u573A\u7AEFredis\u8BED\u8A00\u5305\u6210\u529F,langs:" + Reflect.ownKeys(staticCatalog).join(','));
                    exports.i18n.configure({
                        locales: Reflect.ownKeys(staticCatalog),
                        //不存在的语种默认按照中文翻译
                        fallbacks: { '*': 'zh_CN' },
                        staticCatalog: staticCatalog,
                        mustacheConfig: {
                            tags: ['{', '}'],
                            disable: false
                        },
                        logDebugFn: function (msg) {
                            mslib_1.logger.debug(msg);
                        },
                        logWarnFn: function (msg) {
                            mslib_1.logger.warn(msg);
                        },
                        logErrorFn: function (msg) {
                            mslib_1.logger.error(msg);
                        },
                        missingKeyFn: function (locale, value) {
                            return value;
                        },
                    });
                    return [2 /*return*/];
            }
        });
    });
}
var $regExp = /\$#{{(.+?)\}}/g;
/**
 * 翻译数据，只翻译包含$#{{xxx}}的字符串
 *
 * @param data 翻译的数据，可以是任意对象
 * @param lang 目标语种,如果i18n已配置默认语种,不用传
 */
function $translate(data, lang) {
    if (!exports.i18n)
        return data;
    if (typeof data === 'object') {
        for (var key in data) {
            if (typeof data[key] === 'object') {
                $translate(data[key], lang);
            }
            else {
                if (typeof data[key] === 'string' && $regExp.test(data[key])) {
                    data[key] = data[key].replace($regExp, function (s) {
                        return lang ? exports.i18n.__({ phrase: s.substring(4, s.length - 2), locale: lang }) : exports.i18n.__(s.substring(4, s.length - 2));
                    });
                }
            }
        }
        return data;
    }
    else {
        if (typeof data === 'string' && $regExp.test(data)) {
            return data.replace($regExp, function (s) {
                return lang ? exports.i18n.__({ phrase: s.substring(4, s.length - 2), locale: lang }) : exports.i18n.__(s.substring(4, s.length - 2));
            });
        }
        else {
            return data;
        }
    }
}
exports.$translate = $translate;
/**
 * 翻译数据
 *
 * @param data 翻译的数据，可以是任意对象
 * @param lang 目标语种,如果i18n已配置默认语种,不用传
 */
function translate(data, lang) {
    if (!exports.i18n)
        return data;
    if (typeof data === 'object') {
        for (var key in data) {
            if (typeof data[key] === 'object') {
                translate(data[key], lang);
            }
            else {
                if (typeof data[key] === 'string') {
                    data[key] = lang ? exports.i18n.__({ phrase: data[key], locale: lang }) : exports.i18n.__(data[key]);
                }
            }
        }
        return data;
    }
    else {
        if (typeof data === 'string') {
            return lang ? exports.i18n.__({ phrase: data, locale: lang }) : exports.i18n.__(data);
        }
        else {
            return data;
        }
    }
}
exports.translate = translate;
/**
 * 获取车场主语言
 *
 * 1.云端从redis取
 *
 * 2.场端从sqlite取
 */
function getParkLang(parkId) {
    var _a;
    return __awaiter(this, void 0, void 0, function () {
        var lang, knexInstance, configs;
        return __generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    if (!!Contants_1.default.IS_PARK) return [3 /*break*/, 1];
                    return [2 /*return*/, Redis_1.redisClient.get("lang-{{" + parkId + "}}")];
                case 1:
                    lang = void 0;
                    knexInstance = require('knex')({
                        client: 'sqlite3',
                        connection: {
                            filename: "/home/keytop/data/lotconfig.db"
                        }
                    });
                    return [4 /*yield*/, knexInstance('t_config').where({ session: 'charge', name: 'countryAndLanguage' })];
                case 2:
                    configs = _b.sent();
                    if (configs && configs.length > 0 && configs[0].value)
                        lang = (_a = configs[0]) === null || _a === void 0 ? void 0 : _a.value;
                    return [2 /*return*/, lang];
            }
        });
    });
}
exports.getParkLang = getParkLang;
/**
 * 获取语种
 *
 * 优先级：请求头 > redis(云端)/sqlite(场端) > zh_CN
 * @param parkId
 */
function getLang(parkId) {
    return __awaiter(this, void 0, void 0, function () {
        var lang, headers, error_3;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    lang = null;
                    headers = mslib_1.Context.getRequestHeaders();
                    lang = headers === null || headers === void 0 ? void 0 : headers.language;
                    _a.label = 1;
                case 1:
                    _a.trys.push([1, 4, , 5]);
                    if (!(!lang && Contants_1.IS_PARK && parkId)) return [3 /*break*/, 3];
                    return [4 /*yield*/, getParkLang(parkId)];
                case 2:
                    lang = _a.sent();
                    if (!Contants_1.IS_PROD)
                        mslib_1.logger.info("\u8BFB\u53D6\u8F66\u573A\u4E3B\u8BED\u8A00\u6210\u529F," + (lang || '未设置'));
                    _a.label = 3;
                case 3: return [3 /*break*/, 5];
                case 4:
                    error_3 = _a.sent();
                    mslib_1.logger.error(error_3);
                    return [3 /*break*/, 5];
                case 5: return [2 /*return*/, lang || exports.DEFAULT_LANG];
            }
        });
    });
}
exports.getLang = getLang;
/**
 * 使用i18n对任意类型的对象中的所有字符串进行翻译
 *
 * 语种优先级：请求头 > 车场主语言 > zh_CN
 * @param data 翻译的数据，可以是任意对象
 * @param parkId 车场id,用来获取车场主语言
 */
function t(data, parkId) {
    return __awaiter(this, void 0, void 0, function () {
        var lang;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    if (!exports.i18n || !data)
                        return [2 /*return*/, data];
                    return [4 /*yield*/, getLang(parkId)];
                case 1:
                    lang = _a.sent();
                    return [2 /*return*/, translate(data, lang)];
            }
        });
    });
}
exports.t = t;
/**
 * 使用i18n对任意类型的对象中的所有包含$#{{xxx}}的字符串进行翻译
 *
 * 语种优先级：请求头 > 车场主语言 > zh_CN
 * @param data 翻译的数据，可以是任意对象
 * @param parkId 车场id,用来获取车场主语言
 */
function $t(data, parkId) {
    return __awaiter(this, void 0, void 0, function () {
        var lang;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    if (!exports.i18n || !data)
                        return [2 /*return*/, data];
                    return [4 /*yield*/, getLang(parkId)];
                case 1:
                    lang = _a.sent();
                    return [2 /*return*/, $translate(data, lang)];
            }
        });
    });
}
exports.$t = $t;
//# sourceMappingURL=Global.js.map