feat(i18n): support plural and gender special forms
This commit is contained in:
@@ -6,6 +6,8 @@ import {
|
||||
HtmlAttrAst,
|
||||
HtmlTextAst,
|
||||
HtmlCommentAst,
|
||||
HtmlExpansionAst,
|
||||
HtmlExpansionCaseAst,
|
||||
htmlVisitAll
|
||||
} from 'angular2/src/compiler/html_ast';
|
||||
import {ParseError, ParseLocation} from 'angular2/src/compiler/parse_util';
|
||||
@@ -70,6 +72,19 @@ class _Humanizer implements HtmlAstVisitor {
|
||||
return null;
|
||||
}
|
||||
|
||||
visitExpansion(ast: HtmlExpansionAst, context: any): any {
|
||||
var res = this._appendContext(ast, [HtmlExpansionAst, ast.switchValue, ast.type]);
|
||||
this.result.push(res);
|
||||
htmlVisitAll(this, ast.cases);
|
||||
return null;
|
||||
}
|
||||
|
||||
visitExpansionCase(ast: HtmlExpansionCaseAst, context: any): any {
|
||||
var res = this._appendContext(ast, [HtmlExpansionCaseAst, ast.value]);
|
||||
this.result.push(res);
|
||||
return null;
|
||||
}
|
||||
|
||||
private _appendContext(ast: HtmlAst, input: any[]): any[] {
|
||||
if (!this.includeSourceSpan) return input;
|
||||
input.push(ast.sourceSpan.toString());
|
||||
|
||||
@@ -42,7 +42,7 @@ export function main() {
|
||||
let res = deserializeXmb(`<message-bundle>${msgs}</message-bundle>`, 'someUrl');
|
||||
|
||||
return new I18nHtmlParser(htmlParser, parser, res.content, res.messages)
|
||||
.parse(template, "someurl");
|
||||
.parse(template, "someurl", true);
|
||||
}
|
||||
|
||||
it("should delegate to the provided parser when no i18n", () => {
|
||||
@@ -188,6 +188,82 @@ export function main() {
|
||||
expect(res[1].sourceSpan.start.offset).toEqual(10);
|
||||
});
|
||||
|
||||
it("should handle the plural special form", () => {
|
||||
let translations: {[key: string]: string} = {};
|
||||
translations[id(new Message('zero<ph name="e1">bold</ph>', "plural_0", null))] =
|
||||
'ZERO<ph name="e1">BOLD</ph>';
|
||||
|
||||
let res = parse(`{messages.length, plural,=0 {zero<b>bold</b>}}`, translations);
|
||||
|
||||
expect(humanizeDom(res))
|
||||
.toEqual([
|
||||
[HtmlElementAst, 'ul', 0],
|
||||
[HtmlAttrAst, '[ngPlural]', 'messages.length'],
|
||||
[HtmlElementAst, 'template', 1],
|
||||
[HtmlAttrAst, '[ngPluralCase]', '0'],
|
||||
[HtmlElementAst, 'li', 2],
|
||||
[HtmlTextAst, 'ZERO', 3],
|
||||
[HtmlElementAst, 'b', 3],
|
||||
[HtmlTextAst, 'BOLD', 4]
|
||||
]);
|
||||
});
|
||||
|
||||
it("should correctly set source code positions", () => {
|
||||
let translations: {[key: string]: string} = {};
|
||||
translations[id(new Message('<ph name="e0">bold</ph>', "plural_0", null))] =
|
||||
'<ph name="e0">BOLD</ph>';
|
||||
|
||||
let nodes = parse(`{messages.length, plural,=0 {<b>bold</b>}}`, translations).rootNodes;
|
||||
|
||||
let ul: HtmlElementAst = <HtmlElementAst>nodes[0];
|
||||
|
||||
expect(ul.sourceSpan.start.col).toEqual(0);
|
||||
expect(ul.sourceSpan.end.col).toEqual(42);
|
||||
|
||||
expect(ul.startSourceSpan.start.col).toEqual(0);
|
||||
expect(ul.startSourceSpan.end.col).toEqual(42);
|
||||
|
||||
expect(ul.endSourceSpan.start.col).toEqual(0);
|
||||
expect(ul.endSourceSpan.end.col).toEqual(42);
|
||||
|
||||
let switchExp = ul.attrs[0];
|
||||
expect(switchExp.sourceSpan.start.col).toEqual(1);
|
||||
expect(switchExp.sourceSpan.end.col).toEqual(16);
|
||||
|
||||
let template: HtmlElementAst = <HtmlElementAst>ul.children[0];
|
||||
expect(template.sourceSpan.start.col).toEqual(26);
|
||||
expect(template.sourceSpan.end.col).toEqual(41);
|
||||
|
||||
let switchCheck = template.attrs[0];
|
||||
expect(switchCheck.sourceSpan.start.col).toEqual(26);
|
||||
expect(switchCheck.sourceSpan.end.col).toEqual(28);
|
||||
|
||||
let li: HtmlElementAst = <HtmlElementAst>template.children[0];
|
||||
expect(li.sourceSpan.start.col).toEqual(26);
|
||||
expect(li.sourceSpan.end.col).toEqual(41);
|
||||
|
||||
let b: HtmlElementAst = <HtmlElementAst>li.children[0];
|
||||
expect(b.sourceSpan.start.col).toEqual(29);
|
||||
expect(b.sourceSpan.end.col).toEqual(32);
|
||||
});
|
||||
|
||||
it("should handle other special forms", () => {
|
||||
let translations: {[key: string]: string} = {};
|
||||
translations[id(new Message('m', "gender_male", null))] = 'M';
|
||||
|
||||
let res = parse(`{person.gender, gender,=male {m}}`, translations);
|
||||
|
||||
expect(humanizeDom(res))
|
||||
.toEqual([
|
||||
[HtmlElementAst, 'ul', 0],
|
||||
[HtmlAttrAst, '[ngSwitch]', 'person.gender'],
|
||||
[HtmlElementAst, 'template', 1],
|
||||
[HtmlAttrAst, '[ngSwitchWhen]', 'male'],
|
||||
[HtmlElementAst, 'li', 2],
|
||||
[HtmlTextAst, 'M', 3],
|
||||
]);
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
it("should error when giving an invalid template", () => {
|
||||
expect(humanizeErrors(parse("<a>a</b>", {}).errors))
|
||||
|
||||
@@ -176,6 +176,24 @@ export function main() {
|
||||
]);
|
||||
});
|
||||
|
||||
it("should extract messages from special forms", () => {
|
||||
let res = extractor.extract(`
|
||||
<div>
|
||||
{messages.length, plural,
|
||||
=0 {You have <b>no</b> messages}
|
||||
=1 {You have one message}
|
||||
}
|
||||
</div>
|
||||
`,
|
||||
"someurl");
|
||||
|
||||
expect(res.messages)
|
||||
.toEqual([
|
||||
new Message('You have <ph name="e1">no</ph> messages', "plural_0", null),
|
||||
new Message('You have one message', "plural_1", null)
|
||||
]);
|
||||
});
|
||||
|
||||
it("should remove duplicate messages", () => {
|
||||
let res = extractor.extract(`
|
||||
<!-- i18n: meaning|desc1 -->message<!-- /i18n -->
|
||||
|
||||
Reference in New Issue
Block a user