PO4A(7) | Інструменти Po4a | PO4A(7) |
po4a — набір інструментів для перекладу документації та інших матеріалів
Метою проекту po4a (PO для усього) є спрощення перекладу (та, що ще цікавіше, супровід перекладів) за допомогою інструментів gettext у областях, де такий переклад спочатку не передбачався, зокрема у документації.
Цей документ упорядковано так:
Загалом, цей розділ є не зовсім частиною цього документа. Він є документацією до кожного окремого модуля. Такий поділ допомагає підтримувати актуальність документації та синхронізацію документації із програмним кодом.
Мені подобається ідея програмного забезпечення з відкритим кодом, те, що воно робить програмне забезпечення і початковий код доступним для усіх. Але будучи французом, як добре розумію, що ліцензування — не єдине обмеження у відкритості програмного забезпечення: неперекладене програмне вільне забезпечення непотрібне тим, хто не знає англійської. Для того, щоб зробити його цінним для усіх, слід докласти додаткових зусиль з перекладу.
Розуміння цієї ситуації з боку учасників розробки вільного програмного забезпечення останнім часом разюче поліпшилося. Ми, перекладачі, виграли першу битву і переконали усіх у важливості перекладу. Втім, на жаль, це завдання є лише найлегшою частиною роботи. Тепер нам слід виконати нашу роботу і перекласти усе, що потрібно.
Насправді, саме вільне програмне забезпечення має досить якісний інструментарій для перекладу, дякуючи чудовому набору інструментів gettext. У нас є інструменти для видобування рядків для перекладу з програми, є інструменти для надання їх в уніфікованому вигляді перекладачам і є інструменти для використання результатів їхньої роботи у програмі і показу перекладених повідомлень користувачеві.
Але усе стає трохи інакшим, коли йдеться про документацію. Дуже часто ознайомитися із перекладеною документацією важко (вона не поширюється як частина програми), переклад є лише частковим або застарілим. Останній варіант є найгіршим. Ситуація із застарілим перекладом може бути гіршою за ситуацію, коли перекладу взагалі немає, оскільки у застарілій документації описано поведінку програми, яка вже не є актуальною.
Перекладати документацію нескладно. Тексти є набагато довшими за повідомлення з інтерфейсу програми, отже роботи більше, але для її виконання не потрібно мати якісь особливі технічні навички. Складнощі виникають, коли виникає потреба у підтриманні актуальності роботи. Виявлення частин, до яких було внесено зміни, та частин, які слід оновити, — дуже складне і марудне завдання, під час виконання якого дуже просто помилитися. Думаю, це пояснює те, чому так багато перекладеної документації виявляється застарілою.
Отже, основним завданням po4a є полегшення супроводу перекладів документації. Основна ідея полягає у використанні методології gettext до цього нового застосування. Подібно до gettext, фрагменти тексту видобуваються із початкових документів для представлення їх в уніфікованому форматі для перекладачів. Класичні інструменти gettext допомагають перекладачам оновлювати їхню роботу, коли з'являється новий випуск документації. Але на відміну від класичної моделі gettext переклади вставляються до початкової структури документа так, щоб їх можна було обробляти і розповсюджувати так само просто, як і початкову англійську версію.
Завдяки цьому, визначення частин документа, до яких було внесено зміни, і які слід оновити, стає дуже простим. Ще однією перевагою є те, що інструменти виконають майже усю роботу, якщо структура початкового документа фундаментально зміниться, — глави поміняються місцями, їх буде об'єднано або поділено. Видобування тексту зі структури документа надає змогу абстрагуватися від складнощів із форматуванням тексту і зменшує ймовірність помилок у форматуванні документа (хоча і не усуває її зовсім).
Будь ласка, також ознайомтеся із розділом Поширені питання у цьому документі, щоб дізнатися більше про переваги і недоліки цього підходу.
У поточній версії цей підхід успішно реалізовано для декількох типів документів із текстовим форматуванням:
man
Старий добрий формат сторінок підручника, який використовується у багатьох програмах. Підтримка у po4a тут дуже доречна, оскільки цей формат доволі складний у використанні і не дуже зручний для недосвідчених користувачів. У модулі Locale::Po4a::Man(3pm) також передбачена підтримка формату mdoc, який використовується у сторінках підручника BSD (їх також доволі часто використовують у Linux).
pod
Це формат інтернет-документації до Perl (Perl Online Documentation). За його допомогою документовано саму мову і її розширення, а також більшість із наявних скриптів Perl. Він спрощує синхронізацію документації із кодом, оскільки і документація, і код є частиною одного файла. Це спрощує завдання програміста, але, на жаль, не перекладача.
sgml
Хоча цей формат на сьогодні дещо поступився місцем XML, його ще досить часто використовуються для досить довгих документів. За його допомогою можна створювати цілі книги. Оновлення перекладів таких довгих документів може стати справжнім жахом. diff часто виявляється безпорадним, якщо відступи у початковому тексті після оновлення буде змінено. На щастя, тут у пригоді вам стане po4a.
У поточній версії передбачено підтримку лише DebianDoc і DocBook DTD, але додавання підтримки нових форматі є дуже простим. po4a можна навіть використовувати для невідомих DTD SGML без зміни коду, якщо надати потрібну інформацію за допомогою командного рядка. Див. Locale::Po4a::Sgml(3pm), щоб дізнатися більше.
TeX / LaTeX
Формат LaTeX є основним форматом документації, який використовується у світі вільного програмного забезпечення та для публікацій. Модуль Locale::Po4a::LaTeX(3pm) було перевірено на документації до Python, книзі і декількох презентаціях.
texinfo
У цьому форматі записано усю документацію GNU (наявність такої документації є навіть однією із вимог для отримання статусу офіційного проекту GNU). Підтримка модуля Locale::Po4a::Texinfo(3pm) у po4a усе ще перебуває на початковому етапі. Будь ласка, повідомляйте про вади і ваші запити щодо реалізації функціональних можливостей.
xml
Формат XML є базовим для багатьох форматів документації.
У поточній версії po4a передбачено підтримку DTD DocBook. Докладніше про це на сторінці Locale::Po4a::Docbook(3pm).
інші
Крім того, po4a також може працювати із іншими рідкісними і спеціалізованими форматами, зокрема документацією до параметрів компіляції ядер Linux 2.4+ та діаграмами, які створено за допомогою програми Dia. Додати новий формат часто доволі просто. Основним у цьому є є створення обробника початкового формату. Докладніший опис цього можна знайти у розділі Locale::Po4a::TransTractor(3pm).
На жаль, у po4a все ще не реалізовано декілька форматів документації.
Існує цілий список форматів, підтримку яких ми хотіли б бачити у po4a, і це не лише документація. Насправді, нашою метою є заповнення усіх «дірок», які є у спектрі покриття класичних інструментів gettext. Це стосується описів пакунків (deb і rpm), питань у скриптах встановлення пакунків, журналів змін пакунків та усіх спеціалізованих форматів файлів, які використовуються програмами, зокрема сценаріїв ігор та файлів ресурсів wine.
У цій главі подано довідкові матеріали із відповідями на поширені питання користувачів та наведено дані, які допоможуть зрозуміти усю процедуру роботи комплекту програм. Це вступ до роботи з po4a та документації до специфічних інструментів комплекту.
На наведеній нижче схемі зображено загальний процес перекладу документації за допомогою po4a. Не лякайтеся видимої складності, вона є наслідком того, що тут зображено увесь процес. Насправді, після того, як ви перейдете у вашому проекті на po4a, працюватиме лише права частина схеми.
Зауважте, що як приклад документа, який слід перекласти, вибрано основний.документ, а відповідний перекладений документ позначено перекладений.документ. Суфіксом назви може бути .pod, .xml або .sgml, залежно від формату документа. Докладний опис кожної із частин схеми наведено у наступних розділах.
основний.документ | V +<-----<----+<-----<-----<--------+------->-------->-------+ : | | : {переклад} | { оновлення основний.документ } : : | | : XX.документ | V V (необов'язковий) | основний.документ ->------>---->+ : | (новий) | V V | | [po4a-gettextize] документ.XX.po>+ | | | (старий) | | | | ^ V V | | | [po4a-updatepo] | V | | V переклад.pot ^ V | | | документ.XX.po | | | (неточний) | { переклад } | | | | ^ V V | | {редагування вручну} | | | | | V | V V документ.XX.po --->---->+<---<-документ.XX.po додаток основний.документ (початковий) (актуальний) (необов'язковий)(актуальний) : | | | : V | | +----->----->----->------> + | | | | | V V V +------>-----+------<------+ | V [po4a-translate] | V XX.документ (актуальний)
У лівій частині схеми показано перетворення перекладу, у якому не використовується po4a, на нову систему. У верхній частині праворуч зображено роботу автора початкового тексту (оновлення документації). У середній частині праворуч зображено послідовність автоматичних дій po4a. Новий тестовий матеріал видобувається з документа і порівнюється із наявним перекладом. Виявляються частини, які не змінилися, — для них використовується наявний переклад. Частини, які зазнали часткових змін також пов'язуються із попереднім перекладом, але із особливою позначкою, яка вказує на те, що переклад має бути оновлено. У нижній частині схеми показано процес побудови форматованого перекладеного документа.
Насправді, з точки зору перекладача, єдиною дією, яку слід виконати вручну є частина, яку позначено написом {редагування вручну}. Так, вибачте, але po4a лише допомагає вам перекладати. Програма не здатна виконати переклад за вас…
У цьому розділі описано кроки, потрібні для того, щоб розпочати новий переклад з po4a. Опис дій, які слід виконати для перетворення наявного проекту до цієї системи, можна знайти у відповідному розділі.
Щоб розпочати новий переклад за допомогою po4a, вам слід виконати такі кроки:
$ po4a-gettextize -f <формат> -m <основний_документ> -p <переклад.pot>
Рядком <формат>, звичайно ж, має бути назва формату, використаного у документі основний.документ. Зрозуміло, дані буде виведено до файла переклад.pot. Будь ласка, зверніться до документації із po4a-gettextize(1), щоб дізнатися більше про можливі параметри команди.
Сам переклад можна виконати у режимах PO Emacs або Vi, у Lokalize (на основі KDE), Gtranslator (на основі GNOME) або будь-якій програми, якій ви надаєте перевагу (наприклад Virtaal).
Якщо ви хочете дізнатися більше, вам напевне слід звернутися до документації з gettext, яка є частиною пакунка gettext-doc.
Після завершення перекладу вам потрібна буде перекладена документація для надання її користувачам разом із оригінальною. Для отримання такої документації скористайтеся програмою po4a-translate(1) ось так (тут XX — код мови):
$ po4a-translate -f <формат> -m <основний_документ> -p <документ.XX.po> -l <документ_XX>
Як і раніше, <формат> — формат, у якому записано дані документа основний.документ. Втім, цього разу файл PO, вказаний за допомогою параметра -p, є частиною вхідних даних. Це ваш переклад. Результат обробки буде записано до файла XX.документ.
Докладніше про це на сторінці підручника po4a-translate(1).
Щоб оновити ваш переклад після змін у файлі основний.документ скористайтеся програмою po4a-updatepo(1) ось так:
$ po4a-updatepo -f <формат> -m <новий_основний.документ> -p <старий_документ.XX.po>
(Докладніше про це на сторінці підручника po4a-updatepo(1))
Звичайно ж, нові фрагменти тексту у документі не буде перекладено автоматично у файлі PO під час виконання цієї дії. Вам доведеться оновити вміст файла PO вручну. Крім того, вам слід буде переглянути переклад повідомлень, які було трохи змінено у оригіналі. Щоб переконатися, що ви не пропустите такі повідомлення, їх буде позначено як «неточні» («fuzzy») під час оновлення. Вам слід буде вилучити цю позначку, перш ніж перекладом можна буде скористатися за допомогою po4a-translate. Як і з початковим перекладом, найкраще для цього скористатися вашим улюбленим редактором файлів PO.
Після оновлення вмісту вашого файла PO, коли у ньому не залишиться неперекладених або неточних рядків, ви можете створити файл перекладеної документації, як це описано у попередньому розділі.
Часто трапляється так, що ви звикли перекладати документ вручну, аж доки не трапилася загальна реорганізація початкового документа основний.документ. Далі, після марних спроб з використанням diff або подібних інструментів, ви вирішуєте перейти на po4a. Але, звичайно ж, ви не хочете втрачати наявні переклади. Не хвилюйтеся, цей випадок також передбачено у інструментах po4a. Відповідне перетворення ми називаємо переходом на gettext.
Ключовим моментом тут є однакова структура перекладеного документа та початкового документа. Це уможливлює встановлення відповідності фрагментів тексту програмами.
За сприятливих умов (тобто якщо обидва документи повністю збігаються за структурою), перетворення буде виконано без проблем, і воно триватиме декілька секунд. Якщо ж це не так, будьте готові до певної марудної роботи. Щоб там не було, пам'ятайте, що уся ця робота є платою за наступне комфортне використання po4a. І, звичайно ж, добре, що усе це доведеться робити лише один раз.
Акцентуємо на це увагу: щоб спростити процес, важливо знайти точну версію, яку було використано для перекладу. Найкращим варіантом є визначення номера модифікації у системі керування версіями, яку було використано для перекладу і яка не змінювалася під час виконання перекладу. Ви можете скористатися саме нею.
Поганий результат буде отримано, якщо ви скористаєтеся оновленим початковим текстом і застарілим перекладом. Перетворення лишиться можливим, але його буде виконати складніше. Якщо можливо, не робіть так. Фактично, якщо ви не знайдете початковий текст, найкраще знайти когось, хто виконає перетворення на gettext за вас (але, будь ласка, нехай це буду не я ;).
Можливо, тут я трохи перебільшую. Навіть якщо щось іде не так, існують способи, швидші за повторний повний переклад. Мені вдалося перетворити на формат gettext наявний переклад французькою документації до Perl, хоча там і були проблеми. Об'єм перекладу перевищував два мегабайти, на новий переклад довелося б витратити місяці або навіть роки.
Спочатку я поясню основну частину процедури, а потім ми повернемося до питань усування негараздів. Щоб спростити пояснення, ми ще раз розглянемо наведений вище приклад.
Якщо у вас є старий основний.документ, який відповідає перекладу XX.документ, перетворення на формат gettext можна виконати безпосередньо до файла PO документ.XX.po без потреби у перекладі вручну файла переклад.pot:
$ po4a-gettextize -f <формат> -m <старий_основний.документ> -l <XX.документ> -p <документ.XX.po>
За сприятливих умов, на цьому все. Ви перетворили старий переклад на переклад системи po4a і можете розпочинати його оновлення. Просто виконайте описану декілька розділів вище процедуру синхронізації вашого файла PO із найсвіжішою версією початкового документа і оновіть відповідним чином переклад.
Будь ласка, зауважте, що навіть якщо усе, здається, працює як слід, у процесі можуть все ж трапитися помилки. Причиною є те, що програми po4a не здатні зрозуміти текст і переконатися, що переклад відповідає оригіналу. Ось чому усі рядки у процесі буде позначено як неточні переклади («fuzzy»). Вам слід ретельно перевірити кожен переклад, перш ніж вилучати ці позначки.
Часто структури документів не є повністю тотожними, що не дає po4a-gettextize виконати свою роботу належним чином. У таких випадках доводиться редагувати файли так, щоб досягти однакової структури.
Може допомогти читання розділу Перетворення на gettext: як це працює? нижче. Чітке розуміння внутрішнього процесу допоможе вам виконати завдання. Добре тут те, що po4a-gettextize доволі докладно повідомляє про те, що не так. По-перше, програма точно визначає місце відмінності у структурі документів. Вам слід вивчити рядки, які не збігаються, їхнє розташування у тексті та тип кожного з них. Більше того, дані PO, які буде отримано на момент помилки, буде записано до файла gettextization.failed.po.
Далі, у POD два абзаци може бути об'єднано, якщо рядок, який їх відокремлює містить пробіли, або якщо між рядком =item і вмістом запису немає порожнього рядка.
Така неприємна ситуація трапляється, коли у документі повторюється певний абзац. У цьому випадку, у файлі PO не додається новий запис, а створюється посилання на вже наявний у ньому запис.
Отже, якщо у початковому тексті якийсь абзац використовувався двічі, але переклади цього абзацу є різними, може здатися, що абзац у початковому тексті зник. Щоб усунути проблему, достатньо вилучити новий переклад. Якщо хочете вилучити перший з перекладів, оскільки другий був кращим, просто замініть перший переклад другим.
І навпаки, якщо подібні, але різні абзаци було перекладено однаково, може здатися, що абзац зник у перекладі. Вирішенням проблеми є додавання якоїсь фіктивної частини до абзацу у початковому тексті (наприклад, «Я інший»). Не бійтеся — цей фіктивний рядок буде прибрано під час синхронізації, і якщо доданий текст є достатньо коротким, gettext встановить відповідність між вашим перекладом і наявним текстом (програма позначити переклад як неточний, але цим не слід перейматися, оскільки так буде позначено усі переклади після перетворення на формат gettext).
Сподіваюся, ці підказки допоможуть вам виконати завдання із перетворення перекладу на формат gettext і отримати ваш безцінний переклад у вигляді файла PO. Цей переклад ви зможете синхронізувати з початковим документом, а отже, зможете розпочати створення оновленого перекладу. Будь ласка, зауважте, що якщо текст документа є довгим, початкова синхронізація може бути доволі тривалою.
Наприклад, перше виконання po4a-updatepo для перекладу французькою документації до Perl (файл PO розміром 5,5 МБ) тривало цілих два дні на комп'ютері із процесором G5 з частотою 1 ГГц. Так, 48 годин. Але наступні синхронізації тривали лише декілька секунд навіть на моєму застарілому ноутбуці. Так трапляється, оскільки першого разу більшість початкових рядків (msgid) у файлі PO не мають жодних відповідників у файлі POT. Це змушує gettext шукати найближчі відповідники з використанням доволі складного алгоритму пошуку близьких за вмістом рядків.
Через використання підходу gettext зробити це за допомогою po4a складніше, ніж просто редагувати файл перекладу, створений напряму з оригіналу. Втім, це можливо завдяки так званим додаткам.
Для кращого розуміння, додатки можна вважати латками, які накладаються на перекладений документ після обробки. Насправді, вони відрізняються від звичайних латок (у них лише один рядок контексту, до якого можна вбудувати формальний вираз Perl, і вони лише додають текст без вилучення фрагментів старого), але за функціональними можливостями додатки збігаються з латками.
Метою створення додатків є додавання таких даних до документа, які не є перекладом початкового документа. Типовим застосуванням додатків є додавання розділу, присвяченого самому перекладу, розділу зі списком учасників перекладу та настановами щодо звітування про вади у перекладі.
Додаток слід оформлювати як окремий файл. У першому рядку заголовка додатка має бути вказано місце у створеному документі, куди слід вставити додаток. Решту файла додатка буде вставлено буквально у визначену позицію остаточного документа.
Синтаксис рядка заголовка для визначення контексту доволі строгий: він має починатися з рядка PO4A-HEADER:. Далі має бути вказано список відокремлених крапкою з комою (;) полів ключ=значення. Усі пробіли БЕРУТЬСЯ ДО УВАГИ. Зауважте, що не можна використовувати символ крапки з комою (;) у значенні, екранування цього символу тут також не допоможе. Якщо потрібно, для зручності читання можна вставляти пробіли ( ) перед записом ключ.
Хоча цей контекстний пошук можна розглядати як такий, що працює має із усіма рядками перекладеного документа, насправді, він працює з внутрішніми даними рядка перекладеного документа. Цей внутрішній рядок даних може бути фрагментом тексту абзацу із декількох рядків або може бути лише теґом XML. Точна точка вставлення додатка має знаходитися до або після внутрішнього рядка даних і не може перебувати всередині внутрішнього рядка даних.
Ознайомитися із справжнім вмістом внутрішнього рядка даних перекладеного документа можна за допомогою запуску po4a у діагностичному режимі.
Знову ж таки, усе це може видатися складним, але наведені нижче приклади допоможуть вам правильно записати потрібний вам рядок заголовка. У нашому прикладі ми додаватимемо розділ із назвою «Про переклад» після розділу «Про цей документ».
Ось можливі ключі заголовка:
Якщо вказано режим mode=before, точка вставлення визначається у один крок на основі відповідності вказаному параметру формального виразу position. Ця точка вставлення розташовується безпосередньо перед однозначно встановленим відповідником — внутрішнім рядком даних перекладеного документа.
Якщо вказано режим mode=after, точка вставлення визначається у два кроки за відповідністю форматним виразам, вказаним у параметрі формального виразу position, та параметрами формального виразу beginboundary або endboundary.
Оскільки у розглянутому випадку може бути декілька розділів, скористаємося двокроковим підходом.
mode=after
Якщо цьому виразу відповідатиме декілька рядків (або жодного), пошук точки вставлення зазнає невдачі, отже нічого додаватися не буде. Справді, краще повідомити про помилку, ніж вставляти додаток у помилкове місце.
Якщо визначено mode=before, а вказану точка вставлення перебуває безпосередньо перед внутрішнім рядком даних, який точно відповідає параметру position формального виразу.
Якщо визначено режим mode=after, область пошуку точки вставлення звужується до даних після рядка внутрішніх даних, що однозначно відповідає параметру формального виразу position. Точне ж розташування точки вставлення визначається параметром beginboundary або endboundary.
У нашому випадку нам треба пропустити декілька попередніх розділів звуженням пошуку за допомогою рядка заголовка розділу.
position=Про цей документ
(Насправді, тут вам слід скористатися рядком перекладеного заголовка.)
У нашому прикладі ми можемо визначити кінець розділу, за яким відбуватиметься додавання, додавши:
endboundary=</section>
або, для позначення початку нового розділу, вказавши:
beginboundary=<section>
У обох випадках, наш додаток буде розташовано після </section> і перед <section>. Перший варіант є кращим, оскільки він працюватиму навіть після реорганізації документа.
Дві форми існують через відмінності у форматах документації. У деяких з них передбачено підтримку позначення кінця розділу (подібно до теґу </section>, яким ми щойно скористалися), а в інших кінець розділу ніяк явно не позначається (зокрема такі проблеми виникають у форматі man). У першому випадку шукати слід на межі, у кінці розділу, так, щоб точка вставлення розташовувалися після знайденої позиції. У другому ж випадку, слід шукати на межі, але на початку наступного розділу, так, щоб точка вставлення перебувала точно перед знайденою позицією.
Це може здатися незрозумілим, але, сподіваємося, наступні приклади зроблять усе зрозумілішим.
PO4A-HEADER: mode=after; position=About this document; endboundary=</section> PO4A-HEADER: mode=after; position=About this document; beginboundary=<section>
.SH "AUTHORS"
Вам слід вибрати двокроковий підхід встановленням значення mode=after. Далі, вам слід звузити пошук до рядка після AUTHORS за допомогою параметра формального виразу position. Далі, вам потрібно встановити відповідність початку нового розділу (тобто, ^\.SH) за допомогою параметра формального виразу beginboundary. Тобто, слід зробити так:
PO4A-HEADER:mode=after;position=AUTHORS;beginboundary=\.SH
PO4A-HEADER:mode=after;position=Copyright Big Dude, 2004;beginboundary=^
PO4A-HEADER:mode=after;position=Про цей документ;beginboundary=FakePo4aBoundary
Щоб там не було, пам'ятайте, що це формальні вирази. Наприклад, якщо ви хочете встановити відповідність кінцю розділу nroff, який завершується рядком
.fi
не використовуйте .fi у полі endboundary, оскільки вказаний рядок є формальним виразом, за яким може бути знайдено, наприклад, рядок «the[ fi]le», що, звичайно ж, є небажаним. Правильним значенням для endboundary у цьому випадку буде таке: ^\.fi$.
Якщо додаток опиниться не там, де ви сподівалися, спробуйте додати до рядка команди -vv, щоб отримати додаткові дані щодо того, які дії виконуються для вставляння додатка.
Докладніший приклад
Початковий документ (у форматуванні POD):
|=head1 NAME | |dummy - a dummy program | |=head1 AUTHOR | |me
Далі, наведений нижче додаток забезпечить додавання розділу (українською) щодо перекладачів наприкінці файла.
|PO4A-HEADER:mode=after;position=АВТОР;beginboundary=^=head | |=head1 ПЕРЕКЛАДАЧ | |я |
Щоб розташувати ваш додаток перед записом АВТОР, скористайтеся таким заголовком:
PO4A-HEADER:mode=after;position=ІМ'Я;beginboundary=^=head1
Це працює, оскільки наступний рядок відповідника beginboundary /^=head1/ після розділу «NAME» (перекладеного як «ІМ'Я» українською) є розділ зі списком авторів. Отже, додаток буде розташовано між вказаними розділами. Зауважте, що якщо між розділами NAME і AUTHOR згодом буде додано ще якийсь розділ, po4a помилково додасть додаток перед новим розділом.
Щоб уникнути цього, ви можете досягти результату у інший спосіб за допомогою mode=before:
PO4A-HEADER:mode=before;position=^=head1 АВТОР
Практика використання po4a показала, що іноді стаються помилки, оскільки доводиться викликати дві різні програми у належному порядку (po4a-updatepo, а потім po4a-translate) і кожній з цих програм слід передати більше 3 параметрів. Крім того, у такій системі важко використовувати один файл PO для усіх ваших документів, якщо ці документи зберігають дані у різних форматах.
Програму po4a(1) було створено, щоб усунути ці складнощі. Щойно ваш проект буде переведено на нашу систему, вам достатньо буде написати простий файл налаштувань з поясненнями, де зберігаються ваші файли перекладів (PO і POT), де зберігаються початкові документи, у яких форматах зберігаються ці документи, і де слід зберігати переклади документів.
Далі, виклик po4a(1) із вказаним файлом налаштувань забезпечить синхронізацію файлів PO із початковим документом і належне створення перекладених документів. Звичайно ж, вам знадобиться два виклики цієї програми — один перед редагуванням файлів PO з метою їхнього оновлення, і один після редагування, щоб створити повністю оновлений перекладений документ. Втім, вам доведеться запам'ятати лише один командний рядок.
Модулям po4a передаються параметри (вказані за допомогою параметра -o). Цим можна скористатися для зміни поведінки модулів.
Ви також можете редагувати початковий код наявних модулів або навіть написати власні модулі. Щоб зробити ці модулі видимими для po4a, скопіюйте їх до каталогу із назвою "/щось/там/lib/Locale/Po4a/", а потім додайте шлях "/щось/тамh/blu" до змінної середовища "PERLIB" або "PERL5LIB". Приклад:
PERLLIB=$PWD/lib po4a --previous po4a/po4a.cfg
Зауваження: справжня назва каталогу lib не є важливою.
У цій главі наведено короткий огляд нутрощів po4a, який надасть вам впевненості, якщо ви захочете допомогти нам із супроводом та розвитком комплекту програм. Цей огляд також може допомогти вам зрозуміти, чому програма працює не так, як ви того сподівалися, та як усунути вашу проблему.
Архітектура po4a є об'єктно-орієнтованою (на Perl. Хіба це не чудово?). Загальний предок усіх класів обробки називається TransTractor. Ця дивна назва походить від того факту, що він водночас відповідає за переклад документа (translator) та видобування рядків (extractor).
Формально, він отримує документ для перекладу і файл PO з перекладами на вході і створює два потоки виведених даних: ще один файл PO (який є результатом видобування придатних до перекладу рядків із вхідного документа) та перекладений документ (тієї самої структури, що і вхідний, але із заміною усіх придатних до перекладу рядків на вміст вхідного файла PO). Ось графічне представлення обробки:
Вхідний документ --\ /---> Вихідний документ \ TransTractor:: / (перекладений) +-->-- parse() --------+ / \ Вхідний PO --------/ \---> Вихідний PO (видобутий)
Ця маленька часточка коду є ядром усієї архітектури po4a. Якщо викинути вхідний файл PO і вихідний документ, ми отримуємо po4a-gettextize. Якщо надати вхідний PO і відкинути вихідний PO, отримуємо po4a-translate. po4a двічі викликає TransTractor і між цими викликами викликає msgmerge -U для забезпечення обробки даних у один прохід за допомогою одного файла налаштувань.
TransTractor::parse() є віртуальною функцією, яка реалізується у кожному модулі. Ось невеличкий приклад того, як це працює. Код обробляє список абзаців, кожен з яких починається з <p>.
1 sub parse { 2 PARAGRAPH: while (1) { 3 $my ($paragraph,$pararef,$line,$lref)=("","","",""); 4 $my $first=1; 5 while (($line,$lref)=$document->shiftline() && defined($line)) { 6 if ($line =~ m/<p>/ && !$first--; ) { 7 $document->unshiftline($line,$lref); 8 9 $paragraph =~ s/^<p>//s; 10 $document->pushline("<p>".$document->translate($paragraph,$pararef)); 11 12 next PARAGRAPH; 13 } else { 14 $paragraph .= $line; 15 $pararef = $lref unless(length($pararef)); 16 } 17 } 18 return; # Не отримали визначений рядок? Кінець файла вхідних даних. 19 } 20 }
У рядках 6 і 7 ми бачимо "shiftline()" і "unshiftline()". Ці функції допомагають читати і записувати заголовок внутрішнього потоку вхідних даних основного документа до рядка та його прив'язки. Прив'язка зберігається у рядку "$filename:$linenum". Будь ласка, пам'ятайте, що у Perl передбачено лише одновимірну структур даних для масивів. Отже обробка коду рядка потоку вхідних даних є дещо ускладненою.
У рядку 6 ми бачимо <p> вдруге. Це сигнал щодо наступного абзацу. Отже, ми маємо вставити щойно отриманий рядок назад у початковий документ (рядок 7) і надіслати створений таким чином абзац до виведених даних. Після вилучення початкового <p> з абзацу у рядку 9, ми надсилаємо до виведення об'єднання цього теґу і перекладу решти абзацу.
Ця функція translate() прекрасна. Вона надсилає свій аргумент до вихідного файла PO (видобування) і повертає його переклад, відповідно до вхідного файла PO (переклад). Оскільки вона використовується як частина аргументу pushline(), переклад опиняється у документі, який є результатом обробки.
Хіба це не чудово? Можна створити повноцінний модуль po4a, у якому буде менше за 20 рядків, якщо формат є доволі простим…
Докладніше про це у розділі Locale::Po4a::TransTractor(3pm).
Використана тут ідея полягає у тому, щоб взяти початковий документ і його переклад і вважати, що N-й видобутий рядок з перекладу є перекладом N-го видобутого рядка з оригіналу. Щоб це спрацювало, обидва файли повинні мати абсолютно однакову будову. Наприклад, якщо файли мають наведену нижче будову, дуже малоймовірним є те, що 4-й рядок у перекладі (типу «глава») є перекладом 4-го рядка оригіналу (типу «абзац»).
Оригінал Переклад глава глава абзац абзац абзац абзац абзац глава глава абзац абзац абзац
Для реалізації цієї ідеї засоби обробки po4a використовуються для початкового документа та файла перекладу для видобування даних PO, а потім на їхній основі збирається третій файл PO, якому використовуються рядки з другого файла як переклади рядків з першого. З метою перевірити, чи є рядки, які ми зіставили, справді перекладами одне одного, засоби обробки документів у po4a мають записувати дані щодо синтаксичного типу видобутих рядків до документа (усі наявні засоби так роблять, і так має робити створений вами засіб). Далі, ці дані використовуються для того, щоб забезпечити однаковий синтаксис у обох документах. У попередньому випадку це надало б нам змогу визначити, що рядок 4 є абзацом у одному з випадків і заголовком глави у іншому випадку, а отже повідомити про проблему.
Теоретично, можна виявити проблему і синхронізувати файли нижче за списком записів (як це робить diff). Але при цьому залишається відкритим питання про те, що робити із декількома рядками до синхронізації. Іноді такий підхід призводить до помилкових результатів. Ось чому у поточній реалізації програма не робить спроб повторно синхронізувати рядки і просто завершує роботу, повідомивши докладно про помилку, яка потребує внесення змін до файлів вручну з метою усування проблеми.
Навіть якщо виконуються усі попередні умови, тут усе ж дуже просто можуть виникнути проблеми. Ось чому переклади, які було визначено у цей спосіб позначаються як неточні. Перекладач має переглянути і перевірити їх.
Гаразд, тут усе просто. Перекладений документ не записується одразу на диск, а зберігається у пам'яті, аж доки до нього не буде записано додатки. Використані тут алгоритми є доволі простими. Ми шукаємо рядок, який відповідає формальному виразу позиції і вставляємо додаток перед ним, якщо працюємо у режимі mode=before. Якщо це не так, ми шукаємо наступний рядок, який відповідає межі фрагмента і вставляємо додаток після цього рядка, якщо це endboundary або перед цим рядком, якщо це beginboundary.
У цій главі зібрано поширені питання та відповіді на них. Фактично, більшість питань на сьогодні можна сформулювати так: «Чому усе зроблено так, а не якось інакше?» Якщо вам здається, що po4a не та програма, за допомогою якої можна перекладати документацію, вам варто прочитати цю главу. Якщо у ній ви не знайдете відповідей на ваші питання, будь ласка, зв'яжіться із нами за допомогою списку листування <devel@lists.po4a.org>. Ми будемо раді вашим відгукам.
Так, у po4a кожен абзац перекладається окремо (фактично, це вирішується на рівні модуля, але у всіх наявних модулях це так, отже, це має бути так і у вашому модулі). У цього підходу є дві основні переваги:
Навіть ці переваги не переконують декого у тому, що кожен абзац слід перекладати окремо. Ось декілька тез, які ми можемо висловити у відповідь на заперечення цієї методики:
Засоби професійного перекладу іноді поділяють документ на рівні речення, щоб максимально скористатися можливістю повторного використання попередніх перекладів і пришвидшення процесу. Проблема полягає у тому, що те саме речення може мати декілька різних перекладів, які залежать від контексту.
Абзаци, за означенням, є довшими за речення. Можна сподіватися, що однакові абзаци у двох різних документах матимуть те саме значення (і переклад), незалежно від контексту.
Поділ на частини, менші за речення, дасть дуже погані результати. Пояснення причин є надто довгим, щоб наводити його тут, але зацікавлений читач може звернутися до прикладу, наведеного на сторінці підручника Locale::Maketext::TPJ13(3pm) (яка є частиною документації до Perl). Якщо коротко, у кожної мови є власні правила щодо синтаксису. Не існує способу побудови речення за допомогою збирання перекладів частин речення, які б працювали для усіх відомих мов (навіть для 5 з 10 найрозповсюдженіших).
З першого погляду, gettext не пасує для усіх різновидів перекладу. Наприклад, його не дуже пристосовано для перекладу debconf, інтерфейсу, який використовується усіма пакунками Debian для взаємодії з користувачем під час встановлення. У цьому випадку тексти для перекладу є доволі короткими (десяток рядків на кожен з пакунків), і розташувати переклад у спеціалізованому файлі складно, оскільки переклад має бути доступним до встановлення пакунка.
Саме тому розробник debconf вирішив реалізувати інший підхід, коли переклади розташовуються у тому самому файлі, що і оригінал. Такий підхід є доволі привабливим. Декому може видатися, що це буде добре і для, наприклад, XML. Це б виглядало десь так:
<section> <title lang="en">My title</title> <title lang="uk">Мій заголовок</title> <para> <text lang="en">My text.</text> <text lang="uk">Мій текст.</text> </para> </section>
Але усе це потягло за собою такі проблеми, що зараз використовується лише підхід, який засновано на файлах PO. У початковому файлі можна редагувати лише початковий варіант рядка, а переклади розташовуються у файлах PO, дані яких видобуто із основного шаблону (ці переклади записуються назад до пакунка під час його збирання). Стару систему було відправлено на відпочинок з декількох причин:
Якщо декілька перекладачі надішлють латку одночасно, буде важко об'єднати латки.
Як ви зможете виявити зміни у оригіналі, які слід реалізувати у новій версії перекладу? Щоб скористатися diff, вам потрібні будуть значення щодо версії оригіналу, яку було перекладено. Отже, у вашому житті все одно з'явиться файл PO. ;)
Цей підхід добре працює лише для частини європейських мов, але додавання корейської, української і/або арабської значно ускладнює картину. Можна було б скористатися UTF, але і з ним є певні проблеми.
Більше того, такі проблеми важко виявити (тобто лише ті, хто знає корейську можуть виявити, що кодування хангилю є помилковим [наприклад, через дії перекладача російською]).
gettext розв'язує усі ці проблеми одночасно.
Правда, але кращого варіанта досі ніхто не придумав. Єдиною альтернативою є переклад вручну із усіма проблемами із супроводом такого перекладу.
Наскільки мені відомо, є лише два інших комплекти програм:
Ця програма може працювати лише із форматом XML і лише з певним DTD. Мені не дуже подобається робота зі списками у ній, оскільки використання списків за певних умов призводить до створення величезних msgid. Якщо список дуже великий, перекладати його стає дуже складно.
Основною перевагою po4a над цими програмами є простора додавання додаткових даних (що важко або неможливо зробити у цих програмах) та можливість перетворення даних до стандартного формату gettext.
Намагаючись перекладати документацію або інтерфейс програм ви стикаєтеся із трьома типами проблем: лінгвістичною (не усі добре знають декілька мов), технічною (для цього і існує po4a) та проблемою відносин між людьми. Не усі розробники розуміються на потребі перекладу. Навіть якщо є добра воля з боку розробника, він часто ігнорує питання спрощення роботи перекладачів. Щоб допомогти із цим, у po4a передбачено значний обсяг додаткової документації.
Ще однією важливою річчю є те, що кожне перекладений файл починається з короткого коментаря, який вказує на походження файла та спосіб його використання. Це має допомогти бідолашним розробникам, заваленим купою файлів різними мовами, які вони не розуміють, належним чином використати ці файли.
У проекті po4a перекладені файли вже не є початковими, у тому сенсі, що ці файли не є пріоритетними для внесення до них змін. Оскільки така побудова проекту є трохи незвичною, це стає джерелом простих помилок. Ось чому в усіх файлах вказується такий заголовок:
| ***************************************************** | * GENERATED FILE, DO NOT EDIT * | * THIS IS NO SOURCE FILE, BUT RESULT OF COMPILATION * | ***************************************************** | | This file was generated by po4a-translate(1). Do not store it (in VCS, | for example), but store the PO file used as source file by po4a-translate. | | In fact, consider this as a binary, and the PO file as a regular source file: | If the PO gets lost, keeping this translation up-to-date will be harder ;)
Так само, звичайні файли PO gettext слід лише скопіювати до каталогу po/. Втім, це не стосується тих файлів, з якими працює po4a. Основним ризиком тут є те, що розробник може замінити наявний переклад інтерфейсу програми перекладом її документації. (Дані обох цих перекладів не можуть зберігатися у одному файлі PO, оскільки програма має встановлювати переклад як файл mo, а переклад документації використовується лише для збирання перекладеної документації під час компіляції програми). Ось чому файли PO, створені модулем po-debiandoc містять такий заголовок:
# # ADVISES TO DEVELOPERS: # - you do not need to manually edit POT or PO files. # - this file contains the translation of your debconf templates. # Do not replace the translation of your program with this !! # (or your translators will get very upset) # # ADVISES TO TRANSLATORS: # If you are not familiar with the PO format, gettext documentation # is worth reading, especially sections dedicated to this format. # For example, run: # info -n '(gettext)PO Files' # info -n '(gettext)Header Entry' # # Some information specific to po-debconf are available at # /usr/share/doc/po-debconf/README-trans # or http://www.debian.org/intl/l10n/po-debconf/README-trans #
- https://docs.kde.org/stable5/uk/kdesdk/lokalize/project-view.html - http://www.debian.org/intl/l10n/
Втім, не усе так безхмарно. У цього підходу теж є недоліки, з якими доводиться мати справу.
Однією з моїх мрій є інтеграція po4a до Gtranslator або Lokalize. При відкритті файла документації програма автоматично б видобувала рядки для перекладу, а перекладений файл і файл po записувала б на диск. Якщо б нам вдалося створити модуль MS Word™ (принаймні модуль для RTF), такою комбінацією модуля з програмами для перекладу могли б користуватися навіть професійні перекладачі.
Denis Barbier <barbier,linuxfr.org> Martin Quinson (mquinson#debian.org)
2018-12-09 | Інструменти Po4a |