2016-07-29 13:40:58 -07:00

102 lines
3.2 KiB
TypeScript

/**
* @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 {ListWrapper} from '../../facade/collection';
import * as i18nAst from '../i18n_ast';
import {Serializer} from './serializer';
import * as xml from './xml_helper';
const _MESSAGES_TAG = 'messagebundle';
const _MESSAGE_TAG = 'msg';
const _PLACEHOLDER_TAG = 'ph';
const _EXEMPLE_TAG = 'ex';
export class XmbSerializer implements Serializer {
// TODO(vicb): DOCTYPE
write(messageMap: {[k: string]: i18nAst.Message}): string {
const visitor = new _Visitor();
const declaration = new xml.Declaration({version: '1.0', encoding: 'UTF-8'});
let rootNode = new xml.Tag(_MESSAGES_TAG);
rootNode.children.push(new xml.Text('\n'));
Object.getOwnPropertyNames(messageMap).forEach((id) => {
const message = messageMap[id];
let attrs: {[k: string]: string} = {id};
if (message.description) {
attrs['desc'] = message.description;
}
if (message.meaning) {
attrs['meaning'] = message.meaning;
}
rootNode.children.push(
new xml.Text(' '), new xml.Tag(_MESSAGE_TAG, attrs, visitor.serialize(message.nodes)),
new xml.Text('\n'));
});
return xml.serialize([
declaration,
new xml.Text('\n'),
rootNode,
]);
}
load(content: string): {[k: string]: i18nAst.Node[]} { throw new Error('Unsupported'); }
}
class _Visitor implements i18nAst.Visitor {
visitText(text: i18nAst.Text, context?: any): xml.Node[] { return [new xml.Text(text.value)]; }
visitContainer(container: i18nAst.Container, context?: any): xml.Node[] {
const nodes: xml.Node[] = [];
container.children.forEach((node: i18nAst.Node) => nodes.push(...node.visit(this)));
return nodes;
}
visitIcu(icu: i18nAst.Icu, context?: any): xml.Node[] {
const nodes = [new xml.Text(`{${icu.expression}, ${icu.type}, `)];
Object.getOwnPropertyNames(icu.cases).forEach((c: string) => {
nodes.push(new xml.Text(`${c} {`), ...icu.cases[c].visit(this), new xml.Text(`}`));
});
nodes.push(new xml.Text(`}`));
return nodes;
}
visitTagPlaceholder(ph: i18nAst.TagPlaceholder, context?: any): xml.Node[] {
const startEx = new xml.Tag(_EXEMPLE_TAG, {}, [new xml.Text(`<${ph.tag}>`)]);
const startTagPh = new xml.Tag(_PLACEHOLDER_TAG, {name: ph.startName}, [startEx]);
if (ph.isVoid) {
// void tags have no children nor closing tags
return [startTagPh];
}
const closeEx = new xml.Tag(_EXEMPLE_TAG, {}, [new xml.Text(`</${ph.tag}>`)]);
const closeTagPh = new xml.Tag(_PLACEHOLDER_TAG, {name: ph.closeName}, [closeEx]);
return [startTagPh, ...this.serialize(ph.children), closeTagPh];
}
visitPlaceholder(ph: i18nAst.Placeholder, context?: any): xml.Node[] {
return [new xml.Tag(_PLACEHOLDER_TAG, {name: ph.name})];
}
visitIcuPlaceholder(ph: i18nAst.IcuPlaceholder, context?: any): xml.Node[] {
return [new xml.Tag(_PLACEHOLDER_TAG, {name: ph.name})];
}
serialize(nodes: i18nAst.Node[]): xml.Node[] {
return ListWrapper.flatten(nodes.map(node => node.visit(this)));
}
}