@zohodesk/i18n 1.0.0-beta.34 → 1.0.0-beta.35-murphy

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.
Files changed (51) hide show
  1. package/docs/murphy/01-MURPHY_OVERVIEW.md +148 -0
  2. package/docs/murphy/02-MURPHY_ARCHITECTURE.md +283 -0
  3. package/docs/murphy/03-MURPHY_BACKEND_CONFIG.md +337 -0
  4. package/docs/murphy/04-MURPHY_FRONTEND_INIT.md +437 -0
  5. package/docs/murphy/05-MURPHY_DESK_CLIENT_USAGE.md +467 -0
  6. package/docs/murphy/06-MURPHY_I18N_INTEGRATION.md +402 -0
  7. package/docs/murphy/07-MURPHY_WHY_I18N_APPROACH.md +391 -0
  8. package/es/components/DateTimeDiffFormat.js +5 -19
  9. package/es/components/FormatText.js +2 -2
  10. package/es/components/HOCI18N.js +32 -43
  11. package/es/components/I18N.js +2 -13
  12. package/es/components/I18NProvider.js +0 -9
  13. package/es/components/PluralFormat.js +3 -5
  14. package/es/components/UserTimeDiffFormat.js +5 -9
  15. package/es/components/__tests__/DateTimeDiffFormat.spec.js +157 -221
  16. package/es/components/__tests__/FormatText.spec.js +2 -2
  17. package/es/components/__tests__/HOCI18N.spec.js +2 -4
  18. package/es/components/__tests__/I18N.spec.js +6 -4
  19. package/es/components/__tests__/I18NProvider.spec.js +4 -4
  20. package/es/components/__tests__/PluralFormat.spec.js +2 -2
  21. package/es/components/__tests__/UserTimeDiffFormat.spec.js +249 -348
  22. package/es/index.js +1 -0
  23. package/es/utils/__tests__/jsxTranslations.spec.js +3 -7
  24. package/es/utils/errorReporter.js +31 -0
  25. package/es/utils/index.js +42 -92
  26. package/es/utils/jsxTranslations.js +34 -52
  27. package/lib/I18NContext.js +2 -7
  28. package/lib/components/DateTimeDiffFormat.js +46 -87
  29. package/lib/components/FormatText.js +18 -41
  30. package/lib/components/HOCI18N.js +24 -59
  31. package/lib/components/I18N.js +27 -64
  32. package/lib/components/I18NProvider.js +27 -63
  33. package/lib/components/PluralFormat.js +24 -50
  34. package/lib/components/UserTimeDiffFormat.js +43 -72
  35. package/lib/components/__tests__/DateTimeDiffFormat.spec.js +95 -165
  36. package/lib/components/__tests__/FormatText.spec.js +3 -10
  37. package/lib/components/__tests__/HOCI18N.spec.js +3 -14
  38. package/lib/components/__tests__/I18N.spec.js +4 -12
  39. package/lib/components/__tests__/I18NProvider.spec.js +8 -23
  40. package/lib/components/__tests__/PluralFormat.spec.js +3 -11
  41. package/lib/components/__tests__/UserTimeDiffFormat.spec.js +157 -225
  42. package/lib/index.js +25 -23
  43. package/lib/utils/__tests__/jsxTranslations.spec.js +1 -12
  44. package/lib/utils/errorReporter.js +39 -0
  45. package/lib/utils/index.js +49 -125
  46. package/lib/utils/jsxTranslations.js +61 -100
  47. package/package.json +1 -1
  48. package/src/index.js +5 -0
  49. package/src/utils/errorReporter.js +36 -0
  50. package/src/utils/index.js +8 -1
  51. package/src/utils/jsxTranslations.js +8 -1
