=encoding utf-8

=head1 NAME

App::Greple::xlate - grepleの翻訳サポートモジュール  

=head1 SYNOPSIS

    greple -Mxlate -e ENGINE --xlate pattern target-file

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

=head1 VERSION

Version 0.9908

=head1 DESCRIPTION

B<Greple> B<xlate> モジュールは、目的のテキストブロックを見つけて、翻訳されたテキストに置き換えます。現在、DeepL (F<deepl.pm>) と ChatGPT (F<gpt3.pm>) モジュールがバックエンドエンジンとして実装されています。gpt-4 および gpt-4o の実験的サポートも含まれています。

Perlの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).+>パターンを指定するためのショートカットです。  

コンフリクトマーカーフォーマットのデータは、C<sdif>コマンドとC<-V>オプションを使用して、サイドバイサイドスタイルで表示できます。文字列ごとに比較することは意味がないため、C<--no-cdif>オプションが推奨されます。テキストに色を付ける必要がない場合は、C<--no-textcolor>（またはC<--no-tc>）を指定します。  

    sdif -V --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番目）および偶数番号のパターンに対してのみ実行されます。したがって、次のように2つのパターンが指定されている場合、最初のパターンに一致するテキストは正規化後に処理され、2番目のパターンに一致するテキストには正規化プロセスは実行されません。  

    greple -Mxlate -E normalized -E not-normalized

したがって、複数の行を1行に結合して処理するテキストには最初のパターンを使用し、事前にフォーマットされたテキストには2番目のパターンを使用します。最初のパターンに一致するテキストがない場合は、C<(?!)>のように何も一致しないパターンを使用してください。

=head1 MASKING

時折、翻訳したくないテキストの部分があります。例えば、マークダウンファイルのタグなどです。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<--color=never> オプションを使用して B<--xlate-color> オプションを呼び出します。  

B<--xlate-fold> オプションを使用すると、変換されたテキストは指定された幅で折りたたまれます。デフォルトの幅は70で、B<--xlate-fold-width> オプションで設定できます。ランイン操作のために4列が予約されているため、各行は最大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-turbo

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

B<gpt-4o>のインターフェースは不安定で、現在正しく動作することは保証できません。

=back

=item B<--xlate-labor>

=item B<--xlabor>

翻訳エンジンを呼び出す代わりに、あなたが作業することが期待されています。翻訳するテキストを準備した後、それらはクリップボードにコピーされます。あなたはそれらをフォームに貼り付け、結果をクリップボードにコピーし、リターンを押すことが期待されています。  

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

ターゲット言語を指定します。B<DeepL> エンジンを使用している場合、C<deepl languages> コマンドで利用可能な言語を取得できます。  

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

オリジナルと翻訳されたテキストは、マークダウンのカスタムコンテナスタイルで出力されます。

    ::::::: 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に一度に送信するテキストの最大長を指定します。デフォルト値は、無料のDeepLアカウントサービスに設定されています：API（B<--xlate>）用に128K、クリップボードインターフェース（B<--xlate-labor>）用に5000です。Proサービスを使用している場合、これらの値を変更できるかもしれません。  

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

APIに一度に送信する最大行数を指定してください。

この値を1に設定すると、一度に1行ずつ翻訳します。このオプションはC<--xlate-maxlen>オプションよりも優先されます。

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

ファイル全体のテキストを対象領域として設定します。

=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>コマンドはDocker環境と連携して動作するため、手元に何もインストールされていなくても、Dockerが利用可能であれば使用できます。C<-D>またはC<-C>オプションを使用してください。  

また、さまざまな文書スタイルのためのMakefileが提供されているため、特別な指定なしに他の言語への翻訳が可能です。C<-M>オプションを使用してください。  

DockerとC<make>オプションを組み合わせて、Docker環境でC<make>を実行できます。

C<xlate -C>のように実行すると、現在の作業中のgitリポジトリがマウントされたシェルが起動します。

詳細についてはL</SEE ALSO>セクションの日本語の記事をお読みください。  

=head1 EMACS

リポジトリに含まれるF<xlate.el>ファイルをロードして、EmacsエディタからC<xlate>コマンドを使用します。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認証キー。  

=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::gpt3>  

=over 2

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

Dockerコンテナイメージ。

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

DeepL APIを使用して必要な部分のみを翻訳および置換するGrepleモジュール（日本語）  

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

DeepL APIモジュールを使用して15言語で文書を生成する（日本語）  

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

DeepL APIを使用した自動翻訳Docker環境（日本語）  

=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
