@vocab/react 1.1.4 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +12 -3
- package/dist/declarations/src/index.d.ts +25 -25
- package/dist/vocab-react.cjs.dev.js +2 -14
- package/dist/vocab-react.cjs.prod.js +2 -14
- package/dist/vocab-react.esm.js +0 -12
- package/package.json +3 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
### MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 SEEK
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -20,10 +20,11 @@ Vocab helps you ship multiple languages without compromising the reliability of
|
|
|
20
20
|
|
|
21
21
|
### Step 1: Install Dependencies
|
|
22
22
|
|
|
23
|
-
Vocab is a monorepo with different packages you can install depending on your usage, the below list will get you started using the
|
|
23
|
+
Vocab is a monorepo with different packages you can install depending on your usage, the below list will get you started using the CLI and React integration.
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
$ npm i --save @vocab/cli
|
|
26
|
+
$ npm i --save-dev @vocab/cli
|
|
27
|
+
$ npm i --save @vocab/core @vocab/react
|
|
27
28
|
```
|
|
28
29
|
|
|
29
30
|
### Step 2: Configure Vocab
|
|
@@ -116,6 +117,10 @@ Right now every language is loaded into your web application all the time, which
|
|
|
116
117
|
|
|
117
118
|
This is done using the **VocabWebpackPlugin**. Applying this plugin to your client webpack configuration will replace all vocab files with a dynamic asynchronous chunks designed for the web.
|
|
118
119
|
|
|
120
|
+
```bash
|
|
121
|
+
$ npm i --save-dev @vocab/webpack
|
|
122
|
+
```
|
|
123
|
+
|
|
119
124
|
**webpack.config.js**
|
|
120
125
|
|
|
121
126
|
```js
|
|
@@ -206,7 +211,7 @@ module.exports = {
|
|
|
206
211
|
*/
|
|
207
212
|
generatedLanguages: [
|
|
208
213
|
{
|
|
209
|
-
name: '
|
|
214
|
+
name: 'generatedLanguage',
|
|
210
215
|
extends: 'en',
|
|
211
216
|
generator: {
|
|
212
217
|
transformElement: capitalize,
|
|
@@ -296,6 +301,10 @@ const App = () => (
|
|
|
296
301
|
|
|
297
302
|
The `@vocab/pseudo-localize` package exports low-level functions that can be used for pseudo-localization of translation messages.
|
|
298
303
|
|
|
304
|
+
```bash
|
|
305
|
+
$ npm i --save-dev @vocab/pseudo-localize
|
|
306
|
+
```
|
|
307
|
+
|
|
299
308
|
```ts
|
|
300
309
|
import {
|
|
301
310
|
extendVowels,
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import { TranslationFile, LanguageName, ParsedFormatFnByKey, ParsedFormatFn } from '@vocab/
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
-
|
|
4
|
-
interface TranslationsValue {
|
|
5
|
-
language: LanguageName;
|
|
6
|
-
locale?: Locale;
|
|
7
|
-
}
|
|
8
|
-
interface VocabProviderProps extends TranslationsValue {
|
|
9
|
-
children: ReactNode;
|
|
10
|
-
}
|
|
11
|
-
export declare const VocabProvider: ({ children, language, locale, }: VocabProviderProps) => JSX.Element;
|
|
12
|
-
export declare const useLanguage: () => TranslationsValue;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
[key in keyof Params]: Params[key] extends ParsedFormatFn ? FormatXMLElementReactNodeFn : Params[key];
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
<TranslationKey extends keyof FormatFnByKey>(key: TranslationKey, params: MapToReactNodeFunction<Parameters<FormatFnByKey[TranslationKey]>[0]>): ReturnType<FormatFnByKey[TranslationKey]> extends string ? string : ReactNode | string | Array<ReactNode | string>;
|
|
19
|
-
<TranslationKey extends keyof FormatFnByKey>(key: Parameters<FormatFnByKey[TranslationKey]>[0] extends Record<string, any> ? never : TranslationKey): string;
|
|
20
|
-
};
|
|
21
|
-
export declare function useTranslations<Language extends string, FormatFnByKey extends ParsedFormatFnByKey>(translations: TranslationFile<Language, FormatFnByKey>): {
|
|
22
|
-
ready: boolean;
|
|
23
|
-
t: TranslateFn<FormatFnByKey>;
|
|
24
|
-
};
|
|
25
|
-
export {};
|
|
1
|
+
import type { TranslationFile, LanguageName, ParsedFormatFnByKey, ParsedFormatFn } from '@vocab/core';
|
|
2
|
+
import { type ReactNode } from 'react';
|
|
3
|
+
type Locale = string;
|
|
4
|
+
interface TranslationsValue {
|
|
5
|
+
language: LanguageName;
|
|
6
|
+
locale?: Locale;
|
|
7
|
+
}
|
|
8
|
+
interface VocabProviderProps extends TranslationsValue {
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export declare const VocabProvider: ({ children, language, locale, }: VocabProviderProps) => JSX.Element;
|
|
12
|
+
export declare const useLanguage: () => TranslationsValue;
|
|
13
|
+
type FormatXMLElementReactNodeFn = (parts: ReactNode[]) => ReactNode;
|
|
14
|
+
type MapToReactNodeFunction<Params extends Record<string, any>> = {
|
|
15
|
+
[key in keyof Params]: Params[key] extends ParsedFormatFn ? FormatXMLElementReactNodeFn : Params[key];
|
|
16
|
+
};
|
|
17
|
+
type TranslateFn<FormatFnByKey extends ParsedFormatFnByKey> = {
|
|
18
|
+
<TranslationKey extends keyof FormatFnByKey>(key: TranslationKey, params: MapToReactNodeFunction<Parameters<FormatFnByKey[TranslationKey]>[0]>): ReturnType<FormatFnByKey[TranslationKey]> extends string ? string : ReactNode | string | Array<ReactNode | string>;
|
|
19
|
+
<TranslationKey extends keyof FormatFnByKey>(key: Parameters<FormatFnByKey[TranslationKey]>[0] extends Record<string, any> ? never : TranslationKey): string;
|
|
20
|
+
};
|
|
21
|
+
export declare function useTranslations<Language extends string, FormatFnByKey extends ParsedFormatFnByKey>(translations: TranslationFile<Language, FormatFnByKey>): {
|
|
22
|
+
ready: boolean;
|
|
23
|
+
t: TranslateFn<FormatFnByKey>;
|
|
24
|
+
};
|
|
25
|
+
export {};
|
|
@@ -8,7 +8,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e };
|
|
|
8
8
|
|
|
9
9
|
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
10
10
|
|
|
11
|
-
const TranslationsContext = /*#__PURE__*/React__default[
|
|
11
|
+
const TranslationsContext = /*#__PURE__*/React__default["default"].createContext(undefined);
|
|
12
12
|
const VocabProvider = ({
|
|
13
13
|
children,
|
|
14
14
|
language,
|
|
@@ -18,21 +18,18 @@ const VocabProvider = ({
|
|
|
18
18
|
language,
|
|
19
19
|
locale
|
|
20
20
|
}), [language, locale]);
|
|
21
|
-
return /*#__PURE__*/React__default[
|
|
21
|
+
return /*#__PURE__*/React__default["default"].createElement(TranslationsContext.Provider, {
|
|
22
22
|
value: value
|
|
23
23
|
}, children);
|
|
24
24
|
};
|
|
25
25
|
const useLanguage = () => {
|
|
26
26
|
const context = React.useContext(TranslationsContext);
|
|
27
|
-
|
|
28
27
|
if (!context) {
|
|
29
28
|
throw new Error('Attempted to access translation without Vocab context set. Did you forget to render VocabProvider?');
|
|
30
29
|
}
|
|
31
|
-
|
|
32
30
|
if (!context.language) {
|
|
33
31
|
throw new Error('Attempted to access translation without language set. Did you forget to pass language to VocabProvider?');
|
|
34
32
|
}
|
|
35
|
-
|
|
36
33
|
return context;
|
|
37
34
|
};
|
|
38
35
|
const SERVER_RENDERING = typeof window === 'undefined';
|
|
@@ -44,37 +41,29 @@ function useTranslations(translations) {
|
|
|
44
41
|
const [, forceRender] = React.useReducer(s => s + 1, 0);
|
|
45
42
|
const translationsObject = translations.getLoadedMessages(language, locale || language);
|
|
46
43
|
let ready = true;
|
|
47
|
-
|
|
48
44
|
if (!translationsObject) {
|
|
49
45
|
if (SERVER_RENDERING) {
|
|
50
46
|
throw new Error(`Translations not synchronously available on server render. Applying translations dynamically server-side is not supported.`);
|
|
51
47
|
}
|
|
52
|
-
|
|
53
48
|
translations.load(language).then(() => {
|
|
54
49
|
forceRender();
|
|
55
50
|
});
|
|
56
51
|
ready = false;
|
|
57
52
|
}
|
|
58
|
-
|
|
59
53
|
const t = React.useCallback((key, params) => {
|
|
60
54
|
if (!translationsObject) {
|
|
61
55
|
return ' ';
|
|
62
56
|
}
|
|
63
|
-
|
|
64
57
|
const message = translationsObject === null || translationsObject === void 0 ? void 0 : translationsObject[key];
|
|
65
|
-
|
|
66
58
|
if (!message) {
|
|
67
59
|
// eslint-disable-next-line no-console
|
|
68
60
|
console.error(`Unable to find translation for key "${key}". Possible keys are ${Object.keys(translationsObject).map(v => `"${v}"`).join(', ')}`);
|
|
69
61
|
return '';
|
|
70
62
|
}
|
|
71
|
-
|
|
72
63
|
const result = message.format(params);
|
|
73
|
-
|
|
74
64
|
if (Array.isArray(result)) {
|
|
75
65
|
for (let i = 0; i < result.length; i++) {
|
|
76
66
|
const item = result[i];
|
|
77
|
-
|
|
78
67
|
if (typeof item === 'object' && item && !item.key && /*#__PURE__*/React.isValidElement(item)) {
|
|
79
68
|
result[i] = /*#__PURE__*/React.cloneElement(item, {
|
|
80
69
|
key: `_vocab-${i}`
|
|
@@ -82,7 +71,6 @@ function useTranslations(translations) {
|
|
|
82
71
|
}
|
|
83
72
|
}
|
|
84
73
|
}
|
|
85
|
-
|
|
86
74
|
return result;
|
|
87
75
|
}, [translationsObject]);
|
|
88
76
|
return {
|
|
@@ -8,7 +8,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e };
|
|
|
8
8
|
|
|
9
9
|
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
10
10
|
|
|
11
|
-
const TranslationsContext = /*#__PURE__*/React__default[
|
|
11
|
+
const TranslationsContext = /*#__PURE__*/React__default["default"].createContext(undefined);
|
|
12
12
|
const VocabProvider = ({
|
|
13
13
|
children,
|
|
14
14
|
language,
|
|
@@ -18,21 +18,18 @@ const VocabProvider = ({
|
|
|
18
18
|
language,
|
|
19
19
|
locale
|
|
20
20
|
}), [language, locale]);
|
|
21
|
-
return /*#__PURE__*/React__default[
|
|
21
|
+
return /*#__PURE__*/React__default["default"].createElement(TranslationsContext.Provider, {
|
|
22
22
|
value: value
|
|
23
23
|
}, children);
|
|
24
24
|
};
|
|
25
25
|
const useLanguage = () => {
|
|
26
26
|
const context = React.useContext(TranslationsContext);
|
|
27
|
-
|
|
28
27
|
if (!context) {
|
|
29
28
|
throw new Error('Attempted to access translation without Vocab context set. Did you forget to render VocabProvider?');
|
|
30
29
|
}
|
|
31
|
-
|
|
32
30
|
if (!context.language) {
|
|
33
31
|
throw new Error('Attempted to access translation without language set. Did you forget to pass language to VocabProvider?');
|
|
34
32
|
}
|
|
35
|
-
|
|
36
33
|
return context;
|
|
37
34
|
};
|
|
38
35
|
const SERVER_RENDERING = typeof window === 'undefined';
|
|
@@ -44,37 +41,29 @@ function useTranslations(translations) {
|
|
|
44
41
|
const [, forceRender] = React.useReducer(s => s + 1, 0);
|
|
45
42
|
const translationsObject = translations.getLoadedMessages(language, locale || language);
|
|
46
43
|
let ready = true;
|
|
47
|
-
|
|
48
44
|
if (!translationsObject) {
|
|
49
45
|
if (SERVER_RENDERING) {
|
|
50
46
|
throw new Error(`Translations not synchronously available on server render. Applying translations dynamically server-side is not supported.`);
|
|
51
47
|
}
|
|
52
|
-
|
|
53
48
|
translations.load(language).then(() => {
|
|
54
49
|
forceRender();
|
|
55
50
|
});
|
|
56
51
|
ready = false;
|
|
57
52
|
}
|
|
58
|
-
|
|
59
53
|
const t = React.useCallback((key, params) => {
|
|
60
54
|
if (!translationsObject) {
|
|
61
55
|
return ' ';
|
|
62
56
|
}
|
|
63
|
-
|
|
64
57
|
const message = translationsObject === null || translationsObject === void 0 ? void 0 : translationsObject[key];
|
|
65
|
-
|
|
66
58
|
if (!message) {
|
|
67
59
|
// eslint-disable-next-line no-console
|
|
68
60
|
console.error(`Unable to find translation for key "${key}". Possible keys are ${Object.keys(translationsObject).map(v => `"${v}"`).join(', ')}`);
|
|
69
61
|
return '';
|
|
70
62
|
}
|
|
71
|
-
|
|
72
63
|
const result = message.format(params);
|
|
73
|
-
|
|
74
64
|
if (Array.isArray(result)) {
|
|
75
65
|
for (let i = 0; i < result.length; i++) {
|
|
76
66
|
const item = result[i];
|
|
77
|
-
|
|
78
67
|
if (typeof item === 'object' && item && !item.key && /*#__PURE__*/React.isValidElement(item)) {
|
|
79
68
|
result[i] = /*#__PURE__*/React.cloneElement(item, {
|
|
80
69
|
key: `_vocab-${i}`
|
|
@@ -82,7 +71,6 @@ function useTranslations(translations) {
|
|
|
82
71
|
}
|
|
83
72
|
}
|
|
84
73
|
}
|
|
85
|
-
|
|
86
74
|
return result;
|
|
87
75
|
}, [translationsObject]);
|
|
88
76
|
return {
|
package/dist/vocab-react.esm.js
CHANGED
|
@@ -16,15 +16,12 @@ const VocabProvider = ({
|
|
|
16
16
|
};
|
|
17
17
|
const useLanguage = () => {
|
|
18
18
|
const context = useContext(TranslationsContext);
|
|
19
|
-
|
|
20
19
|
if (!context) {
|
|
21
20
|
throw new Error('Attempted to access translation without Vocab context set. Did you forget to render VocabProvider?');
|
|
22
21
|
}
|
|
23
|
-
|
|
24
22
|
if (!context.language) {
|
|
25
23
|
throw new Error('Attempted to access translation without language set. Did you forget to pass language to VocabProvider?');
|
|
26
24
|
}
|
|
27
|
-
|
|
28
25
|
return context;
|
|
29
26
|
};
|
|
30
27
|
const SERVER_RENDERING = typeof window === 'undefined';
|
|
@@ -36,37 +33,29 @@ function useTranslations(translations) {
|
|
|
36
33
|
const [, forceRender] = useReducer(s => s + 1, 0);
|
|
37
34
|
const translationsObject = translations.getLoadedMessages(language, locale || language);
|
|
38
35
|
let ready = true;
|
|
39
|
-
|
|
40
36
|
if (!translationsObject) {
|
|
41
37
|
if (SERVER_RENDERING) {
|
|
42
38
|
throw new Error(`Translations not synchronously available on server render. Applying translations dynamically server-side is not supported.`);
|
|
43
39
|
}
|
|
44
|
-
|
|
45
40
|
translations.load(language).then(() => {
|
|
46
41
|
forceRender();
|
|
47
42
|
});
|
|
48
43
|
ready = false;
|
|
49
44
|
}
|
|
50
|
-
|
|
51
45
|
const t = useCallback((key, params) => {
|
|
52
46
|
if (!translationsObject) {
|
|
53
47
|
return ' ';
|
|
54
48
|
}
|
|
55
|
-
|
|
56
49
|
const message = translationsObject === null || translationsObject === void 0 ? void 0 : translationsObject[key];
|
|
57
|
-
|
|
58
50
|
if (!message) {
|
|
59
51
|
// eslint-disable-next-line no-console
|
|
60
52
|
console.error(`Unable to find translation for key "${key}". Possible keys are ${Object.keys(translationsObject).map(v => `"${v}"`).join(', ')}`);
|
|
61
53
|
return '';
|
|
62
54
|
}
|
|
63
|
-
|
|
64
55
|
const result = message.format(params);
|
|
65
|
-
|
|
66
56
|
if (Array.isArray(result)) {
|
|
67
57
|
for (let i = 0; i < result.length; i++) {
|
|
68
58
|
const item = result[i];
|
|
69
|
-
|
|
70
59
|
if (typeof item === 'object' && item && !item.key && /*#__PURE__*/isValidElement(item)) {
|
|
71
60
|
result[i] = /*#__PURE__*/cloneElement(item, {
|
|
72
61
|
key: `_vocab-${i}`
|
|
@@ -74,7 +63,6 @@ function useTranslations(translations) {
|
|
|
74
63
|
}
|
|
75
64
|
}
|
|
76
65
|
}
|
|
77
|
-
|
|
78
66
|
return result;
|
|
79
67
|
}, [translationsObject]);
|
|
80
68
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vocab/react",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"main": "dist/vocab-react.cjs.js",
|
|
5
5
|
"module": "dist/vocab-react.esm.js",
|
|
6
6
|
"author": "SEEK",
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
"dist"
|
|
13
13
|
],
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@vocab/
|
|
15
|
+
"@vocab/core": "^1.3.1",
|
|
16
16
|
"intl-messageformat": "^10.0.0"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@types/react": "^18.0.9",
|
|
20
20
|
"react": "^18.1.0"
|
|
21
21
|
}
|
|
22
|
-
}
|
|
22
|
+
}
|