Compare commits

...

11 Commits

Author SHA1 Message Date
SantaSpeen 8792aaeeb9 [+] dedent fix 2025-05-13 18:43:21 +03:00
SantaSpeen 774a1b0ce3 [+] dedent 2025-05-13 18:35:31 +03:00
SantaSpeen 633c92608f [^] url 2025-03-24 00:55:49 +03:00
SantaSpeen 3f0fe22317 [КОСТЫЛЬ] if no {} in phrase - str JUST NOW 2025-03-23 05:34:26 +03:00
SantaSpeen 2a3eca2c31 [-] print 2025-03-23 04:19:19 +03:00
SantaSpeen f26cc65c7f .idea 2025-03-23 04:11:03 +03:00
SantaSpeen 0b9f8b6feb [!] fix2 __getattr__ 2025-03-23 03:45:30 +03:00
SantaSpeen 3581e6ae44 [!] fix __setattr__ 2025-03-23 03:00:10 +03:00
SantaSpeen c261f7e140 [^] builtins hack 2025-03-23 02:52:54 +03:00
SantaSpeen cf50296264 [+] NestedAccessor
[+] support __getattr__
[+] support some.key.here
2025-03-23 02:40:47 +03:00
SantaSpeen 6a0347e7c4 [-] resources 2025-03-23 02:23:23 +03:00
4 changed files with 109 additions and 5 deletions
+1
View File
@@ -168,3 +168,4 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
resources/
+1 -1
View File
@@ -21,5 +21,5 @@ fmt = "<green>{elapsed} -- {time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{leve
Добавление в проект:
```bash
git submodule add ssh://git@git.anidev.ru:222/andiev-soft/I18N-Module src/modules/i18n
git submodule add ssh://git@git.anidev.ru:222/AnidevSoft/I18N-Module.git src/modules/i18n
```
+32 -1
View File
@@ -1,3 +1,23 @@
class _i18_proxy:
@staticmethod
def __getattr__(item):
"""
Get the phrase from the locale file. If the phrase is not found, return the key in uppercase.
:param key: Key to search in the locale file.
:param kwargs: Arguments to format the phrase.
:return: The phrase from the locale file.
"""
@staticmethod
def __init__(**kwargs):
"""
Get the phrase from the locale file. If the phrase is not found, return the key in uppercase.
:param key: Key to search in the locale file.
:param kwargs: Arguments to format the phrase.
:return: The phrase from the locale file.
"""
class i18n:
@staticmethod
def set_lang(lang, encoding=None) -> None:
@@ -17,7 +37,18 @@ class i18n:
:return: The phrase from the locale file.
"""
@staticmethod
def __call__(key: str, **kwargs) -> str:
def __getattr__(item):
"""
Get the phrase from the locale file. If the phrase is not found, return the key in uppercase.
:param key: Key to search in the locale file.
:param kwargs: Arguments to format the phrase.
:return: The phrase from the locale file.
"""
key = item.replace("_", ".") # заменяем _ на . для удобства
return _i18_proxy([key]) # Начинаем цепочку
@staticmethod
def __init__(key: str, **kwargs) -> str:
"""
Get the phrase from the locale file. If the phrase is not found, return the key in uppercase.
+74 -2
View File
@@ -1,14 +1,65 @@
import builtins
import textwrap
from collections import defaultdict
import json5
from loguru import logger
try:
from . import utils
except ImportError:
import utils
log = logger.bind(module="i18n", prefix="init")
log_load = logger.bind(module="i18n", prefix="load")
str_funcs = {attr for attr in dir(str)}
str_funcs.add('__func__')
str_funcs.remove('__init__')
str_funcs.remove('__len__')
str_funcs.remove('__hash__')
str_funcs.remove('__add__')
str_funcs.remove('__str__')
str_funcs.remove('__repr__')
class NestedAccessor:
def __init__(self, parent, key_chain):
self.parent: "I18N" = parent
self.key_chain = key_chain
self.__name__ = f'\r<{".".join(key_chain)}>'.upper()
# self.__func__ = self.key_chain
def __getattr__(self, item):
# Если нет метода, то возвращаем str
key = ".".join((*self.key_chain, item))
if key in self.parent.locale:
if "{" not in self.parent.locale[key]:
return self.parent.get_phrase(key)
if item in str_funcs:
return getattr(self(), item)
return NestedAccessor(self.parent, self.key_chain + [item])
def __len__(self):
return len(self())
def __hash__(self):
return hash(self())
def __call__(self, **kwargs):
key = ".".join(self.key_chain)
return self.parent.get_phrase(key, **kwargs)
def __add__(self, other):
return self() + other
def __str__(self):
return self()
def __repr__(self):
return f"<NestedAccessor key={'.'.join(self.key_chain)}>"
class I18N:
def __init__(self, locale_dir, load_lang, encoding):
@@ -29,6 +80,10 @@ class I18N:
log.debug("Ready")
self._load()
@property
def locale(self):
return self._locale
def _load(self):
if not self._locale_dir:
raise FileNotFoundError(f"Locale directory not found: {self._locale_dir}")
@@ -63,11 +118,28 @@ class I18N:
# key: some.key.here
phrase = self._locale.get(key)
if not phrase:
return key.upper()
return phrase.format_map(defaultdict(lambda: '???', kwargs))
return f"<{key.upper()}>"
return textwrap.dedent(phrase.format_map(defaultdict(lambda: '<unknown>', kwargs)))
def __getattr__(self, item):
key = item.replace("_", ".") # заменяем _ на . для удобства
return NestedAccessor(self, [key]) # Начинаем цепочку
def __call__(self, key: str, **kwargs):
return self.get_phrase(key, **kwargs)
def __getitem__(self, key: str):
return self.get_phrase(key)
if __name__ == '__main__':
i18n = I18N("", "ru", "utf-8")
print(1, i18n.get_phrase("some.key.here", name="John"))
print(2, i18n("some.key.here", name="John"))
print(3, i18n["some.key.here"])
print(4, i18n.some_key_here(name="John"))
print(5, i18n.some_key_here)
print(6, i18n.some.key.here(name="John"))
print(7, i18n.some.key.here)
print(8, i18n.some.key.no.registered)