Skip to content

Commit 37f0028

Browse files
tdesmetMRHarrison
authored andcommitted
feat(i18n): add i18n command line options (angular#3098)
Also available on the webpack plugin.
1 parent e737de4 commit 37f0028

File tree

10 files changed

+85
-10
lines changed

10 files changed

+85
-10
lines changed

packages/@ngtools/webpack/src/plugin.ts

+22-4
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ export interface AotPluginOptions {
2525
entryModule?: string;
2626
mainPath?: string;
2727
typeChecking?: boolean;
28-
2928
skipCodeGeneration?: boolean;
29+
i18nFile?: string;
30+
i18nFormat?: string;
31+
locale?: string;
3032
}
3133

3234

@@ -78,6 +80,9 @@ export class AotPlugin implements Tapable {
7880
private _basePath: string;
7981
private _genDir: string;
8082

83+
private _i18nFile: string;
84+
private _i18nFormat: string;
85+
private _locale: string;
8186

8287
constructor(options: AotPluginOptions) {
8388
this._setupOptions(options);
@@ -93,6 +98,9 @@ export class AotPlugin implements Tapable {
9398
get program() { return this._program; }
9499
get skipCodeGeneration() { return this._skipCodeGeneration; }
95100
get typeCheck() { return this._typeCheck; }
101+
get i18nFile() { return this._i18nFile; }
102+
get i18nFormat() { return this._i18nFormat; }
103+
get locale() { return this._locale; }
96104

97105
private _setupOptions(options: AotPluginOptions) {
98106
// Fill in the missing options.
@@ -153,6 +161,16 @@ export class AotPlugin implements Tapable {
153161
this._reflectorHost = new ngCompiler.ReflectorHost(
154162
this._program, this._compilerHost, this._angularCompilerOptions);
155163
this._reflector = new ngCompiler.StaticReflector(this._reflectorHost);
164+
165+
if (options.hasOwnProperty('i18nFile')) {
166+
this._i18nFile = options.i18nFile;
167+
}
168+
if (options.hasOwnProperty('i18nFormat')) {
169+
this._i18nFormat = options.i18nFormat;
170+
}
171+
if (options.hasOwnProperty('locale')) {
172+
this._locale = options.locale;
173+
}
156174
}
157175

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

224242
const i18nOptions: ngCompiler.NgcCliOptions = {
225-
i18nFile: undefined,
226-
i18nFormat: undefined,
227-
locale: undefined,
243+
i18nFile: this.i18nFile,
244+
i18nFormat: this.i18nFormat,
245+
locale: this.locale,
228246
basePath: this.basePath
229247
};
230248

packages/angular-cli/commands/build.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ export interface BuildOptions {
1515
vendorChunk?: boolean;
1616
verbose?: boolean;
1717
progress?: boolean;
18+
i18nFile?: string;
19+
i18nFormat?: string;
20+
locale?: string;
1821
}
1922

2023
const BuildCommand = Command.extend({
@@ -39,7 +42,10 @@ const BuildCommand = Command.extend({
3942
{ name: 'sourcemap', type: Boolean, default: true, aliases: ['sm'] },
4043
{ name: 'vendor-chunk', type: Boolean, default: true },
4144
{ name: 'verbose', type: Boolean, default: false },
42-
{ name: 'progress', type: Boolean, default: true }
45+
{ name: 'progress', type: Boolean, default: true },
46+
{ name: 'i18n-file', type: String, default: null },
47+
{ name: 'i18n-format', type: String, default: null },
48+
{ name: 'locale', type: String, default: null }
4349
],
4450

4551
run: function (commandOptions: BuildOptions) {

packages/angular-cli/commands/serve.ts

+6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ export interface ServeTaskOptions {
3232
open?: boolean;
3333
vendorChunk?: boolean;
3434
hmr?: boolean;
35+
i18nFile?: string;
36+
i18nFormat?: string;
37+
locale?: string;
3538
}
3639

3740
const ServeCommand = Command.extend({
@@ -103,6 +106,9 @@ const ServeCommand = Command.extend({
103106
default: false,
104107
description: 'Enable hot module replacement',
105108
},
109+
{ name: 'i18n-file', type: String, default: null },
110+
{ name: 'i18n-format', type: String, default: null },
111+
{ name: 'locale', type: String, default: null }
106112
],
107113

108114
run: function(commandOptions: ServeTaskOptions) {

packages/angular-cli/models/webpack-build-typescript.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ export const getWebpackNonAotConfigPartial = function(projectRoot: string, appCo
2929
};
3030
};
3131

32-
export const getWebpackAotConfigPartial = function(projectRoot: string, appConfig: any) {
32+
export const getWebpackAotConfigPartial = function(projectRoot: string, appConfig: any,
33+
i18nFile: string, i18nFormat: string, locale: string) {
3334
return {
3435
module: {
3536
rules: [
@@ -43,7 +44,10 @@ export const getWebpackAotConfigPartial = function(projectRoot: string, appConfi
4344
plugins: [
4445
new AotPlugin({
4546
tsConfigPath: path.resolve(projectRoot, appConfig.root, appConfig.tsconfig),
46-
mainPath: path.join(projectRoot, appConfig.root, appConfig.main)
47+
mainPath: path.join(projectRoot, appConfig.root, appConfig.main),
48+
i18nFile: i18nFile,
49+
i18nFormat: i18nFormat,
50+
locale: locale
4751
}),
4852
]
4953
};

packages/angular-cli/models/webpack-config.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ export class NgCliWebpackConfig {
2424
public environment: string,
2525
outputDir?: string,
2626
baseHref?: string,
27+
i18nFile?: string,
28+
i18nFormat?: string,
29+
locale?: string,
2730
isAoT = false,
2831
sourcemap = true,
2932
vendorChunk = false,
@@ -49,7 +52,7 @@ export class NgCliWebpackConfig {
4952
this.ngCliProject.root, appConfig, sourcemap, verbose
5053
);
5154
const typescriptConfigPartial = isAoT
52-
? getWebpackAotConfigPartial(this.ngCliProject.root, appConfig)
55+
? getWebpackAotConfigPartial(this.ngCliProject.root, appConfig, i18nFile, i18nFormat, locale)
5356
: getWebpackNonAotConfigPartial(this.ngCliProject.root, appConfig);
5457

5558
if (appConfig.mobile) {

packages/angular-cli/tasks/build-webpack-watch.ts

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ export default Task.extend({
2323
runTaskOptions.environment,
2424
outputDir,
2525
runTaskOptions.baseHref,
26+
runTaskOptions.i18nFile,
27+
runTaskOptions.i18nFormat,
28+
runTaskOptions.locale,
2629
runTaskOptions.aot,
2730
runTaskOptions.sourcemap,
2831
runTaskOptions.vendorChunk,

packages/angular-cli/tasks/build-webpack.ts

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ export default <any>Task.extend({
2424
runTaskOptions.environment,
2525
outputDir,
2626
runTaskOptions.baseHref,
27+
runTaskOptions.i18nFile,
28+
runTaskOptions.i18nFormat,
29+
runTaskOptions.locale,
2730
runTaskOptions.aot,
2831
runTaskOptions.sourcemap,
2932
runTaskOptions.vendorChunk,

packages/angular-cli/tasks/serve-webpack.ts

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ export default Task.extend({
2525
serveTaskOptions.environment,
2626
undefined,
2727
undefined,
28+
serveTaskOptions.i18nFile,
29+
serveTaskOptions.i18nFormat,
30+
serveTaskOptions.locale,
2831
serveTaskOptions.aot,
2932
serveTaskOptions.sourcemap,
3033
serveTaskOptions.vendorChunk,

packages/angular-cli/utilities/completion.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88

99
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'
1010

11-
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'
11+
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'
1212
generate_opts='class component directive enum module pipe route service c cl d e m p r s --help'
1313
github_pages_deploy_opts='--base-href --environment --gh-token --gh-username --message --skip-build --target --user-page -bh -e -t'
1414
help_opts='--json --verbose -v'
1515
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'
1616
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'
17-
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'
17+
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'
1818
set_opts='--global -g'
1919
test_opts='--browsers --build --code-coverage --colors --lint --log-level --port --reporters --single-run --sourcemap --watch -cc -l -sm -sr -w'
2020

tests/e2e/tests/build/aot-i18n.ts

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {ng} from '../../utils/process';
2+
import {expectFileToMatch, writeFile, createDir, appendToFile} from '../../utils/fs';
3+
import {expectToFail} from '../../utils/utils';
4+
5+
export default function() {
6+
return Promise.resolve()
7+
.then(() => createDir('src/locale'))
8+
.then(() => writeFile('src/locale/messages.fr.xlf', `
9+
<?xml version="1.0" encoding="UTF-8" ?>
10+
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
11+
<file source-language="en" datatype="plaintext" original="ng2.template">
12+
<body>
13+
<trans-unit id="8def8481e91291a52f9baa31cbdb313e6a6ca02b" datatype="html">
14+
<source>Hello i18n!</source>
15+
<target>Bonjour i18n!</target>
16+
<note priority="1" from="description">An introduction header for this sample</note>
17+
</trans-unit>
18+
</body>
19+
</file>
20+
</xliff>`))
21+
.then(() => appendToFile('src/app/app.component.html',
22+
'<h1 i18n="An introduction header for this sample">Hello i18n!</h1>'))
23+
.then(() => ng('build', '--aot', '--i18n-file', 'src/locale/messages.fr.xlf', '--i18n-format',
24+
'xlf', '--locale', 'fr'))
25+
.then(() => expectFileToMatch('dist/main.bundle.js', /Bonjour i18n!/))
26+
.then(() => ng('build', '--aot'))
27+
.then(() => expectToFail(() => expectFileToMatch('dist/main.bundle.js', /Bonjour i18n!/)))
28+
.then(() => expectFileToMatch('dist/main.bundle.js', /Hello i18n!/));
29+
}

0 commit comments

Comments
 (0)