@zohodesk/i18n 1.0.0-beta.4 → 1.0.0-beta.41-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.
- package/README.md +130 -4
- package/docs/murphy/01-MURPHY_OVERVIEW.md +148 -0
- package/docs/murphy/02-MURPHY_ARCHITECTURE.md +283 -0
- package/docs/murphy/03-MURPHY_BACKEND_CONFIG.md +337 -0
- package/docs/murphy/04-MURPHY_FRONTEND_INIT.md +437 -0
- package/docs/murphy/05-MURPHY_DESK_CLIENT_USAGE.md +467 -0
- package/docs/murphy/06-MURPHY_I18N_INTEGRATION.md +402 -0
- package/docs/murphy/07-MURPHY_WHY_I18N_APPROACH.md +391 -0
- package/es/I18NContext.js +1 -2
- package/es/components/DateTimeDiffFormat.js +185 -209
- package/es/components/FormatText.js +7 -27
- package/es/components/HOCI18N.js +35 -58
- package/es/components/I18N.js +48 -74
- package/es/components/I18NProvider.js +59 -93
- package/es/components/PluralFormat.js +28 -51
- package/es/components/UserTimeDiffFormat.js +66 -81
- package/es/components/__tests__/DateTimeDiffFormat.spec.js +810 -663
- package/es/components/__tests__/FormatText.spec.js +22 -19
- package/es/components/__tests__/HOCI18N.spec.js +19 -25
- package/es/components/__tests__/I18N.spec.js +23 -21
- package/es/components/__tests__/I18NProvider.spec.js +38 -47
- package/es/components/__tests__/PluralFormat.spec.js +23 -20
- package/es/components/__tests__/UserTimeDiffFormat.spec.js +1259 -1110
- package/es/index.js +13 -15
- package/es/utils/__tests__/jsxTranslations.spec.js +170 -0
- package/es/utils/errorReporter.js +41 -0
- package/es/utils/index.js +543 -0
- package/es/utils/jsxTranslations.js +185 -0
- package/lib/I18NContext.js +5 -10
- package/lib/components/DateTimeDiffFormat.js +131 -146
- package/lib/components/FormatText.js +29 -42
- package/lib/components/HOCI18N.js +34 -45
- package/lib/components/I18N.js +46 -57
- package/lib/components/I18NProvider.js +72 -95
- package/lib/components/PluralFormat.js +39 -55
- package/lib/components/UserTimeDiffFormat.js +76 -84
- package/lib/components/__tests__/DateTimeDiffFormat.spec.js +751 -635
- package/lib/components/__tests__/FormatText.spec.js +21 -30
- package/lib/components/__tests__/HOCI18N.spec.js +22 -41
- package/lib/components/__tests__/I18N.spec.js +20 -33
- package/lib/components/__tests__/I18NProvider.spec.js +40 -63
- package/lib/components/__tests__/PluralFormat.spec.js +23 -35
- package/lib/components/__tests__/UserTimeDiffFormat.spec.js +1195 -1046
- package/lib/index.js +83 -104
- package/lib/utils/__tests__/jsxTranslations.spec.js +172 -0
- package/lib/utils/errorReporter.js +49 -0
- package/lib/utils/index.js +583 -0
- package/lib/utils/jsxTranslations.js +216 -0
- package/package.json +4 -3
- package/src/components/DateTimeDiffFormat.js +84 -55
- package/src/components/I18N.js +2 -0
- package/src/components/I18NProvider.js +44 -33
- package/src/components/UserTimeDiffFormat.js +22 -18
- package/src/index.js +12 -9
- package/src/utils/__tests__/jsxTranslations.spec.js +213 -0
- package/src/utils/errorReporter.js +48 -0
- package/src/utils/index.js +644 -0
- package/src/utils/jsxTranslations.js +199 -0
- package/es/components/NewDateFormat.js +0 -50
- package/es/offset.js +0 -629
- package/es/timezones.js +0 -118
- package/es/utils.js +0 -621
- package/lib/components/NewDateFormat.js +0 -68
- package/lib/offset.js +0 -634
- package/lib/timezones.js +0 -129
- package/lib/utils.js +0 -651
- package/src/components/NewDateFormat.js +0 -60
- package/src/offset.js +0 -629
- package/src/timezones.js +0 -113
- package/src/utils.js +0 -648
|
@@ -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
|
package/es/I18NContext.js
CHANGED