Javaweb国际化解决方案

Spring国际化详解,Spring国家化实例及源码详解 Spring国际化相关的,似乎平时接触的也很少,也很少用到这部分的技术。但是做架构、框架封装的时候,又不得不考虑。 阅读详情
消息提示国际化
获取Locale

实现国际化的第一步是获取到用户的Locale。在Web应用程序中,HTTP规范规定了浏览器会在请求中携带Accept-Language头,用来指示用户浏览器设定的语言顺序,如:

Accept-Language: zh-CN,zh;q=0.8,en;q=0.2

上述HTTP请求头表示优先选择简体中文,其次选择中文,最后选择英文。q表示权重,解析后我们可获得一个根据优先级排序的语言列表,把它转换为Java的Locale,即获得了用户的Locale。大多数框架通常只返回权重最高的Locale。

Spring MVC通过LocaleResolver来自动从HttpServletRequest中获取Locale。LocaleResolver的四种实现:
AcceptHeaderLocaleResolver:默认的区域解析器实现,不可手动配置,通过请求头Accept-Language来获取Locale信息。这里需要注意的是HttpServletRequest将Accept-Language头中的语言字符串转为Locale对象时只可使用IETF语言标签(即en-US),而无法使用ISO语言标签(即en_US)。
CookieLocaleResolver:通过客户端的Cookie获取相应的Locale,Cookie为空时再从Accept-Language头中获取。目前最为常用的实现方式。
SessionLocaleResolver:通过Session获取相应的Locale,在目前多为分布式系统架构的情况下使用太过局限,不推荐使用。
FixedLocaleResolver:固定的区域解析器,总是返回一个默认的locale,不指定默认值时为JVM的默认locale,不支持setLocale方法,不能被改变。

在这里我们还是使用最为常用的CookieLocaleResolver来获取Locale。

	@Bean
	public LocaleResolver localeResolver() {
		LocaleResolver localeResolver = new CookieLocaleResolver();
		return localeResolver;
	}

当用户第一次访问网站时,CookieLocaleResolver只能从Accept-Language中获取Locale再设置到Cookie中,下次访问就会直接使用Cookie的设置。CookieLocaleResolver设置的cookie默认有效期为会话结束,我们可以自定义子类来重新设置默认的属性。

public class MyCookieLocaleResolver extends CookieLocaleResolver {
    //重写构造方法,改变cookie信息
    public MyCookieLocaleResolver(){
        this.setCookieName("Locale");
        //cookie有效期30天
        this.setCookieMaxAge(30*24*60*60);
    }
}

如果用户想通过请求接口来切换Locale,还可以配置区域变更拦截器LocaleChangeInterceptor,LocaleChangeInterceptor会配合当前使用的LocaleResolver,使用其setLocale()方法来设置新的Locale。

@Bean
public WebMvcConfigurer i18nInterceptor() {
	return new WebMvcConfigurer() {
		@Override
		public void addInterceptors(InterceptorRegistry registry) {
			LocaleChangeInterceptor i18nInterceptor = new LocaleChangeInterceptor();
			// 设置请求参数名,默认为locale
			i18nInterceptor.setParamName("lang");
			registry.addInterceptor(i18nInterceptor);
		}
	};
}

设置拦截器后即可通过URL?lang=zh_CN方式来切换语言信息,切换后的语言信息会直接存入到Cookie中。

创建资源文件

在resource下新建i18n文件目录,添加多语言配置文件。默认语言,文件名必须使用message.properties,其他语言使用message加Locale名的形式命名。

messages_en_US.properties

user.name=zhangsan

messages_zh_CN.properties

user.name=张三

查找出代码中所有写死的中文消息提示,建立多语言配置

匹配双字节字符(包括汉字在内):[^\x00-\xff]+
创建MessageSource

创建一个Spring提供的MessageSource实例,它自动读取所有的.properties文件。Spring容器可以创建不止一个MessageSource实例,我们可以把自己创建的MessageSource命名为i18nMessageSource,防止和其他实例冲突。

@Bean("i18nMessageSource")
public MessageSource messageSource() {
	ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
	messageSource.setBasename("classpath:i18n/messages");
	messageSource.setDefaultEncoding("UTF-8");
	return messageSource;
}

提供一个统一的工具类来获取多语言配置信息

