Spring 国际化

部署运行你感兴趣的模型镜像

覆写ResourceBundleMessage. 

Spring留接口,其设计给力啊,很容易扩展。

package org.frame.base.message;

import java.io.UnsupportedEncodingException;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.context.support.ResourceBundleMessageSource;

/**
 * 
 * 扩展Spring的resourceBundleMessageSource
 * 使其支持中文,因为properties文件天生不支持中文,如果要其支持,需要转码,麻烦!
 * 
 * 于是扩展一下,实现自动转码
 */
public class ResourceBundleMessageSourceExtend extends
		ResourceBundleMessageSource {

	private static final String ENCODING = "GBK";// 注意属性文件使用GBK编码
	private static final String NULL = "null";

	/** cache the encoding key value * */
	Map<String, String> encodingCache = new ConcurrentHashMap<String, String>(
			20);

	/**
	 * resolve no argus
	 */
	protected String resolveCodeWithoutArguments(String code, Locale locale) {
		String message = super.resolveCodeWithoutArguments(code, locale);
		return decodeString(message, ENCODING);

	}

	/**
	 * resolve args
	 * @see resolveCode(String code, Locale locale)
	 */
	protected MessageFormat createMessageFormat(String msg, Locale locale) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating MessageFormat for pattern [" + msg
					+ "] and locale '" + locale + "'");
		}
		msg = decodeString(msg, ENCODING);
		return new MessageFormat((msg != null ? msg : ""), locale);
	}

	/**
	 * 转码 
	 * @param msg
	 * @param encode
	 * @return
	 */
	private String decodeString(String message, String encode) {
		String encodMessage = encodingCache.get(message);
		if (encodMessage == null) {
			try {
				encodMessage = new String(message.getBytes("ISO8859-1"), encode);
				if (message != null) {
					encodingCache.put(message, encodMessage);
				} else {
					encodingCache.put(message, NULL);
					// log the code is not exist in properties
				}
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		return encodMessage;
	}

}

 配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" " http://www.springframework.org/dtd/spring-beans.dtd ">
<beans default-autowire="byName">
 
	
	<!-- 国际化资源文件 -->
	<bean id="messageSource" class="org.frame.base.message.ResourceBundleMessageSourceExtend">  
           <property name="basenames">  
                <list>  
                   <value>message/message</value>  
                   <value>message/error</value>   
               </list>  
           </property>  
    </bean>  
	 
</beans>

 配置文件内容

message.user.username = 用户名 !
message.user.password = 密码 !

message.user.context = 内容{0}真好 !

 

message.user.username = user name !
message.user.password = password !

 

package org.frame.base.message;

import java.util.Locale;

import org.springframework.context.MessageSource;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MessageSourceTest {
 
	public static void main(String[] args) { 
		   MessageSource messageSource = new ClassPathXmlApplicationContext("message/testMessage.xml");  
		   String message1 = messageSource.getMessage("message.user.username", null, Locale.CHINESE);
		   //String message3 = messageSource.getMessage("message.user.username", null, Locale.CHINESE);
		   String message4 = messageSource.getMessage("message.user.context", new Object[]{"ycl"}, Locale.CHINESE);
		   String message2 = messageSource.getMessage("error.user.validName", null, Locale.CHINESE);
		   System.out.println(message1);
		   System.out.println(message2);
		   System.out.println(message4);
	}

}

 来源:http://a123159521.iteye.com/blog/1323317

您可能感兴趣的与本文相关的镜像

Anything-LLM

Anything-LLM

AI应用

AnythingLLM是一个全栈应用程序,可以使用商用或开源的LLM/嵌入器/语义向量数据库模型,帮助用户在本地或云端搭建个性化的聊天机器人系统,且无需复杂设置

<think>首先,用户的问题是基于之前的引用。引用是: - [1]: 关于Spring框架中的国际化(i18n)实现方案。 - [2]: Spring国际化的应用及原理详解。 - [3]: Spring框架国际化支持:多语言应用的实现。 - [4]: Spring框架中的工厂模式:原理、实现与应用(但用户提到引用仅供参考,不是用户真正需求)。 用户明确说:"上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。" 用户上一次的问题是什么?在对话历史中,用户上一次的问题似乎没有直接显示;在系统指令之前,有示例关于快速排序,但那不是用户的。第一条用户消息是这个:"参考站内引用:引用[1]:... [^1]。我想查找关于Spring国际化的相关信息,如使用方法、实现原理等 请问Spring框架实现国际化的方法和原理" 所以,用户的上一次问题就是这个,我正在回复它。 用户当前问题:"我想查找关于Spring国际化的相关信息,如使用方法、实现原理等 请问Spring框架实现国际化的方法和原理" 我的角色是基于系统指令回复。系统指令包括: - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如:[^1] - 对于数学表达式,使用指定格式,但这个问题可能不涉及数学。 - 结构清晰,逐步解决问题,保证真实可靠。 用户引用了[1],[2],[3],[4],但说引用仅供参考,不是真正需求,我应该基于用户的问题回答关于Spring国际化的方法和原理。 从引用中提取关键信息: - [1]: 简要提到国际化方案,从基本概念到应用。 - [2]: 详细介绍了MessageSource、LocaleResolver等组件,API使用。 - [3]: 通过故事讲解,涉及MessageSource、LocaleResolver、资源文件等。 - [4]: 关于工厂模式,可能无关,但用户说参考。 我应该专注于[2]和[3],因为它们直接相关。 我的回答需要: 1. 回答结构清晰,逐步解决问题:介绍国际化是什么,然后使用方法,然后原理。 2. 使用中文。 3. 在引用段落末尾添加引用标识。既然用户提供了引用,我应该基于这些引用回答。 用户说:"上述引用仅供参考,并不是用户真正的需求",但随后说"请尽可能多的参考用户上一次的问题和你的回答"。用户上一次的问题就是这个,所以我可以直接从引用中提取信息。 或许"用户上一次的问题"指的是在历史中,但在这个对话中,第一次用户问题是这个。 我应该生成相关问题作为结尾。 结构回答: - 先解释国际化是什么。 - 然后讲Spring实现国际化的方法:如何使用,包括配置资源文件、组件等。 - 然后讲原理:核心组件如MessageSource、LocaleResolver如何工作。 - 最后生成相关问题。 添加引用:当我提到引用中的内容时,在段落末尾添加[^1],[^2]等。既然用户编号了引用,我应该使用相同的编号。 用户提供了[1],[2],[3],[4],所以我引用时用[^1],[^2],[^3],[^4]。 例如,当提到MessageSource时,基于[2]和[3]。 确保回答真实可靠:基于标准Spring知识,我可以回忆: - 国际化通过资源包(property files)实现不同语言的文本。 - Spring使用MessageSource接口来加载消息。 - LocaleResolver解析用户的Locale(语言环境)。 - 在Web应用中,LocaleResolver可以从HTTP请求中获取Locale。 步骤: 1. 定义资源文件:messages.properties, messages_fr.properties等。 2. 配置MessageSource bean。 3. 配置LocaleResolver(如SessionLocaleResolver)。 4. 在代码或视图中使用消息。 原理:当请求到来时,LocaleResolver确定Locale,MessageSource根据Locale加载相应的资源文件。 基于引用[2]和[3]。 现在,回答结构: - 引言:什么是Spring国际化。 - 使用方法:逐步说明。 - 实现原理:解释组件交互。 - 结论。 - 生成相关问题。 在末尾添加相关问题。 系统指令说:"生成相关问题",并在示例中是"§§相关问题§§"后列出问题。 所以,我需要包括那个部分。 最后,确保中文。 </think>### Spring框架实现国际化的方法和原理 Spring框架提供了一套强大的国际化(i18n)支持机制,帮助开发者构建多语言应用程序。通过核心组件如`MessageSource`和`LocaleResolver`,Spring实现了资源文件的动态加载和语言切换。下面我将从使用方法到实现原理,逐步解释整个过程,确保内容真实可靠,基于Spring官方文档和最佳实践[^2][^3]。 #### 1. **什么是Spring国际化?** Spring国际化(i18n)是一种机制,允许应用程序根据用户的语言和区域偏好(Locale),动态显示不同语言的文本、标签和信息。这不仅支持多语言切换,还简化了资源的维护和扩展。例如,一个电商网站可以为中文用户显示简体中文界面,为英语用户显示英文界面[^2][^3]。 #### 2. **Spring国际化的使用方法** 实现Spring国际化主要包括配置资源文件、定义核心bean和在实际代码中应用。以下是分步指南: **步骤1: 创建资源文件** - 资源文件(通常为`.properties`文件)存储不同语言的文本消息。文件名格式为`messages_语言代码_国家代码.properties`(如`messages_en_US.properties`表示美式英语)。 - 示例文件内容: - `messages.properties`(默认语言): `welcome.message=Welcome!` - `messages_zh_CN.properties`(简体中文): `welcome.message=欢迎!` - 文件需放在类路径下(如`src/main/resources`)[^2][^3]。 **步骤2: 配置MessageSource bean** - `MessageSource`是核心接口,用于加载和解析资源文件。在Spring配置中(如XML或Java Config),定义一个`ResourceBundleMessageSource`或`ReloadableResourceBundleMessageSource` bean。 - 示例XML配置: ```xml <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="messages" /> <property name="defaultEncoding" value="UTF-8" /> </bean> ``` - `basename`指定资源文件的基础名(这里是`messages`)。 - 在Java Config中,使用`@Bean`注解等效配置[^2][^3]。 **步骤3: 配置LocaleResolver bean** - `LocaleResolver`负责从请求中解析用户的语言环境(Locale)。常用实现包括: - `SessionLocaleResolver`: 将Locale存储在用户会话中。 - `CookieLocaleResolver`: 使用cookie持久化Locale。 - `AcceptHeaderLocaleResolver`: 基于HTTP请求头的`Accept-Language`字段(默认)。 - 示例Java Config配置: ```java @Bean public LocaleResolver localeResolver() { SessionLocaleResolver resolver = new SessionLocaleResolver(); resolver.setDefaultLocale(Locale.ENGLISH); // 设置默认Locale return resolver; } ``` **步骤4: 实现语言切换** - 在Web应用中,可以通过拦截器或控制器动态切换语言: - 添加`LocaleChangeInterceptor` bean,拦截请求参数(如`?lang=zh_CN`)来更新Locale。 - 示例XML配置拦截器: ```xml <mvc:interceptors> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> <property name="paramName" value="lang" /> </bean> </mvc:interceptors> ``` - 在代码中使用消息: - 在控制器中注入`MessageSource`,通过`getMessage`方法获取消息: ```java @Autowired private MessageSource messageSource; public String showMessage(Locale locale) { return messageSource.getMessage("welcome.message", null, locale); } ``` - 在视图层(如Thymeleaf或JSP)直接使用标签:`#{welcome.message}`[^2][^3]。 通过以上步骤,应用程序能根据用户Locale自动加载对应资源文件,实现无缝多语言支持。 #### 3. **Spring国际化的实现原理** Spring国际化的原理基于核心组件的协作,整体流程如下: - **Locale解析过程**: - 当用户发起请求时,`LocaleResolver`解析Locale(如从会话、cookie或请求头中获取)。例如,`SessionLocaleResolver`从HttpSession读取Locale值[^2][^3]。 - 如果没有显式设置,`AcceptHeaderLocaleResolver`会解析HTTP头中的`Accept-Language`字段作为默认Locale。 - **消息加载机制**: - `MessageSource`负责加载资源文件。内部使用`ResourceBundle`(Java标准API)根据Locale查找对应的`.properties`文件。 - 消息查找顺序:先匹配精确的Locale(如`zh_CN`),如果不存在则回退到基本Locale(如`zh`),最后到默认文件(如`messages.properties`)。这确保了容错性和灵活性。 - 消息参数化:`getMessage`方法支持动态参数(如占位符`{0}`),实现消息的个性化输出[^2][^3]。 - **组件交互流程**: 1. Web请求到达时,`DispatcherServlet`调用`LocaleResolver`解析Locale。 2. 请求处理中,`MessageSource`基于解析出的Locale加载资源文件。 3. 在视图渲染时,消息被注入模板(如Thymeleaf的`#{}`语法会自动集成MessageSource)。 4. 语言切换通过拦截器更新LocaleResolver的状态(如改变会话中的Locale值)。 - 整个过程体现了Spring的依赖注入(DI)和控制反转(IoC)设计模式,提升了模块化和可测试性[^3][^4]。 这种机制的好处是解耦了业务逻辑与资源管理,开发者只需关注资源文件和配置,无需手动处理语言切换细节。 #### 总结 Spring框架通过`MessageSource`和`LocaleResolver`等组件,提供了高效、可扩展的国际化方案。使用方法包括资源文件配置、bean定义和动态Locale处理;原理基于Locale的动态解析和资源文件的层次加载。这种设计不仅简化了多语言应用的开发,还支持大型项目中的维护和全球化需求[^2][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值