@@ -0,0 +1,391 @@
1
+ # Why Murphy in i18n Library (Not Desk Client)
2
+
3
+ ## The Question
4
+
5
+ When implementing Murphy error tracking for i18n failures, we had two options:
6
+
7
+ 1. **Option A:** Add tracking in the desk client application
8
+ 2. **Option B:** Add tracking in the i18n library itself
9
+
10
+ This document explains why Option B is the correct choice.
11
+
12
+ ---
13
+
14
+ ## Option A: Murphy in Desk Client App
15
+
16
+ ### How It Would Work
17
+
18
+ ```
19
+ +-------------------------------------------------------------------+
20
+ | OPTION A: DESK CLIENT APPROACH (NOT RECOMMENDED) |
21
+ +-------------------------------------------------------------------+
22
+ | |
23
+ | // In desk client app component |
24
+ | const text = getI18NValue(i18n, 'my.key'); |
25
+ | |
26
+ | // Try to detect if it failed... somehow? |
27
+ | if (text === 'my.key' || text.startsWith('Missing')) { |
28
+ | deskCustomError(...); // Report to Murphy |
29
+ | } |
30
+ | |
31
+ +-------------------------------------------------------------------+
32
+ ```
33
+
34
+ ### Problems with This Approach
35
+
36
+ ```
37
+ +-------------------------------------------------------------------+
38
+ | PROBLEM 1: WHERE TO HOOK? |
39
+ +-------------------------------------------------------------------+
40
+ | |
41
+ | getI18NValue('missing.key') |
42
+ | | |
43
+ | v |
44
+ | Returns: "missing.key" or "Missing: missing.key" |
45
+ | | |
46
+ | v |
47
+ | App receives a string - doesn't know it FAILED! |
48
+ | |
49
+ | Detection requires GUESSING: |
50
+ | +---------------------------------------------------------------+ |
51
+ | | // HACKY: Check if result equals the key | |
52
+ | | if (result === key) { /* maybe failed? */ } | |
53
+ | | | |
54
+ | | // HACKY: Check for "Missing" prefix | |
55
+ | | if (result.startsWith('Missing')) { /* maybe failed? */ } | |
56
+ | | | |
57
+ | | // FALSE POSITIVES: What if translation IS "Missing: ..."? | |
58
+ | | // FALSE NEGATIVES: What if fallback format changes? | |
59
+ | +---------------------------------------------------------------+ |
60
+ | |
61
+ +-------------------------------------------------------------------+
62
+
63
+ +-------------------------------------------------------------------+
64
+ | PROBLEM 2: EVERY APP NEEDS SAME CODE |
65
+ +-------------------------------------------------------------------+
66
+ | |
67
+ | Multiple apps use @zohodesk/i18n: |
68
+ | |
69
+ | +-------------------+ |
70
+ | | supportapp | --> Must add Murphy wrapper (duplicate) |
71
+ | +-------------------+ |
72
+ | + |
73
+ | +-------------------+ |
74
+ | | portal app | --> Must add Murphy wrapper (duplicate) |
75
+ | +-------------------+ |
76
+ | + |
77
+ | +-------------------+ |
78
+ | | ASAP widget | --> Must add Murphy wrapper (duplicate) |
79
+ | +-------------------+ |
80
+ | + |
81
+ | +-------------------+ |
82
+ | | future apps | --> Must remember to add! (easy to miss)|
83
+ | +-------------------+ |
84
+ | |
85
+ +-------------------------------------------------------------------+
86
+
87
+ +-------------------------------------------------------------------+
88
+ | PROBLEM 3: MAINTENANCE NIGHTMARE |
89
+ +-------------------------------------------------------------------+
90
+ | |
91
+ | Scenario: i18n library changes fallback text format |
92
+ | |
93
+ | Before: Returns "missing.key" |
94
+ | After: Returns "MISSING_TRANSLATION: missing.key" |
95
+ | |
96
+ | Required action: |
97
+ | +-- Update supportapp detection logic |
98
+ | +-- Update portal app detection logic |
99
+ | +-- Update ASAP widget detection logic |
100
+ | +-- Update all future apps... |
101
+ | |
102
+ | Risk: Inconsistent implementations, bugs, missed updates |
103
+ | |
104
+ +-------------------------------------------------------------------+
105
+
106
+ +-------------------------------------------------------------------+
107
+ | PROBLEM 4: APPS WITHOUT MURPHY |
108
+ +-------------------------------------------------------------------+
109
+ | |
110
+ | Some apps might not have Murphy configured: |
111
+ | |
112
+ | - New internal tools |
113
+ | - Test environments |
114
+ | - Third-party integrations |
115
+ | |
116
+ | Each app must: |
117
+ | +-- Check if murphy exists |
118
+ | +-- Handle the case where it doesn't |
119
+ | +-- Duplicate this safety check everywhere |
120
+ | |
121
+ +-------------------------------------------------------------------+
122
+ ```
123
+
124
+ ---
125
+
126
+ ## Option B: Murphy in i18n Library
127
+
128
+ ### How It Works
129
+
130
+ ```
131
+ +-------------------------------------------------------------------+
132
+ | OPTION B: I18N LIBRARY APPROACH (RECOMMENDED) |
133
+ +-------------------------------------------------------------------+
134
+ | |
135
+ | // Inside getI18NValue() in i18n library |
136
+ | export const getI18NValue = (i18n) => (key, values) => { |
137
+ | let i18nStr = i18n[key]; |
138
+ | |
139
+ | if (i18nStr === undefined) { |
140
+ | // WE KNOW IT FAILED - Right here, right now! |
141
+ | reportI18NError(I18N_ERROR_TYPES.MISSING_KEY, key); |
142
+ | return getFallbackText(key); |
143
+ | } |
144
+ | |
145
+ | return processTranslation(i18nStr, values); |
146
+ | }; |
147
+ | |
148
+ +-------------------------------------------------------------------+
149
+ ```
150
+
151
+ ### Benefits of This Approach
152
+
153
+ ```
154
+ +-------------------------------------------------------------------+
155
+ | BENEFIT 1: KNOWS EXACTLY WHEN FAILURE OCCURS |
156
+ +-------------------------------------------------------------------+
157
+ | |
158
+ | // Inside getI18NValue() |
159
+ | if (i18nStr === undefined) { |
160
+ | // We are INSIDE the function that processes the key |
161
+ | // We KNOW with 100% certainty it failed |
162
+ | // No guessing, no heuristics, no false positives |
163
+ | reportI18NError(MISSING_KEY, key); |
164
+ | } |
165
+ | |
166
+ +-------------------------------------------------------------------+
167
+
168
+ +-------------------------------------------------------------------+
169
+ | BENEFIT 2: FIX ONCE, WORKS EVERYWHERE |
170
+ +-------------------------------------------------------------------+
171
+ | |
172
+ | +-------------------+ |
173
+ | | i18n library | <-- Fix here once |
174
+ | +--------+----------+ |
175
+ | | |
176
+ | +-----------------+-----------------+ |
177
+ | | | | |
178
+ | v v v |
179
+ | +-------------+ +-------------+ +-------------+ |
180
+ | | supportapp | | portal app | | ASAP widget | |
181
+ | | OK | | OK | | OK | |
182
+ | +-------------+ +-------------+ +-------------+ |
183
+ | |
184
+ | All apps automatically get Murphy tracking! |
185
+ | No code changes in consuming apps needed! |
186
+ | |
187
+ +-------------------------------------------------------------------+
188
+
189
+ +-------------------------------------------------------------------+
190
+ | BENEFIT 3: SAFE FOR APPS WITHOUT MURPHY |
191
+ +-------------------------------------------------------------------+
192
+ | |
193
+ | // errorReporter.js |
194
+ | function isMurphyAvailable() { |
195
+ | return typeof murphy !== 'undefined' && |
196
+ | typeof murphy.error === 'function'; |
197
+ | } |
198
+ | |
199
+ | export function reportI18NError(type, key) { |
200
+ | // ... deduplication logic ... |
201
+ | |
202
+ | if (isMurphyAvailable()) { |
203
+ | murphy.error(...); // Report if Murphy exists |
204
+ | } |
205
+ | // Otherwise: silently skip - no crash, no error! |
206
+ | } |
207
+ | |
208
+ | Result: |
209
+ | +-- App WITH Murphy -> Errors reported to dashboard |
210
+ | +-- App WITHOUT Murphy -> Silently skipped, app works fine |
211
+ | |
212
+ +-------------------------------------------------------------------+
213
+
214
+ +-------------------------------------------------------------------+
215
+ | BENEFIT 4: ZERO OVERHEAD ON HAPPY PATH |
216
+ +-------------------------------------------------------------------+
217
+ | |
218
+ | // Normal case: Translation exists |
219
+ | let i18nStr = i18n[key]; // "Save Ticket" |
220
+ | |
221
+ | if (i18nStr !== undefined) { |
222
+ | // Happy path - no Murphy calls at all! |
223
+ | // Zero performance impact |
224
+ | return processTranslation(i18nStr, values); |
225
+ | } |
226
+ | |
227
+ | // Murphy only called when there's actually an error |
228
+ | |
229
+ +-------------------------------------------------------------------+
230
+
231
+ +-------------------------------------------------------------------+
232
+ | BENEFIT 5: DATACENTER AGNOSTIC |
233
+ +-------------------------------------------------------------------+
234
+ | |
235
+ | i18n library doesn't know or care which datacenter it's in: |
236
+ | |
237
+ | US Server: Murphy already configured with US credentials |
238
+ | JP Server: Murphy already configured with JP credentials |
239
+ | IN Server: Murphy already configured with IN credentials |
240
+ | |
241
+ | i18n library just calls: murphy.error(...) |
242
+ | Murphy SDK handles routing to correct datacenter! |
243
+ | |
244
+ | Same code works everywhere without modification. |
245
+ | |
246
+ +-------------------------------------------------------------------+
247
+ ```
248
+
249
+ ---
250
+
251
+ ## Side-by-Side Comparison
252
+
253
+ ```
254
+ +-------------------------------------------------------------------+
255
+ | COMPARISON TABLE |
256
+ +-------------------------------------------------------------------+
257
+ | |
258
+ | Aspect | Desk Client | i18n Library |
259
+ |---------------------|-----------------|---------------------------|
260
+ | Detection accuracy | Guessing | 100% accurate |
261
+ | Implementation | Every app | Once in library |
262
+ | Maintenance | Update all apps | Update one place |
263
+ | New apps | Must remember | Automatic |
264
+ | Performance | Extra checks | Zero overhead on success |
265
+ | Murphy safety | Each app checks | Built-in check |
266
+ | DC handling | Each app config | Automatic |
267
+ | Code duplication | High | None |
268
+ | |
269
+ +-------------------------------------------------------------------+
270
+ ```
271
+
272
+ ---
273
+
274
+ ## The Doctor Analogy
275
+
276
+ ```
277
+ +-------------------------------------------------------------------+
278
+ | DOCTOR ANALOGY |
279
+ +-------------------------------------------------------------------+
280
+ | |
281
+ | Option A (Desk Client): |
282
+ | +---------------------------------------------------------------+ |
283
+ | | | |
284
+ | | Patient: "I feel fine" | |
285
+ | | | |
286
+ | | App: "The i18n function returned something..." | |
287
+ | | App: "I THINK it might have failed?" | |
288
+ | | App: "Let me guess based on the output..." | |
289
+ | | | |
290
+ | +---------------------------------------------------------------+ |
291
+ | |
292
+ | Option B (i18n Library): |
293
+ | +---------------------------------------------------------------+ |
294
+ | | | |
295
+ | | Doctor (i18n lib): "I examined the patient" | |
296
+ | | Doctor (i18n lib): "The key doesn't exist - I KNOW this" | |
297
+ | | Doctor (i18n lib): *Reports directly to hospital (Murphy)* | |
298
+ | | | |
299
+ | +---------------------------------------------------------------+ |
300
+ | |
301
+ | The doctor KNOWS the diagnosis. |
302
+ | Don't ask the patient to diagnose themselves! |
303
+ | |
304
+ +-------------------------------------------------------------------+
305
+ ```
306
+
307
+ ---
308
+
309
+ ## Real-World Flow
310
+
311
+ ```
312
+ +-------------------------------------------------------------------+
313
+ | REAL-WORLD FLOW: I18N LIBRARY APPROACH |
314
+ +-------------------------------------------------------------------+
315
+ | |
316
+ | 1. User visits page in US datacenter |
317
+ | |
318
+ | 2. Murphy already configured: |
319
+ | desk_urls.murphyAppDomain = "murphy.zoho.com" |
320
+ | murphy.install() already called |
321
+ | |
322
+ | 3. React component renders: |
323
+ | <I18N i18nKey="tickets.status.label" /> |
324
+ | |
325
+ | 4. i18n library processes: |
326
+ | getI18NValue(i18n)('tickets.status.label') |
327
+ | -> i18n['tickets.status.label'] = undefined! |
328
+ | -> reportI18NError(MISSING_KEY, 'tickets.status.label') |
329
+ | -> Returns fallback: "tickets.status.label" |
330
+ | |
331
+ | 5. Murphy SDK sends to murphy.zoho.com: |
332
+ | { |
333
+ | error: "i18n I18N_MISSING_KEY: tickets.status.label", |
334
+ | customTags: { |
335
+ | errorType: "I18N_MISSING_KEY", |
336
+ | i18nKey: "tickets.status.label", |
337
+ | category: "i18n" |
338
+ | } |
339
+ | } |
340
+ | |
341
+ | 6. Developer sees in Murphy dashboard: |
342
+ | "Missing i18n key: tickets.status.label" |
343
+ | -> Adds translation |
344
+ | -> User no longer sees raw key |
345
+ | |
346
+ +-------------------------------------------------------------------+
347
+ ```
348
+
349
+ ---
350
+
351
+ ## Conclusion
352
+
353
+ ```
354
+ +-------------------------------------------------------------------+
355
+ | FINAL RECOMMENDATION |
356
+ +-------------------------------------------------------------------+
357
+ | |
358
+ | Murphy integration belongs in the i18n LIBRARY because: |
359
+ | |
360
+ | 1. ACCURACY: |
361
+ | The library knows EXACTLY when a translation fails |
362
+ | No guessing or heuristics required |
363
+ | |
364
+ | 2. DRY (Don't Repeat Yourself): |
365
+ | One implementation serves all consuming apps |
366
+ | No code duplication |
367
+ | |
368
+ | 3. SAFETY: |
369
+ | Built-in check for Murphy availability |
370
+ | Works with or without Murphy |
371
+ | |
372
+ | 4. PERFORMANCE: |
373
+ | Zero overhead when translations exist |
374
+ | Only reports when there's an actual failure |
375
+ | |
376
+ | 5. MAINTENANCE: |
377
+ | Fix once, benefits all apps |
378
+ | New apps automatically get tracking |
379
+ | |
380
+ | This is the correct architectural decision. |
381
+ | |
382
+ +-------------------------------------------------------------------+
383
+ ```
384
+
385
+ ---
386
+
387
+ ## Related Documents
388
+
389
+ - [05-MURPHY_DESK_CLIENT_USAGE.md](./05-MURPHY_DESK_CLIENT_USAGE.md) - How desk client uses Murphy
390
+ - [06-MURPHY_I18N_INTEGRATION.md](./06-MURPHY_I18N_INTEGRATION.md) - i18n integration details
391
+ - [02-MURPHY_ARCHITECTURE.md](./02-MURPHY_ARCHITECTURE.md) - Overall architecture
@@ -8,10 +8,8 @@ export default class DateTimeDiffFormat extends React.Component {
8
8
  super(props);
9
9
  this.getSuffix = this.getSuffix.bind(this);
10
10
  }
