=encoding utf-8

=head1 NAME

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

=head1 SYNOPSIS

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

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

=head1 VERSION

Version 2.01

=head1 DESCRIPTION

B<Greple> B<xlate> модуль находит нужные текстовые блоки и заменяет их переведённым текстом. Основной движок — GPT-5.5 (F<llm/gpt5.pm>), который вызывает команду L<llm|https://llm.datasette.io/>; DeepL (F<deepl.pm>) и устаревшие движки на основе B<gpty> также включены.

Переводы кэшируются для каждого файла, поэтому повторный запуск команды ничего не стоит для неизменённого текста. Когда документ редактируется, в API снова отправляются только изменённые абзацы; движок, учитывающий контекст, также получает окружающие переводы, необработанный исходный текст вокруг изменения и предыдущую версию отредактированного абзаца, поэтому новый перевод сохраняет устоявшиеся формулировки (см. B<--xlate-context-window>). Конфиденциальные строки можно скрывать перед передачей (см. L</ANONYMIZATION AND TEMPLATES>).

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

    greple -Mxlate --xlate-engine gpt5 -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> для перевода выбранной области. После этого будут найдены нужные разделы и заменены выводом механизма перевода.

По умолчанию исходный и переведенный текст выводятся в формате «маркер конфликта», совместимом с 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

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

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

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

Маскирование защищает разметку от перевода. Чтобы скрыть конфиденциальные строки от самой службы перевода, см. L</ANONYMIZATION AND TEMPLATES>; оба механизма можно использовать совместно.

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

=head1 ANONYMIZATION AND TEMPLATES

Конфиденциальные строки можно скрыть до их отправки в API перевода и восстановить в выходных данных. Доступны три источника правил анонимизации: файл словаря (B<--xlate-anonymize>), встроенные пометки в самом документе (B<--xlate-anonymize-mark>) и значения YAML front matter (B<--xlate-frontmatter>). Каждая строка во время передачи заменяется тегом категории, например C<< <person id=1 /> >>. Цель сокрытия — только передача в API: локальные файлы кэша хранят восстановленный обычный текст. Используйте B<--xlate-dryrun>, чтобы проверить, что именно будет передано.

Для документов-форм (квартальных отчетов и т. п.) заранее определите участников и ссылайтесь на них в основном тексте:

    ---
    報告者: 山田太郎
    発注会社: アクメ株式会社
    ---
    本件について {{ 報告者 }} が調査を行った。

Переведите шаблон один раз для каждого языка с C<--xlate-template> (и C<--xlate-frontmatter>, когда значения сохраняются в файле), затем визуализируйте каждый случай в автономном режиме B<pandoc-embedz> -- значения в C<global:> во внешней конфигурации вообще не попадают в API перевода:

    greple -Mxlate --xlate --xlate-engine=gpt5 --xlate-to=EN-US \
           --xlate-template= --xlate-format=xtxt \
           --match-paragraph --all --need=0 \
           report-template.md > report-template.EN.md
    pandoc-embedz --standalone report-template.EN.md \
                  -c case-123.yaml -o report-123.EN.md < /dev/null

Для встроенных меток предоставление конфигурации определений макросов позволяет одному и тому же переведенному шаблону отображать либо реальные имена, либо отредактированную версию:

    # macros.yaml           # macros-redacted.yaml
    preamble: |             preamble: |
      {% macro person(name) %}{{ name }}{% endmacro %}
                              {% macro person(name) %}(関係者){% endmacro %}

Исключайте блоки embedz из перевода, когда документ их содержит:

    --exclude '^```embedz\n(?s:.*?)^```\n'

=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>. Четыре столбца зарезервированы для операции run‑in, поэтому каждая строка может содержать максимум 74 символа.

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

Указывает используемый движок перевода.

В настоящее время доступны следующие движки

=over 2

=item * B<gpt5>: gpt-5.5 (via the C<llm> command)

=item * B<deepl>: DeepL API (via the C<deepl> command)

=item * B<gpt3>: gpt-3.5-turbo (legacy, via the C<gpty> command)

=item * B<gpt4o>: gpt-4o-mini (legacy, via the C<gpty> command)

=back

Модули движков сначала ищутся в пространствах имён backend (C<llm>, затем C<gpty>), затем непосредственно в C<App::Greple::xlate>. Поэтому C<gpt5> загружает C<App::Greple::xlate::llm::gpt5>, который вызывает команду C<llm>, тогда как C<gpt4o> откатывается к C<App::Greple::xlate::gpty::gpt4o>. Используйте C<--xlate-setopt backend=gpty>, чтобы принудительно задать конкретный backend.

