react-scoped-i18n 0.0.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.
Files changed (128) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -0
  3. package/dist/cjs/createI18nContext/api/createCommons.d.ts +6 -0
  4. package/dist/cjs/createI18nContext/api/createCommons.js +30 -0
  5. package/dist/cjs/createI18nContext/api/createCommons.test.d.ts +1 -0
  6. package/dist/cjs/createI18nContext/api/createCommons.test.js +26 -0
  7. package/dist/cjs/createI18nContext/api/createFormat.d.ts +9 -0
  8. package/dist/cjs/createI18nContext/api/createFormat.js +54 -0
  9. package/dist/cjs/createI18nContext/api/createFormat.test.d.ts +1 -0
  10. package/dist/cjs/createI18nContext/api/createFormat.test.js +71 -0
  11. package/dist/cjs/createI18nContext/api/createT.d.ts +7 -0
  12. package/dist/cjs/createI18nContext/api/createT.js +15 -0
  13. package/dist/cjs/createI18nContext/api/createT.test.d.ts +1 -0
  14. package/dist/cjs/createI18nContext/api/createT.test.js +23 -0
  15. package/dist/cjs/createI18nContext/api/createTGlobal.d.ts +8 -0
  16. package/dist/cjs/createI18nContext/api/createTGlobal.js +31 -0
  17. package/dist/cjs/createI18nContext/api/createTGlobal.test.d.ts +1 -0
  18. package/dist/cjs/createI18nContext/api/createTGlobal.test.js +20 -0
  19. package/dist/cjs/createI18nContext/api/createTPlural.d.ts +5 -0
  20. package/dist/cjs/createI18nContext/api/createTPlural.js +19 -0
  21. package/dist/cjs/createI18nContext/api/createTPlural.test.d.ts +1 -0
  22. package/dist/cjs/createI18nContext/api/createTPlural.test.js +31 -0
  23. package/dist/cjs/createI18nContext/api/createUseI18n.d.ts +21 -0
  24. package/dist/cjs/createI18nContext/api/createUseI18n.js +52 -0
  25. package/dist/cjs/createI18nContext/api/createUseI18n.test.d.ts +1 -0
  26. package/dist/cjs/createI18nContext/api/createUseI18n.test.js +46 -0
  27. package/dist/cjs/createI18nContext/const/index.d.ts +1 -0
  28. package/dist/cjs/createI18nContext/const/index.js +4 -0
  29. package/dist/cjs/createI18nContext/index.d.ts +29 -0
  30. package/dist/cjs/createI18nContext/index.integration.test.d.ts +1 -0
  31. package/dist/cjs/createI18nContext/index.integration.test.js +41 -0
  32. package/dist/cjs/createI18nContext/index.js +45 -0
  33. package/dist/cjs/createI18nContext/provider/createI18nProvider.d.ts +15 -0
  34. package/dist/cjs/createI18nContext/provider/createI18nProvider.js +23 -0
  35. package/dist/cjs/createI18nContext/type/index.d.ts +19 -0
  36. package/dist/cjs/createI18nContext/type/index.js +7 -0
  37. package/dist/cjs/createI18nContext/type/isLanguage.test.d.ts +1 -0
  38. package/dist/cjs/createI18nContext/type/isLanguage.test.js +16 -0
  39. package/dist/cjs/createI18nContext/util/getPluralTranslation.d.ts +7 -0
  40. package/dist/cjs/createI18nContext/util/getPluralTranslation.js +48 -0
  41. package/dist/cjs/createI18nContext/util/getPluralTranslation.test.d.ts +1 -0
  42. package/dist/cjs/createI18nContext/util/getPluralTranslation.test.js +126 -0
  43. package/dist/cjs/createI18nContext/util/getTranslation.d.ts +7 -0
  44. package/dist/cjs/createI18nContext/util/getTranslation.js +32 -0
  45. package/dist/cjs/createI18nContext/util/getTranslation.test.d.ts +1 -0
  46. package/dist/cjs/createI18nContext/util/getTranslation.test.js +96 -0
  47. package/dist/cjs/env.d.ts +1 -0
  48. package/dist/cjs/env.js +9 -0
  49. package/dist/cjs/index.d.ts +1 -0
  50. package/dist/cjs/index.js +5 -0
  51. package/dist/cjs/index.test.d.ts +0 -0
  52. package/dist/cjs/index.test.js +40 -0
  53. package/dist/esm/createI18nContext/api/createCommons.d.ts +7 -0
  54. package/dist/esm/createI18nContext/api/createCommons.d.ts.map +1 -0
  55. package/dist/esm/createI18nContext/api/createCommons.js +26 -0
  56. package/dist/esm/createI18nContext/api/createCommons.test.d.ts +2 -0
  57. package/dist/esm/createI18nContext/api/createCommons.test.d.ts.map +1 -0
  58. package/dist/esm/createI18nContext/api/createCommons.test.js +24 -0
  59. package/dist/esm/createI18nContext/api/createFormat.d.ts +10 -0
  60. package/dist/esm/createI18nContext/api/createFormat.d.ts.map +1 -0
  61. package/dist/esm/createI18nContext/api/createFormat.js +50 -0
  62. package/dist/esm/createI18nContext/api/createFormat.test.d.ts +2 -0
  63. package/dist/esm/createI18nContext/api/createFormat.test.d.ts.map +1 -0
  64. package/dist/esm/createI18nContext/api/createFormat.test.js +69 -0
  65. package/dist/esm/createI18nContext/api/createT.d.ts +8 -0
  66. package/dist/esm/createI18nContext/api/createT.d.ts.map +1 -0
  67. package/dist/esm/createI18nContext/api/createT.js +11 -0
  68. package/dist/esm/createI18nContext/api/createT.test.d.ts +2 -0
  69. package/dist/esm/createI18nContext/api/createT.test.d.ts.map +1 -0
  70. package/dist/esm/createI18nContext/api/createT.test.js +21 -0
  71. package/dist/esm/createI18nContext/api/createTGlobal.d.ts +9 -0
  72. package/dist/esm/createI18nContext/api/createTGlobal.d.ts.map +1 -0
  73. package/dist/esm/createI18nContext/api/createTGlobal.js +27 -0
  74. package/dist/esm/createI18nContext/api/createTGlobal.test.d.ts +2 -0
  75. package/dist/esm/createI18nContext/api/createTGlobal.test.d.ts.map +1 -0
  76. package/dist/esm/createI18nContext/api/createTGlobal.test.js +18 -0
  77. package/dist/esm/createI18nContext/api/createTPlural.d.ts +6 -0
  78. package/dist/esm/createI18nContext/api/createTPlural.d.ts.map +1 -0
  79. package/dist/esm/createI18nContext/api/createTPlural.js +15 -0
  80. package/dist/esm/createI18nContext/api/createTPlural.test.d.ts +2 -0
  81. package/dist/esm/createI18nContext/api/createTPlural.test.d.ts.map +1 -0
  82. package/dist/esm/createI18nContext/api/createTPlural.test.js +29 -0
  83. package/dist/esm/createI18nContext/api/createUseI18n.d.ts +22 -0
  84. package/dist/esm/createI18nContext/api/createUseI18n.d.ts.map +1 -0
  85. package/dist/esm/createI18nContext/api/createUseI18n.js +48 -0
  86. package/dist/esm/createI18nContext/api/createUseI18n.test.d.ts +2 -0
  87. package/dist/esm/createI18nContext/api/createUseI18n.test.d.ts.map +1 -0
  88. package/dist/esm/createI18nContext/api/createUseI18n.test.js +44 -0
  89. package/dist/esm/createI18nContext/const/index.d.ts +2 -0
  90. package/dist/esm/createI18nContext/const/index.d.ts.map +1 -0
  91. package/dist/esm/createI18nContext/const/index.js +1 -0
  92. package/dist/esm/createI18nContext/index.d.ts +30 -0
  93. package/dist/esm/createI18nContext/index.d.ts.map +1 -0
  94. package/dist/esm/createI18nContext/index.integration.test.d.ts +2 -0
  95. package/dist/esm/createI18nContext/index.integration.test.d.ts.map +1 -0
  96. package/dist/esm/createI18nContext/index.integration.test.js +39 -0
  97. package/dist/esm/createI18nContext/index.js +42 -0
  98. package/dist/esm/createI18nContext/provider/createI18nProvider.d.ts +16 -0
  99. package/dist/esm/createI18nContext/provider/createI18nProvider.d.ts.map +1 -0
  100. package/dist/esm/createI18nContext/provider/createI18nProvider.js +19 -0
  101. package/dist/esm/createI18nContext/type/index.d.ts +20 -0
  102. package/dist/esm/createI18nContext/type/index.d.ts.map +1 -0
  103. package/dist/esm/createI18nContext/type/index.js +3 -0
  104. package/dist/esm/createI18nContext/type/isLanguage.test.d.ts +2 -0
  105. package/dist/esm/createI18nContext/type/isLanguage.test.d.ts.map +1 -0
  106. package/dist/esm/createI18nContext/type/isLanguage.test.js +14 -0
  107. package/dist/esm/createI18nContext/util/getPluralTranslation.d.ts +8 -0
  108. package/dist/esm/createI18nContext/util/getPluralTranslation.d.ts.map +1 -0
  109. package/dist/esm/createI18nContext/util/getPluralTranslation.js +44 -0
  110. package/dist/esm/createI18nContext/util/getPluralTranslation.test.d.ts +2 -0
  111. package/dist/esm/createI18nContext/util/getPluralTranslation.test.d.ts.map +1 -0
  112. package/dist/esm/createI18nContext/util/getPluralTranslation.test.js +124 -0
  113. package/dist/esm/createI18nContext/util/getTranslation.d.ts +8 -0
  114. package/dist/esm/createI18nContext/util/getTranslation.d.ts.map +1 -0
  115. package/dist/esm/createI18nContext/util/getTranslation.js +28 -0
  116. package/dist/esm/createI18nContext/util/getTranslation.test.d.ts +2 -0
  117. package/dist/esm/createI18nContext/util/getTranslation.test.d.ts.map +1 -0
  118. package/dist/esm/createI18nContext/util/getTranslation.test.js +94 -0
  119. package/dist/esm/env.d.ts +2 -0
  120. package/dist/esm/env.d.ts.map +1 -0
  121. package/dist/esm/env.js +6 -0
  122. package/dist/esm/index.d.ts +2 -0
  123. package/dist/esm/index.d.ts.map +1 -0
  124. package/dist/esm/index.js +1 -0
  125. package/dist/esm/index.test.d.ts +1 -0
  126. package/dist/esm/index.test.d.ts.map +1 -0
  127. package/dist/esm/index.test.js +7 -0
  128. package/package.json +55 -0
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ describe(`sanity check: createI18nContext is exported`, () => {
36
+ test(`it should be defined`, async () => {
37
+ const { createI18nContext } = await Promise.resolve().then(() => __importStar(require(`./index`)));
38
+ expect(createI18nContext).toBeDefined();
39
+ });
40
+ });
@@ -0,0 +1,7 @@
1
+ import { TranslationMap } from "../type";
2
+ export declare const createCommons: <const Languages extends readonly string[], const Commons extends Record<string, TranslationMap<Languages[number], string>>>({ commons, currentLanguage, fallbackLanguage, }: {
3
+ commons: Commons;
4
+ currentLanguage: Languages[number];
5
+ fallbackLanguage: Languages[number];
6
+ }) => { [K in keyof Commons]?: string | undefined; };
7
+ //# sourceMappingURL=createCommons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createCommons.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/api/createCommons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAIzC,eAAO,MAAM,aAAa,GACxB,KAAK,CAAC,SAAS,SAAS,SAAS,MAAM,EAAE,EACzC,KAAK,CAAC,OAAO,SAAS,MAAM,CAC1B,MAAM,EACN,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAC1C,EACD,iDAIC;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACnC,gBAAgB,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;CACrC,QACkB,CAAC,0CAqCnB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { IS_DEV } from "../../env";
2
+ import { MISSING_TRANSLATION } from "../const";
3
+ export const createCommons = ({ commons, currentLanguage, fallbackLanguage, }) => {
4
+ const result = {};
5
+ for (const key in commons) {
6
+ const translationMap = commons[key];
7
+ const targetTranslation = translationMap[currentLanguage];
8
+ if (targetTranslation) {
9
+ result[key] = targetTranslation;
10
+ continue;
11
+ }
12
+ const fallbackTranslation = translationMap[fallbackLanguage];
13
+ if (fallbackTranslation) {
14
+ if (IS_DEV) {
15
+ console.warn(`[i18n] Missing translation for key "${key}" in current language "${currentLanguage}" in "commons". Defaulting to fallback language "${fallbackLanguage}".`);
16
+ }
17
+ result[key] = fallbackTranslation;
18
+ continue;
19
+ }
20
+ if (IS_DEV) {
21
+ console.warn(`[i18n] Missing translation for key "${key}" in both current language "${currentLanguage}" and fallback language "${fallbackLanguage}" in "commons".`);
22
+ }
23
+ result[key] = MISSING_TRANSLATION;
24
+ }
25
+ return result;
26
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=createCommons.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createCommons.test.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/api/createCommons.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import { createCommons } from "./createCommons";
2
+ describe(`createCommons`, () => {
3
+ it(`returns the correct common translations based on current language and fallback`, () => {
4
+ const result = createCommons({
5
+ commons: {
6
+ welcome: {
7
+ en: `Welcome`,
8
+ es: `Bienvenido`,
9
+ fr: `Bienvenue`,
10
+ },
11
+ goodbye: {
12
+ en: `Goodbye`,
13
+ es: `Adiós`,
14
+ },
15
+ },
16
+ currentLanguage: `fr`,
17
+ fallbackLanguage: `en`,
18
+ });
19
+ expect(result).toEqual({
20
+ welcome: `Bienvenue`,
21
+ goodbye: `Goodbye`,
22
+ });
23
+ });
24
+ });
@@ -0,0 +1,10 @@
1
+ export declare const createFormat: <const Languages extends readonly string[]>({ currentLanguage, }: {
2
+ currentLanguage: Languages[number];
3
+ }) => {
4
+ number: (value: number, options?: Intl.NumberFormatOptions) => string;
5
+ date: (value: Date | number, options?: Intl.DateTimeFormatOptions) => string;
6
+ time: (value: Date | number, options?: Intl.DateTimeFormatOptions) => string;
7
+ currency: (value: number, currency: string, options?: Omit<Intl.NumberFormatOptions, `style` | `currency`>) => string;
8
+ percentage: (value: number, options?: Omit<Intl.NumberFormatOptions, `style`>) => string;
9
+ };
10
+ //# sourceMappingURL=createFormat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createFormat.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/api/createFormat.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,GAAI,KAAK,CAAC,SAAS,SAAS,SAAS,MAAM,EAAE,EAAE,sBAErE;IACD,eAAe,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;CACpC;oBAgBmB,MAAM,YAAY,IAAI,CAAC,mBAAmB;kBAQ5C,IAAI,GAAG,MAAM,YAAY,IAAI,CAAC,qBAAqB;kBAQnD,IAAI,GAAG,MAAM,YAAY,IAAI,CAAC,qBAAqB;sBAWxD,MAAM,YACH,MAAM,YACN,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,UAAU,CAAC;wBAUvD,MAAM,YACH,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC;CAYtD,CAAC"}
@@ -0,0 +1,50 @@
1
+ export const createFormat = ({ currentLanguage, }) => {
2
+ const defaultNumberFormatter = new Intl.NumberFormat(currentLanguage);
3
+ const defaultDateFormatter = new Intl.DateTimeFormat(currentLanguage);
4
+ const defaultTimeFormatter = new Intl.DateTimeFormat(currentLanguage, {
5
+ hour: `numeric`,
6
+ minute: `numeric`,
7
+ second: `numeric`,
8
+ });
9
+ const defaultPercentageFormatter = new Intl.NumberFormat(currentLanguage, {
10
+ style: `percent`,
11
+ });
12
+ return {
13
+ number: (value, options) => {
14
+ if (options) {
15
+ return new Intl.NumberFormat(currentLanguage, options).format(value);
16
+ }
17
+ return defaultNumberFormatter.format(value);
18
+ },
19
+ date: (value, options) => {
20
+ if (options) {
21
+ return new Intl.DateTimeFormat(currentLanguage, options).format(value);
22
+ }
23
+ return defaultDateFormatter.format(value);
24
+ },
25
+ time: (value, options) => {
26
+ if (options) {
27
+ return new Intl.DateTimeFormat(currentLanguage, {
28
+ ...options,
29
+ }).format(value);
30
+ }
31
+ return defaultTimeFormatter.format(value);
32
+ },
33
+ currency: (value, currency, options) => {
34
+ return new Intl.NumberFormat(currentLanguage, {
35
+ style: `currency`,
36
+ currency,
37
+ ...options,
38
+ }).format(value);
39
+ },
40
+ percentage: (value, options) => {
41
+ if (options) {
42
+ return new Intl.NumberFormat(currentLanguage, {
43
+ style: `percent`,
44
+ ...options,
45
+ }).format(value);
46
+ }
47
+ return defaultPercentageFormatter.format(value);
48
+ },
49
+ };
50
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=createFormat.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createFormat.test.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/api/createFormat.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,69 @@
1
+ import { createFormat } from "./createFormat";
2
+ describe(`createFormat`, () => {
3
+ const format = createFormat({
4
+ currentLanguage: `en-US`,
5
+ });
6
+ it(`number formatter returns a formatted value`, () => {
7
+ const formattedNumber = format.number(1234567.89);
8
+ expect(formattedNumber).toBe(`1,234,567.89`);
9
+ });
10
+ it(`number formatter returns a formatted value with options`, () => {
11
+ const formattedNumber = format.number(0.1234, {
12
+ style: `percent`,
13
+ minimumFractionDigits: 2,
14
+ });
15
+ expect(formattedNumber).toBe(`12.34%`);
16
+ });
17
+ it(`date formatter returns a formatted value`, () => {
18
+ const date = new Date(`2024-01-01T12:00:00Z`);
19
+ const formattedDate = format.date(date);
20
+ expect(formattedDate).toBe(`1/1/2024`);
21
+ });
22
+ it(`date formatter returns a formatted value with options`, () => {
23
+ const date = new Date(`1999-01-01T12:00:00Z`);
24
+ const formattedDate = format.date(date, {
25
+ year: `numeric`,
26
+ month: `long`,
27
+ day: `numeric`,
28
+ });
29
+ expect(formattedDate).toBe(`January 1, 1999`);
30
+ });
31
+ it(`time formatter returns a formatted value`, () => {
32
+ const date = new Date(`1912-06-23T02:15:00`);
33
+ const formattedTime = format.time(date);
34
+ expect(formattedTime).toBe(`2:15:00 AM`);
35
+ });
36
+ it(`time formatter returns a formatted value with options`, () => {
37
+ const date = new Date(`2000-12-31T23:45:30`);
38
+ const formattedTime = format.time(date, {
39
+ hour12: false,
40
+ hour: `2-digit`,
41
+ minute: `2-digit`,
42
+ });
43
+ expect(formattedTime).toBe(`23:45`);
44
+ });
45
+ it(`currency formatter returns a formatted value`, () => {
46
+ const formattedCurrency = format.currency(1234.567, `USD`);
47
+ expect(formattedCurrency).toBe(`$1,234.57`);
48
+ });
49
+ it(`currency formatter returns a formatted value with options`, () => {
50
+ const formattedCurrency = format.currency(1234.567, `EUR`, {
51
+ maximumFractionDigits: 1,
52
+ });
53
+ expect(formattedCurrency).toBe(`€1,234.6`);
54
+ });
55
+ it(`percentage formatter returns a formatted value`, () => {
56
+ const formattedPercentage = format.percentage(0.1234);
57
+ expect(formattedPercentage).toBe(`12%`);
58
+ });
59
+ it(`percentage formatter returns a formatted value `, () => {
60
+ const formattedPercentage = format.percentage(0.1234);
61
+ expect(formattedPercentage).toBe(`12%`);
62
+ });
63
+ it(`percentage formatter returns a formatted value with options`, () => {
64
+ const formattedPercentage = format.percentage(0.1234, {
65
+ minimumFractionDigits: 2,
66
+ });
67
+ expect(formattedPercentage).toBe(`12.34%`);
68
+ });
69
+ });
@@ -0,0 +1,8 @@
1
+ import { TranslationMap, TranslationValue } from "../type";
2
+ import { ReactNode } from "react";
3
+ export declare const createT: <const Languages extends readonly string[]>({ currentLanguage, fallbackLanguage, languages, }: {
4
+ currentLanguage: Languages[number];
5
+ fallbackLanguage: Languages[number];
6
+ languages: Readonly<Languages>;
7
+ }) => <Value extends TranslationValue = ReactNode>(translation: TranslationMap<Languages[number], Value>) => Value;
8
+ //# sourceMappingURL=createT.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createT.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/api/createT.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,eAAO,MAAM,OAAO,GAAI,KAAK,CAAC,SAAS,SAAS,SAAS,MAAM,EAAE,EAAE,mDAIhE;IACD,eAAe,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACnC,gBAAgB,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACpC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;CAChC,MAGS,KAAK,SAAS,gBAAgB,GAAG,SAAS,EAChD,aAAa,cAAc,oBAAW,KAAK,CAAC,KAC3C,KAQJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { getTranslation } from "../util/getTranslation";
2
+ export const createT = ({ currentLanguage, fallbackLanguage, languages, }) => {
3
+ return (translation) => {
4
+ return getTranslation({
5
+ translation,
6
+ language: currentLanguage,
7
+ languages,
8
+ fallbackLanguage,
9
+ });
10
+ };
11
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=createT.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createT.test.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/api/createT.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { createT } from "./createT";
3
+ describe(`createT`, () => {
4
+ const t = createT({
5
+ currentLanguage: `fr`,
6
+ fallbackLanguage: `en`,
7
+ languages: [`en`, `es`, `fr`],
8
+ });
9
+ it(`t helper returns a translation`, () => {
10
+ expect(t({
11
+ en: `Hello`,
12
+ es: `Hola`,
13
+ fr: `Bonjour`,
14
+ })).toBe(`Bonjour`);
15
+ expect(t({
16
+ en: _jsx(_Fragment, {}),
17
+ es: `Hola`,
18
+ fr: `Bonjour`,
19
+ })).toBe(`Bonjour`);
20
+ });
21
+ });
@@ -0,0 +1,9 @@
1
+ import { TranslationMap } from "../type";
2
+ export declare const createTGlobal: <const Language extends string>({ currentLanguage, languages, fallbackLanguage, }: {
3
+ currentLanguage: {
4
+ current: Language;
5
+ };
6
+ languages: readonly Language[];
7
+ fallbackLanguage: Language;
8
+ }) => (translation: TranslationMap<Language>) => import("../type").TranslationValue;
9
+ //# sourceMappingURL=createTGlobal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createTGlobal.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/api/createTGlobal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,cAAc,EAAE,MAAM,SAAS,CAAC;AAIrD,eAAO,MAAM,aAAa,GAAI,KAAK,CAAC,QAAQ,SAAS,MAAM,EAAE,mDAI1D;IACD,eAAe,EAAE;QAAE,OAAO,EAAE,QAAQ,CAAA;KAAE,CAAC;IACvC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC/B,gBAAgB,EAAE,QAAQ,CAAC;CAC5B,MAKS,aAAa,cAAc,CAAC,QAAQ,CAAC,uCA0B9C,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { isLanguage } from "../type";
2
+ import { getTranslation } from "../util/getTranslation";
3
+ import { IS_DEV } from "../../env";
4
+ export const createTGlobal = ({ currentLanguage, languages, fallbackLanguage, }) => {
5
+ /**
6
+ * Module-scoped translation function, to be used outside React components.
7
+ * Do not use inside React components, use `useI18n` hook instead.
8
+ */
9
+ return (translation) => {
10
+ if (!isLanguage(currentLanguage.current, languages)) {
11
+ throw new Error(`tGlobal cannot be invoked before <I18nProvider> is mounted`);
12
+ }
13
+ const isValidLanguage = isLanguage(currentLanguage.current, languages);
14
+ if (!isValidLanguage) {
15
+ throw new Error(`Invalid current language "${currentLanguage}"`);
16
+ }
17
+ if (IS_DEV) {
18
+ console.info(`[i18n] Friendly reminder: Make sure you are not using "tGlobal" inside React components. Use "useI18n" hook instead. `);
19
+ }
20
+ return getTranslation({
21
+ translation: translation,
22
+ language: currentLanguage.current,
23
+ languages,
24
+ fallbackLanguage: fallbackLanguage,
25
+ });
26
+ };
27
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=createTGlobal.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createTGlobal.test.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/api/createTGlobal.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { createTGlobal } from "./createTGlobal";
2
+ describe(`createTGlobal`, () => {
3
+ const fakeCurrentLanguageRef = { current: `de` };
4
+ const tGlobal = createTGlobal({
5
+ currentLanguage: fakeCurrentLanguageRef,
6
+ fallbackLanguage: `en`,
7
+ languages: [`en`, `es`, `fr`, `de`],
8
+ });
9
+ it(`tGlobal helper returns a translation`, () => {
10
+ const translation = {
11
+ en: `Goodbye`,
12
+ es: `Adiós`,
13
+ fr: `Au revoir`,
14
+ de: `Auf Wiedersehen`,
15
+ };
16
+ expect(tGlobal(translation)).toBe(`Auf Wiedersehen`);
17
+ });
18
+ });
@@ -0,0 +1,6 @@
1
+ import { PluralTranslationMap } from "../type";
2
+ export declare const createTPlural: <const Languages extends readonly string[]>({ currentLanguage, fallbackLanguage, }: {
3
+ currentLanguage: Languages[number];
4
+ fallbackLanguage: Languages[number];
5
+ }) => (count: number, translations: PluralTranslationMap<Languages[number]>) => string | number | bigint | true | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined>;
6
+ //# sourceMappingURL=createTPlural.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createTPlural.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/api/createTPlural.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAG/C,eAAO,MAAM,aAAa,GAAI,KAAK,CAAC,SAAS,SAAS,SAAS,MAAM,EAAE,EAAE,wCAGtE;IACD,eAAe,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACnC,gBAAgB,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;CACrC,MAMG,OAAO,MAAM,EACb,cAAc,oBAAoB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,yYASxD,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { getPluralTranslation } from "../util/getPluralTranslation";
2
+ export const createTPlural = ({ currentLanguage, fallbackLanguage, }) => {
3
+ /**
4
+ * Pluralization helper function.
5
+ * Selects the appropriate translation based on the count provided.
6
+ */
7
+ return (count, translations) => {
8
+ return getPluralTranslation({
9
+ currentLanguage,
10
+ fallbackLanguage: fallbackLanguage,
11
+ count,
12
+ translations,
13
+ });
14
+ };
15
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=createTPlural.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createTPlural.test.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/api/createTPlural.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ import { createTPlural } from "./createTPlural";
2
+ describe(`createTPlural`, () => {
3
+ const tPlural = createTPlural({
4
+ currentLanguage: `en`,
5
+ fallbackLanguage: `en`,
6
+ });
7
+ it(`tPlural helper returns a translation for specific number`, () => {
8
+ const count = 2;
9
+ const translation = tPlural(count, {
10
+ en: {
11
+ 0: `You have no messages`,
12
+ one: `You have 1 message`,
13
+ many: `You have ${count} messages`,
14
+ },
15
+ sl: {
16
+ 0: `Nimate sporočil`,
17
+ one: `Imate 1 sporočilo`,
18
+ two: `Imate 2 sporočili`,
19
+ many: `Imate ${count} sporočil`,
20
+ },
21
+ pt: {
22
+ 0: `Você não tem mensagens`,
23
+ one: `Você tem 1 mensagem`,
24
+ many: `Você tem ${count} mensagens`,
25
+ },
26
+ });
27
+ expect(translation).toBe(`You have 2 messages`);
28
+ });
29
+ });
@@ -0,0 +1,22 @@
1
+ import { I18nContextType, TranslationMap } from "../type";
2
+ import { Context } from "react";
3
+ export declare const createUseI18n: <const Languages extends readonly string[], const Commons extends Record<string, TranslationMap<Languages[number], string>>>({ I18nContext, languages, fallbackLanguage, commons, }: {
4
+ I18nContext: Context<I18nContextType<Languages[number]> | null>;
5
+ languages: Readonly<Languages>;
6
+ fallbackLanguage: Languages[number];
7
+ commons?: Commons;
8
+ }) => () => {
9
+ t: <Value extends import("../type").TranslationValue = import("react").ReactNode>(translation: TranslationMap<Languages[number], Value>) => Value;
10
+ tPlural: (count: number, translations: import("../type").PluralTranslationMap<Languages[number]>) => string | number | bigint | true | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined>;
11
+ setCurrentLanguage: import("react").Dispatch<import("react").SetStateAction<Languages[number]>>;
12
+ currentLanguage: Languages[number];
13
+ format: {
14
+ number: (value: number, options?: Intl.NumberFormatOptions) => string;
15
+ date: (value: Date | number, options?: Intl.DateTimeFormatOptions) => string;
16
+ time: (value: Date | number, options?: Intl.DateTimeFormatOptions) => string;
17
+ currency: (value: number, currency: string, options?: Omit<Intl.NumberFormatOptions, `style` | `currency`>) => string;
18
+ percentage: (value: number, options?: Omit<Intl.NumberFormatOptions, `style`>) => string;
19
+ };
20
+ commons: { [K in keyof Commons]?: string | undefined; };
21
+ };
22
+ //# sourceMappingURL=createUseI18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createUseI18n.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/api/createUseI18n.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAuB,MAAM,OAAO,CAAC;AAMrD,eAAO,MAAM,aAAa,GACxB,KAAK,CAAC,SAAS,SAAS,SAAS,MAAM,EAAE,EACzC,KAAK,CAAC,OAAO,SAAS,MAAM,CAC1B,MAAM,EACN,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAC1C,EACD,wDAKC;IACD,WAAW,EAAE,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAChE,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC/B,gBAAgB,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;;;;;;;;;;;;;CAmDA,CAAC"}
@@ -0,0 +1,48 @@
1
+ import { useContext, useMemo } from "react";
2
+ import { createT } from "./createT";
3
+ import { createTPlural } from "./createTPlural";
4
+ import { createFormat } from "./createFormat";
5
+ import { createCommons } from "./createCommons";
6
+ export const createUseI18n = ({ I18nContext, languages, fallbackLanguage, commons, }) => {
7
+ /**
8
+ * Hook to access i18n functions and current language.
9
+ */
10
+ return () => {
11
+ const context = useContext(I18nContext);
12
+ if (!context) {
13
+ throw new Error(`useI18n must be used inside <Provider>`);
14
+ }
15
+ const { currentLanguage, setCurrentLanguage } = context;
16
+ const t = useMemo(() => {
17
+ return createT({
18
+ currentLanguage,
19
+ languages,
20
+ fallbackLanguage: fallbackLanguage,
21
+ });
22
+ }, [currentLanguage]);
23
+ const tPlural = useMemo(() => {
24
+ return createTPlural({
25
+ currentLanguage,
26
+ fallbackLanguage: fallbackLanguage,
27
+ });
28
+ }, [currentLanguage]);
29
+ const format = useMemo(() => {
30
+ return createFormat({ currentLanguage });
31
+ }, [currentLanguage]);
32
+ const _commons = useMemo(() => {
33
+ return createCommons({
34
+ commons: commons || {},
35
+ currentLanguage,
36
+ fallbackLanguage,
37
+ });
38
+ }, [currentLanguage]);
39
+ return {
40
+ t,
41
+ tPlural,
42
+ setCurrentLanguage,
43
+ currentLanguage,
44
+ format,
45
+ commons: _commons,
46
+ };
47
+ };
48
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=createUseI18n.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createUseI18n.test.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/api/createUseI18n.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,44 @@
1
+ import { createUseI18n } from "./createUseI18n";
2
+ describe(`createUseI18n`, () => {
3
+ const mockedI18nContext = {};
4
+ it(`prints console.error if used outside of a provider`, () => {
5
+ const useI18n = createUseI18n({
6
+ languages: [`en`, `es`],
7
+ fallbackLanguage: `en`,
8
+ commons: undefined,
9
+ I18nContext: mockedI18nContext,
10
+ });
11
+ // expect console.error to be called
12
+ const consoleErrorSpy = jest
13
+ .spyOn(console, `error`)
14
+ .mockImplementation(() => { });
15
+ try {
16
+ useI18n();
17
+ }
18
+ catch (e) {
19
+ expect(consoleErrorSpy).toHaveBeenCalled(); // eslint-disable-line unused-imports/no-unused-vars
20
+ }
21
+ consoleErrorSpy.mockRestore();
22
+ });
23
+ it(`can be initialised with only required parameters`, () => {
24
+ expect(() => createUseI18n({
25
+ languages: [`en`, `es`],
26
+ fallbackLanguage: `en`,
27
+ commons: undefined,
28
+ I18nContext: mockedI18nContext,
29
+ })).toBeDefined();
30
+ });
31
+ it(`should be initialised with all parameters`, () => {
32
+ expect(() => createUseI18n({
33
+ languages: [`en`, `es`],
34
+ fallbackLanguage: `es`,
35
+ commons: {
36
+ accept: {
37
+ en: `Accept`,
38
+ es: `Aceptar`,
39
+ },
40
+ },
41
+ I18nContext: mockedI18nContext,
42
+ })).toBeDefined();
43
+ });
44
+ });
@@ -0,0 +1,2 @@
1
+ export declare const MISSING_TRANSLATION = "[MISSING TRANSLATION]";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/createI18nContext/const/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,0BAA0B,CAAC"}
@@ -0,0 +1 @@
1
+ export const MISSING_TRANSLATION = `[MISSING TRANSLATION]`;
@@ -0,0 +1,30 @@
1
+ import { TranslationMap } from "./type";
2
+ export declare function createI18nContext<Languages extends readonly string[], Commons extends Record<string, TranslationMap<Languages[number], string>>>({ languages, fallbackLanguage, commons, }: {
3
+ languages: Readonly<Languages>;
4
+ fallbackLanguage: Languages[number];
5
+ commons?: Readonly<Commons>;
6
+ }): {
7
+ I18nProvider: {
8
+ ({ children, initialLanguage, }: {
9
+ children: import("react").ReactNode;
10
+ initialLanguage: Languages[number];
11
+ }): import("react/jsx-runtime").JSX.Element;
12
+ displayName: string;
13
+ };
14
+ useI18n: () => {
15
+ t: <Value extends import("./type").TranslationValue = import("react").ReactNode>(translation: TranslationMap<Languages[number], Value>) => Value;
16
+ tPlural: (count: number, translations: import("./type").PluralTranslationMap<Languages[number]>) => string | number | bigint | true | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined>;
17
+ setCurrentLanguage: import("react").Dispatch<import("react").SetStateAction<Languages[number]>>;
18
+ currentLanguage: Languages[number];
19
+ format: {
20
+ number: (value: number, options?: Intl.NumberFormatOptions) => string;
21
+ date: (value: Date | number, options?: Intl.DateTimeFormatOptions) => string;
22
+ time: (value: Date | number, options?: Intl.DateTimeFormatOptions) => string;
23
+ currency: (value: number, currency: string, options?: Omit<Intl.NumberFormatOptions, `style` | `currency`>) => string;
24
+ percentage: (value: number, options?: Omit<Intl.NumberFormatOptions, `style`>) => string;
25
+ };
26
+ commons: { [K in keyof Readonly<Commons>]?: string | undefined; };
27
+ };
28
+ tGlobal: (translation: TranslationMap<string>) => import("./type").TranslationValue;
29
+ };
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/createI18nContext/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,cAAc,EAAE,MAAM,QAAQ,CAAC;AAOzD,wBAAgB,iBAAiB,CAC/B,SAAS,SAAS,SAAS,MAAM,EAAE,EACnC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,EACzE,EACA,SAAS,EACT,gBAAgB,EAChB,OAAO,GACR,EAAE;IACD,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC/B,gBAAgB,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;CAC7B;;;;;;;;;;;;;;;;;;;;;;;EAmDA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.integration.test.d.ts","sourceRoot":"","sources":["../../../src/createI18nContext/index.integration.test.tsx"],"names":[],"mappings":""}