@UtilityClass
public class MsgUtils {

	public String getMessage(String code) {
		MessageSource messageSource = SpringContextHolder.getBean("i18nMessageSource");
		return messageSource.getMessage(code, null, LocaleContextHolder.getLocale());
	}

	public String getMessage(String code, Object... objects) {
		MessageSource messageSource = SpringContextHolder.getBean("i18nMessageSource");
		return messageSource.getMessage(code, objects, LocaleContextHolder.getLocale());
	}
	
}
字典国际化
添加Locale字段

Web系统中消息提示的内容改动并不频繁,可以直接使用资源文件来配置,但系统字典的信息多为用户自定义,会频繁修改其内容,在字典国际化的实现中再去使用资源文件配置就不太合适了。通过添加locale字段区分不同语言的字典字段,字典表设计如下:

// 字典类型表
CREATE TABLE `sys_dict` (
  `id` int NOT NULL AUTO_INCREMENT,
  `type` varchar(100) NOT NULL COMMENT '类型',
  `description` varchar(100) DEFAULT NULL COMMENT '描述'
);

// 字典项明细表
CREATE TABLE `sys_dict_item` (
  `id` int NOT NULL AUTO_INCREMENT,
  `dict_id` int NOT NULL COMMENT '字典ID',
  `type` varchar(100) NOT NULL COMMENT '字典类型',
  `locale` varchar(10) NOT NULL COMMENT '语言区域',
  `key` varchar(100) NOT NULL,
  `value` varchar(100) NOT NULL
);
动态缓存获取

由于字典信息会在系统中频繁使用,不可能每次使用都去重新查询数据库,将字典信息存储到缓存中可以有效提高效率,使用缓存注解在查询列表请求的同时缓存列表信息

@GetMapping("/type/{type}")
@Cacheable(value = "dict_details", key="#type")
public Object list(@PathVariable String type){
	// 查询数据库获取字典类型列表信息
	return list;
}

但是这样只能缓存指定的字典类型,还需要实现其多语言的切换,重写Spring中KeyGenerator的接口实现,在缓存key值的生成过程中带上Locale信息

public class LocalizedGenerator implements KeyGenerator {

	@Override
	public Object generate(Object target, Method method, Object... params) {
		String key = params[0] + "_" + LocaleContextHolder.getLocale();
		return key;
	}

}

在@Cacheable注解中指定keyGenerator

@Cacheable(value = "dict_details", keyGenerator = "localizedGenerator")
操作日志国际化
多语言配置

操作日志的国际化同消息提示的国际化,可以将日志内容的模板添加到资源文件中,参数可动态传入。

log_en_US.properties

log.user.login=user {0} login success

log_zh_CN.properties

log.user.login=用户{0}登录成功

定义对应的logMessageSource实例

@Bean("logMessageSource")
public MessageSource messageSource() {
	ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
	messageSource.setBasename("classpath:log/log");
	messageSource.setDefaultEncoding("UTF-8");
	return messageSource;
}

获取多语言操作日志信息

MessageSource messageSource = SpringContextHolder.getBean("i18nMessageSource");
String logContent = messageSource.getMessage("log.user.login", "test", LocaleContextHolder.getLocale());
System.out.println(logContent);

日志表仅需要存储多语言资源文件中的key值和动态传入的参数,查询的时候再通过messageSource来获取对应的日志消息。动态参数以json格式存储在mysql数据库,方便使用。

日志表设计:

CREATE TABLE `sys_log` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `template` varchar(255) DEFAULT NULL COMMENT '日志模板',
  `template_params` json DEFAULT NULL COMMENT '模板参数',
  `operate_time` datetime DEFAULT NULL COMMENT '操作时间',
  `operate_by` varchar(64) DEFAULT NULL COMMENT '操作人'
);

mybatisplus处理数据库json数据:

@Data
@TableName(value = "sys_log",autoResultMap = true)
public class SysLog extends Model<SysLog> {

	@TableField(typeHandler = JacksonTypeHandler.class)
	private JSONArray templateParams;

}
自定义日志注解

现在完成了操作日志的多语言信息的获取,在项目中每个业务逻辑处理的过程中都需要记录操作日志,需要使用AOP切面技术将日志记录操作统一处理。

