shibaev164

generate_i18n_stub

Oct 3rd, 2025
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.84 KB | None | 0 0
  1. # presentation/bot/scripts/generate_i18n_stub.py
  2. from pathlib import Path
  3. import re
  4.  
  5. LOCALES_PATH = Path(__file__).parent.parent / "locales"
  6. STUB_FILE = Path(__file__).parent.parent / "i18n.pyi"
  7. LANGUAGES = ["ru", "en"]
  8.  
  9.  
  10. def extract_key_value(ftl_path: Path) -> dict[str, str]:
  11.     """Извлекает ключи и значения из одного .ftl файла."""
  12.     key_values = {}
  13.     current_key = None
  14.     current_value = []
  15.  
  16.     for line in ftl_path.read_text(encoding="utf-8").splitlines():
  17.         if not line.strip() or line.strip().startswith("#"):
  18.             continue
  19.  
  20.         if "=" in line and not line.startswith(" "):
  21.             # Сохраняем предыдущий ключ-значение
  22.             if current_key and current_value:
  23.                 key_values[current_key] = "\n".join(current_value).strip()
  24.  
  25.             # Начинаем новый ключ-значение
  26.             key, value = line.split("=", 1)
  27.             current_key = key.strip().replace("-", "_")
  28.             current_value = [value.strip()]
  29.         elif current_key:
  30.             # Продолжение многострочного значения (может быть с отступом или без)
  31.             current_value.append(line.strip())
  32.  
  33.     # Сохраняем последний ключ-значение
  34.     if current_key and current_value:
  35.         key_values[current_key] = "\n".join(current_value).strip()
  36.  
  37.     return key_values
  38.  
  39.  
  40. def collect_all_translations(base_path: Path) -> dict[str, dict[str, str]]:
  41.     """Собирает все переводы из всех .ftl файлов для всех языков."""
  42.     all_translations = {}
  43.  
  44.     for lang in LANGUAGES:
  45.         lang_path = base_path / lang
  46.         if not lang_path.exists():
  47.             continue
  48.  
  49.         lang_translations = {}
  50.         for ftl_file in lang_path.rglob("*.ftl"):
  51.             key_values = extract_key_value(ftl_file)
  52.             lang_translations.update(key_values)
  53.  
  54.         if lang_translations:
  55.             all_translations[lang] = lang_translations
  56.  
  57.     return all_translations
  58.  
  59.  
  60. def clean_text_for_docstring(text: str) -> str:
  61.     """Очищает текст для использования в docstring."""
  62.     # Убираем HTML теги
  63.     # text = re.sub(r"<[^>]+>", "", text)
  64.     # Заменяем переменные в фигурных скобках на более читаемый вид
  65.     # text = re.sub(r"\{[^}]+\}", "{var}", text)
  66.     # Заменяем переменные в долларах на более читаемый вид
  67.     # text = re.sub(r"\$[a-zA-Z_]+", "{var}", text)
  68.     # Убираем лишние пробелы и переносы строк
  69.     # text = re.sub(r"\s+", " ", text).strip()
  70.     # Ограничиваем длину
  71.     if len(text) > 200:
  72.         text = text[:200] + "..."
  73.     return text
  74.  
  75.  
  76. def generate_stub():
  77.     """Генерирует i18n.pyi для автодополнения методов и объекта i18n с docstring."""
  78.     all_translations = collect_all_translations(LOCALES_PATH)
  79.  
  80.     # Получаем все уникальные ключи
  81.     all_keys = set()
  82.     for lang_translations in all_translations.values():
  83.         all_keys.update(lang_translations.keys())
  84.     all_keys = sorted(all_keys)
  85.  
  86.     with open(STUB_FILE, "w", encoding="utf-8") as f:
  87.         f.write("# presentation/bot/i18n.pyi\n\n")
  88.         f.write("from typing import Literal\n\n")
  89.         f.write("class I18n:\n")
  90.         f.write(
  91.             "    def __init__(self, locale: Literal['ru', 'en'] = 'ru') -> None: ...\n\n"
  92.         )
  93.  
  94.         for key in all_keys:
  95.             # Собираем docstring из всех доступных переводов
  96.             docstring_parts = []
  97.             for lang in LANGUAGES:
  98.                 if lang in all_translations and key in all_translations[lang]:
  99.                     text = all_translations[lang][key]
  100.                     clean_text = clean_text_for_docstring(text)
  101.                     if clean_text:
  102.                         docstring_parts.append(f"{lang}: {clean_text}")
  103.  
  104.             if docstring_parts:
  105.                 docstring = "\n".join(docstring_parts)
  106.                 f.write(f"    def {key}(self, **kwargs) -> str:\n")
  107.                 f.write(f'        """{docstring}"""\n')
  108.                 f.write(f"        ...\n\n")
  109.             else:
  110.                 f.write(f"    def {key}(self, **kwargs) -> str: ...\n\n")
  111.  
  112.         f.write("\n")
  113.         f.write("i18n: I18n\n")
  114.  
  115.  
  116. if __name__ == "__main__":
  117.     generate_stub()
  118.     print(f"Stub i18n.pyi сгенерирован для всех ключей в {LOCALES_PATH}")
  119.     print(
  120.         "Теперь при наведении на методы i18n будут отображаться переводы из .ftl файлов!"
  121.     )
  122.  
Advertisement
Add Comment
Please, Sign In to add comment