109 lines
2.9 KiB
Python
109 lines
2.9 KiB
Python
from typing import Optional
|
|
import logging
|
|
from contextvars import ContextVar
|
|
from collections import defaultdict
|
|
from enum import Enum
|
|
|
|
import gettext
|
|
|
|
from discord.app_commands import Translator, locale_str
|
|
from discord.enums import Locale
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
SOURCE_LOCALE = 'en_GB'
|
|
ctx_locale: ContextVar[str] = ContextVar('locale', default=SOURCE_LOCALE)
|
|
ctx_translator: ContextVar['LeoBabel'] = ContextVar('translator', default=None) # type: ignore
|
|
|
|
null = gettext.NullTranslations()
|
|
|
|
|
|
class LeoBabel(Translator):
|
|
def __init__(self):
|
|
self.supported_locales = {loc.name for loc in Locale}
|
|
self.supported_domains = {}
|
|
self.translators = defaultdict(dict) # locale -> domain -> GNUTranslator
|
|
|
|
async def load(self):
|
|
pass
|
|
|
|
async def unload(self):
|
|
self.translators.clear()
|
|
|
|
def get_translator(self, locale: Optional[str], domain):
|
|
return null
|
|
|
|
def t(self, lazystr, locale=None):
|
|
return lazystr._translate_with(null)
|
|
|
|
async def translate(self, string: locale_str, locale: Locale, context):
|
|
if not isinstance(string, LazyStr):
|
|
return string
|
|
else:
|
|
return string.message
|
|
|
|
ctx_translator.set(LeoBabel())
|
|
|
|
class Method(Enum):
|
|
GETTEXT = 'gettext'
|
|
NGETTEXT = 'ngettext'
|
|
PGETTEXT = 'pgettext'
|
|
NPGETTEXT = 'npgettext'
|
|
|
|
|
|
class LocalBabel:
|
|
def __init__(self, domain):
|
|
self.domain = domain
|
|
|
|
@property
|
|
def methods(self):
|
|
return (self._, self._n, self._p, self._np)
|
|
|
|
def _(self, message):
|
|
return LazyStr(Method.GETTEXT, message, domain=self.domain)
|
|
|
|
def _n(self, singular, plural, n):
|
|
return LazyStr(Method.NGETTEXT, singular, plural, n, domain=self.domain)
|
|
|
|
def _p(self, context, message):
|
|
return LazyStr(Method.PGETTEXT, context, message, domain=self.domain)
|
|
|
|
def _np(self, context, singular, plural, n):
|
|
return LazyStr(Method.NPGETTEXT, context, singular, plural, n, domain=self.domain)
|
|
|
|
|
|
class LazyStr(locale_str):
|
|
__slots__ = ('method', 'args', 'domain', 'locale')
|
|
|
|
def __init__(self, method, *args, locale=None, domain=None):
|
|
self.method = method
|
|
self.args = args
|
|
self.domain = domain
|
|
self.locale = locale
|
|
|
|
@property
|
|
def message(self):
|
|
return self._translate_with(null)
|
|
|
|
@property
|
|
def extras(self):
|
|
return {'locale': self.locale, 'domain': self.domain}
|
|
|
|
def __str__(self):
|
|
return self.message
|
|
|
|
def _translate_with(self, translator: gettext.GNUTranslations):
|
|
method = getattr(translator, self.method.value)
|
|
return method(*self.args)
|
|
|
|
def __repr__(self) -> str:
|
|
return f'{self.__class__.__name__}({self.method}, {self.args!r}, locale={self.locale}, domain={self.domain})'
|
|
|
|
def __eq__(self, obj: object) -> bool:
|
|
return isinstance(obj, locale_str) and self.message == obj.message
|
|
|
|
def __hash__(self) -> int:
|
|
return hash(self.args)
|