@zohodesk/i18n 1.0.0-beta.34 → 1.0.0-beta.36-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 +35 -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 +44 -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 +41 -0
  50. package/src/utils/index.js +8 -1
  51. package/src/utils/jsxTranslations.js +8 -1
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
 
3
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
@@ -10,42 +11,30 @@ exports.placeComponentForTags = placeComponentForTags;
10
11
  exports.prepareI18NFunc = prepareI18NFunc;
11
12
  exports.replaceWithComponentPlaceHolder = replaceWithComponentPlaceHolder;
12
13
  exports.splitMatchedExp = splitMatchedExp;
13
-
14
14
  var _react = _interopRequireDefault(require("react"));
15
-
16
15
  var _index = require("./index");
17
-
18
16
  var _I18NProvider = require("../components/I18NProvider");
19
-
20
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
21
-
22
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
23
-
24
- function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
25
-
17
+ var _errorReporter = require("./errorReporter");
18
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
19
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
20
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
21
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
22
+ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
26
23
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
27
-
28
- function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
29
-
30
- function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
31
-
32
- function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
33
-
34
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
35
-
36
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
37
-
24
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
25
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
26
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
27
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
28
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
38
29
  function splitMatchedExp(_ref) {
39
30
  var expression = _ref.expression,
40
- charLenToOmit = _ref.charLenToOmit,
41
- string = _ref.string;
31
+ charLenToOmit = _ref.charLenToOmit,
32
+ string = _ref.string;
42
33
  var splitString = string.split(new RegExp(expression, 'g'));
43
34
  var matchedExpAll = string.matchAll(new RegExp(expression, 'g'));
44
35
  var matchedExpKeys = [];
45
-
46
36
  var _iterator = _createForOfIteratorHelper(matchedExpAll),
47
- _step;
48
-
37
+ _step;
49
38
  try {
50
39
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
51
40
  var match = _step.value;
@@ -57,42 +46,36 @@ function splitMatchedExp(_ref) {
57
46
  } finally {
58
47
  _iterator.f();
59
48
  }
60
-
61
49
  return {
62
50
  splitString: splitString,
63
51
  matchedExpKeys: matchedExpKeys
64
52
  };
65
53
  }
66
-
67
54
  function generateChildren(_ref2) {
68
55
  var children = _ref2.children,
69
- child = _ref2.child;
56
+ child = _ref2.child;
70
57
  var newChildren = [],
71
- stringPlaceHolders = {};
72
-
58
+ stringPlaceHolders = {};
73
59
  var handleString = function handleString(string) {
74
60
  if (string) {
75
61
  var _splitMatchedExp = splitMatchedExp({
76
- expression: '{[0-9]+?}',
77
- charLenToOmit: 1,
78
- string: string
79
- }),
80
- splitString = _splitMatchedExp.splitString,
81
- matchedExpKeys = _splitMatchedExp.matchedExpKeys;
82
-
62
+ expression: '{[0-9]+?}',
63
+ charLenToOmit: 1,
64
+ string: string
65
+ }),
66
+ splitString = _splitMatchedExp.splitString,
67
+ matchedExpKeys = _splitMatchedExp.matchedExpKeys;
83
68
  stringPlaceHolders[newChildren.length] = matchedExpKeys;
84
69
  newChildren.push(splitString);
85
70
  }
86
71
  };
87
-
88
72
  var _splitMatchedExp2 = splitMatchedExp({
89
- expression: '<[A-Za-z0-9]+?>',
90
- charLenToOmit: 1,
91
- string: child
92
- }),
93
- splitChild = _splitMatchedExp2.splitString,
94
- childrenKeys = _splitMatchedExp2.matchedExpKeys;
95
-
73
+ expression: '<[A-Za-z0-9]+?>',
74
+ charLenToOmit: 1,
75
+ string: child
76
+ }),
77
+ splitChild = _splitMatchedExp2.splitString,
78
+ childrenKeys = _splitMatchedExp2.matchedExpKeys;
96
79
  childrenKeys.forEach(function (childKey, childIndex) {
97
80
  var matchedChild = splitChild[childIndex];
98
81
  handleString(matchedChild);
@@ -104,27 +87,23 @@ function generateChildren(_ref2) {
104
87
  stringPlaceHolders: stringPlaceHolders
105
88
  };
106
89
  }
107
-
108
90
  function createElement() {
109
91
  var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
110
- componentId = _ref3.componentId,
111
- _ref3$children = _ref3.children,
112
- children = _ref3$children === void 0 ? [] : _ref3$children,
113
- _ref3$stringPlaceHold = _ref3.stringPlaceHolders,
114
- stringPlaceHolders = _ref3$stringPlaceHold === void 0 ? {} : _ref3$stringPlaceHold;
115
-
92
+ componentId = _ref3.componentId,
93
+ _ref3$children = _ref3.children,
94
+ children = _ref3$children === void 0 ? [] : _ref3$children,
95
+ _ref3$stringPlaceHold = _ref3.stringPlaceHolders,
96
+ stringPlaceHolders = _ref3$stringPlaceHold === void 0 ? {} : _ref3$stringPlaceHold;
116
97
  return function () {
117
98
  var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
118
- _ref4$components = _ref4.components,
119
- components = _ref4$components === void 0 ? {} : _ref4$components,
120
- _ref4$values = _ref4.values,
121
- values = _ref4$values === void 0 ? [] : _ref4$values;
122
-
99
+ _ref4$components = _ref4.components,
100
+ components = _ref4$components === void 0 ? {} : _ref4$components,
101
+ _ref4$values = _ref4.values,
102
+ values = _ref4$values === void 0 ? [] : _ref4$values;
123
103
  var _ref5 = components[componentId] || {},
124
- _ref5$type = _ref5.type,
125
- type = _ref5$type === void 0 ? _react["default"].Fragment : _ref5$type,
126
- props = _ref5.props;
127
-
104
+ _ref5$type = _ref5.type,
105
+ type = _ref5$type === void 0 ? _react["default"].Fragment : _ref5$type,
106
+ props = _ref5.props;
128
107
  var childElements = children.map(function (child, index) {
129
108
  if (typeof child === 'function') {
130
109
  return child({
@@ -132,60 +111,49 @@ function createElement() {
132
111
  values: values
133
112
  });
134
113
  }
135
-
136
114
  var string = '',
137
- stringIndex = 0;
115
+ stringIndex = 0;
138
116
  (stringPlaceHolders[index] || []).map(function (stringId, index) {
139
117
  if (child[index]) {
140
118
  string += child[index];
141
119
  }
142
-
143
120
  string += values[stringId];
144
121
  stringIndex++;
145
122
  });
146
-
147
123
  if (child[stringIndex]) {
148
124
  string += child[stringIndex];
149
125
  }
150
-
151
126
  return string;
152
127
  });
153
128
  return /*#__PURE__*/_react["default"].createElement.apply(_react["default"], [type, props].concat(_toConsumableArray(childElements)));
154
129
  };
155
130
  }
156
-
157
131
  ;
158
-
159
132
  function replaceWithComponentPlaceHolder(_ref6) {
160
133
  var componentId = _ref6.componentId,
161
- i18nKey = _ref6.i18nKey,
162
- childrenLength = _ref6.childrenLength;
134
+ i18nKey = _ref6.i18nKey,
135
+ childrenLength = _ref6.childrenLength;
163
136
  var closingTagIndex = i18nKey.indexOf("</".concat(componentId, ">"));
164
137
  var childWithOpenTag = i18nKey.substring(0, closingTagIndex);
165
138
  var openTagIndex = childWithOpenTag.lastIndexOf("<".concat(componentId, ">"));
166
139
  return i18nKey.substring(0, openTagIndex) + "<0".concat(childrenLength).concat(componentId, ">") + i18nKey.substring(closingTagIndex + "".concat(componentId).length + 3);
167
140
  }
168
-
169
141
  function prepareI18NFunc() {
170
142
  var _ref7 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
171
- i18nKey = _ref7.i18nKey,
172
- _ref7$children = _ref7.children,
173
- children = _ref7$children === void 0 ? {} : _ref7$children;
174
-
143
+ i18nKey = _ref7.i18nKey,
144
+ _ref7$children = _ref7.children,
145
+ children = _ref7$children === void 0 ? {} : _ref7$children;
175
146
  var componentIdMatch = i18nKey.match(/<\/[A-Za-z0-9]+?>/);
176
-
177
147
  if (componentIdMatch) {
178
148
  var componentId = componentIdMatch[0].substring(2, componentIdMatch[0].length - 1);
179
149
  var childWithOpenTag = (i18nKey.match(new RegExp("(.*?)(?=</".concat(componentId, ">)"))) || [])[0] || '';
180
150
  var child = childWithOpenTag.split("<".concat(componentId, ">")).pop();
181
-
182
151
  var _generateChildren = generateChildren({
183
- children: children,
184
- child: child
185
- }),
186
- _newChildren = _generateChildren.newChildren,
187
- _stringPlaceHolders = _generateChildren.stringPlaceHolders;
188
-
152
+ children: children,
153
+ child: child
154
+ }),
155
+ _newChildren = _generateChildren.newChildren,
156
+ _stringPlaceHolders = _generateChildren.stringPlaceHolders;
189
157
  var childrenLength = Object.keys(children).length;
190
158
  children["0".concat(childrenLength).concat(componentId)] = createElement({
191
159
  componentId: componentId,
@@ -202,21 +170,18 @@ function prepareI18NFunc() {
202
170
  children: children
203
171
  });
204
172
  }
205
-
206
173
  var _generateChildren2 = generateChildren({
207
- child: i18nKey,
208
- children: children
209
- }),
210
- newChildren = _generateChildren2.newChildren,
211
- stringPlaceHolders = _generateChildren2.stringPlaceHolders;
212
-
174
+ child: i18nKey,
175
+ children: children
176
+ }),
177
+ newChildren = _generateChildren2.newChildren,
178
+ stringPlaceHolders = _generateChildren2.stringPlaceHolders;
213
179
  return createElement({
214
180
  componentId: -1,
215
181
  children: newChildren,
216
182
  stringPlaceHolders: stringPlaceHolders
217
183
  });
