Understanding the basis of Java I18n

来源:互联网 发布:牛牛668网络 编辑:程序博客网 时间:2024/05/19 21:58

                                             Understanding the basis of Java I18n

    Locale Abstract

    A Locale object is an identifier for a region/location. It has three attributes : language(valid ISO Language Code, lower-case, two-letter, for example 'en'), country(valid ISO Country Code, upper-case, two-letter, for example 'US') and variant(vendor or browser specific code, for example 'WIN' indicating Windows). The locale representation return by the locale object's toString method may be, for example, en_US_WIN, which will be used as part of a resource bundle name to identify the bundle's locale(discussed later).

    An operation that requires a Locale to perform its task is called locale-sensitive and uses the Locale to tailor information for the user.

    ResourceBundle Abstract

    A Resource Bundle object is a container of key/value pairs, in which, key is a string that uniquely identifies a pair(this is not enforced, for you can get an array of values using a key, but this is convention), and value is a locale-specific object.
   
    You can write program code that is largely independent of the user's locale, isolating most, if not all, of the locale-specific information in resource bundles.

    You typically will not treat a resouce bundle as 'lonely', but as a member of a family. The family of resource bundles share a common base name, which is also the name of the default locale. But their names also have additional components that identify their locales. For example, the base name of a family of resource bundles might be "MyResources". The name of the default locale is then "MyResources". The family can then provide as many locale-specific members as needed, for example a German one named "MyResources_de". The default locale will be used as the bundle of last resort if a specific locale is not supported.

    Each resource bundle in a family contains the same set of keys referring to different sets of locale-specific values. For example, both "MyResources" and "MyResources_de" may have a key "CancelKey" that's used on a button for canceling operations. In "MyResources" the value may be "Cancel" and in "MyResources_de" the value may be "Abbrechen". 

    Resource bundle locating manner

    The basic method for you to locate a resource bundle is ResourceBundle.getBundle(baseName, locale, classLoader). The strategy this method uses for locating bundle is this :
    First, a sequence of candidate resource bundle names are generated from the baseName, specified locale(language1, country1, variant1) and default locale(Locale.getDefault(), language2, country2, variant2) of current jvm instance :
        baseName + "_" + language1 + "_" + country1 + "_" + variant1
        baseName + "_" + language1 + "_" + country1
        baseName + "_" + language1
        baseName + "_" + language2 + "_" + country2 + "_" + variant2
        baseName + "_" + language2 + "_" + country2
        baseName + "_" + language2
        baseName
    Candidate bundle name where the final component is empty string will be omitted.
    Second, getBundle method iterates over the candidate bundle names and tries to find one bundle that can be instantiated. For eache candidate bundle name, getBundle uses the specified classLoader, tries first to load a class and create an instance of it and uses the instance as the result resource bundle. If not applicable, getBundle then tries to load a '.properties' file and create PropertyResourceBundle instance from its contents. If successful, this instance becomes the result resource bundle.
    Third, getBundle will instantiate the parent chain of the result resource bundle. It iterates over the available candidate bundle names by successively removing variant, country, and language(each time with the receding '_') from the name of the result resource bundle. For each available name, getBundle perform actions in the second step to try to instantiate a new bundle instance and call setParent method of previously instantiated bundle with it.

    Notice that we should use a fully qualified class name as the baseName argument.

    Example

    The following class and property files are provided: MyResources.class, MyResources_fr_CH.properties, MyResources_fr_CH.class, MyResources_fr.properties, MyResources_en.properties, MyResources_es_ES.class. The contents of all files are valid (that is, public non-abstract subclasses of ResourceBundle for the ".class" files, syntactically correct ".properties" files). The default locale is Locale("en", "GB").
    Calling getBundle with the shown locale argument values instantiates resource bundles from the following sources:
    Locale("fr", "CH"): result MyResources_fr_CH.class, parent MyResources_fr.properties, parent MyResources.class
    Locale("fr", "FR"): result MyResources_fr.properties, parent MyResources.class
    Locale("de", "DE"): result MyResources_en.properties, parent MyResources.class
    Locale("en", "US"): result MyResources_en.properties, parent MyResources.class
    Locale("es", "ES"): result MyResources_es_ES.class, parent MyResources.class
    The file MyResources_fr_CH.properties is never used because it is hidden by MyResources_fr_CH.class.

    Useful Pattern

    You can deploy and use a hierarchy of families of ResourceBundles :
    family Common : Common.properties, Common_zh_CN.properties
    family ExceptionMessages : ExceptionMessages.properties, ExceptionMessages_zh_CN.properties
    family InfoMessages : InfoMessages.properties, InfoMessage_zh_CN.properties
    If you would like to have the common resource of family ExceptionMessages and family InfoMessages shared in the family Common, a ResourceBundleFacade class may be a good choice :

    public class ResourceBundleFacade {
        private static ResourceBundle commonrb = ResourceBundle.getBundle("yourpackage.Common", locale, variant);
        private static ResourceBundle exceptionrb = ResourceBundle.getBundle("yourpackage.ExceptionMessages", locale, variant);
        private static ResourceBundle inforb = ResourceBundle.getBundle("yourpackage.InfoMessages", locale, variant);
       
        ...

        public static String getExceptionMessage(String key) {
            String message = exceptionrb.getString(key);
            if (message == null) {
                return commonrb.getString(key);
            } else {
                return message;
            }
        }

        ...
    }

原创粉丝点击