自定义日志注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {

	// 日志模板
	String template();

	// 模板参数
	String[] params() default {};
	
}

自定义日志切面,对日志模板参数加入SpEL支持

@Aspect
public class SysLogAspect {

	private static final DefaultParameterNameDiscoverer DEFAULT_PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
    private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
    private static final TemplateParserContext TEMPLATE_PARSER_CONTEXT = new TemplateParserContext();
    private static final ThreadLocal<StandardEvaluationContext> StandardEvaluationContextThreadLocal = new ThreadLocal<>();

	@Around("@annotation(sysLog)")
	@SneakyThrows
	public Object around(ProceedingJoinPoint point, com.goodview.ipp.common.log.annotation.SysLog sysLog) {
		// 模板参数数组
		String[] templateParams = sysLog.params();
		if(templateParams.length > 0) {
			// 获取切点参数列表
			Map<String, Object> methodParams = getMethodParams(point);
			for (int i = 0; i < templateParams.length; i++) {
				// 解析每个模板参数的值
				templateParams[i] = parseExpression(templateParams[i], methodParams);
			}
		}

		// 填充日志实体
		SysLog logVo = new SysLong;
		logVo.setTemplate(sysLog.value());
		// 以json格式保存模板参数
		if(templateParams.length > 0) {
			JSONArray json = new JSONArray();
			for(String str : templateParams) {
				json.add(str);
			}
			logVo.setTemplateParams(json);
		}
		logVo.setOperateBy(user.getUsername());
		logVo.setOperateTime(LocalDateTime.now());

		// 发送异步日志事件
		Object obj;

		try {
			obj = point.proceed();
		} catch (Exception e) {
			// TODO 异常处理
			throw e;
		} finally {
			SpringContextHolder.publishEvent(new SysLogEvent(logVo));
		}

		return obj;
	}

	private Map<String, Object> getMethodParams(ProceedingJoinPoint point){
		MethodSignature signature = (MethodSignature) point.getSignature();
		String methodName = point.getSignature().getName();
        Class<?>[] parameterTypes = signature.getMethod().getParameterTypes();
        Method method;
        try {
            method = point.getTarget().getClass().getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException ex) {
            ex.printStackTrace(System.out);
            return null;
        }
        Object[] args = point.getArgs();
        String[] parameterNames = DEFAULT_PARAMETER_NAME_DISCOVERER.getParameterNames(method);
        Map<String, Object> methodParams = new HashMap<>();
        if (parameterNames != null) {
            for (int i = 0; i < parameterNames.length; i++) {
            	methodParams.put(parameterNames[i], args[i]);
            }
        }
		return methodParams;
	}
	
	private String parseExpression(String template, Map<String, Object> params) {
        // 将ioc容器设置到上下文中
        ApplicationContext applicationContext = SpringContextHolder.getApplicationContext();
        // 线程初始化StandardEvaluationContext
        StandardEvaluationContext standardEvaluationContext = StandardEvaluationContextThreadLocal.get();
        if(standardEvaluationContext == null){
            standardEvaluationContext = new StandardEvaluationContext(applicationContext);
            standardEvaluationContext.addPropertyAccessor(new BeanFactoryAccessor());
            standardEvaluationContext.setBeanResolver(new BeanFactoryResolver(applicationContext));
            StandardEvaluationContextThreadLocal.set(standardEvaluationContext);
        }
        // 将自定义参数添加到上下文
        standardEvaluationContext.setVariables(params);
        // 解析表达式
        Expression expression = EXPRESSION_PARSER.parseExpression(template, TEMPLATE_PARSER_CONTEXT);
        return expression.getValue(standardEvaluationContext, String.class);
    }

}

使用方式

// 纯日志消息
@SysLog(template = "log.user.login")
// 获取方法参数值
@SysLog(template = "log.user.login", params = {"#{username}"})
// 获取方法参数对象的属性的值
@SysLog(template = "log.user.login", params = {"#{user.username}"})
// 通过方法参数查询数据
@SysLog(template = "log.user.login", params = {"#{@userService.getUserName(#id)}"})
javaWeb之国际化(i18n)详解 @TOC 一、国际化开发概述 二、合格的国际化软件 三、固定文本元素的国际化 四、动态数据的国际化 阅读详情

相关推荐

Java国际化标准程序实现

