@wordpress/i18n 5.26.0 → 6.0.1-next.46f643fa0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +28 -27
  3. package/build/create-i18n.js +56 -201
  4. package/build/create-i18n.js.map +1 -1
  5. package/build/default-i18n.js +41 -34
  6. package/build/default-i18n.js.map +1 -1
  7. package/build/index.js.map +1 -1
  8. package/build/sprintf.js +10 -22
  9. package/build/sprintf.js.map +1 -1
  10. package/build/types.js +6 -0
  11. package/build/types.js.map +1 -0
  12. package/build-module/create-i18n.js +56 -201
  13. package/build-module/create-i18n.js.map +1 -1
  14. package/build-module/default-i18n.js +41 -35
  15. package/build-module/default-i18n.js.map +1 -1
  16. package/build-module/index.js.map +1 -1
  17. package/build-module/sprintf.js +10 -22
  18. package/build-module/sprintf.js.map +1 -1
  19. package/build-module/types.js +2 -0
  20. package/build-module/types.js.map +1 -0
  21. package/build-types/create-i18n.d.ts +11 -115
  22. package/build-types/create-i18n.d.ts.map +1 -1
  23. package/build-types/default-i18n.d.ts +55 -47
  24. package/build-types/default-i18n.d.ts.map +1 -1
  25. package/build-types/index.d.ts +4 -3
  26. package/build-types/index.d.ts.map +1 -1
  27. package/build-types/sprintf.d.ts +4 -10
  28. package/build-types/sprintf.d.ts.map +1 -1
  29. package/build-types/types.d.ts +114 -0
  30. package/build-types/types.d.ts.map +1 -0
  31. package/package.json +4 -4
  32. package/src/create-i18n.ts +405 -0
  33. package/src/{default-i18n.js → default-i18n.ts} +47 -35
  34. package/src/index.ts +16 -0
  35. package/src/sprintf.ts +37 -0
  36. package/src/test/{create-i18n.js → create-i18n.ts} +63 -30
  37. package/src/test/{sprintf.js → sprintf.ts} +5 -10
  38. package/src/test/{subscribe-i18n.js → subscribe-i18n.ts} +3 -3
  39. package/src/types.ts +167 -0
  40. package/tsconfig.tsbuildinfo +1 -1
  41. package/src/create-i18n.js +0 -506
  42. package/src/sprintf.js +0 -36
  43. /package/src/test/{default-i18n.js → default-i18n.ts} +0 -0
