Skip to content

Commit 3ac7c68

Browse files
authored
Enhancement: useI18n hook (#195)
* useI18n hook * size limit increase
1 parent 06ef69d commit 3ac7c68

File tree

6 files changed

+132
-54
lines changed

6 files changed

+132
-54
lines changed

.size-limit

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
[
22
{
33
"path": "lib/index.js",
4-
"limit": "3 KB",
4+
"limit": "3.1 KB",
55
"webpack": false
66
},
77
{
88
"path": "lib/index.es.js",
9-
"limit": "2.6 KB",
9+
"limit": "2.7 KB",
1010
"webpack": false
1111
},
1212
{
1313
"path": "lib/index.babel.js",
14-
"limit": "1.9 KB",
14+
"limit": "1.95 KB",
1515
"webpack": false
1616
}
1717
]

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ DO NOT TOUCH. SAVE IT ON TOP.
2424
2525
-->
2626

27+
## [4.1.0] - 2020-10-18
28+
### Added
29+
- `useI18n` hook as part of `createI18nProvider` result.
30+
31+
## Removed
32+
- `createI18nHook` method.
33+
2734
## [4.0.0] - 2020-10-02
2835
### Changed
2936
- Moved from component API to hooks.

README.md

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,11 @@ const {
7878
/**
7979
* Context with config and methods.
8080
*/
81-
I18nContext
81+
I18nContext,
82+
/**
83+
* Hook to recieve config and methods.
84+
*/
85+
useI18n
8286
} = createI18nProvider(
8387
/**
8488
* Methods for binding and providing.
@@ -99,32 +103,6 @@ const {
99103

100104
</details>
101105

102-
### [createI18nHook](https://trigensoftware.github.io/i18n-for-react/modules/_src_createi18nprovider_.html#createi18nhook)
103-
104-
Create hook from context.
105-
106-
<details>
107-
<summary>Usage example</summary>
108-
109-
```js
110-
/**
111-
* Basic example
112-
*/
113-
const useI18n = createI18nHook(I18nContext);
114-
/**
115-
* Then you can use this hook
116-
*/
117-
function SomeComponent() {
118-
const {
119-
__
120-
} = useI18n();
121-
122-
return __`cat`;
123-
}
124-
```
125-
126-
</details>
127-
128106
### [I18nProvider](https://trigensoftware.github.io/i18n-for-react/modules/_src_createi18nprovider_.html#createi18nprovider)
129107

130108
Configurator and provider of `i18n` instance.
@@ -169,6 +147,40 @@ Configurator and provider of `i18n` instance.
169147

170148
</details>
171149

150+
### [useI18n](https://trigensoftware.github.io/i18n-for-react/modules/_src_createi18nprovider_.html#createi18nprovider)
151+
152+
Hook to recieve config and methods.
153+
154+
<details>
155+
<summary>Usage example</summary>
156+
157+
```js
158+
/**
159+
* Basic example
160+
*/
161+
function SomeComponent() {
162+
const {
163+
__
164+
} = useI18n();
165+
166+
return __`cat`;
167+
}
168+
/**
169+
* Fork instance
170+
*/
171+
function SomeComponent() {
172+
const {
173+
__
174+
} = useI18n({
175+
locales: /* ... */
176+
});
177+
178+
return __`cat`;
179+
}
180+
```
181+
182+
</details>
183+
172184
### [rprintf()](https://trigensoftware.github.io/i18n-for-react/modules/_src_rprintf_.html#rprintf)
173185

174186
Format string with wrappers.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "i18n-for-react",
3-
"version": "4.0.0",
3+
"version": "4.1.0",
44
"description": "Modern translation module for React.",
55
"author": "dangreen",
66
"license": "MIT",

src/createI18nProvider.tsx

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React, {
2-
Context,
32
createContext,
43
useContext,
54
useMemo,
@@ -21,7 +20,7 @@ import {
2120
* Create i18n provider with given methods.
2221
* @param methods - I18n methods.
2322
* @param config - Default config.
24-
* @returns Provider.
23+
* @returns Provider, context, and hook.
2524
*/
2625
export function createI18nProvider<
2726
TMethods extends I18nMethods = I18nMethods
@@ -33,15 +32,12 @@ export function createI18nProvider<
3332
const I18nContext = createContext<I18nContextPayload<TMethods>>(null);
3433
const useI18nParentInstance = ({
3534
context
36-
}: I18nProviderProps) => {
35+
}: Partial<I18nProviderProps>) => {
3736
const parentContext = useContext(I18nContext);
3837

3938
return context || parentContext && parentContext.config;
4039
};
41-
const I18nProvider = memo((props: I18nProviderProps) => {
42-
const {
43-
children
44-
} = props;
40+
const useI18nContextPayload = (props: Partial<I18nProviderProps>) => {
4541
const i18nParentInstance = useI18nParentInstance(props);
4642
const instanceProps = i18nParentInstance ? props : { ...config, ...props };
4743
const i18nInstance = useI18nInstance(instanceProps, i18nParentInstance);
@@ -50,29 +46,47 @@ export function createI18nProvider<
5046
[i18nInstance]
5147
);
5248

49+
return payload;
50+
};
51+
const I18nProvider = memo((props: I18nProviderProps) => {
52+
const {
53+
children
54+
} = props;
55+
const payload = useI18nContextPayload(props);
56+
5357
return (
5458
<I18nContext.Provider value={payload}>
5559
{children}
5660
</I18nContext.Provider>
5761
);
5862
});
63+
const useI18n = (config?: I18nProviderConfig) => {
64+
const withConfigRef = useRef(Boolean(config));
65+
66+
if (withConfigRef.current) {
67+
return useI18nContextPayload(config);
68+
}
69+
70+
return useContext(I18nContext);
71+
};
5972

6073
return {
74+
/**
75+
* Config and methods provider.
76+
*/
6177
I18nProvider,
62-
I18nContext
78+
/**
79+
* Context with config and methods.
80+
*/
81+
I18nContext,
82+
/**
83+
* Hook to recieve config and methods.
84+
*/
85+
useI18n
6386
};
6487
}
6588

66-
/**
67-
* Create i18n hook from given context.
68-
* @param context - I18n context.
69-
* @returns Hook function.
70-
*/
71-
export function createI18nHook<T extends I18nMethods>(context: Context<I18nContextPayload<T>>) {
72-
return () => useContext(context);
73-
}
74-
75-
function useI18nInstance(props: I18nProviderProps, i18nParentInstance: I18nConfigInstance) {
89+
function useI18nInstance(props: Partial<I18nProviderProps>, i18nParentInstance: I18nConfigInstance) {
7690
const {
7791
locale,
7892
locales,
@@ -123,7 +137,7 @@ function createI18nInstance(
123137
context,
124138
children,
125139
...config
126-
}: I18nProviderProps,
140+
}: Partial<I18nProviderProps>,
127141
i18nParentInstance: I18nConfigInstance
128142
) {
129143
const configWithLocale = typeof locale === 'string'

test/lib.spec.tsx

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import Enzyme, {
88
import {
99
I18nConfig,
1010
createI18nProvider,
11-
createI18nHook,
1211
__,
1312
__x
1413
} from '../src';
@@ -33,12 +32,12 @@ const CONFIG: I18nConfig = {
3332
describe('i18n-for-react', () => {
3433
const {
3534
I18nProvider,
36-
I18nContext
35+
I18nContext,
36+
useI18n
3737
} = createI18nProvider({
3838
__,
3939
__x
4040
}, CONFIG);
41-
const useI18n = createI18nHook(I18nContext);
4241

4342
it('should translate phrase from global context', () => {
4443
const wrapper = mount(
@@ -179,7 +178,6 @@ describe('i18n-for-react', () => {
179178
</>
180179
);
181180
};
182-
183181
const wrapper = mount(
184182
<I18nProvider>
185183
<Text />
@@ -188,4 +186,51 @@ describe('i18n-for-react', () => {
188186

189187
expect(wrapper.html()).toBe('Hello');
190188
});
189+
190+
it('should create instance by hook', () => {
191+
const Text = () => {
192+
const {
193+
__
194+
} = useI18n(CONFIG);
195+
196+
return (
197+
<>
198+
{__`hi`}
199+
</>
200+
);
201+
};
202+
const wrapper = mount(
203+
<Text />
204+
);
205+
206+
expect(wrapper.html()).toBe('Hello');
207+
});
208+
209+
it('should fork instance by hook', () => {
210+
const subconfig = {
211+
locales: {
212+
en: {
213+
'hi': 'sup'
214+
}
215+
}
216+
};
217+
const Text = () => {
218+
const {
219+
__
220+
} = useI18n(subconfig);
221+
222+
return (
223+
<>
224+
{__`hi`}
225+
</>
226+
);
227+
};
228+
const wrapper = mount(
229+
<I18nProvider>
230+
<Text />
231+
</I18nProvider>
232+
);
233+
234+
expect(wrapper.html()).toBe('sup');
235+
});
191236
});

0 commit comments

Comments
 (0)