@nestbolt/translatable
Configuration
Configure @nestbolt/translatable with forRoot and forRootAsync -- default locale, fallback chains, and fallback-any behavior.
The TranslatableModule supports both static (forRoot) and async (forRootAsync) configuration. The module is registered as global, meaning you only need to import it once in your root AppModule.
Static Configuration (forRoot)
Use forRoot when your configuration values are known at compile time:
import { Module } from "@nestjs/common";
import { TranslatableModule } from "@nestbolt/translatable";
@Module({
imports: [
TranslatableModule.forRoot({
defaultLocale: "en",
fallbackLocales: ["en", "fr", "ar"],
fallbackAny: false,
}),
],
})
export class AppModule {}Async Configuration (forRootAsync)
Use forRootAsync when your configuration depends on other providers, such as ConfigService or environment variables:
import { Module } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import { TranslatableModule } from "@nestbolt/translatable";
@Module({
imports: [
ConfigModule.forRoot(),
TranslatableModule.forRootAsync({
imports: [ConfigModule],
useFactory: (config: ConfigService) => ({
defaultLocale: config.get<string>("DEFAULT_LOCALE", "en"),
fallbackLocales: config.get<string>("FALLBACK_LOCALES", "en,fr").split(","),
fallbackAny: config.get<boolean>("FALLBACK_ANY", false),
}),
inject: [ConfigService],
}),
],
})
export class AppModule {}The useFactory function can return either a TranslatableModuleOptions object or a Promise<TranslatableModuleOptions> for async initialization:
TranslatableModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (config: ConfigService) => {
// Async operations are supported
const localeConfig = await fetchLocaleConfigFromRemote();
return {
defaultLocale: localeConfig.default,
fallbackLocales: localeConfig.fallbacks,
};
},
inject: [ConfigService],
});Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
defaultLocale | string | "en" | The default locale used when no locale is explicitly set via middleware or runWithLocale. |
fallbackLocales | string[] | [defaultLocale] | An ordered list of fallback locales. When a translation is missing in the requested locale, the system tries each locale in this list in order. |
fallbackLocale | string | -- | Deprecated. Shorthand for a single fallback locale. Sets fallbackLocales: [value]. Use fallbackLocales instead. |
fallbackAny | boolean | false | When true, if no translation is found in the requested locale or any fallback locale, the system returns the first available translation in any locale. |
Options in Detail
defaultLocale
The defaultLocale is the locale used when no Accept-Language header is present and no locale has been set via TranslatableService.runWithLocale(). It is also the implicit locale for methods like getTranslation and hasTranslation when no locale argument is provided.
TranslatableModule.forRoot({
defaultLocale: "ar",
})With this configuration, calling entity.getTranslation("name") without a locale argument will return the Arabic translation.
fallbackLocales
The fallbackLocales option defines the order in which the system searches for a translation when the requested locale is not available. The system walks the chain from left to right and returns the first match.
TranslatableModule.forRoot({
defaultLocale: "en",
fallbackLocales: ["en", "fr", "ar"],
})With this configuration, if a user requests German (de) and the entity has:
{ fr: "Bonjour", ar: "مرحبا" }The resolution proceeds:
- Check
de-- not found - Check
en(first fallback) -- not found - Check
fr(second fallback) -- found, return"Bonjour"
If fallbackLocales is not provided, it defaults to [defaultLocale].
fallbackAny
When fallbackAny is set to true, the system will return the first available translation in any locale if both the requested locale and all fallback locales are missing. This is a last-resort behavior.
TranslatableModule.forRoot({
defaultLocale: "en",
fallbackLocales: ["en"],
fallbackAny: true,
})With this configuration, if a user requests German (de) and the entity has only a Japanese translation:
{ ja: "ラップトップ" }The resolution proceeds:
- Check
de-- not found - Check
en(fallback) -- not found fallbackAnyistrue-- return first available:"ラップトップ"
Without fallbackAny: true, the result would be null.
Full Locale Resolution Order
When resolving a translation, the system follows this order:
- Requested locale -- The locale from the
Accept-Languageheader, or the locale passed togetTranslation(key, locale). - Fallback chain -- Each locale in
fallbackLocales, tried in order. - Any available locale -- If
fallbackAny: true, the first available translation in any locale. - null -- If no translation is found anywhere.
Module Registration
The module registers the following providers globally:
| Provider | Description |
|---|---|
TranslatableService | Central service for locale management, fallback resolution, and event emission. |
TranslatableSubscriber | TypeORM subscriber that ensures translation maps are properly serialized/deserialized. |
TranslatableInterceptor | Global interceptor that resolves translatable fields in API responses. |
IsTranslationsConstraint | Validation constraint for the @IsTranslations() decorator. |
Because the module is global, all of these providers are available for injection in any module without additional imports.