Як перекладати файли .po Drupal за допомогою ШІ

Більшість людей асоціюють файли .po з WordPress, але формат gettext передує WordPress на десятиліття і забезпечує переклад інтерфейсу в усьому світі відкритого вихідного коду. Drupal є одним з його найбільших користувачів. Якщо ви керуєте багатомовним сайтом Drupal, кожна мітка меню, опис поля, повідомлення про помилку та рядок модуля проходять через файли .po точно так само, як у WordPress, лише з іншим діалектом заповнювачів та іншим робочим процесом імпорту. І так само, як у WordPress, щойно ваш сайт перевищує кілька десятків рядків, ручний переклад цих файлів стає вузьким місцем.
Цей посібник про те, як перекладати файли .po Drupal за допомогою ШІ, не порушуючи того, що робить Drupal Drupal. Ми розглянемо систему перекладу Drupal, звідки насправді походять рядки, синтаксис заповнювачів, який відрізняється від WordPress і абсолютно має бути збережений, а також повний цикл експорту, перекладу та повторного імпорту, включаючи команди drush, які роблять його повторюваним.
Як працює система перекладу Drupal
Drupal обробляє переклад інтерфейсу через базовий модуль locale (іноді його називають "Переклад інтерфейсу" в сучасному Drupal). Після ввімкнення він керує таблицею бази даних вихідних рядків та їх перекладів для кожної мови, а також може імпортувати та експортувати ці переклади як стандартні файли gettext .po.
Адміністративний інтерфейс розташований за адресою /admin/config/regional/translate. Звідти ви можете шукати неперекладені рядки, редагувати їх вбудовано та, що важливо, імпортувати файл .po для масового завантаження перекладів або експортувати поточний стан до файлу .po для офлайн-редагування. Цей цикл експорт/редагування/імпорт є робочим процесом, який ми оптимізуємо.
На відміну від WordPress, де кожен плагін і тема постачає власні файли .po та .mo в каталозі languages/, Drupal централізує рядки інтерфейсу у своїй базі даних і розглядає .po як формат обміну. Ви експортуєте, працюєте над файлом, а потім імпортуєте його назад. Крок компіляції .mo, який вимагає WordPress, обробляється внутрішньо.
Звідки беруться рядки
Рядки Drupal походять з трьох місць, і повний переклад має охоплювати всі з них:
- Ядро містить тисячі рядків, що підлягають перекладу, для адміністративного інтерфейсу, форм і системних повідомлень.
- Додаткові модулі (Views, Webform, Commerce та інші) реєструють власні рядки за допомогою функції
t(). - Теми надають рядки шаблонів, мітки регіонів та описи налаштувань тем.
Коли ви експортуєте з /admin/config/regional/translate, ви можете обмежити експорт перекладеними, неперекладеними або всіма рядками. Для нового етапу перекладу експорт лише неперекладених рядків надає вам цілеспрямований файл .po з точно тією роботою, яка залишається.
Практичний наслідок цієї триджерельної структури: ваша робота з перекладу ніколи не буває повністю "завершеною". Кожного разу, коли ви додаєте додатковий модуль, вмикаєте нову функцію або оновлюєте ядро Drupal, у таблицях локалізації з'являється нова партія неперекладених записів msgid. Ось чому команди Drupal розглядають переклад як постійний конвеєр, а не як одноразове завдання запуску. Той самий цикл експорту, перекладу та повторного імпорту виконується при кожному розгортанні, яке стосується модулів, і чим швидший цей цикл, тим менше накопичується боргу з перекладу між випусками.
Варто також зазначити, що Drupal може автоматично отримувати переклади, надані спільнотою, з localize.drupal.org для ядра та популярних додаткових модулів. Вони охоплюють загальні рядки, але рідко охоплюють ваші власні модулі, вашу тему або специфічні для проєкту формулювання, які використовує ваш сайт. Розрив між перекладом спільноти та повністю локалізованим сайтом — це саме та робота, яку ШІ швидко усуває.
Заповнювачі Drupal — це не заповнювачі WordPress
Ось найважливіше, що потрібно зрозуміти, перш ніж надсилати будь-який файл .po Drupal перекладачу ШІ: Drupal не використовує заповнювачі у стилі printf %s та %1$s, які домінують у WordPress. Функція t() Drupal використовує три різні префікси заповнювачів, кожен з яких має різну поведінку екранування:
@variable— значення екранується HTML, безпечний стандарт для тексту, наданого користувачем.%variable— значення екранується та обгортається в розмітку виділення<em>.:placeholder— використовується для атрибутів URL, проходить через санітизацію URL.
Типовий вихідний рядок Drupal виглядає так у експортованому файлі .po:
#: core/modules/node/node.module
msgid "@count comments"
msgid_plural "@count comments"
msgstr[0] ""
msgstr[1] ""
#: core/modules/user/user.module
msgid "Welcome @name, you last logged in on %date."
msgstr ""
Якщо перекладач змінює @count на @cuenta, замінює @name перекладеним словом "ім'я" або вставляє пробіл, перетворюючи @count на @ count, заповнювач більше не відповідає тому, що передається викликом t(). Тоді Drupal виводить буквальний токен @count на сторінку замість фактичного числа. Переклад виглядає завершеним, але сайт помітно зламаний.
Це той самий тип помилок, який трапляється з рядками %s у WordPress, і ми детально розглядаємо загальний принцип у статті як перекладати файли PO, не ламаючи програмні змінні. Особливість Drupal полягає просто в тому, що існує три стилі заповнювачів замість одного, і інструмент перекладу повинен розпізнавати їх усі.
Чому загальні перекладачі тут зазнають невдачі
Вставте цей рядок node.module у споживчий машинний перекладач, і ви часто отримаєте спотворений @count, %date в <em> буде локалізовано в інший токен, або форми множини будуть зведені до однієї. Жоден з цих інструментів не був розроблений з урахуванням семантики gettext. Вони перекладають текст; вони не розуміють, що @count — це контракт з кодом програми.
Конвеєр перекладу, що враховує gettext, з блокуванням синтаксису розглядає @variable, %variable та :placeholder як незмінні токени. Вони блокуються перед перекладом і відновлюються після, тому навколишнє речення перекладається, а заповнювачі проходять без змін. Таке ж блокування охоплює %s та %1$s у WordPress, {{name}} у i18next та вбудований HTML, тому один інструмент може обслуговувати проєкт Drupal, Symfony або Laravel так само легко, як і WordPress. Форми множини Drupal через msgid_plural зберігаються як форми множини, а не згладжуються, що важливо, оскільки мови Drupal можуть мати від одного до шести варіантів множини.
Варто також згадати більш тонкий режим відмови. Рядки Drupal часто містять вбудовану розмітку та посилання всередині тексту, що підлягає перекладу, наприклад Read the <a href=":url">documentation</a>, де :url є заповнювачем, і теги <a> повинні залишитися. Перекладач, який не розуміє структуру, може перекласти атрибут href, пропустити закриваючий тег або локалізувати ім'я заповнювача. ШІ, що враховує контекст, який читає весь рядок як єдине ціле, у поєднанні з блокуванням токенів, зберігає як розмітку, так і контракт :url недоторканими, перекладаючи лише читабельний для людини текст "documentation" між ними.
Цикл експорту, перекладу та повторного імпорту
Повторюваний робочий процес має три етапи, і drush робить експорт та імпорт скриптованим, щоб вам не доводилося щоразу клацати по адміністративному інтерфейсу.
Крок 1: Експорт файлу PO
Ви можете експортувати з інтерфейсу за адресою /admin/config/regional/translate, вибравши мову та область експорту, або зробити це з командного рядка. Модуль locale надає функцію експорту через служби перекладу Drupal, і більшість команд створюють для цього скрипти. Типовий виклик drush для запуску імпорту перекладу (зворотного, який ми використовуємо на кроці третьому) виглядає так:
# Re-import a translated PO file for Spanish, overwriting customized strings
drush locale:import es /var/www/translations/es-untranslated.po \
--type=customized --override=all
# Rebuild caches so the new strings render immediately
drush cache:rebuild
Що стосується експорту, адміністративна форма експорту створює файл .po; багато команд обгортають службу експорту локалі в невелику власну команду Drush для повної автоматизації. У будь-якому випадку ви отримуєте стандартний файл gettext .po, що містить ваші неперекладені записи msgid.
Крок 2: Переклад файлу
Це етап, на якому ШІ замінює години ручного редагування. Завантажте експортований файл .po до хмарного перекладача, виберіть цільову мову та дозвольте йому обробити. Оскільки файли .po Drupal для великого сайту зазвичай перевищують 10 МБ після об'єднання ядра, додаткових модулів та тем, тут важлива розумна пакетна обробка: файл розділяється на частини, перекладається та збирається заново без того, щоб ви розділяли його вручну або досягали обмежень розміру. На виході ви отримуєте повний файл .po, у якому кожен msgstr заповнений, а кожен заповнювач @count, %date та :url знаходиться точно там, де він починався.
Крок 3: Повторний імпорт до Drupal
Імпортуйте перекладений файл назад через /admin/config/regional/translate або за допомогою команди drush locale:import, показаної вище, потім перебудуйте кеш. Drupal об'єднує переклади у свої таблиці локалізації, і рядки негайно з'являються на всьому сайті. Запускайте цикл знову щоразу, коли додаєте модуль або оновлюєте ядро, оскільки кожен з них приносить нові неперекладені рядки.
Одна важлива деталь імпорту: прапор --override контролює, чи замінюють вхідні переклади існуючі. Використовуйте --override=all, коли ви хочете, щоб перекладений ШІ файл був авторитетним, або більш консервативне налаштування, якщо ви вручну налаштовували певні рядки в інтерфейсі Drupal, які ви не хочете перезаписувати. Для більшості автоматизованих конвеєрів, розгляд файлу .po як джерела істини та перезапис всього робить систему передбачуваною: файл у системі контролю версій — це те, що показує сайт, і крапка.
Для багатомовних сайтів з кількома цільовими мовами цикл виконується один раз для кожної мови. Експортуйте неперекладений набір, перекладіть його на німецьку, імпортуйте; знову експортуйте, перекладіть на іспанську, імпортуйте; і так далі. Оскільки кожна мова є незалежним файлом .po, ви можете запускати їх паралельно, і хмарний перекладач, що обробляє їх одночасно, перетворює те, що раніше було тижнем роботи підрядника, на один післяобідній час.
Drupal PO — це один з кількох форматів
Варто зазначити, що gettext .po — не єдиний спосіб, яким Drupal обробляє переклад. Сутності конфігурації та контенту також можуть обмінюватися як XLIFF, що є стандартом, на який спирається модуль Translation Management Tool (TMGMT) для робочих процесів професійних постачальників перекладів. Якщо ваша локалізація Drupal проходить через XLIFF, а не файли .po інтерфейсу, принципи збереження заповнювачів ідентичні, але структура файлу відрізняється, і ми розглядаємо цей шлях у статті переклад файлів XLIFF для Drupal, Symfony та Angular.
Однак для рівня перекладу інтерфейсу .po залишається основним робочим інструментом. Цикл експорту, перекладу за допомогою ШІ та повторного імпорту перетворює багатоденну ручну роботу на кілька хвилин обробки, і доки інструмент, який ви використовуєте, справді розуміє заповнювачі gettext, ваші контракти @variable залишаються недоторканими, а ваш сайт Drupal залишається бездоганним у кожній мові, яку ви випускаєте.
Готові перекладати ваші файли
.poDrupal, не порушуючи жодної@variable? Спробуйте SimplePoTranslate безкоштовно — кредитна картка не потрібна. Безкоштовний рівень обробляє стандартні файли gettext.poта.potз повним блокуванням синтаксису, тому ваші заповнювачі Drupal проходять точно так, як очікує код.