fix(compiler): fix missing translations handling (#14113)

PR Close #14113
This commit is contained in:
Victor Berchet
2017-01-25 23:26:49 -08:00
committed by Miško Hevery
parent 8775ab9495
commit 827c3fe199
12 changed files with 139 additions and 107 deletions

View File

@ -488,7 +488,7 @@ function fakeTranslate(
i18nMsgMap[id] = [new i18n.Text(`**${text}**`, null)];
});
const translations = new TranslationBundle(i18nMsgMap, digest, null);
const translations = new TranslationBundle(i18nMsgMap, digest);
const output = mergeTranslations(
htmlNodes, translations, DEFAULT_INTERPOLATION_CONFIG, implicitTags, implicitAttrs);

View File

@ -12,6 +12,7 @@ import * as i18n from '../../src/i18n/i18n_ast';
import {TranslationBundle} from '../../src/i18n/translation_bundle';
import {ParseLocation, ParseSourceFile, ParseSourceSpan} from '../../src/parse_util';
import {serializeNodes} from '../ml_parser/ast_serializer_spec';
import {_extractMessages} from './i18n_parser_spec';
export function main(): void {
describe('TranslationBundle', () => {
@ -22,7 +23,7 @@ export function main(): void {
it('should translate a plain message', () => {
const msgMap = {foo: [new i18n.Text('bar', null)]};
const tb = new TranslationBundle(msgMap, (_) => 'foo', null);
const tb = new TranslationBundle(msgMap, (_) => 'foo');
const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i');
expect(serializeNodes(tb.get(msg))).toEqual(['bar']);
});
@ -37,7 +38,7 @@ export function main(): void {
const phMap = {
ph1: '*phContent*',
};
const tb = new TranslationBundle(msgMap, (_) => 'foo', null);
const tb = new TranslationBundle(msgMap, (_) => 'foo');
const msg = new i18n.Message([srcNode], phMap, {}, 'm', 'd', 'i');
expect(serializeNodes(tb.get(msg))).toEqual(['bar*phContent*']);
});
@ -57,12 +58,29 @@ export function main(): void {
const msg = new i18n.Message([srcNode], {}, {ph1: refMsg}, 'm', 'd', 'i');
let count = 0;
const digest = (_: any) => count++ ? 'ref' : 'foo';
const tb = new TranslationBundle(msgMap, digest, null);
const tb = new TranslationBundle(msgMap, digest);
expect(serializeNodes(tb.get(msg))).toEqual(['--*refMsg*++']);
});
describe('errors', () => {
it('should use the original message or throw when a translation is not found', () => {
const src =
`<some-tag>some text{{ some_expression }}</some-tag>{count, plural, =0 {no} few {a <b>few</b>}}`;
const messages = _extractMessages(`<div i18n>${src}</div>`);
const digest = (_: any) => `no matching id`;
// Empty message map -> use source messages in Ignore mode
let tb = new TranslationBundle({}, digest, null, MissingTranslationStrategy.Ignore);
expect(serializeNodes(tb.get(messages[0])).join('')).toEqual(src);
// Empty message map -> use source messages in Warning mode
tb = new TranslationBundle({}, digest, null, MissingTranslationStrategy.Warning);
expect(serializeNodes(tb.get(messages[0])).join('')).toEqual(src);
// Empty message map -> throw in Error mode
tb = new TranslationBundle({}, digest, null, MissingTranslationStrategy.Error);
expect(() => serializeNodes(tb.get(messages[0])).join('')).toThrow();
});
describe('errors reporting', () => {
it('should report unknown placeholders', () => {
const msgMap = {
foo: [
@ -70,34 +88,35 @@ export function main(): void {
new i18n.Placeholder('', 'ph1', span),
]
};
const tb = new TranslationBundle(msgMap, (_) => 'foo', null);
const tb = new TranslationBundle(msgMap, (_) => 'foo');
const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i');
expect(() => tb.get(msg)).toThrowError(/Unknown placeholder/);
});
it('should report missing translation', () => {
const tb = new TranslationBundle(
{}, (_) => 'foo', null, MissingTranslationStrategy.Error);
const tb = new TranslationBundle({}, (_) => 'foo', null, MissingTranslationStrategy.Error);
const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i');
expect(() => tb.get(msg)).toThrowError(/Missing translation for message foo/);
expect(() => tb.get(msg)).toThrowError(/Missing translation for message "foo"/);
});
it('should report missing translation with MissingTranslationStrategy.Warning', () => {
const log: string[] = [];
const console = {
log: (msg: string) => { throw `unexpected`; },
warn: (msg: string) => log.push(msg),
};
const tb = new TranslationBundle(
{}, (_) => 'foo', null, MissingTranslationStrategy.Warning);
{}, (_) => 'foo', null, MissingTranslationStrategy.Warning, console);
const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i');
const warn = console.warn;
const consoleWarnSpy = spyOn(console, 'warn').and.callThrough();
expect(() => tb.get(msg)).not.toThrowError();
expect(consoleWarnSpy.calls.mostRecent().args[0])
.toMatch(/Missing translation for message foo/);
console.warn = warn;
expect(log.length).toEqual(1);
expect(log[0]).toMatch(/Missing translation for message "foo"/);
});
it('should not report missing translation with MissingTranslationStrategy.Ignore', () => {
const tb = new TranslationBundle(
{}, (_) => 'foo', null, MissingTranslationStrategy.Ignore);
const tb = new TranslationBundle({}, (_) => 'foo', null, MissingTranslationStrategy.Ignore);
const msg = new i18n.Message([srcNode], {}, {}, 'm', 'd', 'i');
expect(() => tb.get(msg)).not.toThrowError();
});
@ -110,9 +129,8 @@ export function main(): void {
const msg = new i18n.Message([srcNode], {}, {ph1: refMsg}, 'm', 'd', 'i');
let count = 0;
const digest = (_: any) => count++ ? 'ref' : 'foo';
const tb =
new TranslationBundle(msgMap, digest, null, MissingTranslationStrategy.Error);
expect(() => tb.get(msg)).toThrowError(/Missing translation for message ref/);
const tb = new TranslationBundle(msgMap, digest, null, MissingTranslationStrategy.Error);
expect(() => tb.get(msg)).toThrowError(/Missing translation for message "ref"/);
});
it('should report invalid translated html', () => {
@ -125,7 +143,7 @@ export function main(): void {
const phMap = {
ph1: '</b>',
};
const tb = new TranslationBundle(msgMap, (_) => 'foo', null);
const tb = new TranslationBundle(msgMap, (_) => 'foo');
const msg = new i18n.Message([srcNode], phMap, {}, 'm', 'd', 'i');
expect(() => tb.get(msg)).toThrowError(/Unexpected closing tag "b"/);
});