325N/A * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. 325N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 325N/A * This code is free software; you can redistribute it and/or modify it 325N/A * under the terms of the GNU General Public License version 2 only, as 325N/A * published by the Free Software Foundation. Oracle designates this 325N/A * particular file as subject to the "Classpath" exception as provided 325N/A * by Oracle in the LICENSE file that accompanied this code. 325N/A * This code is distributed in the hope that it will be useful, but WITHOUT 325N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 325N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 325N/A * version 2 for more details (a copy is included in the LICENSE file that 325N/A * accompanied this code). 325N/A * You should have received a copy of the GNU General Public License version 325N/A * 2 along with this work; if not, write to the Free Software Foundation, 325N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 325N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 325N/A * or visit www.oracle.com if you need additional information or have any 325N/A * This class provides support for multi-language string lookup, as needed 325N/A * to localize messages from applications supporting multiple languages 325N/A * at the same time. One class of such applications is network services, 325N/A * such as HTTP servers, which talk to clients who may not be from the 325N/A * same locale as the server. This class supports a form of negotiation 325N/A * for the language used in presenting a message from some package, where 325N/A * both user (client) preferences and application (server) support are 325N/A * accounted for when choosing locales and formatting messages. 325N/A * <P> Each package should have a singleton package-private message catalog 325N/A * class. This ensures that the correct class loader will always be used to 325N/A * access message resources, and minimizes use of memory: <PRE> 325N/A * package <em>some.package</em>; 325N/A * // "foo" might be public 325N/A * static final Catalog messages = new Catalog (); 325N/A * static final class Catalog extends MessageCatalog { 325N/A * Catalog () { super (Catalog.class); } 325N/A * <P> Messages for a known client could be generated using code 325N/A * something like this: <PRE> 325N/A * String clientLanguages []; 325N/A * String clientMessage; 325N/A * // client languages will probably be provided by client, 325N/A * // e.g. by an HTTP/1.1 "Accept-Language" header. 325N/A * clientLanguages = new String [] { "en-ca", "fr-ca", "ja", "zh" }; 325N/A * clientLocale = foo.messages.chooseLocale (clientLanguages); 325N/A * clientMessage = foo.messages.getMessage (clientLocale, 325N/A * new Object [] { new Integer (numberOfFiles) } 325N/A * <P> At this time, this class does not include functionality permitting 325N/A * messages to be passed around and localized after-the-fact. The consequence 325N/A * of this is that the locale for messages must be passed down through layers 325N/A * which have no normal reason to support such passdown, or else the system 325N/A * default locale must be used instead of the one the client needs. 325N/A * <P> <hr> The following guidelines should be used when constructiong 325N/A * multi-language applications: <OL> 325N/A * <LI> Always use <a href=#chooseLocale>chooseLocale</a> to select the 325N/A * locale you pass to your <code>getMessage</code> call. This lets your 325N/A * applications use IETF standard locale names, and avoids needless 325N/A * use of system defaults. 325N/A * <LI> The localized messages for a given package should always go in 325N/A * a separate <em>resources</em> sub-package. There are security 325N/A * implications; see below. 325N/A * <LI> Make sure that a language name is included in each bundle name, 325N/A * so that the developer's locale will not be inadvertently used. That 325N/A * such defaults rather than giving software a chance to choose a more 325N/A * appropriate language for its messages. Your message bundles should 325N/A * English, language) or <em>Messages_ja.class</em> ("ja" indicates the 325N/A * <LI> Only use property files for messages in languages which can 325N/A * be limited to the ISO Latin/1 (8859-1) characters supported by the 325N/A * property file format. (This is mostly Western European languages.) 325N/A * Otherwise, subclass ResourceBundle to provide your messages; it is 325N/A * simplest to subclass <code>java.util.ListResourceBundle</code>. 325N/A * <LI> Never use another package's message catalog or resource bundles. 325N/A * It should not be possible for a change internal to one package (such 325N/A * as eliminating or improving messages) to break another package. 325N/A * <P> The "resources" sub-package can be treated separately from the 325N/A * package with which it is associated. That main package may be sealed 325N/A * and possibly signed, preventing other software from adding classes to 325N/A * the package which would be able to access methods and data which are 325N/A * not designed to be publicly accessible. On the other hand, resources 325N/A * such as localized messages are often provided after initial product 325N/A * shipment, without a full release cycle for the product. Such files 325N/A * (text and class files) need to be added to some package. Since they 325N/A * should not be added to the main package, the "resources" subpackage is 325N/A * used without risking the security or integrity of that main package 325N/A * as distributed in its JAR file. 325N/A * @author David Brownell 325N/A * @version 1.1, 00/08/05 325N/A * @see java.util.Locale 325N/A * @see java.util.ListResourceBundle 325N/A * @see java.text.MessageFormat 325N/A// leave this as "abstract" -- each package needs its own subclass, 325N/A// else it's not always going to be using the right class loader. 325N/A * Create a message catalog for use by classes in the same package 325N/A * as the specified class. This uses <em>Messages</em> resource 325N/A * bundles in the <em>resources</em> sub-package of class passed as 325N/A * @param packageMember Class whose package has localized messages 325N/A * Create a message catalog for use by classes in the same package 325N/A * as the specified class. This uses the specified resource 325N/A * bundle name in the <em>resources</em> sub-package of class passed 325N/A * as a parameter; for example, <em>resources.Messages</em>. 325N/A * @param packageMember Class whose package has localized messages 325N/A * @param bundle Name of a group of resource bundles 325N/A else // "some.package.ClassName" 325N/A * Get a message localized to the specified locale, using the message ID 325N/A * and package name if no message is available. The locale is normally 325N/A * that of the client of a service, chosen with knowledge that both the 325N/A * client and this server support that locale. There are two error 325N/A * cases: first, when the specified locale is unsupported or null, the 325N/A * default locale is used if possible; second, when no bundle supports 325N/A * that locale, the message ID and package name are used. 325N/A * @param locale The locale of the message to use. If this is null, 325N/A * the default locale will be used. 325N/A * @param messageId The ID of the message to use. 325N/A * @return The message, localized as described above. 325N/A // cope with unsupported locale... 325N/A * Format a message localized to the specified locale, using the message 325N/A * ID with its package name if none is available. The locale is normally 325N/A * the client of a service, chosen with knowledge that both the client 325N/A * server support that locale. There are two error cases: first, if the 325N/A * specified locale is unsupported or null, the default locale is used if 325N/A * possible; second, when no bundle supports that locale, the message ID 325N/A * and package name are used. 325N/A * @param locale The locale of the message to use. If this is null, 325N/A * the default locale will be used. 325N/A * @param messageId The ID of the message format to use. 325N/A * @param parameters Used when formatting the message. Objects in 325N/A * this list are turned to strings if they are not Strings, Numbers, 325N/A * or Dates (that is, if MessageFormat would treat them as errors). 325N/A * @return The message, localized as described above. 325N/A * @see java.text.MessageFormat 325N/A // since most messages won't be tested (sigh), be friendly to 325N/A // the inevitable developer errors of passing random data types 325N/A // to the message formatting code. 325N/A // similarly, cope with unsupported locale... 325N/A // get the appropriately localized MessageFormat object 325N/A retval = packagePrefix (messageId); 325N/A for (int i = 0; i < parameters.length; i++) { 325N/A retval += parameters [i]; 325N/A // return the formatted message 325N/A * Chooses a client locale to use, using the first language specified in 325N/A * the list that is supported by this catalog. If none of the specified 325N/A * languages is supported, a null value is returned. Such a list of 325N/A * languages might be provided in an HTTP/1.1 "Accept-Language" header 325N/A * field, or through some other content negotiation mechanism. 325N/A * <P> The language specifiers recognized are RFC 1766 style ("fr" for 325N/A * all French, "fr-ca" for Canadian French), although only the strict 325N/A * ISO subset (two letter language and country specifiers) is currently 325N/A * supported. Java-style locale strings ("fr_CA") are also supported. 325N/A * @param languages Array of language specifiers, ordered with the most 325N/A * preferable one at the front. For example, "en-ca" then "fr-ca", 325N/A * @return The most preferable supported locale, or null. 325N/A * @see java.util.Locale 325N/A // Canonicalizes the RFC 1766 style language strings ("en-in") to 325N/A // match standard Java usage ("en_IN"), removing strings that don't 325N/A // use two character ISO language and country codes. Avoids all 325N/A // memory allocations possible, so that if the strings passed in are 325N/A // just lowercase ISO codes (a common case) the input is returned. 325N/A // no RFC1766 extensions allowed; "zh" and "zh-tw" (etc) are OK 325N/A // as are regular locale names with no variant ("de_CH"). 325N/A // language code ... if already lowercase, we change nothing 325N/A // language_country ... fixup case, force "_" 325N/A // purge any shadows of deleted RFC1766 extended language codes 325N/A // Returns a locale object supporting the specified locale, using 325N/A // a small cache to speed up some common languages and reduce the 325N/A // needless allocation of memory. 325N/A // Special case the builtin JDK languages 325N/A // JDK also has constants for countries: en_GB, en_US, en_CA, 325N/A // fr_FR, fr_CA, de_DE, ja_JP, ko_KR. We don't use those. 325N/A // cache for isLanguageSupported(), below ... key is a language 325N/A // or locale name, value is a Boolean 325N/A * Returns true iff the specified locale has explicit language support. 325N/A * For example, the traditional Chinese locale "zh_TW" has such support 325N/A * if there are message bundles suffixed with either "zh_TW" or "zh". 325N/A * <P> This method is used to bypass part of the search path mechanism 325N/A * of the <code>ResourceBundle</code> class, specifically the parts which 325N/A * force use of default locales and bundles. Such bypassing is required 325N/A * in order to enable use of a client's preferred languages. Following 325N/A * the above example, if a client prefers "zh_TW" but can also accept 325N/A * "ja", this method would be used to detect that there are no "zh_TW" 325N/A * resource bundles and hence that "ja" messages should be used. This 325N/A * bypasses the ResourceBundle mechanism which will return messages in 325N/A * some other locale (picking some hard-to-anticipate default) instead 325N/A * of reporting an error and letting the client choose another locale. 325N/A * @param localeName A standard Java locale name, using two character 325N/A * language codes optionally suffixed by country codes. 325N/A * @return True iff the language of that locale is supported. 325N/A * @see java.util.Locale 325N/A // Use previous results if possible. We expect that the codebase 325N/A // is immutable, so we never worry about changing the cache. 325N/A // Try "language_country_variant", then "language_country", 325N/A // then finally "language" ... assuming the longest locale name 325N/A // is passed. If not, we'll try fewer options. 325N/A // ... then property files (only for ISO Latin/1 messages) 325N/A // If we got this far, we failed. Remember for later.