@x18n/builtins 0.0.0 → 0.0.2

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.
@@ -1,1096 +0,0 @@
1
- import { defaultTemplates } from "./extractors.mjs";
2
- import { n as sfcFluentBlocks, t as sfcBlocks } from "./sfc-blocks-CQhgEeT6.mjs";
3
- import { braces, colon, dollars, doubleBraces, fluent, icu, linked, nesting, percentBraces, placeholders, printf } from "./placeholders.mjs";
4
- import { r as regexScopes } from "./regex-350J_An-.mjs";
5
- import { isMessageLeaf } from "@x18n/core";
6
- //#region src/presets/shared.ts
7
- /** One plugin holding a library's call specs, regexes, namespace rules, defaults and extraction templates. */
8
- function library(options) {
9
- return {
10
- name: `x18n:${options.name}`,
11
- async config(draft, ctx) {
12
- if (options.namespace) draft.namespace = {
13
- separator: options.namespace.separator,
14
- default: draft.namespace.default ?? options.namespace.default
15
- };
16
- if (options.resources) draft.resources = [...draft.resources, ...options.resources.filter((spec) => !draft.resources.some((r) => r.pattern === spec.pattern))];
17
- if (options.keyStyle && draft.keyStyle === "auto" && !ctx.user.keyStyle) draft.keyStyle = options.keyStyle;
18
- draft.usage = {
19
- ...draft.usage,
20
- calls: [...draft.usage.calls, ...options.calls ?? []],
21
- regex: [...draft.usage.regex, ...options.regex ?? []],
22
- derivedKeys: [...draft.usage.derivedKeys, ...options.derivedKeys ?? []]
23
- };
24
- await options.extra?.(draft);
25
- },
26
- localeFinders: options.finders,
27
- normalizeKey: options.normalizeKey,
28
- transformResource: options.transformResource,
29
- translatePrompt: options.translatePrompt,
30
- extractors: options.templates ? [{
31
- id: options.name,
32
- templates: options.templates
33
- }] : void 0
34
- };
35
- }
36
- function dependsOn(names, prefixes = []) {
37
- return (ctx) => ctx.hasAnyDependency(names) || [...ctx.dependencies].some((dep) => prefixes.some((prefix) => dep.startsWith(prefix)));
38
- }
39
- /** Extensions of JS and TS sources. */
40
- const scriptExtensions = [
41
- "js",
42
- "jsx",
43
- "mjs",
44
- "cjs",
45
- "ts",
46
- "tsx",
47
- "mts",
48
- "cts"
49
- ];
50
- //#endregion
51
- //#region src/presets/angular.ts
52
- const templates = [
53
- "html",
54
- "ts",
55
- "js"
56
- ];
57
- function ngxTranslate() {
58
- return {
59
- name: "ngx-translate",
60
- detect: dependsOn(["@ngx-translate/core"]),
61
- plugins: [library({
62
- name: "ngx-translate",
63
- calls: [{ callee: [
64
- "translate.instant",
65
- "translate.get",
66
- "translate.stream",
67
- "translateService.instant",
68
- "translateService.get",
69
- "translateService.stream",
70
- "_"
71
- ] }],
72
- regex: [{
73
- extensions: templates,
74
- patterns: [
75
- "[`'\"]({key})[`'\"][\\s\\n]*\\|[\\s\\n]*translate\\b",
76
- "[\\s\\n]translate>[\\s\\n]*({key})[\\s\\n]*</",
77
- "\\[translate\\]=[\"']'({key})'[\"']",
78
- "\\stranslate=[\"']({key})[\"']"
79
- ]
80
- }],
81
- resources: [{ pattern: "src/assets/i18n/{locale}.json" }, { pattern: "src/assets/i18n/{locale}/{namespaces}.json" }],
82
- templates: [{
83
- template: "{{ '{key}' | translate }}",
84
- kinds: ["html-text"]
85
- }, {
86
- template: "this.translate.instant('{key}'{args})",
87
- kinds: ["js-string", "js-template"]
88
- }]
89
- }), placeholders(doubleBraces)]
90
- };
91
- }
92
- function transloco() {
93
- return {
94
- name: "transloco",
95
- detect: dependsOn(["@jsverse/transloco", "@ngneat/transloco"]),
96
- plugins: [
97
- library({
98
- name: "transloco",
99
- calls: [{ callee: [
100
- "translate",
101
- "translocoService.translate",
102
- "transloco.translate",
103
- "translocoService.selectTranslate",
104
- "transloco.selectTranslate"
105
- ] }],
106
- regex: [{
107
- extensions: templates,
108
- patterns: [
109
- "[`'\"]({key})[`'\"][\\s\\n]*\\|[\\s\\n]*transloco\\b",
110
- "[^\\w\\d]t\\([\\s\\n]*['\"`]({key})['\"`]",
111
- "[^*\\w\\d]transloco=['\"`]({key})['\"`]"
112
- ]
113
- }],
114
- resources: [{ pattern: "src/assets/i18n/{locale}.json" }, { pattern: "src/assets/i18n/{namespaces}/{locale}.json" }],
115
- templates: [{
116
- template: "{{ '{key}' | transloco }}",
117
- kinds: ["html-text"]
118
- }, {
119
- template: "translate('{key}'{args})",
120
- kinds: ["js-string", "js-template"],
121
- imports: ["import { translate } from '@jsverse/transloco'"]
122
- }]
123
- }),
124
- regexScopes("\\*transloco=\"[^\"]*read:\\s*'([^']+)'", "transloco-read", {
125
- as: "keyPrefix",
126
- extensions: ["html"]
127
- }),
128
- placeholders(doubleBraces)
129
- ]
130
- };
131
- }
132
- //#endregion
133
- //#region src/presets/nls.ts
134
- const nlsFile = /^(?:(.*)\/)?package\.nls(?:\.([\w-]+))?\.json$/;
135
- const bundleFile = /^(?:(.*)\/)?bundle\.l10n(?:\.([\w-]+))?\.json$/;
136
- /** VS Code extension strings: `package.nls[.locale].json` and `l10n/bundle.l10n[.locale].json`. */
137
- const nlsFinder = {
138
- id: "nls",
139
- async find(ctx) {
140
- const paths = await ctx.host.glob(["**/package.nls*.json", "**/bundle.l10n*.json"], {
141
- ignore: ["**/node_modules/**"],
142
- gitignore: true
143
- });
144
- const out = [];
145
- for (const path of paths) {
146
- const nls = nlsFile.exec(path);
147
- const bundle = nls ? void 0 : bundleFile.exec(path);
148
- const match = nls ?? bundle;
149
- if (!match) continue;
150
- out.push({
151
- path,
152
- locale: match[2] ?? ctx.config.sourceLocale,
153
- namespace: void 0,
154
- format: "json"
155
- });
156
- }
157
- return out;
158
- }
159
- };
160
- //#endregion
161
- //#region src/presets/js.ts
162
- const vueI18nCalls = [{ callee: [
163
- "$t",
164
- "t",
165
- "tc",
166
- "$tc",
167
- "te",
168
- "$te",
169
- "tm",
170
- "$tm",
171
- "i18n.t",
172
- "i18n.global.t",
173
- "$i18n.t",
174
- "i18n.tc",
175
- "i18n.te"
176
- ] }, {
177
- callee: "useI18n",
178
- factory: true,
179
- returns: [
180
- "t",
181
- "tc",
182
- "te",
183
- "tm"
184
- ]
185
- }];
186
- function vueI18n() {
187
- return {
188
- name: "vue-i18n",
189
- detect: dependsOn([
190
- "vue-i18n",
191
- "vuex-i18n",
192
- "petite-vue-i18n",
193
- "vue-i18n-bridge"
194
- ], ["@intlify/"]),
195
- plugins: [
196
- library({
197
- name: "vue-i18n",
198
- calls: vueI18nCalls,
199
- templates: [
200
- {
201
- template: "{{ $t('{key}'{args}) }}",
202
- kinds: ["vue-template-text"]
203
- },
204
- {
205
- template: ":{attr}=\"$t('{key}'{args})\"",
206
- kinds: ["vue-attribute"]
207
- },
208
- {
209
- template: "t('{key}'{args})",
210
- kinds: ["js-string", "js-template"],
211
- files: ["**/*.vue"],
212
- imports: ["import { useI18n } from 'vue-i18n'", "const { t } = useI18n()"]
213
- }
214
- ]
215
- }),
216
- placeholders(braces, linked),
217
- sfcBlocks()
218
- ]
219
- };
220
- }
221
- function nuxtI18n() {
222
- return {
223
- name: "nuxt-i18n",
224
- detect: dependsOn(["@nuxtjs/i18n", "nuxt-i18n"]),
225
- plugins: [...vueI18n().plugins, {
226
- name: "x18n:nuxt-i18n",
227
- async config(draft, ctx) {
228
- const nuxtConfig = await ctx.host.readFile("nuxt.config.ts") ?? await ctx.host.readFile("nuxt.config.js");
229
- const langDir = nuxtConfig ? /langDir:\s*['"]([^'"]+)['"]/.exec(nuxtConfig)?.[1]?.replace(/^\.\/|\/$/g, "") : void 0;
230
- const dirs = langDir ? [`i18n/${langDir}`, langDir] : [
231
- "i18n/locales",
232
- "locales",
233
- "lang"
234
- ];
235
- draft.resources = [...draft.resources, ...dirs.map((dir) => ({ pattern: `${dir}/{locale}.{ext}` }))];
236
- }
237
- }]
238
- };
239
- }
240
- const i18nextPlugin = library({
241
- name: "i18next",
242
- namespace: {
243
- separator: ":",
244
- default: "translation"
245
- },
246
- calls: [
247
- {
248
- callee: [
249
- "t",
250
- "i18next.t",
251
- "i18n.t"
252
- ],
253
- namespace: {
254
- arg: 1,
255
- property: "ns"
256
- }
257
- },
258
- {
259
- callee: [
260
- "getFixedT",
261
- "i18next.getFixedT",
262
- "i18n.getFixedT"
263
- ],
264
- factory: true,
265
- returns: ["t"],
266
- namespace: { arg: 1 },
267
- keyPrefix: { arg: 2 }
268
- },
269
- {
270
- callee: "tr",
271
- types: ["TFunction"]
272
- }
273
- ],
274
- derivedKeys: ["{key}_*"],
275
- translatePrompt: (draft, ctx) => {
276
- draft.notes.push(`i18next plural keys end in _${ctx.localeInfo.pluralCategories.join(", _")} for ${ctx.targetLocale}; write one key per category.`);
277
- },
278
- templates: [{
279
- template: "i18next.t('{key}'{args})",
280
- kinds: ["js-string", "js-template"],
281
- imports: ["import i18next from 'i18next'"]
282
- }]
283
- });
284
- function i18next() {
285
- return {
286
- name: "i18next",
287
- detect: dependsOn(["i18next"]),
288
- plugins: [i18nextPlugin, placeholders(doubleBraces, nesting)]
289
- };
290
- }
291
- function reactI18next() {
292
- return {
293
- name: "react-i18next",
294
- detect: dependsOn(["react-i18next", "next-i18next"]),
295
- plugins: [
296
- i18nextPlugin,
297
- placeholders(doubleBraces, nesting),
298
- library({
299
- name: "react-i18next",
300
- calls: [
301
- {
302
- callee: "useTranslation",
303
- factory: true,
304
- returns: ["t"],
305
- namespace: { arg: 0 },
306
- keyPrefix: {
307
- arg: 1,
308
- property: "keyPrefix"
309
- }
310
- },
311
- {
312
- callee: "Trans",
313
- key: {
314
- arg: 0,
315
- property: "i18nKey"
316
- },
317
- namespace: {
318
- arg: 0,
319
- property: "ns"
320
- }
321
- },
322
- {
323
- callee: "Translation",
324
- factory: true,
325
- returns: ["t"],
326
- namespace: {
327
- arg: 0,
328
- property: "ns"
329
- }
330
- }
331
- ],
332
- templates: [{
333
- template: "<Trans i18nKey=\"{key}\" />",
334
- kinds: ["jsx-text"],
335
- imports: ["import { Trans } from 'react-i18next'"]
336
- }, {
337
- template: "{attr}={i18next.t('{key}'{args})}",
338
- kinds: ["jsx-attribute"],
339
- imports: ["import i18next from 'i18next'"]
340
- }]
341
- })
342
- ]
343
- };
344
- }
345
- function nextIntl() {
346
- return {
347
- name: "next-intl",
348
- detect: dependsOn(["next-intl", "use-intl"]),
349
- plugins: [library({
350
- name: "next-intl",
351
- calls: [{
352
- callee: ["useTranslations", "getTranslations"],
353
- factory: true,
354
- returns: [
355
- "t",
356
- "t.rich",
357
- "t.markup",
358
- "t.raw",
359
- "t.has"
360
- ],
361
- keyPrefix: { arg: 0 }
362
- }, {
363
- callee: "getTranslations",
364
- factory: true,
365
- returns: [
366
- "t",
367
- "t.rich",
368
- "t.markup",
369
- "t.raw",
370
- "t.has"
371
- ],
372
- keyPrefix: {
373
- arg: 0,
374
- property: "namespace"
375
- }
376
- }],
377
- resources: [{ pattern: "messages/{locale}.json" }, { pattern: "src/messages/{locale}.json" }],
378
- templates: [
379
- {
380
- template: "{t('{key}'{args})}",
381
- kinds: ["jsx-text"]
382
- },
383
- {
384
- template: "{attr}={t('{key}'{args})}",
385
- kinds: ["jsx-attribute"]
386
- },
387
- {
388
- template: "t('{key}'{args})",
389
- kinds: ["js-string", "js-template"]
390
- }
391
- ]
392
- }), placeholders(icu)]
393
- };
394
- }
395
- function reactIntl() {
396
- return {
397
- name: "react-intl",
398
- detect: dependsOn(["react-intl"], ["@formatjs/"]),
399
- plugins: [library({
400
- name: "react-intl",
401
- calls: [{
402
- callee: [
403
- "intl.formatMessage",
404
- "formatMessage",
405
- "defineMessage",
406
- "FormattedMessage"
407
- ],
408
- key: {
409
- arg: 0,
410
- property: "id"
411
- }
412
- }, {
413
- callee: "defineMessages",
414
- key: {
415
- arg: 0,
416
- property: "*.id"
417
- }
418
- }],
419
- templates: [
420
- {
421
- template: "<FormattedMessage id=\"{key}\" />",
422
- kinds: ["jsx-text"],
423
- imports: ["import { FormattedMessage } from 'react-intl'"]
424
- },
425
- {
426
- template: "{attr}={intl.formatMessage({ id: '{key}' }{args})}",
427
- kinds: ["jsx-attribute"]
428
- },
429
- {
430
- template: "intl.formatMessage({ id: '{key}' }{args})",
431
- kinds: ["js-string", "js-template"]
432
- }
433
- ]
434
- }), placeholders(icu)]
435
- };
436
- }
437
- function svelteI18n() {
438
- return {
439
- name: "svelte-i18n",
440
- detect: dependsOn([
441
- "svelte-i18n",
442
- "sveltekit-i18n",
443
- "@sveltekit-i18n/base"
444
- ]),
445
- plugins: [library({
446
- name: "svelte-i18n",
447
- calls: [{ callee: [
448
- "$_",
449
- "$t",
450
- "$format",
451
- "_",
452
- "t",
453
- "format",
454
- "$json",
455
- "json"
456
- ] }],
457
- templates: [{
458
- template: "{$_('{key}'{args})}",
459
- kinds: ["svelte-text"],
460
- imports: ["import { _ } from 'svelte-i18n'"]
461
- }, {
462
- template: "{attr}={$_('{key}'{args})}",
463
- kinds: ["svelte-attribute"],
464
- imports: ["import { _ } from 'svelte-i18n'"]
465
- }]
466
- }), placeholders(icu)]
467
- };
468
- }
469
- function vscodeExtension() {
470
- return {
471
- name: "vscode-extension",
472
- detect: (ctx) => ctx.hasAnyDependency(["vscode", "@types/vscode"]),
473
- plugins: [library({
474
- name: "vscode-extension",
475
- calls: [{ callee: ["l10n.t", "vscode.l10n.t"] }],
476
- finders: [nlsFinder],
477
- extra: (draft) => {
478
- draft.usage = {
479
- ...draft.usage,
480
- regex: [...draft.usage.regex, {
481
- extensions: ["json"],
482
- patterns: ["\"%({key})%\""]
483
- }]
484
- };
485
- }
486
- }), placeholders(braces)]
487
- };
488
- }
489
- /** Always last: hard-string extraction templates for plain JS, TS and HTML. */
490
- function general() {
491
- return {
492
- name: "general",
493
- detect: () => true,
494
- plugins: [{
495
- name: "x18n:general",
496
- extractors: [{
497
- id: "general",
498
- templates: defaultTemplates
499
- }]
500
- }]
501
- };
502
- }
503
- //#endregion
504
- //#region src/presets/mobile.ts
505
- /** Flutter with `flutter_i18n`: JSON or YAML assets, `FlutterI18n.translate(context, 'key')`. */
506
- function flutter() {
507
- return {
508
- name: "flutter",
509
- detect: dependsOn(["flutter_i18n"]),
510
- plugins: [library({
511
- name: "flutter",
512
- regex: [{
513
- extensions: ["dart"],
514
- patterns: ["[^\\w\\d]FlutterI18n\\.(?:plural|translate)\\(\\s*[\\w\\d.]+,\\s*['\"`]({key})['\"`]", "[^\\w\\d]I18n(?:Plural|Text)\\(\\s*['\"`]({key})['\"`]"]
515
- }],
516
- resources: [{ pattern: "assets/flutter_i18n/{locale}.{ext}" }, { pattern: "assets/i18n/{locale}.{ext}" }],
517
- templates: [{ template: "FlutterI18n.translate(context, '{key}')" }]
518
- }), placeholders(braces)]
519
- };
520
- }
521
- //#endregion
522
- //#region src/presets/server.ts
523
- /** Laravel: `lang/{locale}/{file}.php` arrays and `lang/{locale}.json`; keys are `file.key`. Exclusive like i18n-ally. */
524
- function laravel() {
525
- return {
526
- name: "laravel",
527
- detect: dependsOn(["laravel/framework"]),
528
- exclusive: true,
529
- plugins: [library({
530
- name: "laravel",
531
- regex: [{
532
- extensions: ["php"],
533
- patterns: ["[^\\w\\d](?:__|trans|@lang|trans_choice|Lang::get|Lang::choice)\\(\\s*'([^']+)'", "[^\\w\\d](?:__|trans|@lang|trans_choice|Lang::get|Lang::choice)\\(\\s*\"([^\"]+)\""]
534
- }],
535
- resources: [
536
- { pattern: "lang/{locale}/{namespaces}.php" },
537
- { pattern: "resources/lang/{locale}/{namespaces}.php" },
538
- { pattern: "lang/{locale}.json" },
539
- { pattern: "resources/lang/{locale}.json" }
540
- ],
541
- normalizeKey: (raw) => raw.includes("/") ? raw.replace(/\//g, ".") : void 0,
542
- templates: [{ template: "__('{key}')" }]
543
- }), placeholders(colon)]
544
- };
545
- }
546
- /** Joomla: INI language files, `Text::_('KEY')`. */
547
- function phpJoomla() {
548
- return {
549
- name: "php-joomla",
550
- detect: dependsOn(["joomla/application", "joomla/cms"]),
551
- plugins: [library({
552
- name: "php-joomla",
553
- regex: [{
554
- extensions: ["php"],
555
- patterns: ["J?Text::(?:_|[\\w]+)\\(\\s*['\"]({key})['\"]"]
556
- }],
557
- resources: [{ pattern: "language/{locale}/*.ini" }, { pattern: "administrator/language/{locale}/*.ini" }],
558
- keyStyle: "flat",
559
- templates: [{ template: "Text::_('{key}')" }]
560
- }), placeholders(printf)]
561
- };
562
- }
563
- /** PHP gettext with `.po` files. Exclusive and never detected, as in i18n-ally: list it in `presets`. */
564
- function phpGettext() {
565
- return {
566
- name: "php-gettext",
567
- exclusive: true,
568
- plugins: [library({
569
- name: "php-gettext",
570
- regex: [{
571
- extensions: ["php"],
572
- patterns: ["[^\\w\\d](?:gettext|_|__)\\(\\s*['\"`]({key})['\"`]"]
573
- }],
574
- resources: [{ pattern: "locale/{locale}/LC_MESSAGES/*.po" }, { pattern: "locales/{locale}.po" }],
575
- extra: (draft) => {
576
- draft.extract = {
577
- keygen: "source",
578
- ...draft.extract
579
- };
580
- },
581
- templates: [{ template: "gettext('{key}')" }]
582
- }), placeholders(printf)]
583
- };
584
- }
585
- const viewSuffix = /(?:\.html)?\.(?:erb|haml|slim)$/;
586
- /** `t('.title')` in `app/views/users/index.html.erb` means `users.index.title`. */
587
- function railsLazyKey(raw, path) {
588
- if (!raw.startsWith(".")) return void 0;
589
- const match = /(?:^|\/)app\/views\/(.+)$/.exec(path);
590
- if (!match) return void 0;
591
- return `${match[1].replace(viewSuffix, "").split("/").map((segment) => segment.replace(/^_/, "")).join(".")}${raw}`;
592
- }
593
- function rubyRails() {
594
- return {
595
- name: "ruby-rails",
596
- detect: dependsOn([
597
- "rails",
598
- "rails-i18n",
599
- "railties"
600
- ]),
601
- plugins: [library({
602
- name: "ruby-rails",
603
- regex: [{
604
- extensions: [
605
- "rb",
606
- "erb",
607
- "haml",
608
- "slim"
609
- ],
610
- patterns: [
611
- "[^\\w\\d]t(?:\\(| )\\s*['\"`]({key})['\"`]",
612
- "[^\\w\\d]t\\(:({key})\\)",
613
- "I18n\\.t\\(\\s*['\"`]({key})['\"`]"
614
- ]
615
- }],
616
- resources: [
617
- { pattern: "config/locales/{locale}.yml" },
618
- { pattern: "config/locales/**/*.{locale}.yml" },
619
- { pattern: "config/locales/{locale}/**/*.yml" }
620
- ],
621
- normalizeKey: (raw, ctx) => railsLazyKey(raw, ctx.path),
622
- transformResource: {
623
- applies: (ctx) => /\.ya?ml$/.test(ctx.path),
624
- read(tree, ctx) {
625
- const root = tree[ctx.locale];
626
- return root !== void 0 && !isMessageLeaf(root) ? root : {};
627
- },
628
- toStored: (path, ctx) => [ctx.locale, ...path]
629
- },
630
- templates: [{ template: "t('{key}')" }]
631
- }), placeholders(percentBraces)]
632
- };
633
- }
634
- function jekyll() {
635
- return {
636
- name: "jekyll",
637
- detect: dependsOn(["jekyll-multiple-languages-plugin"]),
638
- plugins: [library({
639
- name: "jekyll",
640
- regex: [{
641
- extensions: [
642
- "html",
643
- "md",
644
- "liquid"
645
- ],
646
- patterns: ["\\{%\\s+t\\s+({key})\\s+%\\}"]
647
- }],
648
- resources: [{ pattern: "_i18n/{locale}.yml" }],
649
- keyStyle: "nested",
650
- templates: [{ template: "{% t {key} %}" }]
651
- })]
652
- };
653
- }
654
- //#endregion
655
- //#region src/presets/web.ts
656
- const jsxTemplates = [
657
- {
658
- template: "{t('{key}'{args})}",
659
- kinds: ["jsx-text"]
660
- },
661
- {
662
- template: "{attr}={t('{key}'{args})}",
663
- kinds: ["jsx-attribute"]
664
- },
665
- {
666
- template: "t('{key}'{args})",
667
- kinds: ["js-string", "js-template"]
668
- }
669
- ];
670
- function nextInternational() {
671
- return {
672
- name: "next-international",
673
- detect: dependsOn(["next-international"]),
674
- plugins: [library({
675
- name: "next-international",
676
- calls: [{
677
- callee: ["useI18n", "getI18n"],
678
- factory: true,
679
- returns: ["t"]
680
- }, {
681
- callee: ["useScopedI18n", "getScopedI18n"],
682
- factory: true,
683
- returns: ["t"],
684
- keyPrefix: { arg: 0 }
685
- }],
686
- resources: [{ pattern: "locales/{locale}.{ext}" }, { pattern: "src/locales/{locale}.{ext}" }],
687
- templates: jsxTemplates
688
- }), placeholders(braces)]
689
- };
690
- }
691
- function nextTranslate() {
692
- return {
693
- name: "next-translate",
694
- detect: dependsOn(["next-translate"]),
695
- plugins: [library({
696
- name: "next-translate",
697
- namespace: {
698
- separator: ":",
699
- default: "common"
700
- },
701
- calls: [
702
- {
703
- callee: "useTranslation",
704
- factory: true,
705
- returns: ["t"],
706
- namespace: { arg: 0 }
707
- },
708
- {
709
- callee: "getT",
710
- factory: true,
711
- returns: ["t"],
712
- namespace: { arg: 1 }
713
- },
714
- {
715
- callee: "Trans",
716
- key: {
717
- arg: 0,
718
- property: "i18nKey"
719
- },
720
- namespace: {
721
- arg: 0,
722
- property: "ns"
723
- }
724
- },
725
- { callee: "t" }
726
- ],
727
- regex: [{
728
- extensions: scriptExtensions,
729
- patterns: ["[^\\w\\d]t`({key})`"]
730
- }],
731
- resources: [{ pattern: "locales/{locale}/{namespace}.json" }],
732
- keyStyle: "nested",
733
- templates: jsxTemplates
734
- }), placeholders(doubleBraces)]
735
- };
736
- }
737
- /** Shopify's i18next format: plural and ordinal forms as nested keys (`{key}.one`). */
738
- function i18nextShopify() {
739
- const forms = [
740
- "plural",
741
- "zero",
742
- "one",
743
- "two",
744
- "few",
745
- "many",
746
- "other",
747
- ...Array.from({ length: 10 }, (_, i) => String(i))
748
- ];
749
- return {
750
- name: "i18next-shopify",
751
- detect: dependsOn(["@shopify/i18next-shopify"]),
752
- plugins: [
753
- ...reactI18next().plugins,
754
- library({
755
- name: "i18next-shopify",
756
- derivedKeys: forms.map((form) => `{key}.${form}`),
757
- keyStyle: "nested"
758
- }),
759
- placeholders(braces)
760
- ]
761
- };
762
- }
763
- function i18nTag() {
764
- return {
765
- name: "i18n-tag",
766
- detect: dependsOn(["es2015-i18n-tag"]),
767
- plugins: [library({
768
- name: "i18n-tag",
769
- regex: [{
770
- extensions: [...scriptExtensions, "vue"],
771
- patterns: ["i18n`({key})`"]
772
- }],
773
- templates: [{
774
- template: "i18n`{key}`",
775
- kinds: ["js-string", "js-template"]
776
- }]
777
- })]
778
- };
779
- }
780
- function fluentVue() {
781
- return {
782
- name: "fluent-vue",
783
- detect: dependsOn([
784
- "fluent-vue",
785
- "fluent-vue-loader",
786
- "rollup-plugin-fluent-vue",
787
- "unplugin-fluent-vue"
788
- ]),
789
- plugins: [
790
- library({
791
- name: "fluent-vue",
792
- calls: [{ callee: [
793
- "$t",
794
- "$ta",
795
- "fluent.format",
796
- "fluent.formatAttrs",
797
- "this.$t",
798
- "this.$ta"
799
- ] }, {
800
- callee: "useFluent",
801
- factory: true,
802
- returns: [
803
- "$t",
804
- "$ta",
805
- "format",
806
- "formatAttrs"
807
- ]
808
- }],
809
- regex: [{
810
- extensions: ["vue"],
811
- patterns: ["v-t:({key})[\\s\\n=>]", "<i18n[\\s\\n]+path=['\"`]({key})['\"`]"]
812
- }],
813
- resources: [{ pattern: "locales/{locale}.ftl" }, { pattern: "src/locales/{locale}.ftl" }],
814
- templates: [
815
- {
816
- template: "{{ $t('{key}'{args}) }}",
817
- kinds: ["vue-template-text"]
818
- },
819
- {
820
- template: ":{attr}=\"$t('{key}'{args})\"",
821
- kinds: ["vue-attribute"]
822
- },
823
- {
824
- template: "$t('{key}'{args})",
825
- kinds: ["js-string", "js-template"]
826
- }
827
- ]
828
- }),
829
- sfcFluentBlocks(),
830
- placeholders(fluent)
831
- ]
832
- };
833
- }
834
- function polyglot() {
835
- return {
836
- name: "polyglot",
837
- detect: dependsOn(["node-polyglot"]),
838
- plugins: [library({
839
- name: "polyglot",
840
- calls: [{ callee: ["polyglot.t", "I18n.t"] }],
841
- regex: [{
842
- extensions: ["rb"],
843
- patterns: ["(?:polyglot|I18n)\\.t\\(\\s*['\"`]({key})['\"`]"]
844
- }],
845
- templates: [{
846
- template: "polyglot.t('{key}'{args})",
847
- kinds: ["js-string", "js-template"]
848
- }]
849
- }), placeholders(percentBraces)]
850
- };
851
- }
852
- function globalize() {
853
- return {
854
- name: "globalize",
855
- detect: dependsOn(["globalize"]),
856
- plugins: [library({
857
- name: "globalize",
858
- calls: [{ callee: [
859
- "Globalize.messageFormatter",
860
- "Globalize.formatMessage",
861
- "globalize.messageFormatter",
862
- "globalize.formatMessage"
863
- ] }],
864
- normalizeKey: (raw) => raw.includes("/") ? raw.replace(/\//g, ".") : void 0,
865
- templates: [{
866
- template: "Globalize.formatMessage('{key}'{args})",
867
- kinds: ["js-string", "js-template"]
868
- }]
869
- }), placeholders(icu)]
870
- };
871
- }
872
- function ui5() {
873
- return {
874
- name: "ui5",
875
- detect: dependsOn(["@ui5/cli"]),
876
- plugins: [library({
877
- name: "ui5",
878
- regex: [{
879
- extensions: [
880
- "xml",
881
- "json",
882
- ...scriptExtensions
883
- ],
884
- patterns: ["\\{i18n>({key})\\}"]
885
- }, {
886
- extensions: scriptExtensions,
887
- patterns: ["getResourceBundle\\(\\)\\.getText\\(\\s*['\"`]({key})['\"`]"]
888
- }],
889
- resources: [{ pattern: "webapp/i18n/i18n_{locale}.properties" }, { pattern: "webapp/i18n/i18n.properties" }],
890
- keyStyle: "flat",
891
- templates: [{
892
- template: "{i18n>{key}}",
893
- files: ["**/*.xml"]
894
- }, {
895
- template: "this.getResourceBundle().getText('{key}')",
896
- kinds: ["js-string", "js-template"]
897
- }]
898
- }), placeholders(braces)]
899
- };
900
- }
901
- function lingui() {
902
- return {
903
- name: "lingui",
904
- detect: dependsOn([
905
- "@lingui/core",
906
- "@lingui/react",
907
- "@lingui/macro"
908
- ]),
909
- plugins: [library({
910
- name: "lingui",
911
- calls: [
912
- { callee: [
913
- "i18n._",
914
- "i18n.t",
915
- "t",
916
- "_"
917
- ] },
918
- {
919
- callee: [
920
- "t",
921
- "msg",
922
- "defineMessage",
923
- "i18n._",
924
- "Trans"
925
- ],
926
- key: {
927
- arg: 0,
928
- property: "id"
929
- }
930
- },
931
- {
932
- callee: "useLingui",
933
- factory: true,
934
- returns: ["t", "_"]
935
- }
936
- ],
937
- regex: [{
938
- extensions: scriptExtensions,
939
- patterns: ["\\bt`({key})`", "<Trans>[\\s]*({key})[\\s]*<\\/Trans>"]
940
- }],
941
- resources: [{ pattern: "src/locales/{locale}/messages.po" }, { pattern: "locales/{locale}/messages.po" }],
942
- extra: (draft) => {
943
- draft.extract = {
944
- keygen: "source",
945
- ...draft.extract
946
- };
947
- },
948
- templates: [{
949
- template: "<Trans>{key}</Trans>",
950
- kinds: ["jsx-text"],
951
- imports: ["import { Trans } from '@lingui/react/macro'"]
952
- }, {
953
- template: "t`{key}`",
954
- kinds: ["js-string", "js-template"],
955
- imports: ["import { t } from '@lingui/core/macro'"]
956
- }]
957
- }), placeholders(icu)]
958
- };
959
- }
960
- function emberIntl() {
961
- return {
962
- name: "ember-intl",
963
- detect: dependsOn(["ember-intl"]),
964
- plugins: [library({
965
- name: "ember-intl",
966
- calls: [{ callee: ["intl.t"] }],
967
- regex: [{
968
- extensions: [
969
- "hbs",
970
- "gjs",
971
- "gts"
972
- ],
973
- patterns: ["\\{\\{\\s*t\\s+['\"`]({key})['\"`]", "\\(\\s*t\\s+['\"`]({key})['\"`]"]
974
- }],
975
- resources: [{ pattern: "translations/{locale}.{ext}" }, { pattern: "translations/{namespaces}/{locale}.{ext}" }],
976
- templates: [{
977
- template: "{{t '{key}'}}",
978
- files: ["**/*.hbs"]
979
- }, {
980
- template: "this.intl.t('{key}'{args})",
981
- kinds: ["js-string", "js-template"]
982
- }]
983
- }), placeholders(icu)]
984
- };
985
- }
986
- function i18nJs() {
987
- return {
988
- name: "i18n-js",
989
- detect: dependsOn(["i18n-js"]),
990
- plugins: [library({
991
- name: "i18n-js",
992
- calls: [{ callee: ["I18n.t", "i18n.t"] }],
993
- templates: [{
994
- template: "i18n.t('{key}'{args})",
995
- kinds: ["js-string", "js-template"]
996
- }]
997
- }), placeholders(percentBraces)]
998
- };
999
- }
1000
- /** Chrome and WebExtension `_locales/{locale}/messages.json`: `{ "name": { "message": "..." } }` reads as `name`. */
1001
- function chromeExtension() {
1002
- return {
1003
- name: "chrome-extension",
1004
- async detect(ctx) {
1005
- for (const path of [
1006
- "manifest.json",
1007
- "src/manifest.json",
1008
- "public/manifest.json"
1009
- ]) if ((await ctx.host.readFile(path))?.includes("\"default_locale\"")) return true;
1010
- return false;
1011
- },
1012
- plugins: [
1013
- library({
1014
- name: "chrome-extension",
1015
- calls: [{ callee: [
1016
- "chrome.i18n.getMessage",
1017
- "browser.i18n.getMessage",
1018
- "i18n.getMessage"
1019
- ] }],
1020
- regex: [{
1021
- extensions: [
1022
- "json",
1023
- "html",
1024
- "css"
1025
- ],
1026
- patterns: ["__MSG_({key})__"]
1027
- }],
1028
- resources: [{ pattern: "_locales/{locale}/messages.json" }, { pattern: "{src,public,extension}/_locales/{locale}/messages.json" }],
1029
- transformResource: {
1030
- applies: (ctx) => /(?:^|\/)_locales\/[^/]+\/messages\.json$/.test(ctx.path),
1031
- read(tree) {
1032
- const out = {};
1033
- for (const [name, entry] of Object.entries(tree)) {
1034
- const message = isMessageLeaf(entry) ? void 0 : entry.message;
1035
- if (message !== void 0 && isMessageLeaf(message)) out[name] = message;
1036
- }
1037
- return out;
1038
- },
1039
- toStored: (path) => [path.join("."), "message"]
1040
- },
1041
- templates: [{
1042
- template: "chrome.i18n.getMessage('{key}')",
1043
- kinds: ["js-string", "js-template"]
1044
- }]
1045
- }),
1046
- {
1047
- name: "x18n:chrome-extension-source-locale",
1048
- async config(draft, ctx) {
1049
- const manifest = await ctx.host.readFile("manifest.json") ?? await ctx.host.readFile("src/manifest.json") ?? await ctx.host.readFile("public/manifest.json");
1050
- const locale = manifest ? /"default_locale"\s*:\s*"([^"]+)"/.exec(manifest)?.[1] : void 0;
1051
- if (locale) draft.sourceLocale = locale;
1052
- }
1053
- },
1054
- placeholders(dollars)
1055
- ]
1056
- };
1057
- }
1058
- //#endregion
1059
- //#region src/presets/index.ts
1060
- /**
1061
- * Presets by name, in detection order: every i18n-ally framework has one.
1062
- * Presets that share plugins (react-i18next and i18next) apply them once.
1063
- */
1064
- const presets = {
1065
- "nuxt-i18n": () => nuxtI18n(),
1066
- "vue-i18n": () => vueI18n(),
1067
- "fluent-vue": () => fluentVue(),
1068
- "i18next-shopify": () => i18nextShopify(),
1069
- "react-i18next": () => reactI18next(),
1070
- "next-translate": () => nextTranslate(),
1071
- "next-international": () => nextInternational(),
1072
- "i18next": () => i18next(),
1073
- "next-intl": () => nextIntl(),
1074
- "react-intl": () => reactIntl(),
1075
- "svelte-i18n": () => svelteI18n(),
1076
- "ngx-translate": () => ngxTranslate(),
1077
- "transloco": () => transloco(),
1078
- "lingui": () => lingui(),
1079
- "ember-intl": () => emberIntl(),
1080
- "polyglot": () => polyglot(),
1081
- "globalize": () => globalize(),
1082
- "i18n-tag": () => i18nTag(),
1083
- "i18n-js": () => i18nJs(),
1084
- "ui5": () => ui5(),
1085
- "chrome-extension": () => chromeExtension(),
1086
- "vscode-extension": () => vscodeExtension(),
1087
- "laravel": () => laravel(),
1088
- "php-joomla": () => phpJoomla(),
1089
- "php-gettext": () => phpGettext(),
1090
- "ruby-rails": () => rubyRails(),
1091
- "jekyll": () => jekyll(),
1092
- "flutter": () => flutter(),
1093
- "general": () => general()
1094
- };
1095
- //#endregion
1096
- export { ngxTranslate as A, nextIntl as C, svelteI18n as D, reactIntl as E, vscodeExtension as O, i18next as S, reactI18next as T, phpJoomla as _, globalize as a, flutter as b, i18nextShopify as c, nextTranslate as d, polyglot as f, phpGettext as g, laravel as h, fluentVue as i, transloco as j, vueI18n as k, lingui as l, jekyll as m, chromeExtension as n, i18nJs as o, ui5 as p, emberIntl as r, i18nTag as s, presets as t, nextInternational as u, railsLazyKey as v, nuxtI18n as w, general as x, rubyRails as y };