format一遍+logger颜色继续改

This commit is contained in:
shenjack 2022-09-04 13:53:09 +08:00
parent fc734a62cb
commit af96529f76
22 changed files with 125 additions and 123 deletions

View File

@ -16,4 +16,3 @@ from .delivery import Delivery
# lazy之后之前全部导入的(太多了写不动__all__了 # lazy之后之前全部导入的(太多了写不动__all__了
from .scientific_unit import * from .scientific_unit import *

View File

@ -1,4 +1,3 @@
# ------------------------------- # -------------------------------
# Difficult Rocket # Difficult Rocket
# Copyright © 2021-2022 by shenjackyuanjie 3695888@qq.com # Copyright © 2021-2022 by shenjackyuanjie 3695888@qq.com

View File

@ -10,4 +10,3 @@ mail: 3695888@qq.com
github: @shenjackyuanjie github: @shenjackyuanjie
gitee: @shenjackyuanjie gitee: @shenjackyuanjie
""" """

View File

@ -18,8 +18,8 @@ from utils import translate
default_style = { default_style = {
'font_name': 'Times New Roman', 'font_name': 'Times New Roman',
'font_size': 12, 'font_size': 12,
'bold': False, 'bold': False,
'italic': False 'italic': False
} }
@ -222,7 +222,7 @@ default_fonts_config = [
# Markdown 粗体语法规则匹配 # Markdown 粗体语法规则匹配
'match': re.compile(r'\*\*(.*?(?<!\s))\*\*'), 'match': re.compile(r'\*\*(.*?(?<!\s))\*\*'),
'shown': re.compile(r'(?<=\*\*)(.*?(?<!\s))(?=\*\*)'), 'shown': re.compile(r'(?<=\*\*)(.*?(?<!\s))(?=\*\*)'),
'tag': { 'tag': {
# 为 match 匹配到的字符添加标签 # 为 match 匹配到的字符添加标签
'match': re.compile(r'\*\*'), 'match': re.compile(r'\*\*'),
'style': SingleTextStyle(text_tag=['bold']) 'style': SingleTextStyle(text_tag=['bold'])
@ -231,14 +231,14 @@ default_fonts_config = [
}, },
{ {
# Markdown 斜体语法规则匹配 # Markdown 斜体语法规则匹配
'match': re.compile(r'\*(.*?(?<!\s))\*'), 'match': re.compile(r'\*(.*?(?<!\s))\*'),
'shown': re.compile(r'(?<=\*)(.*?(?<!\s))(?=\*)'), 'shown': re.compile(r'(?<=\*)(.*?(?<!\s))(?=\*)'),
'ignore': { 'ignore': {
# 如果匹配到的字符含有 tag 就忽略本次解析 # 如果匹配到的字符含有 tag 就忽略本次解析
'match': re.compile(r'\*'), 'match': re.compile(r'\*'),
'tag': SingleTextStyle(text_tag=['italic']) 'tag': SingleTextStyle(text_tag=['italic'])
}, },
'style': SingleTextStyle(italic=True) 'style': SingleTextStyle(italic=True)
}, },
{ {
# Markdown 链接规则匹配 # Markdown 链接规则匹配

View File

@ -112,16 +112,16 @@ if not DR_option.InputBox_use_TextEntry:
width=width + (out_line * 2), height=height + (out_line * 2), width=width + (out_line * 2), height=height + (out_line * 2),
batch=batch, group=group) batch=batch, group=group)
self._光标 = Rectangle(x=x + out_line, y=y + out_line, self._光标 = Rectangle(x=x + out_line, y=y + out_line,
color=cursor_color, color=cursor_color,
width=1, height=self.font_height, width=1, height=self.font_height,
batch=batch, group=group) batch=batch, group=group)
self._选择框 = Rectangle(x=x, y=y, width=0, height=self.font_height, self._选择框 = Rectangle(x=x, y=y, width=0, height=self.font_height,
color=select_color) color=select_color)
self._选择的字 = Label(x=x, y=y, width=0, height=self.font_height, self._选择的字 = Label(x=x, y=y, width=0, height=self.font_height,
color=text_color, color=text_color,
font_name=font_name, font_size=font_size, font_name=font_name, font_size=font_size,
batch=batch, group=group, batch=batch, group=group,
text='') text='')
""" """
输入框的属性 输入框的属性

View File

@ -31,5 +31,3 @@ class DRScreen(BaseScreen):
class DRDEBUGScreen(BaseScreen): class DRDEBUGScreen(BaseScreen):
def __init__(self, main_window: ClientWindow): def __init__(self, main_window: ClientWindow):
super().__init__(main_window) super().__init__(main_window)

View File

@ -20,32 +20,32 @@ INFO = 'info'
RUN = 'run' RUN = 'run'
DR_command = { DR_command = {
'name': 'DR-root', 'name': 'DR-root',
'version': DR_runtime.DR_version, 'version': DR_runtime.DR_version,
INFO: 'DR的自带命令解析树', INFO: 'DR的自带命令解析树',
COMMAND: { COMMAND: {
INFO: '这里是DR的根命令节点', INFO: '这里是DR的根命令节点',
RUN: None, RUN: None,
SUB_COMMAND: { SUB_COMMAND: {
'stop': { 'stop': {
INFO: '退出游戏', INFO: '退出游戏',
RUN: None RUN: None
}, },
'fps': { 'fps': {
INFO: 'FPS相关命令', INFO: 'FPS相关命令',
RUN: None, RUN: None,
SUB_COMMAND: { SUB_COMMAND: {
'log': { 'log': {
INFO: '输出FPS信息', INFO: '输出FPS信息',
RUN: None RUN: None
}, },
'min': { 'min': {
INFO: '输出一段时间内最小fps', INFO: '输出一段时间内最小fps',
RUN: None RUN: None
}, },
'max': { 'max': {
INFO: '输出一段时间内最大FPS', INFO: '输出一段时间内最大FPS',
RUN: None RUN: None
} }
} }
}, },

View File

@ -28,5 +28,3 @@ class BaseRuntimeError(RuntimeError):
class TestError(BaseRuntimeError): class TestError(BaseRuntimeError):
"""在 test 啦""" """在 test 啦"""

View File

@ -61,4 +61,3 @@ class CommandQMarkSufMissing(CommandQMarkMissing):
"""命令中 后面的引号缺失(引号未闭合) """命令中 后面的引号缺失(引号未闭合)
例如: /command "aaaawaa some command""" 例如: /command "aaaawaa some command"""
pre_qmark_pos = None pre_qmark_pos = None

View File

@ -6,7 +6,6 @@
from Difficult_Rocket.exception import BaseError, BaseRuntimeError from Difficult_Rocket.exception import BaseError, BaseRuntimeError
__all__ = ['LanguageNotFound', __all__ = ['LanguageNotFound',
'TranslateError', 'TranslateError',
'TranslateKeyNotFound', 'TranslateKeyNotFound',
@ -27,4 +26,3 @@ class TranslateKeyNotFound(TranslateError):
class TranslateFileNotFound(TranslateError): class TranslateFileNotFound(TranslateError):
"""翻译文件缺失""" """翻译文件缺失"""

View File

@ -1,4 +1,3 @@
# ------------------------------- # -------------------------------
# Difficult Rocket # Difficult Rocket
# Copyright © 2021-2022 by shenjackyuanjie 3695888@qq.com # Copyright © 2021-2022 by shenjackyuanjie 3695888@qq.com

View File

@ -10,4 +10,3 @@ mail: 3695888@qq.com
github: @shenjackyuanjie github: @shenjackyuanjie
gitee: @shenjackyuanjie gitee: @shenjackyuanjie
""" """

View File

@ -4,6 +4,7 @@
# All rights reserved # All rights reserved
# ------------------------------- # -------------------------------
from colorama import Fore, Back, Style from colorama import Fore, Back, Style
print(Fore.RED + 'some red text') print(Fore.RED + 'some red text')
print(Back.GREEN + 'and with a green background') print(Back.GREEN + 'and with a green background')
print(Style.DIM + 'and in dim text') print(Style.DIM + 'and in dim text')

View File

@ -1,4 +1,3 @@
import os import os
# include 目录 # include 目录
@ -7,10 +6,10 @@ include_paths = ["C:\\Users\\shenjack.SHENJACK-5600X\\AppData\\Local\\Programs\\
# 编译选项 # 编译选项
compile_options = { compile_options = {
"-shared": None, "-shared": None,
"-O3": None, "-O3": None,
"-Wall": None, "-Wall": None,
"-Werror": None, "-Werror": None,
"-o": "./py_cprint.dll" "-o": "./py_cprint.dll"
} }
include_command = "-I " include_command = "-I "
@ -38,4 +37,3 @@ compile_command = "gcc.exe ./py_cprint.c {}{}".format(include_command, compile_o
print(compile_command) print(compile_command)
os.system(compile_command) os.system(compile_command)

View File

@ -1,4 +1,3 @@
from objprint import objprint from objprint import objprint
from ctypes import cdll from ctypes import cdll
@ -6,4 +5,3 @@ from ctypes import cdll
cprint = cdll.LoadLibrary("./cprint.dll") cprint = cdll.LoadLibrary("./cprint.dll")
# objprint(cprint) # objprint(cprint)

View File

@ -14,4 +14,3 @@ pycprint.print("abcdefg\n")
pycprint.printf('aaaa') pycprint.printf('aaaa')
pycprint.printf("啊啊啊abc啊怎么了") pycprint.printf("啊啊啊abc啊怎么了")

View File

@ -6,4 +6,5 @@
def print(text: str) -> None: ... # 直接调用fprint def print(text: str) -> None: ... # 直接调用fprint
def printf(text: str) -> None: ... # 测试中 def printf(text: str) -> None: ... # 测试中

View File

@ -14,6 +14,7 @@ from logging import NOTSET, DEBUG, INFO, WARNING, ERROR, FATAL
from types import FrameType from types import FrameType
from typing import Optional, Union, Dict, Iterable, Tuple, Any from typing import Optional, Union, Dict, Iterable, Tuple, Any
os.system('')
# print(os.path.abspath(os.curdir)) # print(os.path.abspath(os.curdir))
# 如果想要直接使用 logger 来 logging # 如果想要直接使用 logger 来 logging
@ -49,97 +50,98 @@ TRACE = 5
FINE = 7 FINE = 7
level_name_map = { level_name_map = {
ALL: 'ALL', # NOTSET ALL: 'ALL', # NOTSET
TRACE: 'TRACE', TRACE: 'TRACE',
FINE: 'FINE', FINE: 'FINE',
DEBUG: 'DEBUG', DEBUG: 'DEBUG',
INFO: 'INFO', INFO: 'INFO',
WARNING: 'WARNING', # WARN WARNING: 'WARNING', # WARN
ERROR: 'ERROR', ERROR: 'ERROR',
FATAL: 'FATAL' FATAL: 'FATAL'
} }
name_level_map = { name_level_map = {
'NOTSET': ALL, 'NOTSET': ALL,
'ALL': ALL, 'ALL': ALL,
'TRACE': TRACE, 'TRACE': TRACE,
'FINE': FINE, 'FINE': FINE,
'DEBUG': DEBUG, 'DEBUG': DEBUG,
'INFO': INFO, 'INFO': INFO,
'WARNING': WARNING, 'WARNING': WARNING,
'WARN': WARNING, 'WARN': WARNING,
'ERROR': ERROR, 'ERROR': ERROR,
'CRITICAL': FATAL, 'CRITICAL': FATAL,
'FATAL': FATAL 'FATAL': FATAL
} }
logger_configs = { logger_configs = {
'Logger': { 'Logger': {
'root': { 'root': {
'level': TRACE, 'level': TRACE,
'color': 'main_color', 'color': 'main_color',
'file': 'main_log_file', 'file': 'main_log_file',
}, },
'client': { 'client': {
'level': TRACE, 'level': TRACE,
'color': 'main_color', 'color': 'main_color',
'file': 'main_log_file', 'file': 'main_log_file',
}, },
'server': { 'server': {
'level': TRACE, 'level': TRACE,
'color': 'main_color', 'color': 'DiGua_color',
'file': 'main_log_file', 'file': 'main_log_file',
}, },
}, },
'Color': { 'Color': {
'main_color': { 'main_color': {
'file_time': '\033[38;2;201;222;56m', 'file_time': '\033[38;2;201;222;56m',
'main_time': '\033[38;2;201;222;56m', 'main_time': '\033[38;2;201;222;56m',
'file_name': '\033[38;2;0;255;180m', 'file_name': '\033[38;2;0;255;180m',
'code_line': '\033[38;2;0;255;180m', 'code_line': '\033[38;2;0;255;180m',
'logger': '\033[0m', 'logger': '\033[0m',
TRACE: {'info': '\033[38;2;138;173;244m', 'message': '\033[38;2;40;40;70m'}, TRACE: {'info': '\033[38;2;138;173;244m', 'message': '\033[38;2;40;40;200m'},
FINE: {'info': '\033[35;48;2;44;44;54m', 'message': '\033[35m'}, FINE: {'info': '\033[35;48;2;44;44;54m', 'message': '\033[35m'},
DEBUG: {'info': '\033[38;2;133;138;149m', 'message': '\033[38;2;133;138;149m'}, DEBUG: {'info': '\033[38;2;133;138;149m', 'message': '\033[38;2;133;138;149m'},
INFO: {'info': '\033[0m', 'message': '\033[0m'}, INFO: {'info': '\033[0m', 'message': '\033[0m'},
WARNING: {'info': '\033[33m', 'message': '\033[33m'}, WARNING: {'info': '\033[33m', 'message': '\033[33m'},
ERROR: {'info': '\033[31m', 'message': '\033[31m'}, ERROR: {'info': '\033[31m', 'message': '\033[31m'},
FATAL: {'info': '\033[38;2;255;255;0;48;2;120;10;10m', 'message': '\033[38;2;255;255;0;48;2;120;10;10m'} FATAL: {'info': '\033[38;2;255;255;0;48;2;120;10;10m', 'message': '\033[38;2;255;255;0;48;2;120;10;10m'}
}, },
'DiGua_color': { 'DiGua_color': {
'file_time': '\033[38;2;201;222;56m', # catppuccin Macchiato
'main_time': '\033[38;2;201;222;56m', 'file_time': '\033[38;2;238;212;159m',
'file_name': '\033[38;2;0;255;180m', 'main_time': '\033[38;2;202;211;245m',
'code_line': '\033[38;2;0;255;180m', 'file_name': '\033[38;2;139;213;202m',
'logger': '\033[0m', 'code_line': '\033[38;2;166;218;149m',
TRACE: {'info': '\033[34;48;2;44;44;54m', 'message': '\033[34;48;2;40;40;70m'}, 'logger': '\033[0m',
FINE: {'info': '\033[35;48;2;44;44;54m', 'message': '\033[35m'}, TRACE: {'info': '\033[38;2;138;173;244m', 'message': '\033[38;2;138;173;244m'},
DEBUG: {'info': '\033[38;2;133;138;149m', 'message': '\033[38;2;133;138;149m'}, FINE: {'info': '\033[38;2;198;160;246m', 'message': '\033[38;2;198;160;246m'},
INFO: {'info': '\033[0m', 'message': '\033[0m'}, DEBUG: {'info': '\033[38;2;133;138;149m', 'message': '\033[38;2;133;138;149m'},
WARNING: {'info': '\033[33m', 'message': '\033[33m'}, INFO: {'info': '\033[0m', 'message': '\033[0m'},
ERROR: {'info': '\033[31m', 'message': '\033[31m'}, WARNING: {'info': '\033[38;2;245;169;127m', 'message': '\033[38;2;245;169;127m'},
FATAL: {'info': '\033[38;2;255;255;0;48;2;120;10;10m', 'message': '\033[38;2;255;255;0;48;2;120;10;10m'} ERROR: {'info': '\033[38;2;237;135;150m', 'message': '\033[38;2;237;135;150m'},
FATAL: {'info': '\033[38;2;255;255;0;48;2;120;10;10m', 'message': '\033[38;2;255;255;0;48;2;120;10;10m', 'logger': '\033[38;2;245;189;230m'}
} }
}, },
'File': { 'File': {
'main_log_file': { 'main_log_file': {
'mode': 'a', 'mode': 'a',
'encoding': 'utf-8', 'encoding': 'utf-8',
'level': TRACE, 'level': TRACE,
'file_name': './logs/{file_time}_logs.md', 'file_name': './logs/{file_time}_logs.md',
'cache_len': 10, 'cache_len': 10,
'cache_time': 1 'cache_time': 1
}, },
}, },
'Formatter': { 'Formatter': {
'MESSAGE': { 'MESSAGE': {
'format': '[{main_time}] [{logger_name}] {level} | {file_name}:{code_line} | {message}' 'format': '[{main_time}] [{logger_name}] {level} | {file_name}:{code_line} | {message}'
}, },
'file_name': 'no frame', 'file_name': 'no frame',
'code_line': 'no frame', 'code_line': 'no frame',
'file_time': {'strftime': '%Y-%m-%d %H-%M'}, 'file_time': {'strftime': '%Y-%m-%d %H-%M'},
'main_time': {'strftime': '%Y-%m-%d %H-%M-%S:%%S'}, # %%S 三位毫秒 'main_time': {'strftime': '%Y-%m-%d %H-%M-%S:%%S'}, # %%S 三位毫秒
...: ... ...: ...
} }
} }
@ -274,7 +276,6 @@ class LogFileCache:
def _log_file_time_write(self, thread: bool = False) -> None: def _log_file_time_write(self, thread: bool = False) -> None:
"""使用 threading.Timer 调用的定时写入日志文件的函数""" """使用 threading.Timer 调用的定时写入日志文件的函数"""
print(f'write! {thread}{self.log_cache.cache}')
if self.log_cache: if self.log_cache:
with self.time_limit_lock: with self.time_limit_lock:
if self.log_cache: if self.log_cache:
@ -320,7 +321,6 @@ class Logger:
self.level = level if level is not None else DEBUG self.level = level if level is not None else DEBUG
self.colors = colors or logger_configs['Color']['main_color'] self.colors = colors or logger_configs['Color']['main_color']
self.formats = formats or logger_configs['Formatter'].copy() self.formats = formats or logger_configs['Formatter'].copy()
self.formats['logger_name'] = f'{self.colors["logger"]}{self.name}{color_reset_suffix}'
if file_conf: if file_conf:
self.file_cache = LogFileCache(file_conf=file_conf) self.file_cache = LogFileCache(file_conf=file_conf)
else: else:
@ -360,14 +360,15 @@ class Logger:
level_with_color = f"{level_with_color}{' ' * (9 - len_without_color_maker(level_with_color))}" level_with_color = f"{level_with_color}{' ' * (9 - len_without_color_maker(level_with_color))}"
formats = self.formats.copy() formats = self.formats.copy()
if frame is not None: if frame is not None:
formats['file_name'] = f"{self.colors['file_name']}{os.path.split(frame.f_code.co_filename)[-1]}{color_reset_suffix}" formats['file_name'] = f"{self.colors[level]['file_name']}{os.path.split(frame.f_code.co_filename)[-1]}{color_reset_suffix}"
formats['code_line'] = f"{self.colors['code_line']}{frame.f_lineno}{color_reset_suffix}" formats['code_line'] = f"{self.colors[level]['code_line']}{frame.f_lineno}{color_reset_suffix}"
formats['logger_name'] = f'{self.colors[level]["logger"]}{self.name}{color_reset_suffix}'
now_time = str(time.time()) now_time = str(time.time())
for key, value in formats.items(): for key, value in formats.items():
if isinstance(value, dict): if isinstance(value, dict):
if 'strftime' in value: if 'strftime' in value:
value['strftime']: str value['strftime']: str
formats[key] = f"{self.colors[key]}{strftime(value['strftime'].replace('%%S', now_time[now_time.find('.') + 1:now_time.find('.') + 4]))}{color_reset_suffix}" formats[key] = f"{self.colors[level][key]}{strftime(value['strftime'].replace('%%S', now_time[now_time.find('.') + 1:now_time.find('.') + 4]))}{color_reset_suffix}"
print_text = self.formats['MESSAGE']['format'].format(level_with_color=level_with_color, print_text = self.formats['MESSAGE']['format'].format(level_with_color=level_with_color,
level=level_with_color, message=text, level=level_with_color, message=text,
**formats) **formats)
@ -422,6 +423,8 @@ class Logger:
def get_key_from_dict(a_dict: Dict, key: Any, default: Any = None) -> Optional[Any]: def get_key_from_dict(a_dict: Dict, key: Any, default: Any = None) -> Optional[Any]:
if default is None:
return a_dict[key]
try: try:
return a_dict[key] return a_dict[key]
except KeyError: except KeyError:
@ -465,15 +468,15 @@ def gen_file_conf(file_name: str,
file_encoding: str = 'utf-8', file_encoding: str = 'utf-8',
file_cache_len: int = 10, file_cache_len: int = 10,
file_cache_time: Union[int, float] = 1) -> dict: file_cache_time: Union[int, float] = 1) -> dict:
return {'file_name': file_name, return {'file_name': file_name,
'level': file_level, 'level': file_level,
'mode': file_mode, 'mode': file_mode,
'encoding': file_encoding, 'encoding': file_encoding,
'cache_len': file_cache_len, 'cache_len': file_cache_len,
'cache_time': file_cache_time} 'cache_time': file_cache_time}
def gen_color_conf(**colors) -> dict: def gen_color_conf(color_name: str = None, **colors) -> dict:
default_color = logger_configs['Color']['main_color'].copy() default_color = logger_configs['Color']['main_color'].copy()
default_color.update(colors) default_color.update(colors)
return default_color return default_color
@ -518,7 +521,21 @@ def get_logger(name: str = 'root') -> Logger:
level=the_config['level'], level=the_config['level'],
file_conf=logger_configs['File'][the_config['file']] if 'file' in the_config else None, file_conf=logger_configs['File'][the_config['file']] if 'file' in the_config else None,
colors=logger_configs['Color'][get_key_from_dict(the_config, 'color', 'main_color')], colors=logger_configs['Color'][get_key_from_dict(the_config, 'color', 'main_color')],
formats=logger_configs['Formatter']) formats=logger_configs['Formatter'].copy())
def format_colors(colors: dict) -> None:
for key, value in colors.items():
if not isinstance(key, str):
continue
for level, value_ in colors.items():
if not isinstance(level, int):
continue
colors[level][key] = get_key_from_dict(colors[level], key, colors[key])
for color in logger_configs['Color']:
format_colors(logger_configs['Color'][color])
def test_logger(the_logger: Logger): def test_logger(the_logger: Logger):
@ -533,9 +550,11 @@ def test_logger(the_logger: Logger):
if __name__ == "__main__": if __name__ == "__main__":
os.chdir('D:/githubs/DR') os.chdir('D:/githubs/DR')
logger = Logger(name="Main", level=NOTSET) logger = get_logger('server')
logger.info('my name is:', logger.name) logger.info('my name is:', logger.name)
a_logger = get_logger('client') a_logger = get_logger('client')
a_logger.trace('tracing') a_logger.trace('tracing')
time.sleep(1.1) time.sleep(1.1)
a_logger.fine('some fine!') a_logger.fine('some fine!')

View File

@ -32,8 +32,8 @@ file configs
""" """
file_error = {FileNotFoundError: 'no {filetype} file was founded!:\n file name: {filename}\n file_type: {filetype}\n stack: {stack}', file_error = {FileNotFoundError: 'no {filetype} file was founded!:\n file name: {filename}\n file_type: {filetype}\n stack: {stack}',
KeyError: 'no stack in {filetype} file {filename} was found! \n file type: {} \n file name: {} \n stack: {stack}', KeyError: 'no stack in {filetype} file {filename} was found! \n file type: {} \n file name: {} \n stack: {stack}',
Exception: 'get some {error_type} error when read {filetype} file {filename}! \n file type: {} \n file name: {} \n stack: {stack}'} Exception: 'get some {error_type} error when read {filetype} file {filename}! \n file type: {} \n file name: {} \n stack: {stack}'}
def load_file(file_name: str, stack: Union[str, list, dict] = None, raise_error: bool = True) -> Union[dict, list]: def load_file(file_name: str, stack: Union[str, list, dict] = None, raise_error: bool = True) -> Union[dict, list]:

View File

@ -20,7 +20,6 @@ from Difficult_Rocket import DR_runtime, DR_option
from Difficult_Rocket.utils import tools from Difficult_Rocket.utils import tools
from Difficult_Rocket.exception.language import * from Difficult_Rocket.exception.language import *
""" """
这部分代码使用了中文编程why 这部分代码使用了中文编程why
你觉得呢 你觉得呢
@ -32,6 +31,7 @@ class Tr:
我不装了我就抄了tr 我不装了我就抄了tr
GOOD GOOD
""" """
def __init__(self): def __init__(self):
self.config_regs = {} self.config_regs = {}
@ -47,8 +47,6 @@ class Tr:
... ...
class Lang: class Lang:
""" """
用于创建一个对应语言的翻译类 用于创建一个对应语言的翻译类