@dialpad/i18n 1.22.3 → 1.24.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.
Files changed (46) hide show
  1. package/bin/force-pull-translations.js +2 -0
  2. package/bin/pull-translations.js +2 -0
  3. package/bin/should-pull.js +2 -0
  4. package/bin/translate-dialpadistan.js +2 -0
  5. package/bin/translation-screenshots-check.js +2 -0
  6. package/bin/upload-translation-service.js +2 -0
  7. package/dist/i18n.cjs +883 -878
  8. package/dist/i18n.cjs.map +1 -1
  9. package/dist/i18n.js +883 -878
  10. package/dist/i18n.js.map +1 -1
  11. package/dist/types/index.d.ts +2 -4
  12. package/dist/types/index.js +1 -2
  13. package/{README.md → docs/README.md} +280 -84
  14. package/index.ts +18 -5
  15. package/package.json +50 -26
  16. package/.eslintignore +0 -1
  17. package/.eslintrc.cjs +0 -12
  18. package/.prettierignore +0 -3
  19. package/.rush/temp/chunked-rush-logs/i18n.build.chunks.jsonl +0 -22
  20. package/.rush/temp/chunked-rush-logs/i18n.format.chunks.jsonl +0 -19
  21. package/.rush/temp/chunked-rush-logs/i18n.lint.chunks.jsonl +0 -2
  22. package/.rush/temp/package-deps_build.json +0 -24
  23. package/.rush/temp/package-deps_format.json +0 -24
  24. package/.rush/temp/package-deps_lint.json +0 -24
  25. package/.rush/temp/shrinkwrap-deps.json +0 -12
  26. package/CHANGELOG.json +0 -63
  27. package/CHANGELOG.md +0 -30
  28. package/base-tsconfig.json +0 -19
  29. package/dialpad-i18n-1.22.2.tgz +0 -0
  30. package/dist/types/src/locale-manager.d.ts +0 -53
  31. package/dist/types/src/locale-manager.js +0 -146
  32. package/eslint-tsconfig.json +0 -5
  33. package/index.html +0 -11
  34. package/rush-logs/i18n.build.error.log +0 -0
  35. package/rush-logs/i18n.build.log +0 -22
  36. package/rush-logs/i18n.format.error.log +0 -0
  37. package/rush-logs/i18n.format.log +0 -19
  38. package/rush-logs/i18n.lint.error.log +0 -0
  39. package/rush-logs/i18n.lint.log +0 -2
  40. package/src/__test__/locale-manager.find.test.ts +0 -78
  41. package/src/__test__/locale-manager.formatters.test.ts +0 -139
  42. package/src/__test__/locale-manager.multiple.test.ts +0 -349
  43. package/src/__test__/locale-manager.test.ts +0 -511
  44. package/src/locale-manager.ts +0 -198
  45. package/tsconfig.json +0 -10
  46. package/vite.config.ts +0 -39
@@ -1,4 +1,2 @@
1
- export type { LocaleCode, NamespaceCode, ResourceKey, LocaleManagerParams, SetLocaleParams, UseI18N, } from '@dialpad/i18n-services/locale-manager';
2
- export type { BundleSource } from '@dialpad/i18n-services/bundle-source';
3
- export { LocaleManager, useI18N, INJECTION_KEY_PREFIX, } from './src/locale-manager';
4
- export { HTTPBundleSource, RawBundleSource, } from '@dialpad/i18n-services/bundle-source';
1
+ export type { LocaleCode, NamespaceCode, ResourceKey, LocaleManagerParams, SetLocaleParams, UseI18N, FluentFormat, FluentFormatAttrs, UniversalRef, BundleSource, Resource, BuiltResource, FTLModule, HTTPBundleSourceParams, RawBundleSourceParams, StorageWrapper, } from '@dialpad/i18n-goblin-core';
2
+ export { BaseLocaleManager, LocaleManager, useI18N, findLocaleManager, globalLocaleManagers, INJECTION_KEY_PREFIX, HTTPBundleSource, RawBundleSource, createStorageWrapper, MemoryStorageWrapper, } from '@dialpad/i18n-goblin-core';
@@ -1,2 +1 @@
1
- export { LocaleManager, useI18N, INJECTION_KEY_PREFIX, } from './src/locale-manager';
2
- export { HTTPBundleSource, RawBundleSource, } from '@dialpad/i18n-services/bundle-source';
1
+ export { BaseLocaleManager, LocaleManager, useI18N, findLocaleManager, globalLocaleManagers, INJECTION_KEY_PREFIX, HTTPBundleSource, RawBundleSource, createStorageWrapper, MemoryStorageWrapper, } from '@dialpad/i18n-goblin-core';
@@ -1,14 +1,16 @@
1
+ <!-- @docsite-text: Internationalization -->
2
+
1
3
  # i18n (Vue 3 compatible)
