=encoding utf-8

=head1 NAME

App::Greple::xlate - модуль поддержки перевода для greple

=head1 SYNOPSIS

    greple -Mxlate::deepl --xlate pattern target-file

    greple -Mxlate::gpt4 --xlate pattern target-file

    greple -Mxlate::gpt5 --xlate pattern target-file

    greple -Mxlate --xlate-engine gpt5 --xlate pattern target-file

=head1 VERSION

Version 0.9918

=head1 DESCRIPTION

Модуль B<Greple> B<xlate> находит нужные текстовые блоки и заменяет их переведенным текстом. В настоящее время в качестве внутреннего движка реализованы модули DeepL (F<deepl.pm>), ChatGPT 4.1 (F<gpt4.pm>) и GPT-5 (F<gpt5.pm>).

Если вы хотите перевести обычные текстовые блоки в документе, написанном в стиле Perl's pod, используйте команду B<greple> с модулем C<xlate::deepl> и C<perl> следующим образом:

    greple -Mxlate::deepl -Mperl --pod --re '^([\w\pP].*\n)+' --all foo.pm

В этой команде шаблонная строка C<^([\w\pP].*\n)+> означает последовательные строки, начинающиеся с букв алфавитно-цифрового ряда и знаков препинания. Эта команда показывает область, которую нужно перевести, выделенной. Опция B<--all> используется для перевода всего текста.

=for html <p>
<img width="750" src="https://raw.githubusercontent.com/kaz-utashiro/App-Greple-xlate/main/images/select-area.png">
</p>

Затем добавьте опцию C<--xlate> для перевода выделенной области. После этого программа найдет нужные участки и заменит их выводом команды B<--deepl>.

По умолчанию оригинальный и транслированный текст печатается в формате "маркер конфликта", совместимом с L<git(1)>. Используя формат C<ifdef>, можно легко получить нужную часть командой L<unifdef(1)>. Выходной формат может быть задан опцией B<--xlate-format>.

=for html <p>
<img width="750" src="https://raw.githubusercontent.com/kaz-utashiro/App-Greple-xlate/main/images/format-conflict.png">
</p>

Если требуется перевести весь текст, используйте опцию B<--match-all>. Это сокращение для указания шаблона C<(?s).+>, который соответствует всему тексту.

Данные в формате конфликтных маркеров можно просматривать в стиле "бок о бок" с помощью команды L<sdif|App::sdif> с опцией C<-V>. Поскольку сравнивать по каждой строке не имеет смысла, рекомендуется использовать опцию C<--no-cdif>. Если вам не нужно окрашивать текст, укажите C<--no-textcolor> (или C<--no-tc>).

    sdif -V --no-filename --no-tc --no-cdif data_shishin.deepl-EN-US.cm

=for html <p>
<img width="750" src="https://raw.githubusercontent.com/kaz-utashiro/App-Greple-xlate/main/images/sdif-cm-view.png">
</p>

=head1 NORMALIZATION

Обработка выполняется в заданных единицах, но в случае последовательности из нескольких строк непустого текста они преобразуются в одну строку. Эта операция выполняется следующим образом:

=over 2

=item *

Удалите пробелы в начале и конце каждой строки.

=item *

Если строка заканчивается полноразмерным символом препинания, объедините ее со следующей строкой.

=item *

Если строка заканчивается символом полной ширины и следующая строка начинается символом полной ширины, объедините строки.

=item *

Если конец или начало строки не являются символами полной ширины, объедините их, вставив символ пробела.

=back

Кэш-данные управляются на основе нормализованного текста, поэтому даже если будут внесены изменения, не влияющие на результаты нормализации, кэшированные данные перевода будут по-прежнему эффективны.

Этот процесс нормализации выполняется только для первого (0-го) и четного шаблона. Таким образом, если два шаблона указаны следующим образом, то текст, соответствующий первому шаблону, будет обработан после нормализации, а для текста, соответствующего второму шаблону, процесс нормализации не будет выполняться.

    greple -Mxlate -E normalized -E not-normalized

Поэтому используйте первый шаблон для текста, который должен быть обработан путем объединения нескольких строк в одну, а второй - для предварительно отформатированного текста. Если в первом шаблоне нет текста для проверки, используйте шаблон, который ничему не соответствует, например C<(?!)>.

=head1 MASKING