=item B<--xlate-labor>

=item B<--xlabor>

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

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

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

=item B<--xlate-from> (Default: C<ORIGINAL>)

Метка, используемая для исходного текста в форматах вывода C<conflict>, C<colon> и C<ifdef>. С движком 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<space+> после преобразованного текста также выводится перевод строки.

=item B<xtxt>

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

=back

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

Укажите максимальную длину текста, отправляемого в API за один раз. Значение по умолчанию 0 означает собственное ограничение движка: для бесплатного сервиса DeepL это 128K для 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>

Укажите пользовательский prompt, который будет отправлен движку перевода. Этот параметр доступен для движков LLM (C<gpt3>, C<gpt4o>, C<gpt5>), но не для DeepL. Вы можете настроить поведение перевода, предоставив конкретные инструкции AI-модели. Если prompt содержит C<%s>, он будет заменен названием целевого языка.

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

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

=item B<--xlate-context-window>=I<n>

(Context-aware engines only, e.g. C<gpt5> on the llm backend)
Количество окружающих переведенных блоков, передаваемых как справочный контекст при повторном переводе измененных блоков (по умолчанию 2). Контекст также включает исходный текст вокруг измененной области (заголовки, структуру списков, подписи) и, когда доступно, предыдущую версию измененного текста, восстановленную из cache, чтобы неизмененная формулировка сохранялась. Установите 0, чтобы полностью отключить контекстно-зависимый перевод. Обратите внимание, что каждая измененная область переводится в отдельном API-вызове, а контекст может добавить до примерно 8000 символов в system prompt, поэтому контекстно-зависимый перевод обменивает некоторую дополнительную стоимость на согласованность.

=item B<--xlate-cache-seed>=I<file>

Инициализируйте cache нового документа из cache-файла другого документа. Полезно для периодических отчетов: заполните cache нового выпуска cache предыдущего выпуска, чтобы неизмененные абзацы не переводились повторно, а отредактированные абзацы сохраняли формулировку предыдущего выпуска. Seed используется только когда целевой cache пуст; иначе он игнорируется с предупреждением. При значении по умолчанию C<--xlate-cache=auto> указание seed также подразумевает создание cache-файла нового документа.

=item B<--xlate-anonymize>=I<file>

Анонимизируйте чувствительные строки перед их отправкой в API перевода и восстанавливайте их в выводе. Файл словаря задает по одной записи на элемент: в JSON (канонический, пригодный для машинной генерации)

    [ { "category": "person",  "text": "山田太郎" },
      { "category": "company", "regex": "アクメ(株式会社)?" } ]

или в простом построчном формате (C<category pattern>, C</.../> для regex). Каждый элемент заменяется тегом категории, таким как C<< <person id=1 /> >>; одна и та же строка всегда получает один и тот же тег, так что модель может отслеживать, кто есть кто. Неизвестные поля JSON игнорируются, поэтому генераторы (например, локальная LLM, извлекающая сущности) могут добавлять собственные аннотации. Категория C<lit> зарезервирована. Локальные cache-файлы по-прежнему хранят восстановленный обычный текст: цель concealment — только передача в API.

Словарь может быть сгенерирован внешним инструментом — например, локальной моделью, извлекающей чувствительные сущности:

    llm -m <local-model> \
        -s 'Extract sensitive entities as a JSON array of objects
            with "category" and "text" fields.' \
        < report.md > report.anon.json
    greple -Mxlate --xlate-anonymize=report.anon.json ...

UTF-8 BOM в файле допускается. Значения в построчном формате front matter могут иметь завершающий комментарий только в отдельной строке, но не после значения.

=item B<--xlate-anonymize-mark>[=I<regex>]

Собирайте записи анонимизации из inline-меток в самом документе. Отметьте первое вхождение как C<{{ person("山田太郎") }}>, и каждое вхождение строки по всему документу будет анонимизировано. Сама метка остается в исходном тексте и в переводе, поэтому документ также может обрабатываться макропроцессором в стиле Jinja2 (определите макрос C<person> для печати или редактирования имени). Пользовательский I<regex> должен содержать именованные захваты C<< (?<category>...) >> и C<< (?<text>...) >>.

Обратите внимание, что для опции с необязательным значением, такой как эта, следующий аргумент-файл будет принят за значение: пишите C<--xlate-anonymize-mark=> (с завершающим C<=>) при использовании нотации по умолчанию.

