在SpringBoot中如何使用国际化配置

2021-06-28  本文已影响0人  冬天里的懒喵

在阅读springboot官方文档spring-boot-reference.pdf的过程中,发现springboot的国际化支持也是非常不错的。前一段时间做了一个项目,需要解决中文、繁体、英文的国际化问题。虽然项目采用了前后端分离,最终通过前端js代码来实现了国际化,但是阅读springboot的解决方式之后,不得不说springboot在这个问题上还是非常便捷的。

1.需求描述和html代码

现在假定需要实现一个登陆业面,使其能支持简体中文、繁体中文和英文登陆。
业面如下:


image.png

要实现上述功能的html代码如下:

<!DOCTYPE html>
<html lang="en" >
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="" method="post">
    <label>Username</label>
    <input type="text" name="username" placeholder="Username">
    <label>Password</label>
    <input type="password" name="password" placeholder="password" >
    <br/>
    <div>
        <label>
            <input type="checkbox" value="remember-me">记住我
        </label>
    </div>
    <button type="submit" >登陆</button>
    <br> <br>

    <a>中文(简体)</a>
    <a>中文(繁体)</a>
    <a>English</a>
</form>

</body>
</html>

现在很容易就实现了这样一个html,那么下面就通过springboot,配合模板引擎来实现。

2.国际化资源配置

要实现上述文字部分的国际化,首先需要定一需要国际化的资源,也就是哪些位置我们需要做国际化。上述网页中,我们可以将form内的文字内容全部国际化。
在idea中,resources下面创建一个i18n目录来存放这些资源,为什么是i18n呢,i18n(其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数)是“国际化”的简称。因此我们将国际化的资源放置在此目录。需要创建的文件如下:

login.username=用户名1
login.sign=登陆1
login.remember=记住我1
login.password=密码1
login.username=Username
login.sign=Sign in
login.remember=Remember Me
login.password=Password
login.username=用户名~
login.sign=登陆~
login.remember=记住我~
login.password=密码~
login.username=用戶名
login.sign=登陸
login.remember=記住我
login.password=密碼

这样上述4个国际化文件创建完毕,分别将上述4个字段定义了不同language下的国际化输出。

3.html

现在需要将上述定义的国际化资源配置到html的模板中,此使需要用到thymeleaf模板引擎。
我们将定义一个login.html的文件放置在resources/templates目录。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="" method="post">
    <label th:text="#{login.username}">Username</label>
    <input type="text" name="username" placeholder="Username" th:placeholder="#{login.username}">
    <label th:text="#{login.password}">Password</label>
    <input type="password" name="password" placeholder="password" th:placeholder="#{login.password}">
    <br/>
    <div>
        <label>
            <input type="checkbox" value="remember-me">[[#{login.remember}]]
        </label>
    </div>
    <button type="submit" th:text="#{login.sign}">Sign in</button>
    <br> <br>

    <a th:href="@{/login(language='zh_CN')}">中文(简体)</a>
    <a th:href="@{/login(language='zh_HK')}">中文(繁体)</a>
    <a th:href="@{/login(language='en_US')}">English</a>
</form>

</body>
</html>

4.Controller

配置好上述代码之后,我们只需要定义一个非常简单的MyController类即可:

package com.dhb.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MyController {
    
    @RequestMapping("login")
    public String login() {
        return "login";
    }
    
}

当然,还需要一个启动类MySpringBootApplication:

package com.dhb;

import com.dhb.servlet.MyServlet;
import com.dhb.servlet.listener.MyHttpSessionListener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@ServletComponentScan
public class MySpringBootApplication {

    public static void main(String[] args) {
        SpringApplication.run(MySpringBootApplication.class, args);
    }

    //将servlet 添加到springboot容器中
    @Bean
    public ServletRegistrationBean<MyServlet> webServletRegistrationBean() {
        ServletRegistrationBean<MyServlet> bean = new ServletRegistrationBean<>(new MyServlet(),"/s2");
        bean.setLoadOnStartup(1);
        return bean;
    }
    
    @Bean
    public ServletListenerRegistrationBean listenerRegistrationBean() {
        ServletListenerRegistrationBean srb = new ServletListenerRegistrationBean();
        srb.setListener(new MyHttpSessionListener());
        System.out.println("listener 创建成功");
        return srb;
    }
}

这样这个国际化问题的demo就基本可以使用了,只需要通过修改浏览器的语言首选项即可:


image.png

在chrome的设置-> 高级-> 语言 中进行配置。
只需要将任何一种语言移动到顶部即可。
我们将语言首选项设置为英语之后:


image.png

打开浏览器访问http://127.0.0.1:8084/login效果如下:

image.png

这样就实现了多语言的切换。

5.手动选择语言的支持

当然,如果每次都需要按浏览器来调整则显得不那么高大上了,我们需要实现按用户自定义制定的语言来实现多语言切换。
我们需要在上述的p标签中增加:

    <a th:href="@{/login(language='zh_CN')}">中文(简体)</a>
    <a th:href="@{/login(language='zh_HK')}">中文(繁体)</a>
    <a th:href="@{/login(language='en_US')}">English</a>

可以看到在点击p标签的内容后将language参数传递到了后端。后端代码中需要定义如下类:

package com.dhb.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ObjectUtils;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

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

@Configuration
public class MyConfig implements WebMvcConfigurer {
    
    @Bean
    public LocaleResolver localeResolver() {
        return new NativeLocaleResolver();
    }

    protected static class NativeLocaleResolver implements LocaleResolver {
        
        @Override
        public Locale resolveLocale(HttpServletRequest request) {
            String language = request.getParameter("language");
            System.out.println("language is: " + language);
            Locale locale = Locale.getDefault();
            if (!ObjectUtils.isEmpty(language)) {
                String[] split = language.split("_");
                locale = new Locale(split[0], split[1]);
            }
            return locale;
        }

        @Override
        public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {

        }
    }
}

主要是实现一个WebMvcConfigurer的接口,让其初始化一个NativeLocaleResolver。在这个类中构造一个 Locale。实际上 Locale包括两个部分,第一部分是语言,第二部分是国家。
Locale(String language, String country)
通过这个构造函数进行构造,根据需要选择不同的国际化资源来实现。

点击繁体效果如下:


image.png

可见,通过springboot来实现国际化配置还是非常方便的。但是目前前后端大多数采用分离架构,因此这个功能也不再像当年struts时代会有非常多的人来使用。

上一篇下一篇

猜你喜欢

热点阅读