Підручник¶
Ця сторінка веде від порожнього каталогу до програми, що вітається японською. П'ять кроків, досвід із gettext не передбачається, і кожна команда показана з виводом, який вона справді дає, — тож на кожному кроці ви знаєте, чи все йде як слід.
Вам потрібен Python 3.14 або новіший, бо t-рядки — новий синтаксис у 3.14.
Японська — приклад цієї сторінки, але від цього вибору нічого не залежить.
Щоб скористатися іншою мовою, замініть ja на кроці 4 — цей код локалі є
єдиним місцем, що її називає.
1. Встановіть¶
Extra [babel] приносить Babel — інструмент, який на кроці 3 збирає ваші
повідомлення у файли каталогів. Це інструмент часу розробки: продакшн-код
рендерить лише стандартною бібліотекою.
2. Позначте повідомлення в коді¶
Створіть app.py:
t"Hello {name}" виглядає як f-рядок, але префікс t тримає текст і
значення окремо, замість зливати їх на місці. Саме цей поділ дозволяє tr()
знайти переклад для цілого речення Hello {name} і вставити значення вже
після.
Запустіть просто зараз:
Перекладів ще не встановлено, тож початковий текст рендериться як є. Програма з цією бібліотекою ніколи не вимагає каталогу для запуску — англійська (або якою є ваша вихідна мова) слугує вбудованим запасним варіантом.
3. Видобудьте повідомлення¶
Перекладачі зазвичай працюють із каталогами, а не з вихідним кодом, тож між вами й ними подорожує невеликий файл — каталог. Перший крок до нього — зібрати з коду всі позначені повідомлення.
Скажіть Babel, як знаходити ваші повідомлення, створивши babel.cfg:
Потім видобудьте їх у файл-шаблон (.pot):
$ mkdir -p locales
$ pybabel extract -F babel.cfg -c "Translators:" -o locales/messages.pot .
extracting messages from app.py (encoding="utf-8")
writing PO template file to locales/messages.pot
locales/messages.pot тепер містить по одному запису на повідомлення:
msgid — це ключ, за яким шукатиме ваш код. Порожній msgstr — місце для
перекладу, але не в цьому файлі: .pot — це шаблон, і наступний крок
копіює його по одному разу на мову.
4. Перекладіть і скомпілюйте¶
Створіть японський каталог із шаблону:
$ pybabel init -i locales/messages.pot -d locales -l ja
creating catalog locales/ja/LC_MESSAGES/messages.po based on locales/messages.pot
Відкрийте locales/ja/LC_MESSAGES/messages.po і заповніть msgstr:
Залиште {name} точно як є — заповнювач і є тим, як значення знаходить своє
місце всередині перекладеного речення, і переклад вільний пересунути його
туди, куди вимагає цільова мова. У реальному проєкті саме цей файл .po ви
передаєте перекладачеві чи вивантажуєте на платформу перекладу; формат в обох
випадках той самий.
Каталоги редагують як текст, але завантажують у двійковій формі (.mo), тож
скомпілюйте:
$ pybabel compile -d locales
compiling catalog locales/ja/LC_MESSAGES/messages.po to locales/ja/LC_MESSAGES/messages.mo
Ця команда — заразом і страхувальна сітка. Якби переклад пошкодив
заповнювач — скажімо, {nome} замість {name}, — вона відмовилася б його
пропустити:
$ pybabel compile -d locales
error: locales/ja/LC_MESSAGES/messages.po:24: translation does not match the
source placeholders: {name} is missing; {nome} is not in the source message
1 errors encountered.
Одне застереження варто знати вже зараз: вона повідомляє про помилку й виходить
з ненульовим кодом, але .mo усе одно записує. На справжньому проєкті саме CI
має спинитися на цьому коді виходу — У продакшені
це налаштовує.
5. Запустіть¶
Кроки 2–4 використовували tr(), який шукає каталог і не знаходить жодного.
Тепер, коли каталог існує, завантажте його і прив'яжіть один раз: Translator
тримає каталог, тож місцям виклику не доводиться його називати, а _ —
традиційне для gettext ім'я результату.
Спрямуйте app.py на скомпільований каталог. Клацніть на позначки, щоб
побачити, що робить кожен рядок:
import gettext
from gettext_tstrings import Translator
_ = Translator(gettext.translation("messages", localedir="locales", languages=["ja"])) # (1)!
name = "Ada"
print(_(t"Hello {name}")) # (2)!
- Стандартна бібліотека завантажує скомпільований
.mo, аTranslatorприв'язує його до викликаного об'єкта._— традиційне ім'я gettext для «переклади це» — коротке, бо воно з'являється на кожному рядку, який бачить користувач. Він виконує той самий переклад, що йtr, прив'язаний до одного каталогу. - У момент виклику: текст t-рядка стає ключем пошуку
Hello {name}, каталог відповідаєこんにちは {name}, відповідь звіряється із заповнювачами джерела, і лише тоді підставляється значення.
Ось і весь цикл, і його варто побачити однією картиною:
flowchart LR
mark["1–2 позначення<br>t-рядки в коді"] --> extract["3 видобування<br>messages.pot"]
extract --> translate["4 переклад<br>ja/…/messages.po"]
translate --> compile["4 компіляція<br>ja/…/messages.mo"]
compile --> run["5 запуск<br>こんにちは Ada"]
Позначити → видобути → перекласти → скомпілювати → запустити. Усе інше на цьому сайті — уточнення одного з цих п'яти кроків.
Куди далі¶
- Навіщо t-рядки — від чого цей дизайн вас захищає порівняно
з
%(name)s,.format()та$-рядками. - Посібник — множина, мова на запит, відкладені рядки і що відбувається під час виконання, коли каталог усе-таки хибний.
- У продакшені — цей самий цикл, як його веде команда тиждень за тижнем: оновлення каталогів, шлюзи CI та платформи перекладу.
- Видобування — повний довідник із
pybabel: власні імена функцій, строгий режим для CI та перевірки, що охороняють ваші каталоги. - Міграція — якщо в проєкті, де ви насправді хочете це зробити, вже є каталоги gettext.
- Для перекладачів — єдина сторінка, яку варто дати тому, хто
заповнює рядки
msgstr.