npm.io
2.0.0 • Published 1 week ago

mapa-frontend-i18n

Licence
Version
2.0.0
Deps
1
Size
1.9 MB
Vulns
0
Weekly
0

mapa-frontend-i18n

Biblioteca Angular de internacionalização (i18n) construída sobre @angular/localize. Fornece os catálogos de tradução do produto MAPA (pt-BR, en, es) e funções para inicializar o idioma da aplicação.

A partir da 2.0, as traduções podem ser carregadas de arquivos JSON hospedados na AWS (S3/CloudFront), permitindo corrigir termos e acentuação sem republicar a lib nem fazer redeploy das aplicações. Os catálogos embutidos continuam no pacote como fallback.

Compatibilidade: a 2.0 é aditiva — a API síncrona da 1.x (initializeAppLanguage, getMapaUiTexts, tipos e catálogos) continua igual. O carregamento remoto é opt-in via initializeAppLanguageAsync. O major marca a mudança de arquitetura (traduções podem vir da rede), não uma quebra de API.


Sumário


Instalação

npm install mapa-frontend-i18n

peerDependency: @angular/localize ~20.3.0 (já presente nas aplicações MAPA).


Como funciona

  • As traduções são um mapa achatado { "chave.do.localize": "texto" }, injetado no @angular/localize via loadTranslations().
  • O $localize resolve cada mensagem no momento em que ela é avaliada, usando o mapa global. Por isso, as traduções precisam ser carregadas antes do bootstrapApplication() — caso contrário a tela aparece com o texto-fonte (pt-BR) ou com as chaves cruas.
  • O carregamento remoto faz o merge { ...embutido, ...remoto }: o remoto sobrescreve o embutido, e qualquer chave ausente no remoto ainda resolve pelo embutido. Ou seja, arquivos remotos parciais são seguros.

Inicialização

Modo 1 — Embutido (síncrono)

Usa apenas os catálogos embutidos no pacote. É o comportamento clássico, sem rede.

import { initializeAppLanguage } from "mapa-frontend-i18n";

initializeAppLanguage(); // lê o idioma do localStorage e carrega o embutido
Modo 2 — Remoto com fallback (recomendado)

Carrega da AWS, com cache local e fallback automático para o embutido. Deve ser aguardado antes do bootstrap.

// main.ts
import { bootstrapApplication } from "@angular/platform-browser";
import { initializeAppLanguageAsync } from "mapa-frontend-i18n";
import { AppComponent } from "./app/app.component";
import { appConfig } from "./app/app.config";
import { environment } from "./environments/environment";

initializeAppLanguageAsync({ baseUrl: environment.i18nBaseUrl })
  .catch(() => undefined) // nunca lança; em falha já usa o fallback embutido
  .then(() => bootstrapApplication(AppComponent, appConfig));

environment.i18nBaseUrl aponta para a pasta que contém os JSON por idioma, por ambiente (dev/staging/prod). Ex.: https://cdn.mapa.com.br/i18n.

Modo 3 — Host distribui aos MFEs

Em micro-frontends, o host busca as traduções uma única vez e as repassa para cada MFE, evitando um request por MFE. Use quando cada MFE roda em um contexto de @angular/localize próprio.

// no host (antes do bootstrap):
import { getStoredAppLanguage, loadRemoteTranslations } from "mapa-frontend-i18n";

const language = getStoredAppLanguage();
const remote = await loadRemoteTranslations(language, {
  baseUrl: environment.i18nBaseUrl,
});
// disponibilize `language` + `remote` para os MFEs (window, store compartilhado, etc.)
// em cada MFE (antes do seu bootstrap):
import { initializeAppLanguageFromData } from "mapa-frontend-i18n";

initializeAppLanguageFromData(language, remote ?? {});

Se os MFEs compartilham o mesmo @angular/localize (singleton via module federation), basta o host chamar initializeAppLanguageAsync uma vez.


Opções de carregamento remoto

RemoteTranslationOptions (usado por initializeAppLanguageAsync e loadRemoteTranslations):

Opção Tipo Padrão Descrição
baseUrl string — (obrigatório) URL base dos JSON, sem barra final. Busca ${baseUrl}/${idioma}.json.
version string undefined Tag de versão (?v=) para cache-busting manual (requer CloudFront com query string na chave de cache).
timeoutMs number 5000 Aborta o request após esse tempo (o boot não trava se a AWS demorar).
fetchImpl typeof fetch globalThis.fetch fetch customizado (testes/SSR).
onError (error: unknown) => void undefined Notificação de erro de fetch/parse (não-fatal; o fallback é usado).

Cache e revalidação

Estratégia stale-while-revalidate:

  • Cache em localStorage, chave i18n.cache.<idioma> (apenas o idioma ativo).
  • 1º acesso: aguarda o fetch; em falha, usa o embutido.
  • Acessos seguintes: aplica o cache na hora (boot instantâneo) e revalida em segundo plano. Se o conteúdo mudou, o cache é atualizado e a nova versão entra no próximo reload.

O request é um GET simples (sem cabeçalhos customizados) com cache: "no-cache": a revalidação contra o CDN é feita pelo próprio browser via ETag/Last-Modified, de forma transparente. Isso evita preflight CORS — o servidor só precisa do cabeçalho Access-Control-Allow-Origin.

Cadeia de fallback em qualquer falha: cache → catálogo embutido (nunca a chave crua).


Arquivos de tradução na AWS

Um arquivo JSON por idioma, contendo o mapa achatado já mesclado de todos os módulos:

${baseUrl}/pt-BR.json
${baseUrl}/en.json
${baseUrl}/es.json

Formato (mesmo shape consumido pelo loadTranslations()):

{
  "common.cancel": "Cancelar",
  "common.close": "Fechar",
  "home.title": "Painel"
}

Gerar/atualizar os JSON

O script de export gera os arquivos a partir dos catálogos embutidos. Use para semear o conteúdo inicial na AWS e para manter o fallback embutido sincronizado a cada release.

npm run export:i18n
# escreve dist/i18n-remote/{pt-BR,en,es}.json

Processo de hotfix de termo (sem republicar)

  1. Edite o termo/acentuação diretamente no JSON do idioma na AWS (ou ajuste só as chaves alteradas — arquivos parciais são suportados).
  2. Faça upload para o S3.
  3. Invalide o cache do CloudFront ou confie no ETag + Cache-Control curto (a revalidação aplica a mudança no próximo reload dos usuários).

Nenhuma publicação de versão da lib nem redeploy das aplicações é necessária.

Os catálogos *.ts embutidos seguem como fallback (último-bom-conhecido). Para mantê-los alinhados com a AWS, rode npm run export:i18n periodicamente e publique uma release quando quiser atualizar o fallback.


Requisitos de infraestrutura (AWS)

  • S3 (com ou sem CloudFront) servindo /i18n/{idioma}.json por ambiente.
  • CORS (obrigatório): basta Access-Control-Allow-Origin liberando as origens das aplicações no GET (não há preflight, pois o request é simples). Bucket público não dispensa CORS — sem ele o browser bloqueia a leitura via fetch. Ver config de exemplo em examples/aws/s3-cors.json.
  • ETag (o S3 já envia) para a revalidação condicional do browser funcionar.
  • Propagação de hotfix:
    • S3 direto (sem CDN): a alteração é imediata no próximo reload.
    • Via CloudFront: use Cache-Control curto (ex.: max-age=300) ou invalide o caminho a cada hotfix — senão o edge serve a versão antiga até a TTL padrão (24h).

Outras APIs

import {
  // Idioma
  getStoredAppLanguage,
  persistAppLanguage,
  applyDocumentLanguage,
  getAngularLocale,
  getIntlLocale,
  resolveAppLanguage,
  APP_LANGUAGE_OPTIONS,
  DEFAULT_APP_LANGUAGE,

  // Textos de UI (validações, paginador, etc.)
  getMapaUiTexts,
  applyPaginatorIntl,
} from "mapa-frontend-i18n";

getMapaUiTexts(language) retorna textos de UI reutilizáveis (filtros, tabela, validações). Alguns valores são funções (paginador e validações com interpolação) e permanecem no código da lib — não são externalizados para JSON.


Idiomas suportados

Código Idioma Padrão
pt-BR Português (fonte/fallback)
es Español
en English

O idioma escolhido é persistido em localStorage na chave menu.language.