Spring Boot MessageSource - Spring Boot 168 EP 9

Spring Boot MessageSource – Spring Boot 168 EP 9

Spring Boot MessageSource

支援多語系訊息顯示,自動設定國際化,能根據不同語言及地區顯示相對應的語言,有助於開發人員通過編寫大量額外代碼來處理各種複雜場景,例如特定於環境的設定、國際化或可設定值,另一種情況是將預設驗證消息修改為更加友好及自定義的訊息, EP 9 增加了設定檔設定及建立了多國語系檔, Spring Message Source 透過單元測試來驗證產出結果。

功能簡介

MessageSource 訊息國際化,根據不同的使用者採用不同的語言、數字格式、日期格式等,當系統被移植到不同的語言及地區時,本身不用做內部工程上的改變或修正,就能正確顯示相對應的訊息。

檔案目錄

./
   +- build.gradle
       +- src
           +- main
           |   +- resources
           |      +- application.properties
           |      +- static
           |          +- i18n
           |          |   +- messages_en_US.properties
           |          |   +- messages_ja_JP.properties
           |          |   +- messages_zh_CN.properties
           |          |   +- messages_zh_TW.properties
           |          |   +- messages.properties
           +- test
           |   +- org
           |       +- ruoxue
           |           +- spring_boot_168
           |               +- test
           |                   +- junit4
           |                       +- MessageSourceTest.java   

Gradle

build.gradle

增加 Spring Boot Starter Test 

修改完後,點右鍵,Gradle -> Refresh Gradle Project 。

buildscript {
	group 'org.ruoxue.spring-boot-168'
	version = '0.0.1-SNAPSHOT'
	ext {
            springBootVersion = '2.1.7.RELEASE'
	}
}

dependencies {
    testImplementation 'junit:junit:4.12'
    testImplementation "org.springframework.boot:spring-boot-starter-test:${springBootVersion}"
}

組態設定

application.properties

Spring Boot Message Properties 增加 Messages 設定。

spring.messages.always-use-message-format=false
spring.messages.basename=static/i18n/messages
spring.messages.cache-duration=3600
spring.messages.encoding=UTF-8
spring.messages.fallback-to-system-locale=true
spring.messages.use-code-as-default-message=false

語系設定

messages_zh_TW.properties

Message Source Spring 新增檔案,增加訊息內容。

spring-boot-168.contact.name=若雪
spring-boot-168.contact.url=https://www.ruoxue.org
spring-boot-168.contact.email=ruoxueorg@gmail.com
spring-boot-168.contact.content=歡迎與我們聯絡,可以利用信箱或是社團留言的方式,留下訊息。

messages_en_US.properties

Message Source Spring 新增檔案,增加訊息內容。

spring-boot-168.contact.name=Ruoxue
spring-boot-168.contact.url=https://www.ruoxue.org
spring-boot-168.contact.email=ruoxueorg@gmail.com
spring-boot-168.contact.content=Welcome to contact us, you can use the mailbox or community message.

messages_zh_CN.properties

Message Source Spring 新增檔案,增加訊息內容。

spring-boot-168.contact.name=若雪
spring-boot-168.contact.url=https://www.ruoxue.org
spring-boot-168.contact.email=ruoxueorg@gmail.com
spring-boot-168.contact.content=欢迎与我们联络,可以利用信箱或是社团留言的方式,留下讯息。

messages_ja_JP.properties

Message Source Spring 新增檔案,增加訊息內容。

spring-boot-168.contact.name=ルクスエ
spring-boot-168.contact.url=https://www.ruoxue.org
spring-boot-168.contact.email=ruoxueorg@gmail.com
spring-boot-168.contact.content=メールボックスまたはコミュニティメッセージを使用して、お問い合わせください。

messages.properties

當找不到對應語系檔,預設採用此語系,內容同 messages_en_US.properties。

單元測試

MessageSourceTest.java

Message Source Spring 新增單元測試檔案,增加 @RunWith(SpringRunner.class)。

package org.ruoxue.spring_boot_168.test.junit4;

