@genrwork/laravel-i18next 0.1.0 → 0.1.1
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 +110 -28
- package/dist/index.cjs +125 -3
- package/dist/index.mjs +124 -1
- package/dist/react.cjs +7 -5
- package/dist/react.mjs +7 -5
- package/dist/shared/{create-i18n-WsDK4Z8L.cjs → create-i18n-DI7Eog6O.cjs} +83 -333
- package/dist/shared/{create-i18n-BSEwKsCX.mjs → create-i18n-DaZzs1DJ.mjs} +78 -333
- package/dist/shared/demand-6YnTqSM4.mjs +92 -0
- package/dist/shared/demand-sbjTXVnl.cjs +101 -0
- package/dist/svelte.cjs +7 -1
- package/dist/svelte.mjs +7 -1
- package/dist/types/contrib/get-plural-index.d.ts +1 -1
- package/dist/types/defaults.d.ts +18 -0
- package/dist/types/demand.d.ts +51 -0
- package/dist/types/index.d.ts +5 -3
- package/dist/types/plugin/convert.d.ts +10 -0
- package/dist/types/plugin/namespaces.d.ts +20 -0
- package/dist/types/plugin/parser.d.ts +3 -0
- package/dist/types/plugin/sources.d.ts +5 -5
- package/dist/types/preload.d.ts +99 -0
- package/dist/types/react/i18n-provider-props.d.ts +5 -0
- package/dist/types/react/provider.d.ts +4 -3
- package/dist/types/shared/create-i18n.d.ts +9 -3
- package/dist/types/utils/cache.d.ts +3 -0
- package/dist/types/vite.d.ts +18 -1
- package/dist/vite.cjs +408 -6
- package/dist/vite.mjs +408 -6
- package/dist/vue.cjs +2 -1
- package/dist/vue.mjs +2 -1
- package/package.json +155 -155
- package/dist/types/format.d.ts +0 -43
- package/dist/types/interfaces/replacements.d.ts +0 -6
- package/dist/types/utils/replacer.d.ts +0 -9
- /package/dist/types/{utils → plugin}/pluralization.d.ts +0 -0
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var i18next = require('i18next');
|
|
4
|
+
var demand = require('./demand-sbjTXVnl.cjs');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The modules lazy loaders (`import.meta.glob()` functions) have already
|
|
8
|
+
* resolved, keyed by the loader itself. Loading a language file is the one
|
|
9
|
+
* asynchronous step of translating; once a loader has been awaited, its
|
|
10
|
+
* module never changes, so every later read of it can be synchronous. That is
|
|
11
|
+
* what lets `preloadI18n()` load translations during page resolution --
|
|
12
|
+
* before anything renders -- and lets `createI18n()` and the backend read
|
|
13
|
+
* them without waiting, so a render never has to suspend.
|
|
14
|
+
*
|
|
15
|
+
* Module scoped on purpose, so it is shared by every i18next instance of the
|
|
16
|
+
* process: a server keeps one copy of each catalog across requests.
|
|
17
|
+
*/ const modules = new WeakMap();
|
|
18
|
+
function getCachedModule(loader) {
|
|
19
|
+
return modules.get(loader);
|
|
20
|
+
}
|
|
21
|
+
function setCachedModule(loader, module) {
|
|
22
|
+
modules.set(loader, module);
|
|
23
|
+
}
|
|
4
24
|
|
|
5
25
|
/**
|
|
6
26
|
* Normalize a `LocaleFileSources` (a single `LocaleFiles` map, or an ordered
|
|
@@ -138,6 +158,9 @@ var i18next = require('i18next');
|
|
|
138
158
|
* module; eager files (`import.meta.glob(..., { eager: true })`) resolve to a
|
|
139
159
|
* module directly; a plain object (hand-built maps, tests) is wrapped as a
|
|
140
160
|
* module's `default`.
|
|
161
|
+
*
|
|
162
|
+
* A loader that was awaited before resolves to its module directly, from the
|
|
163
|
+
* cache (see `src/utils/cache.ts`): reading it is synchronous from then on.
|
|
141
164
|
*/ function toModule(entry) {
|
|
142
165
|
const type = Object.prototype.toString.call(entry);
|
|
143
166
|
if (type === '[object Promise]' || type === '[object Module]') {
|
|
@@ -148,8 +171,14 @@ var i18next = require('i18next');
|
|
|
148
171
|
default: entry
|
|
149
172
|
};
|
|
150
173
|
}
|
|
151
|
-
if (
|
|
152
|
-
|
|
174
|
+
if (typeof entry === 'function') {
|
|
175
|
+
const loader = entry;
|
|
176
|
+
const cached = getCachedModule(loader);
|
|
177
|
+
if (cached) return cached;
|
|
178
|
+
return Promise.resolve(loader()).then((module)=>{
|
|
179
|
+
setCachedModule(loader, module);
|
|
180
|
+
return module;
|
|
181
|
+
});
|
|
153
182
|
}
|
|
154
183
|
return undefined;
|
|
155
184
|
}
|
|
@@ -244,335 +273,36 @@ function isPromiseLike(value) {
|
|
|
244
273
|
}
|
|
245
274
|
LaravelBackend.type = 'backend';
|
|
246
275
|
|
|
247
|
-
/* eslint-disable */ /**
|
|
248
|
-
* Get the index to use for pluralization.
|
|
249
|
-
* The plural rules are derived from code of the Zend Framework.
|
|
250
|
-
*
|
|
251
|
-
* @category Zend
|
|
252
|
-
* @package Zend_Locale
|
|
253
|
-
* @public https://github.com/zendframework/zf1/blob/master/library/Zend/Translate/Plural.php
|
|
254
|
-
* @copyright 2005-2015 Zend Technologies USA Inc. http://www.zend.com
|
|
255
|
-
* @license http://framework.zend.com/license New BSD License
|
|
256
|
-
*
|
|
257
|
-
* @param {String} locale
|
|
258
|
-
* @param {Number} number
|
|
259
|
-
* @return {Number}
|
|
260
|
-
*/ function getPluralIndex(locale, number) {
|
|
261
|
-
locale = locale.replace('-', '_');
|
|
262
|
-
if (locale === 'pt_BR') {
|
|
263
|
-
// temporary set a locale for brazilian
|
|
264
|
-
locale = 'xbr';
|
|
265
|
-
}
|
|
266
|
-
if (locale.length > 3) {
|
|
267
|
-
locale = locale.substring(0, locale.lastIndexOf('_'));
|
|
268
|
-
}
|
|
269
|
-
switch(locale){
|
|
270
|
-
case 'az':
|
|
271
|
-
case 'bo':
|
|
272
|
-
case 'dz':
|
|
273
|
-
case 'id':
|
|
274
|
-
case 'ja':
|
|
275
|
-
case 'jv':
|
|
276
|
-
case 'ka':
|
|
277
|
-
case 'km':
|
|
278
|
-
case 'kn':
|
|
279
|
-
case 'ko':
|
|
280
|
-
case 'ms':
|
|
281
|
-
case 'th':
|
|
282
|
-
case 'tr':
|
|
283
|
-
case 'vi':
|
|
284
|
-
case 'zh':
|
|
285
|
-
return 0;
|
|
286
|
-
case 'af':
|
|
287
|
-
case 'bn':
|
|
288
|
-
case 'bg':
|
|
289
|
-
case 'ca':
|
|
290
|
-
case 'da':
|
|
291
|
-
case 'de':
|
|
292
|
-
case 'el':
|
|
293
|
-
case 'en':
|
|
294
|
-
case 'eo':
|
|
295
|
-
case 'es':
|
|
296
|
-
case 'et':
|
|
297
|
-
case 'eu':
|
|
298
|
-
case 'fa':
|
|
299
|
-
case 'fi':
|
|
300
|
-
case 'fo':
|
|
301
|
-
case 'fur':
|
|
302
|
-
case 'fy':
|
|
303
|
-
case 'gl':
|
|
304
|
-
case 'gu':
|
|
305
|
-
case 'ha':
|
|
306
|
-
case 'he':
|
|
307
|
-
case 'hu':
|
|
308
|
-
case 'is':
|
|
309
|
-
case 'it':
|
|
310
|
-
case 'ku':
|
|
311
|
-
case 'lb':
|
|
312
|
-
case 'ml':
|
|
313
|
-
case 'mn':
|
|
314
|
-
case 'mr':
|
|
315
|
-
case 'nah':
|
|
316
|
-
case 'nb':
|
|
317
|
-
case 'ne':
|
|
318
|
-
case 'nl':
|
|
319
|
-
case 'nn':
|
|
320
|
-
case 'no':
|
|
321
|
-
case 'om':
|
|
322
|
-
case 'or':
|
|
323
|
-
case 'pa':
|
|
324
|
-
case 'pap':
|
|
325
|
-
case 'ps':
|
|
326
|
-
case 'pt':
|
|
327
|
-
case 'so':
|
|
328
|
-
case 'sq':
|
|
329
|
-
case 'sv':
|
|
330
|
-
case 'sw':
|
|
331
|
-
case 'ta':
|
|
332
|
-
case 'te':
|
|
333
|
-
case 'tk':
|
|
334
|
-
case 'ur':
|
|
335
|
-
case 'zu':
|
|
336
|
-
return number === 1 ? 0 : 1;
|
|
337
|
-
case 'am':
|
|
338
|
-
case 'bh':
|
|
339
|
-
case 'fil':
|
|
340
|
-
case 'fr':
|
|
341
|
-
case 'gun':
|
|
342
|
-
case 'hi':
|
|
343
|
-
case 'ln':
|
|
344
|
-
case 'mg':
|
|
345
|
-
case 'nso':
|
|
346
|
-
case 'xbr':
|
|
347
|
-
case 'ti':
|
|
348
|
-
case 'wa':
|
|
349
|
-
return number === 0 || number === 1 ? 0 : 1;
|
|
350
|
-
case 'be':
|
|
351
|
-
case 'bs':
|
|
352
|
-
case 'hr':
|
|
353
|
-
case 'ru':
|
|
354
|
-
case 'sr':
|
|
355
|
-
case 'uk':
|
|
356
|
-
return number % 10 === 1 && number % 100 !== 11 ? 0 : number % 10 >= 2 && number % 10 <= 4 && (number % 100 < 10 || number % 100 >= 20) ? 1 : 2;
|
|
357
|
-
case 'cs':
|
|
358
|
-
case 'sk':
|
|
359
|
-
return number === 1 ? 0 : number >= 2 && number <= 4 ? 1 : 2;
|
|
360
|
-
case 'ga':
|
|
361
|
-
return number === 1 ? 0 : number === 2 ? 1 : 2;
|
|
362
|
-
case 'lt':
|
|
363
|
-
return number % 10 === 1 && number % 100 !== 11 ? 0 : number % 10 >= 2 && (number % 100 < 10 || number % 100 >= 20) ? 1 : 2;
|
|
364
|
-
case 'sl':
|
|
365
|
-
return number % 100 === 1 ? 0 : number % 100 === 2 ? 1 : number % 100 === 3 || number % 100 === 4 ? 2 : 3;
|
|
366
|
-
case 'mk':
|
|
367
|
-
return number % 10 === 1 ? 0 : 1;
|
|
368
|
-
case 'mt':
|
|
369
|
-
return number === 1 ? 0 : number === 0 || number % 100 > 1 && number % 100 < 11 ? 1 : number % 100 > 10 && number % 100 < 20 ? 2 : 3;
|
|
370
|
-
case 'lv':
|
|
371
|
-
return number === 0 ? 0 : number % 10 === 1 && number % 100 !== 11 ? 1 : 2;
|
|
372
|
-
case 'pl':
|
|
373
|
-
return number === 1 ? 0 : number % 10 >= 2 && number % 10 <= 4 && (number % 100 < 12 || number % 100 > 14) ? 1 : 2;
|
|
374
|
-
case 'cy':
|
|
375
|
-
return number === 1 ? 0 : number === 2 ? 1 : number === 8 || number === 11 ? 2 : 3;
|
|
376
|
-
case 'ro':
|
|
377
|
-
return number === 1 ? 0 : number === 0 || number % 100 > 0 && number % 100 < 20 ? 1 : 2;
|
|
378
|
-
case 'ar':
|
|
379
|
-
return number === 0 ? 0 : number === 1 ? 1 : number === 2 ? 2 : number >= 3 && number <= 10 ? 3 : number >= 11 && number <= 99 ? 4 : 5;
|
|
380
|
-
default:
|
|
381
|
-
return 0;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
276
|
/**
|
|
386
|
-
*
|
|
387
|
-
*
|
|
277
|
+
* The i18next options Laravel translations need. `createI18n()` applies them;
|
|
278
|
+
* pass them to `init()` yourself when you set i18next up by hand.
|
|
388
279
|
*
|
|
389
|
-
*
|
|
390
|
-
*
|
|
391
|
-
*
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
280
|
+
* - no key or namespace separator: Laravel keys are flat and contain dots
|
|
281
|
+
* and colons (`auth.failed`, `Email:`);
|
|
282
|
+
* - an empty message counts as missing and falls back to the next language;
|
|
283
|
+
* - no escaping of interpolated values: React, Vue and Svelte already escape
|
|
284
|
+
* what they render, and Laravel's `:name` replacements were never escaped.
|
|
285
|
+
*/ const laravelOptions = {
|
|
286
|
+
keySeparator: false,
|
|
287
|
+
nsSeparator: false,
|
|
288
|
+
returnEmptyString: false,
|
|
289
|
+
interpolation: {
|
|
290
|
+
escapeValue: false
|
|
397
291
|
}
|
|
398
|
-
|
|
399
|
-
const pluralIndex = getPluralIndex(locale, number);
|
|
400
|
-
return segments.length === 1 || !segments[pluralIndex] ? segments[0] : segments[pluralIndex];
|
|
401
|
-
}
|
|
292
|
+
};
|
|
402
293
|
/**
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Get the translation string if the condition matches.
|
|
416
|
-
*
|
|
417
|
-
* @param part
|
|
418
|
-
* @param number
|
|
419
|
-
*/ function extractFromString(part, number) {
|
|
420
|
-
const matches = part.match(/^[{[]([^,{}[\]]*),?([^{}[\]]*)[}\]]([\s\S]*)/);
|
|
421
|
-
if (!matches) return null;
|
|
422
|
-
const [, from, to, value] = matches;
|
|
423
|
-
if ((from === '*' || number >= parseFloat(from)) && (to === '*' || number <= parseFloat(to))) {
|
|
424
|
-
return value;
|
|
425
|
-
}
|
|
426
|
-
return from && parseFloat(from) === number ? value : null;
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Strip the inline conditions from each segment, just leaving the text.
|
|
430
|
-
*
|
|
431
|
-
* @param segments
|
|
432
|
-
*/ function stripConditions(segments) {
|
|
433
|
-
return segments.map((part)=>part.replace(/^[{[]([^[\]{}]*)[}\]]/, ''));
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* Make the place-holder replacements on a line, the Laravel way:
|
|
438
|
-
* `:name` as is, `:NAME` upper-cased and `:Name` capitalized.
|
|
439
|
-
*
|
|
440
|
-
* @param message
|
|
441
|
-
* @param replacements
|
|
442
|
-
*/ function replacer(message, replacements) {
|
|
443
|
-
if (!replacements) return message;
|
|
444
|
-
const patterns = Object.entries(replacements).flatMap(([key, value])=>[
|
|
445
|
-
{
|
|
446
|
-
pattern: new RegExp(`:${key}`, 'g'),
|
|
447
|
-
replacement: value.toString()
|
|
448
|
-
},
|
|
449
|
-
{
|
|
450
|
-
pattern: new RegExp(`:${key.toUpperCase()}`, 'g'),
|
|
451
|
-
replacement: value.toString().toUpperCase()
|
|
452
|
-
},
|
|
453
|
-
{
|
|
454
|
-
pattern: new RegExp(`:${capitalize(key)}`, 'g'),
|
|
455
|
-
replacement: capitalize(value.toString())
|
|
456
|
-
}
|
|
457
|
-
]);
|
|
458
|
-
return patterns.reduce((result, { pattern, replacement })=>result.replace(pattern, replacement), message);
|
|
459
|
-
}
|
|
460
|
-
/**
|
|
461
|
-
* Capitalizing string.
|
|
462
|
-
*
|
|
463
|
-
* @param str
|
|
464
|
-
*/ function capitalize(str) {
|
|
465
|
-
return str ? str[0].toUpperCase() + str.slice(1) : '';
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
* i18next `t()` options that are not Laravel replacements. Use the `replace`
|
|
470
|
-
* option to pass replacements having one of these names.
|
|
471
|
-
*/ const I18NEXT_OPTIONS = new Set([
|
|
472
|
-
'appendNamespaceToMissingKey',
|
|
473
|
-
'applyPostProcessor',
|
|
474
|
-
'context',
|
|
475
|
-
'fallbackLng',
|
|
476
|
-
'i18nResolved',
|
|
477
|
-
'interpolation',
|
|
478
|
-
'joinArrays',
|
|
479
|
-
'keyPrefix',
|
|
480
|
-
'keySeparator',
|
|
481
|
-
'lng',
|
|
482
|
-
'lngs',
|
|
483
|
-
'missingKeyNoValueFallbackToKey',
|
|
484
|
-
'ns',
|
|
485
|
-
'nsSeparator',
|
|
486
|
-
'nest',
|
|
487
|
-
'ordinal',
|
|
488
|
-
'postProcess',
|
|
489
|
-
'replace',
|
|
490
|
-
'returnDetails',
|
|
491
|
-
'returnObjects',
|
|
492
|
-
'scopeNs',
|
|
493
|
-
'skipInterpolation'
|
|
494
|
-
]);
|
|
495
|
-
function getReplacements(options) {
|
|
496
|
-
const fromReplace = options.replace !== null && typeof options.replace === 'object';
|
|
497
|
-
const source = fromReplace ? options.replace : options;
|
|
498
|
-
const replacements = {};
|
|
499
|
-
Object.entries(source).forEach(([key, value])=>{
|
|
500
|
-
if (typeof value !== 'string' && typeof value !== 'number') return;
|
|
501
|
-
// A numeric count selects the plural form, it is replaced after pluralization.
|
|
502
|
-
if (key === 'count' && typeof value === 'number') return;
|
|
503
|
-
if (!fromReplace && (I18NEXT_OPTIONS.has(key) || key.startsWith('defaultValue'))) return;
|
|
504
|
-
replacements[key] = value;
|
|
294
|
+
* Register the `uppercase`, `lowercase` and `capitalize` interpolation formats.
|
|
295
|
+
* The Vite plugin writes Laravel's `:NAME` as `{{name, uppercase}}` and `:Name`
|
|
296
|
+
* as `{{name, capitalize}}`; call this once the instance is initialized.
|
|
297
|
+
*/ function registerCaseFormats(instance) {
|
|
298
|
+
const formatter = instance.services.formatter;
|
|
299
|
+
formatter === null || formatter === void 0 ? void 0 : formatter.add('uppercase', (value)=>String(value).toUpperCase());
|
|
300
|
+
formatter === null || formatter === void 0 ? void 0 : formatter.add('lowercase', (value)=>String(value).toLowerCase());
|
|
301
|
+
formatter === null || formatter === void 0 ? void 0 : formatter.add('capitalize', (value)=>{
|
|
302
|
+
const text = String(value);
|
|
303
|
+
return text ? text[0].toUpperCase() + text.slice(1) : text;
|
|
505
304
|
});
|
|
506
|
-
return replacements;
|
|
507
305
|
}
|
|
508
|
-
/**
|
|
509
|
-
* i18next format plugin translating the way Laravel does:
|
|
510
|
-
*
|
|
511
|
-
* - flat keys (`auth.failed`, `Welcome, :name!`), no key or namespace separators;
|
|
512
|
-
* - `:name`, `:NAME` and `:Name` replacements instead of `{{name}}` interpolation and `$t()` nesting;
|
|
513
|
-
* - a numeric `count` selects the message with Laravel's `trans_choice()` rules
|
|
514
|
-
* (`one|many`, `{0} none|[1,19] some|[20,*] many`) instead of `_one`/`_other` suffixed keys;
|
|
515
|
-
* - empty messages fall back to the next language.
|
|
516
|
-
*/ class LaravelFormat {
|
|
517
|
-
init(i18next) {
|
|
518
|
-
this.i18next = i18next;
|
|
519
|
-
// Laravel keys contain dots and colons: disable the separators, unless given to `init()`.
|
|
520
|
-
const options = i18next.options;
|
|
521
|
-
if (options.userDefinedKeySeparator === undefined) options.keySeparator = false;
|
|
522
|
-
if (options.userDefinedNsSeparator === undefined) options.nsSeparator = false;
|
|
523
|
-
}
|
|
524
|
-
getResource(language, namespace, key) {
|
|
525
|
-
var _a;
|
|
526
|
-
const value = (_a = this.i18next) === null || _a === void 0 ? void 0 : _a.getResource(language, namespace, key, {
|
|
527
|
-
keySeparator: false,
|
|
528
|
-
ignoreJSONStructure: false
|
|
529
|
-
});
|
|
530
|
-
return value || undefined;
|
|
531
|
-
}
|
|
532
|
-
addLookupKeys(finalKeys) {
|
|
533
|
-
return finalKeys;
|
|
534
|
-
}
|
|
535
|
-
parse(message, options, language, namespace, _key, info) {
|
|
536
|
-
if (typeof message !== 'string') return message;
|
|
537
|
-
const replacements = getReplacements(options);
|
|
538
|
-
const translated = replacer(message, replacements);
|
|
539
|
-
const count = options.count;
|
|
540
|
-
if (typeof count !== 'number') return translated;
|
|
541
|
-
return replacer(pluralization(translated, count, this.getPluralLocale(language, namespace, info)), {
|
|
542
|
-
...replacements,
|
|
543
|
-
count: count.toString()
|
|
544
|
-
});
|
|
545
|
-
}
|
|
546
|
-
/**
|
|
547
|
-
* The language the message actually resolved in, so pluralization always
|
|
548
|
-
* matches the text being pluralized -- never merely a language that has
|
|
549
|
-
* translations for the namespace, which is not the same thing once several
|
|
550
|
-
* sources can contribute to one namespace (see LaravelBackend): a single
|
|
551
|
-
* unrelated key from a higher-priority source is enough to make
|
|
552
|
-
* `hasResourceBundle(language, namespace)` true for a namespace whose
|
|
553
|
-
* actual message still came from the fallback language.
|
|
554
|
-
*
|
|
555
|
-
* i18next passes the language the lookup succeeded at as `resolved.usedLng`
|
|
556
|
-
* in `parse()`'s 6th argument (`extendTranslation()` in i18next's own
|
|
557
|
-
* `translator.js`); prefer it. Older i18next in the `>=24` peer range that
|
|
558
|
-
* does not pass it falls back to a heuristic: the current language when it
|
|
559
|
-
* has translations for the namespace, else the fallback language.
|
|
560
|
-
*/ getPluralLocale(language, namespace, info) {
|
|
561
|
-
var _a;
|
|
562
|
-
const usedLng = (_a = info === null || info === void 0 ? void 0 : info.resolved) === null || _a === void 0 ? void 0 : _a.usedLng;
|
|
563
|
-
if (usedLng) return usedLng;
|
|
564
|
-
if (!this.i18next || !language || this.i18next.hasResourceBundle(language, namespace)) return language;
|
|
565
|
-
const [fallbackLanguage] = this.i18next.services.languageUtils.getFallbackCodes(this.i18next.options.fallbackLng, language);
|
|
566
|
-
return fallbackLanguage !== null && fallbackLanguage !== void 0 ? fallbackLanguage : language;
|
|
567
|
-
}
|
|
568
|
-
constructor(){
|
|
569
|
-
this.type = 'i18nFormat';
|
|
570
|
-
/**
|
|
571
|
-
* Non-string translations (e.g. an empty PHP array) are returned as is.
|
|
572
|
-
*/ this.handleAsObject = false;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
LaravelFormat.type = 'i18nFormat';
|
|
576
306
|
|
|
577
307
|
/**
|
|
578
308
|
* Locale of the `<html lang="">` attribute (set by Laravel's `app.blade.php`), or `en`.
|
|
@@ -610,26 +340,39 @@ LaravelFormat.type = 'i18nFormat';
|
|
|
610
340
|
return ()=>instance.off('languageChanged', setDocumentLang);
|
|
611
341
|
}
|
|
612
342
|
/**
|
|
613
|
-
* Create an i18next instance
|
|
343
|
+
* Create an i18next instance reading Laravel language files as i18next JSON: the default
|
|
614
344
|
* namespace from `lang/{locale}.json`, and one namespace per `lang/{locale}/{namespace}.json`
|
|
615
|
-
* file (
|
|
345
|
+
* file (converted from PHP by the Vite plugin, or hand-written the i18next way).
|
|
616
346
|
*
|
|
617
347
|
* With eager files, every known namespace of the locale and fallback locale is
|
|
618
348
|
* preloaded synchronously, so a first render never has to wait for translations.
|
|
619
|
-
*
|
|
349
|
+
*
|
|
350
|
+
* With lazy files, only the namespaces the evaluated modules declared are loaded
|
|
351
|
+
* up front (see `declareNamespaces()`), plus the default one; any other is loaded
|
|
352
|
+
* when a component first asks for it, which suspends until it arrives. Loaded
|
|
353
|
+
* beforehand with `preloadI18n()` -- or `withI18nPreload()` around the page
|
|
354
|
+
* resolver -- the up front ones are already in memory, so the instance is ready
|
|
355
|
+
* synchronously and neither the first render nor a later page ever waits.
|
|
620
356
|
*/ function createI18n({ files, locale, fallbackLocale }) {
|
|
621
357
|
const instance = i18next.createInstance();
|
|
622
358
|
const sources = toSources(files);
|
|
623
|
-
const
|
|
359
|
+
const known = recognizer(sources).getAllNamespaces();
|
|
624
360
|
const resolvedLocale = locale || documentLocale();
|
|
625
361
|
const resolvedFallbackLocale = fallbackLocale || documentLocale();
|
|
626
362
|
const eager = isEagerSources(sources);
|
|
627
|
-
|
|
363
|
+
const namespaces = eager ? known : Array.from(new Set([
|
|
364
|
+
DEFAULT_NAMESPACE,
|
|
365
|
+
...demand.getDeclaredNamespaces()
|
|
366
|
+
])).filter((namespace)=>known.includes(namespace));
|
|
367
|
+
instance.use(LaravelBackend).init({
|
|
368
|
+
...laravelOptions,
|
|
628
369
|
lng: resolvedLocale,
|
|
629
370
|
fallbackLng: resolvedFallbackLocale,
|
|
630
371
|
initAsync: false,
|
|
631
|
-
|
|
632
|
-
|
|
372
|
+
...namespaces.length > 0 ? {
|
|
373
|
+
ns: namespaces
|
|
374
|
+
} : {},
|
|
375
|
+
preload: namespaces.length > 0 ? Array.from(new Set([
|
|
633
376
|
resolvedLocale,
|
|
634
377
|
resolvedFallbackLocale
|
|
635
378
|
])) : undefined,
|
|
@@ -637,11 +380,18 @@ LaravelFormat.type = 'i18nFormat';
|
|
|
637
380
|
files: sources
|
|
638
381
|
}
|
|
639
382
|
});
|
|
383
|
+
registerCaseFormats(instance);
|
|
384
|
+
demand.trackInstance(instance);
|
|
640
385
|
return instance;
|
|
641
386
|
}
|
|
642
387
|
|
|
388
|
+
exports.DEFAULT_NAMESPACE = DEFAULT_NAMESPACE;
|
|
643
389
|
exports.LaravelBackend = LaravelBackend;
|
|
644
|
-
exports.LaravelFormat = LaravelFormat;
|
|
645
390
|
exports.createI18n = createI18n;
|
|
646
391
|
exports.documentLocale = documentLocale;
|
|
392
|
+
exports.laravelOptions = laravelOptions;
|
|
393
|
+
exports.recognizer = recognizer;
|
|
394
|
+
exports.registerCaseFormats = registerCaseFormats;
|
|
395
|
+
exports.resolver = resolver;
|
|
647
396
|
exports.syncDocumentLang = syncDocumentLang;
|
|
397
|
+
exports.toSources = toSources;
|