Skip to content

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 ​

xml
<dependency>
    <groupId>io.github.weihubeats</groupId>
    <artifactId>spring-boot-nebula-i18n</artifactId>
    <version>3.0.6</version>
</dependency>

Quick Start ​

1. Configuration ​

yaml
nebula:
  i18n:
    default-locale: zh_CN
    basename: i18n/messages
    supported-locales:
      - zh_CN
      - en_US
    header-name: X-Lang
    param-name: lang

2. Resource Files ​

Place them under src/main/resources/i18n/ (the basename maps to the path):

i18n/messages_zh_CN.properties

properties
result_code.param_miss=缺少必要的请求参数
greeting=你好,{0}!

i18n/messages_en_US.properties

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.

http
### 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_US

The 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:

PriorityMethodDescription
1Explicit getMessageKey()Override when implementing IErrorCode for fully manual control
2@NebulaMessageKey annotationPlaced on an enum constant for manual specification
3Auto-generatedsnake_case class name . snake_case constant name

Auto-generation rule: ResultCode.PARAM_MISS → result_code.param_miss — zero configuration needed.

java
@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 ResultCode already supports internationalization; message serves as the fallback text when no translation is found.

Fetching Messages in Business Code ​

Fetch the message for the current request language from anywhere:

java
// 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) translates msg per the request language before writing it
  • NebulaRestExceptionHandler translates 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) ​

yaml
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=off

Loaded 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:

java
@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 message

Remote can provide new keys absent locally, and also override local keys with the same name.

Configuration Options ​

OptionDefaultDescription
nebula.i18n.enabledtrueModule switch
nebula.i18n.default-localezh_CNDefault language
nebula.i18n.basenamei18n/messagesLocal resource basename
nebula.i18n.supported-locales[zh_CN, en_US]Supported languages (used for remote loading and validation)
nebula.i18n.header-nameX-LangCustom language header; empty to disable
nebula.i18n.param-namelangQuery language parameter; empty to disable
nebula.i18n.prefer-accept-languagefalseWhether Accept-Language takes precedence over the custom header/param
nebula.i18n.fallback-to-defaulttrueWhether to fall back to the system language on miss
nebula.i18n.remote.enabledfalseEnable remote loading
nebula.i18n.remote.url-template-Remote URL template, supports {basename}/{locale}
nebula.i18n.remote.refresh-interval-seconds0Periodic refresh interval, 0 disables
nebula.i18n.remote.timeout-seconds5Remote 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.

Released under the Apache 2.0 License.