-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuseT.js
64 lines (50 loc) · 1.96 KB
/
useT.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import IntlMessageFormat from 'intl-messageformat';
import { useSelector } from './useSelector.js';
import { get } from '../utils/object.js';
import { isObject } from '../utils/eq.js';
import { useRef } from 'react';
class NotMessageError extends Error {
constructor(key) {
super(`Key '${key}' found an object, and not a message. Are you sure it's correct?`);
this.name = 'NotMessageError';
}
}
class MessageNotFoundError extends Error {
constructor(key) {
super(`Message not found for key '${key}', and no default message was provided.`);
this.name = 'MessageNotFoundError';
}
}
let messageAstCache = {};
export const useT = userProps => {
const doHook = props => {
const lastMessages = useRef();
// force re-rendering when the messages change
useSelector(s => {
const messages = s.messages[s.selectedLang];
if (lastMessages.current !== messages)
messageAstCache = {};
return lastMessages.current = messages;
});
// for reference equality checking below
const defaultT = (key, values, defaultMsg) => {
if (!lastMessages.current) return key; // default to just being identity
let msg;
// figure out our msg situation
if (messageAstCache[key]) msg = new IntlMessageFormat(messageAstCache[key]);
else {
const maybeMsg = get(lastMessages.current, key, defaultMsg);
if (isObject(maybeMsg))
throw new NotMessageError(key);
else if (!maybeMsg)
throw new MessageNotFoundError(key);
msg = new IntlMessageFormat(maybeMsg);
messageAstCache[key] = msg.getAst();
}
return msg.format(values);
};
return Object.freeze({ $t: defaultT, ...props });
};
// curried for composition
return userProps ? doHook(userProps) : doHook;
};