Skip to content

Commit

Permalink
refactor(@angular/cli): provide a default extract-i18n target for app…
Browse files Browse the repository at this point in the history
…lications

The `extract-i18n` command will now use a default project target and builder
name if the target entry is not explicitly defined. This allows the removal
of additional configuration from an `angular.json` file. If the target is
already present than it will take priority over any default builder behavior.
Infrastructure is also now present to allow other architect commands to
have similar functionality in the future.

(cherry picked from commit afbe311)
  • Loading branch information
clydin authored and alan-agius4 committed Jul 8, 2024
1 parent 4c6c32c commit 1772c87
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { Target } from '@angular-devkit/architect';
import { workspaces } from '@angular-devkit/core';
import { Argv } from 'yargs';
import { getProjectByCwd } from '../utilities/config';
import { memoize } from '../utilities/memoize';
Expand All @@ -28,7 +30,33 @@ export abstract class ArchitectCommandModule
{
abstract readonly multiTarget: boolean;

findDefaultBuilderName?(
project: workspaces.ProjectDefinition,
target: Target,
): Promise<string | undefined>;

async builder(argv: Argv): Promise<Argv<ArchitectCommandArgs>> {
const target = this.getArchitectTarget();

// Add default builder if target is not in project and a command default is provided
if (this.findDefaultBuilderName && this.context.workspace) {
for (const [project, projectDefinition] of this.context.workspace.projects) {
if (projectDefinition.targets.has(target)) {
continue;
}

const defaultBuilder = await this.findDefaultBuilderName(projectDefinition, {
project,
target,
});
if (defaultBuilder) {
projectDefinition.targets.set(target, {
builder: defaultBuilder,
});
}
}
}

const project = this.getArchitectProject();
const { jsonHelp, getYargsCompletions, help } = this.context.args.options;

Expand Down Expand Up @@ -60,7 +88,6 @@ export abstract class ArchitectCommandModule
return localYargs;
}

const target = this.getArchitectTarget();
const schemaOptions = await this.getArchitectTargetOptions({
project,
target,
Expand Down
37 changes: 37 additions & 0 deletions packages/angular/cli/src/commands/extract-i18n/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
* found in the LICENSE file at https://angular.dev/license
*/

import { workspaces } from '@angular-devkit/core';
import { createRequire } from 'node:module';
import { join } from 'node:path';
import { ArchitectCommandModule } from '../../command-builder/architect-command-module';
import { CommandModuleImplementation } from '../../command-builder/command-module';

Expand All @@ -17,4 +20,38 @@ export default class ExtractI18nCommandModule
command = 'extract-i18n [project]';
describe = 'Extracts i18n messages from source code.';
longDescriptionPath?: string | undefined;

override async findDefaultBuilderName(
project: workspaces.ProjectDefinition,
): Promise<string | undefined> {
// Only application type projects have a default i18n extraction target
if (project.extensions['projectType'] !== 'application') {
return;
}

const buildTarget = project.targets.get('build');
if (!buildTarget) {
// No default if there is no build target
return;
}

// Provide a default based on the defined builder for the 'build' target
switch (buildTarget.builder) {
case '@angular-devkit/build-angular:application':
case '@angular-devkit/build-angular:browser-esbuild':
case '@angular-devkit/build-angular:browser':
return '@angular-devkit/build-angular:extract-i18n';
case '@angular/build:application':
return '@angular/build:extract-i18n';
}

// For other builders, check for `@angular-devkit/build-angular` and use if found.
// This package is safer to use since it supports both application builder types.
try {
const projectRequire = createRequire(join(this.context.root, project.root) + '/');
projectRequire.resolve('@angular-devkit/build-angular');

return '@angular-devkit/build-angular:extract-i18n';
} catch {}
}
}

0 comments on commit 1772c87

Please sign in to comment.