Skip to content

Commit ec40f5f

Browse files
authored
Create @internationalized scope (#1563)
* Move NumberParser and NumberFormatter into @spectrum-i18n scope * Move message formatter into @spectrum-i18n/message-formatter * Move channel name localizations and value formatting to @react-stately/color Supports different formatting depending on the channel, and adds default aria-label for color slider and color wheel based on channel name * Polyfill degree unit formatting for Safari https://bugs.webkit.org/show_bug.cgi?id=218139 * lint * Rename @spectrum-i18n/message-formatter to just @spectrum-i18n/message * Rename scope to @internationalized * Fix lint
1 parent 93fa74f commit ec40f5f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+888
-570
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ publish-nightly: build
8383
yarn publish:nightly
8484

8585
build:
86-
parcel build packages/@react-{spectrum,aria,stately}/*/ --no-minify
86+
parcel build packages/@react-{spectrum,aria,stately}/*/ packages/@internationalized/*/ --no-minify
8787

8888
website:
8989
yarn build:docs --public-url /reactspectrum/$$(git rev-parse HEAD)/docs --dist-dir dist/$$(git rev-parse HEAD)/docs
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# @internationalized/message
2+
3+
This package is part of [react-spectrum](https://github.com/adobe/react-spectrum). See the repo for more details.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "@internationalized/message",
3+
"version": "3.0.0-alpha.1",
4+
"private": true,
5+
"description": "Internationalized message formatting and locale negotiation",
6+
"license": "Apache-2.0",
7+
"main": "dist/main.js",
8+
"module": "dist/module.js",
9+
"types": "dist/types.d.ts",
10+
"source": "src/index.ts",
11+
"files": [
12+
"dist",
13+
"src"
14+
],
15+
"sideEffects": false,
16+
"repository": {
17+
"type": "git",
18+
"url": "https://github.com/adobe/react-spectrum"
19+
},
20+
"dependencies": {
21+
"@babel/runtime": "^7.6.2",
22+
"intl-messageformat": "^2.2.0"
23+
},
24+
"publishConfig": {
25+
"access": "public"
26+
}
27+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2020 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
export type LocalizedStrings = {
14+
[lang: string]: {
15+
[key: string]: string
16+
}
17+
};
18+
19+
/**
20+
* Stores a mapping of localized strings. Can be used to find the
21+
* closest available string for a given locale.
22+
*/
23+
export class MessageDictionary {
24+
private messages: LocalizedStrings;
25+
private defaultLocale: string;
26+
27+
constructor(messages: LocalizedStrings, defaultLocale: string = 'en-US') {
28+
// Clone messages so we don't modify the original object.
29+
this.messages = {...messages};
30+
this.defaultLocale = defaultLocale;
31+
}
32+
33+
getStringForLocale(key: string, locale: string) {
34+
let strings = this.messages[locale];
35+
if (!strings) {
36+
strings = getStringsForLocale(locale, this.messages, this.defaultLocale);
37+
this.messages[locale] = strings;
38+
}
39+
40+
let string = strings[key];
41+
if (!string) {
42+
throw new Error(`Could not find intl message ${key} in ${locale} locale`);
43+
}
44+
45+
return string;
46+
}
47+
}
48+
49+
function getStringsForLocale(locale: string, strings: LocalizedStrings, defaultLocale = 'en-US') {
50+
// If there is an exact match, use it.
51+
if (strings[locale]) {
52+
return strings[locale];
53+
}
54+
55+
// Attempt to find the closest match by language.
56+
// For example, if the locale is fr-CA (French Canadian), but there is only
57+
// an fr-FR (France) set of strings, use that.
58+
// This could be replaced with Intl.LocaleMatcher once it is supported.
59+
// https://github.com/tc39/proposal-intl-localematcher
60+
let language = getLanguage(locale);
61+
for (let key in strings) {
62+
if (key.startsWith(language + '-')) {
63+
return strings[key];
64+
}
65+
}
66+
67+
// Nothing close, use english.
68+
return strings[defaultLocale];
69+
}
70+
71+
function getLanguage(locale: string) {
72+
// @ts-ignore
73+
if (Intl.Locale) {
74+
// @ts-ignore
75+
return new Intl.Locale(locale).language;
76+
}
77+
78+
return locale.split('-')[0];
79+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2020 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
import IntlMessageFormat from 'intl-messageformat';
14+
import {MessageDictionary} from './MessageDictionary';
15+
16+
/**
17+
* Formats ICU Message strings to create localized strings from a MessageDictionary.
18+
*/
19+
export class MessageFormatter {
20+
private locale: string;
21+
private messages: MessageDictionary;
22+
private cache: {[key: string]: IntlMessageFormat};
23+
24+
constructor(locale: string, messages: MessageDictionary) {
25+
this.locale = locale;
26+
this.messages = messages;
27+
this.cache = {};
28+
}
29+
30+
format(key: string, variables: object) {
31+
let message = this.cache[key];
32+
if (!message) {
33+
let msg = this.messages.getStringForLocale(key, this.locale);
34+
if (!msg) {
35+
throw new Error(`Could not find intl message ${key} in ${this.locale} locale`);
36+
}
37+
38+
message = new IntlMessageFormat(msg, this.locale);
39+
this.cache[key] = message;
40+
}
41+
42+
return message.format(variables);
43+
}
44+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright 2020 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
export * from './MessageDictionary';
14+
export * from './MessageFormatter';
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
# @react-stately/i18n
1+
# @internationalized/number
22

33
This package is part of [react-spectrum](https://github.com/adobe/react-spectrum). See the repo for more details.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Copyright 2020 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
export * from './src';

packages/@react-stately/i18n/package.json renamed to packages/@internationalized/number/package.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"name": "@react-stately/i18n",
2+
"name": "@internationalized/number",
33
"version": "3.0.0-alpha.1",
4-
"description": "Spectrum UI components in React",
4+
"description": "Internationalized number formatting and parsing utilities",
55
"license": "Apache-2.0",
66
"private": true,
77
"main": "dist/main.js",
@@ -20,9 +20,6 @@
2020
"dependencies": {
2121
"@babel/runtime": "^7.6.2"
2222
},
23-
"peerDependencies": {
24-
"react": "^16.8.0 || ^17.0.0-rc.1"
25-
},
2623
"publishConfig": {
2724
"access": "public"
2825
}

0 commit comments

Comments
 (0)