Иногда встречаются части текста, которые не нужно переводить. Например, теги в файлах формата markdown. На сайте DeepL предлагается в таких случаях преобразовывать исключаемые части текста в XML-теги, переводить их, а затем восстанавливать после завершения перевода. Чтобы поддержать эту идею, можно указать части, которые нужно замаскировать от перевода.

    --xlate-setopt maskfile=MASKPATTERN

При этом каждая строка файла `MASKPATTERN` будет интерпретироваться как регулярное выражение, переводить строки, соответствующие ему, и возвращаться после обработки. Строки, начинающиеся с C<#>, игнорируются.

Сложный шаблон может быть записан в нескольких строках с обратным слешем, сопровождаемым новой строкой.

Как текст преобразуется при маскировании, можно увидеть с помощью опции B<--xlate-mask>.

Этот интерфейс является экспериментальным и может быть изменен в будущем.

=head1 OPTIONS

=over 7

=item B<--xlate>

=item B<--xlate-color>

=item B<--xlate-fold>

=item B<--xlate-fold-width>=I<n> (Default: 70)

Запустите процесс перевода для каждой совпавшей области.

Без этой опции B<greple> ведет себя как обычная команда поиска. Таким образом, вы можете проверить, какая часть файла будет подвергнута переводу, прежде чем вызывать фактическую работу.

Результат команды выводится в стандартный аут, поэтому при необходимости перенаправьте его в файл или воспользуйтесь модулем L<App::Greple::update>.

Опция B<--xlate> вызывает опцию B<--xlate-color> с опцией B<--color=never>.

С опцией B<--xlate-fold> преобразованный текст сворачивается на указанную ширину. Ширина по умолчанию равна 70 и может быть задана опцией B<--xlate-fold-width>. Для обкатки зарезервировано четыре колонки, поэтому в каждой строке может содержаться не более 74 символов.

=item B<--xlate-engine>=I<engine>

Определяет используемый движок перевода. Если вы указываете модуль движка напрямую, например C<-Mxlate::deepl>, то этот параметр использовать не нужно.

На данный момент доступны следующие движки

=over 2

=item * B<deepl>: DeepL API

=item * B<gpt3>: gpt-3.5-turbo

=item * B<gpt4>: gpt-4.1

=item * B<gpt4o>: gpt-4o-mini

Интерфейс B<gpt-4o> нестабилен и в настоящее время не может быть гарантированно корректной работы.

=item * B<gpt5>: gpt-5

=back

=item B<--xlate-labor>

=item B<--xlabor>

Вместо того чтобы вызывать механизм перевода, вы должны работать на него. После подготовки текста для перевода он копируется в буфер обмена. Вы должны вставить их в форму, скопировать результат в буфер обмена и нажать кнопку return.

=item B<--xlate-to> (Default: C<EN-US>)

Укажите целевой язык. Вы можете получить доступные языки с помощью команды C<deepl languages> при использовании движка B<DeepL>.

=item B<--xlate-format>=I<format> (Default: C<conflict>)

Укажите формат вывода оригинального и переведенного текста.

Следующие форматы, кроме C<xtxt>, предполагают, что переводимая часть представляет собой набор строк. На самом деле можно перевести только часть строки, но указание формата, отличного от C<xtxt>, не даст значимых результатов.

=over 4

=item B<conflict>, B<cm>

Оригинальный и преобразованный текст печатаются в формате L<git(1)> маркеров конфликтов.

    <<<<<<< ORIGINAL
    original text
    =======
    translated Japanese text
    >>>>>>> JA

Вы можете восстановить исходный файл следующей командой L<sed(1)>.

    sed -e '/^<<<<<<< /d' -e '/^=======$/,/^>>>>>>> /d'

=item B<colon>, I<:::::::>

Оригинальный и переведенный текст выводятся в пользовательском стиле контейнера markdown.

    ::::::: ORIGINAL
    original text
    :::::::
    ::::::: JA
    translated Japanese text
    :::::::

Приведенный выше текст будет переведен в HTML следующим образом.

    <div class="ORIGINAL">
    original text
    </div>
    <div class="JA">
    translated Japanese text
    </div>

Количество двоеточий по умолчанию равно 7. Если вы укажете последовательность двоеточий, например C<:::::>, то она будет использоваться вместо 7 двоеточий.

=item B<ifdef>

Оригинальный и преобразованный текст печатаются в формате L<cpp(1)> C<#ifdef>.

    #ifdef ORIGINAL
    original text
    #endif
    #ifdef JA
    translated Japanese text
    #endif

Вы можете восстановить только японский текст командой B<unifdef>:

    unifdef -UORIGINAL -DJA foo.ja.pm

