SuperAPI AI Directory

i18n-backend

Coding & development

View repository

Updated 10-15 20:31

About this skill

i18n Backend

The API contract is stable in codes. Human text follows the locale of the request or the user. UI: i18n-frontend / i18n-mobile. Contracts: api-design.

Non-negotiable rules

  • code machine-readable (ORDER_NOT_FOUND). message optionally already localized or omitted — the client translates the code. Do not change the code per language.
  • Locale: authenticated user profile > explicit query/header (lang, X-Locale) > Accept-Language > default. Never geo-IP as the sole source.
  • Parse Accept-Language with q-values and fallback (pt-BR → pt → en).
  • Dates in the API: ISO-8601 / epoch. Calendar formatting stays on the client, except for PDF/email generated on the server.
  • Catalogs versioned in the repo (locales/en.json, .ftl, .resx). No ad hoc translation SQL in a feature.
  • Logs and metrics in stable English/technical. Do not localize slog/ILogger for ops.
  • Plurals/ICU on the server only when the server generates text (email, PDF, push).

HTTP

Accept-Language: pt-BR, pt;q=0.8, en;q=0.5
X-Locale: pt-BR
  • Document which header wins. Locale cookie only if the web product already uses it.
  • Content-Language in the response when the body is localized text.
  • Validation: field messages via catalog or codes (validation.email).
  • gRPC: locale in metadata (x-locale); grpc.

What the server translates

Translate on the backend Let the client translate
Email, SMS, push Mobile/web app JSON
PDF / CSV for humans code of API error
Server-side reports UI labels

If the API is only for your app, prefer codes + i18n on the client. If it is public for third parties, message in the requested locale.

Go

  • nicksnyder/go-i18n (or the repo's lib). JSON/TOML bundle per locale.
  • Gin middleware: parse locale → c.Set("locale", tag) → localizer.MustLocalize.
  • golang.org/x/text/language for match. Email templates: pass localizer, do not concatenate.

APIs: golang-apis.

accept := c.GetHeader("Accept-Language")
tag, _ := language.MatchStrings(matcher, accept)
msg := localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "order.not_found"})

Rust

  • Fluent (fluent-templates / i18n-embed) for rich text; rust-i18n if the crate already uses it.
  • Locale in the Extension / Axum extractor. .ftl files per language.
  • unic-langid. Do not format dates with format! without locale.

HTTP: axum. Desktop egui: load Fluent in the App and resolve in the update — do not hardcode menu labels.

C# / ASP.NET Core

  • IStringLocalizer<T> / IViewLocalizer. Resources .resx or JSON providers.
  • RequestLocalizationOptions: SetDefaultCulture, AddSupportedCultures, providers (QueryString, Cookie, AcceptLanguageHeader).
  • ProblemDetails: title localized if the API is for humans; type/code stable.
  • CultureInfo in the request (RequestCulture). CultureInfo.InvariantCulture for persistence/ISO parse.

Host: aspnet-core.

NestJS / TypeScript

  • nestjs-i18n (or equivalent). I18nContext / I18nService. JSON per locale in i18n/.
  • Resolver: header → query → cookie. Fallback to config.
  • Exception filter: maps code → i18n.t('errors.' + code).
  • DTOs: messages from class-validator via i18nValidationMessage.

HTTP: nestjs-apis.

Email and jobs

  • Asynchronous job: store the locale in the payload (the user's). Do not use the worker's locale.
  • Templates: react-email with a dictionary for the same locale. lang in the HTML.
  • Unsubscribe / legal: account language.

Anti-patterns

  • message: err.Error() in pt or en depending on the pod
  • Translate code
  • Concatenate sentences in the service ("Order " + id + " not found" for the user)
  • time.Format("02/01/2006") without locale in email
  • A map[string]map[string]string giant in the handler
  • Accept only lang=pt and break pt-BR

Integration with other skills

  • Contracts: api-design (code + message)
  • Go: golang-apis
  • Rust HTTP: axum
  • C#: aspnet-core
  • Nest: nestjs-apis
  • Clients: i18n-frontend / i18n-mobile
  • Email: react-email
  • gRPC metadata: grpc

Definition of done

  • Locale resolved in the documented order
  • Errors with code stable; human text via catalog or client
  • Catalogs in the repo; ICU/plural where the server generates prose
  • Jobs/emails with persisted locale
  • ISO dates in the JSON API