每个语言对应一个资源文件,文件的命名按照语言和国家的ISO标准命名,例如"messages_en_US.properties"表示英语(美国)的资源文件,"messages_zh_CN.properties"表示中文(中国)的资源文件。类加载资源文件,并根据当前的语言环境获取对应的文本内容,开发人员可以轻松地实现多语言切换的功能。通过运行上面的代码,我们可以看到根据不同的语言环境,程序输出的文本内容也会发生相应的变化。接下来,我们需要在程序中设置不同的语言环境,以便测试多语言支持的效果。

2301_79326254的博客 158

JAVA (Springboot) i18n 国际化语言配置

在 Spring Boot 应用中,国际化(i18n)是一项重要功能,它允许应用根据用户的区域设置(Locale),动态地提供不同语言的内容。这使得应用能够轻松适应全球范围内不同语言和地区用户的需求,增强用户体验。Spring Boot 对国际化的支持基于 Spring 框架的 i18n 功能,并进行了简化配置,使其在 Spring Boot 项目中更易于实现。

weixin_47054648的博客 1万+

Java与国际化与本地化

在实际开发中,开发人员应该根据不同的需求选择合适的工具和API来支持国际化和本地化。Java提供了丰富的API和类来支持国际化,包括Locale、ResourceBundle、DateFormat和NumberFormat等类。这些资源文件通常包含了特定语言环境下的字符串、图像、音频和其他类型的文件。Locale类还提供了一些静态常量,例如Locale.US、Locale.CHINA等,它们分别代表美国和中国的语言环境。Locale是Java中的一个类,用于表示一个特定的区域、国家或语言环境。

吃不胖. 688

(Java)国际化程序

国际化操作是在开发中较为常见的一种要求,实际上国际化的操作就是指一个程序可以同时适应多门语言,即如果现在程序的使用者是中国人,则会显示中文,如果是英文人,则会显示英语,也就是通过国际化操作让一个程序适应各个国家的语言要求。 但是实现国际化程序只靠 Local类时不够的,还需要属性文件和 ResourceBundle 类的支持,所谓的属性文件是指后缀为 “.properties” 的文件,文件中的内...

南淮北安的博客 964

TCNOpen实现TRDP通信协议(源码编译运行测试)

概述 本文介绍了通过TCNOpen开源源码实现TRDP通信,包括源码下载,开发环境搭建,编译运行,测试。 Linux环境下编译运行TRDP (一) 下载CANOpen源码。 下载地址:https://sourceforge.net/p/tcnopen/trdp/HEAD/tree/ (二) 源码编译 下载源码解压过后,在根目录文件readme-makefile.txt有介绍源码的配置和编译方法。 在trdp/config目录下可以看到包含在linux环境下的编译配置文件LINUX_config;执行”m

fengweibo112的博客 9630

audio框架学习-Audio_Flinger分析

文章目录一、代码位置二、audio服务启动2.1 main服务2.2 audioflinger添加到系统服务中2.3 audioflinger的对外接口 之前记录过audioTrack的笔记,这次继续参考audioFlinger相关的代码并做笔记; 参考文档:https://www.cnblogs.com/innost/archive/2011/01/15/1936425.html和https://blog.youkuaiyun.com/zyuanyun/article/details/60890534?spm=100

永不秃头的程序员的博客 2135

JavaWeb同步学习笔记之九十八、JavaWeb_国际化之Locale

JavaWeb_国际化之Locale国际化之Locale 国际化之Locale 1.概述  1)软件的本地化:一个软件在某个国家或地区使用时,采用该国家或地区的语言,数字,货币,日期等习惯。  2)软件的国际化:软件开发时,让它能支持多个国家和地区的本地化应用。使得应用软件能够适应多个地区的语言和文化风俗习惯。  3)随用户区域信息而变化的数据称为本地信息敏感数据。例如数字,货币等数据。  4)...

q124xs的博客 241

深度解析快递柜管理系统的C++实现:设计与实现

本文详细介绍了一个基于C++的快递柜管理系统的设计与实现,包括系统需求分析、架构设计、数据库设计、关键功能模块实现和测试与验证。通过详细的代码示例和理论分析,读者可以全面了解如何开发一个完整的快递柜管理系统。希望本文能够为读者在实际项目开发中提供有价值的参考。

