JAVA SpringBoot-10:页面国际化

页面国际化

有的时候,我们的网站会去涉及中英文甚至多语言的切换,这时候我们就需要学习国际化了!

1.准备工作

先在IDEA中统一设置properties的编码问题!
在这里插入图片描述
编写国际化配置文件,抽取页面需要显示的国际化页面消息。我们可以去登录页面查看一下,哪些内容我们需要编写国际化的配置!


2.配置文件编写

1、我们在resources资源文件下新建一个i18n目录,存放国际化配置文件

什么是i18n?
在这里插入图片描述

  • 类似的还有K8S

2、建立一个login.properties文件,还有一个login_zh_CN.properties;

其中新建三个配置文件,用来配置语言:

  • login.properties:无语言配置时候生效

  • login_en_US.properties:英文生效

  • login_zh_CN.properties:中文生效

命名方式是下划线的组合:文件名_语言_国家.properties;

发现IDEA自动识别了我们要做国际化操作;文件夹变了!
在这里插入图片描述

绑定在一起后,我们想要添加更过语言配置,只需要在大的资源包右键添加到该绑定配置文件即可
在这里插入图片描述弹出如下页面:我们再添加一个英文的;
在这里插入图片描述
此时只需要输入区域名即可创建成功,比如输入en_US,就会自动识别,这样就快捷多了!


然后打开英文或者中文语言的配置文件,点击Resource Bundle进入可视化编辑页面
在这里插入图片描述进入到可视化编辑页面后,点击加号,添加属性,首先新建一个login.tip代表首页中的提示
在这里插入图片描述然后对该提示分别做三种情况的语言配置,在三个对应的输入框输入即可(注意:IDEA2020.1可能无法保存,建议直接在配置文件中编写)
在这里插入图片描述双击点开 login.tip 我们可以发现 可视化配置十分的方便,一次性就可以配置3种
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

接下来再配置所有要转换语言的变量(注意:IDEA2020.1可能无法保存,建议直接在配置文件中编写)
在这里插入图片描述
然后打开三个配置文件的检查 查看其中的文本内容,可以看到已经做好了全部的配置

然后去查看我们的配置文件;

login.properties :默认

login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名

英文:

login.btn=Sign in
login.password=Password
login.remember=Remember me
login.tip=Please sign in
login.username=Username

中文:

login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名

OK,配置文件步骤搞定!


3.配置文件生效探究

在Spring程序中,国际化主要是通过 ResourceBundleMessageSource 这个类来实现的

Spring Boot通过 MessageSourceAutoConfiguration 为我们自动配置好了管理国际化资源文件的组件

