Skip to content

Commit

Permalink
feat(compiler): add source files to xmb/xliff translations (angular#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
ocombe authored and Zhicheng Wang committed Aug 11, 2017
1 parent d2980d0 commit 8447762
Show file tree
Hide file tree
Showing 15 changed files with 311 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import {ANALYZE_FOR_ENTRY_COMPONENTS, Component, ComponentFactoryResolver, Injec

import {BasicComp} from './basic';

@Component({selector: 'cmp-entryComponents', template: '', entryComponents: [BasicComp]})
@Component({
selector: 'cmp-entryComponents',
template: '<p i18n>Welcome</p>',
entryComponents: [BasicComp]
})
export class CompWithEntryComponents {
constructor(public cfr: ComponentFactoryResolver) {}
}
Expand Down
28 changes: 23 additions & 5 deletions packages/compiler-cli/integrationtest/test/i18n_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ const EXPECTED_XMB = `<?xml version="1.0" encoding="UTF-8" ?>
<!ELEMENT ex (#PCDATA)>
]>
<messagebundle>
<msg id="8136548302122759730" desc="desc" meaning="meaning">translate me</msg>
<msg id="3492007542396725315">Welcome</msg>
<msg id="3772663375917578720">other-3rdP-component</msg>
<msg id="8136548302122759730" desc="desc" meaning="meaning"><source>src/basic.ts:1</source>translate me</msg>
<msg id="3492007542396725315"><source>src/basic.ts:5</source><source>src/entry_components.ts:1</source>Welcome</msg>
<msg id="126808141597411718"><source>node_modules/third_party/other_comp.d.ts:1,2</source>other-3rdP-component
multi-lines</msg>
</messagebundle>
`;

Expand All @@ -47,16 +48,33 @@ const EXPECTED_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
<trans-unit id="76e1eccb1b772fa9f294ef9c146ea6d0efa8a2d4" datatype="html">
<source>translate me</source>
<target/>
<context-group purpose="location">
<context context-type="sourcefile">src/basic.ts</context>
<context context-type="linenumber">1</context>
</context-group>
<note priority="1" from="description">desc</note>
<note priority="1" from="meaning">meaning</note>
</trans-unit>
<trans-unit id="65cc4ab3b4c438e07c89be2b677d08369fb62da2" datatype="html">
<source>Welcome</source>
<target/>
<context-group purpose="location">
<context context-type="sourcefile">src/basic.ts</context>
<context context-type="linenumber">5</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/entry_components.ts</context>
<context context-type="linenumber">1</context>
</context-group>
</trans-unit>
<trans-unit id="63a85808f03b8181e36a952e0fa38202c2304862" datatype="html">
<source>other-3rdP-component</source>
<trans-unit id="b0a17f08a4bd742b2acf39780c257c2f519d33ed" datatype="html">
<source>other-3rdP-component
multi-lines</source>
<target/>
<context-group purpose="location">
<context context-type="sourcefile">node_modules/third_party/other_comp.d.ts</context>
<context context-type="linenumber">1</context>
</context-group>
</trans-unit>
</body>
</file>
Expand Down
3 changes: 2 additions & 1 deletion packages/compiler-cli/integrationtest/test/ng_module_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ describe('NgModule', () => {
const fixture = createComponent(ComponentUsingThirdParty);
const thirdPComps = fixture.nativeElement.children;
expect(thirdPComps[0].children[0].children[0].data).toEqual('3rdP-component');
expect(thirdPComps[1].children[0].children[0].data).toEqual('other-3rdP-component');
expect(thirdPComps[1].children[0].children[0].data).toEqual(`other-3rdP-component
multi-lines`);
});

// https://github.com/angular/angular/issues/12428
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {Component} from '@angular/core';

@Component({
selector: 'another-third-party-comp',
template: '<div i18n>other-3rdP-component</div>',
template: `<div i18n>other-3rdP-component
multi-lines</div>`,
})
export class AnotherThirdpartyComponent {
}
}
5 changes: 3 additions & 2 deletions packages/compiler-cli/src/extractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ export class Extractor {
default:
serializer = new compiler.Xliff();
}

return bundle.write(serializer);
return bundle.write(
serializer,
(sourcePath: string) => sourcePath.replace(path.join(this.options.basePath, '/'), ''));
}

