Skip to content

Commit

Permalink
feat(compiler-cli): add i18n parameters to tsconfig
Browse files Browse the repository at this point in the history
You can now add parameters to your tsconfig that will be used when you don't provide cli parameters. It works with ng-xi18n and ngc. Since they both use some parameters with a similar name, those options in tsconfig can have a slightly different name compared to the cli parameters.

Closes angular#16232
Fixes angular#16235
  • Loading branch information
ocombe committed Apr 28, 2017
1 parent de25cfc commit 8a24b8c
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 21 deletions.
34 changes: 23 additions & 11 deletions packages/compiler-cli/src/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,22 @@ export class CodeGenerator {
ngCompilerHost = usePathMapping ? new PathMappedCompilerHost(program, options, context) :
new CompilerHost(program, options, context);
}
let transContent: string = '';
if (cliOptions.i18nFile) {
if (!cliOptions.locale) {

const transFile = cliOptions.i18nFile || options.i18nFile;
const locale = cliOptions.locale || options.translationLocale;
let translations: string = '';
if (transFile) {
if (!locale) {
throw new Error(
`The translation file (${cliOptions.i18nFile}) locale must be provided. Use the --locale option.`);
`The translation file (${transFile}) locale must be provided. Use the --locale option.`);
}
transContent = readFileSync(cliOptions.i18nFile, 'utf8');
translations = readFileSync(transFile, 'utf8');
}

const optMissingTranslation = cliOptions.missingTranslation || options.missingTranslation;
let missingTranslation = MissingTranslationStrategy.Warning;
if (cliOptions.missingTranslation) {
switch (cliOptions.missingTranslation) {
if (optMissingTranslation) {
switch (optMissingTranslation) {
case 'error':
missingTranslation = MissingTranslationStrategy.Error;
break;
Expand All @@ -83,13 +88,20 @@ export class CodeGenerator {
break;
default:
throw new Error(
`Unknown option for missingTranslation (${cliOptions.missingTranslation}). Use either error, warning or ignore.`);
`Unknown option for missingTranslation (${optMissingTranslation}). Use either error, warning or ignore.`);
}
}

let i18nFormat = cliOptions.i18nFormat || options.i18nTranslationFormat || options.i18nFormat;
if (i18nFormat && i18nFormat.toLowerCase() === 'xmb') {
i18nFormat = 'xtb';
}

const {compiler: aotCompiler} = compiler.createAotCompiler(ngCompilerHost, {
translations: transContent,
i18nFormat: cliOptions.i18nFormat,
locale: cliOptions.locale, missingTranslation,
translations,
i18nFormat,
locale,
missingTranslation,
enableLegacyTemplate: options.enableLegacyTemplate !== false,
genFilePreamble: PREAMBLE,
});
Expand Down
5 changes: 3 additions & 2 deletions packages/compiler-cli/src/extract_i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import {Extractor} from './extractor';
function extract(
ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.I18nExtractionCliOptions,
program: ts.Program, host: ts.CompilerHost): Promise<void> {
return Extractor.create(ngOptions, program, host, cliOptions.locale)
.extract(cliOptions.i18nFormat !, cliOptions.outFile);
const format = cliOptions.i18nFormat || ngOptions.i18nFormat || null;
const outFile = cliOptions.outFile || ngOptions.outFile || null;
return Extractor.create(ngOptions, program, host, cliOptions.locale).extract(format, outFile);
}

// Entry point
Expand Down
11 changes: 6 additions & 5 deletions packages/compiler-cli/src/extractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class Extractor {
public host: ts.CompilerHost, private ngCompilerHost: CompilerHost,
private program: ts.Program) {}

extract(formatName: string, outFile: string|null): Promise<void> {
extract(formatName: string|null, outFile: string|null): Promise<void> {
// Checks the format and returns the extension
const ext = this.getExtension(formatName);

Expand All @@ -48,8 +48,8 @@ export class Extractor {
return this.ngExtractor.extract(files);
}

serialize(bundle: compiler.MessageBundle, formatName: string): string {
const format = formatName.toLowerCase();
serialize(bundle: compiler.MessageBundle, formatName: string|null): string {
const format = (formatName || 'xlf').toLowerCase();
let serializer: compiler.Serializer;

switch (format) {
Expand All @@ -70,7 +70,7 @@ export class Extractor {
(sourcePath: string) => sourcePath.replace(path.join(this.options.basePath, '/'), ''));
}

getExtension(formatName: string): string {
getExtension(formatName: string|null): string {
const format = (formatName || 'xlf').toLowerCase();

switch (format) {
Expand Down Expand Up @@ -98,7 +98,8 @@ export class Extractor {
new CompilerHost(program, options, context);
}

const {extractor: ngExtractor} = compiler.Extractor.create(ngCompilerHost, locale || null);
const {extractor: ngExtractor} =
compiler.Extractor.create(ngCompilerHost, locale || options.locale || null);

return new Extractor(options, ngExtractor, tsCompilerHost, ngCompilerHost, program);
}
Expand Down
7 changes: 5 additions & 2 deletions packages/compiler-cli/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ import {isSyntaxError} from '@angular/compiler';

import {CodeGenerator} from './codegen';

function codegen(
function codegenFct(
ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.NgcCliOptions, program: ts.Program,
host: ts.CompilerHost) {
return CodeGenerator.create(ngOptions, cliOptions, program, host).codegen();
}

export function main(
args: any, consoleError: (s: string) => void = console.error): Promise<number> {
args: any, consoleError: (s: string) => void = console.error,
codegen:
(n: tsc.AngularCompilerOptions, c: tsc.NgcCliOptions, p: ts.Program, h: ts.CompilerHost) =>
Promise<any> = codegenFct): Promise<number> {
const project = args.p || args.project || '.';
const cliOptions = new tsc.NgcCliOptions(args);

Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-cli/src/ngtools_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,6 @@ export class NgTools_InternalApi_NG_2 {
const extractor = Extractor.create(
options.angularCompilerOptions, options.program, options.host, locale, hostContext);

return extractor.extract(options.i18nFormat !, options.outFile || null);
return extractor.extract(options.i18nFormat || null, options.outFile || null);
}
}
85 changes: 85 additions & 0 deletions packages/compiler-cli/test/codegen_spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {ɵReflectionCapabilities, ɵreflector} from '@angular/core';
import * as tsc from '@angular/tsc-wrapped';
import {makeTempDir} from '@angular/tsc-wrapped/test/test_support';
import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';

import {main} from '../src/main';


describe('codegen', () => {
let basePath: string;
let write: (fileName: string, content: string) => void;

beforeEach(() => {
basePath = makeTempDir();
write = (fileName: string, content: string) => {
fs.writeFileSync(path.join(basePath, fileName), content, {encoding: 'utf-8'});
};
const nodeModulesPath = path.resolve(basePath, 'node_modules');
fs.mkdirSync(nodeModulesPath);
fs.symlinkSync(path.resolve(__dirname, '..', '..'), path.resolve(nodeModulesPath, '@angular'));
});

// Restore reflector since AoT compiler will update it with a new static reflector
afterEach(() => { ɵreflector.updateCapabilities(new ɵReflectionCapabilities()); });

it('should use i18n params without error', (done) => {
write('tsconfig.json', `{
"compilerOptions": {
"experimentalDecorators": true,
"types": [],
"outDir": "built",
"declaration": true,
"module": "es2015",
"moduleResolution": "node"
},
"angularCompilerOptions": {
"annotateForClosureCompiler": true,
"missingTranslation": "error",
"foo": "bar"
},
"files": ["test.ts"]
}`);

write('test.ts', `const A = 1;`);

spyOn(console, 'error').and.callThrough();

const codegen = jasmine
.createSpy(
'codegenSpy',
(ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.NgcCliOptions,
program: ts.Program, host: ts.CompilerHost) => {
expect(ngOptions.missingTranslation).toBe('error');
expect(ngOptions.i18nFormat).toBeUndefined();
expect(ngOptions.locale).toBeUndefined();
expect((<any>ngOptions).foo).toEqual('bar');

expect(cliOptions.missingTranslation).toBe('ignore');
expect(cliOptions.i18nFormat).toBeNull();
expect(cliOptions.locale).toBeNull();
expect((<any>cliOptions).foo).toBeUndefined();

return Promise.resolve();
})
.and.callThrough();

main({p: basePath, missingTranslation: 'ignore', foo: 'bar'}, console.error, codegen)
.then(() => {
expect(console.error).not.toHaveBeenCalled();
expect(codegen).toHaveBeenCalled();
done();
})
.catch(e => done.fail(e));
});
});
21 changes: 21 additions & 0 deletions tools/@angular/tsc-wrapped/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,27 @@ interface Options extends ts.CompilerOptions {

// Whether to enable support for <template> and the template attribute (true by default)
enableLegacyTemplate?: boolean;

// format for extracted messages file (xlf, xlf2, xmb)
i18nFormat?: string;

// locale of your application for extracted messages file
locale?: string;

// path & name for the extracted messages file
outFile?: string;

// format for imported translation files (xlf, xlf2, xtb)
i18nTranslationFormat?: string;

// locale for imported translation files
translationLocale?: string;

// path & name of your translations file
i18nFile?: string;

// strategy to use for missing translations (error, warning or ignore)
missingTranslation?: string;
}

export default Options;

0 comments on commit 8a24b8c

Please sign in to comment.