=item B<space>

=item B<space+>

Оригинальный и преобразованный текст выводятся на печать, разделенные одной пустой строкой. Для C<пробел+> после преобразованного текста также выводится новая строка.

=item B<xtxt>

Если формат C<xtxt> (переведенный текст) или неизвестен, печатается только переведенный текст.

=back

=item B<--xlate-maxlen>=I<chars> (Default: 0)

Укажите максимальную длину текста, передаваемого в API за один раз. По умолчанию установлено значение, как для бесплатного сервиса DeepL: 128К для API (B<--xlate>) и 5000 для интерфейса буфера обмена (B<--xlate-labor>). Вы можете изменить эти значения, если используете услугу Pro.

=item B<--xlate-maxline>=I<n> (Default: 0)

Укажите максимальное количество строк текста, которое будет отправлено в API за один раз.

Установите значение 1, если вы хотите переводить по одной строке за раз. Этот параметр имеет приоритет перед параметром C<--xlate-maxlen>.

=item B<--xlate-prompt>=I<text>

Укажите пользовательскую подсказку, которая будет отправлена механизму перевода. Этот параметр доступен только при использовании движков ChatGPT (gpt3, gpt4, gpt4o). Вы можете настроить поведение переводчика, предоставив специальные инструкции модели искусственного интеллекта. Если подсказка содержит C<%s>, она будет заменена на название целевого языка.

=item B<--xlate-context>=I<text>

Укажите дополнительную контекстную информацию, которая будет отправлена механизму перевода. Этот параметр можно использовать несколько раз, чтобы указать несколько контекстных строк. Контекстная информация помогает механизму перевода понять фон и создать более точный перевод.

=item B<--xlate-glossary>=I<glossary>

Укажите идентификатор глоссария, который будет использоваться при переводе. Этот параметр доступен только при использовании механизма DeepL. Идентификатор глоссария должен быть получен из учетной записи DeepL и обеспечивает последовательный перевод специфических терминов.

=item B<-->[B<no->]B<xlate-progress> (Default: True)

Результат перевода можно увидеть в реальном времени в выводе STDERR.

=item B<--xlate-stripe>

Используйте модуль L<App::Greple::stripe>, чтобы показать совпадающие части в виде полосок зебры. Это удобно, когда совпадающие части соединены встык.

Цветовая палитра переключается в соответствии с цветом фона терминала. Если вы хотите указать его явно, можно использовать B<--xlate-stripe-light> или B<--xlate-stripe-dark>.

=item B<--xlate-mask>

Выполните функцию маскирования и отобразите преобразованный текст как есть, без восстановления.

=item B<--match-all>

Установите весь текст файла в качестве целевой области.

=item B<--lineify-cm>

=item B<--lineify-colon>

В случае форматов C<cm> и C<colon> вывод разбивается и форматируется построчно. Поэтому, если перевести только часть строки, ожидаемый результат не будет получен. Эти фильтры исправляют вывод, испорченный переводом части строки в обычный построчный вывод.

В текущей реализации, если переводится несколько частей строки, они выводятся как независимые строки.

=back

=head1 CACHE OPTIONS

Модуль B<xlate> может хранить кэшированный текст перевода для каждого файла и считывать его перед выполнением, чтобы исключить накладные расходы на запрос к серверу. При стратегии кэширования по умолчанию C<auto>, он сохраняет данные кэша только тогда, когда файл кэша существует для целевого файла.

Используйте B<--xlate-cache=clear>, чтобы запустить управление кэшем или очистить все существующие данные кэша. После выполнения этой опции будет создан новый файл кэша, если он не существует, а затем он будет автоматически поддерживаться.

=over 7

=item --xlate-cache=I<strategy>

=over 4

=item C<auto> (Default)

Сохранять файл кэша, если он существует.

=item C<create>

Создать пустой файл кэша и выйти.

=item C<always>, C<yes>, C<1>

Сохранять кэш в любом случае, пока целевой файл является обычным файлом.

=item C<clear>

Сначала очистите данные кэша.

=item C<never>, C<no>, C<0>

Никогда не использовать файл кэша, даже если он существует.

=item C<accumulate>

По умолчанию неиспользуемые данные удаляются из файла кэша. Если вы не хотите удалять их и сохранять в файле, используйте C<accumulate>.

=back

=item B<--xlate-update>

Эта опция заставляет обновлять файл кэша, даже если в этом нет необходимости.

=back

