HiveNetCore.i18n 源代码

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
#
# Copyright 2018 黎慧剑
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

"""
国际化文本处理模块

@module i18n
@file i18n.py

"""

import os
import sys
import copy
import json
import re
# 根据当前文件路径将包路径纳入, 在非安装的情况下可以引用到
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))
from HiveNetCore.utils.file_tool import FileTool
from HiveNetCore.utils.global_var_tool import GlobalVarTool


__MOUDLE__ = 'i18n'  # 模块名
__DESCRIPT__ = u'国际化文本处理模块'  # 模块描述
__VERSION__ = '0.1.0'  # 版本
__AUTHOR__ = u'黎慧剑'  # 作者
__PUBLISH__ = '2018.08.29'  # 发布日期


[文档]def set_global_i18n(i18n_obj): """ 设置通用的SimpleI18N实例对象 @param {object} i18n_obj - SimpleI18N实例对象 """ GlobalVarTool.set_global_var('SIMPLE_I18N_GLOBAL_OBJECT', i18n_obj)
[文档]def get_global_i18n(): """ 获取全局SimpleI18N实例对象 @returns {SimpleI18N} - 如果未设置返回None """ return GlobalVarTool.get_global_var('SIMPLE_I18N_GLOBAL_OBJECT')
def _(s, *args): """ 封装对字符串的国际化简化处理函数 @param {string} s - 要进行国际化处理的字符串 @param {tuple} args - 进行占位符替换的变量 @returns {string} - 国际化转换后的字符串 @example 1、直接进行字符串转换 print(_('success!')) 2、通过占位符替换的情况 print(_('my name is $1, i am $2 years old', 'snaker', '30')) """ i18n_obj = GlobalVarTool.get_global_var('SIMPLE_I18N_GLOBAL_OBJECT') if i18n_obj is None: return s else: return i18n_obj.translate(s, args)
[文档]def init_global_i18n(): """ 初始化HiveNetCore的国际化控件, 包括: 1、生成SimpleI18N类, 并设置到全局变量 2、装载HiveNetCore的基础国际化配置信息 """ _i18n_obj = get_global_i18n() if _i18n_obj is None: _i18n_obj = SimpleI18N() set_global_i18n(_i18n_obj) # 装载所需的配置信息, 错误码 _base_path = os.path.abspath(os.path.dirname(__file__) + '/') _error_code_path = os.path.realpath(_base_path + '/hivenet_error_code/') _i18n_obj.load_trans_from_dir( trans_file_path=_error_code_path, trans_file_prefix='errorcode', encoding='utf-8', append=True )
[文档]class SimpleI18N(object): """ 国际化文本处理类 """ ############################# # 变量 ############################# lang = 'en' # 默认语言 __trans_dict = None # 语言信息字典 @property def trans_dict(self): """ 返回已装载的多国语言字典 格式如下: { 'en': { 'success' : 'success', 'failed' : 'failed', 'my name is $1' : 'my name is $1' }, 'zh': { 'success' : '成功', 'failed' : '失败', 'my name is $1' : '我的名字是$1' } } @property {dict} """ return self.__trans_dict
[文档] def __init__(self, lang='en', trans_file_path=None, trans_file_prefix='', encoding='utf-8', auto_loads=False): """ 构造函数 @param {string} lang='en' - 指定默认语言, 例如en、zh等 @param {string} trans_file_path=None - 语言信息文件所在路径, 如果为None则代表不处理信息文件 @param {string} trans_file_prefix='' - 语言信息文件前缀, 例如前缀为test, 信息文件名为test_en.json、test_zh.json等 @param {string} encoding='utf-8' - 解析文件的编码 @param {bool} auto_loads=False - 是否自动加载语言信息文件 """ self.__trans_dict = dict() self.lang = lang if auto_loads and trans_file_path is not None: # 加载语言信息文件 self.load_trans_from_dir( trans_file_path=trans_file_path, trans_file_prefix=trans_file_prefix, encoding=encoding, append=False )
[文档] def load_trans_from_dir(self, trans_file_path, trans_file_prefix, encoding='utf-8', append=True): """ 从指定路径加载语言信息文件到对象中 @param {string} trans_file_path - 语言信息文件所在路径, 如果为None则代表不处理信息文件 @param {string} trans_file_prefix - 语言信息文件前缀, 例如前缀为test, 信息文件名为test_en.json、test_zh.json等 @param {string} encoding='utf-8' - 解析文件的编码 @param {bool} append=True - 是否追加模式, 如果是则以增量方式更新, 否则覆盖原来的配置 """ file_list = FileTool.get_filelist( path=trans_file_path, regex_str=r'^' + trans_file_prefix + r'_\S+\.json$', is_fullname=True ) for file in file_list: # 循环加载语言信息文件 file_name = os.path.split(os.path.realpath(file))[1] file_lang = re.sub(r'\.json$', '', re.sub( r'^' + trans_file_prefix + r'_', '', file_name)) self.load_trans_from_file(file_full_path=file, lang=file_lang, encoding=encoding, append=append)
[文档] def load_trans_from_file(self, file_full_path, lang, encoding='utf-8', append=True): """ 从语言信息文件加载到对象中 @param {string} file_full_path - 语言信息文件全路径( 含文件名) @param {string} lang - 对应的语言, 例如en、zh等 @param {string} encoding='utf-8' - 解析文件的编码 @param {bool} append=True - 是否追加模式, 如果是则以增量方式更新, 否则覆盖原来的配置 """ json_obj = {} with open(file_full_path, 'rt', encoding=encoding) as f: json_obj = json.load(f) self.load_trans_from_json(json_obj, lang=lang, append=append)
[文档] def load_trans_from_str(self, json_str, lang, append=True): """ 从JSON字符串中加载语言信息到对象中 @param {string} json_str - JSON字符串 @param {string} lang - 对应的语言, 例如en、zh等 @param {bool} append=True - 是否追加模式, 如果是则以增量方式更新, 否则覆盖原来的配置 """ json_obj = json.loads(json_str) self.load_trans_from_json(json_obj, lang=lang, append=append)
[文档] def load_trans_from_json(self, json_obj, lang, append=True): """ 从JSON实例变量中加载语言信息到对象中 @param {object} json_obj - 信息字典的json对象 @param {string} lang - 对应的语言, 例如en、zh等 @param {bool} append=True - 是否追加模式, 如果是则以增量方式更新, 否则覆盖原来的配置 """ if append and lang in self.__trans_dict.keys(): # 追加模式, 逐条更新 for key in json_obj.keys(): self.__trans_dict[lang][key] = json_obj[key] else: # 覆盖模式, 直接重新设置值即可 self.__trans_dict[lang] = copy.deepcopy(json_obj)
[文档] def translate(self, msg_id, replace_para=(), lang=None): """ 返回指定语言的文本 @param {string} msg_id - 要翻译的语言ID标识 @param {tuple} replace_para=() - 进行占位符替换的变量 @param {string} lang=None - 要翻译的语言, 如果不指定则采用初始化对象的默认语言 @returns {string} - 国际化转换后的字符串 """ temp_lang = lang if lang is None: temp_lang = self.lang s = msg_id if temp_lang in self.__trans_dict.keys() and msg_id in self.__trans_dict[temp_lang].keys(): # 可以找到对应的语言信息 s = self.__trans_dict[temp_lang][msg_id] # 替换占位符 i = 1 # 记录是第几个 for para in replace_para: if s.find('$' + str(i)) >= 0: s = re.sub(r'\$' + str(i), str(para).replace('\\', '\\\\'), s) # 如果字符串有'\'会抛异常 i = i + 1 # 处理完成 return s
if __name__ == '__main__': # 当程序自己独立运行时执行的操作 # 打印版本信息 print(('模块名: %s - %s\n' '作者: %s\n' '发布日期: %s\n' '版本: %s' % (__MOUDLE__, __DESCRIPT__, __AUTHOR__, __PUBLISH__, __VERSION__)))