我们在IDEA中查看以下MessageSourceAutoConfiguration类

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(name = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME, search = SearchStrategy.CURRENT)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Conditional(ResourceBundleCondition.class)
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {

	private static final Resource[] NO_RESOURCES = {};

	@Bean
	@ConfigurationProperties(prefix = "spring.messages")
	public MessageSourceProperties messageSourceProperties() {
		return new MessageSourceProperties();
	}

	@Bean
	public MessageSource messageSource(MessageSourceProperties properties) {
		ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
		if (StringUtils.hasText(properties.getBasename())) {
		   //他可以设置我们Basenames 基本的名字
			messageSource.setBasenames(StringUtils
			         //然后他会从properties.getBasename(),我们的配置文件去找
					.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
		}
		if (properties.getEncoding() != null) {
			messageSource.setDefaultEncoding(properties.getEncoding().name());
		}
		messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
		Duration cacheDuration = properties.getCacheDuration();
		if (cacheDuration != null) {
			messageSource.setCacheMillis(cacheDuration.toMillis());
		}
		messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
		messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
		return messageSource;
	}
	//......
}

主要了解messageSource()这个方法:

public MessageSource messageSource(MessageSourceProperties properties);

可以看到,它的参数为MessageSourceProperties对象,我们看看这个类

public class MessageSourceProperties {

	/**
	 * Comma-separated list of basenames (essentially a fully-qualified classpath
	 * location), each following the ResourceBundle convention with relaxed support for
	 * slash based locations. If it doesn't contain a package qualifier (such as
	 * "org.mypackage"), it will be resolved from the classpath root.
	 */
	private String basename = "messages";

	/**
	 * Message bundles encoding.
	 */
	private Charset encoding = StandardCharsets.UTF_8;

类中首先声明了一个属性basename,默认值为messages;

我们翻译其注释:

	/**
	 * Comma-separated list of basenames (essentially a fully-qualified classpath
	 * location), each following the ResourceBundle convention with relaxed support for
	 * slash based locations. If it doesn't contain a package qualifier (such as
	 * "org.mypackage"), it will be resolved from the classpath root.
	 */
  • 逗号分隔的基名列表(本质上是完全限定的类路径位置)

  • 每个都遵循ResourceBundle约定,并轻松支持于斜杠的位置

  • 如果不包含包限定符(例如"org.mypackage"),它将从类路径根目录中解析

意思是:

  • 如果你不在springboot配置文件中指定以.分隔开的国际化资源文件名称的话

  • 它默认会去类路径下找messages.properties作为国际化资源文件

这里我们自定义了国际化资源文件,因此我们需要在SpringBoot配置文件application.properties中加入以下配置指定我们配置文件的名称

# 我们的配置文件的真实位置
spring.messages.basename=i18n.login

其中i18n是存放资源的文件夹名,login是资源文件的基本名称。


4.首页获取显示国际化值

去页面获取国际化的值,查看Thymeleaf的文档,找到message取值操作为:#{…}。我们去页面测试下:

IDEA还有提示,非常智能的!

利用#{…} 消息表达式,去首页index.html获取国际化的值,没在<>内的,使用#[[#{ }]]
在这里插入图片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
		<meta name="description" content="">
		<meta name="author" content="">
		<title>登录首页</title>
		<!-- Bootstrap core CSS -->
		<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
		<!-- Custom styles for this template -->
		<link th:href="@{/css/signin.css}" rel="stylesheet">
	</head>

	<body class="text-center">
		<form class="form-signin" action="dashboard.html">
			<img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72">
			<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
			<label class="sr-only">Username</label>
			<input type="text" class="form-control" th:text="#{login.username}" placeholder="Username..." required="" autofocus="">
			<label class="sr-only">Password</label>
			<input type="password" class="form-control" th:text="#{login.password}" placeholder="Password..." required="">
			<div class="checkbox mb-3">
				<label>
          <input type="checkbox" value="remember-me" th:text="#{login.remember}">&nbsp;&nbsp;Remeember me
        </label>
			</div>
			<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>
			<p class="mt-5 mb-3 text-muted">© 2020-2021</p>
			<a class="btn btn-sm">中文</a>
			<a class="btn btn-sm">English</a>
		</form>
	</body>
</html>

重启项目,访问首页,发现已经自动识别为中文的了!
在这里插入图片描述
但是我们想要更好!可以根据按钮自动切换中文英文!


5.配置国际化解析 实现中英文切换

在Spring中有一个国际化的Locale (区域信息对象);里面有一个叫做LocaleResolver (获取区域信息对象)的解析器!

思考:
html lang="en"或html lang="en-US"分别代表什么

HTML的lang属性是用来声明语言类型,,
, , ,


, , 以及

<html lang="en"></html>//英文
<html lang="zh-CN"></html>//中文
<html lang="ja"></html>//日文
<html lang="en-US"></html>//美式英文
<div lang="en">this is English .</div>//英文

写在html标签中的lang属性是声明当前页面的语言类型,这些对于搜索引擎、网页翻译、屏幕阅读浏览器有指导意义。


1.添加中英文切换标签链接

上述实现了登录首页显示为中文,我们在index.html页面中可以看到两个标签

<a class="btn btn-sm">中文</a>
<a class="btn btn-sm">English</a>

也就对应着视图中的
在这里插入图片描述
那么我们怎么通过这两个标签实现中英文切换呢?

首先在这两个标签上加上跳转链接并带上相应的参数

<!--这里传入参数不需要使用?使用key=value-->
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>

2.自定义地区解析器组件

怎么实现我们自定义的地区解析器呢?我们首先来分析一波源码

在Spring中有关于国际化的两个类:

  • Locale:代表地区,每一个Locale对象都代表了一个特定的地理、政治和文化地区
  • LocaleResolver:地区解析器

首先搜索WebMvcAutoConfiguration,可以在其中找到关于一个方法localeResolver()

@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
public LocaleResolver localeResolver() {
    //如果用户配置了,则使用用户配置好的
   if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
      return new FixedLocaleResolver(this.mvcProperties.getLocale());
   }
    //用户没有配置,则使用默认的
   AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
   localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
   return localeResolver;
}

该方法就是获取LocaleResolver地区对象解析器:

  • 如果用户配置了则使用用户配置的地区解析器;
  • 如果用户没有配置,则使用默认的地区解析器

我们可以看到默认地区解析器的是AcceptHeaderLocaleResolver对象,我们点入该类查看源码
在这里插入图片描述
可以发现它继承了LocaleResolver接口,实现了地区解析

因此我们想要实现上述自定义的国际化资源生效,只需要编写一个自己的地区解析器,继承LocaleResolver接口,重写其方法即可。

我们在config包下新建MyLocaleResolver,作为自己的国际化地区解析器
在这里插入图片描述

我们在index.html中,编写了对应的请求跳转

  • 如果点击中文按钮,则跳转到/index.html(l=‘zh_CN’)页面

  • 如果点击English按钮,则跳转到/index.html(l=‘en_US’)页面

<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>

因此我们自定义的地区解析器MyLocaleResolver中,需要处理这两个带参数的链接请求

package com.cy.config;

import org.springframework.web.servlet.LocaleResolver;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;


public class MyLocaleResolver implements LocaleResolver {

    //解析请求
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        //获取请求中的国际化参数
        String language = request.getParameter("l");
        //默认的地区
        Locale locale = Locale.getDefault();
        //如果请求的链接参数不为空,携带了国际化参数
       if (!StringUtils.isEmpty(language)){
           //split分隔
           String[] split = language.split("_");
           //zh_CN(语言_地区)
           locale = new Locale(split[0], split[1]);
       }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
    }
}

为了让我们的区域化信息能够生效,我们需要再配置一下这个组件!在自己的MvcConofig配置类下添加bean;

//自定义的国际化组件生效
@Bean
public LocaleResolver localeResolver() {
    return new MyLocaleResolver();
}

我们重启项目,来访问一下,发现点击按钮可以实现成功切换!

点击中文按钮,跳转到http://localhost:8080/index.html?l=zh_CN,显示为中文
在这里插入图片描述

点击English按钮,跳转到http://localhost:8080/index.html?l=en_US,显示为英文:
在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值