Переводы
m.T
m.T(key, default) возвращает перевод для key или default, если перевода нет.
return msg.Answer(m.T("no_city", "❌ <b>Какой город?</b>"))Значение по умолчанию — не заглушка, а тот текст, с которым модуль поставляется. Модуль без файлов перевода работает прекрасно; переводы — это улучшение.
Всегда передавайте настоящий текст по умолчанию
m.T("no_city", "") при отсутствии ключа отправит пустое сообщение. Пишите ту фразу, которую действительно хотите показать.
Объявление строк
Strings — это каталог того, что ваш модуль умеет говорить:
func (m *Weather) Strings() map[string]string {
return map[string]string{
"name": "Weather",
"_cls_doc": "Погода в городе",
"_cmd_doc_weather": "[город] — показать погоду",
"no_city": "❌ <b>Какой город?</b>",
"not_found": "❌ <b>Город не найден</b>",
}
}| Префикс | Где показывается |
|---|---|
name | Имя модуля в .help |
_cls_doc | Описание модуля |
_cmd_doc_<cmd> | Строка справки этой команды |
_cfg_<key> | Описание этой настройки |
| всё остальное | Везде, где вы вызовете m.T |
Как разрешается ключ
m.T("no_city", ...) ищет goroku.modules.<модуль>.no_city, пробуя имя модуля как написано, в нижнем регистре и в snake_case. Поэтому Weather совпадает с weather, а APILimiter — с api_limiter.
Устаревшие имена
Если переводы лежат под именем, которое не выводится из Name(), скажите об этом явно:
func (m *APIProtection) Name() string { return "APILimiter" }
func (m *APIProtection) TranslationAliases() []string {
return []string{"api_protection"}
}Алиасы пробуются после выведенных имён.
Подстановка
m.T возвращает строку; форматирование — на вас:
tpl := m.T("found", "🌤 <b>{}</b>: {}°C")
return msg.Answer(strings.Replace(strings.Replace(tpl, "{}", city, 1), "{}", temp, 1))Для двух и более значений берите именованные плейсхолдеры: переводчики меняют порядок слов, и позиционные {} при этом ломаются:
tpl := m.T("found", "🌤 <b>{city}</b>: {temp}°C")
out := strings.NewReplacer("{city}", city, "{temp}", temp).Replace(tpl)
return msg.Answer(out)Экранирование
Переведённый текст — это Telegram HTML. Экранируйте всё, что подставляете от пользователя:
import "goroku/goroku/utils"
out := strings.Replace(tpl, "{city}", utils.EscapeHTML(city), 1)