簡體   English   中英

如何避免Java ResourceBundle字符串中的重復?

[英]How do I avoid repetition in Java ResourceBundle strings?

我們有很多字符串包含相同的子字符串,從關於檢查日志或如何聯系支持的句子到包含公司或產品名稱的類似品牌的字符串。 重復導致了我們自己的一些問題(主要是拼寫錯誤或復制/粘貼錯誤),但它也會導致問題,因為它增加了翻譯者必須翻譯的文本數量。

我提出的解決方案是這樣的:

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類?

我認為這是ResourceBundles設計運行方式的一個根本缺陷:引用其他鍵的鍵會自動違反DRY(不要重復自己)原則。 我解決這個問題的方法類似於你的方法:創建一個ReflectiveResourceBundle類,它允許你使用EL表示法在消息中指定資源鍵。

錯誤的方法:

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 taglib一起工作的技巧是設置一個攔截器,用我們自己的資源替換HttpServletRequest的資源。 代碼看起來像這樣:

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

有關更多詳細信息,請查看上面鏈接中的stripes.interceptor包。

如果字符串重復是本地化的,你知道某個字符串將被重復,但只在同一個項目中,共享資源包不是設計的噩夢,那么你可以考慮將字符串分解為多個鍵值部分。 將重復的部分與不重復的部分分開,並重復使用重復的部分。 例如,假設您需要顯示以下兩個字符串:

  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).

但是,您需要注意的一件事是,所有語言中的主語謂詞順序等語法規則可能並不相同。 因此,在分割句子時你需要小心一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM