Skip to content

Commit

Permalink
feat(i18n): add i18n command line options (#3098)
Browse files Browse the repository at this point in the history
Also available on the webpack plugin.
  • Loading branch information
tdesmet authored and hansl committed Dec 14, 2016
1 parent 1352545 commit 2a0a42d
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 10 deletions.
26 changes: 22 additions & 4 deletions packages/@ngtools/webpack/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ export interface AotPluginOptions {
entryModule?: string;
mainPath?: string;
typeChecking?: boolean;

skipCodeGeneration?: boolean;
i18nFile?: string;
i18nFormat?: string;
locale?: string;
}


Expand Down Expand Up @@ -78,6 +80,9 @@ export class AotPlugin implements Tapable {
private _basePath: string;
private _genDir: string;

private _i18nFile: string;
private _i18nFormat: string;
private _locale: string;

constructor(options: AotPluginOptions) {
this._setupOptions(options);
Expand All @@ -93,6 +98,9 @@ export class AotPlugin implements Tapable {
get program() { return this._program; }
get skipCodeGeneration() { return this._skipCodeGeneration; }
get typeCheck() { return this._typeCheck; }
get i18nFile() { return this._i18nFile; }
get i18nFormat() { return this._i18nFormat; }
get locale() { return this._locale; }

private _setupOptions(options: AotPluginOptions) {
// Fill in the missing options.
Expand Down Expand Up @@ -153,6 +161,16 @@ export class AotPlugin implements Tapable {
this._reflectorHost = new ngCompiler.ReflectorHost(
this._program, this._compilerHost, this._angularCompilerOptions);
this._reflector = new ngCompiler.StaticReflector(this._reflectorHost);

if (options.hasOwnProperty('i18nFile')) {
this._i18nFile = options.i18nFile;
}
if (options.hasOwnProperty('i18nFormat')) {
this._i18nFormat = options.i18nFormat;
}
if (options.hasOwnProperty('locale')) {
this._locale = options.locale;
}
}

// registration hook for webpack plugin
Expand Down Expand Up @@ -222,9 +240,9 @@ export class AotPlugin implements Tapable {
this._resourceLoader = new WebpackResourceLoader(compilation);

const i18nOptions: ngCompiler.NgcCliOptions = {
i18nFile: undefined,
i18nFormat: undefined,
locale: undefined,
i18nFile: this.i18nFile,
i18nFormat: this.i18nFormat,
locale: this.locale,
basePath: this.basePath
};

Expand Down
8 changes: 7 additions & 1 deletion packages/angular-cli/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ export interface BuildOptions {
vendorChunk?: boolean;
verbose?: boolean;
progress?: boolean;
i18nFile?: string;
i18nFormat?: string;
locale?: string;
}

const BuildCommand = Command.extend({
Expand All @@ -39,7 +42,10 @@ const BuildCommand = Command.extend({
{ name: 'sourcemap', type: Boolean, default: true, aliases: ['sm'] },
{ name: 'vendor-chunk', type: Boolean, default: true },
{ name: 'verbose', type: Boolean, default: false },
{ name: 'progress', type: Boolean, default: true }
{ name: 'progress', type: Boolean, default: true },
{ name: 'i18n-file', type: String, default: null },
{ name: 'i18n-format', type: String, default: null },
{ name: 'locale', type: String, default: null }
],

run: function (commandOptions: BuildOptions) {
Expand Down
6 changes: 6 additions & 0 deletions packages/angular-cli/commands/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ export interface ServeTaskOptions {
open?: boolean;
vendorChunk?: boolean;
hmr?: boolean;
i18nFile?: string;
i18nFormat?: string;
locale?: string;
}

const ServeCommand = Command.extend({
Expand Down Expand Up @@ -103,6 +106,9 @@ const ServeCommand = Command.extend({
default: false,
description: 'Enable hot module replacement',
},
{ name: 'i18n-file', type: String, default: null },
{ name: 'i18n-format', type: String, default: null },
{ name: 'locale', type: String, default: null }
],

run: function(commandOptions: ServeTaskOptions) {
Expand Down
8 changes: 6 additions & 2 deletions packages/angular-cli/models/webpack-build-typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export const getWebpackNonAotConfigPartial = function(projectRoot: string, appCo
};
};

export const getWebpackAotConfigPartial = function(projectRoot: string, appConfig: any) {
export const getWebpackAotConfigPartial = function(projectRoot: string, appConfig: any,
i18nFile: string, i18nFormat: string, locale: string) {
return {
module: {
rules: [
Expand All @@ -43,7 +44,10 @@ export const getWebpackAotConfigPartial = function(projectRoot: string, appConfi
plugins: [
new AotPlugin({
tsConfigPath: path.resolve(projectRoot, appConfig.root, appConfig.tsconfig),
mainPath: path.join(projectRoot, appConfig.root, appConfig.main)
mainPath: path.join(projectRoot, appConfig.root, appConfig.main),
i18nFile: i18nFile,
i18nFormat: i18nFormat,
locale: locale
}),
]
};
Expand Down
5 changes: 4 additions & 1 deletion packages/angular-cli/models/webpack-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export class NgCliWebpackConfig {
public environment: string,
outputDir?: string,
baseHref?: string,
i18nFile?: string,
i18nFormat?: string,
locale?: string,
isAoT = false,
sourcemap = true,
vendorChunk = false,
Expand All @@ -49,7 +52,7 @@ export class NgCliWebpackConfig {
this.ngCliProject.root, appConfig, sourcemap, verbose
);
const typescriptConfigPartial = isAoT
? getWebpackAotConfigPartial(this.ngCliProject.root, appConfig)
? getWebpackAotConfigPartial(this.ngCliProject.root, appConfig, i18nFile, i18nFormat, locale)
: getWebpackNonAotConfigPartial(this.ngCliProject.root, appConfig);

if (appConfig.mobile) {
Expand Down
3 changes: 3 additions & 0 deletions packages/angular-cli/tasks/build-webpack-watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export default Task.extend({
runTaskOptions.environment,
outputDir,
runTaskOptions.baseHref,
runTaskOptions.i18nFile,
runTaskOptions.i18nFormat,
runTaskOptions.locale,
runTaskOptions.aot,
runTaskOptions.sourcemap,
runTaskOptions.vendorChunk,
Expand Down
3 changes: 3 additions & 0 deletions packages/angular-cli/tasks/build-webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export default <any>Task.extend({
runTaskOptions.environment,
outputDir,
runTaskOptions.baseHref,
runTaskOptions.i18nFile,
runTaskOptions.i18nFormat,
runTaskOptions.locale,
runTaskOptions.aot,
runTaskOptions.sourcemap,
runTaskOptions.vendorChunk,
Expand Down
3 changes: 3 additions & 0 deletions packages/angular-cli/tasks/serve-webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export default Task.extend({
serveTaskOptions.environment,
undefined,
undefined,
serveTaskOptions.i18nFile,
serveTaskOptions.i18nFormat,
serveTaskOptions.locale,
serveTaskOptions.aot,
serveTaskOptions.sourcemap,
serveTaskOptions.vendorChunk,
Expand Down
4 changes: 2 additions & 2 deletions packages/angular-cli/utilities/completion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@

ng_opts='b build completion doc e2e g generate get github-pages:deploy gh-pages:deploy h help i init install lint make-this-awesome new s serve server set t test v version'

build_opts='--aot --base-href --environment --output-path --progress --sourcemap --suppress-sizes --target --vendor-chunk --verbose --watch --watcher -bh -dev -e -o -prod -sm -t -w'
build_opts='--aot --base-href --environment --i18n-file --i18n-format --locale --output-path --progress --sourcemap --suppress-sizes --target --vendor-chunk --verbose --watch --watcher -bh -dev -e -o -prod -sm -t -w'
generate_opts='class component directive enum module pipe route service c cl d e m p r s --help'
github_pages_deploy_opts='--base-href --environment --gh-token --gh-username --message --skip-build --target --user-page -bh -e -t'
help_opts='--json --verbose -v'
init_opts='--dry-run inline-style inline-template --link-cli --mobile --name --prefix --routing --skip-bower --skip-npm --source-dir --style --verbose -d -is -it -lc -n -p -sb -sd -sn -v'
new_opts='--directory --dry-run inline-style inline-template --link-cli --mobile --prefix --routing --skip-bower --skip-git --skip-npm --source-dir --style --verbose -d -dir -is -it -lc -p -sb -sd -sg -sn -v'
serve_opts='--aot --environment --hmr --host --live-reload --live-reload-base-url --live-reload-host --live-reload-live-css --live-reload-port --open --port --proxy-config --sourcemap --ssl --ssl-cert --ssl-key --target --watcher -H -e -lr -lrbu -lrh -lrp -o -p -pc -sm -t -w'
serve_opts='--aot --environment --hmr --host --i18n-file --i18n-format --live-reload --live-reload-base-url --live-reload-host --live-reload-live-css --live-reload-port --locale --open --port --proxy-config --sourcemap --ssl --ssl-cert --ssl-key --target --watcher -H -e -lr -lrbu -lrh -lrp -o -p -pc -sm -t -w'
set_opts='--global -g'
test_opts='--browsers --build --code-coverage --colors --lint --log-level --port --reporters --single-run --sourcemap --watch -cc -l -sm -sr -w'

Expand Down
29 changes: 29 additions & 0 deletions tests/e2e/tests/build/aot-i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {ng} from '../../utils/process';
import {expectFileToMatch, writeFile, createDir, appendToFile} from '../../utils/fs';
import {expectToFail} from '../../utils/utils';

export default function() {
return Promise.resolve()
.then(() => createDir('src/locale'))
.then(() => writeFile('src/locale/messages.fr.xlf', `
<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="ng2.template">
<body>
<trans-unit id="8def8481e91291a52f9baa31cbdb313e6a6ca02b" datatype="html">
<source>Hello i18n!</source>
<target>Bonjour i18n!</target>
<note priority="1" from="description">An introduction header for this sample</note>
</trans-unit>
</body>
</file>
</xliff>`))
.then(() => appendToFile('src/app/app.component.html',
'<h1 i18n="An introduction header for this sample">Hello i18n!</h1>'))
.then(() => ng('build', '--aot', '--i18n-file', 'src/locale/messages.fr.xlf', '--i18n-format',
'xlf', '--locale', 'fr'))
.then(() => expectFileToMatch('dist/main.bundle.js', /Bonjour i18n!/))
.then(() => ng('build', '--aot'))
.then(() => expectToFail(() => expectFileToMatch('dist/main.bundle.js', /Bonjour i18n!/)))
.then(() => expectFileToMatch('dist/main.bundle.js', /Hello i18n!/));
}

0 comments on commit 2a0a42d

Please sign in to comment.