Skip to content

Commit

Permalink
feat: Add list getSeparator utility (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
eKoopmans authored Jul 5, 2022
1 parent f25e109 commit c3fd227
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 15 deletions.
42 changes: 28 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ npm install @brightspace-ui/intl
Then `import` only the functionality you need:

```javascript
import {formatDate, formatTime} from '@brightspace-ui/intl/lib/dateTime.js';
import {formatNumber, formatPercent} from '@brightspace-ui/intl/lib/number.js';
import { formatDate, formatTime } from '@brightspace-ui/intl/lib/dateTime.js';
import { formatNumber, formatPercent } from '@brightspace-ui/intl/lib/number.js';
```

All of the APIs will automatically detect the document's language via the `lang` attribute on the `<html>` element. They'll also look for various `data-` attributes that will be present in Brightspace pages to access override and timezone information.
Expand All @@ -33,7 +33,7 @@ All of the APIs will automatically detect the document's language via the `lang`
Integer and decimal numbers can be formatted in the user's locale using `formatNumber`. Percentages can be formatted using `formatPercent`. Use the optional `options` parameter for rounding.

```javascript
import {formatNumber, formatPercent} from '@brightspace-ui/intl/lib/number.js';
import { formatNumber, formatPercent } from '@brightspace-ui/intl/lib/number.js';

const number = formatNumber(8902.72, [options]); // -> '8,902.72' in en-US
const percent = formatPercent(0.333, [options]); // -> '33.3 %' in en-US
Expand All @@ -47,7 +47,7 @@ Options:
Formatting as an integer (rounded to 0 decimal places):

```javascript
import {formatNumber} from '@brightspace-ui/intl/lib/number.js';
import { formatNumber } from '@brightspace-ui/intl/lib/number.js';

const value = formatNumber(89.72, {
maximumFractionDigits: 0
Expand All @@ -57,7 +57,7 @@ const value = formatNumber(89.72, {
Formatting as a percentage (rounded to 2 decimal places, but always showing at least 2 decimals):

```javascript
import {formatPercent} from '@brightspace-ui/intl/lib/number.js';
import { formatPercent } from '@brightspace-ui/intl/lib/number.js';

const value = formatPercent(0.333, {
minimumFractionDigits: 2,
Expand All @@ -70,7 +70,7 @@ const value = formatPercent(0.333, {
The `parseNumber` method can be used to parse an integer or decimal number written in the user's locale.

```javascript
import {parseNumber} from '@brightspace-ui/intl/lib/number.js';
import { parseNumber } from '@brightspace-ui/intl/lib/number.js';

const value = parseNumber('-8 942,39'); // -> -8942.39 in fr-CA
```
Expand All @@ -84,7 +84,7 @@ Timestamps (milliseconds since the epoch) can be formatted in the user's locale
Combined dates and times are formatted using `formatDateTime`:

```javascript
import {formatDateTime} from '@brightspace-ui/intl/lib/dateTime.js';
import { formatDateTime } from '@brightspace-ui/intl/lib/dateTime.js';

const date = formatDateTime(
new Date(2015, 8, 23, 14, 5),
Expand Down Expand Up @@ -137,7 +137,7 @@ configured time zone, then returns the results of passing this date to `formatTi
To format a **date only** (without the time portion), use `formatDate`:

```javascript
import {formatDate} from '@brightspace-ui/intl/lib/dateTime.js';
import { formatDate } from '@brightspace-ui/intl/lib/dateTime.js';

const value = formatDate(
new Date(2015, 8, 23),
Expand All @@ -161,7 +161,7 @@ Options:
To format a **time only** (without the date portion), use `formatTime`:

```javascript
import {formatTime} from '@brightspace-ui/intl/lib/dateTime.js';
import { formatTime } from '@brightspace-ui/intl/lib/dateTime.js';

const time = formatTime(
new Date(2015, 8, 23, 14, 5)
Expand All @@ -178,7 +178,7 @@ Options:
To parse a date written in the user's locale, use `parseDate`:

```javascript
import {parseDate} from '@brightspace-ui/intl/lib/dateTime.js';
import { parseDate } from '@brightspace-ui/intl/lib/dateTime.js';

const date = parseDate('2015-09-23'); // in fr-CA
date.getFullYear(); // -> 2015
Expand All @@ -191,7 +191,7 @@ date.getDate(); // -> 23
To parse a time written in the user's locale, use `parseTime`:

```javascript
import {parseTime} from '@brightspace-ui/intl/lib/dateTime.js';
import { parseTime } from '@brightspace-ui/intl/lib/dateTime.js';

const date = parseTime('14 h 05'); // in fr-CA
date.getHours(); // -> 14
Expand All @@ -202,7 +202,7 @@ date.getMinutes(); // -> 5

To convert an object containing a UTC date to an object containing a local date corresponding to the `data-timezone` attribute:
```javascript
import {convertUTCToLocalDateTime} from '@brightspace-ui/intl/lib/dateTime.js';
import { convertUTCToLocalDateTime } from '@brightspace-ui/intl/lib/dateTime.js';

const UTCDateTime = {
month: 12,
Expand All @@ -219,7 +219,7 @@ const localDateTime = convertUTCToLocalDateTime(

To convert an object containing a local date corresponding to the `data-timezone` attribute to an object containing a UTC date:
```javascript
import {convertLocalToUTCDateTime} from '@brightspace-ui/intl/lib/dateTime.js';
import { convertLocalToUTCDateTime } from '@brightspace-ui/intl/lib/dateTime.js';

const localDateTime = {
month: 12,
Expand All @@ -239,11 +239,25 @@ const UTCDateTime = convertLocalToUTCDateTime(
Use `formatFileSize` to format a file size appropriately for the user's locale.

```javascript
import {formatFileSize} from '@brightspace-ui/intl/lib/fileSize.js';
import { formatFileSize } from '@brightspace-ui/intl/lib/fileSize.js';

const fileSize = formatFileSize(100); // -> '100 bytes' in en-US
```

## List Formatting

Use `getSeparator` to get the appropriate list separator for the current locale. This is a separator that would be used in spoken language; note that the separator includes a space, for locales where it is appropriate.

```javascript
import { getSeparator } from '@brightspace-ui/intl/lib/list.js';

const separator = getSeparator(); // -> ', ' in en-US
const separator = getSeparator({ nonBreaking: true }); // -> ',\xa0' in en-US
```

Options:
- **nonBreaking**: a Boolean flag, whether to use non-breaking spaces instead of standard spaces; default is `false`

## Contributing

Contributions are welcome, please submit a pull request!
Expand Down
22 changes: 22 additions & 0 deletions lib/list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { getLanguage } from './common.js';

const nbsp = '\xa0';

/**
* Returns a region-specific list separator for the current language.
* @param { Boolean } nonBreaking Whether to replace spaces with non-breaking spaces.
*/
export function getSeparator({ nonBreaking } = {}) {
const langTag = getLanguage();
const baseLanguage = langTag.split('-')[0];
const space = nonBreaking ? nbsp : ' ';

// In this function, most languages return the separator used by the Intl.ListFormat() API with options:
// { style: 'short', type: 'conjunction' }
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat
// Arabic, due to some inconsistencies, returns the separator used by Google Translate.

if (baseLanguage === 'ar') return `${space}،${space}`;
if (['ja', 'zh'].includes(baseLanguage)) return '、';
return `,${space}`;
}
3 changes: 2 additions & 1 deletion test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
<div id="mocha"></div>
<script src="../node_modules/chai/chai.js"></script>
<script src="../node_modules/mocha/mocha.js"></script>
<script>mocha.setup('bdd')</script>
<script>mocha.setup('bdd');</script>
<script type="module" src="common.js"></script>
<script type="module" src="dateTime.js"></script>
<script type="module" src="fileSize.js"></script>
<script type="module" src="number.js"></script>
<script type="module" src="list.js"></script>
<script type="module">
mocha.checkLeaks();
mocha.run();
Expand Down
56 changes: 56 additions & 0 deletions test/list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { getDocumentLocaleSettings } from '../lib/common.js';
import { getSeparator } from '../lib/list.js';

const expect = chai.expect;

describe('getSeparator', () => {

const documentLocaleSettings = getDocumentLocaleSettings();

afterEach(() => documentLocaleSettings.reset());

[
{ locale: 'ar', expect: [' ، ', '\xa0،\xa0'] },
{ locale: 'ar-SA', expect: [' ، ', '\xa0،\xa0'] },
{ locale: 'cy-GB', expect: [', ', ',\xa0'] },
{ locale: 'da', expect: [', ', ',\xa0'] },
{ locale: 'da-DK', expect: [', ', ',\xa0'] },
{ locale: 'de', expect: [', ', ',\xa0'] },
{ locale: 'de-DE', expect: [', ', ',\xa0'] },
{ locale: 'en', expect: [', ', ',\xa0'] },
{ locale: 'en-CA', expect: [', ', ',\xa0'] },
{ locale: 'en-GB', expect: [', ', ',\xa0'] },
{ locale: 'en-US', expect: [', ', ',\xa0'] },
{ locale: 'es', expect: [', ', ',\xa0'] },
{ locale: 'es-ES', expect: [', ', ',\xa0'] },
{ locale: 'es-MX', expect: [', ', ',\xa0'] },
{ locale: 'fr', expect: [', ', ',\xa0'] },
{ locale: 'fr-CA', expect: [', ', ',\xa0'] },
{ locale: 'fr-FR', expect: [', ', ',\xa0'] },
{ locale: 'fr-ON', expect: [', ', ',\xa0'] },
{ locale: 'hi', expect: [', ', ',\xa0'] },
{ locale: 'hi-IN', expect: [', ', ',\xa0'] },
{ locale: 'ja', expect: ['、', '、'] },
{ locale: 'ja-JP', expect: ['、', '、'] },
{ locale: 'ko', expect: [', ', ',\xa0'] },
{ locale: 'ko-KR', expect: [', ', ',\xa0'] },
{ locale: 'nl', expect: [', ', ',\xa0'] },
{ locale: 'nl-NL', expect: [', ', ',\xa0'] },
{ locale: 'pt', expect: [', ', ',\xa0'] },
{ locale: 'pt-BR', expect: [', ', ',\xa0'] },
{ locale: 'sv', expect: [', ', ',\xa0'] },
{ locale: 'sv-SE', expect: [', ', ',\xa0'] },
{ locale: 'tr', expect: [', ', ',\xa0'] },
{ locale: 'tr-TR', expect: [', ', ',\xa0'] },
{ locale: 'zh', expect: ['、', '、'] },
{ locale: 'zh-CN', expect: ['、', '、'] },
{ locale: 'zh-TW', expect: ['、', '、'] },
].forEach((input) => {
it(`should return the separator for locale "${input.locale}"`, () => {
documentLocaleSettings.language = input.locale;
expect(getSeparator()).to.equal(input.expect[0]);
expect(getSeparator({ nonBreaking: true })).to.equal(input.expect[1]);
});
});

});

0 comments on commit c3fd227

Please sign in to comment.