m0_57781768的博客 713

有关自己javaweb项目常见问题汇总

1.你项目是怎样实现国际化的?   java推荐用 XX.properties配置文件,比如lan_Zh_CN.properties里面放你程序的所有中文提示,lan_fr.properties里面放你策划年供需的所有法文提示(和上面的所有中文提示一一对应的),然后在程序里自己实现调用,就是用户在选择不同语言时,读取对应配置文件的提示。 2.Ajax与jquery区别?   ajax一般用

s2940086379的博客 3600

基于灰度信息的图像配准方法

图像配准方法分为三种:基于灰度信息方法、基于变换域方法和基于特征方法。基于灰度信息方法是直接根据图像或图像块灰度信息进行像素上的对齐,该方法主要思想是直接最小化图像信息差异。然而,图像信息差异的判断准则衍生出不同的配准方法。常见的基于灰度信息的图像配准方法包括互相关法、互信息法和误差平方和法。本节将分别对互相关法、互信息法和误差平方和算法展开介绍,并通过MATLAB进行演示。基于灰度的图像方法容易实现,但同样存在不足。该方法对成像条件(光照,遮挡)、图像形变旋转以及噪声极其敏感,同时具有较高的计算复杂度。

weixin_42068054的博客 3775

FPGA赋能:从加权灰度均值到快速收敛的自动曝光实战

本文深入探讨了FPGA在工业视觉自动曝光算法中的应用,重点介绍了加权灰度均值法的优化实现与快速收敛策略。通过硬件友好的算法改造和流水线架构设计,FPGA方案能在1帧内完成曝光调整,显著提升处理速度和能效比,适用于复杂光照条件下的工业检测场景。

weixin_29306317的博客 82

JavaWeb的学习(下)

JavaWeb的学习 尚硅谷JavaWEB基础教程,哔哩哔哩链接:https://www.bilibili.com/video/BV1jW411u7PZ 七、JavaBean • 用作JavaBean的类必须具有一个公共的、无参数的构造方法。 • JavaBean的属性与普通Java类的属性的概念不一样,JavaBean的属性是以方法定义的形式出现的。 • 用于对属性赋值的方法称为属性修改器或setter方法,用于读取属性值的方法称为属性访问器或getter方法。 • 属性修改器必须以小写的set

qq_461491877的博客 1644

【深度学习】基于BERT模型的情感分析(附实战完整代码+数据集)

情感分类是一个快速发展的研究领域,尽管众多模型和数据集在二分类任务中显示出很高的准确性,但细粒度的情感分类任务仍然是一个很大改进空间的领域。分析SST-5数据集,Munikar等人的先前工作表明,嵌入工具BERT允许使用简单的模型来实现最新的准确性。

aaaa_hsjsueu的博客 2万+

springmvc html资源路径,springmvc web国际化i18n解决资源文件路径问题

