Internationalization spring-boot-nebula-i18n
An out-of-the-box multi-language response component: it resolves the request language automatically, translates the unified response msg and error-code messages per language, and supports both local resources and remote loading from a config center (HTTP).
Add the Dependency
<dependency>
<groupId>io.github.weihubeats</groupId>
<artifactId>spring-boot-nebula-i18n</artifactId>
<version>3.0.6</version>
</dependency>Quick Start
1. Configuration
nebula:
i18n:
default-locale: zh_CN
basename: i18n/messages
supported-locales:
- zh_CN
- en_US
header-name: X-Lang
param-name: lang2. Resource Files
Place them under src/main/resources/i18n/ (the basename maps to the path):
i18n/messages_zh_CN.properties
result_code.param_miss=缺少必要的请求参数
greeting=你好,{0}!i18n/messages_en_US.properties
result_code.param_miss=Missing required request parameter
greeting=Hello, {0}!3. Request Example
Language resolution priority: X-Lang header → lang query parameter → Accept-Language → default language.
### Chinese (default)
GET localhost:8091/i18n/error
### English - X-Lang header
GET localhost:8091/i18n/error
X-Lang: en_US
### English - lang query parameter
GET localhost:8091/i18n/error?lang=en_USThe framework resolves the language and writes it into LocaleContextHolder; NebulaResponse.msg and the global exception handler output are translated accordingly.
Message Keys: Three Ways to Specify
Error-code messages are looked up by key; the final key is resolved by the following priority:
| Priority | Method | Description |
|---|---|---|
| 1 | Explicit getMessageKey() | Override when implementing IErrorCode for fully manual control |
| 2 | @NebulaMessageKey annotation | Placed on an enum constant for manual specification |
| 3 | Auto-generated | snake_case class name . snake_case constant name |
Auto-generation rule: ResultCode.PARAM_MISS → result_code.param_miss — zero configuration needed.
@Getter
@AllArgsConstructor
public enum SampleErrorCode implements IErrorCode {
// Key specified manually via annotation
@NebulaMessageKey("order.not_found")
ORDER_NOT_FOUND(40001, "订单不存在"),
// Not annotated; auto-generates sample_error_code.stock_not_enough
STOCK_NOT_ENOUGH(40002, "库存不足");
private final int code;
private final String message;
}The built-in
ResultCodealready supports internationalization;messageserves as the fallback text when no translation is found.
Fetching Messages in Business Code
Fetch the message for the current request language from anywhere:
// By the current request language (LocaleContextHolder)
String msg = NebulaI18nMessage.get("greeting", name);
// Explicit language / explicit fallback
String msg = NebulaI18nMessage.getOrDefault("greeting", args, "Hello", locale);It falls back safely when no MessageSource is configured or the key is missing — no exceptions thrown.
Integration with the Web Module
Takes effect automatically once spring-boot-nebula-web is on the classpath:
NebulaResponse.fail(IErrorCode)translatesmsgper the request language before writing itNebulaRestExceptionHandlertranslates all exception response messages automatically- Without the i18n module, behavior is unchanged (falls back to the default
message) — existing callers are not affected
Remote Message Loading
Messages can be pulled from a remote config center, with local resources as fallback; remote entries take precedence and override.
Option 1: HTTP Fetching (Built-in)
nebula:
i18n:
remote:
enabled: true
# {basename} and {locale} placeholders
url-template: "http://config.xxx/i18n/{basename}_{locale}.properties"
refresh-interval-seconds: 300 # Periodic refresh, 0=offLoaded automatically at startup, then refreshed at the configured interval; when a key is missing remotely, resolution falls through to local resources automatically.
Option 2: Custom SPI Implementation
Register a custom RemoteMessageLoader bean to replace the built-in HTTP implementation and integrate any config center such as Nacos / Apollo:
@Bean
public RemoteMessageLoader myRemoteMessageLoader() {
return () -> {
Map<Locale, Properties> map = new HashMap<>();
// Pull messages from the config center into map
return map;
};
}Remote vs Local
Remote (first) → Local resources (fallback) → Default messageRemote can provide new keys absent locally, and also override local keys with the same name.
Configuration Options
| Option | Default | Description |
|---|---|---|
nebula.i18n.enabled | true | Module switch |
nebula.i18n.default-locale | zh_CN | Default language |
nebula.i18n.basename | i18n/messages | Local resource basename |
nebula.i18n.supported-locales | [zh_CN, en_US] | Supported languages (used for remote loading and validation) |
nebula.i18n.header-name | X-Lang | Custom language header; empty to disable |
nebula.i18n.param-name | lang | Query language parameter; empty to disable |
nebula.i18n.prefer-accept-language | false | Whether Accept-Language takes precedence over the custom header/param |
nebula.i18n.fallback-to-default | true | Whether to fall back to the system language on miss |
nebula.i18n.remote.enabled | false | Enable remote loading |
nebula.i18n.remote.url-template | - | Remote URL template, supports {basename}/{locale} |
nebula.i18n.remote.refresh-interval-seconds | 0 | Periodic refresh interval, 0 disables |
nebula.i18n.remote.timeout-seconds | 5 | Remote request timeout |
Full Example
See spring-boot-nebula-i18n-sample: it ships with a mock remote config service demonstrating remote loading, annotation keys, auto keys, and all NebulaI18nMessage scenarios.