-
Notifications
You must be signed in to change notification settings - Fork 0
/
babel-plugin-react-i18next.js
121 lines (114 loc) · 3.52 KB
/
babel-plugin-react-i18next.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
module.exports = function ({ types: t }) {
// import {Trans} from "react-i18next";
const specifiersTrans = t.importSpecifier(
t.identifier('Trans'),
t.identifier('Trans')
);
const sourceTrans = t.stringLiteral('react-i18next');
const importTrans = t.importDeclaration([specifiersTrans], sourceTrans);
// import i18next from "i18next";
const specifiersI18next = t.importDefaultSpecifier(t.identifier('i18next'));
const sourceI18next = t.stringLiteral('i18next');
const importI18next = t.importDeclaration([specifiersI18next], sourceI18next);
// t function of i18next
const translateFn = (strNode) => {
const ME = t.memberExpression(t.identifier('i18next'), t.identifier('t'));
return t.callExpression(ME, [strNode]);
};
// create Trans element
const transEle = (children) => {
const OpeningElement = t.jsxOpeningElement(
t.jsxIdentifier('Trans'),
[],
false
);
const ClosingElement = t.jsxClosingElement(t.jsxIdentifier('Trans'));
return t.jsxElement(OpeningElement, ClosingElement, children, false);
};
const hasTransPartImported = (specifiers) => {
return (
specifiers.findIndex(
(innerItem) =>
(innerItem && innerItem.imported && innerItem.imported.name) ===
'Trans'
) > -1
);
};
const hasTransImported = (path) => {
return (
path.node.body.findIndex(
(item) =>
(item.source && item.source.value) === 'react-i18next' &&
hasTransPartImported(item.specifiers)
) > -1
);
};
const hasI18nextImported = (path) => {
return path.node.body.find(
(item) => (item.source && item.source.value) === 'i18next'
);
};
const has2LvRelationship = (path) => {
return (
path.node.children.findIndex(
(item) =>
item.type === 'JSXElement' &&
item.children.findIndex((innerItem) => {
return innerItem.type === 'JSXElement';
}) === -1
) > -1 && path.node.openingElement.name.name !== 'Trans'
);
};
return {
visitor: {
Program(path) {
if (!hasTransImported(path)) {
path.node.body.unshift(importTrans);
}
if (!hasI18nextImported(path)) {
path.node.body.unshift(importI18next);
}
},
JSXText(path, state) {
if (state.opts.JSXText !== false) {
const text = path.node.value.trim();
if (text) {
path.replaceWith(
t.jsxExpressionContainer(translateFn(t.stringLiteral(text)))
);
}
}
},
JSXExpressionContainer(path, state) {
if (state.opts.JSXExpressionContainer !== false) {
if (
(path.node.expression.type === 'StringLiteral' &&
path.node.expression.value) ||
path.node.expression.type === 'ConditionalExpression'
) {
path.node.expression = translateFn(path.node.expression);
}
}
},
JSXElement(path, state) {
if (state.opts.JSXElement !== false) {
if (has2LvRelationship(path)) {
path.node.children = [transEle(path.node.children)];
}
}
},
JSXAttribute(path, state) {
if (state.opts.JSXAttribute !== false) {
if (
path.node.value.type === 'StringLiteral' &&
path.node.name.name !== 'className'
) {
path.node.value = t.jsxExpressionContainer(
translateFn(path.node.value)
);
}
}
},
},
};
};