为了实现国际化,我根据一篇文章写了测试代码。参考: 深入分析JavaWeb – 国际化(i18n)首先,我先说一下我一开始错误的示范。整个项目的架构是这样的:1. 控制器BundleTest.java@Controllerpublic class BundleTest {@RequestMapping(value="/globalTest",method=RequestMethod.GET)pub...

weixin_39975810的博客 306

AUTOSAR知识点 之 XCP (三):XCP功能描述

记录一下XCP使用时候的功能包含命令时序、错误码表、事件描述以及对规范的记录。XCP的图示如下从上图就可以看出数据流的流向CAN-CANIF-XCP,发送反之。XCP的状态机如下。

梦想技术家 3074

Simulink仿真状态空间中状态变量时域响应

起因 今天老师留了一道关于状态空间变量响应的题,于是想用simulink仿真,一开始使用state-space模块,但是发现它只能输出y,没办法显示状态变量的变化情况。然而状态变量之间的关系都可以表示为一阶微分方程组,因此我们考虑在Simulink中搭建微分方程组来求解这个问题。 微分方程组 x1˙=x2x2˙=−4x1−5x2+1(1)\dot{x_1}=x_2\\ \dot{x_2}=-4x_...

ZYunfei的博客 7445

JSP——第8章: Web应用开发常见问

本书章节来自:JAVA  WEB 应用与开发  梁胜彬 乔保军主编    清华大学出版社 上一章节:JSP——第7章: MVC与DAO模式 Web应用开发常见问题 本章要点:  Java中文问题  文件上传  文件下载  分页显示  程序国际化  安装与部署Java Web应用  图表开发 1. 中文问题 中文问题的根源

Reserved_person的博客 1157

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

JavaWeb项目国际化出现乱码解决办法

JavaWeb项目国际化出现乱码解决办法 修改当前编译器的编码为UTF-8,如果出现乱码后更改的设置,建议把properties里面的配置重写,如下图所示: IDEA具体设置如图所示: 快捷键ctrl+alt+s,在Editor->File Encoding中设置 如果使用了汉化插件,设置里面找文件编码。 设置完重新构建项目,启动项目,乱码问题就被解决了!! ...

JiaMing11_27的博客 1081

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

JavaWeb中文乱码解决方案

JavaWeb中文乱码解决方案

wangchaoqi1985的博客 120

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

国内的java Web主流框架有哪些

在中国,Java Web 的主流框架包括: Spring MVC: 是一个轻量级的 Java Web 框架,它使用了基于 Java 的反射机制来实现 MVC 架构。它提供了许多优秀的特性,例如依赖注入、声明式事务支持和 MVC 布局支持。 Struts: 是一个基于 MVC 架构的框架,它提供了许多强大的功能,例如表单验证、国际化支持和可扩展的插件架构。 Hibernate: 是一个强大的 ...

weixin_42602241的博客 610

JavaWeb:国际化

国际化开发概述 软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的、符合来访者阅读习惯的页面或数据。 国际化(internationalization)又称为 i18n(读法为i 18 n,据说是因为internationalization(国际化)这个单词从i到n之间有18个英文字母,i18n的名字由此而来)。 合格的国际化软件 软...

离开屏幕的光,哪盏灯照亮你的孤独? 1523

JavaWeb开发——软件国际化(文本元素国际化)

前几天围绕着JDBC编程进行了系统的学习。现在我们对Java程序数据库操作已经是轻车熟路了。也学会了使用各种框架来帮助我们简化编程。 今天是学习计划的第七天,虽然学习热情没有前几天高涨了。但是,写博客总结的习惯应该要坚持下去。废话不多说了。 今天的学习内容是JavaWeb开发——软件国际化。 软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的...

。。。 2667

【JavaWeb】i18n国际化

什么是I18N国际化: 国际化(Internationalization)指的是同一个 网站可以支持多种不同的语言,以方便不同的国家,不同语种的用户访问,一个相同的网站,而不同的人访问的时候可以根据用户所在的区域显示不同的语言文字,而网站的布局样式不发生改变; 国家化三要素: (1)Locale对象:.

weixin_47418550的博客 1139

javaweb之国际化

原文链接 [https://zhhll.com.cn/2021/javaweb/基础/11.国际化/] - 国际化(i18n): i18n internationalization,网站能够提供翻译成访问者的语言或国籍的不同版本的内容 - 本地化(i10n): 向网站添加资源,使其适应特定的地理或文化区域,例如将网站翻译为中文 - 区域设置:通常为语言符号后跟一个由下划线分隔的国家符号。例如"en_US"

Lxn2zh的博客 658

国际化解决方案

以上是项目实践中积累的经验和解决方案,数据库中维护多种字段耦合度较高,不利于扩展,后期会寻找替代方案。大家如果有更好的解决方案请分享出来,互相学习。https://resource.liulingfengyu.cn/img/扫码_搜索联合传播样式-标准色版压缩版.png。

程序员们必读的博客,涵盖IT技术、编程经验等领域。 599

javaweb项目之项目i18n国际化

1.什么是 i18n 国际化? 国际化(Internationalization)指的是同一个网站可以支持多种不同的语言,以方便不同国家,不同语种的用户访问。  关于国际化我们想到的最简单的方案就是为不同的国家创建不同的网站,比如苹果公司,他的英文官网是: http://www.apple.com 而中国官网是http://www.apple.com/cn  苹果公司这种方案并不适合全部公司,而我们希望相同的一个网站,而不同人访问的时候可以根据用户所在的区域显示不同的语言文字,而网站的布局样式等不发生改

qq_43670543的博客 537
上一篇: springboot中使用@Async
IT油条
博客等级 码龄15年 35粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值