getExtension(formatName: string): string {
Expand Down
27 changes: 25 additions & 2 deletions packages/compiler/src/i18n/i18n_ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import {ParseSourceSpan} from '../parse_util';

export class Message {
sources: MessageSpan[];

/**
* @param nodes message AST
* @param placeholders maps placeholder names to static content
Expand All @@ -20,7 +22,28 @@ export class Message {
constructor(
public nodes: Node[], public placeholders: {[phName: string]: string},
public placeholderToMessage: {[phName: string]: Message}, public meaning: string,
public description: string, public id: string) {}
public description: string, public id: string) {
if (nodes.length) {
this.sources = [{
filePath: nodes[0].sourceSpan.start.file.url,
startLine: nodes[0].sourceSpan.start.line + 1,
startCol: nodes[0].sourceSpan.start.col + 1,
endLine: nodes[nodes.length - 1].sourceSpan.end.line + 1,
endCol: nodes[0].sourceSpan.start.col + 1
}];
} else {
this.sources = [];
}
}
}

// line and columns indexes are 1 based
export interface MessageSpan {
filePath: string;
startLine: number;
startCol: number;
endLine: number;
endCol: number;
}

export interface Node {
Expand Down Expand Up @@ -131,4 +154,4 @@ export class RecurseVisitor implements Visitor {
visitPlaceholder(ph: Placeholder, context?: any): any{};

visitIcuPlaceholder(ph: IcuPlaceholder, context?: any): any{};
}
}
12 changes: 10 additions & 2 deletions packages/compiler/src/i18n/message_bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class MessageBundle {
// The public (serialized) format might be different, see the `write` method.
getMessages(): i18n.Message[] { return this._messages; }

write(serializer: Serializer): string {
write(serializer: Serializer, filterSources?: (path: string) => string): string {
const messages: {[id: string]: i18n.Message} = {};
const mapperVisitor = new MapPlaceholderNames();

Expand All @@ -57,6 +57,8 @@ export class MessageBundle {
const id = serializer.digest(message);
if (!messages.hasOwnProperty(id)) {
messages[id] = message;
} else {
messages[id].sources.push(...message.sources);
}
});

Expand All @@ -65,7 +67,13 @@ export class MessageBundle {
const mapper = serializer.createNameMapper(messages[id]);
const src = messages[id];
const nodes = mapper ? mapperVisitor.convert(src.nodes, mapper) : src.nodes;
return new i18n.Message(nodes, {}, {}, src.meaning, src.description, id);
let transformedMessage = new i18n.Message(nodes, {}, {}, src.meaning, src.description, id);
transformedMessage.sources = src.sources;
if (filterSources) {
transformedMessage.sources.forEach(
(source: i18n.MessageSpan) => source.filePath = filterSources(source.filePath));
}
return transformedMessage;
});

return serializer.write(msgList, this._locale);
Expand Down
18 changes: 17 additions & 1 deletion packages/compiler/src/i18n/serializers/xliff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const _FILE_TAG = 'file';
const _SOURCE_TAG = 'source';
const _TARGET_TAG = 'target';
const _UNIT_TAG = 'trans-unit';
const _CONTEXT_GROUP_TAG = 'context-group';
const _CONTEXT_TAG = 'context';

// http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html
// http://docs.oasis-open.org/xliff/v1.2/xliff-profile-html/xliff-profile-html-1.2.html
Expand All @@ -34,10 +36,24 @@ export class Xliff extends Serializer {
const transUnits: xml.Node[] = [];

messages.forEach(message => {
let contextTags: xml.Node[] = [];
message.sources.forEach((source: i18n.MessageSpan) => {
let contextGroupTag = new xml.Tag(_CONTEXT_GROUP_TAG, {purpose: 'location'});
contextGroupTag.children.push(
new xml.CR(10),
new xml.Tag(
_CONTEXT_TAG, {'context-type': 'sourcefile'}, [new xml.Text(source.filePath)]),
new xml.CR(10), new xml.Tag(
_CONTEXT_TAG, {'context-type': 'linenumber'},
[new xml.Text(`${source.startLine}`)]),
new xml.CR(8));
contextTags.push(new xml.CR(8), contextGroupTag);
});

const transUnit = new xml.Tag(_UNIT_TAG, {id: message.id, datatype: 'html'});
transUnit.children.push(
new xml.CR(8), new xml.Tag(_SOURCE_TAG, {}, visitor.serialize(message.nodes)),
new xml.CR(8), new xml.Tag(_TARGET_TAG));
new xml.CR(8), new xml.Tag(_TARGET_TAG), ...contextTags);

if (message.description) {
transUnit.children.push(
Expand Down
12 changes: 11 additions & 1 deletion packages/compiler/src/i18n/serializers/xmb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const _MESSAGES_TAG = 'messagebundle';
const _MESSAGE_TAG = 'msg';
const _PLACEHOLDER_TAG = 'ph';
const _EXEMPLE_TAG = 'ex';
const _SOURCE_TAG = 'source';

const _DOCTYPE = `<!ELEMENT messagebundle (msg)*>
<!ATTLIST messagebundle class CDATA #IMPLIED>
Expand Down Expand Up @@ -54,8 +55,17 @@ export class Xmb extends Serializer {
attrs['meaning'] = message.meaning;
}

let sourceTags: xml.Tag[] = [];
message.sources.forEach((source: i18n.MessageSpan) => {
sourceTags.push(new xml.Tag(_SOURCE_TAG, {}, [
new xml.Text(
`${source.filePath}:${source.startLine}${source.endLine !== source.startLine ? ',' + source.endLine : ''}`)
]));
});

rootNode.children.push(
new xml.CR(2), new xml.Tag(_MESSAGE_TAG, attrs, visitor.serialize(message.nodes)));
new xml.CR(2),
new xml.Tag(_MESSAGE_TAG, attrs, [...sourceTags, ...visitor.serialize(message.nodes)]));
});

rootNode.children.push(new xml.CR());
Expand Down
1 change: 1 addition & 0 deletions packages/compiler/test/i18n/digest_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export function main(): void {
placeholderToMessage: {},
meaning: '',
description: '',
sources: [],
})).toEqual('i');
});
});
Expand Down
Loading

0 comments on commit 8447762

Please sign in to comment.