diff --git a/modules/@angular/compiler/src/i18n/i18n_parser.ts b/modules/@angular/compiler/src/i18n/i18n_parser.ts index b2499e89ec..41a6144b68 100644 --- a/modules/@angular/compiler/src/i18n/i18n_parser.ts +++ b/modules/@angular/compiler/src/i18n/i18n_parser.ts @@ -12,7 +12,6 @@ import * as html from '../ml_parser/ast'; import {getHtmlTagDefinition} from '../ml_parser/html_tags'; import {InterpolationConfig} from '../ml_parser/interpolation_config'; import {ParseSourceSpan} from '../parse_util'; -import {digest} from './digest'; import * as i18n from './i18n_ast'; import {PlaceholderRegistry} from './serializers/placeholder'; @@ -34,8 +33,8 @@ class _I18nVisitor implements html.Visitor { private _isIcu: boolean; private _icuDepth: number; private _placeholderRegistry: PlaceholderRegistry; - private _placeholderToContent: {[name: string]: string}; - private _placeholderToMessage: {[name: string]: i18n.Message}; + private _placeholderToContent: {[phName: string]: string}; + private _placeholderToMessage: {[phName: string]: i18n.Message}; constructor( private _expressionParser: ExpressionParser, diff --git a/modules/@angular/compiler/src/i18n/serializers/xliff.ts b/modules/@angular/compiler/src/i18n/serializers/xliff.ts index 52b8370efe..0f5d1b004d 100644 --- a/modules/@angular/compiler/src/i18n/serializers/xliff.ts +++ b/modules/@angular/compiler/src/i18n/serializers/xliff.ts @@ -35,12 +35,17 @@ export class Xliff implements Serializer { write(messages: i18n.Message[]): string { const visitor = new _WriteVisitor(); - + const visited: {[id: string]: boolean} = {}; const transUnits: xml.Node[] = []; messages.forEach(message => { + const id = this.digest(message); - const transUnit = new xml.Tag(_UNIT_TAG, {id: this.digest(message), datatype: 'html'}); + // deduplicate messages + if (visited[id]) return; + visited[id] = true; + + const transUnit = new xml.Tag(_UNIT_TAG, {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)); diff --git a/modules/@angular/compiler/src/i18n/serializers/xmb.ts b/modules/@angular/compiler/src/i18n/serializers/xmb.ts index e510197fa5..97b3934467 100644 --- a/modules/@angular/compiler/src/i18n/serializers/xmb.ts +++ b/modules/@angular/compiler/src/i18n/serializers/xmb.ts @@ -42,10 +42,17 @@ const _DOCTYPE = ` export class Xmb implements Serializer { write(messages: i18n.Message[]): string { const visitor = new _Visitor(); - const rootNode = new xml.Tag(_MESSAGES_TAG); + const visited: {[id: string]: boolean} = {}; + let rootNode = new xml.Tag(_MESSAGES_TAG); messages.forEach(message => { - const attrs: {[k: string]: string} = {id: this.digest(message)}; + const id = this.digest(message); + + // deduplicate messages + if (visited[id]) return; + visited[id] = true; + + const attrs: {[k: string]: string} = {id}; if (message.description) { attrs['desc'] = message.description; diff --git a/modules/@angular/compiler/src/i18n/serializers/xtb.ts b/modules/@angular/compiler/src/i18n/serializers/xtb.ts index 2cca95c891..a708fc9113 100644 --- a/modules/@angular/compiler/src/i18n/serializers/xtb.ts +++ b/modules/@angular/compiler/src/i18n/serializers/xtb.ts @@ -29,7 +29,7 @@ export class Xtb implements Serializer { load(content: string, url: string, messageBundle: MessageBundle): {[id: string]: ml.Node[]} { // Parse the xtb file into xml nodes - const result = new XmlParser().parse(content, url); + const result = new XmlParser().parse(content, url, true); if (result.errors.length) { throw new Error(`xtb parse errors:\n${result.errors.join('\n')}`); @@ -188,12 +188,11 @@ class _Visitor implements ml.Visitor { visitExpansion(expansion: ml.Expansion, context: any): any { const strCases = expansion.cases.map(c => c.visit(this, null)); - - return `{${expansion.switchValue}, ${expansion.type}, strCases.join(' ')}`; + return `{${expansion.switchValue}, ${expansion.type}, ${strCases.join(' ')}}`; } visitExpansionCase(expansionCase: ml.ExpansionCase, context: any): any { - return `${expansionCase.value} {${ml.visitAll(this, expansionCase.expression, null)}}`; + return `${expansionCase.value} {${ml.visitAll(this, expansionCase.expression, null).join('')}}`; } private _addError(node: ml.Node, message: string): void {