@@ -1,506 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import Tannin from 'tannin';
5
-
6
- /**
7
- * @typedef {Record<string,any>} LocaleData
8
- */
9
-
10
- /**
11
- * Default locale data to use for Tannin domain when not otherwise provided.
12
- * Assumes an English plural forms expression.
13
- *
14
- * @type {LocaleData}
15
- */
16
- const DEFAULT_LOCALE_DATA = {
17
- '': {
18
- /** @param {number} n */
19
- plural_forms( n ) {
20
- return n === 1 ? 0 : 1;
21
- },
22
- },
23
- };
24
-
25
- /*
26
- * Regular expression that matches i18n hooks like `i18n.gettext`, `i18n.ngettext`,
27
- * `i18n.gettext_domain` or `i18n.ngettext_with_context` or `i18n.has_translation`.
28
- */
29
- const I18N_HOOK_REGEXP = /^i18n\.(n?gettext|has_translation)(_|$)/;
30
-
31
- /**
32
- * @typedef {(domain?: string) => LocaleData} GetLocaleData
33
- *
34
- * Returns locale data by domain in a
35
- * Jed-formatted JSON object shape.
36
- *
37
- * @see http://messageformat.github.io/Jed/
38
- */
39
- /**
40
- * @typedef {(data?: LocaleData, domain?: string) => void} SetLocaleData
41
- *
42
- * Merges locale data into the Tannin instance by domain. Note that this
43
- * function will overwrite the domain configuration. Accepts data in a
44
- * Jed-formatted JSON object shape.
45
- *
46
- * @see http://messageformat.github.io/Jed/
47
- */
48
- /**
49
- * @typedef {(data?: LocaleData, domain?: string) => void} AddLocaleData
50
- *
51
- * Merges locale data into the Tannin instance by domain. Note that this
52
- * function will also merge the domain configuration. Accepts data in a
53
- * Jed-formatted JSON object shape.
54
- *
55
- * @see http://messageformat.github.io/Jed/
56
- */
57
- /**
58
- * @typedef {(data?: LocaleData, domain?: string) => void} ResetLocaleData
59
- *
60
- * Resets all current Tannin instance locale data and sets the specified
61
- * locale data for the domain. Accepts data in a Jed-formatted JSON object shape.
62
- *
63
- * @see http://messageformat.github.io/Jed/
64
- */
65
- /** @typedef {() => void} SubscribeCallback */
66
- /** @typedef {() => void} UnsubscribeCallback */
67
- /**
68
- * @typedef {(callback: SubscribeCallback) => UnsubscribeCallback} Subscribe
69
- *
70
- * Subscribes to changes of locale data
71
- */
72
- /**
73
- * @typedef {(domain?: string) => string} GetFilterDomain
74
- * Retrieve the domain to use when calling domain-specific filters.
75
- */
76
- /**
77
- * @typedef {(text: string, domain?: string) => string} __
78
- *
79
- * Retrieve the translation of text.
80
- *
81
- * @see https://developer.wordpress.org/reference/functions/__/
82
- */
83
- /**
84
- * @typedef {(text: string, context: string, domain?: string) => string} _x
85
- *
86
- * Retrieve translated string with gettext context.
87
- *
88
- * @see https://developer.wordpress.org/reference/functions/_x/
89
- */
90
- /**
91
- * @typedef {(single: string, plural: string, number: number, domain?: string) => string} _n
92
- *
93
- * Translates and retrieves the singular or plural form based on the supplied
94
- * number.
95
- *
96
- * @see https://developer.wordpress.org/reference/functions/_n/
97
- */
98
- /**
99
- * @typedef {(single: string, plural: string, number: number, context: string, domain?: string) => string} _nx
100
- *
101
- * Translates and retrieves the singular or plural form based on the supplied
102
- * number, with gettext context.
103
- *
104
- * @see https://developer.wordpress.org/reference/functions/_nx/
105
- */
106
- /**
107
- * @typedef {() => boolean} IsRtl
108
- *
109
- * Check if current locale is RTL.
110
- *
111
- * **RTL (Right To Left)** is a locale property indicating that text is written from right to left.
112
- * For example, the `he` locale (for Hebrew) specifies right-to-left. Arabic (ar) is another common
113
- * language written RTL. The opposite of RTL, LTR (Left To Right) is used in other languages,
114
- * including English (`en`, `en-US`, `en-GB`, etc.), Spanish (`es`), and French (`fr`).
115
- */
116
- /**
117
- * @typedef {(single: string, context?: string, domain?: string) => boolean} HasTranslation
118
- *
119
- * Check if there is a translation for a given string in singular form.
120
- */
121
- /** @typedef {import('@wordpress/hooks').Hooks} Hooks */
122
-
123
- /**
124
- * An i18n instance
125
- *
126
- * @typedef I18n
127
- * @property {GetLocaleData} getLocaleData Returns locale data by domain in a Jed-formatted JSON object shape.
128
- * @property {SetLocaleData} setLocaleData Merges locale data into the Tannin instance by domain. Note that this
129
- * function will overwrite the domain configuration. Accepts data in a
130
- * Jed-formatted JSON object shape.
131
- * @property {AddLocaleData} addLocaleData Merges locale data into the Tannin instance by domain. Note that this
132
- * function will also merge the domain configuration. Accepts data in a
133
- * Jed-formatted JSON object shape.
134
- * @property {ResetLocaleData} resetLocaleData Resets all current Tannin instance locale data and sets the specified
135
- * locale data for the domain. Accepts data in a Jed-formatted JSON object shape.
136
- * @property {Subscribe} subscribe Subscribes to changes of Tannin locale data.
137
- * @property {__} __ Retrieve the translation of text.
138
- * @property {_x} _x Retrieve translated string with gettext context.
139
- * @property {_n} _n Translates and retrieves the singular or plural form based on the supplied
140
- * number.
141
- * @property {_nx} _nx Translates and retrieves the singular or plural form based on the supplied
142
- * number, with gettext context.
143
- * @property {IsRtl} isRTL Check if current locale is RTL.
144
- * @property {HasTranslation} hasTranslation Check if there is a translation for a given string.
145
- */
146
-
147
- /**
148
- * Create an i18n instance
149
- *
150
- * @param {LocaleData} [initialData] Locale data configuration.
151
- * @param {string} [initialDomain] Domain for which configuration applies.
152
- * @param {Hooks} [hooks] Hooks implementation.
153
- *
154
- * @return {I18n} I18n instance.
155
- */
156
- export const createI18n = ( initialData, initialDomain, hooks ) => {
157
- /**
158
- * The underlying instance of Tannin to which exported functions interface.
159
- *
160
- * @type {Tannin}
161
- */
162
- const tannin = new Tannin( {} );
163
-
164
- const listeners = new Set();
165
-
166
- const notifyListeners = () => {
167
- listeners.forEach( ( listener ) => listener() );
168
- };
169
-
170
- /**
171
- * Subscribe to changes of locale data.
172
- *
173
- * @param {SubscribeCallback} callback Subscription callback.
174
- * @return {UnsubscribeCallback} Unsubscribe callback.
175
- */
176
- const subscribe = ( callback ) => {
177
- listeners.add( callback );
178
- return () => listeners.delete( callback );
179
- };
180
-
181
- /** @type {GetLocaleData} */
182
- const getLocaleData = ( domain = 'default' ) => tannin.data[ domain ];
183
-
184
- /**
185
- * @param {LocaleData} [data]
186
- * @param {string} [domain]
187
- */
188
- const doSetLocaleData = ( data, domain = 'default' ) => {
189
- tannin.data[ domain ] = {
190
- ...tannin.data[ domain ],
191
- ...data,
192
- };
193
-
194
- // Populate default domain configuration (supported locale date which omits
195
- // a plural forms expression).
196
- tannin.data[ domain ][ '' ] = {
197
- ...DEFAULT_LOCALE_DATA[ '' ],
198
- ...tannin.data[ domain ]?.[ '' ],
199
- };
200
-
201
- // Clean up cached plural forms functions cache as it might be updated.
202
- delete tannin.pluralForms[ domain ];
203
- };
204
-
205
- /** @type {SetLocaleData} */
206
- const setLocaleData = ( data, domain ) => {
207
- doSetLocaleData( data, domain );
208
- notifyListeners();
209
- };
210
-
211
- /** @type {AddLocaleData} */
212
- const addLocaleData = ( data, domain = 'default' ) => {
213
- tannin.data[ domain ] = {
214
- ...tannin.data[ domain ],
215
- ...data,
216
- // Populate default domain configuration (supported locale date which omits
217
- // a plural forms expression).
218
- '': {
219
- ...DEFAULT_LOCALE_DATA[ '' ],
220
- ...tannin.data[ domain ]?.[ '' ],
221
- ...data?.[ '' ],
222
- },
223
- };
224
-
225
- // Clean up cached plural forms functions cache as it might be updated.
226
- delete tannin.pluralForms[ domain ];
227
-
228
- notifyListeners();
229
- };
230
-
231
- /** @type {ResetLocaleData} */
232
- const resetLocaleData = ( data, domain ) => {
233
- // Reset all current Tannin locale data.
234
- tannin.data = {};
235
-
236
- // Reset cached plural forms functions cache.
237
- tannin.pluralForms = {};
238
-
239
- setLocaleData( data, domain );
240
- };
241
-
242
- /**
243
- * Wrapper for Tannin's `dcnpgettext`. Populates default locale data if not
244
- * otherwise previously assigned.
245
- *
246
- * @param {string|undefined} domain Domain to retrieve the translated text.
247
- * @param {string|undefined} context Context information for the translators.
248
- * @param {string} single Text to translate if non-plural. Used as
249
- * fallback return value on a caught error.
250
- * @param {string} [plural] The text to be used if the number is
251
- * plural.
252
- * @param {number} [number] The number to compare against to use
253
- * either the singular or plural form.
254
- *
255
- * @return {string} The translated string.
256
- */
257
- const dcnpgettext = (
258
- domain = 'default',
259
- context,
260
- single,
261
- plural,
262
- number
263
- ) => {
264
- if ( ! tannin.data[ domain ] ) {
265
- // Use `doSetLocaleData` to set silently, without notifying listeners.
266
- doSetLocaleData( undefined, domain );
267
- }
268
-
269
- return tannin.dcnpgettext( domain, context, single, plural, number );
270
- };
271
-
272
- /** @type {GetFilterDomain} */
273
- const getFilterDomain = ( domain = 'default' ) => domain;
274
-
275
- /** @type {__} */
276
- const __ = ( text, domain ) => {
277
- let translation = dcnpgettext( domain, undefined, text );
278
- if ( ! hooks ) {
279
- return translation;
280
- }
281
-
282
- /**
283
- * Filters text with its translation.
284
- *
285
- * @param {string} translation Translated text.
286
- * @param {string} text Text to translate.
287
- * @param {string} domain Text domain. Unique identifier for retrieving translated strings.
288
- */
289
- translation = /** @type {string} */ (
290
- /** @type {*} */ hooks.applyFilters(
291
- 'i18n.gettext',
292
- translation,
293
- text,
294
- domain
295
- )
296
- );
297
- return /** @type {string} */ (
298
- /** @type {*} */ hooks.applyFilters(
299
- 'i18n.gettext_' + getFilterDomain( domain ),
300
- translation,
301
- text,
302
- domain
303
- )
304
- );
305
- };
306
-
307
- /** @type {_x} */
308
- const _x = ( text, context, domain ) => {
309
- let translation = dcnpgettext( domain, context, text );
310
- if ( ! hooks ) {
311
- return translation;
312
- }
313
-
314
- /**
315
- * Filters text with its translation based on context information.
316
- *
317
- * @param {string} translation Translated text.
318
- * @param {string} text Text to translate.
319
- * @param {string} context Context information for the translators.
320
- * @param {string} domain Text domain. Unique identifier for retrieving translated strings.
321
- */
322
- translation = /** @type {string} */ (
323
- /** @type {*} */ hooks.applyFilters(
324
- 'i18n.gettext_with_context',
325
- translation,
326
- text,
327
- context,
328
- domain
329
- )
330
- );
331
- return /** @type {string} */ (
332
- /** @type {*} */ hooks.applyFilters(
333
- 'i18n.gettext_with_context_' + getFilterDomain( domain ),
334
- translation,
335
- text,
336
- context,
337
- domain
338
- )
339
- );
340
- };
341
-
342
- /** @type {_n} */
343
- const _n = ( single, plural, number, domain ) => {
344
- let translation = dcnpgettext(
345
- domain,
346
- undefined,
347
- single,
348
- plural,
349
- number
350
- );
351
- if ( ! hooks ) {
352
- return translation;
353
- }
354
-
355
- /**
356
- * Filters the singular or plural form of a string.
357
- *
358
- * @param {string} translation Translated text.
359
- * @param {string} single The text to be used if the number is singular.
360
- * @param {string} plural The text to be used if the number is plural.
361
- * @param {string} number The number to compare against to use either the singular or plural form.
362
- * @param {string} domain Text domain. Unique identifier for retrieving translated strings.
363
- */
364
- translation = /** @type {string} */ (
365
- /** @type {*} */ hooks.applyFilters(
366
- 'i18n.ngettext',
367
- translation,
368
- single,
369
- plural,
370
- number,
371
- domain
372
- )
373
- );
374
- return /** @type {string} */ (
375
- /** @type {*} */ hooks.applyFilters(
376
- 'i18n.ngettext_' + getFilterDomain( domain ),
377
- translation,
378
- single,
379
- plural,
380
- number,
381
- domain
382
- )
383
- );
384
- };
385
-
386
- /** @type {_nx} */
387
- const _nx = ( single, plural, number, context, domain ) => {
388
- let translation = dcnpgettext(
389
- domain,
390
- context,
391
- single,
392
- plural,
393
- number
394
- );
395
- if ( ! hooks ) {
396
- return translation;
397
- }
398
-
399
- /**
400
- * Filters the singular or plural form of a string with gettext context.
401
- *
402
- * @param {string} translation Translated text.
403
- * @param {string} single The text to be used if the number is singular.
404
- * @param {string} plural The text to be used if the number is plural.
405
- * @param {string} number The number to compare against to use either the singular or plural form.
406
- * @param {string} context Context information for the translators.
407
- * @param {string} domain Text domain. Unique identifier for retrieving translated strings.
408
- */
409
- translation = /** @type {string} */ (
410
- /** @type {*} */ hooks.applyFilters(
411
- 'i18n.ngettext_with_context',
412
- translation,
413
- single,
414
- plural,
415
- number,
416
- context,
417
- domain
418
- )
419
- );
420
-
421
- return /** @type {string} */ (
422
- /** @type {*} */ hooks.applyFilters(
423
- 'i18n.ngettext_with_context_' + getFilterDomain( domain ),
424
- translation,
425
- single,
426
- plural,
427
- number,
428
- context,
429
- domain
430
- )
431
- );
432
- };
433
-
434
- /** @type {IsRtl} */
435
- const isRTL = () => {
436
- return 'rtl' === _x( 'ltr', 'text direction' );
437
- };
438
-
439
- /** @type {HasTranslation} */
440
- const hasTranslation = ( single, context, domain ) => {
441
- const key = context ? context + '\u0004' + single : single;
442
- let result = !! tannin.data?.[ domain ?? 'default' ]?.[ key ];
443
- if ( hooks ) {
444
- /**
445
- * Filters the presence of a translation in the locale data.
446
- *
447
- * @param {boolean} hasTranslation Whether the translation is present or not..
448
- * @param {string} single The singular form of the translated text (used as key in locale data)
449
- * @param {string} context Context information for the translators.
450
- * @param {string} domain Text domain. Unique identifier for retrieving translated strings.
451
- */
452
- result = /** @type { boolean } */ (
453
- /** @type {*} */ hooks.applyFilters(
454
- 'i18n.has_translation',
455
- result,
456
- single,
457
- context,
458
- domain
459
- )
460
- );
461
-
462
- result = /** @type { boolean } */ (
463
- /** @type {*} */ hooks.applyFilters(
464
- 'i18n.has_translation_' + getFilterDomain( domain ),
465
- result,
466
- single,
467
- context,
468
- domain
469
- )
470
- );
471
- }
472
- return result;
473
- };
474
-
475
- if ( initialData ) {
476
- setLocaleData( initialData, initialDomain );
477
- }
478
-
479
- if ( hooks ) {
480
- /**
481
- * @param {string} hookName
482
- */
483
- const onHookAddedOrRemoved = ( hookName ) => {
484
- if ( I18N_HOOK_REGEXP.test( hookName ) ) {
485
- notifyListeners();
486
- }
487
- };
488
-
489
- hooks.addAction( 'hookAdded', 'core/i18n', onHookAddedOrRemoved );
490
- hooks.addAction( 'hookRemoved', 'core/i18n', onHookAddedOrRemoved );
491
- }
492
-
493
- return {
494
- getLocaleData,
495
- setLocaleData,
496
- addLocaleData,
497
- resetLocaleData,
498
- subscribe,
499
- __,
500
- _x,
501
- _n,
502
- _nx,
503
- isRTL,
504
- hasTranslation,
505
- };
506
- };
package/src/sprintf.js DELETED
@@ -1,36 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import memoize from 'memize';
5
- import sprintfjs from 'sprintf-js';
6
-
7
- /**
8
- * Log to console, once per message; or more precisely, per referentially equal
9
- * argument set. Because Jed throws errors, we log these to the console instead
10
- * to avoid crashing the application.
11
- *
12
- * @param {...*} args Arguments to pass to `console.error`
13
- */
14
- const logErrorOnce = memoize( console.error ); // eslint-disable-line no-console
15
-
16
- /**
17
- * Returns a formatted string. If an error occurs in applying the format, the
18
- * original format string is returned.
19
- *
20
- * @param {string} format The format of the string to generate.
21
- * @param {...*} args Arguments to apply to the format.
22
- *
23
- * @see https://www.npmjs.com/package/sprintf-js
24
- *
25
- * @return {string} The formatted string.
26
- */
27
- export function sprintf( format, ...args ) {
28
- try {
29
- return sprintfjs.sprintf( format, ...args );
30
- } catch ( error ) {
31
- if ( error instanceof Error ) {
32
- logErrorOnce( 'sprintf error: \n\n' + error.toString() );
33
- }
34
- return format;
35
- }
36
- }
File without changes