Commit 9cfb253e authored by Paul Slaughter's avatar Paul Slaughter

Add grammar util

This contains the function `toNounSeriesText` which can be used to build
i18n noun series fragments (i.e. "A, B, and C").
parent 11f9edec
import { sprintf, s__ } from '~/locale';
/**
* Combines each given item into a noun series sentence fragment. It does this
* in a way that supports i18n by giving context and punctuation to the locale
* functions.
*
* **Examples:**
*
* - `["A", "B"] => "A and B"`
* - `["A", "B", "C"] => "A, B, and C"`
*
* **Why only nouns?**
*
* Some languages need a bit more context to translate other series.
*
* @param {String[]} items
*/
export const toNounSeriesText = items => {
if (items.length === 0) {
return '';
} else if (items.length === 1) {
return items[0];
} else if (items.length === 2) {
return sprintf(s__('nounSeries|%{firstItem} and %{lastItem}'), {
firstItem: items[0],
lastItem: items[1],
});
}
return items.reduce((item, nextItem, idx) =>
idx === items.length - 1
? sprintf(s__('nounSeries|%{item}, and %{lastItem}'), { item, lastItem: nextItem })
: sprintf(s__('nounSeries|%{item}, %{nextItem}'), { item, nextItem }),
);
};
export default {
toNounSeriesText,
};
...@@ -8706,6 +8706,15 @@ msgstr "" ...@@ -8706,6 +8706,15 @@ msgstr ""
msgid "notification emails" msgid "notification emails"
msgstr "" msgstr ""
msgid "nounSeries|%{firstItem} and %{lastItem}"
msgstr ""
msgid "nounSeries|%{item}, %{nextItem}"
msgstr ""
msgid "nounSeries|%{item}, and %{lastItem}"
msgstr ""
msgid "or" msgid "or"
msgstr "" msgstr ""
......
import * as grammar from '~/lib/utils/grammar';
describe('utils/grammar', () => {
describe('toNounSeriesText', () => {
it('with empty items returns empty string', () => {
expect(grammar.toNounSeriesText([])).toBe('');
});
it('with single item returns item', () => {
const items = ['Lorem Ipsum'];
expect(grammar.toNounSeriesText(items)).toBe(items[0]);
});
it('with 2 items returns item1 and item2', () => {
const items = ['Dolar', 'Sit Amit'];
expect(grammar.toNounSeriesText(items)).toBe(`${items[0]} and ${items[1]}`);
});
it('with 3 items returns comma separated series', () => {
const items = ['Lorem', 'Ipsum', 'dolar'];
const expected = 'Lorem, Ipsum, and dolar';
expect(grammar.toNounSeriesText(items)).toBe(expected);
});
it('with 6 items returns comma separated series', () => {
const items = ['Lorem', 'ipsum', 'dolar', 'sit', 'amit', 'consectetur'];
const expected = 'Lorem, ipsum, dolar, sit, amit, and consectetur';
expect(grammar.toNounSeriesText(items)).toBe(expected);
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment