@gunshi/plugin-i18n 0.27.0-alpha.9 → 0.27.0-beta.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/README.md +136 -101
- package/lib/index.d.ts +636 -540
- package/lib/index.js +211 -74
- package/package.json +14 -10
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @gunshi/plugin-i18n
|
|
2
2
|
|
|
3
|
+
[![Version][npm-version-src]][npm-version-href]
|
|
4
|
+
[![InstallSize][install-size-src]][install-size-src]
|
|
5
|
+
[![JSR][jsr-src]][jsr-href]
|
|
6
|
+
|
|
3
7
|
> internationalization (i18n) plugin for gunshi.
|
|
4
8
|
|
|
5
9
|
This plugin provides multi-language support for your CLI applications, allowing you to create commands that can display messages in different languages based on user locale.
|
|
@@ -27,16 +31,18 @@ bun add @gunshi/plugin-i18n
|
|
|
27
31
|
|
|
28
32
|
```ts
|
|
29
33
|
import { cli } from 'gunshi'
|
|
30
|
-
import i18n, {
|
|
34
|
+
import i18n, { pluginId as i18nId, defineI18nWithTypes } from '@gunshi/plugin-i18n'
|
|
35
|
+
|
|
36
|
+
import type { I18nExtension } from '@gunshi/plugin-i18n'
|
|
31
37
|
|
|
32
38
|
/**
|
|
33
|
-
* You can define a command with `
|
|
39
|
+
* You can define a command with `defineI18nWithTypes`, which is compatible with the `define` function.
|
|
34
40
|
* This provides full type safety for i18n commands - TypeScript will suggest the 'resource' option
|
|
35
41
|
* and ensure your resource keys match the expected structure.
|
|
36
42
|
*/
|
|
37
43
|
|
|
38
44
|
// Define a command
|
|
39
|
-
const
|
|
45
|
+
const command = defineI18nWithTypes<{ extensions: { [i18nId]: I18nExtension } }>()({
|
|
40
46
|
name: 'greet',
|
|
41
47
|
description: 'Greet someone',
|
|
42
48
|
|
|
@@ -48,16 +54,16 @@ const greetCommand = defineI18n({
|
|
|
48
54
|
},
|
|
49
55
|
|
|
50
56
|
// Define resource fetcher for translations
|
|
51
|
-
resource:
|
|
57
|
+
resource: locale => ({
|
|
52
58
|
description: 'Greet someone in their language',
|
|
53
59
|
'arg:name': "The person's name",
|
|
54
60
|
greeting: 'Hello, {$name}!'
|
|
55
61
|
}),
|
|
56
62
|
|
|
57
|
-
run:
|
|
63
|
+
run: ctx => {
|
|
58
64
|
const { name } = ctx.values
|
|
59
65
|
// Use translate function from context
|
|
60
|
-
console.log(ctx.extensions[
|
|
66
|
+
console.log(ctx.extensions[i18nId].translate('greeting', { name }))
|
|
61
67
|
}
|
|
62
68
|
})
|
|
63
69
|
|
|
@@ -79,7 +85,7 @@ await cli(process.argv.slice(2), greetCommand, {
|
|
|
79
85
|
- Default: `'en-US'`
|
|
80
86
|
- Description: The locale to use for translations. Can be a BCP 47 language tag string or an `Intl.Locale` object.
|
|
81
87
|
|
|
82
|
-
### `
|
|
88
|
+
### `builtinResources`
|
|
83
89
|
|
|
84
90
|
- Type: `Record<string, Record<BuiltinResourceKeys, string>>`
|
|
85
91
|
- Default: `{}`
|
|
@@ -112,19 +118,16 @@ Example with globals plugin:
|
|
|
112
118
|
```ts
|
|
113
119
|
import { cli } from 'gunshi'
|
|
114
120
|
import i18n from '@gunshi/plugin-i18n'
|
|
115
|
-
import globals from '@gunshi/plugin-global'
|
|
121
|
+
import globals from '@gunshi/plugin-global' // need install `@gunshi/plugin-global`
|
|
122
|
+
import jaJPResource from '@gunshi/resources/ja-JP' with { type: 'json' } // need install `@gunshi/resources`
|
|
116
123
|
|
|
117
124
|
await cli(args, command, {
|
|
118
125
|
plugins: [
|
|
119
126
|
globals(), // Adds --help and --version options
|
|
120
127
|
i18n({
|
|
121
128
|
locale: 'ja-JP',
|
|
122
|
-
|
|
123
|
-
'ja-JP':
|
|
124
|
-
help: 'ヘルプメッセージを表示', // Override help translation
|
|
125
|
-
version: 'バージョンを表示' // Override version translation
|
|
126
|
-
// ... other built-in translations
|
|
127
|
-
}
|
|
129
|
+
builtinResources: {
|
|
130
|
+
'ja-JP': jaJPResource // Set from with providing gunshi built-in resources
|
|
128
131
|
}
|
|
129
132
|
})
|
|
130
133
|
]
|
|
@@ -135,33 +138,81 @@ await cli(args, command, {
|
|
|
135
138
|
|
|
136
139
|
### `defineI18n`
|
|
137
140
|
|
|
138
|
-
|
|
141
|
+
Define an i18n-aware command.
|
|
139
142
|
|
|
140
143
|
```ts
|
|
141
144
|
import { defineI18n } from '@gunshi/plugin-i18n'
|
|
142
145
|
|
|
143
|
-
const
|
|
144
|
-
name: '
|
|
146
|
+
const greetCommand = defineI18n({
|
|
147
|
+
name: 'greet',
|
|
148
|
+
description: 'Greet someone',
|
|
145
149
|
args: {
|
|
146
|
-
name: {
|
|
150
|
+
name: {
|
|
151
|
+
type: 'string',
|
|
152
|
+
description: 'Name to greet'
|
|
153
|
+
}
|
|
147
154
|
},
|
|
148
|
-
resource:
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
155
|
+
resource: locale => {
|
|
156
|
+
switch (locale.toString()) {
|
|
157
|
+
case 'ja-JP': {
|
|
158
|
+
return {
|
|
159
|
+
description: '誰かにあいさつ',
|
|
160
|
+
'arg:name': 'あいさつするための名前'
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// other locales ...
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
run: ctx => {
|
|
153
167
|
console.log(`Hello, ${ctx.values.name}!`)
|
|
154
168
|
}
|
|
155
169
|
})
|
|
156
170
|
```
|
|
157
171
|
|
|
172
|
+
The difference from the `define` function is that you can define a `resource` option that can load a locale.
|
|
173
|
+
|
|
174
|
+
### `defineI18nWithTypes`
|
|
175
|
+
|
|
176
|
+
Define an i18n-aware command with types
|
|
177
|
+
|
|
178
|
+
This helper function allows specifying the type parameter of `GunshiParams` while inferring the `Args` type, `ExtendContext` type from the definition.
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import { defineI18nWithTypes } from '@gunshi/plugin-i18n'
|
|
182
|
+
|
|
183
|
+
// Define a command with specific extensions type
|
|
184
|
+
type MyExtensions = { logger: { log: (message: string) => void } }
|
|
185
|
+
|
|
186
|
+
const greetCommand = defineI18nWithTypes<{ extensions: MyExtensions }>()({
|
|
187
|
+
name: 'greet',
|
|
188
|
+
args: {
|
|
189
|
+
name: { type: 'string', description: 'Name to greet' }
|
|
190
|
+
},
|
|
191
|
+
resource: locale => {
|
|
192
|
+
switch (locale.toString()) {
|
|
193
|
+
case 'ja-JP': {
|
|
194
|
+
return {
|
|
195
|
+
description: '誰かにあいさつ',
|
|
196
|
+
'arg:name': 'あいさつするための名前'
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// other locales ...
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
run: ctx => {
|
|
203
|
+
// ctx.values is inferred as { name?: string }
|
|
204
|
+
// ctx.extensions is MyExtensions
|
|
205
|
+
}
|
|
206
|
+
})
|
|
207
|
+
```
|
|
208
|
+
|
|
158
209
|
### `withI18nResource`
|
|
159
210
|
|
|
160
|
-
Add i18n resource to an existing command. This helper is useful for extending an already defined command.
|
|
211
|
+
Add i18n resource to an existing command. This helper is useful for extending an already defined command with `define` function.
|
|
161
212
|
|
|
162
213
|
```ts
|
|
163
|
-
import { define } from 'gunshi' // 'gunshi/definition', or '@gunshi/definition'
|
|
164
|
-
import { withI18nResource } from '@gunshi/plugin-i18n'
|
|
214
|
+
import { define } from 'gunshi' // alternative 'gunshi/definition', or '@gunshi/definition'
|
|
215
|
+
import { withI18nResource, pluginId as i18nId } from '@gunshi/plugin-i18n'
|
|
165
216
|
|
|
166
217
|
const basicCommand = define({
|
|
167
218
|
name: 'test',
|
|
@@ -175,11 +226,10 @@ const basicCommand = define({
|
|
|
175
226
|
run: ctx => console.log(`test: ${ctx.values.target}`)
|
|
176
227
|
})
|
|
177
228
|
|
|
178
|
-
const i18nCommand = withI18nResource(basicCommand, async
|
|
179
|
-
const resource = await import(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
).then(l => l.default || l)
|
|
229
|
+
const i18nCommand = withI18nResource(basicCommand, async locale => {
|
|
230
|
+
const resource = await import(`./path/to/resources/test/${locale.toString()}.json`, {
|
|
231
|
+
with: { type: 'json' }
|
|
232
|
+
}).then(l => l.default || l)
|
|
183
233
|
return resource
|
|
184
234
|
})
|
|
185
235
|
```
|
|
@@ -188,16 +238,16 @@ const i18nCommand = withI18nResource(basicCommand, async ctx => {
|
|
|
188
238
|
|
|
189
239
|
The i18n plugin exports key resolution helper functions that handle the internal key structure, so you don't need to manually prefix your keys:
|
|
190
240
|
|
|
191
|
-
- `resolveKey(key: string,
|
|
192
|
-
- `resolveArgKey(key: string,
|
|
241
|
+
- `resolveKey(key: string, name?: string): string` - Resolves a custom key with command namespace if applicable
|
|
242
|
+
- `resolveArgKey(key: string, name?: string): string` - Resolves an argument key with `arg:` prefix and namespace
|
|
193
243
|
- `resolveBuiltInKey(key: string): string` - Resolves a built-in key with `_:` prefix
|
|
194
244
|
|
|
195
245
|
```ts
|
|
196
246
|
import { resolveKey, resolveArgKey, resolveBuiltInKey } from '@gunshi/plugin-i18n'
|
|
197
247
|
|
|
198
248
|
// These helpers automatically add the correct prefixes
|
|
199
|
-
resolveKey('description', ctx) // Returns namespaced key for description
|
|
200
|
-
resolveArgKey('verbose', ctx) // Returns 'arg:verbose' or 'command:arg:verbose' based on
|
|
249
|
+
resolveKey('description', ctx.name) // Returns namespaced key for description
|
|
250
|
+
resolveArgKey('verbose', ctx.name) // Returns 'arg:verbose' or 'command:arg:verbose' based on command namespace
|
|
201
251
|
resolveBuiltInKey('USAGE') // Returns '_:USAGE'
|
|
202
252
|
```
|
|
203
253
|
|
|
@@ -226,35 +276,43 @@ While the `translate` function accepts keys without prefixes in most cases, usin
|
|
|
226
276
|
#### Example Usage
|
|
227
277
|
|
|
228
278
|
```ts
|
|
229
|
-
import {
|
|
279
|
+
import {
|
|
280
|
+
defineI18nWithTypes,
|
|
281
|
+
pluginId as i18nId,
|
|
282
|
+
resolveKey,
|
|
283
|
+
resolveArgKey,
|
|
284
|
+
resolveBuiltInKey
|
|
285
|
+
} from '@gunshi/plugin-i18n'
|
|
230
286
|
|
|
231
|
-
|
|
287
|
+
import type { I18nExtension } from '@gunshi/plugin-i18n'
|
|
288
|
+
|
|
289
|
+
const createCommand = defineI18nWithTypes<{ extensions: { [i18nId]: I18nExtension } }>()({
|
|
232
290
|
name: 'deploy',
|
|
233
291
|
args: {
|
|
234
292
|
environment: { type: 'string', short: 'e' },
|
|
235
293
|
force: { type: 'boolean', short: 'f' }
|
|
236
294
|
},
|
|
237
|
-
resource:
|
|
295
|
+
resource: locale => ({
|
|
238
296
|
description: 'Deploy application',
|
|
239
297
|
'arg:environment': 'Target environment',
|
|
240
298
|
'arg:force': 'Force deployment',
|
|
241
|
-
|
|
242
|
-
|
|
299
|
+
start: 'Starting deployment...',
|
|
300
|
+
success: 'Deployment completed successfully!'
|
|
243
301
|
}),
|
|
244
|
-
run:
|
|
245
|
-
const { translate } = ctx.extensions[
|
|
302
|
+
run: ctx => {
|
|
303
|
+
const { translate } = ctx.extensions[i18nId]
|
|
246
304
|
|
|
247
|
-
//
|
|
248
|
-
console.log(translate('
|
|
305
|
+
// Usage helper for custom keys (prefix with command name)
|
|
306
|
+
console.log(translate(resolveKey('start', ctx.name)))
|
|
249
307
|
|
|
250
308
|
// Using helpers for explicit control
|
|
251
|
-
const envKey = resolveArgKey('environment', ctx)
|
|
309
|
+
const envKey = resolveArgKey('environment', ctx.name)
|
|
252
310
|
console.log(translate(envKey)) // Same as translate('arg:environment')
|
|
253
311
|
|
|
254
312
|
// Useful when building dynamic keys
|
|
255
313
|
const args = ['environment', 'force']
|
|
256
314
|
for (const arg of args) {
|
|
257
|
-
const key = resolveArgKey(arg, ctx)
|
|
315
|
+
const key = resolveArgKey(arg, ctx.name)
|
|
258
316
|
const description = translate(key)
|
|
259
317
|
console.log(`${arg}: ${description}`)
|
|
260
318
|
}
|
|
@@ -282,6 +340,7 @@ Available extensions:
|
|
|
282
340
|
- `locale: Intl.Locale`: The current locale
|
|
283
341
|
- `translate<T>(key: T, values?: Record<string, unknown>): string`: Translation function
|
|
284
342
|
- `loadResource(locale: string | Intl.Locale, ctx: CommandContext, command: Command): Promise<boolean>`: Manually load resources for a specific locale and command
|
|
343
|
+
- `registerGlobalOptionResources: (option: string, resources: Record<string, string>) => void`: Register global option resources. If your global option description needs the localization, you can install resource of it at `extension` or `onExtension` hook
|
|
285
344
|
|
|
286
345
|
## 📝 Resource Key Naming Conventions
|
|
287
346
|
|
|
@@ -321,20 +380,21 @@ Here's an example illustrating the convention:
|
|
|
321
380
|
```ts
|
|
322
381
|
import { defineI18n } from '@gunshi/plugin-i18n'
|
|
323
382
|
|
|
383
|
+
// if you want to use `I18nExtension` in `run`, you should use `defineI18nWithTypes`, not `defineI18n`
|
|
324
384
|
const command = defineI18n({
|
|
325
385
|
name: 'my-command',
|
|
326
386
|
args: {
|
|
327
387
|
target: { type: 'string' },
|
|
328
388
|
verbose: { type: 'boolean' }
|
|
329
389
|
},
|
|
330
|
-
resource:
|
|
390
|
+
resource: locale => {
|
|
331
391
|
// Example for 'en-US' locale
|
|
332
392
|
return {
|
|
333
|
-
description: 'This is my command.', // No prefix
|
|
334
|
-
'arg:target': 'The target file to process.', // 'arg:' prefix
|
|
335
|
-
'arg:verbose': 'Enable verbose output.', // 'arg:' prefix
|
|
393
|
+
description: 'This is my command.', // built-in key, No prefix
|
|
394
|
+
'arg:target': 'The target file to process.', // argument key, 'arg:' prefix
|
|
395
|
+
'arg:verbose': 'Enable verbose output.', // argument key, 'arg:' prefix
|
|
336
396
|
'arg:no-verbose': 'Disable verbose logging specifically.', // Optional custom translation for the negatable option
|
|
337
|
-
processing_message: 'Processing target...' // No prefix
|
|
397
|
+
processing_message: 'Processing target...' // custom keys, No prefix
|
|
338
398
|
}
|
|
339
399
|
},
|
|
340
400
|
run: ctx => {
|
|
@@ -393,13 +453,15 @@ The `translate` function has different behaviors depending on the key type:
|
|
|
393
453
|
This difference is important for error handling and fallback displays:
|
|
394
454
|
|
|
395
455
|
```ts
|
|
456
|
+
import { resolveKey, resolveBuiltInKey } from '@gunshi/plugin-i18n'
|
|
457
|
+
|
|
396
458
|
const { translate } = ctx.extensions['g:i18n']
|
|
397
459
|
|
|
398
460
|
// Custom key not found
|
|
399
|
-
translate('nonexistent_key') // Returns: ''
|
|
461
|
+
translate(resolveKey('nonexistent_key', ctx.name)) // Returns: ''
|
|
400
462
|
|
|
401
463
|
// Built-in key not found (if not overridden)
|
|
402
|
-
translate('USAGE') // Returns: 'USAGE'
|
|
464
|
+
translate(resolveBuiltInKey('USAGE')) // Returns: 'USAGE'
|
|
403
465
|
```
|
|
404
466
|
|
|
405
467
|
### Resource Loading Behavior
|
|
@@ -456,17 +518,19 @@ await cli(args, command, {
|
|
|
456
518
|
The default translation adapter supports simple interpolation using `{$key}` syntax:
|
|
457
519
|
|
|
458
520
|
```ts
|
|
521
|
+
import { pluginId as i18nId, resolveKey } from '@gunshi/plugin-i18n'
|
|
522
|
+
|
|
459
523
|
// In your resource
|
|
460
524
|
const resource = {
|
|
461
525
|
welcome: 'Welcome, {$name}!',
|
|
462
|
-
|
|
526
|
+
items_count: 'You have {$count} items',
|
|
463
527
|
file_deleted: 'Deleted {$path}',
|
|
464
528
|
error_message: 'Error: {$error}'
|
|
465
529
|
}
|
|
466
530
|
// In your command
|
|
467
|
-
const { translate } = ctx.extensions[
|
|
531
|
+
const { translate } = ctx.extensions[i18nId]
|
|
468
532
|
translate(resolveKey('welcome'), { name: 'John' }) // "Welcome, John!"
|
|
469
|
-
translate(resolveKey('
|
|
533
|
+
translate(resolveKey('items_count'), { count: 5 }) // "You have 5 items"
|
|
470
534
|
translate(resolveKey('file_deleted'), { path: '/tmp/file.txt' }) // "Deleted /tmp/file.txt"
|
|
471
535
|
translate(resolveKey('error_message'), { error: 'File not found' }) // "Error: File not found"
|
|
472
536
|
```
|
|
@@ -537,7 +601,7 @@ When you provide a custom translation adapter:
|
|
|
537
601
|
|
|
538
602
|
```ts
|
|
539
603
|
import { cli } from 'gunshi'
|
|
540
|
-
import i18n, {
|
|
604
|
+
import i18n, { defineI18nWithTypes, pluginId as i18nId, resolveKey } from '@gunshi/plugin-i18n'
|
|
541
605
|
import {
|
|
542
606
|
createCoreContext,
|
|
543
607
|
getLocaleMessage,
|
|
@@ -546,6 +610,8 @@ import {
|
|
|
546
610
|
translate as intlifyTranslate
|
|
547
611
|
} from '@intlify/core' // need to install `npm install --save @intlify/core@next`
|
|
548
612
|
|
|
613
|
+
import type { I18nExtension } from '@gunshi/plugin-i18n'
|
|
614
|
+
|
|
549
615
|
// Create an Intlify translation adapter factory
|
|
550
616
|
function createIntlifyAdapterFactory(options) {
|
|
551
617
|
return new IntlifyTranslation(options)
|
|
@@ -606,7 +672,7 @@ class IntlifyTranslation {
|
|
|
606
672
|
}
|
|
607
673
|
|
|
608
674
|
// Define your command
|
|
609
|
-
const command =
|
|
675
|
+
const command = defineI18nWithTypes<{ extensions: { [i18nId]: I18nExtension } }>()({
|
|
610
676
|
name: 'greeter',
|
|
611
677
|
|
|
612
678
|
args: {
|
|
@@ -622,10 +688,8 @@ const command = defineI18n({
|
|
|
622
688
|
},
|
|
623
689
|
|
|
624
690
|
// Define a resource fetcher with Intlify syntax
|
|
625
|
-
resource:
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
if (locale === 'ja-JP') {
|
|
691
|
+
resource: locale => {
|
|
692
|
+
if (locale.toString() === 'ja-JP') {
|
|
629
693
|
return {
|
|
630
694
|
description: '挨拶アプリケーション',
|
|
631
695
|
'arg:name': '挨拶する相手の名前',
|
|
@@ -646,11 +710,11 @@ const command = defineI18n({
|
|
|
646
710
|
|
|
647
711
|
run: ctx => {
|
|
648
712
|
const { name = 'World', count } = ctx.values
|
|
649
|
-
const { translate } = ctx.extensions[
|
|
713
|
+
const { translate } = ctx.extensions[i18nId]
|
|
650
714
|
|
|
651
715
|
// Use the translation function with Intlify
|
|
652
716
|
const key = count > 1 ? 'greeting_plural' : 'greeting'
|
|
653
|
-
const message = translate(key, { name, count })
|
|
717
|
+
const message = translate(resolveKey(key, ctx.name), { name, count })
|
|
654
718
|
|
|
655
719
|
console.log(message)
|
|
656
720
|
}
|
|
@@ -685,43 +749,6 @@ With Intlify, you get advanced features like:
|
|
|
685
749
|
|
|
686
750
|
<!-- eslint-enable markdown/no-missing-label-refs -->
|
|
687
751
|
|
|
688
|
-
## 🎯 Type-Safe Translation Keys
|
|
689
|
-
|
|
690
|
-
The i18n plugin provides sophisticated TypeScript type support for translation keys. When using TypeScript, the `translate` function will provide auto-completion and type checking for:
|
|
691
|
-
|
|
692
|
-
- Built-in keys (`USAGE`, `OPTIONS`, `COMMANDS`, etc.)
|
|
693
|
-
- Argument keys based on your command's args definition (`arg:name`, `arg:verbose`, etc.)
|
|
694
|
-
- Custom keys defined in your resource
|
|
695
|
-
|
|
696
|
-
```ts
|
|
697
|
-
import { defineI18n } from '@gunshi/plugin-i18n'
|
|
698
|
-
|
|
699
|
-
const command = defineI18n({
|
|
700
|
-
name: 'example',
|
|
701
|
-
args: {
|
|
702
|
-
file: { type: 'string' },
|
|
703
|
-
verbose: { type: 'boolean' }
|
|
704
|
-
},
|
|
705
|
-
resource: async () => ({
|
|
706
|
-
description: 'Example command',
|
|
707
|
-
'arg:file': 'File to process',
|
|
708
|
-
'arg:verbose': 'Enable verbose output',
|
|
709
|
-
custom_message: 'This is a custom message'
|
|
710
|
-
}),
|
|
711
|
-
run: ctx => {
|
|
712
|
-
const { translate } = ctx.extensions['g:i18n']
|
|
713
|
-
|
|
714
|
-
// TypeScript knows these are valid keys
|
|
715
|
-
translate('USAGE') // Built-in key
|
|
716
|
-
translate('arg:file') // Arg key from command definition
|
|
717
|
-
translate('custom_message') // Custom key from resource
|
|
718
|
-
|
|
719
|
-
// TypeScript will error on invalid keys
|
|
720
|
-
// translate('invalid_key') // Type error!
|
|
721
|
-
}
|
|
722
|
-
})
|
|
723
|
-
```
|
|
724
|
-
|
|
725
752
|
## 📚 API References
|
|
726
753
|
|
|
727
754
|
See the [API References](./docs/index.md)
|
|
@@ -729,3 +756,11 @@ See the [API References](./docs/index.md)
|
|
|
729
756
|
## ©️ License
|
|
730
757
|
|
|
731
758
|
[MIT](http://opensource.org/licenses/MIT)
|
|
759
|
+
|
|
760
|
+
<!-- Badges -->
|
|
761
|
+
|
|
762
|
+
[npm-version-src]: https://img.shields.io/npm/v/@gunshi/plugin-i18n?style=flat
|
|
763
|
+
[npm-version-href]: https://npmjs.com/package/@gunshi/plugin-i18n@alpha
|
|
764
|
+
[jsr-src]: https://jsr.io/badges/@gunshi/plugin-i18n
|
|
765
|
+
[jsr-href]: https://jsr.io/@gunshi/plugin-i18n
|
|
766
|
+
[install-size-src]: https://pkg-size.dev/badge/install/67599
|