1 | 'use strict';
|
2 |
|
3 | var fs = require('fs');
|
4 | var path = require('path');
|
5 |
|
6 | var keys = ['i18NProviderUtils.getI18NValue', 'getI18NValue', '<FormatText', '<PluralFormat', '//I18N'];
|
7 |
|
8 | var i18nLogs = {};
|
9 | var fileObj = {};
|
10 | var initialized = false;
|
11 | var fileList = [];
|
12 | var filename;
|
13 | var context = process.env.npm_config_server_context || 'app';
|
14 | var appPath = fs.realpathSync(process.cwd());
|
15 | var cachePath = path.join(appPath, 'node_modules', '.cache');
|
16 | if (!fs.existsSync(cachePath)) {
|
17 | fs.mkdir(cachePath);
|
18 | }
|
19 |
|
20 | var jsonPath = path.join(cachePath, 'i18nkeys.json');
|
21 | var dynamicI18nsPath = path.join(appPath, context, 'properties', 'i18nkeys.json');
|
22 |
|
23 | function isTernary(str) {
|
24 | var operator = void 0;
|
25 | if (str.indexOf('?') !== -1) {
|
26 | operator = '?';
|
27 | } else if (str.indexOf('&') !== -1) {
|
28 | operator = '&';
|
29 | }
|
30 | return operator;
|
31 | }
|
32 |
|
33 | function getTernary(str) {
|
34 | var operatorIndex = void 0;
|
35 | var operator = isTernary(str);
|
36 | str = str.split(operator);
|
37 | str.splice(0, 1);
|
38 | var substr = str[0].trim();
|
39 | str = str.join(operator);
|
40 | var output = [];
|
41 | if (operator === '&') {
|
42 | output.push(substr);
|
43 | } else if (operator === '?') {
|
44 | substr = substr.split(':');
|
45 | output.push(substr[0]);
|
46 | output.push(substr[1]);
|
47 | str = str.split(':');
|
48 | str.splice(0, 1);
|
49 | str = str.join(':');
|
50 | }
|
51 | if (isTernary(str)) {
|
52 | getTernary(str).forEach(function (i18n) {
|
53 | output.push(i18n);
|
54 | });
|
55 | }
|
56 | return output;
|
57 | }
|
58 |
|
59 | function getI18NValue(line, subIndex) {
|
60 | var words = line.split('getI18NValue');
|
61 | var keys = [];
|
62 | words.splice(0, 1);
|
63 | words.forEach(function (word, wordIndex) {
|
64 | var params = getInnerValue(word, '(', ')', null, 'getI18NValue');
|
65 | if (params) {
|
66 | var lastWord = words[wordIndex - 1];
|
67 | var index = lastWord ? lastWord.trim().endsWith('i18NProviderUtils.') ? 0 : 1 : subIndex;
|
68 | var param = params.split(',')[index];
|
69 | if (!param) {
|
70 |
|
71 | }
|
72 | if (param) {
|
73 | if (isTernary(param)) {
|
74 | param = getTernary(param);
|
75 | } else {
|
76 | param = [param];
|
77 | }
|
78 | param.forEach(function (i18n) {
|
79 | i18n = i18n.trim();
|
80 | if (i18n.indexOf('"') === -1 && i18n.indexOf("'") === -1) {
|
81 | keys.push(false);
|
82 | } else {
|
83 | i18n = i18n.replace(/"/g, '');
|
84 | i18n = i18n.replace(/'/g, '');
|
85 | keys.push(i18n);
|
86 | }
|
87 | });
|
88 | }
|
89 | }
|
90 | });
|
91 | return keys;
|
92 | }
|
93 |
|
94 | function getI18N(line) {
|
95 | if (isTernary(line)) {
|
96 | line = getTernary(line);
|
97 | } else {
|
98 | line = [line];
|
99 | }
|
100 | var keys = [];
|
101 | line.forEach(function (sentance) {
|
102 | var props = getInnerValue(sentance, '"', '"', {
|
103 | start: "'",
|
104 | end: "'"
|
105 | }, 'Component');
|
106 | if (props) {
|
107 | props = props.trim();
|
108 | }
|
109 | keys.push(props);
|
110 | });
|
111 | return keys;
|
112 | }
|
113 |
|
114 | function getKey(line, index) {
|
115 | index = index ? index : 0;
|
116 | var regex = new RegExp(keys[index], 'i');
|
117 | if (line.match(regex)) {
|
118 | return keys[index];
|
119 | } else if (index >= keys.length) {
|
120 | return false;
|
121 | } else {
|
122 | index += 1;
|
123 | return getKey(line, index);
|
124 | }
|
125 | }
|
126 |
|
127 | function getInnerValue(sentance, start, end, option, key) {
|
128 | if (sentance.indexOf(start) === -1) {
|
129 | if (option) {
|
130 | start = option.start;
|
131 | end = end.start;
|
132 | } else {
|
133 | return false;
|
134 | }
|
135 | }
|
136 | if (key === 'getI18NValue') {
|
137 | var startIndex = sentance.indexOf(start) + 1;
|
138 | var endIndex = sentance.indexOf(end);
|
139 | return sentance.substring(startIndex, endIndex);
|
140 | } else if (key === 'Component') {
|
141 | sentance = sentance.split(start)[1];
|
142 | if (sentance) {
|
143 | sentance = sentance.split(end)[0];
|
144 | return sentance;
|
145 | }
|
146 | return false;
|
147 | } else {
|
148 | return false;
|
149 | }
|
150 | }
|
151 |
|
152 | function getComponent(line, key) {
|
153 | var words = line.split(key);
|
154 | var keys = [];
|
155 | words.splice(0, 1);
|
156 | words.forEach(function (word) {
|
157 | if (isTernary(word)) {
|
158 | word = getTernary(word);
|
159 | } else {
|
160 | word = [word];
|
161 | }
|
162 | word.forEach(function (sentance) {
|
163 | var props = getInnerValue(sentance, '"', '"', {
|
164 | start: "'",
|
165 | end: "'"
|
166 | }, 'Component');
|
167 | if (props) {
|
168 | props = props.trim();
|
169 | }
|
170 | keys.push(props);
|
171 | });
|
172 | });
|
173 | return keys;
|
174 | }
|
175 |
|
176 | function getPluralFormat(line) {
|
177 | var one = getComponent(line, 'one');
|
178 | var many = getComponent(line, 'many');
|
179 | var zero = getComponent(line, 'zero');
|
180 | var all = one.concat(many);
|
181 | all = all.concat(zero);
|
182 | return all;
|
183 | }
|
184 |
|
185 | function updaeFileObj(filename) {
|
186 | i18nLogs[filename] = Object.assign({}, fileObj[filename]);
|
187 | fileObj = {};
|
188 | }
|
189 |
|
190 | function updateI18N(fname) {
|
191 | if (initialized) {
|
192 | updaeFileObj(fname);
|
193 | }
|
194 | var tempObj = {};
|
195 | for (filename in i18nLogs) {
|
196 | Object.keys(i18nLogs[filename]).forEach(function (key) {
|
197 | tempObj[key] = key;
|
198 | });
|
199 | }
|
200 | var obj = {};
|
201 | var dynamicI18ns = {};
|
202 | if (fs.existsSync(jsonPath)) {
|
203 | obj = require(jsonPath);
|
204 | dynamicI18ns = require(dynamicI18nsPath);
|
205 | }
|
206 | fs.writeFileSync(jsonPath, JSON.stringify(Object.assign(dynamicI18ns, obj, tempObj)));
|
207 | }
|
208 |
|
209 | function addI18N(i18n, filename) {
|
210 | if (i18n) {
|
211 | if (!i18nLogs[filename]) {
|
212 | i18nLogs[filename] = {};
|
213 | }
|
214 | if (!fileObj[filename] && initialized) {
|
215 | fileObj[filename] = {};
|
216 | }
|
217 | if (initialized) {
|
218 | fileObj[filename][i18n] = i18n;
|
219 | }
|
220 | i18nLogs[filename][i18n] = i18n;
|
221 | }
|
222 | }
|
223 |
|
224 | function i18NLoader(source) {
|
225 | if (source.indexOf('fz-i18n') === -1) {
|
226 | return source;
|
227 | }
|
228 | var lines = source.split('\n');
|
229 | var tag = '';
|
230 | var isFormatText = false;
|
231 | var isPluralFormat = false;
|
232 | filename = this.resourcePath;
|
233 | lines.forEach(function (line) {
|
234 | var key = getKey(line);
|
235 | if (key === 'i18NProviderUtils.getI18NValue') {
|
236 | var i18ns = getI18NValue(line, 0);
|
237 | i18ns.forEach(function (i18n) {
|
238 | addI18N(i18n, filename);
|
239 | });
|
240 | } else if (key === 'getI18NValue') {
|
241 | var _i18ns = getI18NValue(line, 1);
|
242 | _i18ns.forEach(function (i18n) {
|
243 | addI18N(i18n, filename);
|
244 | });
|
245 | } else if (key === '<FormatText' || isFormatText) {
|
246 | tag += line;
|
247 | if (!isFormatText) {
|
248 | isFormatText = true;
|
249 | }
|
250 | var cleanTag = tag.replace(/\s+/, '');
|
251 | if (cleanTag.indexOf('/>') !== -1 || cleanTag.indexOf('</FormatText>') !== -1) {
|
252 | var _i18ns2 = getComponent(tag, 'i18NKey');
|
253 | _i18ns2.forEach(function (i18n) {
|
254 | addI18N(i18n, filename);
|
255 | });
|
256 | tag = '';
|
257 | isFormatText = false;
|
258 | }
|
259 | } else if (key === '<PluralFormat' || isPluralFormat) {
|
260 | tag += line;
|
261 | if (!isPluralFormat) {
|
262 | isPluralFormat = true;
|
263 | }
|
264 | var _cleanTag = tag.replace(/\s+/, '');
|
265 | if (_cleanTag.indexOf('/>') !== -1 || _cleanTag.indexOf('</PluralFormat>') !== -1) {
|
266 | var _i18ns3 = getPluralFormat(tag);
|
267 | _i18ns3.forEach(function (i18n) {
|
268 | addI18N(i18n, filename);
|
269 | });
|
270 | tag = '';
|
271 | isPluralFormat = false;
|
272 | }
|
273 | } else if (key === '//I18N') {
|
274 | var _i18ns4 = getI18N(line);
|
275 | _i18ns4.forEach(function (i18n) {
|
276 | addI18N(i18n, filename);
|
277 | });
|
278 | }
|
279 | });
|
280 | updateI18N(filename);
|
281 | if (!initialized) {
|
282 | if (fileList.indexOf(filename) === -1) {
|
283 | fileList.push(filename);
|
284 | } else {
|
285 | initialized = true;
|
286 | }
|
287 | }
|
288 | return source;
|
289 | }
|
290 |
|
291 | module.exports = i18NLoader; |
\ | No newline at end of file |