什麼是I8n 國際化(I18n)指的是設計和開發產品的過程,使得它們能夠適應多種語言和文化環境,而不需要進行大量的代碼更改。這通常涉及到創建一個基礎版本的產品,然後通過配置和資源文件來添加對不同語言和地區的支持。 這樣,當產品需要在新的地理區域或語言環境中使用時,只需要添加或更新相應的資源文件,而不 ...
什麼是I8n
國際化(I18n
)指的是設計和開發產品的過程,使得它們能夠適應多種語言和文化環境,而不需要進行大量的代碼更改。這通常涉及到創建一個基礎版本的產品,然後通過配置和資源文件來添加對不同語言和地區的支持。
這樣,當產品需要在新的地理區域或語言環境中使用時,只需要添加或更新相應的資源文件,而不需要修改產品本身的代碼。
❝"
❞I18n
" 是 "Internationalization
" 的縮寫形式,之所以是 "I18n
" 而不是 "Int
" 或者其他縮寫,是因為 "Internationalization
" 這個詞的第一個字母是 "I
",最後一個字母是 "n
",而在這兩個字母之間有 18 個字元。因此,"I18n
" 成為了一個流行的縮寫方式,類似的還有 "K8s
" 。
Spring Boot I18n
I8n
體現在Java
後端比較常見的就是錯誤提示,而SpringBoot
本身就提供了對I8n的支持。使用也非常簡單,可以參考一下官方文檔。
添加國際化資源文件
SpringBoot
預設會讀取classpath/resource
下的messages
目錄里的國際化資源文件,可以通過下麵這個配置更改:
spring.messages.basename=messages
咱們先通過Idea
創建國際化資源文件,方法如下:
創建完成後在reources
目錄下能看到這些國際化資源文件,圖中為了演示,定義了咱們開發中比較常見的登錄錯誤提示信息。
創建工具類
創建工具類的目的是方便咱們獲取國際化信息
public class I18nUtil {
public static String getI18nMessage(String code) {
try {
// SpringBoot提供有一個MessageSource的預設實現
MessageSource messageSource = SpringUtils.getBean("messageSource");
// 從SpringBoot中獲取請求上下文 語言
Locale locale = LocaleContextHolder.getLocale();
// 因為我項目只有中文和英文,所以判斷一下除了指定中文,否則預設使用英文
// 這裡對簡體中文的定義,Locale[] SIMPLIFIED_CHINESE = {Locale.CHINESE, Locale.CHINA, Locale.SIMPLIFIED_CHINESE, Locale.PRC};
if (Arrays.stream(LocaleUtils.SIMPLIFIED_CHINESE).toList().contains(locale)) {
locale = Locale.SIMPLIFIED_CHINESE;
} else {
locale = Locale.US;
}
return messageSource.getMessage(code, null, locale);
} catch (Exception e) {
log.error("獲取國際化內容異常", e);
// 如果獲取國際化信息失敗就返回原內容
return code;
}
}
}
定義介面統一返回類
@Data
public class RestResult<T> implements Serializable {
private static final long serialVersionUID = 1L;
/** 狀態標識碼 */
private String code;
/** 描述信息 */
private String message;
/** 數據 */
private T data;
public String getMessage(){
if (StrUtil.isNotEmpty(this.code)) {
// 獲取I8n
return I18nUtil.getI18nMessage(this.code)
}
return this.message;
}
// 省略其他方法。。。
}
請求頭添加語言編碼
curl -H "Accept-Language: zh-CN" http://example.com
Spring Cloud 配置I8n
上面是一個簡單的是SpringBoot
項目配置I8n的流程,但是在Spring Cloud
下通常會有多個服務(SpringBoot
項目)。按照我們的習慣一般有一個公共項目(common
),用於封裝POJO
和一些通用的工具類、常量類之類的功能,然後把這個項目打成jar
包,其他業務服務都會依賴這個項目,達到功能復用的目的。通用我們也會將一些通用的錯誤信息(比如:用戶Id不能為空)放到common
項目裡面,那麼怎麼把這些通用錯誤信息配置成I8n
呢?
❝按照上面所說,我們把
❞common
項目打成jar
包供其他業務服務使用,那麼當其他服務引入common
依賴以後,common
就和業務服務同處於一個Spring
容器,這時候上面的I8n
配置就無法讀取到common
裡面的I8n
配置了(上面講過了SpringBoot
預設讀取的是項目classpath/resource
下的配置文件)。因此我們需要自定義一個MessageSource
然後讀取common
下的I8n
配置就可以了。
首先,我們在 common
的resource
下創建I8n
配置文件,方法和上面一樣,因為和業務服務同處一個Spring
容器,所以我們需要將資源名稱區分開,我們暫且就叫common_messages
, 如下圖所示:
然後,我們配置一個自定義 MessageSource
Bean
,並且讀取我們設置的common_messages
@Bean(name = "commonMessageSource")
public ResourceBundleMessageSource resourceBundleMessageSource() throws IOException {
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
source.setDefaultEncoding(StandardCharsets.UTF_8.displayName());
source.setBasename("common_messages");
return source;
}
最後,調整 I8nUtil
邏輯,先讀取業務服務自己的I8n
,如果沒有再從common
I8n
獲取,如果還沒有則返回原code
public class I18nUtil {
public static String getI18nMessage(String code) {
try {
// SpringBoot提供有一個MessageSource的預設實現
MessageSource messageSource = SpringUtils.getBean("messageSource");
// 從SpringBoot中獲取請求上下文 語言
Locale locale = LocaleContextHolder.getLocale();
// 因為我項目只有中文和英文,所以判斷一下除了指定中文,否則預設使用英文
// 這裡對簡體中文的定義,Locale[] SIMPLIFIED_CHINESE = {Locale.CHINESE, Locale.CHINA, Locale.SIMPLIFIED_CHINESE, Locale.PRC};
if (Arrays.stream(LocaleUtils.SIMPLIFIED_CHINESE).toList().contains(locale)) {
locale = Locale.SIMPLIFIED_CHINESE;
} else {
locale = Locale.US;
}
try{
// 先讀取業務服務自己配置的I8n
return messageSource.getMessage(code, null, locale);
}catch (NoSuchMessageException e) {
// 如果沒有獲取到,再從common裡面讀取I18n
ResourceBundleMessageSource commonMessageSource = SpringUtils.getBean("commonMessageSource");
return commonMessageSource.getMessage(code, null, locale);
}
} catch (Exception e) {
log.error("獲取國際化內容異常", e);
// 如果獲取國際化信息失敗就返回原內容
return code;
}
}
}
本文使用 markdown.com.cn 排版