Skip to content

Commit

Permalink
fix(@angular-devkit/build-angular): remove deprecated View Engine sup…
Browse files Browse the repository at this point in the history
…port for i18n extraction

BREAKING CHANGE: Removal of View Engine support from i18n extraction
With the removal of the deprecated View Engine compiler in Angular version 12 for applications, the `ng extract-i18n` command will now always use the Ivy compiler.
The `--ivy` option has also been removed as Ivy-based extraction is always enabled.
The default behavior for applications is to use the Ivy compiler for building/extraction and no changes are required for these applications.
For applications that have opted-out of Ivy, a warning will be shown and Ivy-based extraction will be attempted. If the extraction fails,
the application may need to be updated to become Ivy compatible.
  • Loading branch information
clydin authored and filipesilva committed Mar 30, 2021
1 parent 3388418 commit 012700a
Show file tree
Hide file tree
Showing 11 changed files with 33 additions and 283 deletions.
74 changes: 28 additions & 46 deletions packages/angular_devkit/build_angular/src/extract-i18n/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ export async function execute(
const metadata = await context.getProjectMetadata(context.target);
const i18n = createI18nOptions(metadata);

let usingIvy = false;
let useLegacyIds = true;

const ivyMessages: LocalizeMessage[] = [];
Expand Down Expand Up @@ -198,52 +197,37 @@ export async function execute(
},
context,
(wco) => {
const isIvyApplication = wco.tsConfig.options.enableIvy !== false;

// Default value for legacy message ids is currently true
useLegacyIds = wco.tsConfig.options.enableI18nLegacyMessageIdFormat ?? true;

// Ivy extraction is the default for Ivy applications.
usingIvy = (isIvyApplication && options.ivy === undefined) || !!options.ivy;

if (usingIvy) {
if (!isIvyApplication) {
context.logger.warn(
'Ivy extraction enabled but application is not Ivy enabled. Extraction may fail.',
);
}
} else if (isIvyApplication) {
if (wco.tsConfig.options.enableIvy === false) {
context.logger.warn(
'Ivy extraction not enabled but application is Ivy enabled. ' +
'If the extraction fails, the `--ivy` flag will enable Ivy extraction.',
'Ivy extraction enabled but application is not Ivy enabled. Extraction may fail.',
);
}

// Default value for legacy message ids is currently true
useLegacyIds = wco.tsConfig.options.enableI18nLegacyMessageIdFormat ?? true;

const partials = [
{ plugins: [new NoEmitPlugin()] },
getCommonConfig(wco),
getBrowserConfig(wco),
// Only use VE extraction if not using Ivy
getAotConfig(wco, !usingIvy),
getAotConfig(wco),
getStatsConfig(wco),
];

// Add Ivy application file extractor support
if (usingIvy) {
partials.unshift({
module: {
rules: [
{
test: /\.[t|j]s$/,
loader: require.resolve('./ivy-extract-loader'),
options: {
messageHandler: (messages: LocalizeMessage[]) => ivyMessages.push(...messages),
},
partials.unshift({
module: {
rules: [
{
test: /\.[t|j]s$/,
loader: require.resolve('./ivy-extract-loader'),
options: {
messageHandler: (messages: LocalizeMessage[]) => ivyMessages.push(...messages),
},
],
},
});
}
},
],
},
});

// Replace all stylesheets with an empty default export
partials.push({
Expand All @@ -259,16 +243,14 @@ export async function execute(
},
);

if (usingIvy) {
try {
require.resolve('@angular/localize');
} catch {
return {
success: false,
error: `Ivy extraction requires the '@angular/localize' package.`,
outputPath: outFile,
};
}
try {
require.resolve('@angular/localize');
} catch {
return {
success: false,
error: `Ivy extraction requires the '@angular/localize' package.`,
outputPath: outFile,
};
}

const webpackResult = await runWebpack(
Expand All @@ -283,8 +265,8 @@ export async function execute(
// Set the outputPath to the extraction output location for downstream consumers
webpackResult.outputPath = outFile;

// Complete if using VE or if Webpack build failed
if (!usingIvy || !webpackResult.success) {
// Complete if Webpack build failed
if (!webpackResult.success) {
return webpackResult;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,6 @@
"description": "Specifies the source language of the application.",
"x-deprecated": "Use 'i18n' project level sub-option 'sourceLocale' instead."
},
"ivy": {
"type": "boolean",
"description": "Use Ivy compiler to extract translations. The default for Ivy applications."
},
"progress": {
"type": "boolean",
"description": "Log progress to the console.",
Expand Down
24 changes: 0 additions & 24 deletions tests/legacy-cli/e2e/tests/i18n/build-locale.ts

This file was deleted.

21 changes: 0 additions & 21 deletions tests/legacy-cli/e2e/tests/i18n/extract-default.ts

This file was deleted.

28 changes: 0 additions & 28 deletions tests/legacy-cli/e2e/tests/i18n/extract-errors.ts

This file was deleted.

2 changes: 1 addition & 1 deletion tests/legacy-cli/e2e/tests/i18n/extract-ivy-libraries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export default async function() {
await installPackage(localizeVersion);

// Extract messages
await ng('extract-i18n', '--ivy');
await ng('extract-i18n');
await expectFileToMatch('messages.xlf', 'Hello world');
await expectFileToMatch('messages.xlf', 'i18n-lib-test works!');
await expectFileToMatch('messages.xlf', 'src/app/app.component.html');
Expand Down
19 changes: 4 additions & 15 deletions tests/legacy-cli/e2e/tests/i18n/extract-ivy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,14 @@ import { expectToFail } from '../../utils/utils';
import { readNgVersion } from '../../utils/version';

export default async function() {
// Ivy only test
if (getGlobalVariable('argv')['ve']) {
return;
}

// Setup an i18n enabled component
await ng('generate', 'component', 'i18n-test');
await writeFile(
join('src/app/i18n-test', 'i18n-test.component.html'),
'<p i18n>Hello world</p>',
);

// Should fail with --ivy flag if `@angular/localize` is missing
// Should fail if `@angular/localize` is missing
const { message: message1 } = await expectToFail(() => ng('extract-i18n'));
if (!message1.includes(`Ivy extraction requires the '@angular/localize' package.`)) {
throw new Error('Expected localize package error message when missing');
Expand All @@ -33,14 +28,8 @@ export default async function() {
}
await installPackage(localizeVersion);

// Should show ivy enabled application warning without --ivy flag
const { stderr: message3 } = await ng('extract-i18n', '--no-ivy');
if (!message3.includes(`Ivy extraction not enabled but application is Ivy enabled.`)) {
throw new Error('Expected ivy enabled application warning');
}

// Should not show any warnings when extracting
const { stderr: message5 } = await ng('extract-i18n', '--ivy');
const { stderr: message5 } = await ng('extract-i18n');
if (message5.includes('WARNING')) {
throw new Error('Expected no warnings to be shown');
}
Expand All @@ -52,8 +41,8 @@ export default async function() {
config.angularCompilerOptions = angularCompilerOptions;
});

// Should show ivy disabled application warning with --ivy flag and enableIvy false
const { message: message4 } = await expectToFail(() => ng('extract-i18n', '--ivy'));
// Should show ivy disabled application warning with enableIvy false
const { message: message4 } = await expectToFail(() => ng('extract-i18n'));
if (!message4.includes(`Ivy extraction enabled but application is not Ivy enabled.`)) {
throw new Error('Expected ivy disabled application warning');
}
Expand Down
23 changes: 0 additions & 23 deletions tests/legacy-cli/e2e/tests/i18n/extract-locale.ts

This file was deleted.

19 changes: 0 additions & 19 deletions tests/legacy-cli/e2e/tests/i18n/extract-outfile.ts

This file was deleted.

23 changes: 0 additions & 23 deletions tests/legacy-cli/e2e/tests/i18n/extract-xmb.ts

This file was deleted.

Loading

0 comments on commit 012700a

Please sign in to comment.