/* * ModeShape (http://www.modeshape.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * <p> * A simple framework for defining internationalized strings and obtaining the localized forms. * </p> * <p> * The {@link org.modeshape.common.i18n.I18n} class represents an internationalized string with the ability to obtain the localized message * given a {@link java.util.Locale Locale} or, if not supplied, the {@link java.util.Locale#getDefault() default locale}. * </p> * <h3>Using the I18n objects</h3> * <p> * To use, simply create a class with a public static non-final I18n instance for each of the internationalized strings. * The name of the field is used as the message key in the localization files, so use a name that is meaningful * within the codebase. The class should also have a static initializer to populate the I18n instances. For example, * here is a class that defines three internationalized strings: * <pre> * public final class MyAppI18n { * * public static I18n errorImportingContent; * public static I18n unableToFindSourceWithName; * public static I18n executorIsShutdown; * * static { * try { * I18n.initialize(MyAppI18n.class); * } catch (final Exception err) { * System.err.println(err); * } * } * } * </pre> * You can have as many of these classes in your application or library, so you have the flexibility to organize * your I18n objects to suit your needs. You could, for example, define one of these classes in each of your * applications modules, or you could even define one in each package. * </p> * <h3>Localization</h3> * <p> * The localized strings are loaded from property files based upon the name of the locale and the class containing * the I18n message objects (the one with the static intializer): * <pre> * <package>.<className>_<localeName>.properties * </pre> * For example, here are the names of some localization bundles for the "<code>org.example.MyAppI18n</code>" class: * <ul> * <li>"<code>org.example.MyAppI18n.properties_en</code>" is the bundle containing the English strings</li> * <li>"<code>org.example.MyAppI18n.properties_fr</code>" is the bundle containing the French strings</li> * <li>"<code>org.example.MyAppI18n.properties</code>" is the bundle used if no locale is specified</li> * </ul> * </p> * <p> * Each of these files is a simple properties file, where the property names (the keys) must match the I18n field names, * and the property values are the localized message. So, given the "<code>org.example.MyAppI18n</code>" class above, * here is an example of a localization bundle: * <pre> * errorImportingContent = Error importing {0} content from {1} * unableToFindSourceWithName = Unable to find a source named "{0}" * executorIsShutdown = The executor is already shutdown * </pre> * Note that each of the localized messages may contain number parameters that are replaced with actual values * supplied to the {@link org.modeshape.common.i18n.I18n#text(Object...)} or {@link org.modeshape.common.i18n.I18n#text(java.util.Locale, Object...)} methods. * </p> * <h3>Localization Repositories</h3> * <p> * By default, the localization bundles must be found on the classpath. This makes sense for most applications that * include their localization bundles with their JARs or make them available on the classpath. You can always specify * the classloader to use, however. * </p> * <h3>Testing the localizations</h3> * <p> * The framework provides several utility methods to obtain any problems the were found while loading the localized * messages. * <ul> * <li>{@link org.modeshape.common.i18n.I18n#getLocalizationProblemLocales(Class)} returns the set of Locale objects for which there were problems;</li> * <li>{@link org.modeshape.common.i18n.I18n#getLocalizationProblems(Class)} returns the set of problems found while loading all of the locales;</li> * <li>{@link org.modeshape.common.i18n.I18n#getLocalizationProblems(Class,java.util.Locale)} returns the set of problems found while loading the supplied locale</li> * </ul> * Problems include any missing messages in a localization file, extra messages in a localization file, or inability * to access the localization file. * </p> * <p> * These utility methods can be used in unit tests to ensure that all locale message bundles were loaded successfully. * In fact, this framework provides an abstract unit test that does exactly this. To use simply create a concrete * subclass with a no-arg constructor that calls the abstract class's constructor with the {@link java.lang.Class} containing * the {@link org.modeshape.common.i18n.I18n} objects: * <pre> * public class MyAppI18nTest extends AbstractI18nTest { * public MyAppI18nTest() { * super(MyAppI18n.class); * } * } * </pre> * </p> */ package org.modeshape.common.i18n;