2
4
 
3
5
  ## Introduction
4
6
 
5
- This package contains all the logic needed to take care the i18n of a Dialpad
7
+ This package contains all the logic needed to handle i18n for a Dialpad
6
8
  application extending from the common logic existing in the base locale manager
7
9
  that you can find about on the
8
- [i18n-services documentation](../i18n-services/README.md), based on different
9
- bundle sources.
10
+ [i18n-services documentation](../../i18n-services/docs/README.md), based on
11
+ different bundle sources.
10
12
 
11
- ## How it works?
13
+ ## How it works
12
14
 
13
15
  There are essentially two main concepts behind the scenes:
14
16
 
@@ -46,31 +48,27 @@ different use cases.
46
48
  efficient access while still being flexible enough to load translations on
47
49
  demand.
48
50
 
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._
51
+ **Note:** Both implementations are provisional and may change. Currently,
52
+ `RawBundleSource` is the preferred option for most applications.
52
53
 
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
+ #### Synchronous Resource Loading with [builtResources](../../i18n-goblin-core/src/bundle-source)
54
55
 
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.
56
+ While the [dynamicResources](../../i18n-goblin-core/src/bundle-source) method is
57
+ used for asynchronously loading resources, the
58
+ [RawBundleSource](../../i18n-goblin-core/src/bundle-source) class also provides
59
+ a [builtResources](../../i18n-goblin-core/src/bundle-source) method for
60
+ synchronous resource loading. This is useful when you have the localization
61
+ resources available at compile time and prefer to import them directly without
62
+ dealing with promises.
64
63
 
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)
64
+ ##### How to use [builtResources](../../i18n-goblin-core/src/bundle-source)
66
65
 
67
66
  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:
67
+ use the [builtResources](../../i18n-goblin-core/src/bundle-source) method to
68
+ process the resources. Here's an example:
71
69
 
72
70
  ```typescript
73
- import { RawBundleSource } from '@dialpad/i18n-services';
71
+ import { RawBundleSource } from '@dialpad/i18n';
74
72
  // Import your .ftl files directly
75
73
  import enUSResource from './locales/en-US.ftl';
76
74
  import esResource from './locales/es.ftl';
@@ -100,23 +98,22 @@ pnpm add @dialpad/i18n
100
98
 
101
99
  ### Configuration - Static resources
102
100
 
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
101
+ ### Integrating LocaleManager with Vue using the [install](../../i18n-goblin-core/src/locale-manager) Method
104
102
 
105
103
  When using `LocaleManager` within a Vue application, **(especially in the
106
104
  context of a library, you should be aware that install needs to receive a
107
105
  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.
106
+ [install](../../i18n-goblin-core/src/locale-manager) method. This method
107
+ registers `LocaleManager` with the Vue instance, allowing for global access to
108
+ localization functionalities across the application.
111
109
 
112
- #### Usage of [install](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:43:2-55:3)
110
+ #### Usage of [install](../../i18n-goblin-core/src/locale-manager)
113
111
 
114
112
  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.
113
+ [install](../../i18n-goblin-core/src/locale-manager) method. This method accepts
114
+ an optional `namespace` parameter, which is particularly useful when you are
115
+ developing a library and need to avoid conflicts with other potential instances
116
+ of `LocaleManager` in the consumer's environment.
120
117
 
121
118
  By using different namespaces, you can have multiple instances of
122
119
  `LocaleManager` available globally in Vue. This is ideal for libraries that may
@@ -131,8 +128,8 @@ scoped localization management is required.
131
128
  ##### Example
132
129
 
133
130
  ```typescript