11
-
12
11
  getSuffix(min) {
13
12
  let suffix;
14
-
15
13
  if (this.props.ago && min < 0) {
16
14
  suffix = this.props.ago || '';
17
15
  } else if (this.props.later || min > 0) {
@@ -19,10 +17,8 @@ export default class DateTimeDiffFormat extends React.Component {
19
17
  } else {
20
18
  suffix = '';
21
19
  }
22
-
23
20
  return suffix;
24
21
  }
25
-
26
22
  render() {
27
23
  const {
28
24
  type,
@@ -95,9 +91,10 @@ export default class DateTimeDiffFormat extends React.Component {
95
91
  timeFormat: timeFormat,
96
92
  datePattern: datePattern,
97
93
  dateTimePattern: `${datePattern} ${timeFormat}`
98
- }; //In if condition we'll remove year and set date format if the current year is not required
99
- //In else part we'll set the date format as it is
94
+ };
100
95
 
96
+ //In if condition we'll remove year and set date format if the current year is not required
97
+ //In else part we'll set the date format as it is
101
98
  if (isEnabledCurrentYear === true && diffObj1.years === 0 && diffObj1.tYear === diffObj1.crntYear) {
102
99
  let dateFormat = getDatePatternWithoutYear(datePattern);
103
100
  diffObj1.dateFormat = dateFormat;
@@ -106,12 +103,10 @@ export default class DateTimeDiffFormat extends React.Component {
106
103
  diffObj1.dateFormat = datePattern;
107
104
  diffObj1.dateTimeFormat = `${datePattern} ${timeFormat}`;
108
105
  }
109
-
110
106
  let key = '';
111
107
  let values = [];
112
108
  let text = null;
113
109
  let isSuffixEnable = false;
114
-
115
110
  if (format) {
116
111
  let years, months, days, hours, minutes, seconds;
117
112
  years = diffObj1.years > 1 ? '2' : diffObj1.years;
@@ -128,15 +123,12 @@ export default class DateTimeDiffFormat extends React.Component {
128
123
  } else {
129
124
  res = res + next;
130
125
  }
131
-
132
126
  return res;
133
127
  }, '');
134
128
  let value = format(diffObj1, pattern);
135
-
136
129
  if (value && typeof value === 'object') {
137
130
  key = value.key;
138
131
  values = getValues(value.params, diffObj);
139
-
140
132
  if (pattern.indexOf('00000') === 0) {
141
133
  //suffix ignore for second hook
142
134
  isSuffixEnable = false;
@@ -149,32 +141,28 @@ export default class DateTimeDiffFormat extends React.Component {
149
141
  } else {
150
142
  let dateObj = new Date(toDateObj);
151
143
  let curDateObj = new Date(fromDateObj);
152
- let diffDayType = diffObj1.yDays; //In this condition, to calculate different days we have copied it from live --> diffDayType
144
+ let diffDayType = diffObj1.yDays;
153
145
 
146
+ //In this condition, to calculate different days we have copied it from live --> diffDayType
154
147
  if (isOverdue && dateObj.getDate() < curDateObj.getDate() && diffObj1.yDays == 0) {
155
148
  diffDayType = -1;
156
149
  }
157
-
158
150
  if (!isOverdue) {
159
151
  let diffHr = dateObj.getHours() - curDateObj.getHours();
160
-
161
152
  if (diffHr < 0) {
162
153
  diffDayType += 1;
163
154
  } else if (diffHr == 0) {
164
155
  let diffMins = dateObj.getMinutes() - curDateObj.getMinutes();
165
-
166
156
  if (diffMins < 0) {
167
157
  diffDayType += 1;
168
158
  } else if (diffMins == 0) {
169
159
  let diffSec = dateObj.getSeconds() - curDateObj.getSeconds();
170
-
171
160
  if (diffSec < 0) {
172
161
  diffDayType += 1;
173
162
  }
174
163
  }
175
164
  }
176
165
  }
177
-
178
166
  if (diff.y === 0 && (diffDayType === 0 || diffDayType === 1)) {
179
167
  if (dateObj.getDate() === curDateObj.getDate()) {
180
168
  var value = today && today(diffObj1) || others(diffObj1);
@@ -191,7 +179,6 @@ export default class DateTimeDiffFormat extends React.Component {
191
179
  text = formatDate(toDateObj, value);
192
180
  }
193
181
  }
194
-
195
182
  return text ? /*#__PURE__*/React.createElement("span", {
196
183
  className: className,
197
184
  "data-title": title,
@@ -204,7 +191,6 @@ export default class DateTimeDiffFormat extends React.Component {
204
191
  "data-title": title
205
192
  });
206
193
  }
207
-
208
194
  }
209
195
  DateTimeDiffFormat.propTypes = {
210
196
  ago: PropTypes.string,
@@ -3,10 +3,10 @@ import PropTypes from 'prop-types';
3
3
  import I18N from "./I18N";
4
4
  export default class FormatText extends React.Component {
5
5
  render() {
6
- return /*#__PURE__*/React.createElement(I18N, { ...this.props
6
+ return /*#__PURE__*/React.createElement(I18N, {
7
+ ...this.props
7
8
  });
8
9
  }
9
-
10
10
  }
11
11
  FormatText.propTypes = {
12
12
  i18NKey: PropTypes.string.isRequired,
@@ -2,49 +2,38 @@ import React, { Children } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { replaceI18NValuesWithRegex, unescapeUnicode } from "../utils";
4
4
  import { I18NContext } from "../I18NContext";
5
- export default (function () {
6
- let i18NKeys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
7
- return Component => {
8
- class HOCI18N extends React.Component {
9
- constructor(props) {
10
- super(props);
11
- this.getI18NValue = this.getI18NValue.bind(this);
12
- }
13
-
14
- getI18NValue(key) {
15
- const {
16
- i18n
17
- } = this.context || {};
18
-
19
- if (typeof i18n === 'undefined') {
20
- return key;
21
- }
22
-
23
- let i18nStr = i18n[key];
24
-
25
- if (i18nStr === undefined) {
26
- return key;
27
- }
28
-
29
- return unescapeUnicode(i18nStr);
5
+ export default (i18NKeys = []) => Component => {
6
+ class HOCI18N extends React.Component {
7
+ constructor(props) {
8
+ super(props);
9
+ this.getI18NValue = this.getI18NValue.bind(this);
10
+ }
11
+ getI18NValue(key) {
12
+ const {
13
+ i18n
14
+ } = this.context || {};
15
+ if (typeof i18n === 'undefined') {
16
+ return key;
30
17
  }
31
-
32
- render() {
33
- let i18nProps = i18NKeys.reduce((result, key) => {
34
- if (this.props[key]) {
35
- result[key] = this.getI18NValue(this.props[key]);
36
- }
37
-
38
- return result;
39
- }, {});
40
- return /*#__PURE__*/React.createElement(Component, { ...this.props,
41
- ...i18nProps
42
- });
18
+ let i18nStr = i18n[key];
19
+ if (i18nStr === undefined) {
20
+ return key;
43
21
  }
44
-
22
+ return unescapeUnicode(i18nStr);
23
+ }
24
+ render() {
25
+ let i18nProps = i18NKeys.reduce((result, key) => {
26
+ if (this.props[key]) {
27
+ result[key] = this.getI18NValue(this.props[key]);
28
+ }
29
+ return result;
30
+ }, {});
31
+ return /*#__PURE__*/React.createElement(Component, {
32
+ ...this.props,
33
+ ...i18nProps
34
+ });
45
35
  }
46
-
47
- HOCI18N.contextType = I18NContext;
48
- return HOCI18N;
49
- };
50
- });
36
+ }
37
+ HOCI18N.contextType = I18NContext;
38
+ return HOCI18N;
39
+ };
@@ -9,7 +9,6 @@ export default class I18N extends React.Component {
9
9
  this.getI18NValue = this.getI18NValue.bind(this);
10
10
  this.createElement = this.createElement.bind(this);
11
11
  }
12
-
13
12
  getI18NValue() {
14
13
  const {
15
14
  i18NKey: key,
@@ -18,35 +17,28 @@ export default class I18N extends React.Component {
18
17
  const {
19
18
  i18n
20
19
  } = this.context || {};
21
-
22
20
  if (typeof i18n === 'undefined') {
23
21
  return key;
24
22
  }
25
-
26
23
  let i18nStr = i18n[key];
27
-
28
24
  if (i18nStr === undefined) {
29
25
  return key;
30
26
  }
31
-
32
27
  i18nStr = replaceI18NValuesWithRegex(i18nStr, values);
33
28
  return unescapeUnicode(i18nStr);
34
29
  }
35
-
36
30
  createElement() {
37
31
  const props = Object.keys(this.props).reduce((result, nextKey) => {
38
32
  if (nextKey != 'i18NKey' && nextKey != 'tag' && nextKey != 'values' && nextKey != 'isHtml' && nextKey != 'dataId') {
39
33
  result[nextKey] = this.props[nextKey];
40
34
  }
41
-
42
35
  return result;
43
- }, {}); //const child=this.getI18NValue();
44
-
36
+ }, {});
37
+ //const child=this.getI18NValue();
45
38
  if (this.props.dataId) {
46
39
  props['data-id'] = this.props.dataId;
47
40
  props['data-test-id'] = this.props.dataId;
48
41
  }
49
-
50
42
  if (this.props.isHtml) {
51
43
  let dangerouslySetInnerHTML = {
52
44
  __html: HTMLPurifier.sanitize(this.getI18NValue())
@@ -55,14 +47,11 @@ export default class I18N extends React.Component {
55
47
  dangerouslySetInnerHTML
56
48
  }));
57
49
  }
58
-
59
50
  return /*#__PURE__*/React.createElement(this.props.tag, props, this.getI18NValue());
60
51
  }
61
-
62
52
  render() {
63
53
  return this.createElement();
64
54
  }
65
-
66
55
  }
67
56
  I18N.propTypes = {
68
57
  i18NKey: PropTypes.string.isRequired,