Archived
1
0
Fork 0
This repository has been archived on 2024-04-26. You can view files and clone it, but cannot push or open issues or pull requests.
akari-bot/core/utils/i18n.py

96 lines
2.8 KiB
Python
Raw Normal View History

2022-08-18 01:16:48 +00:00
import os
2022-08-18 05:46:18 +00:00
from collections.abc import MutableMapping
2022-08-30 12:49:01 +00:00
from string import Template
from typing import TypedDict
import ujson as json
2022-08-18 05:46:18 +00:00
from core.elements.message import MessageSession
2022-08-18 01:16:48 +00:00
# Load all locale files into memory
# We might change this behavior in the future and read them on demand as
# locale files get too large
locale_cache = {}
2022-08-18 15:26:26 +00:00
2022-08-18 05:46:18 +00:00
# From https://stackoverflow.com/a/6027615
def flatten(d, parent_key='', sep='.'):
items = []
for k, v in d.items():
new_key = parent_key + sep + k if parent_key else k
if isinstance(v, MutableMapping):
items.extend(flatten(v, new_key, sep=sep).items())
else:
items.append((new_key, v))
return dict(items)
2022-08-18 15:26:26 +00:00
def remove_suffix(string, suffix):
return string[:-len(suffix)] if string.endswith(suffix) else string
2022-08-18 01:16:48 +00:00
def load_locale_file():
locales = os.listdir('./locales')
for l in locales:
with open(f'./locales/{l}', 'r', encoding='utf-8') as f:
2022-08-18 15:26:26 +00:00
locale_cache[remove_suffix(l, '.json')] = flatten(json.load(f))
2022-08-18 01:16:48 +00:00
load_locale_file()
2022-08-18 15:26:26 +00:00
2022-08-18 01:16:48 +00:00
class LocaleFile(TypedDict):
key: str
string: str
class Locale:
2022-08-18 15:26:26 +00:00
def __init__(self, locale: str, fallback_lng=None):
"""创建一个本地化对象"""
2022-08-18 01:16:48 +00:00
2022-08-18 15:26:26 +00:00
if fallback_lng is None:
fallback_lng = ['zh_cn', 'en_us']
2022-08-18 01:16:48 +00:00
self.locale = locale
self.data: LocaleFile = locale_cache[locale]
self.fallback_lng = fallback_lng
def __getitem__(self, key: str):
return self.data[key]
def __contains__(self, key: str):
return key in self.data
2022-08-18 07:31:24 +00:00
def t(self, key: str, *args, **kwargs) -> str:
2022-08-18 01:16:48 +00:00
'''获取本地化字符串'''
2022-08-18 07:31:24 +00:00
localized = self.get_string_with_fallback(key)
return Template(localized).safe_substitute(*args, **kwargs)
2022-08-18 01:16:48 +00:00
def get_string_with_fallback(self, key: str) -> str:
value = self.data.get(key, None)
if value is not None:
2022-08-18 15:26:26 +00:00
return value # 1. 如果本地化字符串存在,直接返回
2022-08-18 01:16:48 +00:00
fallback_lng = list(self.fallback_lng)
fallback_lng.insert(0, self.locale)
for lng in fallback_lng:
if lng in locale_cache:
string = locale_cache[lng].get(key, None)
if string is not None:
2022-08-18 15:26:26 +00:00
return string # 2. 如果在 fallback 语言中本地化字符串存在,直接返回
return key # 3. 如果在 fallback 语言中本地化字符串不存在,返回 key
2022-08-18 01:16:48 +00:00
2022-08-18 05:46:18 +00:00
def get_target_locale_setting(msg: MessageSession):
return msg.locale
2022-08-18 05:46:18 +00:00
def get_target_locale(msg: MessageSession):
2022-08-18 07:31:24 +00:00
return Locale(str(get_target_locale_setting(msg)))
2022-08-18 05:46:18 +00:00
def get_available_locales():
return list(locale_cache.keys())
__all__ = ['Locale', 'load_locale_file', 'get_target_locale', 'get_target_locale_setting', 'get_available_locales']