4

私は現在、非常に大規模な Perl/ Mason Web アプリケーションの国際化に取り組んでいます。このアプリケーションは 20 年近く経ち、比較的古風な Perl スタイルで書かれています。Moose や別のオブジェクト指向モジュールは使用しません。現在、Locale::Maketext::Gettextを使用してメッセージを検索し、GNU Gettext カタログ ファイルを使用することを計画しています。

bigass コードベースから文字列を抽出するためのツールをいくつか開発しようとしています。現在、私が持っているのは、文字列リテラルを探してソースを解析し、ユーザーにコンテキストと文字列を翻訳用にマークする必要があるかどうかを尋ね、そうであればマークする比較的単純な Perl スクリプトだけです。

マークする必要のある文字列と、無視できる文字列に関しては、あまりにも多くのノイズがあります。ソース内の多くの文字列は、ハッシュ キーや次のような型比較など、ユーザー向けではありません。

if (ref($db_obj) eq 'A::Type::Of::Db::Module')

提案された各文字列にいくつかのヒューリスティックを適用して、すぐに無視できるかどうかを確認します (たとえば、ハッシュ ルックアップに使用される文字列は無視します。これは、コードベースでは 99% の時間、これらはユーザーに面していないためです)。しかし、それにもかかわらず、私のプログラムが表示する文字列の約 90% は、私が気にしないものです。

文字列抽出のタスクを自動化するのに役立つより良い方法はありますか (つまり、ソースからすべての文字列リテラルを取得するよりもインテリジェントなもの)? Perl と Mason の両方のソースを処理できる商用プログラムはありますか?

また、私は優れたツールについて (かなりばかげた) アイデアを思いつきました。そのワークフローを以下に示します。このようなものを実装する努力をする価値があるでしょうか (おそらく作業の 80% を非常に迅速に処理できます)、それとも面倒で煩わしい手動の文字列抽出プロセスに従うべきでしょうか?

  1. ソースからすべての文字列リテラルを抽出し、それを Gettext PO ファイルに入れることから始めます。
  2. 次に、Mason プラグインを作成して、アプリケーションによって提供される各ページの HTML を解析し、ユーザーが見ている文字列に注目することを目標にします。
  3. アプリケーションを徹底的に使用し、すべてのユースケースをカバーして、ユーザー向けの文字列のストアを構築してください。
  4. ユーザーが見たこの文字列のストアを考慮して、カタログ ファイル内の文字列に対してあいまい一致を実行し、一致するカタログ エントリを UI から追跡します。
  5. 最後に、カタログ ファイル内で一致しなかったものはユーザー向けではない可能性が高いため、それらをカタログから削除します。
4

2 に答える 2

4

私が知っている Perl ツールで、国際化が必要な文字列とそうでない文字列をインテリジェントに抽出するものはありません。それらを書くときにコードでそれらをマークすることになっていますが、あなたが言ったように、それは行われていません。

PPIを使用して、文字列抽出をインテリジェントに行うことができます。

#!/usr/bin/env perl

use strict;
use warnings;

use Carp;
use PPI;

my $doc = PPI::Document->new(shift);

# See PPI::Node for docs on find
my $strings = $doc->find(sub {
    my($top, $element) = @_;
    print ref $element, "\n";

    # Look for any quoted string or here doc.
    # Does not pick up unquoted hash keys.
    return $element->isa("PPI::Token::Quote")   ||
           $element->isa("PPI::Token::HereDoc");
});

# Display the content and location.
for my $string (@$strings) {
    my($line, $row, $col) = @{ $string->location };
    print  "Found string at line $line starting at character $col.\n";
    printf "String content: '%s'\n", string_content($string);
}


# *sigh* PPI::Token::HereDoc doesn't have a string method
sub string_content {
    my $string = shift;
    return $string->isa("PPI::Token::Quote")   ? $string->string :
           $string->isa("PPI::Token::HereDoc") ? $string->heredoc :
           croak "$string is neither a here-doc nor a quote";
}

文字列を囲むトークンをより高度に調べて、それが重要なものかどうかを判断できます。詳細については、 PPI::ElementおよびPPI::Nodeを参照してください。または、文字列の内容を調べて、それが重要かどうかを判断できます。

「重要」はあなた次第なので、これ以上先に進むことはできません。

于 2011-10-04T20:21:55.180 に答える
0

当社のソース コード検索エンジンは、通常、認識している言語の語彙素から構築されたインデックスを使用して、大規模なコード ベースを効率的に検索するために使用されます。その言語のリストは、Java、C#、COBOL、そして ... Perl など、非常に幅広いものです。語彙素エクストラクタは言語に正確です (精度が基本となる、言語に依存しないプログラム変換システムであるDMS Software Reengineering Toolkitから「盗まれた」ため)。

インデックス付きのコード ベースがあれば、クエリを入力して、言語固有の空白に関係なく、語彙素の任意のシーケンスを見つけることができます。そのようなクエリのヒットとその場所をログに記録できます。

非常に短いクエリ:

S

を検索エンジンに渡すと、文字列として分類されるすべての字句要素が検出されます (キーワード、変数名、コメントはすべて無視されます。文字列だけです!)。(通常、「Hello」で終わる文字列を検索するために S=*Hello など、正規表現の制約を使用してより複雑なクエリを作成します)

ここでの関連性は、ソース コード検索エンジンが Perl の文字列の字句構文に関する正確な知識を持っていることです (具体的には、補間された文字列の要素とすべての風変わりなエスケープ シーケンスを含みます)。したがって、上記のクエリは Perl のすべての文字列を検索します。ログオンすると、すべての文字列とその場所がログに記録されます。

このスタントは実際には、検索エンジンが理解できるどの言語でも機能するため、このような国際化タスクで文字列を抽出する一般的な方法です。

于 2011-10-08T17:10:06.910 に答える