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

```markdown
<custom-container>
The original and translated text are output in a markdown's custom container style.
元のテキストと翻訳されたテキストは、マークダウンのカスタムコンテナスタイルで出力されます。
</custom-container>
```

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

元のテキストと変換されたテキストは、1つの空白行で区切られて印刷されます。
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<-V>オプションを使用して、B<sdif>で競合マーカー形式を横に表示します。  

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

自動翻訳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
