Chuyển đến nội dung

API i18n

Đường dẫn import: @sdcorejs/nestjs/i18n

Package i18n bản địa hóa các envelope apiError của thư viện. Package cung cấp catalog tiếng Anh và tiếng Việt, resolver Accept-Language, resolver template đơn giản và global exception filter tùy chọn.

Các export

ExportLoạiMục đích
MessageCatalog, CatalogstypeÁnh xạ code -> templatelanguage -> catalog
II18nResolverinterfaceContract translate(code, rawLang, data?)
ILanguageResolverinterfaceContract resolve(raw): locale
I18N_RESOLVER, LANGUAGE_RESOLVERvalueDI token
LanguageResolverOptionsinterfaceCác ngôn ngữ được hỗ trợ và fallback
DefaultLanguageResolverclassParser Accept-Language có trọng số
SimpleI18nOptionsinterfaceCatalog, fallback và language resolver tùy chọn
SimpleI18nResolverclassTra cứu catalog và nội suy {var}
CORE_CATALOG_EN, CORE_CATALOG_VI, CORE_CATALOGSvalueThông báo tích hợp của thư viện
SdI18nExceptionFilterclassBản địa hóa body HttpException dạng apiError
I18nModule, I18nModuleOptionsclass/typeProvider global và APP_FILTER tùy chọn

Cấu hình module

ts
I18nModule.forRoot({
  supportedLanguages: ['en', 'vi'],
  fallbackLanguage: 'en',
  catalogs: {
    en: { 'catalog.product.not-found': 'Product {id} was not found' },
    vi: { 'catalog.product.not-found': 'Không tìm thấy sản phẩm {id}' },
  },
});
OptionMặc địnhHành vi
catalogs{}Shallow-merge theo từng ngôn ngữ trên message core.* tích hợp; consumer được ưu tiên
supportedLanguages['en', 'vi']Các mã locale cơ sở được resolver mặc định chấp nhận
fallbackLanguage'en'Locale và catalog fallback
resolverSimpleI18nResolverLớp DI tùy chỉnh triển khai II18nResolver
useGlobalFiltertrueĐăng ký SdI18nExceptionFilter làm APP_FILTER

SdCoreModule chỉ nối dây i18n khi có option i18n.

Phân giải ngôn ngữ

ts
const resolver = new DefaultLanguageResolver({
  supported: ['en', 'vi'],
  fallback: 'en',
});

resolver.resolve('fr;q=0.4, vi-VN;q=0.9'); // 'vi'

Resolver tách các tag phân cách bằng dấu phẩy, đọc trọng số q (mặc định 1), sắp xếp giảm dần, chuyển về chữ thường và bỏ region (vi-VN thành vi). Tag không xác định hoặc không hợp lệ sẽ fallback.

Contract dịch

ts
interface II18nResolver {
  translate(
    code: string,
    lang: string | undefined,
    data?: Record<string, unknown>,
  ): string;
}

SimpleI18nResolver tra ngôn ngữ đích, sau đó ngôn ngữ fallback, rồi trả lại stable code. Nó thay placeholder {word} từ data và giữ nguyên placeholder không khớp. Với ICU, pluralization hoặc catalog từ xa, hãy đăng ký một lớp resolver tùy chỉnh.

Hành vi exception filter

ts
throw new NotFoundException(
  apiError('catalog.product.not-found', 'Product not found', { id }),
);

Khi bật filter, HTTP response trở thành:

json
{
  "error": {
    "code": "catalog.product.not-found",
    "message": "Không tìm thấy sản phẩm 123",
    "data": { "id": "123" }
  }
}

Header thô ContextService.lang được truyền vào resolver. Các validation issue được bản địa hóa riêng lẻ bằng cách dùng message làm code và params làm dữ liệu nội suy. Response không phải apiError của HttpException được giữ nguyên. Khi không có resolver, code và message mặc định được giữ nguyên.

Chỉ đặt useGlobalFilter: false khi bạn tự đăng ký SdI18nExceptionFilter hoặc có application filter duy trì cùng error contract.

Lưu ý bảo mật

  • Coi nội dung catalog là phần trình bày, không phải logic phân quyền. Client phải rẽ nhánh theo code ổn định, không bao giờ theo message đã dịch.
  • Giữ dữ liệu nội suy có giới hạn và không nhạy cảm; filter giữ lại dữ liệu đó trong response.
  • ContextService.lang là đầu vào không tin cậy. Resolver tùy chỉnh phải chuẩn hóa nó trước khi tra cứu filesystem, network hoặc dynamic-module.

Phát hành theo giấy phép MIT.