mapa-frontend-i18n 1.3.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,264 @@
1
+ # mapa-frontend-i18n
2
+
3
+ Biblioteca Angular de internacionalização (i18n) construída sobre
4
+ [`@angular/localize`](https://angular.dev/guide/i18n). Fornece os catálogos de
5
+ tradução do produto MAPA (pt-BR, en, es) e funções para inicializar o idioma da
6
+ aplicação.
7
+
8
+ A partir da **2.0**, as traduções podem ser carregadas de **arquivos JSON
9
+ hospedados na AWS (S3/CloudFront)**, permitindo corrigir termos e acentuação
10
+ **sem republicar a lib nem fazer redeploy das aplicações**. Os catálogos
11
+ embutidos continuam no pacote como _fallback_.
12
+
13
+ > **Compatibilidade:** a 2.0 é aditiva — a API síncrona da 1.x
14
+ > (`initializeAppLanguage`, `getMapaUiTexts`, tipos e catálogos) continua igual.
15
+ > O carregamento remoto é **opt-in** via `initializeAppLanguageAsync`. O major
16
+ > marca a mudança de arquitetura (traduções podem vir da rede), não uma quebra
17
+ > de API.
18
+
19
+ ---
20
+
21
+ ## Sumário
22
+
23
+ - [Instalação](#instalação)
24
+ - [Como funciona](#como-funciona)
25
+ - [Inicialização](#inicialização)
26
+ - [Modo 1 — Embutido (síncrono)](#modo-1--embutido-síncrono)
27
+ - [Modo 2 — Remoto com fallback (recomendado)](#modo-2--remoto-com-fallback-recomendado)
28
+ - [Modo 3 — Host distribui aos MFEs](#modo-3--host-distribui-aos-mfes)
29
+ - [Opções de carregamento remoto](#opções-de-carregamento-remoto)
30
+ - [Cache e revalidação](#cache-e-revalidação)
31
+ - [Arquivos de tradução na AWS](#arquivos-de-tradução-na-aws)
32
+ - [Gerar/atualizar os JSON](#geraratualizar-os-json)
33
+ - [Processo de hotfix de termo](#processo-de-hotfix-de-termo-sem-republicar)
34
+ - [Requisitos de infraestrutura](#requisitos-de-infraestrutura-aws)
35
+ - [Outras APIs](#outras-apis)
36
+ - [Idiomas suportados](#idiomas-suportados)
37
+
38
+ ---
39
+
40
+ ## Instalação
41
+
42
+ ```bash
43
+ npm install mapa-frontend-i18n
44
+ ```
45
+
46
+ `peerDependency`: `@angular/localize ~20.3.0` (já presente nas aplicações MAPA).
47
+
48
+ ---
49
+
50
+ ## Como funciona
51
+
52
+ - As traduções são um **mapa achatado** `{ "chave.do.localize": "texto" }`,
53
+ injetado no `@angular/localize` via `loadTranslations()`.
54
+ - O `$localize` resolve cada mensagem **no momento em que ela é avaliada**, usando
55
+ o mapa global. Por isso, **as traduções precisam ser carregadas antes do
56
+ `bootstrapApplication()`** — caso contrário a tela aparece com o texto-fonte
57
+ (pt-BR) ou com as chaves cruas.
58
+ - O carregamento remoto faz o merge `{ ...embutido, ...remoto }`: o remoto
59
+ **sobrescreve** o embutido, e qualquer chave ausente no remoto ainda resolve
60
+ pelo embutido. Ou seja, **arquivos remotos parciais são seguros**.
61
+
62
+ ---
63
+
64
+ ## Inicialização
65
+
66
+ ### Modo 1 — Embutido (síncrono)
67
+
68
+ Usa apenas os catálogos embutidos no pacote. É o comportamento clássico, sem
69
+ rede.
70
+
71
+ ```ts
72
+ import { initializeAppLanguage } from "mapa-frontend-i18n";
73
+
74
+ initializeAppLanguage(); // lê o idioma do localStorage e carrega o embutido
75
+ ```
76
+
77
+ ### Modo 2 — Remoto com fallback (recomendado)
78
+
79
+ Carrega da AWS, com cache local e _fallback_ automático para o embutido. **Deve
80
+ ser aguardado antes do bootstrap.**
81
+
82
+ ```ts
83
+ // main.ts
84
+ import { bootstrapApplication } from "@angular/platform-browser";
85
+ import { initializeAppLanguageAsync } from "mapa-frontend-i18n";
86
+ import { AppComponent } from "./app/app.component";
87
+ import { appConfig } from "./app/app.config";
88
+ import { environment } from "./environments/environment";
89
+
90
+ initializeAppLanguageAsync({ baseUrl: environment.i18nBaseUrl })
91
+ .catch(() => undefined) // nunca lança; em falha já usa o fallback embutido
92
+ .then(() => bootstrapApplication(AppComponent, appConfig));
93
+ ```
94
+
95
+ `environment.i18nBaseUrl` aponta para a pasta que contém os JSON por idioma, por
96
+ ambiente (dev/staging/prod). Ex.: `https://cdn.mapa.com.br/i18n`.
97
+
98
+ ### Modo 3 — Host distribui aos MFEs
99
+
100
+ Em micro-frontends, o **host** busca as traduções uma única vez e as repassa para
101
+ cada MFE, evitando um request por MFE. Use quando cada MFE roda em um contexto de
102
+ `@angular/localize` próprio.
103
+
104
+ ```ts
105
+ // no host (antes do bootstrap):
106
+ import { getStoredAppLanguage, loadRemoteTranslations } from "mapa-frontend-i18n";
107
+
108
+ const language = getStoredAppLanguage();
109
+ const remote = await loadRemoteTranslations(language, {
110
+ baseUrl: environment.i18nBaseUrl,
111
+ });
112
+ // disponibilize `language` + `remote` para os MFEs (window, store compartilhado, etc.)
113
+ ```
114
+
115
+ ```ts
116
+ // em cada MFE (antes do seu bootstrap):
117
+ import { initializeAppLanguageFromData } from "mapa-frontend-i18n";
118
+
119
+ initializeAppLanguageFromData(language, remote ?? {});
120
+ ```
121
+
122
+ > Se os MFEs compartilham o mesmo `@angular/localize` (singleton via module
123
+ > federation), basta o host chamar `initializeAppLanguageAsync` uma vez.
124
+
125
+ ---
126
+
127
+ ## Opções de carregamento remoto
128
+
129
+ `RemoteTranslationOptions` (usado por `initializeAppLanguageAsync` e
130
+ `loadRemoteTranslations`):
131
+
132
+ | Opção | Tipo | Padrão | Descrição |
133
+ | ------------ | -------------------------- | -------------- | ------------------------------------------------------------------------- |
134
+ | `baseUrl` | `string` | — (obrigatório) | URL base dos JSON, sem barra final. Busca `${baseUrl}/${idioma}.json`. |
135
+ | `version` | `string` | `undefined` | Tag de versão (`?v=`) para _cache-busting_ manual (requer CloudFront com query string na chave de cache). |
136
+ | `timeoutMs` | `number` | `5000` | Aborta o request após esse tempo (o boot não trava se a AWS demorar). |
137
+ | `fetchImpl` | `typeof fetch` | `globalThis.fetch` | `fetch` customizado (testes/SSR). |
138
+ | `onError` | `(error: unknown) => void` | `undefined` | Notificação de erro de fetch/parse (não-fatal; o _fallback_ é usado). |
139
+
140
+ ---
141
+
142
+ ## Cache e revalidação
143
+
144
+ Estratégia _stale-while-revalidate_:
145
+
146
+ - Cache em `localStorage`, chave `i18n.cache.<idioma>` (apenas o idioma ativo).
147
+ - **1º acesso:** aguarda o fetch; em falha, usa o embutido.
148
+ - **Acessos seguintes:** aplica o cache **na hora** (boot instantâneo) e revalida
149
+ em segundo plano. Se o conteúdo mudou, o cache é atualizado e **a nova versão
150
+ entra no próximo reload**.
151
+
152
+ O request é um **GET simples** (sem cabeçalhos customizados) com `cache:
153
+ "no-cache"`: a revalidação contra o CDN é feita pelo próprio browser via
154
+ `ETag`/`Last-Modified`, de forma transparente. Isso evita _preflight_ CORS — o
155
+ servidor só precisa do cabeçalho `Access-Control-Allow-Origin`.
156
+
157
+ Cadeia de _fallback_ em qualquer falha: `cache → catálogo embutido` (nunca a
158
+ chave crua).
159
+
160
+ ---
161
+
162
+ ## Arquivos de tradução na AWS
163
+
164
+ Um arquivo JSON **por idioma**, contendo o mapa achatado já mesclado de todos os
165
+ módulos:
166
+
167
+ ```
168
+ ${baseUrl}/pt-BR.json
169
+ ${baseUrl}/en.json
170
+ ${baseUrl}/es.json
171
+ ```
172
+
173
+ Formato (mesmo shape consumido pelo `loadTranslations()`):
174
+
175
+ ```json
176
+ {
177
+ "common.cancel": "Cancelar",
178
+ "common.close": "Fechar",
179
+ "home.title": "Painel"
180
+ }
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Gerar/atualizar os JSON
186
+
187
+ O script de export gera os arquivos a partir dos catálogos embutidos. Use para
188
+ **semear** o conteúdo inicial na AWS e para manter o _fallback_ embutido
189
+ sincronizado a cada release.
190
+
191
+ ```bash
192
+ npm run export:i18n
193
+ # escreve dist/i18n-remote/{pt-BR,en,es}.json
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Processo de hotfix de termo (sem republicar)
199
+
200
+ 1. Edite o termo/acentuação diretamente no JSON do idioma na AWS (ou ajuste só as
201
+ chaves alteradas — arquivos parciais são suportados).
202
+ 2. Faça upload para o S3.
203
+ 3. Invalide o cache do CloudFront **ou** confie no `ETag` + `Cache-Control` curto
204
+ (a revalidação aplica a mudança no próximo reload dos usuários).
205
+
206
+ Nenhuma publicação de versão da lib nem redeploy das aplicações é necessária.
207
+
208
+ > Os catálogos `*.ts` embutidos seguem como _fallback_ (último-bom-conhecido).
209
+ > Para mantê-los alinhados com a AWS, rode `npm run export:i18n` periodicamente e
210
+ > publique uma release quando quiser atualizar o _fallback_.
211
+
212
+ ---
213
+
214
+ ## Requisitos de infraestrutura (AWS)
215
+
216
+ - **S3** (com ou sem CloudFront) servindo `/i18n/{idioma}.json` por ambiente.
217
+ - **CORS (obrigatório):** basta `Access-Control-Allow-Origin` liberando as origens
218
+ das aplicações no GET (não há _preflight_, pois o request é simples). Bucket
219
+ público **não** dispensa CORS — sem ele o browser bloqueia a leitura via `fetch`.
220
+ Ver config de exemplo em [`examples/aws/s3-cors.json`](../../examples/aws/s3-cors.json).
221
+ - **`ETag`** (o S3 já envia) para a revalidação condicional do browser funcionar.
222
+ - **Propagação de hotfix:**
223
+ - **S3 direto (sem CDN):** a alteração é **imediata** no próximo reload.
224
+ - **Via CloudFront:** use `Cache-Control` curto (ex.: `max-age=300`) **ou
225
+ invalide** o caminho a cada hotfix — senão o edge serve a versão antiga até a
226
+ TTL padrão (24h).
227
+
228
+ ---
229
+
230
+ ## Outras APIs
231
+
232
+ ```ts
233
+ import {
234
+ // Idioma
235
+ getStoredAppLanguage,
236
+ persistAppLanguage,
237
+ applyDocumentLanguage,
238
+ getAngularLocale,
239
+ getIntlLocale,
240
+ resolveAppLanguage,
241
+ APP_LANGUAGE_OPTIONS,
242
+ DEFAULT_APP_LANGUAGE,
243
+
244
+ // Textos de UI (validações, paginador, etc.)
245
+ getMapaUiTexts,
246
+ applyPaginatorIntl,
247
+ } from "mapa-frontend-i18n";
248
+ ```
249
+
250
+ `getMapaUiTexts(language)` retorna textos de UI reutilizáveis (filtros, tabela,
251
+ validações). Alguns valores são **funções** (paginador e validações com
252
+ interpolação) e permanecem no código da lib — não são externalizados para JSON.
253
+
254
+ ---
255
+
256
+ ## Idiomas suportados
257
+
258
+ | Código | Idioma | Padrão |
259
+ | ------- | ---------- | ------ |
260
+ | `pt-BR` | Português | ✅ (fonte/fallback) |
261
+ | `es` | Español | |
262
+ | `en` | English | |
263
+
264
+ O idioma escolhido é persistido em `localStorage` na chave `menu.language`.
@@ -4119,6 +4119,18 @@ const PT_RUNTIME_TRANSLATIONS$5 = {
4119
4119
  "common.failure": "Falha!",
4120
4120
  "common.filters": "Filtros",
4121
4121
  "common.moneyPlaceholder": "0,00",
4122
+ "common.month.april": "abril",
4123
+ "common.month.august": "agosto",
4124
+ "common.month.december": "dezembro",
4125
+ "common.month.february": "fevereiro",
4126
+ "common.month.january": "janeiro",
4127
+ "common.month.july": "julho",
4128
+ "common.month.june": "junho",
4129
+ "common.month.march": "março",
4130
+ "common.month.may": "maio",
4131
+ "common.month.november": "novembro",
4132
+ "common.month.october": "outubro",
4133
+ "common.month.september": "setembro",
4122
4134
  "common.no": "Não",
4123
4135
  "common.observation": "Observações",
4124
4136
  "common.search.company": "Pesquisar empresa",
@@ -4441,7 +4453,8 @@ const PT_RUNTIME_TRANSLATIONS$5 = {
4441
4453
  "statement.list.section.title": "Movimentações",
4442
4454
  "statement.page.description": "Consulte seu histórico de uso na plataforma.",
4443
4455
  "statement.page.title": "Extrato de uso",
4444
- "statement.transaction.usedEvaluations": "{VAR_PLURAL, plural, =1 {1 avaliação utilizada} other {# avaliações utilizadas}}",
4456
+ "statement.transaction.usedEvaluationSingular": "1 avaliação utilizada",
4457
+ "statement.transaction.usedEvaluationsPlural": "{$INTERPOLATION} avaliações utilizadas",
4445
4458
  "statement.summary.availableCredits": "Créditos disponíveis",
4446
4459
  "statement.summary.contractInfo": "Informações Contratuais",
4447
4460
  "statement.summary.lastPurchase": "Última compra",
@@ -5305,6 +5318,54 @@ const MISSING_RUNTIME_TRANSLATIONS$3 = {
5305
5318
  en: "0.00",
5306
5319
  es: "0,00",
5307
5320
  },
5321
+ "common.month.april": {
5322
+ en: "april",
5323
+ es: "abril",
5324
+ },
5325
+ "common.month.august": {
5326
+ en: "august",
5327
+ es: "agosto",
5328
+ },
5329
+ "common.month.december": {
5330
+ en: "december",
5331
+ es: "diciembre",
5332
+ },
5333
+ "common.month.february": {
5334
+ en: "february",
5335
+ es: "febrero",
5336
+ },
5337
+ "common.month.january": {
5338
+ en: "january",
5339
+ es: "enero",
5340
+ },
5341
+ "common.month.july": {
5342
+ en: "july",
5343
+ es: "julio",
5344
+ },
5345
+ "common.month.june": {
5346
+ en: "june",
5347
+ es: "junio",
5348
+ },
5349
+ "common.month.march": {
5350
+ en: "march",
5351
+ es: "marzo",
5352
+ },
5353
+ "common.month.may": {
5354
+ en: "may",
5355
+ es: "mayo",
5356
+ },
5357
+ "common.month.november": {
5358
+ en: "november",
5359
+ es: "noviembre",
5360
+ },
5361
+ "common.month.october": {
5362
+ en: "october",
5363
+ es: "octubre",
5364
+ },
5365
+ "common.month.september": {
5366
+ en: "september",
5367
+ es: "septiembre",
5368
+ },
5308
5369
  "common.no": {
5309
5370
  en: "No",
5310
5371
  es: "No",
@@ -6593,9 +6654,13 @@ const MISSING_RUNTIME_TRANSLATIONS$3 = {
6593
6654
  en: "Usage statement",
6594
6655
  es: "Extracto de uso",
6595
6656
  },
6596
- "statement.transaction.usedEvaluations": {
6597
- en: "{VAR_PLURAL, plural, =1 {1 used evaluation} other {# used evaluations}}",
6598
- es: "{VAR_PLURAL, plural, =1 {1 evaluación utilizada} other {# evaluaciones utilizadas}}",
6657
+ "statement.transaction.usedEvaluationSingular": {
6658
+ en: "1 used evaluation",
6659
+ es: "1 evaluación utilizada",
6660
+ },
6661
+ "statement.transaction.usedEvaluationsPlural": {
6662
+ en: "{$INTERPOLATION} used evaluations",
6663
+ es: "{$INTERPOLATION} evaluaciones utilizadas",
6599
6664
  },
6600
6665
  "statement.summary.availableCredits": {
6601
6666
  en: "Available credits",
@@ -15264,6 +15329,125 @@ function getAppLanguageOption(language) {
15264
15329
  ?? APP_LANGUAGE_OPTIONS[0];
15265
15330
  }
15266
15331
 
15332
+ const CACHE_KEY_PREFIX = "i18n.cache.";
15333
+ const DEFAULT_TIMEOUT_MS = 5000;
15334
+ function getCacheKey(language) {
15335
+ return `${CACHE_KEY_PREFIX}${language}`;
15336
+ }
15337
+ function buildUrl(baseUrl, language, version) {
15338
+ const normalized = baseUrl.replace(/\/+$/, "");
15339
+ const url = `${normalized}/${language}.json`;
15340
+ return version ? `${url}?v=${encodeURIComponent(version)}` : url;
15341
+ }
15342
+ /** True only for a plain object whose every value is a string. */
15343
+ function isFlatTranslations(value) {
15344
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
15345
+ return false;
15346
+ }
15347
+ return Object.values(value).every((entry) => typeof entry === "string");
15348
+ }
15349
+ function resolveFetch(options) {
15350
+ if (options.fetchImpl) {
15351
+ return options.fetchImpl;
15352
+ }
15353
+ return typeof fetch === "undefined" ? undefined : fetch;
15354
+ }
15355
+ function withTimeout(timeoutMs) {
15356
+ if (typeof AbortController === "undefined") {
15357
+ return { signal: undefined, done: () => undefined };
15358
+ }
15359
+ const controller = new AbortController();
15360
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
15361
+ return { signal: controller.signal, done: () => clearTimeout(timer) };
15362
+ }
15363
+ /**
15364
+ * Reads the cached translations for a language from localStorage. Returns
15365
+ * `null` when there is no cache, it is unreadable, or its shape is invalid.
15366
+ * Safe to call during SSR (returns `null` when localStorage is unavailable).
15367
+ */
15368
+ function readCachedTranslations(language) {
15369
+ if (typeof localStorage === "undefined") {
15370
+ return null;
15371
+ }
15372
+ try {
15373
+ const raw = localStorage.getItem(getCacheKey(language));
15374
+ if (!raw) {
15375
+ return null;
15376
+ }
15377
+ const parsed = JSON.parse(raw);
15378
+ if (!isFlatTranslations(parsed.data)) {
15379
+ return null;
15380
+ }
15381
+ return {
15382
+ version: typeof parsed.version === "string" ? parsed.version : null,
15383
+ data: parsed.data,
15384
+ };
15385
+ }
15386
+ catch {
15387
+ return null;
15388
+ }
15389
+ }
15390
+ function writeCachedTranslations(language, payload) {
15391
+ if (typeof localStorage === "undefined") {
15392
+ return;
15393
+ }
15394
+ try {
15395
+ localStorage.setItem(getCacheKey(language), JSON.stringify(payload));
15396
+ }
15397
+ catch {
15398
+ // Quota exceeded or storage disabled: ignore, the in-memory result still applies.
15399
+ }
15400
+ }
15401
+ /**
15402
+ * Fetches the remote translations for a language, updating the localStorage
15403
+ * cache.
15404
+ *
15405
+ * Uses a plain GET (no custom request headers) on purpose: this keeps it a
15406
+ * "simple" CORS request, so the only server requirement is an
15407
+ * `Access-Control-Allow-Origin` header — no OPTIONS preflight. Freshness is
15408
+ * delegated to the HTTP layer via `cache: "no-cache"`, which makes the browser
15409
+ * revalidate against the CDN's `ETag`/`Last-Modified` transparently (a 304 is
15410
+ * resolved by the browser and surfaces here as a normal 200).
15411
+ *
15412
+ * Resolution order on failure: cached data (if any), otherwise `null` so the
15413
+ * caller can fall back to the embedded catalogs. Never throws.
15414
+ */
15415
+ async function loadRemoteTranslations(language, options) {
15416
+ const fetchImpl = resolveFetch(options);
15417
+ if (!fetchImpl || !options.baseUrl) {
15418
+ return null;
15419
+ }
15420
+ const cached = readCachedTranslations(language);
15421
+ const url = buildUrl(options.baseUrl, language, options.version);
15422
+ const { signal, done } = withTimeout(options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
15423
+ try {
15424
+ const response = await fetchImpl(url, {
15425
+ cache: "no-cache",
15426
+ signal,
15427
+ });
15428
+ if (!response.ok) {
15429
+ throw new Error(`Failed to load translations: HTTP ${response.status}`);
15430
+ }
15431
+ const data = await response.json();
15432
+ if (!isFlatTranslations(data)) {
15433
+ throw new Error("Remote translations payload is not a flat string map");
15434
+ }
15435
+ writeCachedTranslations(language, {
15436
+ version: options.version ?? null,
15437
+ fetchedAt: Date.now(),
15438
+ data,
15439
+ });
15440
+ return data;
15441
+ }
15442
+ catch (error) {
15443
+ options.onError?.(error);
15444
+ return cached?.data ?? null;
15445
+ }
15446
+ finally {
15447
+ done();
15448
+ }
15449
+ }
15450
+
15267
15451
  function getStoredAppLanguage() {
15268
15452
  if (typeof window === "undefined") {
15269
15453
  return DEFAULT_APP_LANGUAGE;
@@ -15300,6 +15484,64 @@ function initializeAppLanguage(options = {}) {
15300
15484
  }
15301
15485
  return language;
15302
15486
  }
15487
+ /**
15488
+ * Merges the embedded (build-time) catalog for a language with an optional
15489
+ * remote map and hands the result to `@angular/localize`. The remote entries
15490
+ * override the embedded ones, while any key missing remotely still resolves
15491
+ * from the embedded fallback — so partial remote files are safe.
15492
+ */
15493
+ function applyTranslations(language, remote) {
15494
+ const merged = {
15495
+ ...(ANGULAR_RUNTIME_TRANSLATIONS[language] ?? {}),
15496
+ ...(remote ?? {}),
15497
+ };
15498
+ if (Object.keys(merged).length > 0) {
15499
+ loadTranslations(merged);
15500
+ }
15501
+ }
15502
+ /**
15503
+ * Initializes translations by loading them from the remote (AWS) JSON files,
15504
+ * with the embedded catalogs as a fallback. MUST be awaited before the host
15505
+ * application bootstraps, because `$localize` resolves messages at evaluation
15506
+ * time from the global map populated here.
15507
+ *
15508
+ * Behaviour:
15509
+ * - With a local cache: applies the cached copy immediately (instant boot) and
15510
+ * revalidates in the background; an updated copy takes effect on the next reload.
15511
+ * - Without a cache: awaits the remote fetch and, on any failure, falls back to
15512
+ * the embedded catalogs (never the raw keys).
15513
+ */
15514
+ async function initializeAppLanguageAsync(options) {
15515
+ const language = getStoredAppLanguage();
15516
+ if (options.clearExistingTranslations) {
15517
+ clearTranslations();
15518
+ }
15519
+ applyDocumentLanguage(language);
15520
+ const cached = readCachedTranslations(language);
15521
+ if (cached) {
15522
+ applyTranslations(language, cached.data);
15523
+ // Fire-and-forget revalidation; the refreshed cache applies on next reload.
15524
+ void loadRemoteTranslations(language, options).catch(() => undefined);
15525
+ return language;
15526
+ }
15527
+ const remote = await loadRemoteTranslations(language, options);
15528
+ applyTranslations(language, remote);
15529
+ return language;
15530
+ }
15531
+ /**
15532
+ * Initializes translations from data the caller already fetched. Intended for
15533
+ * micro-frontend setups where a host fetches the remote translations once and
15534
+ * shares them with each MFE, avoiding one network request per MFE. The data is
15535
+ * merged over the embedded fallback, like {@link initializeAppLanguageAsync}.
15536
+ */
15537
+ function initializeAppLanguageFromData(language, remote, options = {}) {
15538
+ if (options.clearExistingTranslations) {
15539
+ clearTranslations();
15540
+ }
15541
+ applyDocumentLanguage(language);
15542
+ applyTranslations(language, remote);
15543
+ return language;
15544
+ }
15303
15545
 
15304
15546
  const PAGINATOR_COPY_BY_LANGUAGE = {
15305
15547
  "pt-BR": {
@@ -15564,5 +15806,5 @@ function getMapaUiTexts(language) {
15564
15806
  * Generated bundle index. Do not edit.
15565
15807
  */
15566
15808
 
15567
- export { ANGULAR_RUNTIME_TRANSLATIONS, APP_LANGUAGE_OPTIONS, APP_LANGUAGE_STORAGE_KEY, DEFAULT_APP_LANGUAGE, MAPA_UI_TEXTS_PT_BR, MA_TRANSLATIONS, MCA_TRANSLATIONS, MENU_TRANSLATIONS, MF_TRANSLATIONS, MGA_TRANSLATIONS, MGC_TRANSLATIONS, MO_TRANSLATIONS, MP_TRANSLATIONS, MV_TRANSLATIONS, applyDocumentLanguage, applyPaginatorIntl, formatPaginatorRange, formatPaginatorShowingRange, getAngularLocale, getAppLanguageOption, getIntlLocale, getMapaUiTexts, getPaginatorNavigationLabels, getStoredAppLanguage, initializeAppLanguage, isAppLanguage, persistAppLanguage, resolveAppLanguage };
15809
+ export { ANGULAR_RUNTIME_TRANSLATIONS, APP_LANGUAGE_OPTIONS, APP_LANGUAGE_STORAGE_KEY, DEFAULT_APP_LANGUAGE, MAPA_UI_TEXTS_PT_BR, MA_TRANSLATIONS, MCA_TRANSLATIONS, MENU_TRANSLATIONS, MF_TRANSLATIONS, MGA_TRANSLATIONS, MGC_TRANSLATIONS, MO_TRANSLATIONS, MP_TRANSLATIONS, MV_TRANSLATIONS, applyDocumentLanguage, applyPaginatorIntl, formatPaginatorRange, formatPaginatorShowingRange, getAngularLocale, getAppLanguageOption, getIntlLocale, getMapaUiTexts, getPaginatorNavigationLabels, getStoredAppLanguage, initializeAppLanguage, initializeAppLanguageAsync, initializeAppLanguageFromData, isAppLanguage, loadRemoteTranslations, persistAppLanguage, readCachedTranslations, resolveAppLanguage };
15568
15810
  //# sourceMappingURL=mapa-frontend-i18n.mjs.map