Skip to content

Commit

Permalink
closes #70: Add support to add a prefix to translated target languages
Browse files Browse the repository at this point in the history
  • Loading branch information
martinroob committed Feb 23, 2018
1 parent deb03cf commit 3de97a6
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 9 deletions.
8 changes: 8 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
<a name="0.12.0"></a>
# [0.12.0](https://github.com/martinroob/ngx-i18nsupport/compare/v0.12.0...v0.11.1) (2018-02-23)

### Features

* **xliffmerge:** Added support to add a prefix to translated target languages.
<br>There are 2 new options `targetPraefix` and `targetSuffix` used for copied untranslated units ([#70](https://github.com/martinroob/ngx-i18nsupport/issues/70)).

<a name="0.11.1"></a>
# [0.11.1](https://github.com/martinroob/ngx-i18nsupport/compare/v0.11.1...v0.11.0) (2018-02-16)

Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ Options:
"supportNgxTranslate": false,
"ngxTranslateExtractionPattern": "@@|ngx-translate",
"useSourceAsTarget": true,
"targetPraefix": "",
"targetSuffix": "",
"allowIdChange": false,
"autotranslate": false,
"apikey": "",
Expand All @@ -119,7 +121,15 @@ The options are:
defines what messages are exported to json translation files for ngx-translate.
For details how to use it have a look at the Wiki Page [ngx translate usage](https://github.com/martinroob/ngx-i18nsupport/wiki/ngx-translate-usage).
- `useSourceAsTarget` (boolean, default `true`): flag, if source should be copied to target for new trans-units
- `allowIdChange` (boolean, default `false`):
- `targetPraefix` (since 0.12.0) (string, default """):
when the flag `useSourceAsTarget` is set and a source is copied to target,
then the target string will be praefixed by this value.
E.g. `targetPraefix: "%%"` and source contains the string "menu", target will contain "%%menu" at the end.
- `targetSuffix` (since 0.12.0) (string, default """):
when the flag `useSourceAsTarget` is set and a source is copied to target,
then the target string will be suffixed by this value.
E.g. `targetSuffix: "%%"` and source contains the string "menu", target will contain "menu%%" at the end.
- `allowIdChange` (since 0.11.0) (boolean, default `false`):
flag, wether xliffmerge should merge transunits with changed IDs.
When there is only a small change in the original message text, e.g. a trailing white space, the Angular extraction tool will change the ID of the unit.
This means that the translations of the unit are lost.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"dependencies": {
"chalk": "^2.2.0",
"commander": "^2.9.0",
"ngx-i18nsupport-lib": "^1.7.0",
"ngx-i18nsupport-lib": "^1.8.1",
"request": "^2.81.0",
"rxjs": "^5.5.6"
}
Expand Down
2 changes: 2 additions & 0 deletions src/xliffmerge/i-xliff-merge-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export interface IXliffMergeOptions {
ngxTranslateExtractionPattern?: string; // Criteria, what messages should be used for ngx-translate output
// see details on the documentation page https://github.com/martinroob/ngx-i18nsupport/wiki/ngx-translate-usage
useSourceAsTarget?: boolean; // Flag, whether source must be used as target for new trans-units
targetPraefix?: string; // Praefix for target copied from sourced
targetSuffix?: string; // Suffix for target copied from sourced
autotranslate?: boolean|string[]; // enable auto translate via Google Translate
// if it is an array, list of languages to autotranslate
// if it is true, autotranslate all languages (except source language of course)
Expand Down
46 changes: 44 additions & 2 deletions src/xliffmerge/xlf12-merge.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ describe('XliffMerge XLIFF 1.2 format tests', () => {
srcDir: WORKDIR,
genDir: WORKDIR,
i18nFile: MASTERFILE,
useSourceAsTarget: false
useSourceAsTarget: false
}
};
let xliffMergeCmd = XliffMerge.createFromOptions(commandOut, {languages: ['de']}, profileContent);
Expand Down Expand Up @@ -163,7 +163,7 @@ describe('XliffMerge XLIFF 1.2 format tests', () => {
srcDir: WORKDIR,
genDir: WORKDIR,
i18nFile: MASTERFILE,
useSourceAsTarget: false
useSourceAsTarget: false
}
};
let xliffMergeCmd = XliffMerge.createFromOptions(commandOut, {languages: ['de', 'en']}, profileContent);
Expand All @@ -186,6 +186,48 @@ describe('XliffMerge XLIFF 1.2 format tests', () => {
done();
});

it('should generate translated file for all languages with set praefix and suffix (#70)', (done) => {
FileUtil.copy(MASTER1SRC, MASTER);
let ws: WriterToString = new WriterToString();
let commandOut = new CommandOutput(ws);
let profileContent: IConfigFile = {
xliffmergeOptions: {
defaultLanguage: 'de',
srcDir: WORKDIR,
genDir: WORKDIR,
i18nFile: MASTERFILE,
targetPraefix: '%%',
targetSuffix: '!!',
}
};
let xliffMergeCmd = XliffMerge.createFromOptions(commandOut, {languages: ['de', 'en']}, profileContent);
xliffMergeCmd.run();
expect(ws.writtenData()).not.toContain('ERROR');
let langFileGerman: ITranslationMessagesFile = readXliff(xliffMergeCmd.generatedI18nFile('de'));
expect(langFileGerman.sourceLanguage()).toBe('de');
expect(langFileGerman.targetLanguage()).toBe('de');
langFileGerman.forEachTransUnit((tu: ITransUnit) => {
if (!tu.targetContent().startsWith('{VAR')) {
expect(tu.targetContent()).toBe('%%' + tu.sourceContent() + '!!');
} else {
expect(tu.targetContent()).toBe(tu.sourceContent());
}
expect(tu.targetState()).toBe('final');
});
let langFileEnglish: ITranslationMessagesFile = readXliff(xliffMergeCmd.generatedI18nFile('en'));
expect(langFileEnglish.sourceLanguage()).toBe('de');
expect(langFileEnglish.targetLanguage()).toBe('en');
langFileEnglish.forEachTransUnit((tu: ITransUnit) => {
if (!tu.targetContent().startsWith('{VAR')) {
expect(tu.targetContent()).toBe('%%' + tu.sourceContent() + '!!');
} else {
expect(tu.targetContent()).toBe(tu.sourceContent());
}
expect(tu.targetState()).toBe('new');
});
done();
});

it('should merge translated file for all languages', (done) => {
FileUtil.copy(MASTER1SRC, MASTER);
let ws: WriterToString = new WriterToString();
Expand Down
45 changes: 44 additions & 1 deletion src/xliffmerge/xlf20-merge.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,50 @@ describe('XliffMerge XLIFF 2.0 format tests', () => {
done();
});

it('should generate translated file with natove trans unit status "initial", testcase for issue #57', (done) => {
it('should generate translated file for all languages with set praefix and suffix (#70)', (done) => {
FileUtil.copy(MASTER1SRC, MASTER);
let ws: WriterToString = new WriterToString();
let commandOut = new CommandOutput(ws);
let profileContent: IConfigFile = {
xliffmergeOptions: {
defaultLanguage: 'de',
srcDir: WORKDIR,
genDir: WORKDIR,
i18nFormat: 'xlf2',
i18nFile: MASTERFILE,
targetPraefix: '%%',
targetSuffix: '!!',
}
};
let xliffMergeCmd = XliffMerge.createFromOptions(commandOut, {languages: ['de', 'en']}, profileContent);
xliffMergeCmd.run();
expect(ws.writtenData()).not.toContain('ERROR');
let langFileGerman: ITranslationMessagesFile = readXliff2(xliffMergeCmd.generatedI18nFile('de'));
expect(langFileGerman.sourceLanguage()).toBe('de');
expect(langFileGerman.targetLanguage()).toBe('de');
langFileGerman.forEachTransUnit((tu: ITransUnit) => {
if (!tu.targetContent().startsWith('{VAR')) {
expect(tu.targetContent()).toBe('%%' + tu.sourceContent() + '!!');
} else {
expect(tu.targetContent()).toBe(tu.sourceContent());
}
expect(tu.targetState()).toBe('final');
});
let langFileEnglish: ITranslationMessagesFile = readXliff2(xliffMergeCmd.generatedI18nFile('en'));
expect(langFileEnglish.sourceLanguage()).toBe('de');
expect(langFileEnglish.targetLanguage()).toBe('en');
langFileEnglish.forEachTransUnit((tu: ITransUnit) => {
if (!tu.targetContent().startsWith('{VAR')) {
expect(tu.targetContent()).toBe('%%' + tu.sourceContent() + '!!');
} else {
expect(tu.targetContent()).toBe(tu.sourceContent());
}
expect(tu.targetState()).toBe('new');
});
done();
});

it('should generate translated file with native trans unit status "initial", testcase for issue #57', (done) => {
FileUtil.copy(MASTER1SRC, MASTER);
let ws: WriterToString = new WriterToString();
let commandOut = new CommandOutput(ws);
Expand Down
37 changes: 37 additions & 0 deletions src/xliffmerge/xliff-merge-parameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export class XliffMergeParameters {
private _supportNgxTranslate: boolean;
private _ngxTranslateExtractionPattern: string;
private _useSourceAsTarget: boolean;
private _targetPraefix: string;
private _targetSuffix: string;
private _autotranslate: boolean|string[];
private _apikey: string;
private _apikeyfile: string;
Expand Down Expand Up @@ -158,6 +160,12 @@ export class XliffMergeParameters {
if (!isNullOrUndefined(profile.useSourceAsTarget)) {
this._useSourceAsTarget = profile.useSourceAsTarget;
}
if (!isNullOrUndefined(profile.targetPraefix)) {
this._targetPraefix = profile.targetPraefix;
}
if (!isNullOrUndefined(profile.targetSuffix)) {
this._targetSuffix = profile.targetSuffix;
}
if (!isNullOrUndefined(profile.autotranslate)) {
this._autotranslate = profile.autotranslate;
}
Expand Down Expand Up @@ -234,6 +242,15 @@ export class XliffMergeParameters {
this.errorsFound.push(new XliffMergeError('ngxTranslateExtractionPattern "' + this.ngxTranslateExtractionPattern() + '": ' + checkResult));
}
}
// targetPraefix and targetSuffix check
if (!this.useSourceAsTarget()) {
if (this.targetPraefix().length > 0) {
this.warningsFound.push('configured targetPraefix "' + this.targetPraefix() + '" will not be used because "useSourceAsTarget" is disabled"');
}
if (this.targetSuffix().length > 0) {
this.warningsFound.push('configured targetSuffix "' + this.targetSuffix() + '" will not be used because "useSourceAsTarget" is disabled"');
}
}
}

/**
Expand Down Expand Up @@ -277,6 +294,10 @@ export class XliffMergeParameters {
commandOutput.debug('ngxTranslateExtractionPattern:\t%s', this.ngxTranslateExtractionPattern());
}
commandOutput.debug('useSourceAsTarget:\t%s', this.useSourceAsTarget());
if (this.useSourceAsTarget()) {
commandOutput.debug('targetPraefix:\t"%s"', this.targetPraefix());
commandOutput.debug('targetSuffix:\t"%s"', this.targetSuffix());
}
commandOutput.debug('allowIdChange:\t%s', this.allowIdChange());
commandOutput.debug('autotranslate:\t%s', this.autotranslate());
if (this.autotranslate()) {
Expand Down Expand Up @@ -393,6 +414,22 @@ export class XliffMergeParameters {
return (isNullOrUndefined(this._useSourceAsTarget)) ? true : this._useSourceAsTarget;
}

/**
* Praefix used for target when copying new trans-units
* Default is ""
*/
public targetPraefix(): string {
return (isNullOrUndefined(this._targetPraefix)) ? "" : this._targetPraefix;
}

/**
* Suffix used for target when copying new trans-units
* Default is ""
*/
public targetSuffix(): string {
return (isNullOrUndefined(this._targetSuffix)) ? "" : this._targetSuffix;
}

/**
* Whether to use autotranslate for new trans-units
* Default is false
Expand Down
36 changes: 36 additions & 0 deletions src/xliffmerge/xliff-merge.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,42 @@ describe('XliffMerge test spec', () => {
done();
});

it('should accept targetPraefix and targetSuffix parameter', (done) => {
let ws: WriterToString = new WriterToString();
let commandOut = new CommandOutput(ws);
let profileContent: IConfigFile = {
xliffmergeOptions: {
languages: ['de', 'en', 'fr'],
targetPraefix: '%%',
targetSuffix: '!!',
}
};
let xliffMergeCmd = XliffMerge.createFromOptions(commandOut, {verbose: true}, profileContent);
xliffMergeCmd.run();
expect(ws.writtenData()).toContain('* targetPraefix:\t"%%"');
expect(ws.writtenData()).toContain('* targetSuffix:\t"!!"');
done();
});

it('should output a warning when targetPraefix or targetSuffix are set, but useSourceAsTarget is disabled', (done) => {
let ws: WriterToString = new WriterToString();
let commandOut = new CommandOutput(ws);
let profileContent: IConfigFile = {
xliffmergeOptions: {
languages: ["de"],
useSourceAsTarget: false,
targetPraefix: '%%',
targetSuffix: '!!',
}
};
let xliffMergeCmd = XliffMerge.createFromOptions(commandOut, {verbose: true}, profileContent);
xliffMergeCmd.run();
const allWarnings = xliffMergeCmd.warnings().join('\n');
expect(allWarnings).toContain('configured targetPraefix "%%" will not be used because "useSourceAsTarget" is disabled');
expect(allWarnings).toContain('configured targetSuffix "!!" will not be used because "useSourceAsTarget" is disabled');
done();
});

});

});
13 changes: 12 additions & 1 deletion src/xliffmerge/xliff-merge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,14 @@ export class XliffMerge {
return this.parameters.generatedNgxTranslateFile(lang);
}

/**
* Warnings found during the run.
* @return {string[]}
*/
public warnings(): string[] {
return this.parameters.warningsFound;
}

private readMaster() {
try {
this.master = TranslationMessagesFileReader.fromFile(this.parameters.i18nFormat(), this.parameters.i18nFile(), this.parameters.encoding());
Expand Down Expand Up @@ -270,6 +278,8 @@ export class XliffMerge {
// and set target-language
// and copy source to target if necessary
let isDefaultLang: boolean = (lang == this.parameters.defaultLanguage());
this.master.setNewTransUnitTargetPraefix(this.parameters.targetPraefix());
this.master.setNewTransUnitTargetSuffix(this.parameters.targetSuffix());
let languageSpecificMessagesFile: ITranslationMessagesFile = this.master.createTranslationFileForLang(lang, languageXliffFilePath, isDefaultLang, this.parameters.useSourceAsTarget());
return this.autoTranslate(this.master.sourceLanguage(), lang, languageSpecificMessagesFile).map((summary) => {
// write it to file
Expand Down Expand Up @@ -303,13 +313,14 @@ export class XliffMerge {
private mergeMasterTo(lang: string, languageXliffFilePath: string): Observable<void> {
// read lang specific file
let languageSpecificMessagesFile: ITranslationMessagesFile = TranslationMessagesFileReader.fromFile(XliffMerge.translationFormat(this.parameters.i18nFormat()), languageXliffFilePath, this.parameters.encoding());

let isDefaultLang: boolean = (lang == this.parameters.defaultLanguage());
let newCount = 0;
let correctSourceContentCount = 0;
let correctSourceRefCount = 0;
let correctDescriptionOrMeaningCount = 0;
let idChangedCount = 0;
languageSpecificMessagesFile.setNewTransUnitTargetPraefix(this.parameters.targetPraefix());
languageSpecificMessagesFile.setNewTransUnitTargetSuffix(this.parameters.targetSuffix());
this.master.forEachTransUnit((masterTransUnit) => {
let transUnit: ITransUnit = languageSpecificMessagesFile.transUnitWithId(masterTransUnit.id);

Expand Down
37 changes: 37 additions & 0 deletions src/xliffmerge/xmb-merge.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,43 @@ describe('XliffMerge XMB format tests', () => {
done();
});

it('should generate translated file for all languages with set praefix and suffix (#70)', (done) => {
FileUtil.copy(MASTER1SRC, MASTER);
let ws: WriterToString = new WriterToString();
let commandOut = new CommandOutput(ws);
let profileContent: IConfigFile = {
xliffmergeOptions: {
defaultLanguage: 'de',
srcDir: WORKDIR,
genDir: WORKDIR,
i18nFormat: 'xmb',
i18nFile: MASTERFILE,
targetPraefix: '%%',
targetSuffix: '!!',
}
};
let xliffMergeCmd = XliffMerge.createFromOptions(commandOut, {languages: ['de', 'en']}, profileContent);
xliffMergeCmd.run();
expect(ws.writtenData()).not.toContain('ERROR');
let langFileGerman: ITranslationMessagesFile = readXtbWithMaster(xliffMergeCmd.generatedI18nFile('de'), MASTER);
langFileGerman.forEachTransUnit((tu: ITransUnit) => {
if (!tu.targetContent().startsWith('{VAR')) {
expect(tu.targetContent()).toBe('%%' + tu.sourceContent() + '!!');
} else {
expect(tu.targetContent()).toBe(tu.sourceContent());
}
});
let langFileEnglish: ITranslationMessagesFile = readXtbWithMaster(xliffMergeCmd.generatedI18nFile('en'), MASTER);
langFileEnglish.forEachTransUnit((tu: ITransUnit) => {
if (!tu.targetContent().startsWith('{VAR')) {
expect(tu.targetContent()).toBe('%%' + tu.sourceContent() + '!!');
} else {
expect(tu.targetContent()).toBe(tu.sourceContent());
}
});
done();
});

it('should merge translated file for all languages using format xmb', (done) => {
FileUtil.copy(MASTER1SRC, MASTER);
let ws: WriterToString = new WriterToString();
Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -925,9 +925,9 @@ nan@^2.3.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.1.tgz#8c84f7b14c96b89f57fbc838012180ec8ca39a01"

ngx-i18nsupport-lib@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/ngx-i18nsupport-lib/-/ngx-i18nsupport-lib-1.7.0.tgz#668abfabae9695ba0ab4fb14712a08fd729dccb6"
ngx-i18nsupport-lib@^1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/ngx-i18nsupport-lib/-/ngx-i18nsupport-lib-1.8.1.tgz#81a9375412e71245e9510c02be3be047de00c5b7"
dependencies:
"@types/xmldom" "^0.1.29"
tokenizr "^1.1.4"
Expand Down

0 comments on commit 3de97a6

Please sign in to comment.