Можно настроить альтернативные нотации, например C<< --xlate-anonymize-mark='@@(?<category>[a-z][a-z0-9_]*):(?<text>[^\n]+?)@@' >> для меток в стиле C<@@person:NAME@@>, или форму HTML-комментария, которая остается невидимой в отрендеренном Markdown. Правила меток собираются для каждого документа: строка, отмеченная в одном входном файле, не скрывается в другом файле того же запуска (в отличие от значений front matter, которые накапливаются между файлами).

=item B<--xlate-template>[=I<regex>]

Обрабатывайте шаблонные выражения (по умолчанию: Jinja2 C<{{ ... }}>, C<{% ... %}>, C<{# ... #}>) как непрозрачные placeholders: инструктируйте модель копировать их без изменений и проверяйте для каждого блока, что ответ содержит ровно те же выражения, каждое — то же число раз. Их порядок может измениться, поскольку перевод правомерно переставляет их в соответствии с порядком слов целевого языка. Поврежденное выражение прерывает выполнение; кэш сохраняется контрольной точкой и замораживается, так что ничего из оплаченного не теряется.

Обратите внимание, что с опцией с необязательным значением, подобной этой, следующий файловый аргумент будет принят за значение: пишите C<--xlate-template=> (с завершающим C<=>) при использовании нотации по умолчанию.

=item B<--xlate-frontmatter>

Обрабатывайте начальный блок C<---> ... C<---> как YAML front matter: исключайте его из перевода и из контекстных срезов фазы 2, а его плоские значения C<key: value> добавляйте в правила анонимизации (категория C<var>) в качестве страховочной меры. При нескольких входных файлах собранные значения накапливаются (с уклоном в сторону сокрытия).

Всегда оставляйте пустую строку после закрывающего C<--->. При шаблоне сопоставления в стиле абзацев front matter, непосредственно переходящий в основной текст, образует один пересекающий границу блок, который исключение не может подавить (в этом случае выводится предупреждение); значения всё равно анонимизируются, но сам front matter будет отправлен на перевод.

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

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

=item B<--xlate-dryrun>

Не вызывайте API перевода; вместо этого показывайте через индикатор хода выполнения каждую полезную нагрузку ровно в том виде, в каком она была бы передана (после анонимизации и маскирования). Полезно для проверки того, что покидает машину, и для оценки стоимости запуска.

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

Смотрите результат перевода в реальном времени в выводе STDERR. Полезная нагрузка C<From> показывается в передаваемом виде, после анонимизации и маскирования.

=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 обрабатываются с помощью L<App::dozo>, который также можно использовать как самостоятельную команду. Команда C<dozo> поддерживает конфигурационный файл C<.dozorc> для постоянных настроек контейнера.

Кроме того, поскольку предоставлены makefile-файлы для различных стилей документов, перевод на другие языки возможен без специальной настройки. Используйте опцию 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>, а язык можно указать, вызывая её с префиксным аргументом.

=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, используемый устаревшими движками B<gpty>. Движок B<gpt5> на базе C<llm> также считывает эту переменную, но ключи, сохранённые с помощью C<llm keys set openai>, тоже работают.

=item GREPLE_XLATE_CACHE

Установите стратегию кэша по умолчанию (см. L</CACHE OPTIONS>).

=back

=head1 INSTALL

=head2 CPANMINUS

    $ cpanm App::Greple::xlate

=head2 TOOLS

Установите инструмент командной строки для используемого вами движка: C<llm> для движка B<gpt5>, C<deepl> для DeepL, C<gpty> для устаревших движков GPT.

L<https://llm.datasette.io/>

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

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

=head1 SEE ALSO

=head2 MODULES

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

L<App::dozo> — универсальный запускатель Docker, используемый xlate для операций с контейнерами

=head2 RELATED MODULES

=over 2

=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 RESOURCES

=over 2

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

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

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

Библиотека C<getoptlong.sh>, используемая для разбора опций в скрипте C<xlate> и L<App::dozo>.

=item * L<https://llm.datasette.io/>

Команда C<llm>, используемая движком B<gpt5> для доступа к моделям LLM.

=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

=back

=head2 ARTICLES

=over 2

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

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

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

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

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

Среда Docker для автоматического перевода с API DeepL (на японском)

=back

=head1 AUTHOR

Kazumasa Utashiro

=head1 LICENSE

Copyright © 2023-2026 Kazumasa Utashiro.

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

=cut
