@dialpad/i18n 1.16.0

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/.eslintignore ADDED
@@ -0,0 +1 @@
1
+ dist
package/.eslintrc.cjs ADDED
@@ -0,0 +1,12 @@
1
+ module.exports = {
2
+ extends: ['@dialpad'],
3
+ overrides: [
4
+ {
5
+ files: ['*.ts'],
6
+ parserOptions: {
7
+ project: ['./eslint-tsconfig.json'],
8
+ tsconfigRootDir: __dirname,
9
+ },
10
+ },
11
+ ],
12
+ };
@@ -0,0 +1,3 @@
1
+ dist
2
+ CHANGELOG.md
3
+ eslint_report.*
package/CHANGELOG.md ADDED
@@ -0,0 +1,34 @@
1
+ ## [@dialpad/i18n-v1.16.0](https://github.com/dialpad/web-clients/compare/@dialpad/i18n-v1.15.0...@dialpad/i18n-v1.16.0) (2025-07-02)
2
+
3
+
4
+ ### Features
5
+
6
+ * add localstorage wrapper to i18n ([#1321](https://github.com/dialpad/web-clients/issues/1321)) ([1a34a80](https://github.com/dialpad/web-clients/commit/1a34a80c035079decf2670be1bb43a1671aa97eb))
7
+
8
+ ## [@dialpad/i18n-v1.15.0](https://github.com/dialpad/web-clients/compare/@dialpad/i18n-v1.14.1...@dialpad/i18n-v1.15.0) (2025-05-21)
9
+
10
+
11
+ ### Features
12
+
13
+ * **infra-7827:** improvements to install in dp1 and to add sources on the fly ([#1273](https://github.com/dialpad/web-clients/issues/1273)) ([8ed826b](https://github.com/dialpad/web-clients/commit/8ed826b8f404b699a4297f25fa5e536bc89bf1c6))
14
+
15
+ ## [@dialpad/i18n-v1.14.1](https://github.com/dialpad/web-clients/compare/@dialpad/i18n-v1.14.0...@dialpad/i18n-v1.14.1) (2025-04-01)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * add repository field to package json ([#1241](https://github.com/dialpad/web-clients/issues/1241)) ([6db2cdf](https://github.com/dialpad/web-clients/commit/6db2cdf23ee3e2ee7661a878f122c169bc0ceead))
21
+
22
+ ## [@dialpad/i18n-v1.14.0](https://github.com/dialpad/web-clients/compare/@dialpad/i18n-v1.13.0...@dialpad/i18n-v1.14.0) (2025-03-05)
23
+
24
+
25
+ ### Features
26
+
27
+ * **infra-7804:** add translations screenshots flows to upload and check ([#1139](https://github.com/dialpad/web-clients/issues/1139)) ([1aa5a79](https://github.com/dialpad/web-clients/commit/1aa5a790e4485d45ba9d923bb09d6a5186d22621))
28
+
29
+ ## [@dialpad/i18n-v1.13.0](https://github.com/dialpad/web-clients/compare/@dialpad/i18n-v1.12.1...@dialpad/i18n-v1.13.0) (2025-01-23)
30
+
31
+
32
+ ### Features
33
+
34
+ * **infra-7599:** add vue2 and vue3 compatibility ([#1126](https://github.com/dialpad/web-clients/issues/1126)) ([f0d016b](https://github.com/dialpad/web-clients/commit/f0d016bfe7bc9f22fd0fc594e303b48487b7cca8))
package/README.md ADDED
@@ -0,0 +1,533 @@
1
+ # i18n (Vue 3 compatible)
2
+
3
+ ## Introduction
4
+
5
+ This package contains all the logic needed to take care the i18n of a Dialpad
6
+ application extending from the common logic existing in the base locale manager
7
+ that you can find about on the
8
+ [i18n-services documentation](../i18n-services/README.md), based on different
9
+ bundle sources.
10
+
11
+ ## How it works?
12
+
13
+ There are essentially two main concepts behind the scenes:
14
+
15
+ ### LocaleManager
16
+
17
+ The LocaleManager extends the BaseLocaleManager to oversee the
18
+ internationalization (i18n) in a Vue3.js application using the
19
+ [Fluent localization framework](https://projectfluent.org/). Its
20
+ responsibilities include:
21
+
22
+ - **Loading and caching translation bundles:** Manages the `.ftl` data, which
23
+ maps keys to text for each locale.
24
+ - **Switching the current locale:** Provides methods to change the active
25
+ language dynamically.
26
+ - **Handling bundle namespaces:** Manages potential duplicate bundle requests
27
+ from multiple sources, though this feature is still being refined.
28
+ - **Initializing the Vue plugin:** Exposes translation methods (`$t`, `$ta`) to
29
+ `Vue` templates, enabling localized content within the application.
30
+
31
+ ### BundleSource
32
+
33
+ The second key concept is the BundleSource interface, which abstracts the
34
+ loading and management of localization resources. This interface has two primary
35
+ implementations: `RawBundleSource` and `HTTPBundleSource`, each designed for
36
+ different use cases.
37
+
38
+ - `RawBundleSource`: This implementation handles localization resources defined
39
+ within the application. It organizes these resources defined directly in the
40
+ application, and imported directly at runtime (for example, using
41
+ `import(./[locale].ftl`). This approach is ideal for applications with mostly
42
+ static content.
43
+
44
+ - `HTTPBundleSource`: This implementation fetches localization resources
45
+ dynamically from a server. It caches these resources locally, allowing for
46
+ efficient access while still being flexible enough to load translations on
47
+ demand.
48
+
49
+ **Disclaimer:** _Both implementations are provisional and may change as we
50
+ better understand our needs. Currently, `RawBundleSource` is the preferred
51
+ option for most applications._
52
+
53
+ #### Synchronous Resource Loading with [builtResources](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-services/bundle/bundle-source/raw.js:28:2-34:3)
54
+
55
+ While the
56
+ [dynamicResources](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-services/bundle/bundle-source/raw.js:2:2-17:3)
57
+ method is used for asynchronously loading resources, the
58
+ [RawBundleSource](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-services/bundle/bundle-source/raw.d.ts:14:0-30:1)
59
+ class also provides a
60
+ [builtResources](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-services/bundle/bundle-source/raw.js:28:2-34:3)
61
+ method for synchronous resource loading. This is useful when you have the
62
+ localization resources available at compile time and prefer to import them
63
+ directly without dealing with promises.
64
+
65
+ ##### How to use [builtResources](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-services/bundle/bundle-source/raw.js:28:2-34:3)
66
+
67
+ Instead of dynamically importing `.ftl` files, you can import them directly and
68
+ use the
69
+ [builtResources](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-services/bundle/bundle-source/raw.js:28:2-34:3)
70
+ method to process the resources. Here's an example:
71
+
72
+ ```typescript
73
+ import { RawBundleSource } from '@dialpad/i18n-services';
74
+ // Import your .ftl files directly
75
+ import enUSResource from './locales/en-US.ftl';
76
+ import esResource from './locales/es.ftl';
77
+
78
+ // Create an array of BuiltResource objects
79
+ const builtResourcesArray: BuiltResource[] = [
80
+ ['en-US', 'namespace', enUSResource],
81
+ ['es', 'namespace', esResource],
82
+ // ... add other locales and namespaces as needed
83
+ ];
84
+
85
+ // Convert BuiltResource objects to Resource objects using builtResources
86
+ const resources: Resource[] =
87
+ RawBundleSource.builtResources(builtResourcesArray);
88
+
89
+ // Now, resources can be used to instantiate RawBundleSource or for any other purpose
90
+ const bundleSource = new RawBundleSource({ resources });
91
+ ```
92
+
93
+ ## Setup
94
+
95
+ ### Installation
96
+
97
+ ```sh
98
+ pnpm add @dialpad/i18n
99
+ ```
100
+
101
+ ### Configuration - Static resources
102
+
103
+ ### Integrating LocaleManager with Vue using the [install](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:43:2-55:3) Method
104
+
105
+ When using `LocaleManager` within a Vue application, **(especially in the
106
+ context of a library, you should be aware that install needs to receive a
107
+ non-default namespace value)** it's important to properly integrate it using the
108
+ [install](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:43:2-55:3)
109
+ method. This method registers `LocaleManager` with the Vue instance, allowing
110
+ for global access to localization functionalities across the application.
111
+
112
+ #### Usage of [install](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:43:2-55:3)
113
+
114
+ After creating an instance of `LocaleManager`, you must call the
115
+ [install](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:43:2-55:3)
116
+ method. This method accepts an optional `namespace` parameter, which is
117
+ particularly useful when you are developing a library and need to avoid
118
+ conflicts with other potential instances of `LocaleManager` in the consumer's
119
+ environment.
120
+
121
+ By using different namespaces, you can have multiple instances of
122
+ `LocaleManager` available globally in Vue. This is ideal for libraries that may
123
+ be used in conjunction with other Vue plugins or in larger applications where
124
+ scoped localization management is required.
125
+
126
+ ##### Parameters
127
+
128
+ - `namespace`: (Optional) The namespace under which the `LocaleManager` will be
129
+ registered. Defaults to `'default'` if no namespace is provided.
130
+
131
+ ##### Example
132
+
133
+ ```typescript
134
+ import Vue from 'vue';
135
+ import { LocaleManager } from '@dialpad/i18n-vue2';
136
+
137
+ // Create a LocaleManager instance with your configuration options
138
+ const localeManager = new LocaleManager({
139
+ // ... configuration options, see on Dynamic resources configuration section
140
+ });
141
+
142
+ // Install the LocaleManager with a specific namespace to avoid conflicts
143
+ localeManager.install('my-namespace');
144
+
145
+ // Your library's users can now access the LocaleManager instance globally in Vue
146
+ new Vue({
147
+ // ... other options
148
+ }).$mount('#app');
149
+ ```
150
+
151
+ ### Configuration - Dynamic resources
152
+
153
+ We recommend you to include this in your own composable that handle every locale
154
+ and i18n set up logic, i.e.:
155
+
156
+ ```ts
157
+ //src/localization/i18n.ts
158
+ import type { App } from 'vue';
159
+ import { LocaleManager, RawBundleSource } from '@dialpad/i18n';
160
+
161
+ export async function hostI18NManager({
162
+ vueApp,
163
+ }: {
164
+ vueApp: App;
165
+ }): Promise<void> {
166
+ const bundleSource = new RawBundleSource({
167
+ resources: await RawBundleSource.dynamicResources([
168
+ ['en-US', 'your-app', import('./en-US.ftl?raw')],
169
+ ]),
170
+ });
171
+
172
+ const manager = new LocaleManager({
173
+ bundleSource,
174
+ preferredLocale: 'en-US', // optional
175
+ allowedLocales: ['en-US'], // optional
176
+ fallbackLocale: 'en-US',
177
+ namespaces: ['your-app'],
178
+ });
179
+
180
+ await manager.ready;
181
+
182
+ vueApp.use(manager);
183
+ }
184
+ ```
185
+
186
+ **Important note:** let's say that you have more than one `allowedLocales`, or
187
+ that your `fallbackLocale`/`preferredLocale` is different from what you're
188
+ specifying on the `allowedLocales` prop to the `LocaleManager` instance. In
189
+ those cases you need to verify that you have specified a Bundle resource for
190
+ each locale, in order to have them working properly, i.e.:
191
+
192
+ ```ts
193
+ //src/localization/i18n.ts
194
+ import type { App } from 'vue';
195
+ import { LocaleManager, RawBundleSource } from '@dialpad/i18n';
196
+
197
+ export async function hostI18NManager({
198
+ vueApp,
199
+ }: {
200
+ vueApp: App;
201
+ }): Promise<void> {
202
+ const bundleSource = new RawBundleSource({
203
+ resources: await RawBundleSource.dynamicResources([
204
+ // You must **always** have one resource per locale.
205
+ ['dp-DP', 'your-app', import('./dp-DP.ftl?raw')],
206
+ // This one is for the `fallbackLocale`
207
+ ['en-US', 'your-app', import('./en-US.ftl?raw')],
208
+ ]),
209
+ });
210
+
211
+ const manager = new LocaleManager({
212
+ bundleSource,
213
+ // I'm using Dialpadistan as my locale
214
+ preferredLocale: 'dp-DP',
215
+ // But my fallback is en-US (if it was part of the locales this is the same concept, **you need to add one resource per locale**)
216
+ fallbackLocale: 'en-US',
217
+ namespaces: ['your-app'],
218
+ });
219
+
220
+ await manager.ready;
221
+
222
+ vueApp.use(manager);
223
+ }
224
+ ```
225
+
226
+ After this, you should plug this into your `main.ts`. You will call it like:
227
+
228
+ ```ts
229
+ // src/main.ts
230
+
231
+ import { createHost } from '@dialpad/host-entry';
232
+ import { hostI18NManager } from './localization/i18n';
233
+ import { hostEnv } from './constants';
234
+
235
+ await createHost(hostEnv)
236
+ // ... all your config
237
+ .vueCreated(hostI18NManager)
238
+ // ... some other config
239
+ .start();
240
+ ```
241
+
242
+ ## Usage
243
+
244
+ ### User's locale selection criteria
245
+
246
+ You will find that this API is (and should always be) the same as the
247
+ [i18n-vue2 tool](../i18n-vue2/README.md).
248
+
249
+ When instantiating the LocaleManager (or when calling setI18N), the
250
+ preferredLocale and allowedLocales parameters are optional. BUT this is the
251
+ following criteria to select it.
252
+
253
+ If preferredLocale param is provided, use that. If allowedLocales param is
254
+ provided, use the first one. If localStorage contains the previously-used value,
255
+ use that. If navigator.language is available, use that. Use the fallbackLocale.
256
+
257
+ First of all you need to understand he difference between `$t` and `$ta`, which
258
+ mainly lies in their outputs:
259
+
260
+ ### useI18N() hook API
261
+
262
+ There are three main functions exported: `$t`, `$ta`, and `setI18N()`, and two
263
+ exported values: `currentLocale` and `allowedLocales`.
264
+
265
+ (Keep in mind that you should have a fluent file (en-US.ftl in this case)
266
+ following the Fluent rules.)
267
+
268
+ #### `$t`
269
+
270
+ Returns a translated string based on a key and optional variables. It’s used for
271
+ simple text translations.
272
+
273
+ ```ftl
274
+ # src/localization/en-US.ftl
275
+ PARAGRAPH_KEY = Amazing paragraph, { $name }
276
+ ```
277
+
278
+ ```ts
279
+ // Component file
280
+ const greeting = $t('PARAGRAPH_KEY', { name: 'John' });
281
+ // Output: "Amazing paragraph, John"
282
+ ```
283
+
284
+ #### `$ta`
285
+
286
+ Returns an object containing translated attributes to pass directly as props to
287
+ components, it can contain aria-label, title, etc, rather than just a plain
288
+ text. It’s useful for handling element attributes in the UI.
289
+
290
+ ```ftl
291
+ # src/localization/en-US.ftl
292
+ BUTTON_NAME =
293
+ .aria-label = { $title } now
294
+ .title = { $title }
295
+ ```
296
+
297
+ ```ts
298
+ // Component file
299
+ const buttonAttrs = $ta('BUTTON_NAME', { title: 'Submit' });
300
+
301
+ // Output: { ariaLabel: "Submit now", title: "Submit" }
302
+
303
+ // Usage:
304
+ <template>
305
+ <DtButton v-bind="$ta('BUTTON_NAME', { title: 'Submit' });" />
306
+ </template>;
307
+ ```
308
+
309
+ In both cases, any valid fluent syntax is allowed, so the usage of
310
+ [it might include functions](https://projectfluent.org/fluent/guide/functions.html)
311
+ or any other feature provided [by the framework](https://projectfluent.org/).
312
+ (You can find
313
+ [real world examples on this file](../app-core/src/localization/en-US.ftl))
314
+
315
+ ##### Vue component example - $t, $ta
316
+
317
+ Here's an example of how to use the `LocaleManager` in a `Vue` component.
318
+
319
+ ```vue
320
+ <script>
321
+ /* `useI18N` exposes the `$t` and `$ta` localization methods, **for use in the setup method**, and these are both available by default in templates with no extra calls needed. */
322
+
323
+ import { useI18N } from '@dialpad/i18n';
324
+
325
+ const { $t, $ta } = useI18N();
326
+ </script>
327
+
328
+ <template>
329
+ <div>
330
+ <p>{{ $t('PARAGRAPH_KEY') }}</p>
331
+ <button
332
+ v-bind="
333
+ $ta('BUTTON_NAME', {
334
+ name,
335
+ })
336
+ "
337
+ />
338
+ </div>
339
+ </template>
340
+ ```
341
+
342
+ using the following Fluent file as example:
343
+
344
+ ```ftl
345
+ # src/localization/en-US.ftl
346
+ PARAGRAPH_KEY = Amazing paragraph, { $name }
347
+ BUTTON_NAME =
348
+ .aria-label = { $title } now
349
+ .title = { $title }
350
+ ```
351
+
352
+ #### `setI18N`
353
+
354
+ This function receives a `Partial<SetLocaleParams>`. This allows you to change
355
+ any of the set up parameters after the initialization of the `LocaleManager`,
356
+ but the main use case is to change locales dynamically.
357
+
358
+ You probably want to use this in addition to:
359
+
360
+ - `currentLocale`, determined by the
361
+ [criteria defined in the usage section](#usage).
362
+ - `allowedLocales`, are all the allowed locale codes, sorted alphabetically,
363
+ defined during initialization of the `LocaleManager`.
364
+
365
+ ##### Vue component example - setI18N, allowedLocales, currentLocales
366
+
367
+ ```vue
368
+ <script setup lang="ts">
369
+ // your imports ...
370
+ const { setI18N, allowedLocales, currentLocale } = useI18N();
371
+ </script>
372
+
373
+ <template>
374
+ <DtDropdown placement="bottom-end">
375
+ <template #anchor="{ attrs }">
376
+ <DtButton v-bind="attrs" size="md" importance="clear">
377
+ {{ currentLocale }}
378
+ </DtButton>
379
+ </template>
380
+ <template #list="{ close }">
381
+ <template v-for="locale in allowedLocales" :key="locale">
382
+ <DtListItem
383
+ navigation-type="tab"
384
+ @click="
385
+ setI18N({ locales: locale });
386
+ close();
387
+ "
388
+ >
389
+ {{ locale }}
390
+ </DtListItem>
391
+ </template>
392
+ </template>
393
+ </DtDropdown>
394
+ </template>
395
+ ```
396
+
397
+ ### Dynamically Changing Locales with [changeLocale](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:64:2-88:3) Method
398
+
399
+ The
400
+ [changeLocale](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:64:2-88:3)
401
+ method provides the functionality to dynamically change the current locale of
402
+ your application. This method can target a specific
403
+ [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
404
+ by namespace or all
405
+ [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
406
+ instances globally.
407
+
408
+ #### changeLocale()
409
+
410
+ To change the locale settings, call the
411
+ [changeLocale](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:64:2-88:3)
412
+ method on your
413
+ [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
414
+ instance. You can pass optional parameters to update the locale settings and
415
+ optionally specify a namespace to target a specific
416
+ [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1).
417
+ If no namespace is provided, the locale settings will be updated for all
418
+ [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
419
+ instances.
420
+
421
+ ##### Parameters
422
+
423
+ - `args`: (Optional) A `Partial<SetLocaleParams>` object containing the new
424
+ locale settings to be applied.
425
+ - `namespace`: (Optional) The namespace of the
426
+ [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
427
+ instance whose locale settings you want to change. If not provided, all
428
+ instances will be updated.
429
+
430
+ ###### Behavior
431
+
432
+ - Retrieves the map of
433
+ [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
434
+ instances from the Vue prototype.
435
+ - If a namespace is specified, it targets the corresponding
436
+ [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
437
+ and throws an error if it does not exist.
438
+ - If no namespace is specified, it targets all registered
439
+ [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
440
+ instances.
441
+ - Updates the locale settings for the targeted
442
+ [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)(s)
443
+ using the provided arguments.
444
+
445
+ ###### Example
446
+
447
+ ```typescript
448
+ // Assuming you have a LocaleManager instance
449
+ const manager = new LocaleManager(...);
450
+
451
+ // To change the locale settings for a specific namespace
452
+ manager.changeLocale({ preferredLocale: 'fr-FR' }, 'myNamespace');
453
+
454
+ // To change the locale settings for all LocaleManager instances
455
+ manager.changeLocale({ preferredLocale: 'fr-FR' });
456
+
457
+ ### Adding Resources at Runtime with `addSources`
458
+
459
+ #### API Method: `addSources`
460
+
461
+ The `addSources` method allows you to add multiple translation resources to the `LocaleManager` at runtime. Once all resources are loaded, it triggers the `ready` promise indicating that the locale manager is fully initialized and ready to handle localization requests.
462
+ ```
463
+
464
+ ### Adding Resources at Runtime with `addSources`
465
+
466
+ #### API Method: `addSources`
467
+
468
+ The `addSources` method allows you to add multiple translation resources to the
469
+ `LocaleManager` at runtime. Once all resources are loaded, it triggers the
470
+ `ready` promise indicating that the locale manager is fully initialized and
471
+ ready to handle localization requests.
472
+
473
+ ##### Parameters
474
+
475
+ - `sources`: An array of `BuiltResource` items where each item contains:
476
+ - `locale`: The locale code for the translation resource.
477
+ - `namespace`: The namespace associated with the resource.
478
+ - `source`: The actual source string or a promise that resolves to the source
479
+ string.
480
+
481
+ ##### Example
482
+
483
+ ```typescript
484
+ // Assuming you have a LocaleManager instance
485
+ const manager = new LocaleManager(...);
486
+
487
+ // Define your resources
488
+ const resourcesToAdd: BuiltResource[] = [
489
+ // Array of [locale, namespace, source] tuples
490
+ ['en-US', 'namespace1', sourceStringOrPromise],
491
+ ['es-ES', 'namespace1', anotherSourceStringOrPromise],
492
+ // Add more resources as needed
493
+ ];
494
+
495
+ // Add the resources to the LocaleManager
496
+ manager.addSources(resourcesToAdd);
497
+ ```
498
+
499
+ ## Context screenshots
500
+
501
+ Context screenshots are, as their name suggest, screenshots that provide context
502
+ to recognize where each translation is used in each app.
503
+
504
+ Each screenshot should contain visual information of where the translation can
505
+ be found in the app with enough context to be easily located. If other dev looks
506
+ at the screenshot they should be able to locate it fairly easily in your app.
507
+
508
+ There should be one screenshot per each translation key on each `.ftl` file. You
509
+ can reuse the same screenshot for multiple keys, but each file will correspond
510
+ to one key, so you must make one copy for each translation key. The screenshot
511
+ filename will be `{translationKeyHere}.png`. We only support `.png` images for
512
+ now.
513
+
514
+ There is a PR check which will fail if any translation key is missing its
515
+ corresponding screenshot. There is an exception list for paths that should be
516
+ ignored by this check. Avoid using it unless it's completely necessary. If you
517
+ strictly need to use it, remember to mention in your commit message why you are
518
+ using it.
519
+
520
+ These screenshots will be located in a directory called `context-screenshots`
521
+ sibling to each `.ftl` file in your project. If you have an `.ftl` file, it
522
+ should have a sibling screenshots directory. Each screenshot has a file size
523
+ limit of 20MB.
524
+
525
+ The screenshots are uploaded to smartling along with the CSV/FTL files through a
526
+ github action when a PR to main is merged.
527
+
528
+ ## Resources
529
+
530
+ - [Fluent docs](https://github.com/projectfluent/fluent/wiki)
531
+ - [I18n best practices](https://localization.blog/2022/05/16/i18n-best-practices-keep-it-together/)
532
+ - [18n-services docs](../i18n-services/README.md)
533
+ - [i18n for vue2 docs](../i18n-vue2/README.md)
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "noEmit": false,
8
+ "lib": ["ESNext", "DOM", "DOM.Iterable"],
9
+ "experimentalDecorators": true,
10
+ "resolveJsonModule": true,
11
+ "jsx": "preserve",
12
+ "isolatedModules": true,
13
+ "forceConsistentCasingInFileNames": true,
14
+ "skipLibCheck": true,
15
+ "types": ["vite/client", "vitest/globals"],
16
+ "noPropertyAccessFromIndexSignature": false,
17
+ "verbatimModuleSyntax": true
18
+ }
19
+ }