🌎 Переводы
Введение
Для поддержки многоязычия в PBModular встроена система переводов. Модули могут предоставлять переводы для разных языков, и фреймворк автоматически загрузит и сделает их доступными, основываясь на глобальной языковой конфигурации бота.
Шаг 1: Создание файлов перевода
- Внутри каталога вашего модуля создайте папку с именем
strings/
. - Внутри
strings/
создайте YAML-файлы для каждого языка, который вы хотите поддерживать. В имени файла должен быть указан код языка ISO 639-1 (например, en.yaml, ru.yaml, es.yaml). - Структурируйте переводы в файлах YAML, используя вложенные ключи для организации.
Пример strings/en.yaml:
# strings/en.yaml
greeting: "Hello, {user}!"
farewell: Goodbye, {user}!
errors:
not_found: "Sorry, the item could not be found."
permission_denied: |
You do not have permission to do that.
{user}
Шаг 2: Загрузка переводов
Во время инициализации модуля BaseModule
автоматически:
- Сканирует каталог
strings/
. - Загружает все найденные валидные файлы
.yaml
в словарь, доступный черезself.rawS
. Ключами являются коды языков (например,self.rawS['en']
,self.rawS['ru']
). - Определяет язык для использования на основе глобальной конфигурации бота (
config.language
иconfig.fallback_language
).- Сначала проверяется
config.language
. - Если он не найден в
self.rawS
, он пробуетconfig.fallback_language
. - Если запасной язык также не найден, выдается предупреждение и используется первый язык, загруженный в
self.rawS
.
- Сначала проверяется
- Загружает переводы выбранного языка (потенциально объединенные с языком резервного копирования для отсутствующих ключей) в
self.S
. Этот объектself.S
являетсяSafeDict
, то есть обращение к несуществующему ключу возвращает сам ключ, а не вызывает ошибкуKeyError
. - Хранит код активного в данный момент языка в
self.cur_lang
.
Слияние с резервным языком
Если в папке strings/ вашего модуля есть и основной язык (config.language
), и запасной язык (config.fallback_language
), фреймворк создает объединенный словарь для self.S
. Он начинает с копии строк резервного языка, а затем объединяет строки основного языка. Это означает, что любая строка, присутствующая в первичном языке, отменяет значение резервного, но любая строка, отсутствующая в первичном, но присутствующая в резервном, все равно будет доступна.
Шаг 3: Использование переводов в коде
Доступ к переведенным строкам через словарь self.S
. Используйте стандартное форматирование строк Python (.format()
или f-strings) для вставки переменных.
# Внутри метода BaseModule или ModuleExtension
async def greet_user(self, message: Message):
user_name = message.from_user.first_name
# Доступ к простой строке
await message.reply(self.S["greeting"].format(user=user_name))
async def show_help(self, message: Message):
help_title = self.S["help"]["title"] # Доступ к вложенным ключам
command_name = "mycommand"
usage_text = self.S["help"]["usage"].format(command=command_name)
await message.reply(f"**{help_title}**\n\n{usage_text}")
async def handle_error(self, message: Message, error_key: str):
# Использование свойства SafeDict: если ключ отсутствует, возвращается сам ключ
error_message = self.S["errors"][error_key]
await message.reply(f"Error: {error_message}")
# Пример доступа к необработанным переводам или текущему языку
def log_languages(self):
self.logger.info(f"Current language code: {self.cur_lang}")
self.logger.info(f"Available language codes: {list(self.rawS.keys())}")
# Прямой доступ к конкретному языку (встречается реже)
# english_farewell = self.rawS.get("en", {}).get("farewell", "Fallback Farewell")
Использование этой системы гарантирует, что ваш модуль легко адаптируется к различным языкам, настроенным в боте, обеспечивая лучший пользовательский опыт.