Skip to content

Internationalised errors

Producers across the library throw i18n codes, not sentences:

ts
import { apiError } from '@sdcorejs/nestjs/core';
throw new BadRequestException(apiError('core.validation.failed', 'Validation failed', { issues }));

@sdcorejs/nestjs/i18n closes the loop end-to-end:

  • SdI18nExceptionFilter — catches HttpExceptions carrying an apiError body, localizes message via the resolver using the request's ctx.lang, emits the { error: { code, message, data } } envelope. code is preserved for client-side handling.
  • SimpleI18nResolver — catalog lookup catalogs[lang][code] → catalogs[fallback][code] → code, with {var} interpolation from data (+ Zod issue params). For ICU / plurals, implement a custom II18nResolver.
  • DefaultLanguageResolver — parses the raw Accept-Language header (vi-VN,vi;q=0.9,en;q=0.8) to a supported base code, q-sorted, with fallback.
  • Built-in catalogs — en + vi messages for every core.* code the library throws, shipped in CORE_CATALOGS. Merge your app's catalog over them.

Enable via the i18n key (opt-in — omit to leave envelopes untranslated):

ts
SdCoreModule.forRoot({
  i18n: {
    fallbackLanguage: 'vi',
    supportedLanguages: ['en', 'vi'],
    catalogs: {                      // merged OVER built-in core.* (consumer wins)
      vi: { 'app.product.name.min': 'Tên phải có ít nhất {minimum} ký tự' },
    },
    // resolver: MyIcuResolver,       // optional: replace SimpleI18nResolver entirely
    // useGlobalFilter: false,        // optional: skip the global APP_FILTER
  },
});

ApiResponse.ok(data) / ApiResponse.noContent() wrap successful responses.

Released under the MIT License.