angular/angular · warning
When merging multiple translation files, the target locale "
Error message
When merging multiple translation files, the target locale "${nextBundle.locale}" found in "${filePaths[i]}" does not match the target locale "${bundle.locale}" found in earlier files [${previousFiles}]. What it means
`mergeBundles()` loads every listed translation file and folds them into one bundle; when a later file declares a target locale different from the first file's, this warning is emitted (only if a diagnostics object is attached to the loader). The merge continues, the first bundle's locale wins, and duplicate message IDs across the files are separately reported.
Source
Thrown at packages/localize/tools/src/translate/translation_files/translation_loader.ts:141
/**
* There is more than one `filePath` for this locale, so load each as a bundle and then merge
* them all together.
*/
private mergeBundles(
filePaths: AbsoluteFsPath[],
providedLocale: string | undefined,
): TranslationBundle {
const bundles = filePaths.map((filePath) => this.loadBundle(filePath, providedLocale));
const bundle = bundles[0];
for (let i = 1; i < bundles.length; i++) {
const nextBundle = bundles[i];
if (nextBundle.locale !== bundle.locale) {
if (this.diagnostics) {
const previousFiles = filePaths
.slice(0, i)
.map((f) => `"${f}"`)
.join(', ');
this.diagnostics.warn(
`When merging multiple translation files, the target locale "${nextBundle.locale}" found in "${filePaths[i]}" does not match the target locale "${bundle.locale}" found in earlier files [${previousFiles}].`,
);
}
}
Object.keys(nextBundle.translations).forEach((messageId) => {
if (bundle.translations[messageId] !== undefined) {
this.diagnostics?.add(
this.duplicateTranslation,
`Duplicate translations for message "${messageId}" when merging "${filePaths[i]}".`,
);
} else {
bundle.translations[messageId] = nextBundle.translations[messageId];
}
});
}
return bundle;
}
}View on GitHub (pinned to 51cb07e980)
Solutions
- Group translation file paths by locale and call the translate step (mergeBundles) once per locale.
- Find the offending file named in the warning and fix its declared locale to match the rest of the set.
- Add a CI check that every file in a merge set declares the same locale before invoking the loader.
Example fix
// before: merging files that declare different locales const bundle = loader.mergeBundles(['fr.json', 'en-US.json']); // after: one merge per locale const fr = loader.mergeBundles(['fr.json', 'fr-FR.json']); const en = loader.mergeBundles(['en.json', 'en-US.json']);
Defensive patterns
Strategy: validation
Validate before calling
// Group translation files by declared locale before merging
function groupByLocale(files: string[]): Map<string, string[]> {
const groups = new Map<string, string[]>();
for (const f of files) {
const declared = JSON.parse(readFileSync(f, 'utf8'))['@@locale'] ?? JSON.parse(readFileSync(f, 'utf8')).locale;
groups.set(declared, [...(groups.get(declared) ?? []), f]);
}
return groups; // merge each group separately
} Prevention
- Never glob multiple locales into one translate invocation; iterate per locale.
- Assert all files in a merge set share the same declared locale before calling mergeBundles.
When it happens
Trigger: Calling `mergeBundles(['fr.json', 'en.json'])` - any list where files parsed to different `locale` values; the warning fires at the first index whose locale differs from bundle[0].
Common situations: Globbing all translation files (multiple locales) into a single translate/build invocation instead of grouping per locale; one stray file with a wrong or missing locale field mixed into a per-locale set.
Related errors
- Unexpected value of the `${key}` header provided. Expecting
- RESPONSE_IS_NOT_A_STRING
- FETCH_UPLOAD_PROGRESS_NOT_SUPPORTED
- FETCH_RESPONSE_BODY_TOO_LARGE
- JSONP_WRONG_METHOD
AI-assisted analysis of angular/angular@51cb07e980 (2026-08-22).
Data as JSON: /api/errors/5b4a64bb82a83480.
Report an issue: GitHub.