7
7
*/
8
8
import { custom } from 'babel-loader' ;
9
9
import { ScriptTarget } from 'typescript' ;
10
+ import { ApplicationPresetOptions } from './presets/application' ;
10
11
11
12
interface AngularCustomOptions {
12
13
forceAsyncTransformation : boolean ;
13
14
forceES5 : boolean ;
14
15
shouldLink : boolean ;
16
+ i18n : ApplicationPresetOptions [ 'i18n' ] ;
15
17
}
16
18
17
19
/**
@@ -65,48 +67,76 @@ export default custom<AngularCustomOptions>(() => {
65
67
} ) ;
66
68
67
69
return {
68
- async customOptions ( { scriptTarget, ...loaderOptions } , { source } ) {
70
+ async customOptions ( { i18n , scriptTarget, ...rawOptions } , { source } ) {
69
71
// Must process file if plugins are added
70
- let shouldProcess = Array . isArray ( loaderOptions . plugins ) && loaderOptions . plugins . length > 0 ;
72
+ let shouldProcess = Array . isArray ( rawOptions . plugins ) && rawOptions . plugins . length > 0 ;
73
+
74
+ const customOptions : AngularCustomOptions = {
75
+ forceAsyncTransformation : false ,
76
+ forceES5 : false ,
77
+ shouldLink : false ,
78
+ i18n : undefined ,
79
+ } ;
71
80
72
81
// Analyze file for linking
73
- let shouldLink = false ;
74
82
const { hasLinkerSupport, requiresLinking } = await checkLinking ( this . resourcePath , source ) ;
75
83
if ( requiresLinking && ! hasLinkerSupport ) {
76
84
// Cannot link if there is no linker support
77
85
this . emitError (
78
86
'File requires the Angular linker. "@angular/compiler-cli" version 11.1.0 or greater is needed.' ,
79
87
) ;
80
88
} else {
81
- shouldLink = requiresLinking ;
89
+ customOptions . shouldLink = requiresLinking ;
82
90
}
83
- shouldProcess ||= shouldLink ;
91
+ shouldProcess ||= customOptions . shouldLink ;
84
92
85
93
// Analyze for ES target processing
86
- let forceES5 = false ;
87
- let forceAsyncTransformation = false ;
88
- const esTarget = scriptTarget as ScriptTarget ;
89
- if ( esTarget < ScriptTarget . ES2015 ) {
90
- // TypeScript files will have already been downlevelled
91
- forceES5 = ! / \. t s x ? $ / . test ( this . resourcePath ) ;
92
- } else if ( esTarget >= ScriptTarget . ES2017 ) {
93
- forceAsyncTransformation = source . includes ( 'async' ) ;
94
+ const esTarget = scriptTarget as ScriptTarget | undefined ;
95
+ if ( esTarget !== undefined ) {
96
+ if ( esTarget < ScriptTarget . ES2015 ) {
97
+ // TypeScript files will have already been downlevelled
98
+ customOptions . forceES5 = ! / \. t s x ? $ / . test ( this . resourcePath ) ;
99
+ } else if ( esTarget >= ScriptTarget . ES2017 ) {
100
+ customOptions . forceAsyncTransformation = source . includes ( 'async' ) ;
101
+ }
102
+ shouldProcess ||= customOptions . forceAsyncTransformation || customOptions . forceES5 ;
103
+ }
104
+
105
+ // Analyze for i18n inlining
106
+ if (
107
+ i18n &&
108
+ ! / [ \\ \/ ] @ a n g u l a r [ \\ \/ ] (?: c o m p i l e r | l o c a l i z e ) / . test ( this . resourcePath ) &&
109
+ source . includes ( '$localize' )
110
+ ) {
111
+ const { translationFiles, ...i18nOptions } = i18n as ApplicationPresetOptions [ 'i18n' ] & {
112
+ translationFiles ?: string [ ] ;
113
+ } ;
114
+ customOptions . i18n = i18nOptions ;
115
+
116
+ // Add translation files as dependencies of the file to support rebuilds
117
+ // Except for `@angular/core` which needs locale injection but has no translations
118
+ if ( translationFiles && ! / [ \\ \/ ] @ a n g u l a r [ \\ \/ ] c o r e / . test ( this . resourcePath ) ) {
119
+ for ( const file of translationFiles ) {
120
+ this . addDependency ( file ) ;
121
+ }
122
+ }
123
+
124
+ shouldProcess = true ;
94
125
}
95
- shouldProcess ||= forceAsyncTransformation || forceES5 ;
96
126
97
127
// Add provided loader options to default base options
98
- const options : Record < string , unknown > = {
128
+ const loaderOptions : Record < string , unknown > = {
99
129
...baseOptions ,
100
- ...loaderOptions ,
130
+ ...rawOptions ,
101
131
} ;
102
132
103
133
// Skip babel processing if no actions are needed
104
134
if ( ! shouldProcess ) {
105
135
// Force the current file to be ignored
106
- options . ignore = [ ( ) => true ] ;
136
+ loaderOptions . ignore = [ ( ) => true ] ;
107
137
}
108
138
109
- return { custom : { forceAsyncTransformation , forceES5 , shouldLink } , loader : options } ;
139
+ return { custom : customOptions , loader : loaderOptions } ;
110
140
} ,
111
141
config ( configuration , { customOptions } ) {
112
142
return {
@@ -119,6 +149,7 @@ export default custom<AngularCustomOptions>(() => {
119
149
angularLinker : customOptions . shouldLink ,
120
150
forceES5 : customOptions . forceES5 ,
121
151
forceAsyncTransformation : customOptions . forceAsyncTransformation ,
152
+ i18n : customOptions . i18n ,
122
153
diagnosticReporter : ( type , message ) => {
123
154
switch ( type ) {
124
155
case 'error' :
@@ -131,7 +162,7 @@ export default custom<AngularCustomOptions>(() => {
131
162
break ;
132
163
}
133
164
} ,
134
- } as import ( './presets/application' ) . ApplicationPresetOptions ,
165
+ } as ApplicationPresetOptions ,
135
166
] ,
136
167
] ,
137
168
} ;
0 commit comments