import static org.junit.Assert.assertEquals;
import java.util.Locale;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ruoxue.spring_boot_168.Application;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.MessageSource;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class MessageSourceTest {

	@Autowired
	private MessageSource messageSource;

	@Test
	public void getMessage_zh_TW() {
		String name = messageSource.getMessage("spring-boot-168.contact.name", (Object[]) null,
				Locale.TRADITIONAL_CHINESE);
		System.out.println("name: " + name);
		assertEquals("若雪", name);

		String url = messageSource.getMessage("spring-boot-168.contact.url", (Object[]) null,
				Locale.TRADITIONAL_CHINESE);
		System.out.println("url: " + url);
		assertEquals("https://www.ruoxue.org", url);

		String email = messageSource.getMessage("spring-boot-168.contact.email", (Object[]) null,
				Locale.TRADITIONAL_CHINESE);
		System.out.println("email: " + email);
		assertEquals("ruoxueorg@gmail.com", email);

		String content = messageSource.getMessage("spring-boot-168.contact.content", (Object[]) null,
				Locale.TRADITIONAL_CHINESE);
		System.out.println("content: " + content);
	}

	@Test
	public void getMessage_en_US() {
		String name = messageSource.getMessage("spring-boot-168.contact.name", (Object[]) null, Locale.US);
		System.out.println("name: " + name);
		assertEquals("Ruoxue", name);

		String url = messageSource.getMessage("spring-boot-168.contact.url", (Object[]) null, Locale.US);
		System.out.println("url: " + url);
		assertEquals("https://www.ruoxue.org", url);

		String email = messageSource.getMessage("spring-boot-168.contact.email", (Object[]) null, Locale.US);
		System.out.println("email: " + email);
		assertEquals("ruoxueorg@gmail.com", email);

		String content = messageSource.getMessage("spring-boot-168.contact.content", (Object[]) null, Locale.US);
		System.out.println("content: " + content);
	}

	@Test
	public void getMessage_zh_CN() {
		String name = messageSource.getMessage("spring-boot-168.contact.name", (Object[]) null,
				Locale.SIMPLIFIED_CHINESE);
		System.out.println("name: " + name);
		assertEquals("若雪", name);

		String url = messageSource.getMessage("spring-boot-168.contact.url", (Object[]) null,
				Locale.SIMPLIFIED_CHINESE);
		System.out.println("url: " + url);
		assertEquals("https://www.ruoxue.org", url);

		String email = messageSource.getMessage("spring-boot-168.contact.email", (Object[]) null,
				Locale.SIMPLIFIED_CHINESE);
		System.out.println("email: " + email);
		assertEquals("ruoxueorg@gmail.com", email);

		String content = messageSource.getMessage("spring-boot-168.contact.content", (Object[]) null,
				Locale.SIMPLIFIED_CHINESE);
		System.out.println("content: " + content);
	}

	@Test
	public void getMessage_ja_JP() {
		String name = messageSource.getMessage("spring-boot-168.contact.name", (Object[]) null, Locale.JAPAN);
		System.out.println("name: " + name);
		assertEquals("ルクスエ", name);

		String url = messageSource.getMessage("spring-boot-168.contact.url", (Object[]) null, Locale.JAPAN);
		System.out.println("url: " + url);
		assertEquals("https://www.ruoxue.org", url);

		String email = messageSource.getMessage("spring-boot-168.contact.email", (Object[]) null, Locale.JAPAN);
		System.out.println("email: " + email);
		assertEquals("ruoxueorg@gmail.com", email);

		String content = messageSource.getMessage("spring-boot-168.contact.content", (Object[]) null, Locale.JAPAN);
		System.out.println("content: " + content);
	}
}

getMessage_zh_TW

測試方法上點右鍵執行 Run As -> JUnit Test ,查看 console。

name: 若雪
url: https://www.ruoxue.org
email: ruoxueorg@gmail.com
content: 歡迎與我們聯絡,可以利用信箱或是社團留言的方式,留下訊息。

getMessage_en_US

測試方法上點右鍵執行 Run As -> JUnit Test ,查看 console。

name: Ruoxue
url: https://www.ruoxue.org
email: ruoxueorg@gmail.com
content: Welcome to contact us, you can use the mailbox or community message.

getMessage_zh_CN

測試方法上點右鍵執行 Run As -> JUnit Test ,查看 console。

name: 若雪
url: https://www.ruoxue.org
email: ruoxueorg@gmail.com
content: 欢迎与我们联络,可以利用信箱或是社团留言的方式,留下讯息。

getMessage_ja_JP

測試方法上點右鍵執行 Run As -> JUnit Test ,查看 console。

name: ルクスエ
url: https://www.ruoxue.org
email: ruoxueorg@gmail.com
content: メールボックスまたはコミュニティメッセージを使用して、お問い合わせください。

故障排除

缺少 @RunWith

執行 JUnit Test,拋出例外,發生錯誤,stack trace 如下:

java.lang.NullPointerException
	at test.MessageSourceTest.getMessage_zh_TW(MessageSourceTest.java:22)

這是因為沒有整合 Spring ,messageSource 無建構成物件,要加上 @RunWith 註解,使其實例化,修改完後,再次執行,就能順利運行。

// 修改前
@SpringBootTest(classes = Application.class)
public class MessageSourceTest {

// 修改後
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class MessageSourceTest {

心得分享

Spring Boot MessageSource 走向國際化,意味著產品有適用於任何地方的潛力,讓所研發的產品能輕易地配合許多不同國家、地區,使用 MessageSource Spring Boot 滿足許多不同客群的語系需求。

發佈留言