1.创建 Spring Boot + Kotlin + Maven 项目

chenguangjian:i18n-demo jack$ tree 
.
├── HELP.md
├── i18n-demo.iml
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
│ ├── kotlin
│ │ └── com
│ │ └── example
│ │ └── i18ndemo
│ │ ├── Application.kt
│ │ ├── IndexController.kt
│ │ ├── LocaleConfig.kt
│ │ └── LocaleMessage.kt
│ └── resources
│ ├── application.properties
│ ├── i18n
│ │ ├── messages.properties
│ │ ├── messages_en_US.properties
│ │ └── messages_zh_CN.properties
│ ├── static
│ └── templates
│ └── index.ftlh
└── test
└── kotlin
└── com
└── example
└── i18ndemo
└── ApplicationTests.kt

15 directories, 15 files

2.添加pom.xml依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>i18n-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>i18n-demo</name>
<description>Demo project for Spring Boot</description>

<properties>
<java.version>1.8</java.version>
<kotlin.version>1.3.72</kotlin.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
</dependencies>

<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>

</project>

3.IndexController.kt

package com.example.i18ndemo

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Controller
import org.springframework.ui.ModelMap
import org.springframework.web.bind.annotation.RequestMapping

/**
* @author: Jack
* 2020/10/16 14:42
*/
@Controller
class IndexController {
@Autowired
lateinit var localeMessage: LocaleMessage

@RequestMapping(value = ["/", ""])
fun hello(model: ModelMap): String {
val welcome = localeMessage.getMessage("welcome")
model.addAttribute("welcome", welcome)
return "index"
}
}

4.封装国际化工具类 LocaleMessage.kt

package com.example.i18ndemo

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.MessageSource
import org.springframework.context.i18n.LocaleContextHolder
import org.springframework.stereotype.Component
import java.util.*


/**
* 封装国际化工具类
* @author: Jack
* 2020/10/16 16:21
*/
@Component
class LocaleMessage {
@Autowired
lateinit var messageSource: MessageSource

fun getMessage(code: String): String? {
val locale: Locale = LocaleContextHolder.getLocale()
return messageSource.getMessage(code, null, null, locale)
}

}

5.本地化配置类 LocaleConfig.kt

package com.example.i18ndemo

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
import java.util.*

/**
* 本地化配置类
*
* @author: Jack
* 2020/10/16 17:08
*/
@Configuration
class LocaleConfig {

/**
* 默认解析器,其中locale表示默认语言
*/
@Bean
fun localeResolver(): LocaleResolver {
val sessionLocaleResolver = SessionLocaleResolver()
sessionLocaleResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE)
sessionLocaleResolver.setTimeZoneAttributeName("GMT+8")
return sessionLocaleResolver
}

/**
* 默认拦截器,其中lang表示切换语言的参数名
*/
@Bean
fun localeInterceptorConfigurer(): WebMvcConfigurer {
return object : WebMvcConfigurer {
override fun addInterceptors(registry: InterceptorRegistry) {
val localeInterceptor = LocaleChangeInterceptor()
localeInterceptor.paramName = "lang"
registry.addInterceptor(localeInterceptor)
}
}
}

}

6.配置语言文案


SpringBoot 国际化实现跨地区的多语言切换_spring


创建文件夹 resources/i18n , 创建文件:
messages.properties

welcome=你好,世界

messages_en_US.properties

welcome=Hello,World

messages_zh_CN.properties

welcome=你好,世界

7.配置 application.properties

spring.messages.basename=i18n/messages
spring.messages.encoding=UTF-8
spring.messages.cache-duration=3600
spring.freemarker.suffix=.ftlh
spring.freemarker.charset=UTF-8
spring.freemarker.enabled=true
spring.freemarker.allow-session-override=true
spring.freemarker.expose-session-attributes=true

8. 模板文件 templates/index.ftlh

<a href="?lang=en_US"> 英语</a>
<a href="?lang=zh_CN"> 中文</a>
<h1>${welcome}</h1>

9.启动测试 Application.kt

package com.example.i18ndemo

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
import org.springframework.boot.runApplication

@SpringBootApplication(exclude = [ErrorMvcAutoConfiguration::class])
class Application

fun main(args: Array<String>) {
runApplication<Application>(*args)
}

​http://127.0.0.1:8080/?lang=en_US​

SpringBoot 国际化实现跨地区的多语言切换_大数据_02


​http://127.0.0.1:8080/?lang=zh_CN​


SpringBoot 国际化实现跨地区的多语言切换_编程语言_03



Kotlin开发者社区


SpringBoot 国际化实现跨地区的多语言切换_java_04