=head1 COMMAND LINE INTERFACE

Вы можете легко использовать этот модуль из командной строки с помощью команды C<xlate>, входящей в дистрибутив. Информацию об использовании см. на странице руководства C<xlate>.

Команда C<xlate> поддерживает длинные опции в стиле GNU, такие как C<--to-lang>, C<--from-lang>, C<--engine> и C<--file>. Используйте C<xlate -h>, чтобы увидеть все доступные опции.

Команда C<xlate> работает совместно со средой Docker, поэтому даже если у вас ничего не установлено, вы можете использовать ее, пока доступен Docker. Используйте опцию C<-D> или C<-C>.

Операции Docker обрабатываются скриптом C<xrun>, который также можно использовать как отдельную команду. Скрипт C<xrun> поддерживает конфигурационный файл C<.xrunrc> для постоянных настроек контейнера.

Кроме того, поскольку в комплекте поставляются make-файлы для различных стилей документов, перевод на другие языки возможен без специальных уточнений. Используйте опцию C<-M>.

Вы также можете комбинировать опции Docker и C<make>, чтобы запустить C<make> в среде Docker.

Выполнение C<xlate -C> запустит оболочку с подключенным текущим рабочим git-репозиторием.

Подробности читайте в японской статье в разделе L</SEE ALSO>.

=head1 EMACS

Загрузите файл F<xlate.el>, включенный в репозиторий, чтобы использовать команду C<xlate> из редактора Emacs. Функция C<xlate-region> переводит заданный регион. Язык по умолчанию - C<EN-US>, и вы можете указать язык, вызывая ее с помощью аргумента prefix.

=for html <p>
<img width="750" src="https://raw.githubusercontent.com/kaz-utashiro/App-Greple-xlate/main/images/emacs.png">
</p>

=head1 ENVIRONMENT

=over 7

=item DEEPL_AUTH_KEY

Задайте ключ аутентификации для сервиса DeepL.

=item OPENAI_API_KEY

Ключ аутентификации OpenAI.

=back

=head1 INSTALL

=head2 CPANMINUS

    $ cpanm App::Greple::xlate

=head2 TOOLS

Необходимо установить инструменты командной строки для DeepL и ChatGPT.

L<https://github.com/DeepLcom/deepl-python>

L<https://github.com/tecolicom/App-gpty>

=head1 SEE ALSO

L<App::Greple::xlate>

L<App::Greple::xlate::deepl>

L<App::Greple::xlate::gpt4>

L<App::Greple::xlate::gpt5>

=over 2

=item * L<https://hub.docker.com/r/tecolicom/xlate>

Образ контейнера Docker.

=item * L<https://github.com/tecolicom/getoptlong>

Библиотека C<getoptlong.sh> используется для разбора опций в скриптах C<xlate> и C<xrun>.

=item * L<https://github.com/DeepLcom/deepl-python>

DeepL Библиотека Python и команда CLI.

=item * L<https://github.com/openai/openai-python>

Библиотека OpenAI Python

=item * L<https://github.com/tecolicom/App-gpty>

Интерфейс командной строки OpenAI

=item * L<App::Greple>

Подробную информацию о шаблоне целевого текста см. в руководстве B<greple>. Используйте опции B<--inside>, B<--outside>, B<--include>, B<--exclude> для ограничения области совпадения.

=item * L<App::Greple::update>

Вы можете использовать модуль C<-Mupdate> для модификации файлов по результатам команды B<greple>.

=item * L<App::sdif>

Используйте B<sdif>, чтобы показать формат маркера конфликта бок о бок с опцией B<-V>.

=item * L<App::Greple::stripe>

Использование модуля Greple B<stripe> с помощью опции B<--xlate-stripe>.

=back

=head2 ARTICLES

=over 2

=item * L<https://qiita.com/kaz-utashiro/items/1c1a51a4591922e18250>

Модуль Greple для перевода и замены только необходимых частей с помощью DeepL API (на японском языке)

=item * L<https://qiita.com/kaz-utashiro/items/a5e19736416ca183ecf6>

Генерация документов на 15 языках с помощью модуля DeepL API (на японском языке)

=item * L<https://qiita.com/kaz-utashiro/items/1b9e155d6ae0620ab4dd>

Автоматический перевод Docker-окружения с помощью DeepL API (на японском языке)

=back

=head1 AUTHOR

Kazumasa Utashiro

=head1 LICENSE

Copyright © 2023-2025 Kazumasa Utashiro.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut
