Skip to content

Commit cbe028e

Browse files
minijusdgp1130
authored andcommitted
feat(@angular-devkit/build-angular): expose i18nDuplicateTranslation option of browser and server builders
Closes #22201
1 parent 11f817a commit cbe028e

File tree

7 files changed

+65
-21
lines changed

7 files changed

+65
-21
lines changed

goldens/public-api/angular_devkit/build_angular/src/index.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ export interface BrowserBuilderOptions {
4343
deployUrl?: string;
4444
extractLicenses?: boolean;
4545
fileReplacements?: FileReplacement[];
46-
i18nMissingTranslation?: I18NMissingTranslation;
46+
i18nDuplicateTranslation?: I18NTranslation;
47+
i18nMissingTranslation?: I18NTranslation;
4748
index: IndexUnion;
4849
inlineStyleLanguage?: InlineStyleLanguage;
4950
localize?: Localize;
@@ -259,7 +260,8 @@ export interface ServerBuilderOptions {
259260
externalDependencies?: string[];
260261
extractLicenses?: boolean;
261262
fileReplacements?: FileReplacement_3[];
262-
i18nMissingTranslation?: I18NMissingTranslation_2;
263+
i18nDuplicateTranslation?: I18NTranslation_2;
264+
i18nMissingTranslation?: I18NTranslation_2;
263265
inlineStyleLanguage?: InlineStyleLanguage_3;
264266
localize?: Localize_2;
265267
main: string;

packages/angular_devkit/build_angular/src/builders/browser/schema.json

+6
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,12 @@
220220
"enum": ["warning", "error", "ignore"],
221221
"default": "warning"
222222
},
223+
"i18nDuplicateTranslation": {
224+
"type": "string",
225+
"description": "How to handle duplicate translations for i18n.",
226+
"enum": ["warning", "error", "ignore"],
227+
"default": "warning"
228+
},
223229
"localize": {
224230
"description": "Translate the bundles in one or more locales.",
225231
"oneOf": [

packages/angular_devkit/build_angular/src/builders/dev-server/index.ts

+15-7
Original file line numberDiff line numberDiff line change
@@ -368,14 +368,22 @@ async function setupLocalize(
368368
compiler.hooks.thisCompilation.tap('build-angular', (compilation) => {
369369
if (i18n.shouldInline && i18nLoaderOptions.translation === undefined) {
370370
// Reload translations
371-
loadTranslations(locale, localeDescription, context.workspaceRoot, loader, {
372-
warn(message) {
373-
addWarning(compilation, message);
374-
},
375-
error(message) {
376-
addError(compilation, message);
371+
loadTranslations(
372+
locale,
373+
localeDescription,
374+
context.workspaceRoot,
375+
loader,
376+
{
377+
warn(message) {
378+
addWarning(compilation, message);
379+
},
380+
error(message) {
381+
addError(compilation, message);
382+
},
377383
},
378-
});
384+
undefined,
385+
browserOptions.i18nDuplicateTranslation,
386+
);
379387
i18nLoaderOptions.translation = localeDescription.translation;
380388
}
381389

packages/angular_devkit/build_angular/src/builders/server/schema.json

+6
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@
133133
"enum": ["warning", "error", "ignore"],
134134
"default": "warning"
135135
},
136+
"i18nDuplicateTranslation": {
137+
"type": "string",
138+
"description": "How to handle duplicate translations for i18n.",
139+
"enum": ["warning", "error", "ignore"],
140+
"default": "warning"
141+
},
136142
"localize": {
137143
"description": "Translate the bundles in one or more locales.",
138144
"oneOf": [

packages/angular_devkit/build_angular/src/utils/build-options.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
Budget,
1414
CrossOrigin,
1515
ExtraEntryPoint,
16-
I18NMissingTranslation,
16+
I18NTranslation,
1717
IndexUnion,
1818
InlineStyleLanguage,
1919
Localize,
@@ -38,7 +38,7 @@ export interface BuildOptions {
3838
verbose?: boolean;
3939
progress?: boolean;
4040
localize?: Localize;
41-
i18nMissingTranslation?: I18NMissingTranslation;
41+
i18nMissingTranslation?: I18NTranslation;
4242
bundleDependencies?: boolean;
4343
externalDependencies?: string[];
4444
watch?: boolean;

packages/angular_devkit/build_angular/src/utils/i18n-options.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import fs from 'fs';
1212
import module from 'module';
1313
import os from 'os';
1414
import path from 'path';
15-
import { Schema as BrowserBuilderSchema } from '../builders/browser/schema';
15+
import { Schema as BrowserBuilderSchema, I18NTranslation } from '../builders/browser/schema';
1616
import { Schema as ServerBuilderSchema } from '../builders/server/schema';
1717
import { readTsconfig } from '../utils/read-tsconfig';
1818
import { TranslationLoader, createTranslationLoader } from './load-translations';
@@ -233,6 +233,7 @@ export async function configureI18nBuild<T extends BrowserBuilderSchema | Server
233233
},
234234
},
235235
usedFormats,
236+
buildOptions.i18nDuplicateTranslation,
236237
);
237238

238239
if (usedFormats.size > 1 && tsConfig.options.enableI18nLegacyMessageIdFormat !== false) {
@@ -282,6 +283,7 @@ export function loadTranslations(
282283
loader: TranslationLoader,
283284
logger: { warn: (message: string) => void; error: (message: string) => void },
284285
usedFormats?: Set<string>,
286+
duplicateTranslation?: I18NTranslation,
285287
) {
286288
for (const file of desc.files) {
287289
const loadResult = loader(path.join(workspaceRoot, file.path));
@@ -308,9 +310,18 @@ export function loadTranslations(
308310
// Merge translations
309311
for (const [id, message] of Object.entries(loadResult.translations)) {
310312
if (desc.translation[id] !== undefined) {
311-
logger.warn(
312-
`WARNING [${file.path}]: Duplicate translations for message '${id}' when merging`,
313-
);
313+
const duplicateTranslationMessage = `[${file.path}]: Duplicate translations for message '${id}' when merging.`;
314+
switch (duplicateTranslation) {
315+
case I18NTranslation.Ignore:
316+
break;
317+
case I18NTranslation.Error:
318+
logger.error(`ERROR ${duplicateTranslationMessage}`);
319+
break;
320+
case I18NTranslation.Warning:
321+
default:
322+
logger.warn(`WARNING ${duplicateTranslationMessage}`);
323+
break;
324+
}
314325
}
315326
desc.translation[id] = message;
316327
}

tests/legacy-cli/e2e/tests/i18n/ivy-localize-merging.ts

+17-6
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,20 @@
88

99
import { ng } from '../../utils/process';
1010
import { updateJsonFile } from '../../utils/project';
11+
import { expectToFail } from '../../utils/utils';
1112
import { setupI18nConfig } from './setup';
1213

13-
export default async function() {
14+
export default async function () {
1415
// Setup i18n tests and config.
1516
await setupI18nConfig();
1617

1718
// Update angular.json
18-
await updateJsonFile('angular.json', workspaceJson => {
19+
await updateJsonFile('angular.json', (workspaceJson) => {
1920
const appProject = workspaceJson.projects['test-project'];
2021
// tslint:disable-next-line: no-any
2122
const i18n: Record<string, any> = appProject.i18n;
2223

23-
i18n.locales['fr'] = [
24-
i18n.locales['fr'],
25-
i18n.locales['fr'],
26-
]
24+
i18n.locales['fr'] = [i18n.locales['fr'], i18n.locales['fr']];
2725
appProject.architect['build'].options.localize = ['fr'];
2826
});
2927

@@ -32,5 +30,18 @@ export default async function() {
3230
throw new Error('duplicate translations warning not shown');
3331
}
3432

33+
await updateJsonFile('angular.json', (workspaceJson) => {
34+
const appProject = workspaceJson.projects['test-project'];
35+
appProject.architect['build'].options.i18nDuplicateTranslation = 'error';
36+
});
37+
await expectToFail(() => ng('build'));
3538

39+
await updateJsonFile('angular.json', (workspaceJson) => {
40+
const appProject = workspaceJson.projects['test-project'];
41+
appProject.architect['build'].options.i18nDuplicateTranslation = 'ignore';
42+
});
43+
const { stderr: err2 } = await ng('build');
44+
if (err2.includes('Duplicate translations for message')) {
45+
throw new Error('duplicate translations message not ignore');
46+
}
3647
}

0 commit comments

Comments
 (0)