1 | const {expect} = require('chai');
|
2 |
|
3 | import {extractMessages as extract} from '../src/extract';
|
4 | import translateMessagesToBundle from '../src/translate';
|
5 |
|
6 |
|
7 | describe('translation', function() {
|
8 | it('generates correct translator functions', function() {
|
9 | var translations = {
|
10 | 'Hello': 'Helo',
|
11 | 'world': 'byd',
|
12 | '<a href="foo">tag with only safe attributes</a>': '<a href="bar">Mae tag sydd <span>wedi</span> dim ond priodoleddau sy\'n ddiogel</a>',
|
13 | '<a:link href="foo">tag with unsafe attributes</a:link>': '<a:link href="bar">tag gyda phriodoleddau anniogel</a:link>',
|
14 | '<SelfClosing />': 'Translated: <SelfClosing />',
|
15 | '<SelfClosing:foo />': 'Translated: <SelfClosing:foo />',
|
16 | '<Member.Name />': 'Translated: <Member.Name />',
|
17 | 'Cat: {nested}': 'Cat : {nested}',
|
18 | 'hatters': 'hetwyr',
|
19 | 'And now {a.member.expression}': 'Ac yn awr {a.member.expression}',
|
20 | '<Re /><Ordering />': '<Ordering /><Re />',
|
21 | 'Check out: <Component />': '<Component/> "checked" out!',
|
22 | '<span:stat><ReactIntl.FormattedNumber /></span:stat>opportunities': '<span:stat><ReactIntl.FormattedNumber /></span:stat>oportunidades',
|
23 | '<Pluralize:items><Match when="=0">You have no items in your cart</Match><Match when="one">You have one item in your cart</Match><Match when="other">You have {this.state.count} items in your cart</Match></Pluralize:items>':
|
24 | '<Pluralize:items><Match when="=0">No tiene nada in su carrito</Match><Match when="one">Tiene ún articulo en su carrito</Match><Match when="other">Tiene {this.state.count} articulos en su carrito</Match></Pluralize:items>'
|
25 | };
|
26 |
|
27 | var expectedResultsForTranslationBundles = {
|
28 | '<I18N>Hello</I18N>': 'function() { return <span>Helo</span>; }',
|
29 | 'i18n("world")': 'function() { return "byd"; }',
|
30 | '<I18N><a href="foo">tag with only safe attributes</a></I18N>': 'function() { return <span><a href="bar">Mae tag sydd <span>wedi</span> dim ond priodoleddau sy\'n ddiogel</a></span>; }',
|
31 | '<I18N><a:link href="foo" target="_blank">tag with unsafe attributes</a:link></I18N>': 'function() { return <span><a href="bar" target="_blank">tag gyda phriodoleddau anniogel</a></span>; }',
|
32 | '<I18N><a href="foo" target="_blank" i18n-id="link">tag with unsafe attributes</a></I18N>': 'function() { return <span><a href="bar" target="_blank">tag gyda phriodoleddau anniogel</a></span>; }',
|
33 | '<I18N><SelfClosing i18n-id="foo" attr="attr" /></I18N>': 'function(SelfClosing) { return <span>Translated: <SelfClosing attr="attr" /></span>; }',
|
34 | '<I18N><SelfClosing {...foo}/></I18N>': 'function(SelfClosing, foo) { return <span>Translated: <SelfClosing {...foo} /></span>; }',
|
35 | '<I18N><Member.Name /></I18N>': 'function(Member) { return <span>Translated: <Member.Name /></span>; }',
|
36 | '<I18N>Cat: {nested}</I18N>': "function(nested) { return <span>Cat : {nested}</span>; }",
|
37 | '<I18N>And now {a.member.expression}</I18N>': 'function(a) { return <span>Ac yn awr {a.member.expression}</span>; }',
|
38 | '<I18N>Check out: <Component gnar={3 * shnar}/></I18N>': 'function(Component, shnar) { return <span><Component gnar={3 * shnar} /> "checked" out!</span>; }',
|
39 | '<I18N><Re /><Ordering /></I18N>': 'function(Re, Ordering) { return <span><Ordering /><Re /></span>; }',
|
40 | '<I18N><Pluralize:items on={this.state.count}><Match when="=0">You have no items in your cart</Match><Match when="one">You have one item in your cart</Match><Match when="other">You have {this.state.count} items in your cart</Match></Pluralize:items></I18N>':
|
41 | 'function(Pluralize, Match) { return <span><Pluralize on={this.state.count}><Match when="=0">No tiene nada in su carrito</Match><Match when="one">Tiene ún articulo en su carrito</Match><Match when="other">Tiene {this.state.count} articulos en su carrito</Match></Pluralize></span>; }'
|
42 | };
|
43 |
|
44 | Object.keys(expectedResultsForTranslationBundles).forEach(original => {
|
45 | const expected = expectedResultsForTranslationBundles[original];
|
46 | const bundle = translateMessagesToBundle(original, translations, {inputFormat: 'js'}).bundle;
|
47 | expect(bundle[Object.keys(bundle)[0]]).to.equal(expected);
|
48 | });
|
49 | });
|
50 |
|
51 | it('warns on invalid translations', function() {
|
52 | const originalSource = `
|
53 | function render () {
|
54 | return <p>
|
55 | <I18N>Hello, world. <Component />{foo}{bar.baz}</I18N>
|
56 | </p>
|
57 | }
|
58 | `;
|
59 |
|
60 |
|
61 | const invalidTranslations = [
|
62 | '<a target="_blank">Unsafe attribute</a> <Component />{foo}{bar.baz}',
|
63 | '<a:made-up-id></a:made-up-id><Component />{foo}{bar.baz}',
|
64 | '{random + expression + in + placeholder}<Component />{foo}{bar.baz}',
|
65 | '{non.existant.name}<Component />{foo}{bar.baz}',
|
66 | '<Component /> Duplicated expressions: {foo}{foo}{bar.baz}',
|
67 | 'Missing component.',
|
68 | 'Duplicated component. <Component /> <Component />',
|
69 | ];
|
70 | var correctTranslation = 'Helo, byd. <Component />{foo}{bar.baz}';
|
71 |
|
72 | var extraction = extract(originalSource)[0];
|
73 |
|
74 | function translateMessage(translation) {
|
75 | translateMessagesToBundle(originalSource, {[extraction]: translation}, {inputFormat: 'js'});
|
76 | }
|
77 |
|
78 | expect(() => translateMessage(correctTranslation)).to.not.throw();
|
79 |
|
80 | invalidTranslations.forEach(translation => {
|
81 | expect(() => translateMessage(translation)).to.throw();
|
82 | });
|
83 | });
|
84 | });
|