Skip to content

Commit

Permalink
fix(@formatjs/intl-displaynames): fix script canonicalization, fix #2622
Browse files Browse the repository at this point in the history
  • Loading branch information
longlho committed Feb 22, 2021
1 parent a32c53c commit be07282
Show file tree
Hide file tree
Showing 16 changed files with 103 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function isUnicodeScriptSubtag(script: string): boolean {
export function CanonicalCodeForDisplayNames(
type: 'language' | 'region' | 'script' | 'currency',
code: string
) {
): string {
if (type === 'language') {
return CanonicalizeLocaleList([code])[0];
}
Expand All @@ -29,7 +29,7 @@ export function CanonicalCodeForDisplayNames(
if (!isUnicodeScriptSubtag(code)) {
throw RangeError('invalid script');
}
return `${code[0].toUpperCase()}${code.slice(1)}`;
return `${code[0].toUpperCase()}${code.slice(1).toLowerCase()}`;
}
invariant(type === 'currency', 'invalid type');
if (!IsWellFormedCurrencyCode(code)) {
Expand Down
45 changes: 14 additions & 31 deletions packages/intl-displaynames/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ToString,
CanonicalizeLocaleList,
ToObject,
CanonicalCodeForDisplayNames,
} from '@formatjs/ecma402-abstract';

export interface DisplayNamesOptions {
Expand Down Expand Up @@ -116,15 +117,15 @@ export class DisplayNames {
static supportedLocalesOf(
locales?: string | string[],
options?: Pick<DisplayNamesOptions, 'localeMatcher'>
) {
): string[] {
return SupportedLocales(
DisplayNames.availableLocales,
CanonicalizeLocaleList(locales),
options
);
}

static __addLocaleData(...data: DisplayNamesLocaleData[]) {
static __addLocaleData(...data: DisplayNamesLocaleData[]): void {
for (const {data: d, locale} of data) {
const minimizedLocale = new (Intl as any).Locale(locale)
.minimize()
Expand All @@ -140,7 +141,7 @@ export class DisplayNames {
}
}

of(code: string | number | object): string | undefined {
of(code: string | number | Record<string, unknown>): string | undefined {
checkReceiver(this, 'of');
const type = getSlot(this, 'type');
const codeAsString = ToString(code);
Expand All @@ -156,38 +157,20 @@ export class DisplayNames {
);

// Canonicalize the case.
let canonicalCode: string;
let canonicalCode = CanonicalCodeForDisplayNames(type, codeAsString);

// This is only used to store extracted language region.
let regionSubTag: string | undefined;
switch (type) {
// Normalize the locale id and remove the region.
case 'language': {
canonicalCode = CanonicalizeLocaleList(codeAsString)[0];
const regionMatch = /-([a-z]{2}|\d{3})\b/i.exec(canonicalCode);
if (regionMatch) {
// Remove region subtag
canonicalCode =
canonicalCode.substring(0, regionMatch.index) +
canonicalCode.substring(regionMatch.index + regionMatch[0].length);
regionSubTag = regionMatch[1];
}
break;
}
// currency code should be all upper-case.
case 'currency':
canonicalCode = codeAsString.toUpperCase();
break;
// script code should be title case
case 'script':
if (type === 'language') {
const regionMatch = /-([a-z]{2}|\d{3})\b/i.exec(canonicalCode);
if (regionMatch) {
// Remove region subtag
canonicalCode =
codeAsString[0] + codeAsString.substring(1).toLowerCase();
break;
// region shold be all upper-case
case 'region':
canonicalCode = codeAsString.toUpperCase();
break;
canonicalCode.substring(0, regionMatch.index) +
canonicalCode.substring(regionMatch.index + regionMatch[0].length);
regionSubTag = regionMatch[1];
}
}

const typesData = localeData.types[type];
// If the style of choice does not exist, fallback to "long".
const name =
Expand Down
8 changes: 7 additions & 1 deletion packages/intl-displaynames/tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import '@formatjs/intl-getcanonicallocales/polyfill';
import '@formatjs/intl-locale/polyfill';
import {DisplayNames} from '../';
import {DisplayNames} from '..';

import * as en from './locale-data/en.json';
import * as zh from './locale-data/zh.json';
Expand All @@ -28,6 +28,12 @@ describe('.of()', () => {
).toBe('简体中文(XY)');
});

it('find script correctly', function () {
expect(
new DisplayNames('zh', {type: 'script', fallback: 'code'}).of('arab')
).toBe('阿拉伯文');
});

describe('with fallback set to "none"', () => {
it('returns undefined when called with language code that has unrecognized region subtag', () => {
expect(
Expand Down
2 changes: 1 addition & 1 deletion packages/react-intl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const FormattedList: React.FC<
> = createFormattedComponent('formatList');
export const FormattedDisplayName: React.FC<
DisplayNamesOptions & {
value: string | number | object;
value: string | number | Record<string, unknown>;
}
> = createFormattedComponent('formatDisplayName');
export const FormattedDateParts: React.FC<
Expand Down
2 changes: 1 addition & 1 deletion website/docs/intl.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ type FormatDisplayNameOptions = {
}
function formatDisplayName(
value: string | number | object,
value: string | number | Record<string, unknown>,
options: FormatDisplayNameOptions
): string | undefined
```
Expand Down
4 changes: 4 additions & 0 deletions website/docs/polyfills.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ Our current list of polyfills includes:
- [Intl.DateTimeFormat](polyfills/intl-datetimeformat.md) (ES2020)

![Polyfill Hierarchy](/img/polyfills.svg)

# polyfill.io Integration

For basic use cases, we recommend using [polyfill.io](https://polyfill.io/) or [polyfill-library](https://github.com/Financial-Times/polyfill-library) to generate polyfill bundle since it automatically resolves the dependencies above for you.
9 changes: 9 additions & 0 deletions website/docs/polyfills/intl-datetimeformat.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ This package requires the following capabilities:

## Usage

### Via polyfill.io

You can use [polyfill.io URL Builder](https://polyfill.io/v3/url-builder/) to create a polyfill script tag for `Intl.DateTimeFormat`. By default the created URL does not come with any locale data. In order to add locale data, append `Intl.DateTimeFormat.~locale.<locale>` to your list of features. For example:

```html
<!-- Polyfill Intl.DateTimeFormat, its dependencies & `en` locale data -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=Intl.DateTimeFormat,Intl.DateTimeFormat.~locale.en"></script>
```

### Simple

```tsx
Expand Down
9 changes: 9 additions & 0 deletions website/docs/polyfills/intl-displaynames.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ Everything in <https://github.com/tc39/proposal-intl-displaynames>.

## Usage

### Via polyfill.io

You can use [polyfill.io URL Builder](https://polyfill.io/v3/url-builder/) to create a polyfill script tag for `Intl.DisplayNames`. By default the created URL does not come with any locale data. In order to add locale data, append `Intl.DisplayNames.~locale.<locale>` to your list of features. For example:

```html
<!-- Polyfill Intl.DisplayNames, its dependencies & `en` locale data -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=Intl.DisplayNames,Intl.DisplayNames.~locale.en"></script>
```

### Simple

```tsx
Expand Down
9 changes: 9 additions & 0 deletions website/docs/polyfills/intl-getcanonicallocales.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ yarn add @formatjs/intl-getcanonicallocales

## Usage

### Via polyfill.io

You can use [polyfill.io URL Builder](https://polyfill.io/v3/url-builder/) to create a polyfill script tag for `Intl.GetCanonicalLocales`. For example:

```html
<!-- Polyfill Intl.GetCanonicalLocales & its dependencies -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=Intl.GetCanonicalLocales"></script>
```

### Simple

```tsx
Expand Down
9 changes: 9 additions & 0 deletions website/docs/polyfills/intl-listformat.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ yarn add @formatjs/intl-listformat

## Usage

### Via polyfill.io

You can use [polyfill.io URL Builder](https://polyfill.io/v3/url-builder/) to create a polyfill script tag for `Intl.ListFormat`. By default the created URL does not come with any locale data. In order to add locale data, append `Intl.ListFormat.~locale.<locale>` to your list of features. For example:

```html
<!-- Polyfill Intl.ListFormat, its dependencies & `en` locale data -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=Intl.ListFormat,Intl.ListFormat.~locale.en"></script>
```

### Simple

```tsx
Expand Down
9 changes: 9 additions & 0 deletions website/docs/polyfills/intl-locale.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ yarn add @formatjs/intl-locale

## Usage

### Via polyfill.io

You can use [polyfill.io URL Builder](https://polyfill.io/v3/url-builder/) to create a polyfill script tag for `Intl.Locale`. For example:

```html
<!-- Polyfill Intl.Locale & its dependencies -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=Intl.Locale"></script>
```

### Simple

```tsx
Expand Down
9 changes: 9 additions & 0 deletions website/docs/polyfills/intl-numberformat.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ Everything in the ES2020 Internationalization API spec (https://tc39.es/ecma402)

## Usage

### Via polyfill.io

You can use [polyfill.io URL Builder](https://polyfill.io/v3/url-builder/) to create a polyfill script tag for `Intl.NumberFormat`. By default the created URL does not come with any locale data. In order to add locale data, append `Intl.NumberFormat.~locale.<locale>` to your list of features. For example:

```html
<!-- Polyfill Intl.NumberFormat, its dependencies & `en` locale data -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=Intl.NumberFormat,Intl.NumberFormat.~locale.en"></script>
```

### Simple

```tsx
Expand Down
9 changes: 9 additions & 0 deletions website/docs/polyfills/intl-pluralrules.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ yarn add @formatjs/intl-pluralrules

## Usage

### Via polyfill.io

You can use [polyfill.io URL Builder](https://polyfill.io/v3/url-builder/) to create a polyfill script tag for `Intl.PluralRules`. By default the created URL does not come with any locale data. In order to add locale data, append `Intl.PluralRules.~locale.<locale>` to your list of features. For example:

```html
<!-- Polyfill Intl.PluralRules, its dependencies & `en` locale data -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=Intl.PluralRules,Intl.PluralRules.~locale.en"></script>
```

### Simple

```tsx
Expand Down
9 changes: 9 additions & 0 deletions website/docs/polyfills/intl-relativetimeformat.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ This package requires the following capabilities:

## Usage

### Via polyfill.io

You can use [polyfill.io URL Builder](https://polyfill.io/v3/url-builder/) to create a polyfill script tag for `Intl.RelativeTimeFormat`. By default the created URL does not come with any locale data. In order to add locale data, append `Intl.RelativeTimeFormat.~locale.<locale>` to your list of features. For example:

```html
<!-- Polyfill Intl.RelativeTimeFormat, its dependencies & `en` locale data -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=Intl.RelativeTimeFormat,Intl.RelativeTimeFormat.~locale.en"></script>
```

### Simple

```tsx
Expand Down
2 changes: 1 addition & 1 deletion website/docs/react-intl/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ type FormatDisplayNameOptions = {
}
function formatDisplayName(
value: string | number | object,
value: string | number | Record<string, unknown>,
options?: FormatDisplayNameOptions
): string | undefined
```
Expand Down
2 changes: 1 addition & 1 deletion website/docs/react-intl/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ has `props` that correspond to `DisplayNameOptions`. You might need a [polyfill]
```ts
props: FormatDisplayNameOptions &
{
value: string | number | object,
value: string | number | Record<string, unknown>,
}
```

Expand Down

0 comments on commit be07282

Please sign in to comment.