2021-09-08 23:38:34 +08:00
|
|
|
|
# -------------------------------
|
|
|
|
|
# Difficult Rocket
|
2023-01-20 14:08:12 +08:00
|
|
|
|
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
|
2021-09-08 23:38:34 +08:00
|
|
|
|
# All rights reserved
|
|
|
|
|
# -------------------------------
|
|
|
|
|
|
2021-09-02 22:47:10 +08:00
|
|
|
|
"""
|
2022-11-26 21:48:55 +08:00
|
|
|
|
writen by shenjackyuanjie <3695888@qq.com>
|
2021-09-02 22:47:10 +08:00
|
|
|
|
mail: 3695888@qq.com
|
|
|
|
|
github: @shenjackyuanjie
|
|
|
|
|
gitee: @shenjackyuanjie
|
|
|
|
|
"""
|
|
|
|
|
|
2022-07-01 13:59:08 +08:00
|
|
|
|
import inspect
|
|
|
|
|
|
2023-01-03 16:24:06 +08:00
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
from typing import Union, Tuple, Any, Type, List, Dict, Hashable, Optional
|
2021-09-22 06:21:48 +08:00
|
|
|
|
|
2022-08-12 21:07:36 +08:00
|
|
|
|
from Difficult_Rocket import DR_runtime, DR_option
|
2022-04-26 22:05:58 +08:00
|
|
|
|
from Difficult_Rocket.utils import tools
|
2022-07-04 10:36:19 +08:00
|
|
|
|
from Difficult_Rocket.exception.language import *
|
2021-09-22 06:21:48 +08:00
|
|
|
|
|
2022-11-26 22:45:30 +08:00
|
|
|
|
|
2023-01-03 16:24:06 +08:00
|
|
|
|
@dataclass
|
|
|
|
|
class TranslateConfig:
|
2023-01-16 18:34:17 +08:00
|
|
|
|
raise_error: bool = False # 引用错误时抛出错误
|
2023-02-03 20:31:44 +08:00
|
|
|
|
crack_normal: bool = True # 出现错误引用后 将引用到的正确内容替换为引用路径
|
2023-01-16 18:34:17 +08:00
|
|
|
|
insert_crack: bool = True # 加入引用的错误内容
|
|
|
|
|
is_final: bool = False # 是否为最终内容
|
|
|
|
|
keep_get: bool = True # 引用错误后是否继续引用
|
|
|
|
|
always_copy: bool = False # 是否一直新建 Translate (为 True 会降低性能)
|
2023-01-31 22:07:18 +08:00
|
|
|
|
source: Optional[Union["Tr", "Translates"]] = None # 翻译来源 (用于默认翻译)
|
2023-01-03 16:24:06 +08:00
|
|
|
|
|
2023-01-31 22:07:18 +08:00
|
|
|
|
def set(self, item: str, value: Union[bool, "Tr", "Translates"]) -> 'TranslateConfig':
|
2023-01-03 16:24:06 +08:00
|
|
|
|
assert getattr(self, item, None) is not None, f'Config {item} is not in TranslateConfig'
|
|
|
|
|
assert type(value) is bool
|
|
|
|
|
setattr(self, item, value)
|
|
|
|
|
return self
|
|
|
|
|
|
2023-01-03 22:28:26 +08:00
|
|
|
|
def __copy__(self) -> 'TranslateConfig':
|
|
|
|
|
return TranslateConfig(raise_error=self.raise_error,
|
|
|
|
|
crack_normal=self.crack_normal,
|
|
|
|
|
insert_crack=self.insert_crack,
|
|
|
|
|
is_final=self.is_final,
|
2023-01-16 18:34:17 +08:00
|
|
|
|
keep_get=self.keep_get,
|
2023-01-31 22:07:18 +08:00
|
|
|
|
always_copy=self.always_copy,
|
|
|
|
|
source=self.source)
|
2023-01-03 22:28:26 +08:00
|
|
|
|
|
|
|
|
|
def copy(self) -> 'TranslateConfig':
|
|
|
|
|
return self.__copy__()
|
|
|
|
|
|
2023-01-03 16:24:06 +08:00
|
|
|
|
|
2023-01-16 18:34:17 +08:00
|
|
|
|
key_type = Union[str, int, Hashable]
|
|
|
|
|
|
|
|
|
|
|
2022-11-26 23:35:49 +08:00
|
|
|
|
class Translates:
|
2023-01-06 20:01:34 +08:00
|
|
|
|
name = 'Translate'
|
|
|
|
|
|
2023-01-19 16:34:06 +08:00
|
|
|
|
def __init__(self, value: Union[Dict[str, Any], list, tuple, str],
|
2023-01-03 16:24:06 +08:00
|
|
|
|
config: Optional[TranslateConfig] = None,
|
2023-01-19 16:34:06 +08:00
|
|
|
|
get_list: Optional[List[Tuple[bool, str]]] = None):
|
|
|
|
|
""" 一个用于翻译的东西
|
2022-11-27 13:45:59 +08:00
|
|
|
|
:param value: 翻译键节点
|
2023-01-03 22:28:26 +08:00
|
|
|
|
:param config: 配置
|
|
|
|
|
:param get_list: 获取列表
|
2022-11-27 13:45:59 +08:00
|
|
|
|
"""
|
2022-11-26 22:45:30 +08:00
|
|
|
|
self.value: Union[Dict[str, Any], list, tuple] = value
|
2023-01-03 16:24:06 +08:00
|
|
|
|
self.config = config or TranslateConfig()
|
2022-11-26 22:45:30 +08:00
|
|
|
|
self.get_list = get_list or []
|
2023-01-03 16:24:06 +08:00
|
|
|
|
|
2023-01-16 18:34:17 +08:00
|
|
|
|
def set_conf_(self, option: Union[str, TranslateConfig],
|
|
|
|
|
value: Optional[Union[bool, List[str]]] = None) -> 'Translates':
|
2023-01-19 16:34:06 +08:00
|
|
|
|
assert isinstance(option, (TranslateConfig, str))
|
2023-01-03 16:24:06 +08:00
|
|
|
|
if isinstance(option, TranslateConfig):
|
|
|
|
|
self.config = option
|
|
|
|
|
return self
|
|
|
|
|
self.config.set(option, value)
|
2023-01-16 18:34:17 +08:00
|
|
|
|
return self
|
|
|
|
|
|
|
|
|
|
def _raise_no_value(self, e: Exception, item: key_type):
|
|
|
|
|
if self.config.raise_error:
|
|
|
|
|
raise TranslateKeyNotFound(self.value, [x[1] for x in self.get_list]) from None
|
2023-01-24 23:59:07 +08:00
|
|
|
|
elif DR_option.report_translate_not_found:
|
2023-01-16 18:34:17 +08:00
|
|
|
|
frame = inspect.currentframe()
|
|
|
|
|
if frame is not None:
|
2023-02-03 00:05:32 +08:00
|
|
|
|
frame = frame.f_back.f_back
|
|
|
|
|
code_list = [self.__getitem__.__code__, self.__getattr__.__code__,
|
|
|
|
|
self.__copy__.__code__, self.copy.__code__,
|
|
|
|
|
Tr.lang.__code__, Tr.__getitem__.__code__,
|
|
|
|
|
Tr.__call__.__code__] # 调用堆栈上的不需要的东西
|
|
|
|
|
while True:
|
|
|
|
|
if frame.f_code not in code_list: # 直到调用堆栈不是不需要的东西
|
|
|
|
|
break
|
|
|
|
|
frame = frame.f_back # 继续向上寻找
|
2023-01-16 18:34:17 +08:00
|
|
|
|
frame = f'call at {frame.f_code.co_filename}:{frame.f_lineno}'
|
|
|
|
|
else:
|
|
|
|
|
frame = 'but No Frame environment'
|
|
|
|
|
raise_info = f"{self.name} Cause a error when getting {item} {frame}"
|
|
|
|
|
print(raise_info)
|
2022-11-26 22:45:30 +08:00
|
|
|
|
|
2023-01-31 22:07:18 +08:00
|
|
|
|
def __getitem__(self, item: Union[key_type, List[key_type], Tuple[key_type]]) -> "Translates":
|
2022-11-26 22:45:30 +08:00
|
|
|
|
try:
|
2023-01-31 22:07:18 +08:00
|
|
|
|
if isinstance(item, (str, int, Hashable)):
|
|
|
|
|
cache_value = self.value[item]
|
|
|
|
|
else:
|
|
|
|
|
cache_value = self.value
|
|
|
|
|
for a_item in item:
|
|
|
|
|
cache_value = cache_value[a_item]
|
2023-01-19 16:34:06 +08:00
|
|
|
|
if isinstance(cache_value, (int, str,)):
|
|
|
|
|
self.config.is_final = True
|
2023-01-16 18:34:17 +08:00
|
|
|
|
self.get_list.append((True, item))
|
|
|
|
|
if self.config.always_copy:
|
2023-01-19 16:34:06 +08:00
|
|
|
|
return Translates(value=cache_value, config=self.config, get_list=self.get_list)
|
|
|
|
|
self.value = cache_value
|
2023-01-16 18:34:17 +08:00
|
|
|
|
except (KeyError, TypeError, AttributeError) as e:
|
|
|
|
|
self.get_list.append((False, item))
|
|
|
|
|
self._raise_no_value(e, item)
|
2023-01-19 16:34:06 +08:00
|
|
|
|
if not self.config.keep_get:
|
|
|
|
|
self.config.is_final = True
|
2023-02-03 20:31:44 +08:00
|
|
|
|
return self
|
2023-01-16 18:34:17 +08:00
|
|
|
|
|
2023-02-03 20:31:44 +08:00
|
|
|
|
def __call__(self, *args, **kwargs) -> Union[dict, list, int, str]:
|
2023-02-03 20:39:40 +08:00
|
|
|
|
return self.__str__()
|
2023-01-31 22:07:18 +08:00
|
|
|
|
|
2023-01-19 16:34:06 +08:00
|
|
|
|
def copy(self):
|
|
|
|
|
return self.__copy__()
|
2023-01-16 18:34:17 +08:00
|
|
|
|
|
|
|
|
|
def __copy__(self) -> 'Translates':
|
2023-02-03 00:05:32 +08:00
|
|
|
|
return Translates(value=self.value, config=self.config, get_list=self.get_list)
|
2022-11-26 21:48:55 +08:00
|
|
|
|
|
2023-01-19 16:34:06 +08:00
|
|
|
|
def __getattr__(self, item: key_type) -> "Translates":
|
2023-02-03 20:31:44 +08:00
|
|
|
|
if (self.config.is_final or any(x[0] for x in self.get_list)) and hasattr(self.value, item):
|
2023-02-03 00:05:32 +08:00
|
|
|
|
return getattr(self.value, item)
|
2023-01-05 21:36:47 +08:00
|
|
|
|
# 实际上我这里完全不需要处理正常需求,因为 __getattribute__ 已经帮我处理过了
|
2022-11-26 21:48:55 +08:00
|
|
|
|
return self.__getitem__(item)
|
|
|
|
|
|
|
|
|
|
def __str__(self):
|
2023-02-03 20:31:44 +08:00
|
|
|
|
if not any(not x[0] for x in self.get_list):
|
|
|
|
|
return self.value
|
2023-01-19 16:34:06 +08:00
|
|
|
|
if self.config.crack_normal:
|
|
|
|
|
return f'{".".join(f"{gets[1]}({gets[0]})" for gets in self.get_list)}'
|
|
|
|
|
elif self.config.insert_crack:
|
|
|
|
|
return f'{self.value}.{".".join(gets[1] for gets in self.get_list if not gets[0])}'
|
|
|
|
|
return self.value
|
2022-11-26 21:48:55 +08:00
|
|
|
|
|
2021-09-02 22:47:10 +08:00
|
|
|
|
|
2022-07-01 13:59:08 +08:00
|
|
|
|
class Tr:
|
|
|
|
|
"""
|
2023-01-16 18:34:17 +08:00
|
|
|
|
我不装了,我就抄了tr(实际上没啥关系)
|
2022-08-16 13:25:44 +08:00
|
|
|
|
GOOD
|
2022-07-01 13:59:08 +08:00
|
|
|
|
"""
|
2023-01-03 16:24:06 +08:00
|
|
|
|
|
2023-01-03 22:28:26 +08:00
|
|
|
|
def __init__(self, language: str = None, config: Optional[TranslateConfig] = None):
|
2022-12-08 09:53:22 +08:00
|
|
|
|
"""
|
|
|
|
|
诶嘿,我抄的MCDR
|
|
|
|
|
:param language: Tr 所使用的的语言
|
2023-01-03 22:28:26 +08:00
|
|
|
|
:param config: 配置
|
2022-12-08 09:53:22 +08:00
|
|
|
|
"""
|
2023-02-03 00:05:32 +08:00
|
|
|
|
self.language_name = language if language is not None else DR_runtime.language
|
2023-01-31 22:07:18 +08:00
|
|
|
|
self.translates: Dict[str, Union[str, Dict]] = tools.load_file(f'configs/lang/{self.language_name}.toml')
|
2022-11-26 21:48:55 +08:00
|
|
|
|
self.default_translate: Dict = tools.load_file(f'configs/lang/{DR_runtime.default_language}.toml')
|
2023-02-03 00:05:32 +08:00
|
|
|
|
self.default_config = config.set('source', self) if config is not None else TranslateConfig(source=self)
|
2023-01-31 22:07:18 +08:00
|
|
|
|
self.translates_cache = Translates(value=self.translates, config=self.default_config.copy())
|
|
|
|
|
|
2023-02-03 20:39:40 +08:00
|
|
|
|
def update_lang(self) -> bool:
|
|
|
|
|
if
|
|
|
|
|
|
2023-01-31 22:07:18 +08:00
|
|
|
|
def default(self, items: Union[str, List[str]]) -> Translates:
|
|
|
|
|
if isinstance(items, list):
|
|
|
|
|
cache_translate = self.default_translate
|
|
|
|
|
for item in items:
|
|
|
|
|
cache_translate = cache_translate[item]
|
|
|
|
|
return cache_translate
|
|
|
|
|
else:
|
|
|
|
|
return self.default_translate[items]
|
|
|
|
|
|
2023-02-03 20:31:44 +08:00
|
|
|
|
def lang(self, *items) -> Translates:
|
2023-02-03 00:05:32 +08:00
|
|
|
|
cache = self.translates_cache.copy()
|
|
|
|
|
for item in items:
|
|
|
|
|
cache = cache[item]
|
|
|
|
|
return cache
|
2023-01-03 16:24:06 +08:00
|
|
|
|
|
2023-02-03 00:05:32 +08:00
|
|
|
|
def __getitem__(self, item: Union[str, int]) -> Translates:
|
|
|
|
|
return self.translates_cache.copy()[item]
|
2023-01-05 21:36:47 +08:00
|
|
|
|
|
2023-02-03 00:05:32 +08:00
|
|
|
|
def __call__(self, *args, **kwargs) -> Translates:
|
|
|
|
|
return self.translates_cache.copy()
|
2022-07-04 10:36:19 +08:00
|
|
|
|
|
2022-07-01 13:59:08 +08:00
|
|
|
|
|
2023-02-03 20:39:40 +08:00
|
|
|
|
tr = Tr()
|