`, true)).toEqual([[
- HtmlTokenType.RAW_TEXT,
- 'Unexpected character "EOF" (Do you have an unescaped "{" in your template?).',
- '0:21',
- ]]);
- });
-
- it('should include 2 lines of context in message', () => {
- let src = '111\n222\n333\nE\n444\n555\n666\n';
- let file = new ParseSourceFile(src, 'file://');
- let location = new ParseLocation(file, 12, 123, 456);
- let span = new ParseSourceSpan(location, location);
- let error = new HtmlTokenError('**ERROR**', null, span);
- expect(error.toString())
- .toEqual(`**ERROR** ("\n222\n333\n[ERROR ->]E\n444\n555\n"): file://@123:456`);
- });
- });
-
- describe('unicode characters', () => {
- it('should support unicode characters', () => {
- expect(tokenizeAndHumanizeSourceSpans(`
`, true)).toEqual([[
+ lex.TokenType.RAW_TEXT,
+ `Unexpected character "EOF" (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.)`,
+ '0:21',
+ ]]);
+ });
+
+ it('should include 2 lines of context in message', () => {
+ let src = '111\n222\n333\nE\n444\n555\n666\n';
+ let file = new ParseSourceFile(src, 'file://');
+ let location = new ParseLocation(file, 12, 123, 456);
+ let span = new ParseSourceSpan(location, location);
+ let error = new lex.TokenError('**ERROR**', null, span);
+ expect(error.toString())
+ .toEqual(`**ERROR** ("\n222\n333\n[ERROR ->]E\n444\n555\n"): file://@123:456`);
+ });
+ });
+
+ describe('unicode characters', () => {
+ it('should support unicode characters', () => {
+ expect(tokenizeAndHumanizeSourceSpans(`
', '{count, plural, =0 {html}}',
+ '{{interp}}'
+ ],
+ '', ''
+ ],
+ ]);
+ });
+
+ it('should ignore other comments', () => {
+ expect(extract(`message1`))
+ .toEqual([
+ [['message1'], 'meaning1', 'desc1'],
+ ]);
+ });
+
+ it('should not create a message for empty blocks',
+ () => { expect(extract(``)).toEqual([]); });
+ });
+
+ describe('ICU messages', () => {
+ it('should extract ICU messages from translatable elements', () => {
+ // single message when ICU is the only children
+ expect(extract('
{count, plural, =0 {text}}
')).toEqual([
+ [['{count, plural, =0 {text}}'], 'm', 'd'],
+ ]);
+
+ // one message for the element content and one message for the ICU
+ expect(extract('
before{count, plural, =0 {text}}after
')).toEqual([
+ [['before', '{count, plural, =0 {text}}', 'after'], 'm', 'd'],
+ [['{count, plural, =0 {text}}'], '', ''],
+ ]);
+ });
+
+ it('should extract ICU messages from translatable block', () => {
+ // single message when ICU is the only children
+ expect(extract('{count, plural, =0 {text}}')).toEqual([
+ [['{count, plural, =0 {text}}'], 'm', 'd'],
+ ]);
+
+ // one message for the block content and one message for the ICU
+ expect(extract('before{count, plural, =0 {text}}after'))
+ .toEqual([
[['{count, plural, =0 {text}}'], '', ''],
+ [['before', '{count, plural, =0 {text}}', 'after'], 'm', 'd'],
]);
- });
+ });
- it('should extract ICU messages from translatable block', () => {
- // single message when ICU is the only children
- expect(extract('{count, plural, =0 {text}}')).toEqual([
- [['{count, plural, =0 {text}}'], 'm', 'd'],
+ it('should not extract ICU messages outside of i18n sections',
+ () => { expect(extract('{count, plural, =0 {text}}')).toEqual([]); });
+
+ it('should not extract nested ICU messages', () => {
+ expect(extract('
{count, plural, =0 { {sex, gender, =m {m}} }}
'))
+ .toEqual([
+ [['{count, plural, =0 {{sex, gender, =m {m}} }}'], 'm', 'd'],
]);
+ });
+ });
- // one message for the block content and one message for the ICU
- expect(extract('before{count, plural, =0 {text}}after'))
- .toEqual([
- [['{count, plural, =0 {text}}'], '', ''],
- [['before', '{count, plural, =0 {text}}', 'after'], 'm', 'd'],
- ]);
- });
+ describe('attributes', () => {
+ it('should extract from attributes outside of translatable section', () => {
+ expect(extract('')).toEqual([
+ [['title="msg"'], 'm', 'd'],
+ ]);
+ });
- it('should not extract ICU messages outside of i18n sections',
- () => { expect(extract('{count, plural, =0 {text}}')).toEqual([]); });
+ it('should extract from attributes in translatable element', () => {
+ expect(extract('
`)).toEqual([
+ ['Could not mark an element as translatable inside a translatable section', ''],
+ ]);
});
- describe('implicit attributes', () => {
- it('should extract implicit attributes', () => {
- expect(extract('bolditalic', [], {'b': ['title']}))
- .toEqual([
- [['title="bb"'], '', ''],
- ]);
- });
+ it('should report translatable elements in implicit elements', () => {
+ expect(extractErrors(`
`, ['p'])).toEqual([
+ ['Could not mark an element as translatable inside a translatable section', ''],
+ ]);
});
- describe('errors', () => {
- describe('elements', () => {
- it('should report nested translatable elements', () => {
- expect(extractErrors(`
`)).toEqual([
- [
- 'Could not mark an element as translatable inside a translatable section',
- ''
- ],
- ]);
- });
-
- it('should report translatable elements in implicit elements', () => {
- expect(extractErrors(`
`, ['p'])).toEqual([
- [
- 'Could not mark an element as translatable inside a translatable section',
- ''
- ],
- ]);
- });
-
- it('should report translatable elements in translatable blocks', () => {
- expect(extractErrors(``)).toEqual([
- [
- 'Could not mark an element as translatable inside a translatable section',
- ''
- ],
- ]);
- });
- });
-
- describe('blocks', () => {
- it('should report nested blocks', () => {
- expect(extractErrors(``))
- .toEqual([
- ['Could not start a block inside a translatable section', '`)).toEqual([
- ['Unclosed block', '`)).toEqual([
- ['Could not start a block inside a translatable section', '`, ['p'])).toEqual([
- ['Could not start a block inside a translatable section', '`)).toEqual([
- ['I18N blocks should not cross element boundaries', '`)).toEqual([
- ['I18N blocks should not cross element boundaries', '`, ['b'])).toEqual([
- ['Could not mark an element as translatable inside a translatable section', ''],
- ]);
- });
- });
+ it('should report translatable elements in translatable blocks', () => {
+ expect(extractErrors(``)).toEqual([
+ ['Could not mark an element as translatable inside a translatable section', ''],
+ ]);
});
});
+
+ describe('blocks', () => {
+ it('should report nested blocks', () => {
+ expect(extractErrors(``)).toEqual([
+ ['Could not start a block inside a translatable section', '`)).toEqual([
+ ['Unclosed block', '`)).toEqual([
+ ['Could not start a block inside a translatable section', '`, ['p'])).toEqual([
+ ['Could not start a block inside a translatable section', '`)).toEqual([
+ ['I18N blocks should not cross element boundaries', '`)).toEqual([
+ ['I18N blocks should not cross element boundaries', '`, ['b'])).toEqual([
+ ['Could not mark an element as translatable inside a translatable section', ''],
+ ]);
+ });
+ });
+ });
+ });
}
function getExtractionResult(
- html: string, implicitTags: string[], implicitAttrs:
- {[k: string]: string[]}): ExtractionResult {
+ html: string, implicitTags: string[],
+ implicitAttrs: {[k: string]: string[]}): ExtractionResult {
const htmlParser = new HtmlParser();
const parseResult = htmlParser.parse(html, 'extractor spec', true);
if (parseResult.errors.length > 1) {
@@ -275,8 +262,8 @@ function getExtractionResult(
}
function extract(
- html: string, implicitTags: string[] = [], implicitAttrs:
- {[k: string]: string[]} = {}): [string[], string, string][] {
+ html: string, implicitTags: string[] = [],
+ implicitAttrs: {[k: string]: string[]} = {}): [string[], string, string][] {
const messages = getExtractionResult(html, implicitTags, implicitAttrs).messages;
// clang-format off
@@ -287,8 +274,7 @@ function extract(
}
function extractErrors(
- html: string, implicitTags: string[] = [], implicitAttrs:
- {[k: string]: string[]} = {}): any[] {
+ html: string, implicitTags: string[] = [], implicitAttrs: {[k: string]: string[]} = {}): any[] {
const errors = getExtractionResult(html, implicitTags, implicitAttrs).errors;
return errors.map((e): [string, string] => [e.msg, e.span.toString()]);
diff --git a/modules/@angular/compiler/test/i18n/i18n_html_parser_spec.ts b/modules/@angular/compiler/test/i18n/i18n_html_parser_spec.ts
deleted file mode 100644
index 8646bcbb87..0000000000
--- a/modules/@angular/compiler/test/i18n/i18n_html_parser_spec.ts
+++ /dev/null
@@ -1,298 +0,0 @@
-/**
- * @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 {Lexer as ExpressionLexer} from '@angular/compiler/src/expression_parser/lexer';
-import {Parser as ExpressionParser} from '@angular/compiler/src/expression_parser/parser';
-import {I18nHtmlParser} from '@angular/compiler/src/i18n/i18n_html_parser';
-import {Message, id} from '@angular/compiler/src/i18n/message';
-import {deserializeXmb} from '@angular/compiler/src/i18n/xmb_serializer';
-import {ParseError} from '@angular/compiler/src/parse_util';
-import {ddescribe, describe, expect, iit, it} from '@angular/core/testing/testing_internal';
-
-import {StringMapWrapper} from '../../src/facade/collection';
-import {HtmlAttrAst, HtmlElementAst, HtmlTextAst} from '../../src/html_parser/html_ast';
-import {HtmlParseTreeResult, HtmlParser} from '../../src/html_parser/html_parser';
-import {InterpolationConfig} from '../../src/html_parser/interpolation_config';
-import {humanizeDom} from '../html_parser/html_ast_spec_utils';
-
-export function main() {
- describe('I18nHtmlParser', () => {
- function parse(
- template: string, messages: {[key: string]: string}, implicitTags: string[] = [],
- implicitAttrs: {[k: string]: string[]} = {},
- interpolation?: InterpolationConfig): HtmlParseTreeResult {
- let htmlParser = new HtmlParser();
-
- let msgs = '';
- StringMapWrapper.forEach(
- messages, (v: string, k: string) => msgs += `${v}`);
- let res = deserializeXmb(`${msgs}`, 'someUrl');
-
- const expParser = new ExpressionParser(new ExpressionLexer());
-
- return new I18nHtmlParser(
- htmlParser, expParser, res.content, res.messages, implicitTags, implicitAttrs)
- .parse(template, 'someurl', true, interpolation);
- }
-
- it('should delegate to the provided parser when no i18n', () => {
- expect(humanizeDom(parse('
', translations).rootNodes[0]).children;
-
- expect(res[0].sourceSpan.start.offset).toEqual(18);
- expect(res[1].sourceSpan.start.offset).toEqual(10);
- });
-
- describe('errors', () => {
- it('should error when giving an invalid template', () => {
- expect(humanizeErrors(parse('a', {}).errors)).toEqual([
- 'Unexpected closing tag "b"'
- ]);
- });
-
- it('should error when no matching message (attr)', () => {
- let mid = id(new Message('some message', null, null));
- expect(humanizeErrors(parse('', {}).errors))
- .toEqual([`Cannot find message for id '${mid}', content 'some message'.`]);
- });
-
- it('should error when no matching message (text)', () => {
- let mid = id(new Message('some message', null, null));
- expect(humanizeErrors(parse('
some message
', {}).errors)).toEqual([
- `Cannot find message for id '${mid}', content 'some message'.`
- ]);
- });
-
- it('should error when a non-placeholder element appears in translation', () => {
- let translations: {[key: string]: string} = {};
- translations[id(new Message('some message', null, null))] = 'a';
-
- expect(humanizeErrors(parse('
some message
', translations).errors)).toEqual([
- `Unexpected tag "a". Only "ph" tags are allowed.`
- ]);
- });
-
- it('should error when a placeholder element does not have the name attribute', () => {
- let translations: {[key: string]: string} = {};
- translations[id(new Message('some message', null, null))] = 'a';
-
- expect(humanizeErrors(parse('
some message
', translations).errors)).toEqual([
- `Missing "name" attribute.`
- ]);
- });
-
- it('should error when the translation refers to an invalid expression', () => {
- let translations: {[key: string]: string} = {};
- translations[id(new Message('hi ', null, null))] =
- 'hi ';
-
- expect(
- humanizeErrors(parse('', translations).errors))
- .toEqual(['Invalid interpolation name \'INTERPOLATION_99\'']);
- });
- });
-
- describe('implicit translation', () => {
- it('should support attributes', () => {
- let translations: {[key: string]: string} = {};
- translations[id(new Message('some message', null, null))] = 'another message';
-
- expect(humanizeDom(parse('', translations, [], {
- 'i18n-el': ['value']
- }))).toEqual([[HtmlElementAst, 'i18n-el', 0], [HtmlAttrAst, 'value', 'another message']]);
- });
-
- it('should support attributes with meaning and description', () => {
- let translations: {[key: string]: string} = {};
- translations[id(new Message('some message', 'meaning', 'description'))] = 'another message';
-
- expect(humanizeDom(parse(
- '',
- translations, [], {'i18n-el': ['value']})))
- .toEqual([[HtmlElementAst, 'i18n-el', 0], [HtmlAttrAst, 'value', 'another message']]);
- });
-
- it('should support elements', () => {
- let translations: {[key: string]: string} = {};
- translations[id(new Message('message', null, null))] = 'another message';
-
- expect(humanizeDom(parse('message', translations, ['i18n-el'])))
- .toEqual([[HtmlElementAst, 'i18n-el', 0], [HtmlTextAst, 'another message', 1]]);
- });
-
- it('should support elements with meaning and description', () => {
- let translations: {[key: string]: string} = {};
- translations[id(new Message('message', 'meaning', 'description'))] = 'another message';
-
- expect(humanizeDom(parse(
- 'message', translations,
- ['i18n-el'])))
- .toEqual([[HtmlElementAst, 'i18n-el', 0], [HtmlTextAst, 'another message', 1]]);
- });
- });
- });
-}
-
-function humanizeErrors(errors: ParseError[]): string[] {
- return errors.map(error => error.msg);
-}
diff --git a/modules/@angular/compiler/test/i18n/i18n_parser_spec.ts b/modules/@angular/compiler/test/i18n/i18n_parser_spec.ts
index 13c658a5bf..18171c7bd9 100644
--- a/modules/@angular/compiler/test/i18n/i18n_parser_spec.ts
+++ b/modules/@angular/compiler/test/i18n/i18n_parser_spec.ts
@@ -6,25 +6,26 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {serializeAst} from '@angular/compiler/src/i18n/catalog';
+import {Message} from '@angular/compiler/src/i18n/i18n_ast';
import {extractI18nMessages} from '@angular/compiler/src/i18n/i18n_parser';
import {ddescribe, describe, expect, it} from '@angular/core/testing/testing_internal';
import {HtmlParser} from '../../src/html_parser/html_parser';
import {DEFAULT_INTERPOLATION_CONFIG} from '../../src/html_parser/interpolation_config';
+import {serializeAst} from '../../src/i18n/message_bundle';
export function main() {
- ddescribe('I18nParser', () => {
+ describe('I18nParser', () => {
describe('elements', () => {
it('should extract from elements', () => {
- expect(extract('
`)).toEqual([
[
[
'text',
@@ -152,33 +157,36 @@ export function main() {
describe('ICU messages', () => {
it('should extract as ICU when single child of an element', () => {
- expect(extract('
{count, plural, =0 {zero}}
')).toEqual([
+ expect(_humanizeMessages('
{count, plural, =0 {zero}}
')).toEqual([
[['{count, plural, =0 {[zero]}}'], 'm', 'd'],
]);
});
it('should extract as ICU + ph when not single child of an element', () => {
- expect(extract('
', 'url', DEFAULT_INTERPOLATION_CONFIG);
- expect(humanizeCatalog(catalog)).toEqual([
+ expect(humanizeMessages(messages)).toEqual([
'a486901=Translate Me',
]);
});
it('should extract the same message with different meaning in different entries', () => {
- catalog.updateFromTemplate(
+ messages.updateFromTemplate(
'
Translate Me
Translate Me
', 'url',
DEFAULT_INTERPOLATION_CONFIG);
- expect(humanizeCatalog(catalog)).toEqual([
+ expect(humanizeMessages(messages)).toEqual([
'a486901=Translate Me',
'8475f2cc=Translate Me',
]);
});
});
- describe(
- 'load', () => {
- // TODO
- });
-
describe('strHash', () => {
it('should return a hash value', () => {
// https://github.com/google/closure-library/blob/1fb19a857b96b74e6523f3e9d33080baf25be046/closure/goog/string/string_test.js#L1115
@@ -66,16 +57,16 @@ export function main(): void {
}
class _TestSerializer implements Serializer {
- write(messageMap: {[k: string]: i18nAst.Message}): string {
+ write(messageMap: {[id: string]: i18n.Message}): string {
return Object.keys(messageMap)
.map(id => `${id}=${serializeAst(messageMap[id].nodes)}`)
.join('//');
}
- load(content: string): {[k: string]: i18nAst.Node[]} { return null; }
+ load(content: string, url: string, placeholders: {}): {} { return null; }
}
-function humanizeCatalog(catalog: Catalog): string[] {
+function humanizeMessages(catalog: MessageBundle): string[] {
return catalog.write(new _TestSerializer()).split('//');
}
diff --git a/modules/@angular/compiler/test/i18n/message_extractor_spec.ts b/modules/@angular/compiler/test/i18n/message_extractor_spec.ts
deleted file mode 100644
index ade2e93c4b..0000000000
--- a/modules/@angular/compiler/test/i18n/message_extractor_spec.ts
+++ /dev/null
@@ -1,275 +0,0 @@
-/**
- * @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 {Lexer as ExpressionLexer} from '@angular/compiler/src/expression_parser/lexer';
-import {Parser as ExpressionParser} from '@angular/compiler/src/expression_parser/parser';
-import {Message} from '@angular/compiler/src/i18n/message';
-import {MessageExtractor, removeDuplicates} from '@angular/compiler/src/i18n/message_extractor';
-import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
-
-import {HtmlParser} from '../../src/html_parser/html_parser';
-
-
-export function main() {
- describe('MessageExtractor', () => {
- let extractor: MessageExtractor;
-
- beforeEach(() => {
- const expParser = new ExpressionParser(new ExpressionLexer());
- const htmlParser = new HtmlParser();
- extractor = new MessageExtractor(htmlParser, expParser, ['i18n-tag'], {'i18n-el': ['trans']});
- });
-
- it('should extract from partitions', () => {
- let res = extractor.extract(
- `
- message1
- message2
- message3`,
- 'someUrl');
-
- expect(res.messages).toEqual([
- new Message('message1', 'meaning1', 'desc1'),
- new Message('message2', 'meaning2'),
- new Message('message3', null),
- ]);
- });
-
- it('should ignore other comments', () => {
- let res = extractor.extract(
- `
- message1`,
- 'someUrl');
-
- expect(res.messages).toEqual([new Message('message1', 'meaning1', 'desc1')]);
- });
-
- describe('ICU messages', () => {
- it('should replace icu messages with placeholders', () => {
- let res = extractor.extract('
{count, plural, =0 {text} }
', 'someurl');
- expect(res.messages).toEqual([new Message(
- '{count, plural =0 {text}}', null, null)]);
- });
-
- it('should replace HTML with placeholders in ICU cases', () => {
- let res =
- extractor.extract('
{count, plural, =0 {
html
} }
', 'someurl');
- expect(res.messages).toEqual([new Message(
- '{count, plural =0 {html}}', null, null)]);
- });
-
- it('should replace interpolation with placeholders in ICU cases', () => {
- let res =
- extractor.extract('
{count, plural, =0 {{{interpolation}}}}
', 'someurl');
- expect(res.messages).toEqual([new Message(
- '{count, plural =0 {}}',
- null, null)]);
- });
-
- it('should not replace nested interpolation with placeholders in ICU cases', () => {
- let res = extractor.extract(
- '
', 'someurl');
- expect(res.messages).toEqual([new Message(
- 'Hi and ',
- null, null)]);
- });
-
- it('should replace interpolation with placeholders (attributes)', () => {
- let res =
- extractor.extract('', 'someurl');
- expect(res.messages).toEqual([new Message(
- 'Hi and ', null, null)]);
- });
-
- it('should replace interpolation with named placeholders if provided (text nodes)', () => {
- let res = extractor.extract(
- `
-
Hi {{one //i18n(ph="FIRST")}} and {{two //i18n(ph="SECOND")}}
`,
- 'someurl');
- expect(res.messages).toEqual([new Message(
- 'Hi and ', null, null)]);
- });
-
- it('should replace interpolation with named placeholders if provided (attributes)', () => {
- let res = extractor.extract(
- `
- `,
- 'someurl');
- expect(res.messages).toEqual([new Message(
- 'Hi and ', null, null)]);
- });
- });
-
- describe('placehoders', () => {
- it('should match named placeholders with extra spacing', () => {
- let res = extractor.extract(
- `
- `,
- 'someurl');
- expect(res.messages).toEqual([new Message(
- 'Hi and ', null, null)]);
- });
-
- it('should suffix duplicate placeholder names with numbers', () => {
- let res = extractor.extract(
- `
- `,
- 'someurl');
- expect(res.messages).toEqual([new Message(
- 'Hi and and ', null,
- null)]);
- });
- });
-
- describe('html', () => {
- it('should extract from elements with the i18n attr', () => {
- let res = extractor.extract('
message
', 'someurl');
- expect(res.messages).toEqual([new Message('message', 'meaning', 'desc')]);
- });
-
- it('should extract from elements with the i18n attr without a desc', () => {
- let res = extractor.extract('
message
', 'someurl');
- expect(res.messages).toEqual([new Message('message', 'meaning', null)]);
- });
-
- it('should extract from elements with the i18n attr without a meaning', () => {
- let res = extractor.extract('
message
', 'someurl');
- expect(res.messages).toEqual([new Message('message', null, null)]);
- });
-
- it('should extract from attributes', () => {
- let res = extractor.extract(
- `
-
-
- `,
- 'someurl');
-
- expect(res.messages).toEqual([
- new Message('message1', 'meaning1', 'desc1'), new Message('message2', 'meaning2', 'desc2')
- ]);
- });
-
- it('should handle html content', () => {
- let res = extractor.extract(
- '
zero
one
two
', 'someurl');
- expect(res.messages).toEqual([new Message(
- 'zeroonetwo', null, null)]);
- });
-
- it('should handle html content with interpolation', () => {
- let res =
- extractor.extract('
zero{{a}}
{{b}}
', 'someurl');
- expect(res.messages).toEqual([new Message(
- 'zero',
- null, null)]);
- });
-
- it('should extract from nested elements', () => {
- let res = extractor.extract(
- '
message2
',
- 'someurl');
- expect(res.messages).toEqual([
- new Message('message2', 'meaning2', 'desc2'), new Message('message1', 'meaning1', 'desc1')
- ]);
- });
-
- it('should extract messages from attributes in i18n blocks', () => {
- let res = extractor.extract(
- '
message
', 'someurl');
- expect(res.messages).toEqual([
- new Message('message', null, null),
- new Message('value', 'meaning', 'desc')
- ]);
- });
- });
-
- it('should remove duplicate messages', () => {
- let res = extractor.extract(
- `
- message
- message`,
- 'someUrl');
-
- expect(removeDuplicates(res.messages)).toEqual([
- new Message('message', 'meaning', 'desc1'),
- ]);
- });
-
- describe('implicit translation', () => {
- it('should extract from elements', () => {
- let res = extractor.extract('message', 'someurl');
- expect(res.messages).toEqual([new Message('message', null, null)]);
- });
-
- it('should extract meaning and description from elements when present', () => {
- let res = extractor.extract(
- 'message', 'someurl');
- expect(res.messages).toEqual([new Message('message', 'meaning', 'description')]);
- });
-
- it('should extract from attributes', () => {
- let res = extractor.extract(``, 'someurl');
- expect(res.messages).toEqual([new Message('message', null, null)]);
- });
-
- it('should extract meaning and description from attributes when present', () => {
- let res = extractor.extract(
- ``, 'someurl');
- expect(res.messages).toEqual([new Message('message', 'meaning', 'desc')]);
- });
- });
-
- describe('errors', () => {
- it('should error on i18n attributes without matching "real" attributes', () => {
- let res = extractor.extract(
- `
-
-
`,
- 'someurl');
-
- expect(res.errors.length).toEqual(1);
- expect(res.errors[0].msg).toEqual('Missing attribute \'title2\'.');
- });
-
- it('should error when i18n comments are unbalanced', () => {
- const res = extractor.extract('message1', 'someUrl');
- expect(res.errors.length).toEqual(1);
- expect(res.errors[0].msg).toEqual('Missing closing \'i18n\' comment.');
- });
-
- it('should error when i18n comments are unbalanced', () => {
- const res = extractor.extract('', 'someUrl');
- expect(res.errors.length).toEqual(1);
- expect(res.errors[0].msg).toEqual('Missing closing \'i18n\' comment.');
- });
-
- it('should return parse errors when the template is invalid', () => {
- let res = extractor.extract(' {
- describe('id', () => {
- it('should return a different id for messages with and without the meaning', () => {
- let m1 = new Message('content', 'meaning', null);
- let m2 = new Message('content', null, null);
- expect(id(m1)).toEqual(id(m1));
- expect(id(m1)).not.toEqual(id(m2));
- });
- });
- });
-}
diff --git a/modules/@angular/compiler/test/i18n/serializers/util_spec.ts b/modules/@angular/compiler/test/i18n/serializers/placeholder_spec.ts
similarity index 96%
rename from modules/@angular/compiler/test/i18n/serializers/util_spec.ts
rename to modules/@angular/compiler/test/i18n/serializers/placeholder_spec.ts
index b539671c40..3d24f7a3d7 100644
--- a/modules/@angular/compiler/test/i18n/serializers/util_spec.ts
+++ b/modules/@angular/compiler/test/i18n/serializers/placeholder_spec.ts
@@ -6,14 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
-
-
import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
-import {PlaceholderRegistry} from '../../../src/i18n/serializers/util';
+import {PlaceholderRegistry} from '../../../src/i18n/serializers/placeholder';
export function main(): void {
- ddescribe('PlaceholderRegistry', () => {
+ describe('PlaceholderRegistry', () => {
let reg: PlaceholderRegistry;
beforeEach(() => { reg = new PlaceholderRegistry(); });
@@ -34,11 +32,11 @@ export function main(): void {
expect(reg.getStartTagPlaceholderName('p', {}, false)).toEqual('START_PARAGRAPH');
});
- it('should be case insensitive for tag name', () => {
+ it('should be case sensitive for tag name', () => {
expect(reg.getStartTagPlaceholderName('p', {}, false)).toEqual('START_PARAGRAPH');
- expect(reg.getStartTagPlaceholderName('P', {}, false)).toEqual('START_PARAGRAPH');
+ expect(reg.getStartTagPlaceholderName('P', {}, false)).toEqual('START_PARAGRAPH_1');
expect(reg.getCloseTagPlaceholderName('p')).toEqual('CLOSE_PARAGRAPH');
- expect(reg.getCloseTagPlaceholderName('P')).toEqual('CLOSE_PARAGRAPH');
+ expect(reg.getCloseTagPlaceholderName('P')).toEqual('CLOSE_PARAGRAPH_1');
});
it('should generate the same name for the same tag with the same attributes', () => {
diff --git a/modules/@angular/compiler/test/i18n/serializers/xmb_spec.ts b/modules/@angular/compiler/test/i18n/serializers/xmb_spec.ts
index d9108e7892..fbfb4a36a5 100644
--- a/modules/@angular/compiler/test/i18n/serializers/xmb_spec.ts
+++ b/modules/@angular/compiler/test/i18n/serializers/xmb_spec.ts
@@ -6,16 +6,15 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {Catalog} from '@angular/compiler/src/i18n/catalog';
-import {XmbSerializer} from '@angular/compiler/src/i18n/serializers/xmb';
+import {Xmb} from '@angular/compiler/src/i18n/serializers/xmb';
import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {HtmlParser} from '../../../src/html_parser/html_parser';
import {DEFAULT_INTERPOLATION_CONFIG} from '../../../src/html_parser/interpolation_config';
-
+import {MessageBundle} from '../../../src/i18n/message_bundle';
export function main(): void {
- ddescribe('XMB serializer', () => {
+ describe('XMB serializer', () => {
const HTML = `
not translatable
translatable element with placeholders {{ interpolation}}
@@ -35,35 +34,18 @@ export function main(): void {
it('should throw when trying to load an xmb file', () => {
expect(() => {
- const serializer = new XmbSerializer();
- serializer.load(XMB);
+ const serializer = new Xmb();
+ serializer.load(XMB, 'url', {});
}).toThrow();
});
});
}
function toXmb(html: string): string {
- let catalog = new Catalog(new HtmlParser, [], {});
- const serializer = new XmbSerializer();
+ let catalog = new MessageBundle(new HtmlParser, [], {});
+ const serializer = new Xmb();
catalog.updateFromTemplate(html, '', DEFAULT_INTERPOLATION_CONFIG);
return catalog.write(serializer);
-}
-
-// xml version="1.0" encoding="UTF-8" ?>translatable
-// element <b>with placeholders</b>{ count, plural, =0 {<p>test</p>}}foo{ count, plural, =0 {{ sex, gender, other {<p>deeply nested</p>}} }}
-// xml version="1.0" encoding="UTF-8" ?>translatable
-// element <b>with placeholders</b>{ count, plural, =0 {<p>test</p>}}{ count,
-// plural, =0 {{ sex, gender, other {<p>deeply
-// nested</p>}} }}foo
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/modules/@angular/compiler/test/i18n/serializers/xml_helper_spec.ts b/modules/@angular/compiler/test/i18n/serializers/xml_helper_spec.ts
index 1edc8d3f44..49b4e14917 100644
--- a/modules/@angular/compiler/test/i18n/serializers/xml_helper_spec.ts
+++ b/modules/@angular/compiler/test/i18n/serializers/xml_helper_spec.ts
@@ -11,7 +11,7 @@ import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit
import * as xml from '../../../src/i18n/serializers/xml_helper';
export function main(): void {
- ddescribe('XML helper', () => {
+ describe('XML helper', () => {
it('should serialize XML declaration', () => {
expect(xml.serialize([new xml.Declaration({version: '1.0'})]))
.toEqual(' xml version="1.0" ?>');
diff --git a/modules/@angular/compiler/test/i18n/serializers/xtb_spec.ts b/modules/@angular/compiler/test/i18n/serializers/xtb_spec.ts
new file mode 100644
index 0000000000..434d48692b
--- /dev/null
+++ b/modules/@angular/compiler/test/i18n/serializers/xtb_spec.ts
@@ -0,0 +1,171 @@
+/**
+ * @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 {Xtb} from '@angular/compiler/src/i18n/serializers/xtb';
+import {escapeRegExp} from '@angular/core/src/facade/lang';
+import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
+
+import {HtmlParser} from '../../../src/html_parser/html_parser';
+import {DEFAULT_INTERPOLATION_CONFIG} from '../../../src/html_parser/interpolation_config';
+import {serializeAst} from '../../html_parser/ast_serializer_spec';
+
+export function main(): void {
+ describe('XTB serializer', () => {
+ let serializer: Xtb;
+
+ function loadAsText(content: string, placeholders: {[id: string]: {[name: string]: string}}):
+ {[id: string]: string} {
+ const asAst = serializer.load(content, 'url', placeholders);
+ let asText: {[id: string]: string} = {};
+ Object.getOwnPropertyNames(asAst).forEach(
+ id => { asText[id] = serializeAst(asAst[id]).join(''); });
+
+ return asText;
+ }
+
+ beforeEach(() => { serializer = new Xtb(new HtmlParser(), DEFAULT_INTERPOLATION_CONFIG); });
+
+
+ describe('load', () => {
+ it('should load XTB files without placeholders', () => {
+ const XTB = `
+
+
+ bar
+`;
+
+ expect(loadAsText(XTB, {})).toEqual({foo: 'bar'});
+ });
+
+ it('should load XTB files with placeholders', () => {
+ const XTB = `
+
+
+ bar
+`;
+
+ expect(loadAsText(XTB, {foo: {PLACEHOLDER: '!'}})).toEqual({foo: 'bar!!'});
+ });
+
+ it('should load complex XTB files', () => {
+ const XTB = `
+ xml version="1.0" encoding="UTF-8" ?>
+
+ translatable element <b>with placeholders</b>
+ { count, plural, =0 {<p>test</p>}}
+ foo
+ { count, plural, =0 {{ sex, gender, other {<p>deeply nested</p>}} }}
+`;
+
+ const PLACEHOLDERS = {
+ a: {
+ START_BOLD_TEXT: '',
+ CLOSE_BOLD_TEXT: '',
+ INTERPOLATION: '{{ a + b }}',
+ },
+ b: {
+ START_PARAGRAPH: '
',
+ CLOSE_PARAGRAPH: '
',
+ },
+ d: {
+ START_PARAGRAPH: '
',
+ CLOSE_PARAGRAPH: '
',
+ },
+ };
+
+ expect(loadAsText(XTB, PLACEHOLDERS)).toEqual({
+ a: 'translatable element with placeholders {{ a + b }}',
+ b: '{ count, plural, =0 {