(feature): Add basic streamalerts.
This commit is contained in:
3
src/babel/__init__.py
Normal file
3
src/babel/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .translator import SOURCE_LOCALE, LeoBabel, LocalBabel, LazyStr, ctx_locale, ctx_translator
|
||||
|
||||
babel = LocalBabel('babel')
|
||||
81
src/babel/enums.py
Normal file
81
src/babel/enums.py
Normal file
@@ -0,0 +1,81 @@
|
||||
from enum import Enum
|
||||
from . import babel
|
||||
|
||||
_p = babel._p
|
||||
|
||||
|
||||
class LocaleMap(Enum):
|
||||
american_english = 'en-US'
|
||||
british_english = 'en-GB'
|
||||
bulgarian = 'bg'
|
||||
chinese = 'zh-CN'
|
||||
taiwan_chinese = 'zh-TW'
|
||||
croatian = 'hr'
|
||||
czech = 'cs'
|
||||
danish = 'da'
|
||||
dutch = 'nl'
|
||||
finnish = 'fi'
|
||||
french = 'fr'
|
||||
german = 'de'
|
||||
greek = 'el'
|
||||
hindi = 'hi'
|
||||
hungarian = 'hu'
|
||||
italian = 'it'
|
||||
japanese = 'ja'
|
||||
korean = 'ko'
|
||||
lithuanian = 'lt'
|
||||
norwegian = 'no'
|
||||
polish = 'pl'
|
||||
brazil_portuguese = 'pt-BR'
|
||||
romanian = 'ro'
|
||||
russian = 'ru'
|
||||
spain_spanish = 'es-ES'
|
||||
swedish = 'sv-SE'
|
||||
thai = 'th'
|
||||
turkish = 'tr'
|
||||
ukrainian = 'uk'
|
||||
vietnamese = 'vi'
|
||||
hebrew = 'he-IL'
|
||||
|
||||
|
||||
# Original Discord names
|
||||
locale_names = {
|
||||
'id': (_p('localenames|locale:id', "Indonesian"), "Bahasa Indonesia"),
|
||||
'da': (_p('localenames|locale:da', "Danish"), "Dansk"),
|
||||
'de': (_p('localenames|locale:de', "German"), "Deutsch"),
|
||||
'en-GB': (_p('localenames|locale:en-GB', "English, UK"), "English, UK"),
|
||||
'en-US': (_p('localenames|locale:en-US', "English, US"), "English, US"),
|
||||
'es-ES': (_p('localenames|locale:es-ES', "Spanish"), "Español"),
|
||||
'fr': (_p('localenames|locale:fr', "French"), "Français"),
|
||||
'hr': (_p('localenames|locale:hr', "Croatian"), "Hrvatski"),
|
||||
'it': (_p('localenames|locale:it', "Italian"), "Italiano"),
|
||||
'lt': (_p('localenames|locale:lt', "Lithuanian"), "Lietuviškai"),
|
||||
'hu': (_p('localenames|locale:hu', "Hungarian"), "Magyar"),
|
||||
'nl': (_p('localenames|locale:nl', "Dutch"), "Nederlands"),
|
||||
'no': (_p('localenames|locale:no', "Norwegian"), "Norsk"),
|
||||
'pl': (_p('localenames|locale:pl', "Polish"), "Polski"),
|
||||
'pt-BR': (_p('localenames|locale:pt-BR', "Portuguese, Brazilian"), "Português do Brasil"),
|
||||
'ro': (_p('localenames|locale:ro', "Romanian, Romania"), "Română"),
|
||||
'fi': (_p('localenames|locale:fi', "Finnish"), "Suomi"),
|
||||
'sv-SE': (_p('localenames|locale:sv-SE', "Swedish"), "Svenska"),
|
||||
'vi': (_p('localenames|locale:vi', "Vietnamese"), "Tiếng Việt"),
|
||||
'tr': (_p('localenames|locale:tr', "Turkish"), "Türkçe"),
|
||||
'cs': (_p('localenames|locale:cs', "Czech"), "Čeština"),
|
||||
'el': (_p('localenames|locale:el', "Greek"), "Ελληνικά"),
|
||||
'bg': (_p('localenames|locale:bg', "Bulgarian"), "български"),
|
||||
'ru': (_p('localenames|locale:ru', "Russian"), "Pусский"),
|
||||
'uk': (_p('localenames|locale:uk', "Ukrainian"), "Українська"),
|
||||
'hi': (_p('localenames|locale:hi', "Hindi"), "हिन्दी"),
|
||||
'th': (_p('localenames|locale:th', "Thai"), "ไทย"),
|
||||
'zh-CN': (_p('localenames|locale:zh-CN', "Chinese, China"), "中文"),
|
||||
'ja': (_p('localenames|locale:ja', "Japanese"), "日本語"),
|
||||
'zh-TW': (_p('localenames|locale:zh-TW', "Chinese, Taiwan"), "繁體中文"),
|
||||
'ko': (_p('localenames|locale:ko', "Korean"), "한국어"),
|
||||
}
|
||||
|
||||
# More names for languages not supported by Discord
|
||||
locale_names |= {
|
||||
'he': (_p('localenames|locale:he', "Hebrew"), "Hebrew"),
|
||||
'he-IL': (_p('localenames|locale:he-IL', "Hebrew"), "Hebrew"),
|
||||
'ceaser': (_p('localenames|locale:test', "Test Language"), "dfbtfs"),
|
||||
}
|
||||
108
src/babel/translator.py
Normal file
108
src/babel/translator.py
Normal file
@@ -0,0 +1,108 @@
|
||||
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)
|
||||
20
src/babel/utils.py
Normal file
20
src/babel/utils.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from .translator import ctx_translator
|
||||
from . import babel
|
||||
|
||||
_, _p, _np = babel._, babel._p, babel._np
|
||||
|
||||
|
||||
MONTHS = _p(
|
||||
'utils|months',
|
||||
"January,February,March,April,May,June,July,August,September,October,November,December"
|
||||
)
|
||||
|
||||
SHORT_MONTHS = _p(
|
||||
'utils|short_months',
|
||||
"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"
|
||||
)
|
||||
|
||||
|
||||
def local_month(month, short=False):
|
||||
string = MONTHS if not short else SHORT_MONTHS
|
||||
return ctx_translator.get().t(string).split(',')[month-1]
|
||||
Reference in New Issue
Block a user