Додавання перекладу до своєї програми

Ubuntu Touch — велика спільнота з багатьма мовами та діалектами. Коли Вам захочеться збільшити кількість користувачів програми через додавання до неї перекладів різними мовами, це може буди складним завданням, чи то буде програма з нуля, чи портування/форк вже наявної програми. Нижче буде описано, як реалізувати можливість додавати переклади до своєї програми, якщо вона ще не має такої функції.

Підказка: Якщо Ви маєте навички перекладу та шукаєте інформацію як перекладати програми, які вже мають багатомовну можливість, зверніться, будь ласка, до Документації з перекладу в частині внесків та участі.

Як перекладається текст (технічний фон)

Оскільки розділ з описом вже наявний у Документації з перекладу в частині внесків та участі, це було б чудово, якби перед початком роботи зі своєю програмою, Ви б уже розуміли технічну частину.

Більшість програм для Ubuntu Touch використовують для перекладу GNU gettext. Файл-шаблон .pot містить усі мовні рядки програми. З цього шаблону створюються окремі файли .po для кожної мови. Ці файли .po містять актуальні переклади. Для додавання нової мови потрібно створити новий файл .po. Для перекладу на нову мову у файлах .po потрібно редагувати рядки. Поруч з оригінальним текстом на окремому рядку (переважно англійською) потрібно додати переклад відповідною мовою, використовуючи синтаксис файлів .po, так званий gettext. Деякі програми використовують для перекладу QtLinguist. Цей інструмент дотримується тих самих правил, тільки використовує для перекладів файли .ts з іншим синтаксисом. Шаблоном служить у такому разі один файл .ts.

У програмі, якщо використовується gettext, рядки позначаються як i18n.tr("string"), якщо використовується QtLinguist, то tr("string"). Коли програма створюється, ці рядки для перекладу збираються та записуються до файлу-шаблону .pot або до .ts. Після цього мовні файли .po та .ts необхідно оновити з їх шаблонів.

Коли рядки будуть перекладені, вони стануть доступними користувачам з випуском нової версії програми.

Про що потрібно пам’ятати розробнику під час створення нової програми для Ubuntu Touch?

Рекомендований спосіб створення програми для Ubuntu Touch з нуля, це використання одного з шаблонів clickable через команду clickable create. Ці шаблони вже мають все, що потрібно для створення програм з багатомовною можливістю та потребують з Вашого боку мінімальних зусиль, щоб це стало реальністю. Якщо починаєте з одного з цих шаблонів, Ваша програма після збірки матиме для кожного текстового рядка структуру i18n.tr("string") якщо користуєтеся gettext або tr("string"), якщо користуєтеся QtLinguist. Нижче наведено приклад для кнопки:

Button {
        id: menuNewGame
        text: i18n.tr("New Game")
        gradient: LomiriColors.orangeGradient
        anchors {
                margins: units.gu(2)
                centerIn: parent
        }

        onClicked: {
        aNewGame()
        }
}

Зверніть увагу на поле text: з форматом i18n.tr("string") для рядка "New Game". Коли програма буде збиратися, файли CMakelist.txt викликатимуть gettext, який своєю чергою оновить мовні файли в теці ./po. Це виглядатиме приблизно так:

#: ../components/Menu.qml:196
msgid "New Game"
msgstr ""

Використання шаблонів clickable забезпечує автоматичне оновлення файлів .po та .ts з усіма доступними рядками Вашої програми після кожного її редагування та збирання.

Як додавати переклад до вже наявних програм?

Якщо Ви вже почали роботу над програмою без використання шаблонів clickable, чи може портуєте наявну програму, або навіть оновлюєте програму зі старої версії Ubuntu Touch на нову, то ймовірно в коді програми немає такої багатомовної структури. Це все нормально, оскільки додати багатомовну підтримку з gettext можна й для вже наявних програм.

Спочатку створіть теку po у кореневому каталозі своєї програми. У цій теці створіть файл CMakeLists.txt та додайте у нього таку інформацію для виклику gettext:

 1     include(FindGettext)
 2     find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)
 3
 4     set(DOMAIN ${FULL_PROJECT_NAME})
 5     set(POT_FILE ${DOMAIN}.pot)
 6     file(GLOB PO_FILES *.po)
 7
 8     # Creates the .pot file containing the translations template
 9     add_custom_target(${POT_FILE} ALL
10             COMMENT "Generating translation template"
11             COMMAND ${INTLTOOL_EXTRACT} --update --type=gettext/ini
12                     --srcdir=${CMAKE_SOURCE_DIR} ${DESKTOP_FILE_NAME}.in
13
14     COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} -o ${POT_FILE}
15             -D ${CMAKE_CURRENT_SOURCE_DIR}
16             -D ${CMAKE_CURRENT_BINARY_DIR}
17             --from-code=UTF-8
18             --c++ --qt --language=javascript --add-comments=TRANSLATORS
19             --keyword=tr --keyword=tr:1,2 --keyword=ctr:1c,2 --keyword=dctr:2c,3 --keyword=N_ --keyword=_
20             --keyword=dtr:2 --keyword=dtr:2,3 --keyword=tag --keyword=tag:1c,2
21             --package-name='${DOMAIN}'
22             --sort-by-file
23             ${I18N_SRC_FILES}
24     COMMAND ${CMAKE_COMMAND} -E copy ${POT_FILE} ${CMAKE_CURRENT_SOURCE_DIR})
25
26     # Builds the binary translations catalog for each language
27     # it finds source translations (*.po) for
28     foreach(PO_FILE ${PO_FILES})
29     get_filename_component(LANG ${PO_FILE} NAME_WE)
30     gettext_process_po_files(${LANG} ALL PO_FILES ${PO_FILE})
31     set(INSTALL_DIR ${CMAKE_INSTALL_LOCALEDIR}/share/locale/${LANG}/LC_MESSAGES)
32     install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LANG}.gmo
33             DESTINATION ${INSTALL_DIR}
34             RENAME ${DOMAIN}.mo)
35     endforeach(PO_FILE)

Далі Вам буде потрібно додати такий код до головного файлу CMakeLists.txt Вашого проєкту:

 1     add_subdirectory(po)
 2
 3     file(GLOB_RECURSE I18N_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po *.qml *.js)
 4     list(FILTER I18N_SRC_FILES EXCLUDE REGEX "${CMAKE_CURRENT_SOURCE_DIR}/build/.*" )
 5     list(APPEND I18N_SRC_FILES ${DESKTOP_FILE_NAME}.in.h)
 6
 7     find_program(INTLTOOL_MERGE intltool-merge)
 8     if(NOT INTLTOOL_MERGE)
 9     message(FATAL_ERROR "Could not find intltool-merge, please install the intltool package")
10     endif()
11     find_program(INTLTOOL_EXTRACT intltool-extract)
12     if(NOT INTLTOOL_EXTRACT)
13     message(FATAL_ERROR "Could not find intltool-extract, please install the intltool package")
14     endif()
15
16     add_custom_target(${DESKTOP_FILE_NAME} ALL
17     COMMENT "Merging translations into ${DESKTOP_FILE_NAME}..."
18     COMMAND LC_ALL=C ${INTLTOOL_MERGE} -d -u ${CMAKE_SOURCE_DIR}/po ${CMAKE_SOURCE_DIR}/${DESKTOP_FILE_NAME}.in ${DESKTOP_FILE_NAME}
19     COMMAND sed -i 's/${PROJECT_NAME}-//g' ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE_NAME}
20     )
21
22     install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE_NAME} DESTINATION ${DATA_DIR})

Також можливо потрібно додати деякі уточнення на початку Вашого проєктного файлу CMakeLists.txt:

1     set(PROJECT_NAME "Your project")
2     set(FULL_PROJECT_NAME "Your.project")
3     set(CMAKE_INSTALL_PREFIX /)
4     set(DATA_DIR /)
5     set(DESKTOP_FILE_NAME ${PROJECT_NAME}.desktop)

Все, що Вам залишилося зробити, це позначити текст у своїй програмі маркерами i18n.tr(«string») або tr(«string»). Можна просто змінити вже наявні рядки та додати до них ці маркери, як у цьому прикладі з кнопкою:

Button {
id: returnToGame
text: i18n.tr("Return to game")
gradient: LomiriColors.orangeGradient
visible: false
anchors {
    margins: units.gu(2)
    top: menuSave.bottom
    horizontalCenter: parent.horizontalCenter
}

onClicked: {
        mainView.menu = false;
        }
}

У цьому прикладі ми додали до текстового поля text: маркування i18n.tr("string") для рядка "Return to game". Тепер якщо запустити процес збирання, cmake запустить програму gettext, пройдеться крізь усі файли *.qml та *.js (у цьому прикладі) та створить для Вашої програми необхідний файл .pot, який вже далі для перекладу Вашої програми зможуть використовувати перекладачі!

Якщо Вам потрібні додаткові приклади як це працює, можна ознайомитися з подібними комітами для CitySim:

Реорганізація для можливості перекладу

Успішно додано можливості перекладу

Додано переклади до всіх текстів