首页 > 其他分享 >IntelliJ+SpringBoot项目实战(27)--实现国际化项目开发

IntelliJ+SpringBoot项目实战(27)--实现国际化项目开发

时间:2024-12-05 16:59:08浏览次数:7  
标签:27 IntelliJ -- springframework 国际化 user import i18n org

        因为有时候承接一些国外项目,项目需要支持国际化。国际化包括页面静态文字的国际化,接口中返回的信息的国际化,JS脚本里内容的国际化。

一、配置国际化语言

        在openjweb-core工程中增加默认国际化语言配置类:

package org.openjweb.core.config;

import java.util.Locale;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
//配置国际化语言
@Configuration
public class LocaleConfig {
    /**
     *  默认解析器 其中locale表示默认语言 LocaleResolver 用于设置当前会话的默认的国际化语言。
     */
    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver localeResolver = new SessionLocaleResolver();
        localeResolver.setDefaultLocale(Locale.CHINA);//指定默认语言,,英文可指定Locale.US
        return localeResolver;
    }

}

二、增加配置类,指定国际化参数

        国际化参数指在URL中通过?后面的国际化参数来选择语言。除了浏览器根据操作系统选择默认语种外,也可以手工指定。例如?lang=zh_CN 表示读取国际化文件messages_zh_CN.properties。下面增加一个WebMvcConfig配置类,实现WebMvcConfigurer,这个类后面还可以增加全局跨域控制等(以后再介绍)。

package org.openjweb.core.config;


import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //默认拦截器 其中lang表示切换语言的参数名 LocaleChangeInterceptor 指定切换国际化语言的参数名。
        // 例如?lang=zh_CN 表示读取国际化文件messages_zh_CN.properties。
        //System.out.println("增加国际化拦截器...........");
        LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
        localeInterceptor.setParamName("lang");// 指定设置国际化的参数
        registry.addInterceptor(localeInterceptor);

    }

}

三、按语种、key值获取国际化内容的工具类

        开发一个根据语种、key值获取国际化内容的工具类MessageUtils(在openjweb-common的路径下):

package org.openjweb.common.util;

import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;

@Component
public class MessageUtils {
    private static MessageSource messageSource;

    public MessageUtils(MessageSource messageSource) {
        MessageUtils.messageSource = messageSource;
    }

    /**
     * 获取单个国际化翻译值
     */
    public static String get(String msgKey) {
        try {
            return messageSource.getMessage(msgKey, null, LocaleContextHolder.getLocale());
        } catch (Exception e) {
            return msgKey;
        }
    }
}

四、创建国际化配置文件

        在openjweb-sys的application-dev.yml里指定国际化文件的相对路径为static/i18n.messages,并在resources下创建static\i18n目录。application-dev.xml这样配置:

spring:
  messages:
    basename: static/i18n.message

        注意static前不加/ ,static/i18n.messages ,是指src/main/resources/static/i18n下面以messages开头的国际化文件,千万不要写成static/i18n/messages ,网上很多例子写成了static/i18n/messages ,导致无法实现国际化!也可以写成 static.i18n.messages  。下面在resources/static/i18n目录下创建三个文件(分别是中文简体、英文、中文繁体):

messages_en_US.properties文件内容:
 

user.title=User Login

user.welcome=Welcome

user.username=Username

user.password=Password

user.login=Sign In

        messages_zh_CN.properties   (保存后可能自动转unicode码,不方便维护),所以需要把项目的properties字符集设置为UTF-8:

        文件内容:

user.title=用户登陆
user.welcome=欢迎
user.username=登陆用户
user.password=登陆密码
user.login=登陆

        再建一个中文繁体的messages_zh_TW.properties:

user.title=用戶登陸
user.welcome=歡迎
user.username=登陸用戶
user.password=登陸密碼
user.login=登陸

        切记还要增加一个默认的messages.peoperties,否则多语种解析不生效,这个文件复制messages_zh_CN即可,哪个是默认语种就复制哪个。

         

五、创建静态测试页

        现在做一个静态测试页,在src/main/resources/templates/建一个userlist.html文件(项目以前有这个测试页了,现在国际化):

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>hello</title>
    <meta htp-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>

<body>
<table>
    <tr>

        <td>用户名</td>
        <!--非国际化-->
        <td>登录账号</td>
        <!--国际化-->
        <td th:text="#{user.title}">登录账号 </td>
    </tr>

    <tr th:each="user:${users}">
        <td th:text="${user.realName}"></td>
        <td th:text="${user.loginId}"></td>

    </tr>