218
184
  }
219
-
220
185
  function i18nMechanismForComponents(i18nValue, key) {
221
186
  if (typeof i18nValue === 'string') {
222
187
  i18nValue = (0, _index.unescapeUnicode)(i18nValue);
@@ -226,30 +191,26 @@ function i18nMechanismForComponents(i18nValue, key) {
226
191
  window.loadI18nChunk && window.loadI18nChunk(_defineProperty({}, key, value));
227
192
  i18nValue = value;
228
193
  }
229
-
230
194
  return i18nValue;
231
195
  }
232
-
233
196
  function placeComponentForTags(i18nValue) {
234
197
  var value = _I18NProvider.i18NProviderUtils.getI18NComponent(i18nValue);
235
-
236
198
  return i18nMechanismForComponents(value, value);
237
199
  }
238
-
239
200
  function getI18NComponent(i18n) {
240
201
  if (typeof i18n === 'undefined') {
202
+ (0, _errorReporter.reportI18NError)(_errorReporter.I18N_ERROR_TYPES.UNDEFINED_OBJECT, 'i18n_object_jsx');
241
203
  return function (key) {
242
204
  return key;
243
205
  };
244
206
  }
245
-
246
207
  return function (key) {
247
208
  var i18nStr = i18n[key];
248
-
249
209
  if (i18nStr === undefined) {
250
- return key;
210
+ var isNumeric = /^\d+$/.test(key);
211
+ (0, _errorReporter.reportI18NError)(isNumeric ? _errorReporter.I18N_ERROR_TYPES.NUMERIC_FALLBACK : _errorReporter.I18N_ERROR_TYPES.MISSING_KEY, key);
212
+ return (0, _errorReporter.getFallbackText)(key);
251
213
  }
252
-
253
214
  return i18nMechanismForComponents(i18nStr, key);
254
215
  };
255
216
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zohodesk/i18n",
3
- "version": "1.0.0-beta.34",
3
+ "version": "1.0.0-beta.36-murphy",
4
4
  "main": "lib/index",
5
5
  "module": "es/index.js",
6
6
  "jsnext:main": "es/index.js",
package/src/index.js CHANGED
@@ -21,6 +21,11 @@ export {
21
21
  monthi18n,
22
22
  timei18n
23
23
  } from './utils';
24
+ export {
25
+ reportI18NError,
26
+ clearReportedKeys,
27
+ I18N_ERROR_TYPES
28
+ } from './utils/errorReporter';
24
29
  import { getI18NValue as getI18NValue1 } from './utils';
25
30
  export { I18NContext } from './I18NContext';
26
31
  export {
@@ -0,0 +1,41 @@
1
+ export const I18N_ERROR_TYPES = {
2
+ UNDEFINED_OBJECT: 'I18N_UNDEFINED_OBJECT',
3
+ MISSING_KEY: 'I18N_MISSING_KEY',
4
+ NUMERIC_FALLBACK: 'I18N_NUMERIC_FALLBACK'
5
+ };
6
+
7
+ const reportedKeys = new Set();
8
+
9
+ function isMurphyAvailable() {
10
+ return typeof murphy !== 'undefined' && typeof murphy.error === 'function';
11
+ }
12
+
13
+ export function reportI18NError(type, key) {
14
+ const dedupeKey = `${type}:${key}`;
15
+ if (reportedKeys.has(dedupeKey)) {
16
+ return;
17
+ }
18
+ reportedKeys.add(dedupeKey);
19
+
20
+ if (isMurphyAvailable()) {
21
+ const error = new Error(`i18n ${type}: ${key}`);
22
+ error.name = type;
23
+
24
+ murphy.error(error, undefined, {
25
+ customTags: {
26
+ errorType: type,
27
+ i18nKey: key,
28
+ category: 'i18n'
29
+ },
30
+ preventClientGrouping: true
31
+ });
32
+ }
33
+ }
34
+ export function clearReportedKeys() {
35
+ reportedKeys.clear();
36
+ }
37
+
38
+ export function getFallbackText(key) {
39
+ const isNumeric = /^\d+$/.test(key);
40
+ return isNumeric ? `text.unavailable.${key}` : key;
41
+ }
@@ -2,6 +2,7 @@ import datetime from '@zohodesk/datetimejs';
2
2
  import {
3
3
  i18NProviderUtils
4
4
  } from '../components/I18NProvider';
5
+ import { reportI18NError, I18N_ERROR_TYPES, getFallbackText } from './errorReporter';
5
6
 
6
7
  export const dayi18n = {
7
8
  'Sun': 'deskreact.calendar.daynameshort.sunday',
@@ -290,6 +291,7 @@ export function getLocalizedValue({
290
291
  }
291
292
  export function getI18NValue(i18n) {
292
293
  if (typeof i18n === 'undefined') {
294
+ reportI18NError(I18N_ERROR_TYPES.UNDEFINED_OBJECT, 'i18n_object');
293
295
  return (key) => key;
294
296
  }
295
297
  return (key, values, localizedProps) => {
@@ -297,7 +299,12 @@ export function getI18NValue(i18n) {
297
299
  const finalKey = getMappedKey(key);
298
300
  let i18nStr = i18n[finalKey];
299
301
  if (i18nStr === undefined) {
300
- return localizedValue || finalKey;
302
+ const isNumeric = /^\d+$/.test(finalKey);
303
+ reportI18NError(
304
+ isNumeric ? I18N_ERROR_TYPES.NUMERIC_FALLBACK : I18N_ERROR_TYPES.MISSING_KEY,
305
+ finalKey
306
+ );
307
+ return localizedValue || getFallbackText(finalKey);
301
308
  }
302
309
  i18nStr = replaceI18NValuesWithRegex(i18nStr, values);
303
310
  return localizedValue || unescapeUnicode(i18nStr);
@@ -5,6 +5,7 @@ import {
5
5
  import {
6
6
  i18NProviderUtils
7
7
  } from "../components/I18NProvider";
8
+ import { reportI18NError, I18N_ERROR_TYPES, getFallbackText } from './errorReporter';
8
9
 
9
10
  export function splitMatchedExp({
10
11
  expression,
@@ -180,12 +181,18 @@ export function placeComponentForTags(i18nValue) {
180
181
 
181
182
  export function getI18NComponent(i18n) {
182
183
  if(typeof i18n === 'undefined') {
184
+ reportI18NError(I18N_ERROR_TYPES.UNDEFINED_OBJECT, 'i18n_object_jsx');
183
185
  return (key) => key;
184
186
  }
185
187
  return (key) => {
186
188
  let i18nStr = i18n[key];
187
189
  if (i18nStr === undefined) {
188
- return key;
190
+ const isNumeric = /^\d+$/.test(key);
191
+ reportI18NError(
192
+ isNumeric ? I18N_ERROR_TYPES.NUMERIC_FALLBACK : I18N_ERROR_TYPES.MISSING_KEY,
193
+ key
194
+ );
195
+ return getFallbackText(key);
189
196
  }
190
197
  return i18nMechanismForComponents(i18nStr, key);
191
198
  }