mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-23 23:59:27 +08:00
feat(@schematics/angular): add migration to add new i18n options for Ivy
This migration will update current projects by adding the `i18n` project level option and add `localize` option in the server and browser builder configurations when both `i18nLocale` and `i18nFile` are defined.
This commit is contained in:
parent
7045a781ea
commit
750baf92d6
@ -15,7 +15,7 @@ import {
|
||||
removePropertyInAstObject,
|
||||
} from '../../utility/json-utils';
|
||||
import { Builders } from '../../utility/workspace-models';
|
||||
import { getAllOptions, getTargets, getWorkspace, isIvyEnabled } from './utils';
|
||||
import { getAllOptions, getProjectTarget, getTargets, getWorkspace, isIvyEnabled } from './utils';
|
||||
|
||||
export const ANY_COMPONENT_STYLE_BUDGET = {
|
||||
type: 'anyComponentStyle',
|
||||
@ -33,6 +33,7 @@ export function updateWorkspaceConfig(): Rule {
|
||||
updateStyleOrScriptOption('scripts', recorder, target);
|
||||
addAnyComponentStyleBudget(recorder, target);
|
||||
updateAotOption(tree, recorder, target);
|
||||
addBuilderI18NOptions(recorder, target);
|
||||
}
|
||||
|
||||
for (const { target } of getTargets(workspace, 'test', Builders.Karma)) {
|
||||
@ -42,6 +43,11 @@ export function updateWorkspaceConfig(): Rule {
|
||||
|
||||
for (const { target } of getTargets(workspace, 'server', Builders.Server)) {
|
||||
updateOptimizationOption(recorder, target);
|
||||
addBuilderI18NOptions(recorder, target);
|
||||
}
|
||||
|
||||
for (const { target, project } of getTargets(workspace, 'extract-i18n', Builders.ExtractI18n)) {
|
||||
addProjectI18NOptions(recorder, target, project);
|
||||
}
|
||||
|
||||
tree.commitUpdate(recorder);
|
||||
@ -50,6 +56,72 @@ export function updateWorkspaceConfig(): Rule {
|
||||
};
|
||||
}
|
||||
|
||||
function addProjectI18NOptions(recorder: UpdateRecorder, builderConfig: JsonAstObject, projectConfig: JsonAstObject) {
|
||||
const browserConfig = getProjectTarget(projectConfig, 'build', Builders.Browser);
|
||||
if (!browserConfig || browserConfig.kind !== 'object') {
|
||||
return;
|
||||
}
|
||||
|
||||
// browser builder options
|
||||
let locales: Record<string, string> | undefined;
|
||||
const options = getAllOptions(browserConfig);
|
||||
for (const option of options) {
|
||||
const localeId = findPropertyInAstObject(option, 'i18nLocale');
|
||||
if (!localeId || localeId.kind !== 'string') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const localeFile = findPropertyInAstObject(option, 'i18nFile');
|
||||
if (!localeFile || localeFile.kind !== 'string') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const localIdValue = localeId.value;
|
||||
const localeFileValue = localeFile.value;
|
||||
|
||||
if (!locales) {
|
||||
locales = {
|
||||
[localIdValue]: localeFileValue,
|
||||
};
|
||||
} else {
|
||||
locales[localIdValue] = localeFileValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (locales) {
|
||||
// Get sourceLocale from extract-i18n builder
|
||||
const i18nOptions = getAllOptions(builderConfig);
|
||||
const sourceLocale = i18nOptions
|
||||
.map(o => {
|
||||
const sourceLocale = findPropertyInAstObject(o, 'i18nLocale');
|
||||
|
||||
return sourceLocale && sourceLocale.value;
|
||||
})
|
||||
.find(x => !!x);
|
||||
|
||||
// Add i18n project configuration
|
||||
insertPropertyInAstObjectInOrder(recorder, projectConfig, 'i18n', {
|
||||
locales,
|
||||
// tslint:disable-next-line: no-any
|
||||
sourceLocale: sourceLocale as any,
|
||||
}, 6);
|
||||
}
|
||||
}
|
||||
|
||||
function addBuilderI18NOptions(recorder: UpdateRecorder, builderConfig: JsonAstObject) {
|
||||
const options = getAllOptions(builderConfig);
|
||||
|
||||
for (const option of options) {
|
||||
const localeId = findPropertyInAstObject(option, 'i18nLocale');
|
||||
if (!localeId || localeId.kind !== 'string') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// add new localize option
|
||||
insertPropertyInAstObjectInOrder(recorder, option, 'localize', [localeId.value], 12);
|
||||
}
|
||||
}
|
||||
|
||||
function updateAotOption(tree: Tree, recorder: UpdateRecorder, builderConfig: JsonAstObject) {
|
||||
const options = findPropertyInAstObject(builderConfig, 'options');
|
||||
if (!options || options.kind !== 'object') {
|
||||
|
@ -296,5 +296,76 @@ describe('Migration to version 9', () => {
|
||||
expect(config.production.optimization).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('i18n configuration', () => {
|
||||
function getI18NConfig(localId: string): object {
|
||||
return {
|
||||
outputPath: `dist/my-project-${localId}/`,
|
||||
i18nFile: `src/locale/messages.${localId}.xlf`,
|
||||
i18nFormat: 'xlf',
|
||||
i18nLocale: localId,
|
||||
};
|
||||
}
|
||||
|
||||
describe('when i18n builder options are set', () => {
|
||||
it(`should add 'localize' option in configuration`, async () => {
|
||||
let config = getWorkspaceTargets(tree);
|
||||
config.build.options.aot = false;
|
||||
config.build.options = getI18NConfig('fr');
|
||||
config.build.configurations.de = getI18NConfig('de');
|
||||
updateWorkspaceTargets(tree, config);
|
||||
|
||||
const tree2 = await schematicRunner.runSchematicAsync('migration-09', {}, tree.branch()).toPromise();
|
||||
config = getWorkspaceTargets(tree2).build;
|
||||
expect(config.options.localize).toEqual(['fr']);
|
||||
expect(config.configurations.de.localize).toEqual(['de']);
|
||||
});
|
||||
|
||||
it(`should add i18n 'sourceLocale' project config when 'extract-i18n' 'i18nLocale' is defined`, async () => {
|
||||
const config = getWorkspaceTargets(tree);
|
||||
config.build.options.aot = false;
|
||||
config.build.options = getI18NConfig('fr');
|
||||
config['extract-i18n'].options.i18nLocale = 'en-GB';
|
||||
config.build.configurations.de = getI18NConfig('de');
|
||||
updateWorkspaceTargets(tree, config);
|
||||
|
||||
const tree2 = await schematicRunner.runSchematicAsync('migration-09', {}, tree.branch()).toPromise();
|
||||
const projectConfig = JSON.parse(tree2.readContent(workspacePath)).projects['migration-test'];
|
||||
expect(projectConfig.i18n.sourceLocale).toBe('en-GB');
|
||||
expect(projectConfig.i18n.locales).toBeDefined();
|
||||
});
|
||||
|
||||
it(`should add i18n 'locales' project config`, async () => {
|
||||
const config = getWorkspaceTargets(tree);
|
||||
config.build.options.aot = false;
|
||||
config.build.options = getI18NConfig('fr');
|
||||
config.build.configurations.de = getI18NConfig('de');
|
||||
updateWorkspaceTargets(tree, config);
|
||||
|
||||
const tree2 = await schematicRunner.runSchematicAsync('migration-09', {}, tree.branch()).toPromise();
|
||||
const projectConfig = JSON.parse(tree2.readContent(workspacePath)).projects['migration-test'];
|
||||
expect(projectConfig.i18n.sourceLocale).toBeUndefined();
|
||||
expect(projectConfig.i18n.locales).toEqual({
|
||||
de: 'src/locale/messages.de.xlf',
|
||||
fr: 'src/locale/messages.fr.xlf',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when i18n builder options are not set', () => {
|
||||
it(`should not add 'localize' option`, async () => {
|
||||
const tree2 = await schematicRunner.runSchematicAsync('migration-09', {}, tree.branch()).toPromise();
|
||||
const config = getWorkspaceTargets(tree2).build;
|
||||
expect(config.options.localize).toBeUndefined();
|
||||
expect(config.configurations.production.localize).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not add i18n project config', async () => {
|
||||
const tree2 = await schematicRunner.runSchematicAsync('migration-09', {}, tree.branch()).toPromise();
|
||||
const projectConfig = JSON.parse(tree2.readContent(workspacePath)).projects['migration-test'];
|
||||
expect(projectConfig.i18n).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -12,7 +12,36 @@ import { getWorkspacePath } from '../../utility/config';
|
||||
import { findPropertyInAstObject } from '../../utility/json-utils';
|
||||
import { Builders, WorkspaceTargets } from '../../utility/workspace-models';
|
||||
|
||||
/** Get all workspace targets which builder and target names matches the provided. */
|
||||
/** Get a project target which builder and target names matches the provided. */
|
||||
export function getProjectTarget(
|
||||
project: JsonAstObject,
|
||||
targetName: Exclude<keyof WorkspaceTargets, number>,
|
||||
builderName: Builders,
|
||||
): JsonAstObject | undefined {
|
||||
const projectRoot = findPropertyInAstObject(project, 'root');
|
||||
if (!projectRoot || projectRoot.kind !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const architect = findPropertyInAstObject(project, 'architect');
|
||||
if (!architect || architect.kind !== 'object') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const target = findPropertyInAstObject(architect, targetName);
|
||||
if (!target || target.kind !== 'object') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const builder = findPropertyInAstObject(target, 'builder');
|
||||
// Projects who's build builder is @angular-devkit/build-ng-packagr
|
||||
if (builder && builder.kind === 'string' && builder.value === builderName) {
|
||||
return target;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getTargets(
|
||||
workspace: JsonAstObject,
|
||||
targetName: Exclude<keyof WorkspaceTargets, number>,
|
||||
@ -30,24 +59,8 @@ export function getTargets(
|
||||
continue;
|
||||
}
|
||||
|
||||
const projectRoot = findPropertyInAstObject(projectConfig, 'root');
|
||||
if (!projectRoot || projectRoot.kind !== 'string') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const architect = findPropertyInAstObject(projectConfig, 'architect');
|
||||
if (!architect || architect.kind !== 'object') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const target = findPropertyInAstObject(architect, targetName);
|
||||
if (!target || target.kind !== 'object') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const builder = findPropertyInAstObject(target, 'builder');
|
||||
// Projects who's build builder is @angular-devkit/build-ng-packagr
|
||||
if (builder && builder.kind === 'string' && builder.value === builderName) {
|
||||
const target = getProjectTarget(projectConfig, targetName, builderName);
|
||||
if (target) {
|
||||
targets.push({ target, project: projectConfig });
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user