/
githubmirror
/
angular-cli
Обзор
Документация
Войти
/
githubmirror
/
angular-cli
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/angular/build/src/tools/esbuild/i18n-locale-plugin.ts
156 строк
6 KB
Charles Lyding
fix(@angular/build): prevent externalizing builder-injected i18n locale data
08 июл 2026, 17:49
08 июл 2026, 17:49
85c53d9
Код
Авторство
О чём код?
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ import type { Plugin, ResolveResult } from 'esbuild'; import { createProjectResolver } from '../../utils/resolve-project'; /** * The internal namespace used by generated locale import statements and Angular locale data plugin. */ export const LOCALE_DATA_NAMESPACE = 'angular:locale/data'; /** * The base module location used to search for locale specific data. */ export const LOCALE_DATA_BASE_MODULE = '@angular/common/locales/global'; /** * Creates an esbuild plugin that resolves Angular locale data files from `@angular/common`. * * @returns An esbuild plugin. */ export function createAngularLocaleDataPlugin(): Plugin { return { name: 'angular-locale-data', setup(build): void { build.onResolve({ filter: /^angular:locale\/data:/ }, async ({ path }) => { // Extract the locale from the path const rawLocaleTag = path.split(':', 3)[2]; // Extract and normalize the base name of the raw locale tag let partialLocaleTag: string; try { const locale = new Intl.Locale(rawLocaleTag); partialLocaleTag = locale.baseName; } catch { return { path: rawLocaleTag, namespace: LOCALE_DATA_NAMESPACE, errors: [ { text: `Invalid or unsupported locale provided in configuration: "${rawLocaleTag}"`, }, ], }; } let exact = true; let projectResolve: ((packageName: string) => string) | undefined; while (partialLocaleTag) { // Angular embeds the `en`/`en-US` locale into the framework and it does not need to be included again here. // The onLoad hook below for the locale data namespace has an `empty` loader that will prevent inclusion. // Angular does not contain exact locale data for `en-US` but `en` is equivalent. if (partialLocaleTag === 'en' || partialLocaleTag === 'en-US') { return { path: rawLocaleTag, namespace: LOCALE_DATA_NAMESPACE, }; } // Attempt to resolve the locale tag data within the Angular base module location const potentialPath = `${LOCALE_DATA_BASE_MODULE}/${partialLocaleTag}`; // If packages are configured to be external then leave the original angular locale import path. // This happens when using the development server with caching enabled to allow Vite prebundling to work. // There currently is no option on the esbuild resolve function to resolve while disabling the option. // NOTE: If esbuild eventually allows controlling the external package options in a build.resolve call, this // workaround can be removed. let result: ResolveResult | undefined; const { packages, absWorkingDir } = build.initialOptions; if (packages === 'external' && absWorkingDir) { projectResolve ??= createProjectResolver(absWorkingDir); try { projectResolve(potentialPath); result = { errors: [], warnings: [], external: true, sideEffects: true, namespace: '', suffix: '', pluginData: undefined, path: potentialPath, }; } catch {} } else { result = await build.resolve(potentialPath, { kind: 'import-statement', resolveDir: absWorkingDir, }); if (result && result.external && absWorkingDir) { projectResolve ??= createProjectResolver(absWorkingDir); try { const resolvedPath = projectResolve(potentialPath); result = { ...result, external: false, path: resolvedPath, }; } catch {} } } if (result?.path) { if (exact) { return result; } else { return { ...result, warnings: [ ...result.warnings, { location: null, text: `Locale data for '${rawLocaleTag}' cannot be found. Using locale data for '${partialLocaleTag}'.`, }, ], }; } } // Remove the last subtag and try again with a less specific locale. // Usually the match is exact so the string splitting here is not done until actually needed after the exact // match fails to resolve. const parts = partialLocaleTag.split('-'); partialLocaleTag = parts.slice(0, -1).join('-'); exact = false; } // Not found so issue a warning and use an empty loader. Framework built-in `en-US` data will be used. // This retains existing behavior as in the Webpack-based builder. return { path: rawLocaleTag, namespace: LOCALE_DATA_NAMESPACE, warnings: [ { location: null, text: `Locale data for '${rawLocaleTag}' cannot be found. No locale data will be included for this locale.`, }, ], }; }); // Locales that cannot be found will be loaded as empty content with a warning from the resolve step build.onLoad({ filter: /./, namespace: LOCALE_DATA_NAMESPACE }, () => ({ contents: '', loader: 'empty', })); }, }; }