Featured image of post 如何在SpringBoot中實現基礎的I18n

如何在SpringBoot中實現基礎的I18n

快樂的薪水小偷

專案中i18n之實現

i18n全名internationalization,因為中間的字母有18個,於是就用i18n來稱呼它。所謂的i18n就是根據不同的語系會有不同的Message回傳,比如說臺灣人在登入失敗時會出現「登入失敗」,美國人在登入時會出現「Login Fail」,這種因應不同地區的使用者來客製化訊息的工作,就是i18n。

涉及到的基本知識

ResourceBundle

想要做到i18n,最重要的就是地區(Locale)的資料,地區資料有兩個部分組成,分別是語言編碼ISO 639加上區域編碼ISO3166,比如說

  • en_US:英文_美國
  • en-AU:英文_澳洲
  • en-HK :英文_香港

等等的,詳細資訊可以查看http://www.i18nguy.com/unicode/language-identifiers.html

而在Java中,想要實現這樣的功能就會涉及到ResouceBundle

image-20231011110511503

這個類可以用來將程式中的文本,與程式碼分離出來,而不是寫死在程式中,具體可以來看下面的Code。

Java中如何實現i18n

首先先開一個新的Java Maven專案,並在resources的資料夾底下建立兩個檔案

  1. messages_en_US.properties
  2. messages_zh_TW.properties

image-20231011111140222

再來到我們的Main方法中,先創建出一個Locale物件

1
2
3
4
5
public class Main {
    public static void main(String[] args) {
        Locale locale = new Locale("zh", "TW");
    }
}

可以看出是Language跟Country參數

image-20231011111558995

接著創造ResourceBundle物件,其中messages就是我們properties檔案的base name,讓程式知道哪些properties是i18n的文本

1
2
3
4
5
6
public class Main {
    public static void main(String[] args) {
        Locale locale = new Locale("zh", "TW");
        ResourceBundle resourceBundle = ResourceBundle.getBundle("messages",locale);
    }
}

image-20231011111954460

接著我們可以用getString 的方式來取得properties中的值

iShot_2023-10-11_11.21.12

只要改變Locale的參數,我們就可以去調整打印出來的內容,比如說現在將Locale改成en_US

iShot_2023-10-11_11.23.36

這樣就是最基礎的,在Java中實現i18n的方法

在SpringBoot中如何實現i18n(基礎)

首先先創造一個SpringBoot專案,接著到application.yml中配置一些基礎資訊

1
2
3
4
5
spring:
  messages:
    basename: i18n/messages
    encoding: UTF-8

其中basename就和上面的Java Basename一樣,都是在指定我們的i18配置檔是放在什麼地方,以這個basename為例,就代表放在resources/i18n底下

image-20231011113215740

設置好後,就到resources/i18n資料夾中,配置i18n相關的檔案

[{0}]代表的是格式化訊息的占位符

image-20231011114926863

然後配置一個controller,並加入MessageSource的Bean

MessageSource 是 Spring Framework 提供的一個介面,用於支援應用程式的國際化(Internationalization)和本地化(Localization)。它提供了一種在應用程式中輕鬆管理文本訊息的機制,以便根據使用者的語言和地區首選項來提供相應的文本訊息。

MessageSource 介面的主要功能包括:

  1. 文本訊息檢索: MessageSource 允許您在應用程式中定義和存儲文本訊息,通常以鍵值對的形式。這些文本訊息可以是應用程式中的各種提示、標籤、錯誤訊息等。
  2. 國際化支援: 您可以配置不同語言和地區的訊息,以便根據使用者的首選語言和地區設定來動態選擇合適的訊息。這使得應用程式能夠以多語言和本地化方式呈現訊息。
  3. 參數替換: MessageSource 支援將參數插入訊息中,以便將動態值嵌入到訊息中。這對於包含佔位符的訊息非常有用。
  4. 訊息格式化: 您可以定義訊息的格式,以適應不同的訊息類型,如日期、時間、貨幣等。

MessageSource 介面的常見實現是 ResourceBundleMessageSource,它使用 Java 的 ResourceBundle 機制來存儲和檢索訊息。但 Spring 也提供其他實現,如 ReloadableResourceBundleMessageSource,允許在不重啟應用程式的情況下重新加載訊息資源。

使用 MessageSource 的主要步驟包括:

  1. 配置 MessageSource Bean,通常在 Spring 配置文件中或 Java 配置類中完成。
  2. 在應用程式中使用 MessageSourcegetMessage 方法來檢索訊息,指定訊息的鍵和可選參數。
  3. 根據使用者的語言和地區首選項,MessageSource 會動態地返回適當的訊息。

總之,MessageSource 是 Spring Framework 中的一個重要元件,用於實現國際化和本地化,幫助開發者構建多語言和多地區支援的應用程式,提高使用者體驗。

–Generate By ChatGPT

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@RestController
@RequiredArgsConstructor
public class DemoController {

    private final MessageSource messageSource;


    @GetMapping("/")
    public ResponseEntity<String> demo() {
        String message = messageSource.getMessage("error", new String[]{"發生錯誤"}, Locale.TAIWAN);
        System.out.println(message);
        return ResponseEntity.ok().body("Hello");
    }
}

iShot_2023-10-11_11.46.41

可以看出MessageSource,依照我們配置的Locale去i18n底下找到對應的文本,並且打印出來。我們可以修改Locale的值來改變打印出來的文本

iShot_2023-10-11_11.54.27

想當然耳,我們不可能是把i18n的配置寫死,所以可以用 LocaleContextHolder.getLocale()來取得目前使用者的語言來動態注入Locale資料

1
2
3
4
5
6
@GetMapping("/")
    public ResponseEntity<String> demo() {
        String message = messageSource.getMessage("error", new String[]{"發生錯誤"},  LocaleContextHolder.getLocale());
        System.out.println(message);
        return ResponseEntity.ok().body("Hello");
    }

這部分動態注入的方式,實際實現可以有很多種方式,比如說Interceptor、Filter作轉換,然後用AOP的方式轉換,都是可以行的方案。

Licensed under CC BY-NC-SA 4.0