Skip to content

Commit fcfcb96

Browse files
committed
test: List with grammatical inflections on each item (unicode-org/message-format-wg#165)
1 parent 514bac8 commit fcfcb96

File tree

1 file changed

+89
-29
lines changed

1 file changed

+89
-29
lines changed

packages/messageformat/src/mf2-features.test.ts

Lines changed: 89 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -328,43 +328,103 @@ describe('Multi-selector messages (unicode-org/message-format-wg#119)', () => {
328328
});
329329
});
330330

331-
const maybe = process.version > 'v12' ? test : test.skip;
332-
maybe('List formatter (unicode-org/message-format-wg#36)', () => {
333-
function LIST(
334-
locales: string[],
335-
options: FunctionOptions,
336-
...args: (string | string[])[]
337-
) {
338-
let list: string[] = [];
339-
for (const arg of args) list = list.concat(arg);
340-
// @ts-ignore
341-
const lf = new Intl.ListFormat(locales, options);
342-
return lf.format(list);
343-
}
344-
const runtime: Runtime = {
345-
select: fluentRuntime.select,
346-
format: Object.assign({ LIST }, fluentRuntime.format)
347-
};
331+
const maybe = process.version > 'v14' ? describe : describe.skip;
332+
maybe('List formatting', () => {
333+
test('Intl.ListFormat, combine/flatten inputs (unicode-org/message-format-wg#36)', () => {
334+
function LIST(
335+
locales: string[],
336+
options: FunctionOptions | undefined,
337+
...args: (string | string[])[]
338+
) {
339+
let list: string[] = [];
340+
for (const arg of args) list = list.concat(arg);
341+
// @ts-ignore
342+
const lf = new Intl.ListFormat(locales, options);
343+
return lf.format(list);
344+
}
345+
const runtime: Runtime = {
346+
select: fluentRuntime.select,
347+
format: Object.assign({ LIST }, fluentRuntime.format)
348+
};
348349

349-
const src = source`
350+
const src = source`
350351
plain = { LIST($list) }
351352
and = { LIST($list, style: "short", type: "conjunction") }
352353
or = { LIST($list, style: "long", type: "disjunction") }
353354
or-other = { LIST($list, "another vehicle", type: "disjunction") }
354355
`;
355-
const res = compileFluent(src, { id: 'res', locale: 'en' });
356-
const mf = new MessageFormat('en', runtime, res);
357-
const list = ['Motorcycle', 'Bus', 'Car'];
356+
const res = compileFluent(src, { id: 'res', locale: 'en' });
357+
const mf = new MessageFormat('en', runtime, res);
358+
const list = ['Motorcycle', 'Bus', 'Car'];
359+
360+
const plainMsg = mf.format('res', ['plain'], { list });
361+
expect(plainMsg).toBe('Motorcycle, Bus, and Car');
362+
363+
const andMsg = mf.format('res', ['and'], { list });
364+
expect(andMsg).toBe('Motorcycle, Bus, & Car');
358365

359-
const plainMsg = mf.format('res', ['plain'], { list });
360-
expect(plainMsg).toBe('Motorcycle, Bus, and Car');
366+
const orMsg = mf.format('res', ['or'], { list });
367+
expect(orMsg).toBe('Motorcycle, Bus, or Car');
361368

362-
const andMsg = mf.format('res', ['and'], { list });
363-
expect(andMsg).toBe('Motorcycle, Bus, & Car');
369+
const otherMsg = mf.format('res', ['or-other'], { list });
370+
expect(otherMsg).toBe('Motorcycle, Bus, Car, or another vehicle');
371+
});
364372

365-
const orMsg = mf.format('res', ['or'], { list });
366-
expect(orMsg).toBe('Motorcycle, Bus, or Car');
373+
test('List formatting with grammatical inflection on each list item (unicode-org/message-format-wg#3)', () => {
374+
const runtime: Runtime = {
375+
select: fluentRuntime.select,
376+
format: Object.assign({ dative, LIST }, fluentRuntime.format)
377+
};
367378

368-
const otherMsg = mf.format('res', ['or-other'], { list });
369-
expect(otherMsg).toBe('Motorcycle, Bus, Car, or another vehicle');
379+
function dative(locales: string[], _options: unknown, arg: string) {
380+
if (locales[0] !== 'ro') throw new Error('Only Romanian supported');
381+
const data: Record<string, string> = {
382+
Maria: 'Mariei',
383+
Ileana: 'Ilenei',
384+
Petre: 'lui Petre'
385+
};
386+
return data[arg] || arg;
387+
}
388+
389+
function LIST(
390+
locales: string[],
391+
options: FunctionOptions | undefined,
392+
...args: (string | string[])[]
393+
) {
394+
let list: string[] = [];
395+
for (const arg of args) list = list.concat(arg);
396+
if (typeof options?.each === 'string') {
397+
const fn = runtime.format[options.each];
398+
if (typeof fn !== 'function')
399+
throw new Error(`list each function not found: ${options.each}`);
400+
list = list.map(li => fn(locales, undefined, li));
401+
}
402+
// @ts-ignore
403+
const lf = new Intl.ListFormat(locales, options);
404+
return lf.format(list);
405+
}
406+
407+
const src = source`
408+
msg = { $count ->
409+
[one] I-am dat cadouri { LIST($list, each: "dative") }.
410+
*[other] Le-am dat cadouri { LIST($list, each: "dative") }.
411+
}
412+
`;
413+
const res = compileFluent(src, { id: 'res', locale: 'ro' });
414+
const mf = new MessageFormat('ro', runtime, res);
415+
416+
const list1 = ['Petre'];
417+
const msg1 = mf.format('res', ['msg'], {
418+
count: list1.length,
419+
list: list1
420+
});
421+
expect(msg1).toBe('I-am dat cadouri lui Petre.');
422+
423+
const list3 = ['Maria', 'Ileana', 'Petre'];
424+
const msg3 = mf.format('res', ['msg'], {
425+
count: list3.length,
426+
list: list3
427+
});
428+
expect(msg3).toBe('Le-am dat cadouri Mariei, Ilenei și lui Petre.');
429+
});
370430
});

0 commit comments

Comments
 (0)