Solon 採取不同的做法。整個 i18n 模組圍繞三種解析器、一個註解和一個工具類別建構而成——無需 XML、無需攔截器註冊、無需樣板配置。
讓我逐步說明其運作方式。
資源約定
將訊息檔案放置於 resources/i18n/ 目錄下:
resources/i18n/messages.properties # 預設(例如中文)
resources/i18n/messages_en_US.properties # 美式英文
resources/i18n/messages_ja_JP.properties # 日文
Enter fullscreen mode Exit fullscreen mode
檔案格式為標準 Java properties:
# messages_en_US.properties
login.title=Sign In
login.welcome=Welcome, {0}!
app.name=Solon Application
Enter fullscreen mode Exit fullscreen mode
就是這樣。無需 bean 宣告、無需位置配置。Solon 會自動發現它們。
三種語系解析器,一行切換
Solon 內建三種語系解析器。預設為標頭式,但您只需一行程式碼即可切換。
1. 標頭解析器(預設)
讀取 Content-Language 標頭,若無則退回 Accept-Language:
# app.yml — 無需配置,開箱即用
Enter fullscreen mode Exit fullscreen mode
自訂標頭名稱:
@Configuration
public class I18nConfig {
@Bean
public LocaleResolver localeInit() {
LocaleResolverHeader resolver = new LocaleResolverHeader();
resolver.setHeaderName("lang"); // 現在讀取 "lang" 標頭
return resolver;
}
}
Enter fullscreen mode Exit fullscreen mode
2. Cookie 解析器
預設從名為 SOLON.LOCALE 的 cookie 讀取語系:
@Configuration
public class I18nConfig {
@Bean
public LocaleResolver localeInit() {
return new LocaleResolverCookie();
}
}
Enter fullscreen mode Exit fullscreen mode
自訂 cookie 名稱:
resolver.setCookieName("lang");
Enter fullscreen mode Exit fullscreen mode
3. Session 解析器
從 session 屬性讀取語系:
@Configuration
public class I18nConfig {
@Bean
public LocaleResolver localeInit() {
return new LocaleResolverSession();
}
}
Enter fullscreen mode Exit fullscreen mode
自訂屬性名稱:
resolver.setAttrName("lang");
Enter fullscreen mode Exit fullscreen mode
4. 自訂解析器
若三種解析器皆不適用,可直接實作 LocaleResolver:
@Component
public class QueryParamResolver implements LocaleResolver {
@Override
public Locale getLocale(Context ctx) {
String lang = ctx.param("lang");
if (lang != null) {
return LocaleUtil.toLocale(lang);
}
return Locale.getDefault();
}
@Override
public void setLocale(Context ctx, Locale locale) {
ctx.setLocale(locale);
}
}
Enter fullscreen mode Exit fullscreen mode
三種讀取訊息的方式
1. I18nUtil — 快速存取
靜態方法適用於任何地方的單次查詢:
// 從目前請求情境(自動解析語系)
String title = I18nUtil.getMessage("login.title");
// 使用特定 Locale
String welcome = I18nUtil.getMessage(locale, "login.welcome", "Alice");
// 使用 Context 物件
I18nUtil.getMessage(ctx, "app.name");
Enter fullscreen mode Exit fullscreen mode
2. I18nService — 命名 Bundle 存取
當您需要從特定 bundle 讀取訊息時:
I18nService loginI18n = new I18nService("i18n.login");
@Mapping("/greet")
public String greet(Locale locale) {
return loginI18n.get(locale, "login.welcome", "Alice");
}
Enter fullscreen mode Exit fullscreen mode
3. I18nBundle — 程式化 Bundle
進階用法,取得原始 bundle:
I18nBundle bundle = I18nUtil.getBundle("i18n.messages", locale);
String value = bundle.get("login.title");
String formatted = bundle.getAndFormat("login.welcome", "Alice");
Enter fullscreen mode Exit fullscreen mode
@I18n — 模板整合
在控制器上加上 @I18n,每個模板都會獲得 i18n 變數:
@I18n("i18n.login")
@Controller
public class LoginController {
@Mapping("/login")
public ModelAndView login() {
return new ModelAndView("login.ftl");
}
}
Enter fullscreen mode Exit fullscreen mode
若未指定 bundle 名稱,預設為 i18n.messages。
模板語法範例
Freemarker(login.ftl):
<h1>${i18n["login.title"]}</h1>
<p>${i18n.getAndFormat("login.welcome", session.user.name)}</p>
Enter fullscreen mode Exit fullscreen mode
Thymeleaf:
<h1 th:text="${i18n.get('login.title')}">Sign In</h1>
<p th:text="${i18n.getAndFormat('login.welcome', 'Alice')}">Welcome!</p>
Enter fullscreen mode Exit fullscreen mode
Beetl:
<h1>${i18n["login.title"]}</h1>
<p>${@i18n.getAndFormat("login.welcome", "Alice")}</p>
Enter fullscreen mode Exit fullscreen mode
Enjoy:
<h1>#(i18n.get("login.title"))</h1>
<p>#(i18n.getAndFormat("login.welcome", "Alice"))</p>
Enter fullscreen mode Exit fullscreen mode
延伸至分散式環境
對於將翻譯管理於配置中心或 CMS 的團隊,可實作 I18nBundleFactory:
@Component
public class RemoteBundleFactory implements I18nBundleFactory {
@Override
public I18nBundle create(String bundleName, Locale locale) {
// 從遠端配置中心取得
Props props = getRemoteProps(bundleName, locale);
return new I18nBundleImpl(props, locale);
}
}
Enter fullscreen mode Exit fullscreen mode
註冊它:
I18nUtil.setBundleFactory(new RemoteBundleFactory());
Enter fullscreen mode Exit fullscreen mode
Solon 內建的 I18nBundleFactoryLocal 從 resources/i18n/ 讀取;工廠模式允許您在不修改應用程式程式碼的情況下,切換至 Redis、Nacos 或任何其他來源。
最小依賴
solon-i18n 模組除了 solon-core 之外,沒有任何傳遞依賴。若您使用 solon-web,則已包含此模組。
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-i18n</artifactId>
</dependency>
Enter fullscreen mode Exit fullscreen mode
權衡取捨
您無法獲得:
- 無
MessageSource風格的層級結構(Solon 對每個名稱使用扁平化 bundle) - 無開發模式自動重新載入(需重啟以取得變更,或實作支援熱重載的自訂
I18nBundleFactory) - 無內建語言切換端點(故意留給解析器處理——透過查詢參數切換需自訂
LocaleResolver)
您可獲得:
- 不到 60 秒即可運作的 i18n
- 三種可立即上線的解析器策略
- 跨 5 種引擎的一流模板整合
- 適用於分散式配置的可延伸工廠模式
- 零 XML、零攔截器、零繁瑣設定
摘要
Solon 的 i18n 模型遵循框架理念:慣例優於配置,但需要時可切換。一個依賴、一個模板註解、一個程式化存取工具,以及三個即插即用的解析器,涵蓋絕大多數真實情境。
若您曾為 MessageSource 配置苦惱,不妨試試看——體驗將令人驚艷。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.