forked from angular/angular
/
main.ts
159 lines (144 loc) · 6.12 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/env node
/**
* @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 * as glob from 'glob';
import {resolve} from 'path';
import * as yargs from 'yargs';
import {AssetTranslationHandler} from './asset_files/asset_translation_handler';
import {getOutputPathFn, OutputPathFn} from './output_path';
import {SourceFileTranslationHandler} from './source_files/source_file_translation_handler';
import {MissingTranslationStrategy} from './source_files/source_file_utils';
import {TranslationLoader} from './translation_files/translation_loader';
import {SimpleJsonTranslationParser} from './translation_files/translation_parsers/simple_json/simple_json_translation_parser';
import {Xliff1TranslationParser} from './translation_files/translation_parsers/xliff1/xliff1_translation_parser';
import {Xliff2TranslationParser} from './translation_files/translation_parsers/xliff2/xliff2_translation_parser';
import {Translator} from './translator';
import {Diagnostics} from '../diagnostics';
if (require.main === module) {
const args = process.argv.slice(2);
const options =
yargs
.option('r', {
alias: 'root',
required: true,
describe:
'The root path of the files to translate, either absolute or relative to the current working directory. E.g. `dist/en`.',
})
.option('s', {
alias: 'source',
required: true,
describe:
'A glob pattern indicating what files to translate, relative to the `root` path. E.g. `bundles/**/*`.',
})
.option('l', {
alias: 'source-locale',
describe:
'The source locale of the application. If this is provided then a copy of the application will be created with no translation but just the `$localize` calls stripped out.',
})
.option('t', {
alias: 'translations',
required: true,
array: true,
describe:
'A list of paths to the translation files to load, either absolute or relative to the current working directory.\n' +
'E.g. "-t src/locale/messages.en.xlf src/locale/messages.fr.xlf src/locale/messages.de.xlf".',
})
.option('target-locales', {
array: true,
describe:
'A list of target locales for the translation files, which will override any target locale parsed from the translation file.\n' +
'E.g. "-t en fr de".',
})
.option('o', {
alias: 'outputPath',
required: true,
describe:
'A output path pattern to where the translated files will be written. The marker `{{LOCALE}}` will be replaced with the target locale. E.g. `dist/{{LOCALE}}`.'
})
.option('m', {
alias: 'missingTranslation',
describe: 'How to handle missing translations.',
choices: ['error', 'warning', 'ignore'],
default: 'warning',
})
.help()
.parse(args);
const sourceRootPath = options['r'];
const sourceFilePaths =
glob.sync(options['s'], {absolute: true, cwd: sourceRootPath, nodir: true});
const translationFilePaths: string[] = options['t'];
const outputPathFn = getOutputPathFn(options['o']);
const diagnostics = new Diagnostics();
const missingTranslation: MissingTranslationStrategy = options['m'];
const sourceLocale: string|undefined = options['l'];
const translationFileLocales: string[] = options['target-locales'] || [];
translateFiles({sourceRootPath, sourceFilePaths, translationFilePaths, translationFileLocales,
outputPathFn, diagnostics, missingTranslation, sourceLocale});
diagnostics.messages.forEach(m => console.warn(`${m.type}: ${m.message}`));
process.exit(diagnostics.hasErrors ? 1 : 0);
}
export interface TranslateFilesOptions {
/**
* The root path of the files to translate, either absolute or relative to the current working
* directory. E.g. `dist/en`
*/
sourceRootPath: string;
/**
* The files to translate, relative to the `root` path.
*/
sourceFilePaths: string[];
/**
* An array of paths to the translation files to load, either absolute or relative to the current
* working directory.
*/
translationFilePaths: string[];
/**
* A collection of the target locales for the translation files.
*/
translationFileLocales: (string|undefined)[];
/**
* A function that computes the output path of where the translated files will be written.
* The marker `{{LOCALE}}` will be replaced with the target locale. E.g. `dist/{{LOCALE}}`.
*/
outputPathFn: OutputPathFn;
/**
* An object that will receive any diagnostics messages due to the processing.
*/
diagnostics: Diagnostics;
/**
* How to handle missing translations.
*/
missingTranslation: MissingTranslationStrategy;
/**
* The locale of the source files.
* If this is provided then a copy of the application will be created with no translation but just
* the `$localize` calls stripped out.
*/
sourceLocale?: string;
}
export function translateFiles({sourceRootPath, sourceFilePaths, translationFilePaths,
translationFileLocales, outputPathFn, diagnostics,
missingTranslation, sourceLocale}: TranslateFilesOptions) {
const translationLoader = new TranslationLoader(
[
new Xliff2TranslationParser(),
new Xliff1TranslationParser(),
new SimpleJsonTranslationParser(),
],
diagnostics);
const resourceProcessor = new Translator(
[
new SourceFileTranslationHandler({missingTranslation}),
new AssetTranslationHandler(),
],
diagnostics);
const translations = translationLoader.loadBundles(translationFilePaths, translationFileLocales);
sourceRootPath = resolve(sourceRootPath);
resourceProcessor.translateFiles(
sourceFilePaths, sourceRootPath, outputPathFn, translations, sourceLocale);
}