@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.
- package/bin/force-pull-translations.js +2 -0
- package/bin/pull-translations.js +2 -0
- package/bin/should-pull.js +2 -0
- package/bin/translate-dialpadistan.js +2 -0
- package/bin/translation-screenshots-check.js +2 -0
- package/bin/upload-translation-service.js +2 -0
- package/dist/i18n.cjs +883 -878
- package/dist/i18n.cjs.map +1 -1
- package/dist/i18n.js +883 -878
- package/dist/i18n.js.map +1 -1
- package/dist/types/index.d.ts +2 -4
- package/dist/types/index.js +1 -2
- package/{README.md → docs/README.md} +280 -84
- package/index.ts +18 -5
- package/package.json +50 -26
- package/.eslintignore +0 -1
- package/.eslintrc.cjs +0 -12
- package/.prettierignore +0 -3
- package/.rush/temp/chunked-rush-logs/i18n.build.chunks.jsonl +0 -22
- package/.rush/temp/chunked-rush-logs/i18n.format.chunks.jsonl +0 -19
- package/.rush/temp/chunked-rush-logs/i18n.lint.chunks.jsonl +0 -2
- package/.rush/temp/package-deps_build.json +0 -24
- package/.rush/temp/package-deps_format.json +0 -24
- package/.rush/temp/package-deps_lint.json +0 -24
- package/.rush/temp/shrinkwrap-deps.json +0 -12
- package/CHANGELOG.json +0 -63
- package/CHANGELOG.md +0 -30
- package/base-tsconfig.json +0 -19
- package/dialpad-i18n-1.22.2.tgz +0 -0
- package/dist/types/src/locale-manager.d.ts +0 -53
- package/dist/types/src/locale-manager.js +0 -146
- package/eslint-tsconfig.json +0 -5
- package/index.html +0 -11
- package/rush-logs/i18n.build.error.log +0 -0
- package/rush-logs/i18n.build.log +0 -22
- package/rush-logs/i18n.format.error.log +0 -0
- package/rush-logs/i18n.format.log +0 -19
- package/rush-logs/i18n.lint.error.log +0 -0
- package/rush-logs/i18n.lint.log +0 -2
- package/src/__test__/locale-manager.find.test.ts +0 -78
- package/src/__test__/locale-manager.formatters.test.ts +0 -139
- package/src/__test__/locale-manager.multiple.test.ts +0 -349
- package/src/__test__/locale-manager.test.ts +0 -511
- package/src/locale-manager.ts +0 -198
- package/tsconfig.json +0 -10
- package/vite.config.ts +0 -39
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export type { LocaleCode, NamespaceCode, ResourceKey, LocaleManagerParams, SetLocaleParams, UseI18N, } from '@dialpad/i18n-
|
|
2
|
-
export
|
|
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';
|
package/dist/types/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export { LocaleManager, useI18N, INJECTION_KEY_PREFIX, } from '
|
|
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
|
|
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](
|
|
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
|
-
**
|
|
50
|
-
|
|
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](
|
|
54
|
+
#### Synchronous Resource Loading with [builtResources](../../i18n-goblin-core/src/bundle-source)
|
|
54
55
|
|
|
55
|
-
While the
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
[
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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](
|
|
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
|
-
|
|
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
|
|
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](
|
|
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](
|
|
109
|
-
|
|
110
|
-
|
|
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](
|
|
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](
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
|
135
|
-
import { LocaleManager } from '@dialpad/i18n
|
|
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
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
})
|
|
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
|
-
|
|
154
|
-
|
|
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:**
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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](
|
|
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
|
|
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](
|
|
503
|
+
### Dynamically Changing Locales with [changeLocale](../../i18n-goblin-core/src/locale-manager) Method
|
|
396
504
|
|
|
397
|
-
The
|
|
398
|
-
|
|
399
|
-
method
|
|
400
|
-
|
|
401
|
-
[LocaleManager](
|
|
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](
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
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](
|
|
425
|
-
|
|
426
|
-
|
|
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](
|
|
432
|
-
|
|
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](
|
|
435
|
-
|
|
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](
|
|
438
|
-
instances.
|
|
540
|
+
[LocaleManager](../../i18n-goblin-core/src/locale-manager) instances.
|
|
439
541
|
- Updates the locale settings for the targeted
|
|
440
|
-
[LocaleManager](
|
|
441
|
-
|
|
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
|
-
- [
|
|
531
|
-
- [i18n for vue2 docs](
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
3
|
+
"version": "1.24.0",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "
|
|
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-
|
|
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": "~
|
|
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
|
-
"
|
|
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/
|
|
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
|