3.15.1 Internationalization using MessageSource

ApplicationContext接口扩展了一个名为MessageSource的接口,因此提供了国际化(i18n)功能。 Spring还提供了接口HierarchicalMessageSource,它可以分层解析消息。这些接口一起提供了Spring对消息解析的基础。在这些接口上定义的方法包括:

  • String getMessage(String code,Object [] args,String default,Locale loc):用于从“MessageSource”中检索消息的基本方法。当找不到指定区域设置的消息时,将使用默认消息。任何传递的参数都将成为替换值,使用标准库提供的MessageFormat功能。
  • String getMessage(String code,Object [] args,Locale loc):本质上与上一个方法相同,但有一个区别:不能指定默认消息;如果找不到消息,则抛出NoSuchMessageException
  • String getMessage(MessageSourceResolvable resolvable,Locale locale):在前面的方法中使用的所有属性也被包装在一个名为MessageSourceResolvable的类中,你可以使用这个方法。

当一个ApplicationContext被加载时,它会自动搜索在上下文中定义的一个MessageSource bean。 bean必须有名称messageSource。如果找到这样的bean,则将对前面方法的所有调用委派给消息源。如果没有找到消息源,ApplicationContext会尝试找到一个包含同名bean的父对象。如果是,它使用那个bean作为MessageSource。如果ApplicationContext找不到消息的任何源,一个空的DelegatingMessageSource被实例化,以便能够接受对上面定义的方法的调用。

Spring提供了两个MessageSource实现,ResourceBundleMessageSourceStaticMessageSource。两者实现HierarchicalMessageSource为了做嵌套消息。 “StaticMessageSource”很少使用,但提供了程序化的方式来添加消息到源。 ResourceBundleMessageSource如下例所示:

<beans>
    <bean id="messageSource"
            class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>format</value>
                <value>exceptions</value>
                <value>windows</value>
            </list>
        </property>
    </bean>
</beans>

在示例中,假设你在类路径中定义了三个资源包,称为“format”,“exceptions”和“windows”。 任何解析消息的请求都将以JDK标准方式处理,通过ResourceBundles解析消息。 为了示例的目的,假设上述两个资源束文件的内容是...

# in format.properties
message=Alligators rock!
# in exceptions.properties
argument.required=The {0} argument is required.

A program to execute the MessageSource functionality is shown in the next example. Remember that all ApplicationContext implementations are also MessageSource implementations and so can be cast to the MessageSource interface. 执行MessageSource功能的程序如下例所示。 记住所有的ApplicationContext实现也是MessageSource实现,因此可以被转换到MessageSource接口。

public static void main(String[] args) {
    MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
    String message = resources.getMessage("message", null, "Default", null);
    System.out.println(message);
}

上述程序产生的输出将是...

Alligators rock!

总而言之,MessageSource在一个名为beans.xml的文件中定义,该文件存在于类路径的根目录下。 messageSource bean定义通过其basenames属性引用了大量的资源束。 在列表中传递到basenames属性的三个文件作为文件存在于类路径的根目录,分别称为format.propertiesexceptions.propertieswindows.properties

下一个示例显示传递给消息查询的参数; 这些参数将被转换为字符串并插入查找消息中的占位符。

<beans>

    <!-- this MessageSource is being used in a web application -->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="exceptions"/>
    </bean>

    <!-- lets inject the above MessageSource into this POJO -->
    <bean id="example" class="com.foo.Example">
        <property name="messages" ref="messageSource"/>
    </bean>

</beans>
public class Example {

    private MessageSource messages;

    public void setMessages(MessageSource messages) {
        this.messages = messages;
    }

    public void execute() {
        String message = this.messages.getMessage("argument.required",
            new Object [] {"userDao"}, "Required", null);
        System.out.println(message);
    }

}

调用execute()方法产生的输出将是...

The userDao argument is required.

关于国际化(i18n),Spring的各种“MessageSource”实现遵循与标准JDKResourceBundle相同的区域设置解析和回滚规则。 简而言之,继续前面定义的“messageSource”示例,如果要针对英国(en-GB)语言环境解析消息,你将创建名为format_en_GB.propertiesexceptions_en_GB.properties的文件, windows_en_GB.properties

通常,区域设置解析由应用程序的环境配置管理。 在此示例中,手动指定要解析(英国)邮件的区域设置。

# in exceptions_en_GB.properties
argument.required=Ebagum lad, the {0} argument is required, I say, required.
public static void main(final String[] args) {
    MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
    String message = resources.getMessage("argument.required",
        new Object [] {"userDao"}, "Required", Locale.UK);
    System.out.println(message);
}

运行上述程序的输出将是...

Ebagum lad, the 'userDao' argument is required, I say, required.

你还可以使用MessageSourceAware接口来获取对已定义的任何MessageSource的引用。 在创建和配置bean时,在实现MessageSourceAware接口的ApplicationContext中定义的任何bean都会注入应用程序上下文的“MessageSource”。

[Note]
作为ResourceBundleMessageSource的替代,Spring提供了一个ReloadableResourceBundleMessageSource类。 这个变体支持相同的bundle文件格式,但是比标准的基于JDK的ResourceBundleMessageSource实现更灵活。特别是,它允许从任何Spring资源位置(不仅仅是从类路径)读取文件,并支持bundle重新加载bundle属性文件 同时有效地将它们缓存在其间)。 查看ReloadableResourceBundleMessageSource javadocs可以进一步了解详细信息。

results matching ""

    No results matching ""