Correct java.util.ResourceBundle Organization

让人想犯罪 __ 提交于 2019-12-31 07:10:34

问题


I have an internationalized project with many modules. Each module has its own set of bundles:

- database-module
    + com_naugler_project_database.properties
    + com_naugler_project_database_fr.properties
- mapping-module
    + com_naugler_project_mapping.properties
    + com_naugler_project_mapping_fr.properties

However, many of the internationalized terms are redundant (such as 'OK' or 'Cancel') and I would like have these terms in one place for easier maintenance and development.

I found this helpful explanation of ResourceBundle inheritance, but it appears as though a (not?) common ancestor would not be internationalized properly because:

- common-module
    + com_naugler_project.properties
    + com_naugler_project_fr.properties          <-- this is not an ancestor
- database-module
    + com_naugler_project_database.properties
    + com_naugler_project_database_fr.properties <-- of this

Am I way off base with my bundle organization? What is the right way to provide a common internationalized ancestor?


回答1:


What you want seems to be the hierarchy of Resources, that is, you probably want one class to derive from over (or being composed of some specific part and some common part).

Basically, ResourceBundle was not designed for it, and you are on your own.

But you want some advice, I suppose.

  • Make sure that common terms are really common. That is things like "OK", "Cancel", "Next >", "< Previous", "Open", "File", etc. will have common translations in their context. I mean it is fairly safe to translate such standard items only once, but if you want to use them in different context, you still need another entry. Why? Because "Open" button translation would be different than "Open" dialog title translation in quite a few languages.

  • Move all the .properties files to one place (for example a directory called "resources"). Of course module-specific files should be separated to different subdirectories...

    • Create a resource factory that will return an instance of the ResourceBundle class (or your own Facade - this approach will actually let you share some common bundle).
  • The good practice for large applications is to create some Language Pack, that is to separate language resources to their own directories (i.e. /resources/en, /resources/fr, /resources/zh-Hans). The problem with this approach, however would be the fact that you would need to implement resource fallback by yourself (with the aid of an article you mention in the question, the hierarchy is actually resource loading hierarchy). That means some special cases like falling back from language tag "nb" to "no" but not falling back from "nn"; falling back from "zh-CN" and "zh-SG" to "zh-Hans" and then to "zh" but falling back from "zh-HK" and "zh-TW" and "zh-MO" to "zh-Hant" and then to your default language, not falling from "pt-BR" to "pt" (falling back to default language instead).

Seems like a lot of work? Well, but the maintenance work afterwards would be minimal.

One thing might come in handy PropertyResourceBundle have two constructors that will let you load whatever properties file you want, namely: PropertyResourceBundle(InputStream stream) and PropertyResourceBundle(Reader reader). Honestly, in large projects standard ResourceBundle mechanism has too many limitations, so you really need your own resource access layer...




回答2:


As Paweł Dyda indicated, resource bundles on their own do not support class hierarchy resolution. However the Rincl project, which my company just released, should do just what you're looking for---and handle UTF-8 .properties files and XML properties files as well. It even does message formatting for you on the fly.

As explained in the in the Rincl quick start, you can simply implement Rincled and then call getResources(); Rincl will load your resource bundles even if declared in a parent class or interface:

public class MyClass extends BaseClass implements Rincled {
  …

    final String userName = "Jane Doe";
    //Retrieve the formatted user label based upon the current locale.
    //en-US: "Settings for user Jane Doe."
    //pt-BR: "Definições para usuário Jane Doe."
    final String userLabel = getResources().getString("user-label", userName);
  …

Rincl is available at http://rincl.io/ with an intro and even a full lesson on Java internationalization. There are many new features coming up, but the latest version should already work for you. Let me know if you have any questions or problems.



来源:https://stackoverflow.com/questions/11416375/correct-java-util-resourcebundle-organization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!