- PVSM.RU - https://www.pvsm.ru -
Продолжаю серию статей, посвященных настройке непрерывных локализаций. Первую вы можете найти здесь [1]. В этой статье я расскажу, как интегрировать связку Serge-Smartcat-GitLab и настроить конфигурационные файлы Serge на примере тестового проекта. Инструкция для Ubuntu.
Результатом выполнения сборки Vagrant будет виртуальная машина с Ubuntu, на которую установлен Serge с плагином Smartcat. Все необходимые файлы будут скопированы, ssh-ключ — создан. Вы можете сразу переходить к настройке проекта и запуску приложения.
Если у вас под рукой нет сервера с Ubuntu, вы можете использовать Vagrant. Как это работает:
Создайте группу пользователей serge:
sudo groupadd serge
Создайте пользователя serge c домашним каталогом /usr/local/serge:
sudo useradd -g serge serge -m -d /usr/local/serge
Полная документация Serge находится здесь [4].
Обновите метаданные локальной базы пакетов:
sudo apt-get -qq update
Установите инструментарий для сборки, а также необходимые пакеты. Перед началом установки убедитесь, что установлен Perl 5.10 или выше.
sudo apt-get -qq -y install build-essential libssl-dev libexpat-dev unzip wget
Перейдите в домашний каталог пользователя serge и установите Serge со всеми необходимыми зависимостями.
cd /usr/local/serge
sudo -u serge wget https://github.com/evernote/serge/archive/master.zip -O serge-master.zip
sudo -u serge unzip serge-master.zip
sudo -u serge unlink serge-master.zip
cd serge-master
sudo cpan App::cpanminus
sudo cpanm --installdeps .
sudo -u serge sudo ln -s /usr/local/serge/serge-master/bin/serge /usr/local/bin/serge
sudo cpanm HTTP::Daemon@6.01
sudo cpanm Serge::Sync::Plugin::TranslationService::Smartcat
sudo cpan install LWP::Protocol::https
Создайте пользователю serge ssh-ключ, по которому пользователь serge будет ходить в GitLab:
sudo -u serge ssh-keygen -t rsa -N "" -f .id_rsa_serge
Создайте пользователя serge в GitLab и добавьте его во все репозитории с правами developer.
Скопируйте ssh-ключ из файла id_rsa_serge.pub в настройки профиля пользователя serge в GitLab. Это необходимо, чтобы Serge мог получать и отправлять строки в GitLab.
Установка завершена!
Для начала работы необходимо:
Прежде чем перейти к настройке, опишу общий принцип работы. Стандартный цикл локализации включает в себя 5 шагов:
Как Serge узнает, какие строки надо отправить на перевод? Для определения новых строк используются стандартные инструменты git: берется разница между master-веткой и текущей. Diff отправляется на перевод.
Важно: Как правило, master-ветка является protected, поэтому для определения diff-ов используется дополнительная ветка переводов, мы ее называем base-translate. То есть, после мержа релиза в master, master необходимо дополнительно смержить в base-translate.
Здесь есть важный момент. Необходимо построить процессы таким образом, чтобы, с одной стороны, разработчики понимали, что и в какой момент уйдет на перевод, а с другой, чтобы техпис не бегал кругами, взявшись за голову, потому что у него diff составил 1000 строк. А вроде только заголовок поправили.
Serge заходит в репозиторий, берет все ветки, и начинает сравнивать их с master-веткой. Для каждой ветки, в которой обнаружен diff, он создает в проекте Smartcat набор документов на перевод. Чтобы не погрязнуть в хаосе неактуальных веток и не стоять около каждого разработчика с вопросом: “а ты не забыл удалить ветку?”, удобно использовать префиксы. Например, у нас Serge работает только с ветками, которые имеют префикс translate- .
Также важно, чтобы в ветку с префиксом translate- попадали уже вычитанные и утвержденные тексты, готовые к переводу. Никому ведь не хочется разбирать историю коммитов в тщетных попытках понять, что это за тексты и почему diff выглядит именно так?
Наш процесс подготовки контента выглядит следующим образом:
Постановка задачи. Когда задача находится в стадии постановки, иногда уже там появляются тексты, которые должны в неизменном виде попасть в приложение. Если они есть, копирайтер и технический писатель помогают их финализировать.
Разработка макетов. Когда дизайнер подготовил макеты, технический писатель и копирайтер вычитывают все тексты. Таким образом, в разработку попадают вычитанные макеты на английском языке. Разработчик не должен думать о текстах, он просто берет готовые строки с макетов.
Разработка. К сожалению, предыдущие шаги не могут покрыть все возможные типы текстов. Например, макеты не включают валидаторы, ошибки API, некоторые модальные окна. Если в процессе разработки понадобилось добавить строки, технический писатель и копирайтер предоставляют разработчику все необходимые тексты.
Таким образом, в какой-то момент времени мы имеем состояние, когда ветка содержит в себе все новые тексты, необходимые для той части кода, которая в ней разрабатывается. В этот момент от нее создается новая ветка с префиксом translate- и Serge может начинать процесс перевода. Когда переводы готовы, разработчик забирает их из translate-ветки, и далее действует по git flow, принятому в команде.
Данный процесс минимизирует вовлеченность разработчика в процесс локализации, а также сводит к абсолютному минимуму количество ручного труда: надо всего лишь создать ветку.
Дальнейшее описание процесса настройки во многом опирается на то, что в команде существуют схожие договоренности и процессы.
Войдите под пользователем serge:
sudo -Hu serge -i
Создайте директорию groups:
mkdir groups
В этой директории будут размещены проекты, соответствующие репозиториям в GitLab. Имеет смысл повторять структуру групп репозиториев и их расположения для облегчения навигации.
Создайте директорию для первого проекта:
cd groups
mkdir myproject
cd myproject
Скопируйте файлы конфигурации Serge. Можно установить midnight commander [11]и управлять файлами при помощи файлового менеджера. Перед установкой MC необходимо выйти из-под учетной записи serge.
exit
sudo apt install mc
sudo -Hu serge -i
Файлы, которые необходимо скопировать из /usr/local/serge/serge-master/bin/tools/feature-branch-config-generator:
cp /usr/local/serge/serge-master/bin/tools/feature-branch-config-generator/{myproject.cfg,myproject.inc,myproject.serge.tmpl,myproject_branches.txt} /usr/local/serge/serge-master/groups/myproject
cp /usr/local/serge/serge-master/bin/tools/feature-branch-config-generator/fbcgen.pl /usr/local/serge/serge-master/
Создайте файл для записи логов плагина:
mkdir log
cd log
touch smartcat.log
Важно! В source_path_prefix в конце должна стоять точка %FBCGEN_BRANCH.
Вызов плагина Smartcat необходимо добавить в соответствующий раздел myproject.serge.tmpl
sync {
ts
{
plugin Smartcat
data
{
project_id 12345678-1234-1234-1234-1234567890123
token_id 12345678-1234-1234-1234-1234567890123
token 1_qwertyuiopasdfghjklzxcvbn
push {
disassemble_algorithm_name Serge.io PO
}
pull {
complete_projects NO
complete_documents YES
}
log_file ./log/smartcat.log
}
}
Описание некоторых параметров:
Ниже приведены конфигурационные файлы для проекта с 6 языками. Проект хранит исходные строки в js-формате. Используется 5-символьный формат именования файлов. Путь к ресурсным файлам: ./branches/base-translate/client/src/translations.
# This is a configuration file for fbcgen.pl
# Usage: fbcgen.pl myproject.cfg
# Root directory where the master branch checkout is located.
# (path is relative to the location of the configuration file itself).
# The local checkout should be initialized *before* fbcgen.pl is run.
# You can run `serge --initialize onboarding-frontend.serge.tmpl`
# to do an initial checkout of the project data.
$data_dir = './branches/base-translate';
$branch_list_file = 'myproject_branches.txt';
# Where to load Serge config template from.
# (path is relative to the location of the configuration file itself).
$template_file = "myproject.serge.tmpl";
# Where to save the localized Serge config file.
# (path is relative to the location of the configuration file itself).
$output_file = "myproject.local.serge";
our $skip_branch_mask = '^(master)$'; # skip these branches unconditionally
our $unmerged_branch_mask = '^(translate-)'; # process unmerged branches matching this mask
our $any_branch_mask = '^(translate-)'; # additionally, process these branches even if they were merged
# Filter out commits that match this mask when determining if branch is inactive.
$skip_commit_mask = '^l10n@example.com';
# This sub returns a hash map of additional parameters
# that can be referenced in template as `$FBCGEN_<VARIABLE_NAME>`.
# For example, `EXTRA_INCLUDE` parameter generated in the function below
# is referenced in `myproject.serge.tmpl` file as `$FBCGEN_EXTRA_INCLUDE`.
$calculate_params = sub {
my ($branch) = @_;
return {
# for branch names starting with `release/`, return an empty string;
# otherwise, return a string that will be used in the `@include` directive
EXTRA_INCLUDE => $branch =~ m!^release/! ? '' : "myproject.inc#skip-saving-localized-filesn"
}
}
# Here we define a job template (common parameters) that will be reused
# across all jobs in the generated configuration file.
# Certain job parameters (like job ID and paths) will be overridden
# in each feature branch job.
job-template
{
name JS file processing ('master' branch)
id myproject.js.base-translate # master job id
db_namespace myproject
destination_languages ru ko de ja zh-Hans
source_dir ./myproject/base-translate/res/en
output_file_path ./myproject/base-translate/res/%LANG%/%FILE%
source_match .js$
parser
{
plugin parse_js
}
ts_file_path ./po/myproject/%LOCALE%/%FILE%.po
callback_plugins
{
:feature_branch
{
plugin feature_branch
data
{
master_job myproject.js.base-translate # this must match your master job id
}
}
}
}
# This block will be included conditionally
# for all branches except the `release/` ones (see myproject.cfg).
# This allows one to skip saving localized files in non-release branches
# (but still gather from them strings for translation).
skip-saving-localized-files
{
callback_plugins
{
:skip-saving-localized-files
{
plugin process_if
phase can_generate_localized_file
data
{
if
{
lang_matches .
then
{
return NO
}
}
}
}
}
}
sync {
ts
{
plugin Smartcat
data
{
project_id %project_id%
token_id %token_id%
token %token%
push {
disassemble_algorithm_name Serge.io PO
}
pull {
complete_projects NO
complete_documents YES
}
}
}
vcs {
plugin git
data {
local_path ./branches
add_unversioned YES
name L10N Robot
email l10n-robot@example.com
remote_path {
base-translate git@gitlab.loc:common/myproject.git#base-translate
/* FBCGEN_BRANCH_REMOTES
$FBCGEN_DIR_PADDED git@gitlab.loc:common/myproject.git#$FBCGEN_BRANCH
*/
}
}
}
}
jobs {
:develop {
id job.base-translate
name myproject
source_language en
destination_languages ru zh-Hans ko de ja
optimizations NO
source_dir ./branches/base-translate/client/src/translations
source_match `en-US.js`
debug NO
parser {
plugin parse_js
}
leave_untranslated_blank YES
db_source DBI:SQLite:dbname=./myproject.db3
db_namespace myproject
ts_file_path ./po/1bd80338-a0b5-48b3-822c-e90affd2cdcc/%LANG%/%FILE%.po
output_file_path ./branches/base-translate/client/src/translations/%CULTURE%.%EXT%
output_bom NO
output_lang_rewrite {
zh-Hans zh
}
callback_plugins {
:feature_branch {
plugin feature_branch
data {
master_job job.base-translate
}
}
}
}
/* FBCGEN_BRANCH_JOBS
:$FBCGEN_DIR {
@inherit .#jobs/:develop
id job.$FBCGEN_DIR
$FBCGEN_EXTRA_INCLUDE
source_path_prefix $FBCGEN_BRANCH.
source_dir ./branches/$FBCGEN_DIR/client/src/translations/
output_file_path ./branches/$FBCGEN_DIR/client/src/translations/%CULTURE%.%EXT%
}
*/
}
Клонируем репозиторий
GIT_SSH_COMMAND="ssh -i /usr/local/serge/serge-master/.id_rsa_serge" git clone -b base-translate git@gitlab.loc:groups/myproject.git branches/base-translate/
Формируется файл .serge:
GIT_SSH_COMMAND="ssh -i /usr/local/serge/serge-master/.id_rsa_serge" /usr/local/serge/serge-master/fbcgen.pl myproject.cfg
Забор изменений из всех веток репозитория:
GIT_SSH_COMMAND="ssh -i /usr/local/serge/serge-master/.id_rsa_serge" serge pull --initialize myproject.local.serge
Забор изменений переводов по всем веткам из Smartcat:
GIT_SSH_COMMAND="ssh -i /usr/local/serge/serge-master/.id_rsa_serge" serge pull-ts myproject.local.serge
Формирование БД и .po:
GIT_SSH_COMMAND="ssh -i /usr/local/serge/serge-master/.id_rsa_serge" serge localize myproject.local.serge
Отправка новых данных из репозитория в Smartcat:
GIT_SSH_COMMAND="ssh -i /usr/local/serge/serge-master/.id_rsa_serge" serge push-ts myproject.local.serge
Отправка полученных переводов в репозиторий в соответствующие ветки:
GIT_SSH_COMMAND="ssh -i /usr/local/serge/serge-master/.id_rsa_serge" serge push myproject.local.serge
Следующие статьи будут посвящены траблшутингу и описанию частных случаев интеграции.
Автор: NatalyaPavlikova
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/localization/313564
Ссылки в тексте:
[1] здесь: https://habr.com/ru/post/445532/
[2] инструкции: https://help.ubuntu.ru/wiki/vagrant
[3] Скачайте : https://github.com/npavlikova/serge-smartcat
[4] здесь: https://serge.io/
[5] Smartcat: https://www.smartcat.ai/
[6] коды языков: https://help.smartcat.ai/hc/en-us/articles/360004895371-Supported-languages-and-language-codes
[7] project_id: https://help.smartcat.ai/hc/en-us/articles/115002522912-What-is-Smartcat-project-ID
[8] token и token_id: https://help.smartcat.ai/hc/en-us/articles/115002475012-Getting-Started-with-SmartCAT-API
[9] support@smartcat.ai: mailto:support@smartcat.ai
[10] Pootle: https://serge.io/docs/guides/pootle/
[11] midnight commander : https://midnight-commander.org/
[12] документации serge: https://serge.io/docs/file-formats/
[13] Источник: https://habr.com/ru/post/446640/?utm_campaign=446640
Нажмите здесь для печати.