14

ログの確認やサポートへの連絡方法に関する文章から、会社名や製品名を含むブランディングのような文字列まで、同じ部分文字列を含む文字列がたくさんありました。この繰り返しは、私たち自身にいくつかの問題 (主にタイプミスやコピー/貼り付けのエラー) を引き起こしていましたが、翻訳者が翻訳しなければならないテキストの量が増えるという問題も引き起こしました。

私が思いついた解決策は次のようなものでした:

public class ExpandingResourceBundleControl extends ResourceBundle.Control {
  public static final ResourceBundle.Control EXPANDING =
    new ExpandingResourceBundleControl();

  private ExpandingResourceBundleControl() { }

  @Override
  public ResourceBundle newBundle(String baseName, Locale locale, String format,
                                  ClassLoader loader, boolean reload)
    throws IllegalAccessException, InstantiationException, IOException {

      ResourceBundle inner = super.newBundle(baseName, locale, format, loader, reload);
      return inner == null ? null : new ExpandingResourceBundle(inner, loader);
  }
}

ExpandingResourceBundle実際のリソース バンドルに委譲しますが、{{this.kind.of.thing}} の変換を実行してリソース内のキーを検索します。

これらのいずれかを取得するたびに、次の場所に移動する必要があります。

ResourceBundle.getBundle("com/acme/app/Bundle", EXPANDING);

そして、これはうまくいきます - しばらくの間。

最終的に起こることは、いくつかの新しいコード (私たちの場合、Matisse から吐き出された自動生成されたコード) が、カスタム コントロールを指定せずに同じリソース バンドルを検索することです。これは、単純な単体テストを記述して呼び出す場合と、それを呼び出さない場合の再現性がないように見えますが、実際にアプリケーションを実行すると発生します。どういうわけか、内部のキャッシュResourceBundleが適切な値を排出し、壊れた値に置き換えます。理由はまだわかりません.Sunのjarファイルはデバッグ情報なしでコンパイルされているため、デバッグは雑用です.

私の質問:

  1. 私が気付いていないかもしれないデフォルトの ResourceBundle.Control をグローバルに設定する方法はありますか? それはすべてをかなりエレガントに解決します。

  2. おそらく ResourceBundle クラスをまったく改ざんすることなく、この種のものをエレガントに処理する他の方法はありますか?

4

2 に答える 2

6

これは、ResourceBundle が機能するように設計されている方法の根本的な欠陥だと思います。他のキーを参照するキーは、自動的に DRY (自分自身を繰り返さない) 原則に違反します。これを回避する方法は、あなたの方法と似ていました。 EL 表記を使用して、メッセージでリソース キーを指定できる ReflectiveResourceBundle クラスを作成します。

間違った方法:

my.name.first=Bob
my.name.last=Smith
my.name.full=Bob Smith

正しい方法:

my.name.first=Bob
my.name.last=Smith
my.name.full=${my.name.first} ${my.name.last}

コードを GitHub にアップロードしたので、誰でもダウンロードできます。さらに、Stripes Framework ( http://www.stripesframework.org/ ) を使用しているすべてのユーザー向けにサンプル コードを追加して、すぐに使い始めることができるようにしました。

これを標準の JSTL fmt taglibs で動作させる秘訣は、HttpServletRequest のリソースを独自のものに置き換えるインターセプターをセットアップすることでした。コードは次のようになります。

ResourceBundle bundle = MyStaticResourceHoldingTheBundle.getBundle();
Config.set(request, Config.FMT_LOCALIZATION_CONTEXT, new LocalizationContext(bundle, locale));

詳細については、上記のリンクにある stripes.interceptor パッケージを参照してください。

于 2010-04-11T17:37:03.217 に答える
0

特定の文字列が繰り返されることがわかっているという意味で文字列の繰り返しがローカライズされているが、リソースバンドルの共有が設計上の悪夢ではないように同じプロジェクト内でのみ行われる場合は、文字列を複数のKey-Value部分に分割することを検討できます。繰り返される部分と繰り返されない部分を分離し、繰り返される部分を再利用します。たとえば、表示する必要のある次の2つの文字列があるとします。

  1. 「アカビタイサンショウウオはオーストラリア原産の小さなスズメ目鳥です。」
  2. 「アカビタイサンショウウオは、大陸の多くの乾燥地域で見られます。」

リソースバンドルは次のようになります。

robin.name=The Red-capped Robin
robin.native=is a small passerine bird native to Australia.
robin.region=is found in dryer regions across much of the continent.

次に、必要な場所で必要な部品を組み合わせますbundle.getString("robin.name")+bundle.getString(robin.native).

ただし、注意が必要なことの1つは、主語の述語の順序などの文法規則がすべての言語で同じではない可能性があることです。したがって、文を分割するときは少し注意する必要があります。

于 2010-04-09T06:50:24.043 に答える