专注分享 Java、 Kotlin、Spring/Spring Boot、MySQL、redis、neo4j、NoSQL、Android、JavaScript、React、Node、函数式编程、编程思想、"高可用,高性能,高实时"大型分布式系统架构设计主题。

High availability, high performance, high real-time large-scale distributed system architecture design

分布式框架:Zookeeper、分布式中间件框架等
分布式存储:GridFS、FastDFS、TFS、MemCache、redis等
分布式数据库:Cobar、tddl、Amoeba、Mycat
云计算、大数据、AI算法
虚拟化、云原生技术
分布式计算框架:MapReduce、Hadoop、Storm、Flink等
分布式通信机制:Dubbo、RPC调用、共享远程数据、消息队列等
消息队列MQ:Kafka、MetaQ,RocketMQ
怎样打造高可用系统:基于硬件、软件中间件、系统架构等一些典型方案的实现:HAProxy、基于Corosync+Pacemaker的高可用集群套件中间件系统
Mycat架构分布式演进
大数据Join背后的难题:数据、网络、内存和计算能力的矛盾和调和
Java分布式系统中的高性能难题:AIO,NIO,Netty还是自己开发框架?
高性能事件派发机制:线程池模型、Disruptor模型等等。。。

合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下。不积跬步,无以至千里;不积小流,无以成江河。


SpringBoot 国际化实现跨地区的多语言切换_spring_05


Kotlin 简介

Kotlin是一门非研究性的语言,它是一门非常务实的工业级编程语言,它的使命就是帮助程序员们解决实际工程实践中的问题。使用Kotlin 让 Java程序员们的生活变得更好,Java中的那些空指针错误,浪费时间的冗长的样板代码,啰嗦的语法限制等等,在Kotlin中统统消失。Kotlin 简单务实,语法简洁而强大,安全且表达力强,极富生产力。

Java诞生于1995年,至今已有23年历史。当前最新版本是 Java 9。在 JVM 生态不断发展繁荣的过程中,也诞生了Scala、Groovy、Clojure 等兄弟语言。

Kotlin 也正是 JVM 家族中的优秀一员。Kotlin是一种现代语言(版本1.0于2016年2月发布)。它最初的目的是像Scala那样,优化Java语言的缺陷,提供更加简单实用的编程语言特性,并且解决了性能上的问题,比如编译时间。 JetBrains在这些方面做得非常出色。

Kotlin语言的特性

用 Java 开发多年以后,能够尝试一些新的东西真是太棒了。如果您是 Java 开发人员,使用 Kotlin 将会非常自然流畅。如果你是一个Swift开发者,你将会感到似曾相识,比如可空性(Nullability)。 Kotlin语言的特性有:

1.简洁

大幅减少样板代码量。

2.与Java的100%互操作性

Kotlin可以直接与Java类交互,反之亦然。这个特性使得我们可以直接重用我们的代码库,并将其迁移到 Kotlin中。由于Java的互操作性几乎无处不在。我们可以直接访问平台API以及现有的代码库,同时仍然享受和使用 Kotlin 的所有强大的现代语言功能。

3.扩展函数

Kotlin 类似于 C# 和 Gosu, 它提供了为现有类提供新功能扩展的能力,而不必从该类继承或使用任何类型的设计模式 (如装饰器模式)。

4.函数式编程

Kotlin 语言一等支持函数式编程,就像Scala一样。具备高阶函数、Lambda 表达式等函数式基本特性。

5.默认和命名参数

在Kotlin中,您可以为函数中的参数设置一个默认值,并给每个参数一个名称。这有助于编写易读的代码。

6.强大的开发工具支持

而由于是JetBrains出品,我们拥有很棒的IDE支持。虽然Java到Kotlin的自动转换并不是100% OK 的,但它确实是一个非常好的工具。使用 IDEA 的工具转换Java代码为 Kotlin 代码时,可以轻松地重用60%-70%的结果代码,而且修改成本很小。

Kotlin 除了简洁强大的语法特性外,还有实用性非常强的API以及围绕它构建的生态系统。例如:集合类 API、IO 扩展类、反射API 等。同时 Kotlin 社区也提供了丰富的文档和大量的学习资料,还有在线REPL。

A modern programming language that makes developers happier. Open source forever


SpringBoot 国际化实现跨地区的多语言切换_java_06

图来自《Kotlin从入门到进阶实战》 (陈光剑,清华大学出版社) SpringBoot 国际化实现跨地区的多语言切换_编程语言_07

图来自《Kotlin从入门到进阶实战》 (陈光剑,清华大学出版社) SpringBoot 国际化实现跨地区的多语言切换_分布式_08


​https://kotlinlang.org/​