Skip to content

Commit 0009d92

Browse files
author
Angular Builds
committed
aa9e7c6 fix(@angular-devkit/build-angular): normalize locale tags with Intl API when resolving in application builder
1 parent ad72039 commit 0009d92

File tree

4 files changed

+58
-24
lines changed

4 files changed

+58
-24
lines changed

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
22
"name": "@angular-devkit/build-angular",
3-
"version": "17.0.5+sha-bce3fa6",
3+
"version": "17.0.5+sha-aa9e7c6",
44
"description": "Angular Webpack Build Facade",
55
"main": "src/index.js",
66
"typings": "src/index.d.ts",
77
"builders": "builders.json",
88
"dependencies": {
99
"@ampproject/remapping": "2.2.1",
10-
"@angular-devkit/architect": "github:angular/angular-devkit-architect-builds#bce3fa6",
11-
"@angular-devkit/build-webpack": "github:angular/angular-devkit-build-webpack-builds#bce3fa6",
12-
"@angular-devkit/core": "github:angular/angular-devkit-core-builds#bce3fa6",
10+
"@angular-devkit/architect": "github:angular/angular-devkit-architect-builds#aa9e7c6",
11+
"@angular-devkit/build-webpack": "github:angular/angular-devkit-build-webpack-builds#aa9e7c6",
12+
"@angular-devkit/core": "github:angular/angular-devkit-core-builds#aa9e7c6",
1313
"@babel/core": "7.23.2",
1414
"@babel/generator": "7.23.0",
1515
"@babel/helper-annotate-as-pure": "7.22.5",
@@ -20,7 +20,7 @@
2020
"@babel/preset-env": "7.23.2",
2121
"@babel/runtime": "7.23.2",
2222
"@discoveryjs/json-ext": "0.5.7",
23-
"@ngtools/webpack": "github:angular/ngtools-webpack-builds#bce3fa6",
23+
"@ngtools/webpack": "github:angular/ngtools-webpack-builds#aa9e7c6",
2424
"@vitejs/plugin-basic-ssl": "1.0.1",
2525
"ansi-colors": "4.1.3",
2626
"autoprefixer": "10.4.16",

src/tools/esbuild/i18n-locale-plugin.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
import type { Plugin } from 'esbuild';
9+
/**
10+
* The internal namespace used by generated locale import statements and Angular locale data plugin.
11+
*/
12+
export declare const LOCALE_DATA_NAMESPACE = "angular:locale/data";
913
/**
1014
* The base module location used to search for locale specific data.
1115
*/

src/tools/esbuild/i18n-locale-plugin.js

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
* found in the LICENSE file at https://angular.io/license
88
*/
99
Object.defineProperty(exports, "__esModule", { value: true });
10-
exports.createAngularLocaleDataPlugin = exports.LOCALE_DATA_BASE_MODULE = void 0;
10+
exports.createAngularLocaleDataPlugin = exports.LOCALE_DATA_BASE_MODULE = exports.LOCALE_DATA_NAMESPACE = void 0;
11+
/**
12+
* The internal namespace used by generated locale import statements and Angular locale data plugin.
13+
*/
14+
exports.LOCALE_DATA_NAMESPACE = 'angular:locale/data';
1115
/**
1216
* The base module location used to search for locale specific data.
1317
*/
@@ -33,12 +37,37 @@ function createAngularLocaleDataPlugin() {
3337
}
3438
build.onResolve({ filter: /^angular:locale\/data:/ }, async ({ path }) => {
3539
// Extract the locale from the path
36-
const originalLocale = path.split(':', 3)[2];
37-
// Remove any private subtags since these will never match
38-
let partialLocale = originalLocale.replace(/-x(-[a-zA-Z0-9]{1,8})+$/, '');
40+
const rawLocaleTag = path.split(':', 3)[2];
41+
// Extract and normalize the base name of the raw locale tag
42+
let partialLocaleTag;
43+
try {
44+
const locale = new Intl.Locale(rawLocaleTag);
45+
partialLocaleTag = locale.baseName;
46+
}
47+
catch {
48+
return {
49+
path: rawLocaleTag,
50+
namespace: exports.LOCALE_DATA_NAMESPACE,
51+
errors: [
52+
{
53+
text: `Invalid or unsupported locale provided in configuration: "${rawLocaleTag}"`,
54+
},
55+
],
56+
};
57+
}
3958
let exact = true;
40-
while (partialLocale) {
41-
const potentialPath = `${exports.LOCALE_DATA_BASE_MODULE}/${partialLocale}`;
59+
while (partialLocaleTag) {
60+
// Angular embeds the `en`/`en-US` locale into the framework and it does not need to be included again here.
61+
// The onLoad hook below for the locale data namespace has an `empty` loader that will prevent inclusion.
62+
// Angular does not contain exact locale data for `en-US` but `en` is equivalent.
63+
if (partialLocaleTag === 'en' || partialLocaleTag === 'en-US') {
64+
return {
65+
path: rawLocaleTag,
66+
namespace: exports.LOCALE_DATA_NAMESPACE,
67+
};
68+
}
69+
// Attempt to resolve the locale tag data within the Angular base module location
70+
const potentialPath = `${exports.LOCALE_DATA_BASE_MODULE}/${partialLocaleTag}`;
4271
const result = await build.resolve(potentialPath, {
4372
kind: 'import-statement',
4473
resolveDir: build.initialOptions.absWorkingDir,
@@ -54,36 +83,37 @@ function createAngularLocaleDataPlugin() {
5483
...result.warnings,
5584
{
5685
location: null,
57-
text: `Locale data for '${originalLocale}' cannot be found. Using locale data for '${partialLocale}'.`,
86+
text: `Locale data for '${rawLocaleTag}' cannot be found. Using locale data for '${partialLocaleTag}'.`,
5887
},
5988
],
6089
};
6190
}
6291
}
63-
// Remove the last subtag and try again with a less specific locale
64-
const parts = partialLocale.split('-');
65-
partialLocale = parts.slice(0, -1).join('-');
92+
// Remove the last subtag and try again with a less specific locale.
93+
// Usually the match is exact so the string splitting here is not done until actually needed after the exact
94+
// match fails to resolve.
95+
const parts = partialLocaleTag.split('-');
96+
partialLocaleTag = parts.slice(0, -1).join('-');
6697
exact = false;
67-
// The locales "en" and "en-US" are considered exact to retain existing behavior
68-
if (originalLocale === 'en-US' && partialLocale === 'en') {
69-
exact = true;
70-
}
7198
}
7299
// Not found so issue a warning and use an empty loader. Framework built-in `en-US` data will be used.
73100
// This retains existing behavior as in the Webpack-based builder.
74101
return {
75-
path: originalLocale,
76-
namespace: 'angular:locale/data',
102+
path: rawLocaleTag,
103+
namespace: exports.LOCALE_DATA_NAMESPACE,
77104
warnings: [
78105
{
79106
location: null,
80-
text: `Locale data for '${originalLocale}' cannot be found. No locale data will be included for this locale.`,
107+
text: `Locale data for '${rawLocaleTag}' cannot be found. No locale data will be included for this locale.`,
81108
},
82109
],
83110
};
84111
});
85112
// Locales that cannot be found will be loaded as empty content with a warning from the resolve step
86-
build.onLoad({ filter: /./, namespace: 'angular:locale/data' }, () => ({ loader: 'empty' }));
113+
build.onLoad({ filter: /./, namespace: exports.LOCALE_DATA_NAMESPACE }, () => ({
114+
contents: '',
115+
loader: 'empty',
116+
}));
87117
},
88118
};
89119
}

uniqueId

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Mon Dec 04 2023 08:16:43 GMT+0000 (Coordinated Universal Time)
1+
Mon Dec 04 2023 08:37:36 GMT+0000 (Coordinated Universal Time)

0 commit comments

Comments
 (0)