</body>
</table>
</html>

        上面的代码中,使用的是thymeleaf模板,国际化成功后,会将登录账号改为国际化定义文件里user.title 设置的值。现在我们开发一个控制层的类,指定视图为这个userlist.html,之前的示例介绍了这个控制层类,现在再贴下代码:

package org.openjweb.sys.controller;

import org.openjweb.sys.entity.CommUser;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.ArrayList;
import java.util.List;

@Controller
@RequestMapping("/demo/tmpl/")
public class TemplateController {

    //http://localhost:8001/demo/tmpl/queryUser

    @RequestMapping(value = "queryUser")

    public String list(Model model) {
        List<CommUser> userList = new ArrayList<>();
        CommUser user = new CommUser();
        user.setLoginId("admin");
        user.setRealName("阿宝");
        userList.add(user);
        model.addAttribute("users", userList);
        return "userlist";//不知道是否区分大小写
    }

    //http://localhost:8001/demo/tmpl/queryUser2
    @RequestMapping(value = "queryUser2")
    public ModelAndView list2() {
        List<CommUser> userList = new ArrayList<>();
        CommUser user = new CommUser();
        user.setLoginId("admin");
        user.setRealName("阿宝");
        userList.add(user);
        ModelAndView model = new ModelAndView();
        model.addObject("users",userList);
        model.setViewName("userlist");//指定视图
        return model;//这个前端没有解析出来
    }
}

启动SpringBoot,分别按下面的链接访问:

http://localhost:8001/demo/tmpl/queryUser

http://localhost:8001/demo/tmpl/queryUser?lang=zh_CN  简体中文 

http://localhost:8001/demo/tmpl/queryUser?lang=en_US  美式英文

http://localhost:8001/demo/tmpl/queryUser?lang=zh_TW  繁体中文

上面的模板引擎使用的thymeleaf,那么如果模板引擎使用的beetle,是否也支持国际化标签呢?网上找到这个例子,可以参考下:Spring boot+beetl+i18n国际化处理的方法 - 编程语言 - 亿速云国际化(internationalization)是设计和制造容易适应不同区域要求的产品的一种方式。它要求从产品中抽离所有地域语言,国家/地区和文化相关的元素。换言之,�...icon-default.png?t=O83Ahttps://www.yisu.com/jc/202561.html

   现在我们看下演示的效果:

        

        那么如果是VUE前后端分离的模式如何做国际化呢?这个以后再研究,这种情况可以考虑VUE页面所有的文字标签都要从后台获取对应语种的标签。 