134
- import Vue from 'vue';
135
- import { LocaleManager } from '@dialpad/i18n-vue2';
131
+ import { createApp } from 'vue';
132
+ import { LocaleManager } from '@dialpad/i18n';
136
133
 
137
134
  // Create a LocaleManager instance with your configuration options
138
135
  const localeManager = new LocaleManager({
@@ -142,16 +139,17 @@ const localeManager = new LocaleManager({
142
139
  // Install the LocaleManager with a specific namespace to avoid conflicts
143
140
  localeManager.install('my-namespace');
144
141
 
145
- // Your library's users can now access the LocaleManager instance globally in Vue
146
- new Vue({
147
- // ... other options
148
- }).$mount('#app');
142
+ // Your app's users can now access the LocaleManager instance globally in Vue
143
+ const app = createApp({
144
+ /* ... */
145
+ });
146
+ app.mount('#app');
149
147
  ```
150
148
 
151
149
  ### Configuration - Dynamic resources
152
150
 
153
- We recommend you to include this in your own composable that handle every locale
154
- and i18n set up logic, i.e.:
151
+ You should include this in your own composable that handles locale and i18n
152
+ setup logic, for example:
155
153
 
156
154
  ```ts
157
155
  //src/localization/i18n.ts
@@ -183,11 +181,11 @@ export async function hostI18NManager({
183
181
  }
184
182
  ```
185
183
 
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.:
184
+ **Important note:** If you have more than one `allowedLocales`, or if your
185
+ `fallbackLocale`/`preferredLocale` is different from what you're specifying on
186
+ the `allowedLocales` prop to the `LocaleManager` instance, in those cases, you
187
+ need to verify that you have specified a Bundle resource for each locale for
188
+ them to work properly. For example:
191
189
 
192
190
  ```ts
193
191
  //src/localization/i18n.ts
@@ -223,6 +221,116 @@ export async function hostI18NManager({
223
221
  }
224
222
  ```
225
223
 
224
+ ### Configuration - Multiple namespaces
225
+
226
+ For larger applications, having a single `en-US.ftl` file may not scale well.
227
+ You can split your translations across multiple `.ftl` files by using different
228
+ **namespaces**. Each resource maps to a unique `[locale, namespace]` pair, so
229
+ you can organize translations per feature, module, or component.
230
+
231
+ ```ts
232
+ //src/localization/i18n.ts
233
+ import type { App } from 'vue';
234
+ import { LocaleManager, RawBundleSource } from '@dialpad/i18n';
235
+
236
+ export async function hostI18NManager({
237
+ vueApp,
238
+ }: {
239
+ vueApp: App;
240
+ }): Promise<void> {
241
+ const bundleSource = new RawBundleSource({
242
+ resources: await RawBundleSource.dynamicResources([
243
+ // One .ftl file per feature/module, each with its own namespace
244
+ ['en-US', 'feature-chat', import('./chat/en-US.ftl?raw')],
245
+ ['en-US', 'feature-settings', import('./settings/en-US.ftl?raw')],
246
+ ['en-US', 'feature-contacts', import('./contacts/en-US.ftl?raw')],
247
+ ]),
248
+ });
249
+
250
+ const manager = new LocaleManager({
251
+ bundleSource,
252
+ fallbackLocale: 'en-US',
253
+ // List all namespaces used above
254
+ namespaces: ['feature-chat', 'feature-settings', 'feature-contacts'],
255
+ });
256
+
257
+ await manager.ready;
258
+
259
+ vueApp.use(manager);
260
+ }
261
+ ```
262
+
263
+ Given the following `.ftl` files per feature:
264
+
265
+ ```ftl
266
+ # src/localization/chat/en-US.ftl
267
+ CHAT_TITLE = Chat
268
+ CHAT_SEND_BUTTON =
269
+ .aria-label = Send message
270
+ .title = Send
271
+ CHAT_INPUT_PLACEHOLDER = Type a message...
272
+ ```
273
+
274
+ ```ftl
275
+ # src/localization/contacts/en-US.ftl
276
+ CONTACTS_TITLE = Contacts
277
+ CONTACTS_SEARCH_PLACEHOLDER = Search contacts...
278
+ ```
279
+
280
+ You can then use `useI18N` with the corresponding namespace in your Vue
281
+ components:
282
+
283
+ ```vue
284
+ <script setup lang="ts">
285
+ // Pass the namespace to useI18N to get translations from a specific .ftl file
286
+ import { useI18N } from '@dialpad/i18n';
287
+
288
+ const { $t, $ta } = useI18N('feature-chat');
289
+ </script>
290
+
291
+ <template>
292
+ <div>
293
+ <h1>{{ $t('CHAT_TITLE') }}</h1>
294
+ <input :placeholder="$t('CHAT_INPUT_PLACEHOLDER')" />
295
+ <button v-bind="$ta('CHAT_SEND_BUTTON')" />
296
+ </div>
297
+ </template>
298
+ ```
299
+
300
+ ```vue
301
+ <script setup lang="ts">
302
+ import { useI18N } from '@dialpad/i18n';
303
+
304
+ const { $t } = useI18N('feature-contacts');
305
+ </script>
306
+
307
+ <template>
308
+ <div>
309
+ <h1>{{ $t('CONTACTS_TITLE') }}</h1>
310
+ <input :placeholder="$t('CONTACTS_SEARCH_PLACEHOLDER')" />
311
+ </div>
312
+ </template>
313
+ ```
314
+
315
+ > **Tip:** If your app only uses a single namespace (the common case for smaller
316
+ > apps), you can omit the namespace parameter — `useI18N()` defaults to
317
+ > `'default'`.
318
+
319
+ You can also add resources at runtime using `addSources`, which is useful for
320
+ lazy-loading translations for features that are not immediately needed:
321
+
322
+ ```ts
323
+ // Later, when loading a new feature dynamically
324
+ manager.addSources([
325
+ ['en-US', 'feature-analytics', analyticsTranslationSource],
326
+ ]);
327
+ ```
328
+
329
+ > **Note:** Each `[locale, namespace]` combination must be unique. Providing the
330
+ > same pair twice will throw an error. If you need multiple locales per
331
+ > namespace, provide one resource per locale as shown in the
332
+ > [Dynamic resources](#configuration---dynamic-resources) examples above.
333
+
226
334
  After this, you should plug this into your `main.ts`. You will call it like:
227
335
 
228
336
  ```ts
@@ -244,7 +352,7 @@ await createHost(hostEnv)
244
352
  ### User's locale selection criteria
245
353
 
246
354
  You will find that this API is (and should always be) the same as the
247
- [i18n-vue2 tool](../i18n-vue2/README.md).
355
+ [i18n-vue2 tool](../../i18n-vue2/docs/README.md).
248
356
 
249
357
  When instantiating the LocaleManager (or when calling setI18N), the
250
358
  preferredLocale and allowedLocales parameters are optional. BUT this is the
@@ -254,7 +362,7 @@ If preferredLocale param is provided, use that. If allowedLocales param is
254
362
  provided, use the first one. If localStorage contains the previously-used value,
255
363
  use that. If navigator.language is available, use that. Use the fallbackLocale.
256
364
 
257
- First of all you need to understand he difference between `$t` and `$ta`, which
365
+ First, you need to understand the difference between `$t` and `$ta`, which
258
366
  mainly lies in their outputs:
259
367
 
260
368
  ### useI18N() hook API
@@ -392,53 +500,47 @@ const { setI18N, allowedLocales, currentLocale } = useI18N();
392
500
  </template>
393
501
  ```
394
502
 
395
- ### 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
503
+ ### Dynamically Changing Locales with [changeLocale](../../i18n-goblin-core/src/locale-manager) Method
396
504
 
397
- The
398
- [changeLocale](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:64:2-88:3)
399
- method provides the functionality to dynamically change the current locale of
400
- your application. This method can target a specific
401
- [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
402
- by namespace or all
403
- [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
404
- instances globally.
505
+ The [changeLocale](../../i18n-goblin-core/src/locale-manager) method provides
506
+ the functionality to dynamically change the current locale of your application.
507
+ This method can target a specific
508
+ [LocaleManager](../../i18n-goblin-core/src/locale-manager) by namespace or all
509
+ [LocaleManager](../../i18n-goblin-core/src/locale-manager) instances globally.
405
510
 
406
511
  #### changeLocale()
407
512
 
408
513
  To change the locale settings, call the
409
- [changeLocale](cci:1://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:64:2-88:3)
410
- method on your
411
- [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
412
- instance. You can pass optional parameters to update the locale settings and
413
- optionally specify a namespace to target a specific
414
- [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1).
415
- If no namespace is provided, the locale settings will be updated for all
416
- [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
417
- instances.
514
+ [changeLocale](../../i18n-goblin-core/src/locale-manager) method on your
515
+ [LocaleManager](../../i18n-goblin-core/src/locale-manager) instance. You can
516
+ pass optional parameters to update the locale settings and optionally specify a
517
+ namespace to target a specific
518
+ [LocaleManager](../../i18n-goblin-core/src/locale-manager). If no namespace is
519
+ provided, the locale settings will be updated for all
520
+ [LocaleManager](../../i18n-goblin-core/src/locale-manager) instances.
418
521
 
419
522
  ##### Parameters
420
523
 
421
524
  - `args`: (Optional) A `Partial<SetLocaleParams>` object containing the new
422
525
  locale settings to be applied.
423
526
  - `namespace`: (Optional) The namespace of the
424
- [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
425
- instance whose locale settings you want to change. If not provided, all
426
- instances will be updated.
527
+ [LocaleManager](../../i18n-goblin-core/src/locale-manager) instance whose
528
+ locale settings you want to change. If not provided, all instances will be
529
+ updated.
427
530
 
428
531
  ###### Behavior
429
532
 
430
533
  - Retrieves the map of
431
- [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
432
- instances from the Vue prototype.
534
+ [LocaleManager](../../i18n-goblin-core/src/locale-manager) instances from the
535
+ Vue prototype.
433
536
  - If a namespace is specified, it targets the corresponding
434
- [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
435
- and throws an error if it does not exist.
537
+ [LocaleManager](../../i18n-goblin-core/src/locale-manager) and throws an error
538
+ if it does not exist.
436
539
  - If no namespace is specified, it targets all registered
437
- [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)
438
- instances.
540
+ [LocaleManager](../../i18n-goblin-core/src/locale-manager) instances.
439
541
  - Updates the locale settings for the targeted
440
- [LocaleManager](cci:2://file:///Users/daniellovero/src/web-clients/packages/i18n-vue2/src/locale-manager.ts:21:0-89:1)(s)
441
- using the provided arguments.
542
+ [LocaleManager](../../i18n-goblin-core/src/locale-manager)(s) using the
543
+ provided arguments.
442
544
 
443
545
  ###### Example
444
546
 
@@ -451,12 +553,6 @@ manager.changeLocale({ preferredLocale: 'fr-FR' }, 'myNamespace');
451
553
 
452
554
  // To change the locale settings for all LocaleManager instances
453
555
  manager.changeLocale({ preferredLocale: 'fr-FR' });
454
-
455
- ### Adding Resources at Runtime with `addSources`
456
-
457
- #### API Method: `addSources`
458
-
459
- 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.
460
556
  ```
461
557
 
462
558
  ### Adding Resources at Runtime with `addSources`
@@ -494,6 +590,106 @@ const resourcesToAdd: BuiltResource[] = [
494
590
  manager.addSources(resourcesToAdd);
495
591
  ```
496
592
 
593
+ ## CLI Tools
594
+
595
+ `@dialpad/i18n` exposes the following CLI scripts as bin commands. You can run
596
+ them directly with your package manager (e.g. `pnpm exec <command>` or
597
+ `npx <command>`):
598
+
599
+ | Command | Description |
600
+ | ------------------------------- | ------------------------------------------------------------------ |
601
+ | `translate-dialpadistan` | Converts an `en-US.ftl` file into a `dp-DP.ftl` file |
602
+ | `pull-translations` | Pulls published translations from Smartling |
603
+ | `force-pull-translations` | Force-pulls latest translations without waiting for job completion |
604
+ | `upload-translation-service` | Pushes `en-US.ftl` source files to Smartling |
605
+ | `translation-screenshots-check` | Checks that context screenshots exist for all translation keys |
606
+ | `should-pull` | Checks whether translations should be pulled |
607
+
608
+ ### Dialpadistan translator
609
+
610
+ This feature uses the `@fluent/syntax` parser and a set of regex and grammar
611
+ rules to convert an `en-US.ftl` file into a `dp-DP.ftl` inside the same
612
+ directory. The "dialpadistani" language replaces each Latin character with a
613
+ non-Latin equivalent, which is useful for testing proper rendering of different
614
+ fonts.
615
+
616
+ For example:
617
+
618
+ ```ftl
619
+ # src/localization/en-US.ftl
620
+
621
+ MESSAGE_INPUT_LABEL = New message input
622
+ FEED_NEW_SEPARATOR = Beginning of unread items
623
+ ```
624
+
625
+ Will translate to:
626
+
627
+ ```ftl
628
+ # src/localization/dp-DP.ftl
629
+
630
+ MESSAGE_INPUT_LABEL = Ŋάŵ ɱάššëğά īŋþø†
631
+ FEED_NEW_SEPARATOR = Sάğīŋŋīŋğ ůƒ øŋřάëḍ ī†άɱš
632
+ ```
633
+
634
+ To execute a Dialpadistan translation you should run the following script
635
+ pointing to your Fluent English file: _(Note: it can either be a relative path
636
+ or an absolute path)_
637
+
638
+ ```sh
639
+ pnpm exec translate-dialpadistan /your/english/fluent/file/en-US.ftl
640
+ ```
641
+
642
+ After a successful translation, a message appears in your terminal indicating
643
+ where the output file was placed. The output folder is _the same as your English
644
+ Fluent file_.
645
+
646
+ e.g. in this case you will see
647
+ `File transformed and saved as /your/english/fluent/file/dp-DP.ftl`.
648
+
649
+ #### Known issues
650
+
651
+ There is one specific scenario where this translator is failing, and we don't
652
+ consider it to be harmful. This is because of a bug on `@fluent/syntax` parser.
653
+
654
+ And this is when having a comment right in the middle between an equal sign and
655
+ a value, and that comment has at least one placeholder, whatever's after the
656
+ text of the first placeholder will be translated (and if the comment it's
657
+ multi-lined every comment line will be squashed and inlined after that
658
+ placeholder as well)
659
+
660
+ e.g.
661
+
662
+ ```ftl
663
+ MY_KEY =
664
+ # My awesome comment
665
+ # And here the {$placeholder} is present
666
+ .aria-label = { $name } ({ $muted ->
667
+ [true] Muted{" "}
668
+ *[other] {""}
669
+ })
670
+ ```
671
+
672
+ will be translated to:
673
+
674
+ ```ftl
675
+ MY_KEY =
676
+ # My awesome comment
677
+ # And here the {$placeholder} os sintirp
678
+ .aria-label = { $name } ({ $muted ->
679
+ [true] Muted{" "}
680
+ *[other] {""}
681
+ })
682
+ ```
683
+
684
+ This is because of the way the `@fluent/syntax` parser works at the current
685
+ version. Fixing this would require either patching the parser behavior or adding
686
+ extensive regex pre- and post-processing, both of which would increase
687
+ complexity and reduce robustness. Given that this only affects comments, we
688
+ prefer to wait for an upstream fix in a future version.
689
+
690
+ **But keep in mind that whenever adding comments, it should be before the whole
691
+ KEY = VALUE and not in between.**
692
+
497
693
  ## Context screenshots
498
694
 
499
695
  Context screenshots are, as their name suggest, screenshots that provide context
@@ -527,5 +723,5 @@ github action when a PR to main is merged.
527
723
 
528
724
  - [Fluent docs](https://github.com/projectfluent/fluent/wiki)
529
725
  - [I18n best practices](https://localization.blog/2022/05/16/i18n-best-practices-keep-it-together/)
530
- - [18n-services docs](../i18n-services/README.md)
531
- - [i18n for vue2 docs](../i18n-vue2/README.md)
726
+ - [i18n-services docs (deprecated)](../../i18n-services/docs/README.md)
727
+ - [i18n for vue2 docs (deprecated)](../../i18n-vue2/docs/README.md)
package/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ // Re-export everything from goblin-core
1
2
  export type {
2
3
  LocaleCode,
3
4
  NamespaceCode,
@@ -5,15 +6,27 @@ export type {
5
6
  LocaleManagerParams,
6
7
  SetLocaleParams,
7
8
  UseI18N,
8
- } from '@dialpad/i18n-services/locale-manager';
9
+ FluentFormat,
10
+ FluentFormatAttrs,
11
+ UniversalRef,
12
+ BundleSource,
13
+ Resource,
14
+ BuiltResource,
15
+ FTLModule,
16
+ HTTPBundleSourceParams,
17
+ RawBundleSourceParams,
18
+ StorageWrapper,
19
+ } from '@dialpad/i18n-goblin-core';
9
20
 
10
- export type { BundleSource } from '@dialpad/i18n-services/bundle-source';
11
21
  export {
22
+ BaseLocaleManager,
12
23
  LocaleManager,
13
24
  useI18N,
25
+ findLocaleManager,
26
+ globalLocaleManagers,
14
27
  INJECTION_KEY_PREFIX,
15
- } from './src/locale-manager';
16
- export {
17
28
  HTTPBundleSource,
18
29
  RawBundleSource,
19
- } from '@dialpad/i18n-services/bundle-source';
30
+ createStorageWrapper,
31
+ MemoryStorageWrapper,
32
+ } from '@dialpad/i18n-goblin-core';
package/package.json CHANGED
@@ -1,31 +1,72 @@
1
1
  {
2
2
  "name": "@dialpad/i18n",
3
- "version": "1.22.3",
3
+ "version": "1.24.0",
4
4
  "private": false,
5
- "description": "Dialpad's internationalization library",
5
+ "description": "Internationalization library for Vue 3 apps using Mozilla's Fluent syntax, with locale management, translation bundle loading, and CLI tools for translation workflows",
6
+ "keywords": [
7
+ "i18n",
8
+ "internationalization",
9
+ "localization",
10
+ "fluent",
11
+ "vue",
12
+ "translation",
13
+ "locale"
14
+ ],
6
15
  "author": "Dialpad",
7
16
  "license": "UNLICENSED",
8
17
  "type": "module",
18
+ "files": [
19
+ "dist",
20
+ "bin",
21
+ "docs",
22
+ "index.ts"
23
+ ],
24
+ "scripts": {
25
+ "typecheck": "rushx types:check",
26
+ "typecheck:ci": "rushx typecheck",
27
+ "lint": "echo 'needs migration to use @dialpad/eslint-config'",
28
+ "lint:ci": "echo 'needs migration to use @dialpad/eslint-config'",
29
+ "format": "prettier ./ --write",
30
+ "format:ci": "prettier ./ --check",
31
+ "test": "vitest",
32
+ "test:ci": "echo 'no tests'",
33
+ "coverage": "vitest run --coverage --passWithNoTests",
34
+ "coverage:open": "rushx coverage && open coverage/index.html",
35
+ "build": "run-p build:*",
36
+ "build:main": "vite build --config vite.config.ts",
37
+ "build:types": "rushx types:build",
38
+ "types:build": "tsc",
39
+ "types:check": "tsc --noEmit"
40
+ },
9
41
  "dependencies": {
10
- "@dialpad/i18n-services": "1.11.0"
42
+ "@dialpad/i18n-goblin-core": "1.0.2",
43
+ "@dialpad/i18n-goblin-services": "1.0.2"
11
44
  },
12
45
  "devDependencies": {
46
+ "@dialpad/eslint-config": "1.0.2",
13
47
  "@vitejs/plugin-vue": "~5.1.4",
14
48
  "npm-run-all": "4.1.5",
15
- "prettier": "~2.8.8",
49
+ "prettier": "~3.3.3",
16
50
  "typescript": "~5.6.3",
17
51
  "vite": "~5.4.10",
18
52
  "vue": "~3.5.12",
19
- "vue-tsc": "1.8.8",
20
- "vitest": "~2.1.4",
21
53
  "eslint": "~9.13.0",
22
- "@dialpad/eslint-config": "2.1.0"
54
+ "vue-tsc": "~3.1.1",
55
+ "vitest": "~2.1.4"
23
56
  },
24
57
  "exports": {
25
58
  "import": "./dist/i18n.js",
26
59
  "types": "./dist/types/index.d.ts",
27
60
  "require": "./dist/i18n.cjs"
28
61
  },
62
+ "bin": {
63
+ "translate-dialpadistan": "./bin/translate-dialpadistan.js",
64
+ "translation-screenshots-check": "./bin/translation-screenshots-check.js",
65
+ "upload-translation-service": "./bin/upload-translation-service.js",
66
+ "pull-translations": "./bin/pull-translations.js",
67
+ "force-pull-translations": "./bin/force-pull-translations.js",
68
+ "should-pull": "./bin/should-pull.js"
69
+ },
29
70
  "peerDependencies": {
30
71
  "vue": "^3.0.0"
31
72
  },
@@ -34,23 +75,6 @@
34
75
  },
35
76
  "repository": {
36
77
  "type": "git",
37
- "url": "https://github.com/dialpad/web-clients.git"
38
- },
39
- "scripts": {
40
- "typecheck": "rushx types:check",
41
- "typecheck:ci": "rushx typecheck",
42
- "lint": "echo 'needs migration to use @dialpad/eslint-config'",
43
- "lint:ci": "echo 'needs migration to use @dialpad/eslint-config'",
44
- "format": "prettier ./ --write",
45
- "format:ci": "prettier ./ --check",
46
- "test": "vitest",
47
- "test:ci": "rushx test 2>&1",
48
- "coverage": "vitest run --coverage --passWithNoTests",
49
- "coverage:open": "rushx coverage && open coverage/index.html",
50
- "build": "run-p build:*",
51
- "build:main": "vite build --config vite.config.ts",
52
- "build:types": "rushx types:build",
53
- "types:build": "tsc",
54
- "types:check": "tsc --noEmit"
78
+ "url": "https://github.com/dialpad/goblin-client-tools"
55
79
  }
56
- }
80
+ }
package/.eslintignore DELETED
@@ -1 +0,0 @@
1
- dist
package/.eslintrc.cjs DELETED
@@ -1,12 +0,0 @@
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
- };