如何简化Angular国际化的angular.json多语言配置?
Great catch—you’re totally right that duplicating all that config for every locale is clunky, error-prone, and a clear violation of the DRY (Don’t Repeat Yourself) principle. Let’s break down a few practical ways to simplify this in your Angular project:
1. Use Angular CLI’s Native Configuration Inheritance
This is the cleanest, most maintainable approach since it leverages Angular’s built-in tools without extra scripts. Here’s how:
First, create a base configuration file (e.g., angular-base.json) to hold all the shared settings:
{ "projects": { "web": { "architect": { "build": { "configurations": { "base-i18n": { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" } ], "optimization": true, "outputHashing": "all", "sourceMap": false, "extractCss": true, "namedChunks": false, "aot": true, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "budgets": [ { "type": "initial", "maximumWarning": "2mb", "maximumError": "5mb" }, { "type": "anyComponentStyle", "maximumWarning": "6kb", "maximumError": "10kb" } ] } } } } } } }
Then, update your main angular.json to extend this base file, and only define locale-specific differences for each language:
{ "extends": "./angular-base.json", "projects": { "web": { "architect": { "build": { "configurations": { "en": { "extends": "base-i18n", "outputPath": "dist/web/en", "i18nFile": "src/locale/messages.en.xlf", "i18nFormat": "xlf", "i18nLocale": "en" }, "de": { "extends": "base-i18n", "outputPath": "dist/web/de", "i18nFile": "src/locale/messages.de.xlf", "i18nFormat": "xlf", "i18nLocale": "de" } } } } } } }
Now every locale config only includes what’s unique—no more copy-pasting the entire build settings block.
2. Generate Configs with a Simple Node Script
If you have dozens of locales or need dynamic configuration, a small Node.js script can automate the process entirely.
Create a script file (e.g., generate-i18n-config.js):
const fs = require('fs'); const angularJson = require('./angular.json'); // Define your shared base config once const baseBuildConfig = { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" } ], "optimization": true, "outputHashing": "all", "sourceMap": false, "extractCss": true, "namedChunks": false, "aot": true, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "budgets": [ { "type": "initial", "maximumWarning": "2mb", "maximumError": "5mb" }, { "type": "anyComponentStyle", "maximumWarning": "6kb", "maximumError": "10kb" } ] }; // List all your locales here const locales = [ { code: 'en', messageFile: 'messages.en.xlf' }, { code: 'de', messageFile: 'messages.de.xlf' }, // Add more locales as needed: { code: 'fr', messageFile: 'messages.fr.xlf' } ]; // Generate and inject each locale's config into angular.json locales.forEach(locale => { angularJson.projects.web.architect.build.configurations[locale.code] = { ...baseBuildConfig, "outputPath": `dist/web/${locale.code}`, "i18nFile": `src/locale/${locale.messageFile}`, "i18nFormat": "xlf", "i18nLocale": locale.code }; }); // Save the updated config back to angular.json fs.writeFileSync('./angular.json', JSON.stringify(angularJson, null, 2));
Add a script to your package.json to run it easily:
{ "scripts": { "generate-i18n-config": "node generate-i18n-config.js" } }
Now whenever you add a new locale, just update the locales array in the script and run npm run generate-i18n-config—no manual editing of angular.json required.
3. Use Command-Line Arguments with a Shared Base Config
If you prefer to keep angular.json minimal, you can define a single base i18n configuration and pass locale-specific values via the command line.
First, add a shared i18n-base config to angular.json:
{ "projects": { "web": { "architect": { "build": { "configurations": { "i18n-base": { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" } ], "optimization": true, "outputHashing": "all", "sourceMap": false, "extractCss": true, "namedChunks": false, "aot": true, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "budgets": [ { "type": "initial", "maximumWarning": "2mb", "maximumError": "5mb" }, { "type": "anyComponentStyle", "maximumWarning": "6kb", "maximumError": "10kb" } ] } } } } } } }
Then add locale-specific build scripts to package.json:
{ "scripts": { "build:en": "ng build --configuration=i18n-base --output-path=dist/web/en --i18n-file=src/locale/messages.en.xlf --i18n-locale=en", "build:de": "ng build --configuration=i18n-base --output-path=dist/web/de --i18n-file=src/locale/messages.de.xlf --i18n-locale=de" } }
Now you can run npm run build:en or npm run build:de to build each locale without duplicating config in angular.json.
Recommendation
For most projects, the configuration inheritance approach (Option 1) is the best choice—it’s native to Angular, easy to maintain, and avoids extra tooling or scripts. If you have a large number of locales, the script-based generation (Option 2) will save you even more time.
内容的提问来源于stack exchange,提问作者Stefan Falk

