Skip to content

Commit 2b73c12

Browse files
author
Angular Builds
committed
a42e045 fix(@angular-devkit/build-angular): respect i18nDuplicateTranslation option when duplicates exist
1 parent 382ddf9 commit 2b73c12

File tree

9 files changed

+49
-9
lines changed

9 files changed

+49
-9
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@angular-devkit/build-angular",
3-
"version": "20.0.0-rc.2+sha-36c2a82",
3+
"version": "20.0.0-rc.2+sha-a42e045",
44
"description": "Angular Webpack Build Facade",
55
"main": "src/index.js",
66
"typings": "src/index.d.ts",

src/builders/extract-i18n/builder.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,20 @@ async function execute(options, context, transforms) {
115115
return node_path_1.default.relative(from, to);
116116
},
117117
};
118+
const duplicateTranslationBehavior = normalizedOptions.i18nOptions.duplicateTranslationBehavior;
118119
const diagnostics = checkDuplicateMessages(
119120
// eslint-disable-next-line @typescript-eslint/no-explicit-any
120-
checkFileSystem, extractionResult.messages, 'warning',
121+
checkFileSystem, extractionResult.messages, duplicateTranslationBehavior,
121122
// eslint-disable-next-line @typescript-eslint/no-explicit-any
122123
extractionResult.basePath);
123-
if (diagnostics.messages.length > 0) {
124-
context.logger.warn(diagnostics.formatDiagnostics(''));
124+
if (diagnostics.messages.length > 0 && duplicateTranslationBehavior !== 'ignore') {
125+
if (duplicateTranslationBehavior === 'error') {
126+
context.logger.error(`Extraction Failed: ${diagnostics.formatDiagnostics('')}`);
127+
return { success: false };
128+
}
129+
else {
130+
context.logger.warn(diagnostics.formatDiagnostics(''));
131+
}
125132
}
126133
// Serialize all extracted messages
127134
const serializer = await createSerializer(localizeToolsModule, normalizedOptions.format, normalizedOptions.i18nOptions.sourceLocale, extractionResult.basePath, extractionResult.useLegacyIds, diagnostics);

src/builders/extract-i18n/options.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.dev/license
77
*/
8+
import { type I18nOptions } from '@angular/build/private';
9+
import { type DiagnosticHandlingStrategy } from '@angular/localize/tools';
810
import { BuilderContext } from '@angular-devkit/architect';
911
import { Schema as ExtractI18nOptions, Format } from './schema';
1012
export type NormalizedExtractI18nOptions = Awaited<ReturnType<typeof normalizeOptions>>;
@@ -22,7 +24,9 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
2224
workspaceRoot: string;
2325
projectRoot: string;
2426
buildTarget: import("@angular-devkit/architect").Target;
25-
i18nOptions: import("@angular/build/private").I18nOptions;
27+
i18nOptions: I18nOptions & {
28+
duplicateTranslationBehavior: DiagnosticHandlingStrategy;
29+
};
2630
format: Format.Arb | Format.Json | Format.LegacyMigrate | Format.Xliff | Format.Xliff2 | Format.Xmb;
2731
outFile: string;
2832
progress: boolean;

src/builders/extract-i18n/options.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ async function normalizeOptions(context, projectName, options) {
3333
// Target specifier defaults to the current project's build target with no specified configuration
3434
const buildTargetSpecifier = options.buildTarget ?? ':';
3535
const buildTarget = (0, architect_1.targetFromTargetString)(buildTargetSpecifier, projectName, 'build');
36-
const i18nOptions = (0, private_1.createI18nOptions)(projectMetadata, /** inline */ false, context.logger);
36+
const i18nOptions = {
37+
...(0, private_1.createI18nOptions)(projectMetadata, /** inline */ false, context.logger),
38+
duplicateTranslationBehavior: options.i18nDuplicateTranslation || 'warning',
39+
};
3740
// Normalize xliff format extensions
3841
let format = options.format;
3942
switch (format) {

src/builders/extract-i18n/schema.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ export type Schema = {
1212
* Output format for the generated file.
1313
*/
1414
format?: Format;
15+
/**
16+
* How to handle duplicate translations.
17+
*/
18+
i18nDuplicateTranslation?: I18NDuplicateTranslation;
1519
/**
1620
* Name of the file to output.
1721
*/
@@ -39,3 +43,11 @@ export declare enum Format {
3943
Xliff2 = "xliff2",
4044
Xmb = "xmb"
4145
}
46+
/**
47+
* How to handle duplicate translations.
48+
*/
49+
export declare enum I18NDuplicateTranslation {
50+
Error = "error",
51+
Ignore = "ignore",
52+
Warning = "warning"
53+
}

src/builders/extract-i18n/schema.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// THIS FILE IS AUTOMATICALLY GENERATED. TO UPDATE THIS FILE YOU NEED TO CHANGE THE
33
// CORRESPONDING JSON SCHEMA FILE, THEN RUN devkit-admin build (or bazel build ...).
44
Object.defineProperty(exports, "__esModule", { value: true });
5-
exports.Format = void 0;
5+
exports.I18NDuplicateTranslation = exports.Format = void 0;
66
/**
77
* Output format for the generated file.
88
*/
@@ -18,3 +18,12 @@ var Format;
1818
Format["Xliff2"] = "xliff2";
1919
Format["Xmb"] = "xmb";
2020
})(Format || (exports.Format = Format = {}));
21+
/**
22+
* How to handle duplicate translations.
23+
*/
24+
var I18NDuplicateTranslation;
25+
(function (I18NDuplicateTranslation) {
26+
I18NDuplicateTranslation["Error"] = "error";
27+
I18NDuplicateTranslation["Ignore"] = "ignore";
28+
I18NDuplicateTranslation["Warning"] = "warning";
29+
})(I18NDuplicateTranslation || (exports.I18NDuplicateTranslation = I18NDuplicateTranslation = {}));

src/builders/extract-i18n/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@
2727
"outFile": {
2828
"type": "string",
2929
"description": "Name of the file to output."
30+
},
31+
"i18nDuplicateTranslation": {
32+
"type": "string",
33+
"description": "How to handle duplicate translations.",
34+
"enum": ["error", "warning", "ignore"]
3035
}
3136
},
3237
"additionalProperties": false

src/utils/normalize-cache.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
1010
exports.normalizeCacheOptions = normalizeCacheOptions;
1111
const node_path_1 = require("node:path");
1212
/** Version placeholder is replaced during the build process with actual package version */
13-
const VERSION = '20.0.0-rc.2+sha-36c2a82';
13+
const VERSION = '20.0.0-rc.2+sha-a42e045';
1414
function hasCacheMetadata(value) {
1515
return (!!value &&
1616
typeof value === 'object' &&

uniqueId

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Tue May 20 2025 14:57:04 GMT+0000 (Coordinated Universal Time)
1+
Tue May 20 2025 15:51:23 GMT+0000 (Coordinated Universal Time)

0 commit comments

Comments
 (0)