六、JS文件国际化

        为什么要考虑JS文件的国际化?因为js文件的一些提示信息可能不需要直接从后台获取动态信息,所以需要考虑JS文件的国际化。如果使用jquery,国际化需要引入下面的依赖(在openjweb-core的pom.xml中添加):

        

        <dependency>
			<!--webjars版本定位器 用于省略版本号-->
			<groupId>org.webjars</groupId>
			<artifactId>webjars-locator-core</artifactId>
		</dependency>

		<dependency>
			<!--jQuery前端依赖-->
			<groupId>org.webjars</groupId>
			<artifactId>jquery</artifactId>
			<version>3.6.0</version>
		</dependency>


		<dependency>
			<!--jQuery国际化插件-->
			<groupId>org.webjars.bower</groupId>
			<artifactId>jquery-i18n-properties</artifactId>
			<version>1.2.7</version>
		</dependency>

        然后在上面的WebMvcConfig.java中增加一个自定义的映射,这样就不用再单独写Controller了,仅用于测试JS多语:

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/testduoyu").setViewName("testduoyu");//不能命名testlocale 可能locale有冲突
    }

        然后在openjweb-sys的resources/templates下创建一个testduoyu.html文件:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
    <title th:text="#{user.title}">用户登陆</title>
    <!-- 演示如何定位js的路径 -->
    <script th:src="@{/webjars/jquery/3.6.0/jquery.min.js}"></script>
   
    <script th:src="@{/webjars/jquery-i18n-properties/1.2.7/jquery.i18n.properties.min.js}"></script>

    <script th:inline="javascript">
        //获取应用路径
        var ROOT = [[${#servletContext.contextPath}]];//自定义映射影响取不到值?



        //获取默认语言
        var LANG_COUNTRY = [[${#locale.language+'_'+#locale.country}]];

        console.log("ROOT IS:");
        console.log(ROOT);
        console.log(LANG_COUNTRY);//get zh_CN
        //alert("ROOT:"+ROOT);
        //alert("LANG_COUNTRY:"+LANG_COUNTRY);//正常获取

        //初始化i18n插件
        $.i18n.properties({
            path: ROOT + 'i18n/',//这里表示访问路径--不要加static ,这个是相对路径
            name: 'messages',//文件名开头
            language: LANG_COUNTRY,//文件名语言 例如en_US
            mode: 'both'//默认值
        });

        //初始化i18n函数
        function i18n(msgKey) {
            try {
                return $.i18n.prop(msgKey);
            } catch (e) {
                return msgKey;
            }
        }
        //获取国际化翻译值
        console.log(i18n('user.title'));//通过js的i18读取多语文字
        alert(i18n('user.title'));
        console.log(i18n('User Login'));
    </script>
</head>
<body>
<div class="logo_box">
    <select id="locale">
        <option value="zh_CN">中文简体</option>
        <option value="zh_TW">中文繁体</option>
        <option value="en_US">English</option>
    </select>
    <h3 th:text="#{user.welcome}">欢迎登陆</h3>

    <form>
        <div class="input_outer">
            <span class="u_user"></span>
            <input id="username" name="username" class="text" type="text" th:placeholder="#{user.username}">
        </div>
        <div class="input_outer">
            <span class="us_uer"></span>
            <input id="password" name="password" class="text" type="password" th:placeholder="#{user.password}">
        </div>
        <div class="mb2">
            <a class="act-but submit" th:text="#{user.login}">登录</a>
        </div>
    </form>
</div>


<script th:inline="javascript">
    //选中语言
    $("#locale").find('option[value="' + LANG_COUNTRY + '"]').attr('selected', true);
  

    //切换语言
    $("#locale").change(function () {
    	var url=ROOT + '/testduoyu?lang=' + $("#locale").val();
    	location.href=url;
    	//alert(url)
        $.get(url, function () {
            location.reload();
        });
    });

</script>


</body>
</html>

        注意<script th:src="@{/webjars/jquery/3.6.0/jquery.min.js}"></script>路径的写法,这个是打开本机Maven下载的webjars,在.m2\repository\org\webjars\jquery\3.6.0有个jquery-3.6.0.jar,打开这个,对应里面的路径:

i18对应js的写法:<script th:src="@{/webjars/jquery-i18n-properties/1.2.7/jquery.i18n.properties.min.js}"></script>

获取应用路径: var ROOT = [[${#servletContext.contextPath}]];

 thymeleaf取上下文路径,如果application.properties配置server.servlet.context-path=/comm,则ROOT为/comm,访问路径则需要加上/comm如: http://localhost:8001/comm/....

var LANG_COUNTRY = [[${#locale.language+'_'+#locale.country}]]; 计算当前选择语种及国家,返回格式示例zh_CN

使用i18n取不同语种内容:

        在测试JS国际化之前,因为需要js需要访问webjars路径和i18n下面的messages*.properties文件,所以WebSecurityConfig文件的地址白名单里需要增加/webjars/**和/i18n/**,见下面的代码:

        

.antMatchers("/login.html", "/img/**","/demo/**","/webjars/**",  "/testduoyu","/i18n/**").permitAll()

        testduoyu.html中,alert(i18n('user.title')); 演示了js读取国际化文件user.title的值。

接下来演示JS的多语种展示:

http://localhost:8001/demo/testduoyu?lang=zh_CN

http://localhost:8001/demo/testduoyu?lang=en_US

http://localhost:8001/demo/testduoyu?lang=zh_TW 

        注意:测试的时候请package打成jar包启动(java -jar openjweb-sys-0.0.1-SNAPSHOT.jar),目前发现不打包直接在IDEA里运行应用显示乱码。

 

 

        可以看出,选择不同的语种,alert窗口会显示对应语种的提示信息。

        以上是在HTML页面和JS中国际化的示例。后面会介绍接口返回JSON的全局国际化处理。

       本文源码可从github上下载:

https://github.com/openjweb/cloud/tree/mastericon-default.png?t=O83Ahttps://github.com/openjweb/cloud/tree/master

标签:27,IntelliJ,--,springframework,国际化,user,import,i18n,org
From: https://blog.csdn.net/baozhengw/article/details/144254829

相关文章

  • 一文教你用vite创建vue3项目初始化并添加router、axios、Pinia保姆级教程
    文章目录一、什么是vite二、什么是vue3三、什么是router四、什么是axios五、什么是pinia六、详细教程1.查看nodejs版本2.使用vite最新版3.配置@指代src目录(可选)4.安装router5.引入axios6.引入pinia一、什么是viteVite是新一代的前端构建工具,在尤雨溪开发Vue3.0的......
  • 保姆级教程用vite创建vue3项目并初始化添加PrimeVue UI踩坑实录
    文章目录一、什么是PrimeVue二、详细教程1.添加PrimeVue2.配置main.js3.添加自动引入4.配置vite.config.js5.创建测试页面一、什么是PrimeVuePrimeVue是一个用于Vue.js3.x开发的一款高质量、广受欢迎的WebUI组件库。官网地址:https://primevue.org/二......
  • 电子材料试验机在塑胶行业中的应用:提升材料性能评估
    一、前言电子材料试验机,特别是用于塑胶行业的版本,是用于测试塑料和其他合成材料的关键设备。该试验机主要通过精确测量塑料样品在拉伸、压缩、弯曲等力学条件下的表现,评估其在实际使用中的性能和可靠性。塑胶材料,尤其是塑料和复合材料,已经广泛应用于汽车、电子、建筑、医疗等......
  • 纯js可定制的跨浏览器日期时间选择器插件
    Rome是一款纯js可定制的跨浏览器日期时间选择器插件。该日期时间选择器不依赖于jquery,但它依赖于moments.js。可以通过CSS文件来自定义该日期时间选择器的外观样式。在线预览 下载  安装可以通过Bower或nmp来安装该日期时间选择器插件。npminstall--saveromebower......
  • tf.sparse.reshape ValueError: Cannot reshape a tensor with xxx elements to shape
    目录项目场景问题描述报错信息原因分析解决方案后续问题项目场景大口径超表面的逆向优化设计,需要处理大型稀疏张量,超过10^10次方个数据。问题描述在使用tf.sparse.SparseTensor将大批量三维稀疏张量整形成二维稀疏张量的时候,代码报错,用简单的代码举个例子:import......
  • 车载打气泵解决方案pcba开发设计
    车载打气泵主要由驱动电机、气压传感器、LED屏幕、控制电路等模块组成,主控电路MCU接收测压信息,控制电机转速,从而调整充气量与充气速度。一键预设功能,接上气嘴后,自动检测胎压情况,充满自动停止,和手动充气相比,省去了繁琐的步骤又节省了体力。产品主要应用场合:主要用于汽车,也可以......
  • python学opencv|读取图像(二)保存彩色图像
    【1】引言前序学习过程中,已经掌握了读取图像的基本操作,对三个函数的功能有了基本了解:cv.imread()、cv.imshow()、cv.imwrite()学习文章链接为:python学opencv|读取图像-CSDN博客不过这篇文章里,我们获得的图像是灰度图。如果需要彩色图,那又如何处理,这就是本次课程的目的。......
  • SDF-Loc: Signed Distance Field based 2D Relocalization and Map Update in Dynamic
    SDF-Loc:SignedDistanceFieldbased2DRelocalizationandMapUpdateinDynamicEnvironmentsSDF-Loc:动态环境中基于符号距离场的二维重定位和地图更新作者来自中国杭州阿里巴巴达摩院人工智能实验室。{ximing.zmm,yimingchen,na.lmy}@alibaba-inc.com。2019American......
  • Python 装饰器
    基本概念装饰器是一种强大的工具,允许你在不修改原有函数或方法代码的情况下,给其增加额外的功能。装饰器本质上是一个函数,它接受一个函数作为参数并返回一个新的函数。基本语法defmy_decorator(func):defwrapper(*args,**kwargs):print('函数运行之前')......
  • openrestry学习day1(懒狗版)
    前几天随便写了下lua,那我们今天就准备运用lua写写openrestry。openrestry运用命令其实就是nginx的命令。先从下载开始吧。1、下载。打开https://openresty.org/cn/download.html,下载对应版本就可以了。2、就照着这个官网一步往下面走吧。https://moonbingbing......