@prosopo/locale 3.2.8 → 3.3.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 (159) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +10 -9
  2. package/.turbo/turbo-build$colon$tsc.log +5 -5
  3. package/.turbo/turbo-build.log +11 -10
  4. package/CHANGELOG.md +36 -0
  5. package/dist/cjs/i18SharedOptions.cjs +1 -1
  6. package/dist/cjs/i18nBackend.cjs +4 -1
  7. package/dist/cjs/i18nFrontend.cjs +4 -1
  8. package/dist/cjs/loadI18next.cjs +41 -14
  9. package/dist/cjs/locales/en/translation.cjs +1 -0
  10. package/dist/cjs/process.cjs +17 -0
  11. package/dist/cjs/translationKey.cjs +2 -0
  12. package/dist/i18SharedOptions.js +2 -1
  13. package/dist/i18SharedOptions.js.map +1 -1
  14. package/dist/i18nBackend.d.ts.map +1 -1
  15. package/dist/i18nBackend.js +4 -1
  16. package/dist/i18nBackend.js.map +1 -1
  17. package/dist/i18nFrontend.d.ts.map +1 -1
  18. package/dist/i18nFrontend.js +4 -1
  19. package/dist/i18nFrontend.js.map +1 -1
  20. package/dist/loadI18next.d.ts +1 -0
  21. package/dist/loadI18next.d.ts.map +1 -1
  22. package/dist/loadI18next.js +41 -15
  23. package/dist/loadI18next.js.map +1 -1
  24. package/dist/locales/ar/translation.json +1 -0
  25. package/dist/locales/az/translation.json +1 -0
  26. package/dist/locales/cs/translation.json +1 -0
  27. package/dist/locales/de/translation.json +1 -0
  28. package/dist/locales/el/translation.json +1 -0
  29. package/dist/locales/en/translation.js +1 -0
  30. package/dist/locales/en/translation.json +1 -0
  31. package/dist/locales/es/translation.json +1 -0
  32. package/dist/locales/fi/translation.json +1 -0
  33. package/dist/locales/fr/translation.json +1 -0
  34. package/dist/locales/hi/translation.json +1 -0
  35. package/dist/locales/hu/translation.json +1 -0
  36. package/dist/locales/id/translation.json +1 -0
  37. package/dist/locales/it/translation.json +1 -0
  38. package/dist/locales/ja/translation.json +1 -0
  39. package/dist/locales/jv/translation.json +1 -0
  40. package/dist/locales/ko/translation.json +1 -0
  41. package/dist/locales/ml/translation.json +1 -0
  42. package/dist/locales/ms/translation.json +1 -0
  43. package/dist/locales/nl/translation.json +1 -0
  44. package/dist/locales/no/translation.json +1 -0
  45. package/dist/locales/pl/translation.json +1 -0
  46. package/dist/locales/pt/translation.json +1 -0
  47. package/dist/locales/pt-BR/translation.json +1 -0
  48. package/dist/locales/ro/translation.json +1 -0
  49. package/dist/locales/ru/translation.json +1 -0
  50. package/dist/locales/sr/translation.json +1 -0
  51. package/dist/locales/sv/translation.json +1 -0
  52. package/dist/locales/th/translation.json +1 -0
  53. package/dist/locales/tr/translation.json +1 -0
  54. package/dist/locales/uk/translation.json +1 -0
  55. package/dist/locales/vi/translation.json +1 -0
  56. package/dist/locales/zh-CN/translation.json +1 -0
  57. package/dist/process.d.ts +2 -0
  58. package/dist/process.d.ts.map +1 -0
  59. package/dist/process.js +17 -0
  60. package/dist/process.js.map +1 -0
  61. package/dist/tests/i18SharedOptions.unit.test.d.ts +2 -0
  62. package/dist/tests/i18SharedOptions.unit.test.d.ts.map +1 -0
  63. package/dist/tests/i18SharedOptions.unit.test.js +91 -0
  64. package/dist/tests/i18SharedOptions.unit.test.js.map +1 -0
  65. package/dist/tests/i18nBackend.unit.test.d.ts +2 -0
  66. package/dist/tests/i18nBackend.unit.test.d.ts.map +1 -0
  67. package/dist/tests/i18nBackend.unit.test.js +153 -0
  68. package/dist/tests/i18nBackend.unit.test.js.map +1 -0
  69. package/dist/tests/i18nFrontend.unit.test.d.ts +2 -0
  70. package/dist/tests/i18nFrontend.unit.test.d.ts.map +1 -0
  71. package/dist/tests/i18nFrontend.unit.test.js +199 -0
  72. package/dist/tests/i18nFrontend.unit.test.js.map +1 -0
  73. package/dist/tests/i18nMiddleware.unit.test.d.ts +2 -0
  74. package/dist/tests/i18nMiddleware.unit.test.d.ts.map +1 -0
  75. package/dist/tests/i18nMiddleware.unit.test.js +80 -0
  76. package/dist/tests/i18nMiddleware.unit.test.js.map +1 -0
  77. package/dist/tests/loadI18next.unit.test.d.ts +2 -0
  78. package/dist/tests/loadI18next.unit.test.d.ts.map +1 -0
  79. package/dist/tests/loadI18next.unit.test.js +270 -0
  80. package/dist/tests/loadI18next.unit.test.js.map +1 -0
  81. package/dist/tests/locale.test-d.d.ts +2 -0
  82. package/dist/tests/locale.test-d.d.ts.map +1 -0
  83. package/dist/tests/locale.test-d.js +88 -0
  84. package/dist/tests/locale.test-d.js.map +1 -0
  85. package/dist/tests/process.unit.test.d.ts +2 -0
  86. package/dist/tests/process.unit.test.d.ts.map +1 -0
  87. package/dist/tests/process.unit.test.js +14 -0
  88. package/dist/tests/process.unit.test.js.map +1 -0
  89. package/dist/tests/translationKey.unit.test.d.ts +2 -0
  90. package/dist/tests/translationKey.unit.test.d.ts.map +1 -0
  91. package/dist/tests/translationKey.unit.test.js +108 -0
  92. package/dist/tests/translationKey.unit.test.js.map +1 -0
  93. package/dist/tests/translations.unit.test.d.ts +2 -0
  94. package/dist/tests/translations.unit.test.d.ts.map +1 -0
  95. package/dist/tests/translations.unit.test.js +74 -0
  96. package/dist/tests/translations.unit.test.js.map +1 -0
  97. package/dist/tests/useTranslation.unit.test.d.ts +2 -0
  98. package/dist/tests/useTranslation.unit.test.d.ts.map +1 -0
  99. package/dist/tests/useTranslation.unit.test.js +81 -0
  100. package/dist/tests/useTranslation.unit.test.js.map +1 -0
  101. package/dist/tests/util.unit.test.d.ts +2 -0
  102. package/dist/tests/util.unit.test.d.ts.map +1 -0
  103. package/dist/tests/util.unit.test.js +66 -0
  104. package/dist/tests/util.unit.test.js.map +1 -0
  105. package/dist/translationKey.d.ts +4 -0
  106. package/dist/translationKey.d.ts.map +1 -1
  107. package/dist/translationKey.js +2 -1
  108. package/dist/translationKey.js.map +1 -1
  109. package/package.json +2 -2
  110. package/src/i18SharedOptions.ts +4 -4
  111. package/src/i18nBackend.ts +16 -0
  112. package/src/i18nFrontend.ts +16 -0
  113. package/src/loadI18next.ts +83 -15
  114. package/src/locales/ar/translation.json +1 -0
  115. package/src/locales/az/translation.json +1 -0
  116. package/src/locales/cs/translation.json +1 -0
  117. package/src/locales/de/translation.json +1 -0
  118. package/src/locales/el/translation.json +1 -0
  119. package/src/locales/en/translation.json +1 -0
  120. package/src/locales/es/translation.json +1 -0
  121. package/src/locales/fi/translation.json +1 -0
  122. package/src/locales/fr/translation.json +1 -0
  123. package/src/locales/hi/translation.json +1 -0
  124. package/src/locales/hu/translation.json +1 -0
  125. package/src/locales/id/translation.json +1 -0
  126. package/src/locales/it/translation.json +1 -0
  127. package/src/locales/ja/translation.json +1 -0
  128. package/src/locales/jv/translation.json +1 -0
  129. package/src/locales/ko/translation.json +1 -0
  130. package/src/locales/ml/translation.json +1 -0
  131. package/src/locales/ms/translation.json +1 -0
  132. package/src/locales/nl/translation.json +1 -0
  133. package/src/locales/no/translation.json +1 -0
  134. package/src/locales/pl/translation.json +1 -0
  135. package/src/locales/pt/translation.json +1 -0
  136. package/src/locales/pt-BR/translation.json +1 -0
  137. package/src/locales/ro/translation.json +1 -0
  138. package/src/locales/ru/translation.json +1 -0
  139. package/src/locales/sr/translation.json +1 -0
  140. package/src/locales/sv/translation.json +1 -0
  141. package/src/locales/th/translation.json +1 -0
  142. package/src/locales/tr/translation.json +1 -0
  143. package/src/locales/uk/translation.json +1 -0
  144. package/src/locales/vi/translation.json +1 -0
  145. package/src/locales/zh-CN/translation.json +1 -0
  146. package/src/process.ts +29 -0
  147. package/src/tests/i18SharedOptions.unit.test.ts +139 -0
  148. package/src/tests/i18nBackend.unit.test.ts +241 -0
  149. package/src/tests/i18nFrontend.unit.test.ts +302 -0
  150. package/src/tests/i18nMiddleware.unit.test.ts +140 -0
  151. package/src/tests/loadI18next.unit.test.ts +443 -0
  152. package/src/tests/locale.test-d.ts +156 -0
  153. package/src/tests/process.unit.test.ts +33 -0
  154. package/src/tests/translationKey.unit.test.ts +166 -0
  155. package/src/tests/translations.unit.test.ts +110 -0
  156. package/src/tests/useTranslation.unit.test.ts +134 -0
  157. package/src/tests/util.unit.test.ts +102 -0
  158. package/src/translationKey.ts +18 -3
  159. package/tsconfig.tsbuildinfo +1 -1
@@ -1,5 +1,5 @@
1
1
 
2
- > @prosopo/locale@3.2.8 build:cjs
2
+ > @prosopo/locale@3.3.0 build:cjs
3
3
  > NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
4
4
 
5
5
  ViteCommonJSConfig: .
@@ -9,23 +9,24 @@ ViteCommonJSConfig: .
9
9
  vite v8.1.5 building ssr environment for production...
10
10
  Bundle build started
11
11
  
12
- ✓ 12 modules transformed.
12
+ ✓ 13 modules transformed.
13
13
  rendering chunks...
14
14
  computing gzip size...
15
15
  dist/cjs/util.cjs 0.28 kB │ gzip: 0.17 kB
16
16
  dist/cjs/useTranslation.cjs 0.35 kB │ gzip: 0.20 kB
17
17
  dist/cjs/i18nMiddleware.cjs 0.36 kB │ gzip: 0.21 kB
18
- dist/cjs/i18SharedOptions.cjs 0.42 kB │ gzip: 0.27 kB
19
- dist/cjs/translationKey.cjs 0.64 kB │ gzip: 0.36 kB
18
+ dist/cjs/i18SharedOptions.cjs 0.41 kB │ gzip: 0.25 kB
19
+ dist/cjs/translationKey.cjs 0.74 kB │ gzip: 0.38 kB
20
+ dist/cjs/process.cjs 0.78 kB │ gzip: 0.46 kB
20
21
  dist/cjs/index.cjs 0.83 kB │ gzip: 0.27 kB
21
22
  dist/cjs/translations.cjs 0.86 kB │ gzip: 0.46 kB
22
- dist/cjs/loadI18next.cjs 0.90 kB │ gzip: 0.37 kB
23
23
  dist/cjs/_virtual/_rolldown/runtime.cjs 1.00 kB │ gzip: 0.50 kB
24
- dist/cjs/i18nBackend.cjs 1.36 kB │ gzip: 0.58 kB
25
- dist/cjs/i18nFrontend.cjs 2.35 kB │ gzip: 0.84 kB
26
- dist/cjs/locales/en/translation.cjs 15.72 kB │ gzip: 5.59 kB
24
+ dist/cjs/i18nBackend.cjs 1.47 kB │ gzip: 0.62 kB
25
+ dist/cjs/loadI18next.cjs 2.03 kB │ gzip: 0.84 kB
26
+ dist/cjs/i18nFrontend.cjs 2.47 kB │ gzip: 0.87 kB
27
+ dist/cjs/locales/en/translation.cjs 15.80 kB │ gzip: 5.62 kB
27
28
 
28
- ✓ built in 83ms
29
+ ✓ built in 86ms
29
30
  [copy-plugin] copying /home/runner/work/captcha/captcha/packages/locale/src/locales/ar/translation.json to /home/runner/work/captcha/captcha/packages/locale/dist/locales/ar/translation.json
30
31
  [copy-plugin] copying /home/runner/work/captcha/captcha/packages/locale/src/locales/az/translation.json to /home/runner/work/captcha/captcha/packages/locale/dist/locales/az/translation.json
31
32
  [copy-plugin] copying /home/runner/work/captcha/captcha/packages/locale/src/locales/cs/translation.json to /home/runner/work/captcha/captcha/packages/locale/dist/locales/cs/translation.json
@@ -1,14 +1,14 @@
1
1
 
2
- > @prosopo/locale@3.2.8 build:tsc
2
+ > @prosopo/locale@3.3.0 build:tsc
3
3
  > tsc --build --verbose
4
4
 
5
- 8:58:35 PM - Projects in this build:
5
+ 7:04:34 AM - Projects in this build:
6
6
  * ../../dev/config/tsconfig.json
7
7
  * tsconfig.json
8
8
 
9
- 8:58:36 PM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/webpack/webpack.config.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
9
+ 7:04:34 AM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/vite/vite-plugin-copy.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
10
10
 
11
- 8:58:36 PM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
11
+ 7:04:34 AM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
12
12
 
13
- 8:58:36 PM - Building project '/home/runner/work/captcha/captcha/packages/locale/tsconfig.json'...
13
+ 7:04:34 AM - Building project '/home/runner/work/captcha/captcha/packages/locale/tsconfig.json'...
14
14
 
@@ -1,9 +1,9 @@
1
1
 
2
- > @prosopo/locale@3.2.8 build
2
+ > @prosopo/locale@3.3.0 build
3
3
  > npm run build:cross-env -- --mode ${NODE_ENV:-development}
4
4
 
5
5
 
6
- > @prosopo/locale@3.2.8 build:cross-env
6
+ > @prosopo/locale@3.3.0 build:cross-env
7
7
  > vite build --config vite.esm.config.ts --mode production
8
8
 
9
9
  ViteEsmConfig: .
@@ -13,23 +13,24 @@ ViteEsmConfig: .
13
13
  vite v8.1.5 building ssr environment for production...
14
14
  Bundle build started
15
15
  
16
- ✓ 12 modules transformed.
16
+ ✓ 13 modules transformed.
17
17
  rendering chunks...
18
18
  computing gzip size...
19
19
  dist/_virtual/_rolldown/runtime.js 0.04 kB │ gzip: 0.06 kB
20
20
  dist/util.js 0.25 kB │ gzip: 0.16 kB
21
21
  dist/i18nMiddleware.js 0.27 kB │ gzip: 0.18 kB
22
22
  dist/useTranslation.js 0.30 kB │ gzip: 0.19 kB
23
- dist/i18SharedOptions.js 0.37 kB │ gzip: 0.26 kB
23
+ dist/i18SharedOptions.js 0.37 kB │ gzip: 0.25 kB
24
24
  dist/index.js 0.47 kB │ gzip: 0.20 kB
25
- dist/translationKey.js 0.61 kB │ gzip: 0.36 kB
25
+ dist/translationKey.js 0.68 kB │ gzip: 0.37 kB
26
26
  dist/translations.js 0.70 kB │ gzip: 0.39 kB
27
- dist/loadI18next.js 0.84 kB │ gzip: 0.36 kB
28
- dist/i18nBackend.js 0.91 kB │ gzip: 0.49 kB
29
- dist/i18nFrontend.js 1.65 kB │ gzip: 0.74 kB
30
- dist/locales/en/translation.js 15.49 kB │ gzip: 5.56 kB
27
+ dist/process.js 0.77 kB │ gzip: 0.46 kB
28
+ dist/i18nBackend.js 1.01 kB │ gzip: 0.53 kB
29
+ dist/i18nFrontend.js 1.75 kB │ gzip: 0.78 kB
30
+ dist/loadI18next.js 1.93 kB │ gzip: 0.83 kB
31
+ dist/locales/en/translation.js 15.56 kB │ gzip: 5.59 kB
31
32
 
32
- ✓ built in 117ms
33
+ ✓ built in 74ms
33
34
  [copy-plugin] copying /home/runner/work/captcha/captcha/packages/locale/src/locales/ar/translation.json to /home/runner/work/captcha/captcha/packages/locale/dist/locales/ar/translation.json
34
35
  [copy-plugin] copying /home/runner/work/captcha/captcha/packages/locale/src/locales/az/translation.json to /home/runner/work/captcha/captcha/packages/locale/dist/locales/az/translation.json
35
36
  [copy-plugin] copying /home/runner/work/captcha/captcha/packages/locale/src/locales/cs/translation.json to /home/runner/work/captcha/captcha/packages/locale/dist/locales/cs/translation.json
package/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # @prosopo/locale
2
2
 
3
+ ## 3.3.0
4
+ ### Minor Changes
5
+
6
+ - 9091a78: test(locale): unit + type tests, fix empty translation-key schema and i18n load hangs
7
+
8
+ - `getLeafFieldPath` never emitted a path, because a string leaf returned `[]`
9
+ and the parent mapped over that empty list. `TranslationKeysSchema` was
10
+ therefore an empty `z.enum`, and mongoose registers its enum validator even
11
+ for an empty list — so every non-null `result.reason` failed validation on the
12
+ three solution schemas in `@prosopo/types-database`.
13
+ - `loadI18next` wrapped its dynamic imports in a synchronous `try/catch`, which
14
+ cannot see a rejected import or a rejected `changeLanguage`. Those paths left
15
+ the returned promise pending forever instead of rejecting.
16
+ - `initializeI18n` only registered its `loaded` listener on the initialisation
17
+ path, so a caller arriving after i18next was already up (or on the client, for
18
+ the backend module) waited on an event that would never fire.
19
+ - `loadI18next` now bounds itself with `I18N_LOAD_TIMEOUT_MS` (10s). Resolution
20
+ is event-driven, so a backend that never answers left the promise pending for
21
+ the lifetime of the process. On timeout it resolves with the degraded instance
22
+ — i18next renders the key itself for a missing resource, and neither caller
23
+ handles a rejection — or rejects if no instance was ever created.
24
+ - The `process.env` read in `i18SharedOptions` goes through a `getProcess()`
25
+ seam so the browser-runtime path is testable.
26
+
27
+ ## 3.2.9
28
+ ### Patch Changes
29
+
30
+ - bcef918: Adds a per-email submission-count rate limit on the verify pipeline. Site operators can now cap how many server-checked captcha submissions any one normalised email (Gmail dot / `+tag` tricks collapsed across providers) may back before further submissions from that address are rejected with `API.SPAM_EMAIL_COUNT_EXCEEDED`.
31
+
32
+ - New `spamFilter.emailRules.maxEmailSubmissionCount` (int, min 1, optional) on `ClientSettingsSchema`.
33
+ - New `metadata.emailNormalised` field on all three captcha records (image / PoW / puzzle) — written alongside `metadata.email` whenever `storeMetadata` is on. Backed by a partial index (`spamEmailCount_partial`) on each collection.
34
+ - New DB method `countCommitmentsByNormalisedEmail(dappAccount, emailNormalised)` sums the three per-collection counts so limits span captcha types.
35
+ - Puzzle verify gains a `spamFilter` parameter to bring it to parity with img/pow for the count check.
36
+ - English + all 31 non-English locales gain the `API.SPAM_EMAIL_COUNT_EXCEEDED` translation.
37
+ - Fixes silent-drift bug: `UserSettingsSchema.spamFilter.emailRules` was missing `maxEmailSubmissionCount` on the mongoose side, which strict mode would have dropped on `$set`.
38
+
3
39
  ## 3.2.8
4
40
  ### Patch Changes
5
41
 
@@ -1,6 +1,6 @@
1
1
  const require_translations = require("./translations.cjs");
2
2
  var i18nSharedOptions = {
3
- debug: (typeof process !== "undefined" ? process.env?.PROSOPO_LOG_LEVEL : void 0) === "debug",
3
+ debug: require("./process.cjs").getProcess()?.env?.PROSOPO_LOG_LEVEL === "debug",
4
4
  fallbackLng: require_translations.LanguageSchema.enum.en,
5
5
  namespace: "translation",
6
6
  supportedLngs: Object.values(require_translations.Languages),
@@ -22,10 +22,13 @@ function initializeI18n(i18nLoadedCallback) {
22
22
  ns: ["translation"],
23
23
  backend: { loadPath }
24
24
  });
25
+ let notified = false;
25
26
  i18next.default.on("loaded", () => {
27
+ if (notified) return;
28
+ notified = true;
26
29
  i18nLoadedCallback?.(i18next.default);
27
30
  });
28
- }
31
+ } else i18nLoadedCallback?.(i18next.default);
29
32
  return i18next.default;
30
33
  }
31
34
  //#endregion
@@ -49,10 +49,13 @@ function initializeI18n(i18nLoadedCallback, lng) {
49
49
  },
50
50
  ...reactOptions
51
51
  });
52
+ let notified = false;
52
53
  i18next.default.on("loaded", () => {
54
+ if (notified) return;
55
+ notified = true;
53
56
  i18nLoadedCallback?.(i18next.default);
54
57
  });
55
- }
58
+ } else i18nLoadedCallback?.(i18next.default);
56
59
  return i18next.default;
57
60
  }
58
61
  //#endregion
@@ -1,26 +1,53 @@
1
1
  //#region src/loadI18next.ts
2
2
  var i18nInstance;
3
+ /**
4
+ * How long to wait for i18next to report `loaded` before giving up on it.
5
+ *
6
+ * Resolution is driven by an event, and events are not guaranteed: a backend
7
+ * that never answers (http backend against a dead CDN, fs backend against a
8
+ * missing locales dir) leaves the listener armed and the promise pending for
9
+ * the lifetime of the process. `cli.ts` calls loadI18next(true).then(...) with
10
+ * nothing to time it out, so a pending promise there is a silent boot hang with
11
+ * no log line to explain it.
12
+ */
13
+ var I18N_LOAD_TIMEOUT_MS = 1e4;
3
14
  var reconcileLanguage = async (instance, lng) => {
4
15
  if (lng && instance.language !== lng) await instance.changeLanguage(lng);
5
16
  return instance;
6
17
  };
7
18
  async function loadI18next(backend, lng) {
8
19
  return new Promise((resolve, reject) => {
9
- try {
10
- if (backend) Promise.resolve().then(() => require("./i18nBackend.cjs")).then(({ default: initializeI18n }) => {
11
- if (!i18nInstance) i18nInstance = initializeI18n(resolve);
12
- else resolve(i18nInstance);
13
- });
14
- else Promise.resolve().then(() => require("./i18nFrontend.cjs")).then(({ default: initializeI18n }) => {
15
- if (!i18nInstance) i18nInstance = initializeI18n((instance) => {
16
- reconcileLanguage(instance, lng).then(resolve);
17
- }, lng);
18
- else reconcileLanguage(i18nInstance, lng).then(resolve);
19
- });
20
- } catch (e) {
21
- reject(e);
22
- }
20
+ let settled = false;
21
+ const timer = setTimeout(() => {
22
+ settled = true;
23
+ if (i18nInstance) resolve(i18nInstance);
24
+ else reject(/* @__PURE__ */ new Error(`i18next did not load within ${I18N_LOAD_TIMEOUT_MS}ms and no instance was created`));
25
+ }, I18N_LOAD_TIMEOUT_MS);
26
+ timer.unref?.();
27
+ const done = (instance) => {
28
+ if (settled) return;
29
+ settled = true;
30
+ clearTimeout(timer);
31
+ resolve(instance);
32
+ };
33
+ const failWith = (error) => {
34
+ if (settled) return;
35
+ settled = true;
36
+ clearTimeout(timer);
37
+ reject(error);
38
+ };
39
+ if (backend) Promise.resolve().then(() => require("./i18nBackend.cjs")).then(({ default: initializeI18n }) => {
40
+ if (!i18nInstance) i18nInstance = initializeI18n(done);
41
+ else done(i18nInstance);
42
+ }).catch(failWith);
43
+ else Promise.resolve().then(() => require("./i18nFrontend.cjs")).then(({ default: initializeI18n }) => {
44
+ if (!i18nInstance) i18nInstance = initializeI18n((instance) => {
45
+ reconcileLanguage(instance, lng).then(done).catch(failWith);
46
+ }, lng);
47
+ else reconcileLanguage(i18nInstance, lng).then(done).catch(failWith);
48
+ }).catch(failWith);
23
49
  });
24
50
  }
25
51
  //#endregion
52
+ exports.I18N_LOAD_TIMEOUT_MS = I18N_LOAD_TIMEOUT_MS;
26
53
  exports.default = loadI18next;
@@ -120,6 +120,7 @@ var API = {
120
120
  "PROVIDER_VERIFY_FAILED": "Provider verification failed",
121
121
  "SPAM_EMAIL_DOMAIN": "Email domain not allowed",
122
122
  "SPAM_EMAIL_RULE": "Email address blocked by spam filter rules",
123
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Too many submissions from this email address",
123
124
  "VPN_BLOCKED": "Requests from VPN connections are not allowed for this site",
124
125
  "PROXY_BLOCKED": "Requests from proxy servers are not allowed for this site",
125
126
  "TOR_BLOCKED": "Requests from Tor exit nodes are not allowed for this site",
@@ -0,0 +1,17 @@
1
+ //#region src/process.ts
2
+ /**
3
+ * The `process` global, or undefined where there is none.
4
+ *
5
+ * This package is reached transitively from browser bundles, where `process`
6
+ * may be missing entirely or present but stripped down. A bare `process.env`
7
+ * read throws a ReferenceError in that case and takes the whole page down.
8
+ *
9
+ * It is a function, and it lives in its own module, so callers can be tested
10
+ * against a runtime that has no `process` at all. Inlining the `typeof` check
11
+ * at the point of use makes that branch untestable: vitest calls
12
+ * `process.memoryUsage()` between suites, so stubbing the real global away
13
+ * fails the run rather than the module under test.
14
+ */
15
+ var getProcess = () => typeof process !== "undefined" ? process : void 0;
16
+ //#endregion
17
+ exports.getProcess = getProcess;
@@ -6,6 +6,7 @@ function getLeafFieldPath(obj) {
6
6
  return Object.keys(obj).reduce((arr, key) => {
7
7
  const value = obj[key];
8
8
  if (value === void 0) throw new Error(`Undefined value for key ${key}`);
9
+ if (typeof value === "string") return arr.concat(key);
9
10
  const children = getLeafFieldPath(value);
10
11
  return arr.concat(children.map((child) => {
11
12
  return `${key}.${child}`;
@@ -15,3 +16,4 @@ function getLeafFieldPath(obj) {
15
16
  var TranslationKeysSchema = zod.z.enum(getLeafFieldPath(require_translation.default));
16
17
  //#endregion
17
18
  exports.TranslationKeysSchema = TranslationKeysSchema;
19
+ exports.getLeafFieldPath = getLeafFieldPath;
@@ -1,6 +1,7 @@
1
1
  import { LanguageSchema, Languages } from "./translations.js";
2
+ import { getProcess } from "./process.js";
2
3
  var i18nSharedOptions = {
3
- debug: (typeof process !== "undefined" ? process.env?.PROSOPO_LOG_LEVEL : void 0) === "debug",
4
+ debug: getProcess()?.env?.PROSOPO_LOG_LEVEL === "debug",
4
5
  fallbackLng: LanguageSchema.enum.en,
5
6
  namespace: "translation",
6
7
  supportedLngs: Object.values(Languages),
@@ -1 +1 @@
1
- {"version":3,"file":"i18SharedOptions.js","sourceRoot":"","sources":["../src/i18SharedOptions.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAM9D,MAAM,QAAQ,GACb,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC;AAE7E,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAChC,KAAK,EAAE,QAAQ,KAAK,OAAO;IAC3B,WAAW,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE;IACnC,SAAS,EAAE,aAAa;IACxB,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;IACvC,wBAAwB,EAAE,KAAK;CAC/B,CAAC"}
1
+ {"version":3,"file":"i18SharedOptions.js","sourceRoot":"","sources":["../src/i18SharedOptions.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAM9D,MAAM,QAAQ,GAAG,UAAU,EAAE,EAAE,GAAG,EAAE,iBAAiB,CAAC;AAEtD,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAChC,KAAK,EAAE,QAAQ,KAAK,OAAO;IAC3B,WAAW,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE;IACnC,SAAS,EAAE,aAAa;IACxB,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;IACvC,wBAAwB,EAAE,KAAK;CAC/B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"i18nBackend.d.ts","sourceRoot":"","sources":["../src/i18nBackend.ts"],"names":[],"mappings":"AAeA,OAAO,IAAI,MAAM,SAAS,CAAC;AAY3B,wBAAgB,cAAc,CAC7B,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,IAAI,KAAK,IAAI,0BAsBjD;AAED,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"i18nBackend.d.ts","sourceRoot":"","sources":["../src/i18nBackend.ts"],"names":[],"mappings":"AAeA,OAAO,IAAI,MAAM,SAAS,CAAC;AAY3B,wBAAgB,cAAc,CAC7B,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,IAAI,KAAK,IAAI,0BAsCjD;AAED,eAAe,cAAc,CAAC"}
@@ -19,10 +19,13 @@ function initializeI18n(i18nLoadedCallback) {
19
19
  ns: ["translation"],
20
20
  backend: { loadPath }
21
21
  });
22
+ let notified = false;
22
23
  i18n.on("loaded", () => {
24
+ if (notified) return;
25
+ notified = true;
23
26
  i18nLoadedCallback?.(i18n);
24
27
  });
25
- }
28
+ } else i18nLoadedCallback?.(i18n);
26
29
  return i18n;
27
30
  }
28
31
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"i18nBackend.js","sourceRoot":"","sources":["../src/i18nBackend.ts"],"names":[],"mappings":"AAcA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,IAAI,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,QAAQ,GACb,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,8BAA8B,CAAC,OAAO,CACrE,SAAS,EACT,EAAE,CACF,CAAC;AAEH,MAAM,UAAU,cAAc,CAC7B,kBAAiD;IAEjD,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,YAAY,EAAE,EAAE,CAAC;QAC3C,MAAM,WAAW,GAAG,IAAI,0BAA0B,CAAC,IAAI,EAAE;YACxD,KAAK,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC;QACH,IAAI;aAEF,GAAG,CAAC,SAAS,CAAC;aACd,GAAG,CAAC,WAAW,CAAC;aAChB,IAAI,CAAC;YACL,GAAG,iBAAiB;YACpB,EAAE,EAAE,CAAC,aAAa,CAAC;YACnB,OAAO,EAAE;gBACR,QAAQ;aACR;SACD,CAAC,CAAC;QACJ,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YACtB,kBAAkB,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"i18nBackend.js","sourceRoot":"","sources":["../src/i18nBackend.ts"],"names":[],"mappings":"AAcA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,IAAI,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,QAAQ,GACb,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,8BAA8B,CAAC,OAAO,CACrE,SAAS,EACT,EAAE,CACF,CAAC;AAEH,MAAM,UAAU,cAAc,CAC7B,kBAAiD;IAEjD,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,YAAY,EAAE,EAAE,CAAC;QAC3C,MAAM,WAAW,GAAG,IAAI,0BAA0B,CAAC,IAAI,EAAE;YACxD,KAAK,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC;QACH,IAAI;aAEF,GAAG,CAAC,SAAS,CAAC;aACd,GAAG,CAAC,WAAW,CAAC;aAChB,IAAI,CAAC;YACL,GAAG,iBAAiB;YACpB,EAAE,EAAE,CAAC,aAAa,CAAC;YACnB,OAAO,EAAE;gBACR,QAAQ;aACR;SACD,CAAC,CAAC;QAKJ,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YACtB,IAAI,QAAQ,EAAE,CAAC;gBACd,OAAO;YACR,CAAC;YACD,QAAQ,GAAG,IAAI,CAAC;YAChB,kBAAkB,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACJ,CAAC;SAAM,CAAC;QAMP,kBAAkB,EAAE,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,eAAe,cAAc,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"i18nFrontend.d.ts","sourceRoot":"","sources":["../src/i18nFrontend.ts"],"names":[],"mappings":"AAcA,OAAO,IAA0B,MAAM,SAAS,CAAC;AAuBjD,wBAAgB,cAAc,CAC7B,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,IAAI,KAAK,IAAI,EACjD,GAAG,CAAC,EAAE,MAAM,0BA+CZ;AAED,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"i18nFrontend.d.ts","sourceRoot":"","sources":["../src/i18nFrontend.ts"],"names":[],"mappings":"AAcA,OAAO,IAA0B,MAAM,SAAS,CAAC;AAuBjD,wBAAgB,cAAc,CAC7B,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,IAAI,KAAK,IAAI,EACjD,GAAG,CAAC,EAAE,MAAM,0BA+DZ;AAED,eAAe,cAAc,CAAC"}
@@ -44,10 +44,13 @@ function initializeI18n(i18nLoadedCallback, lng) {
44
44
  },
45
45
  ...reactOptions
46
46
  });
47
+ let notified = false;
47
48
  i18n.on("loaded", () => {
49
+ if (notified) return;
50
+ notified = true;
48
51
  i18nLoadedCallback?.(i18n);
49
52
  });
50
- }
53
+ } else i18nLoadedCallback?.(i18n);
51
54
  return i18n;
52
55
  }
53
56
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"i18nFrontend.js","sourceRoot":"","sources":["../src/i18nFrontend.ts"],"names":[],"mappings":"AAcA,OAAO,IAA0B,MAAM,SAAS,CAAC;AACjD,OAAO,8BAA8B,MAAM,kCAAkC,CAAC;AAC9E,OAAO,cAAc,MAAM,yBAAyB,CAAC;AACrD,OAAO,WAAW,MAAM,sBAAsB,CAAC;AAC/C,OAAO,kBAAkB,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,MAAM,YAAY,GAAgB;IACjC,KAAK,EAAE;QACN,WAAW,EAAE,IAAI;KACjB;IACD,SAAS,EAAE;QACV,KAAK,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC;QACpD,MAAM,EAAE,CAAC,cAAc,EAAE,QAAQ,CAAC;KAClC;CACD,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAE,SAAiB,EAAE,EAAE;IAC3D,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IAClD,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,QAAQ,EAAE,EAAE,EAAE,CAAC,YAAY,QAAQ,IAAI,SAAS,OAAO,CAAC;AAC/F,CAAC,CAAC;AAEF,MAAM,UAAU,cAAc,CAC7B,kBAAiD,EACjD,GAAY;IAEZ,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QACzB,IAAI;aAEF,GAAG,CAAC,cAAc,CAAC;aACnB,GAAG,CACH,IAAI,8BAA8B,CAAC,IAAI,EAAE;YACxC,KAAK,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,WAAW,CAAC;YAC9C,iBAAiB,EAAE,KAAK;YACxB,YAAY,EAAE,SAAS;YACvB,kBAAkB,EAAE,YAAY;YAChC,MAAM,EAAE,CAAC,cAAc,EAAE,QAAQ,CAAC;SAClC,CAAC,CACF;aACA,GAAG,CAAC,gBAAgB,CAAC;aACrB,IAAI,CAAC;YACL,GAAG,iBAAiB;YAOpB,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE;gBACR,QAAQ,EAAE;oBACT,WAAW;oBAEX,kBAAkB,CACjB,CAAC,QAAgB,EAAE,SAAiB,EAAE,EAAE,CACvC,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CACzC;iBACD;gBACD,cAAc,EAAE;oBACf;wBACC,QAAQ,EAAE,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC;qBAC1C;iBACD;aACD;YACD,GAAG,YAAY;SACA,CAAC,CAAC;QACnB,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YACtB,kBAAkB,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"i18nFrontend.js","sourceRoot":"","sources":["../src/i18nFrontend.ts"],"names":[],"mappings":"AAcA,OAAO,IAA0B,MAAM,SAAS,CAAC;AACjD,OAAO,8BAA8B,MAAM,kCAAkC,CAAC;AAC9E,OAAO,cAAc,MAAM,yBAAyB,CAAC;AACrD,OAAO,WAAW,MAAM,sBAAsB,CAAC;AAC/C,OAAO,kBAAkB,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,MAAM,YAAY,GAAgB;IACjC,KAAK,EAAE;QACN,WAAW,EAAE,IAAI;KACjB;IACD,SAAS,EAAE;QACV,KAAK,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC;QACpD,MAAM,EAAE,CAAC,cAAc,EAAE,QAAQ,CAAC;KAClC;CACD,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAE,SAAiB,EAAE,EAAE;IAC3D,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IAClD,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,QAAQ,EAAE,EAAE,EAAE,CAAC,YAAY,QAAQ,IAAI,SAAS,OAAO,CAAC;AAC/F,CAAC,CAAC;AAEF,MAAM,UAAU,cAAc,CAC7B,kBAAiD,EACjD,GAAY;IAEZ,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QACzB,IAAI;aAEF,GAAG,CAAC,cAAc,CAAC;aACnB,GAAG,CACH,IAAI,8BAA8B,CAAC,IAAI,EAAE;YACxC,KAAK,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,WAAW,CAAC;YAC9C,iBAAiB,EAAE,KAAK;YACxB,YAAY,EAAE,SAAS;YACvB,kBAAkB,EAAE,YAAY;YAChC,MAAM,EAAE,CAAC,cAAc,EAAE,QAAQ,CAAC;SAClC,CAAC,CACF;aACA,GAAG,CAAC,gBAAgB,CAAC;aACrB,IAAI,CAAC;YACL,GAAG,iBAAiB;YAOpB,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE;gBACR,QAAQ,EAAE;oBACT,WAAW;oBAEX,kBAAkB,CACjB,CAAC,QAAgB,EAAE,SAAiB,EAAE,EAAE,CACvC,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CACzC;iBACD;gBACD,cAAc,EAAE;oBACf;wBACC,QAAQ,EAAE,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC;qBAC1C;iBACD;aACD;YACD,GAAG,YAAY;SACA,CAAC,CAAC;QAKnB,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YACtB,IAAI,QAAQ,EAAE,CAAC;gBACd,OAAO;YACR,CAAC;YACD,QAAQ,GAAG,IAAI,CAAC;YAChB,kBAAkB,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACJ,CAAC;SAAM,CAAC;QAMP,kBAAkB,EAAE,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,eAAe,cAAc,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import type { i18n } from "i18next";
2
+ export declare const I18N_LOAD_TIMEOUT_MS = 10000;
2
3
  declare function loadI18next(backend: boolean, lng?: string): Promise<i18n>;
3
4
  export type { i18n as Ti18n };
4
5
  export default loadI18next;
@@ -1 +1 @@
1
- {"version":3,"file":"loadI18next.d.ts","sourceRoot":"","sources":["../src/loadI18next.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAapC,iBAAe,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCxE;AAED,YAAY,EAAE,IAAI,IAAI,KAAK,EAAE,CAAC;AAE9B,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"loadI18next.d.ts","sourceRoot":"","sources":["../src/loadI18next.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAapC,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAY3C,iBAAe,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6FxE;AAED,YAAY,EAAE,IAAI,IAAI,KAAK,EAAE,CAAC;AAE9B,eAAe,WAAW,CAAC"}
@@ -1,26 +1,52 @@
1
1
  //#region src/loadI18next.ts
2
2
  var i18nInstance;
3
+ /**
4
+ * How long to wait for i18next to report `loaded` before giving up on it.
5
+ *
6
+ * Resolution is driven by an event, and events are not guaranteed: a backend
7
+ * that never answers (http backend against a dead CDN, fs backend against a
8
+ * missing locales dir) leaves the listener armed and the promise pending for
9
+ * the lifetime of the process. `cli.ts` calls loadI18next(true).then(...) with
10
+ * nothing to time it out, so a pending promise there is a silent boot hang with
11
+ * no log line to explain it.
12
+ */
13
+ var I18N_LOAD_TIMEOUT_MS = 1e4;
3
14
  var reconcileLanguage = async (instance, lng) => {
4
15
  if (lng && instance.language !== lng) await instance.changeLanguage(lng);
5
16
  return instance;
6
17
  };
7
18
  async function loadI18next(backend, lng) {
8
19
  return new Promise((resolve, reject) => {
9
- try {
10
- if (backend) import("./i18nBackend.js").then(({ default: initializeI18n }) => {
11
- if (!i18nInstance) i18nInstance = initializeI18n(resolve);
12
- else resolve(i18nInstance);
13
- });
14
- else import("./i18nFrontend.js").then(({ default: initializeI18n }) => {
15
- if (!i18nInstance) i18nInstance = initializeI18n((instance) => {
16
- reconcileLanguage(instance, lng).then(resolve);
17
- }, lng);
18
- else reconcileLanguage(i18nInstance, lng).then(resolve);
19
- });
20
- } catch (e) {
21
- reject(e);
22
- }
20
+ let settled = false;
21
+ const timer = setTimeout(() => {
22
+ settled = true;
23
+ if (i18nInstance) resolve(i18nInstance);
24
+ else reject(/* @__PURE__ */ new Error(`i18next did not load within ${I18N_LOAD_TIMEOUT_MS}ms and no instance was created`));
25
+ }, I18N_LOAD_TIMEOUT_MS);
26
+ timer.unref?.();
27
+ const done = (instance) => {
28
+ if (settled) return;
29
+ settled = true;
30
+ clearTimeout(timer);
31
+ resolve(instance);
32
+ };
33
+ const failWith = (error) => {
34
+ if (settled) return;
35
+ settled = true;
36
+ clearTimeout(timer);
37
+ reject(error);
38
+ };
39
+ if (backend) import("./i18nBackend.js").then(({ default: initializeI18n }) => {
40
+ if (!i18nInstance) i18nInstance = initializeI18n(done);
41
+ else done(i18nInstance);
42
+ }).catch(failWith);
43
+ else import("./i18nFrontend.js").then(({ default: initializeI18n }) => {
44
+ if (!i18nInstance) i18nInstance = initializeI18n((instance) => {
45
+ reconcileLanguage(instance, lng).then(done).catch(failWith);
46
+ }, lng);
47
+ else reconcileLanguage(i18nInstance, lng).then(done).catch(failWith);
48
+ }).catch(failWith);
23
49
  });
24
50
  }
25
51
  //#endregion
26
- export { loadI18next as default };
52
+ export { I18N_LOAD_TIMEOUT_MS, loadI18next as default };
@@ -1 +1 @@
1
- {"version":3,"file":"loadI18next.js","sourceRoot":"","sources":["../src/loadI18next.ts"],"names":[],"mappings":"AAeA,IAAI,YAAkB,CAAC;AAEvB,MAAM,iBAAiB,GAAG,KAAK,EAC9B,QAAc,EACd,GAAuB,EACP,EAAE;IAClB,IAAI,GAAG,IAAI,QAAQ,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;QACtC,MAAM,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAEF,KAAK,UAAU,WAAW,CAAC,OAAgB,EAAE,GAAY;IACxD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtC,IAAI,CAAC;YACJ,IAAI,OAAO,EAAE,CAAC;gBACb,MAAM,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE;oBAC/D,IAAI,CAAC,YAAY,EAAE,CAAC;wBAEnB,YAAY,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;oBACxC,CAAC;yBAAM,CAAC;wBAEP,OAAO,CAAC,YAAY,CAAC,CAAC;oBACvB,CAAC;gBACF,CAAC,CAAC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE;oBAChE,IAAI,CAAC,YAAY,EAAE,CAAC;wBAKnB,YAAY,GAAG,cAAc,CAAC,CAAC,QAAQ,EAAE,EAAE;4BAC1C,KAAK,iBAAiB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;wBACrD,CAAC,EAAE,GAAG,CAAC,CAAC;oBACT,CAAC;yBAAM,CAAC;wBAMP,KAAK,iBAAiB,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACzD,CAAC;gBACF,CAAC,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACZ,MAAM,CAAC,CAAC,CAAC,CAAC;QACX,CAAC;IACF,CAAC,CAAC,CAAC;AACJ,CAAC;AAID,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"loadI18next.js","sourceRoot":"","sources":["../src/loadI18next.ts"],"names":[],"mappings":"AAeA,IAAI,YAAkB,CAAC;AAYvB,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAE3C,MAAM,iBAAiB,GAAG,KAAK,EAC9B,QAAc,EACd,GAAuB,EACP,EAAE;IAClB,IAAI,GAAG,IAAI,QAAQ,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;QACtC,MAAM,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAEF,KAAK,UAAU,WAAW,CAAC,OAAgB,EAAE,GAAY;IACxD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAQtC,IAAI,OAAO,GAAG,KAAK,CAAC;QAGpB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC7B,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,YAAY,EAAE,CAAC;gBAClB,OAAO,CAAC,YAAY,CAAC,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACP,MAAM,CACL,IAAI,KAAK,CACR,+BAA+B,oBAAoB,gCAAgC,CACnF,CACD,CAAC;YACH,CAAC;QACF,CAAC,EAAE,oBAAoB,CAAC,CAAC;QAIzB,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAKhB,MAAM,IAAI,GAAG,CAAC,QAAc,EAAQ,EAAE;YACrC,IAAI,OAAO,EAAE,CAAC;gBACb,OAAO;YACR,CAAC;YACD,OAAO,GAAG,IAAI,CAAC;YACf,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnB,CAAC,CAAC;QACF,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAQ,EAAE;YACzC,IAAI,OAAO,EAAE,CAAC;gBACb,OAAO;YACR,CAAC;YACD,OAAO,GAAG,IAAI,CAAC;YACf,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,KAAK,CAAC,CAAC;QACf,CAAC,CAAC;QAQF,IAAI,OAAO,EAAE,CAAC;YACb,MAAM,CAAC,kBAAkB,CAAC;iBACxB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE;gBACrC,IAAI,CAAC,YAAY,EAAE,CAAC;oBAGnB,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;gBACrC,CAAC;qBAAM,CAAC;oBAEP,IAAI,CAAC,YAAY,CAAC,CAAC;gBACpB,CAAC;YACF,CAAC,CAAC;iBACD,KAAK,CAAC,QAAQ,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACP,MAAM,CAAC,mBAAmB,CAAC;iBACzB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE;gBACrC,IAAI,CAAC,YAAY,EAAE,CAAC;oBAKnB,YAAY,GAAG,cAAc,CAAC,CAAC,QAAQ,EAAE,EAAE;wBAC1C,KAAK,iBAAiB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;oBAClE,CAAC,EAAE,GAAG,CAAC,CAAC;gBACT,CAAC;qBAAM,CAAC;oBAMP,KAAK,iBAAiB,CAAC,YAAY,EAAE,GAAG,CAAC;yBACvC,IAAI,CAAC,IAAI,CAAC;yBACV,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACnB,CAAC;YACF,CAAC,CAAC;iBACD,KAAK,CAAC,QAAQ,CAAC,CAAC;QACnB,CAAC;IACF,CAAC,CAAC,CAAC;AACJ,CAAC;AAID,eAAe,WAAW,CAAC"}
@@ -43,6 +43,7 @@
43
43
  "INVALID_BODY": "بيانات غير صالحة",
44
44
  "PARSE_ERROR": "خطأ في تحليل الطلب",
45
45
  "SPAM_EMAIL_RULE": "عنوان البريد الإلكتروني محظور بواسطة قواعد مكافحة البريد العشوائي",
46
+ "SPAM_EMAIL_COUNT_EXCEEDED": "كثرة الطلبات من عنوان البريد الإلكتروني هذا",
46
47
  "VPN_BLOCKED": "لا يُسمح بالطلبات من اتصالات VPN لهذا الموقع",
47
48
  "PROXY_BLOCKED": "لا يُسمح بالطلبات من خوادم البروكسي لهذا الموقع",
48
49
  "TOR_BLOCKED": "لا يُسمح بالطلبات من عقد خروج Tor لهذا الموقع",
@@ -43,6 +43,7 @@
43
43
  "INVALID_BODY": "Yanlış bədən",
44
44
  "PARSE_ERROR": "Tələbi pars edərkən səhv baş verdi",
45
45
  "SPAM_EMAIL_RULE": "E-poçt ünvanı spam filtr qaydaları ilə bloklanıb",
46
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Bu e-poçt ünvanından çox sayda göndəriş",
46
47
  "VPN_BLOCKED": "Bu sayt üçün VPN bağlantılarından sorğulara icazə verilmir",
47
48
  "PROXY_BLOCKED": "Bu sayt üçün proksi serverlərdən sorğulara icazə verilmir",
48
49
  "TOR_BLOCKED": "Bu sayt üçün Tor çıxış qovşaqlarından sorğulara icazə verilmir",
@@ -43,6 +43,7 @@
43
43
  "INVALID_BODY": "Neplatné tělo",
44
44
  "PARSE_ERROR": "Chyba při zpracování požadavku",
45
45
  "SPAM_EMAIL_RULE": "E-mailová adresa blokována pravidly spamového filtru",
46
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Příliš mnoho odeslání z této e-mailové adresy",
46
47
  "VPN_BLOCKED": "Požadavky z VPN připojení nejsou pro tento web povoleny",
47
48
  "PROXY_BLOCKED": "Požadavky z proxy serverů nejsou pro tento web povoleny",
48
49
  "TOR_BLOCKED": "Požadavky z výstupních uzlů Tor nejsou pro tento web povoleny",
@@ -43,6 +43,7 @@
43
43
  "INVALID_BODY": "Ungültiger Körper",
44
44
  "PARSE_ERROR": "Fehler beim Parsen der Anfrage",
45
45
  "SPAM_EMAIL_RULE": "E-Mail-Adresse durch Spamfilter-Regeln blockiert",
46
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Zu viele Einsendungen von dieser E-Mail-Adresse",
46
47
  "VPN_BLOCKED": "Anfragen über VPN-Verbindungen sind für diese Website nicht erlaubt",
47
48
  "PROXY_BLOCKED": "Anfragen über Proxy-Server sind für diese Website nicht erlaubt",
48
49
  "TOR_BLOCKED": "Anfragen über Tor-Exit-Knoten sind für diese Website nicht erlaubt",
@@ -30,6 +30,7 @@
30
30
  "INVALID_BODY": "Μη έγκυρο σώμα",
31
31
  "PARSE_ERROR": "Σφάλμα ανάλυσης αιτήματος",
32
32
  "SPAM_EMAIL_RULE": "Η διεύθυνση email αποκλείστηκε από κανόνες φίλτρου spam",
33
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Πάρα πολλές υποβολές από αυτή τη διεύθυνση email",
33
34
  "VPN_BLOCKED": "Αιτήματα από συνδέσεις VPN δεν επιτρέπονται για αυτόν τον ιστότοπο",
34
35
  "PROXY_BLOCKED": "Αιτήματα από διακομιστές proxy δεν επιτρέπονται για αυτόν τον ιστότοπο",
35
36
  "TOR_BLOCKED": "Αιτήματα από κόμβους εξόδου Tor δεν επιτρέπονται για αυτόν τον ιστότοπο",
@@ -120,6 +120,7 @@ var API = {
120
120
  "PROVIDER_VERIFY_FAILED": "Provider verification failed",
121
121
  "SPAM_EMAIL_DOMAIN": "Email domain not allowed",
122
122
  "SPAM_EMAIL_RULE": "Email address blocked by spam filter rules",
123
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Too many submissions from this email address",
123
124
  "VPN_BLOCKED": "Requests from VPN connections are not allowed for this site",
124
125
  "PROXY_BLOCKED": "Requests from proxy servers are not allowed for this site",
125
126
  "TOR_BLOCKED": "Requests from Tor exit nodes are not allowed for this site",
@@ -122,6 +122,7 @@
122
122
  "PROVIDER_VERIFY_FAILED": "Provider verification failed",
123
123
  "SPAM_EMAIL_DOMAIN": "Email domain not allowed",
124
124
  "SPAM_EMAIL_RULE": "Email address blocked by spam filter rules",
125
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Too many submissions from this email address",
125
126
  "VPN_BLOCKED": "Requests from VPN connections are not allowed for this site",
126
127
  "PROXY_BLOCKED": "Requests from proxy servers are not allowed for this site",
127
128
  "TOR_BLOCKED": "Requests from Tor exit nodes are not allowed for this site",
@@ -43,6 +43,7 @@
43
43
  "INVALID_BODY": "Cuerpo inválido",
44
44
  "PARSE_ERROR": "Error al analizar la respuesta",
45
45
  "SPAM_EMAIL_RULE": "Dirección de correo electrónico bloqueada por reglas de filtro de spam",
46
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Demasiados envíos desde esta dirección de correo electrónico",
46
47
  "VPN_BLOCKED": "Las solicitudes desde conexiones VPN no están permitidas para este sitio",
47
48
  "PROXY_BLOCKED": "Las solicitudes desde servidores proxy no están permitidas para este sitio",
48
49
  "TOR_BLOCKED": "Las solicitudes desde nodos de salida Tor no están permitidas para este sitio",
@@ -49,6 +49,7 @@
49
49
  "PROVIDER_VERIFY_FAILED": "Palveluntarjoajan tarkistus epäonnistui",
50
50
  "SPAM_EMAIL_DOMAIN": "Sähköpostiverkkotunnus ei ole sallittu",
51
51
  "SPAM_EMAIL_RULE": "Sähköpostiosoite estetty roskapostisuodattimen säännöillä",
52
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Liian monta lähetystä tästä sähköpostiosoitteesta",
52
53
  "VPN_BLOCKED": "VPN-yhteyksien pyynnöt eivät ole sallittuja tälle sivustolle",
53
54
  "PROXY_BLOCKED": "Välityspalvelimien pyynnöt eivät ole sallittuja tälle sivustolle",
54
55
  "TOR_BLOCKED": "Tor-poistumissolmujen pyynnöt eivät ole sallittuja tälle sivustolle",
@@ -43,6 +43,7 @@
43
43
  "INVALID_BODY": "Cuerpo inválido",
44
44
  "PARSE_ERROR": "Erreur d'analyse de la demande",
45
45
  "SPAM_EMAIL_RULE": "Adresse e-mail bloquée par les règles du filtre anti-spam",
46
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Trop de soumissions depuis cette adresse e-mail",
46
47
  "VPN_BLOCKED": "Les requêtes provenant de connexions VPN ne sont pas autorisées pour ce site",
47
48
  "PROXY_BLOCKED": "Les requêtes provenant de serveurs proxy ne sont pas autorisées pour ce site",
48
49
  "TOR_BLOCKED": "Les requêtes provenant de nœuds de sortie Tor ne sont pas autorisées pour ce site",
@@ -342,6 +342,7 @@
342
342
  "INVALID_BODY": "अमनय बड",
343
343
  "PARSE_ERROR": "अनरध वशषण म तरट",
344
344
  "SPAM_EMAIL_RULE": "स्पैम फ़िल्टर नियमों द्वारा ईमेल पता अवरुद्ध",
345
+ "SPAM_EMAIL_COUNT_EXCEEDED": "इस ईमेल पते से बहुत अधिक सबमिशन",
345
346
  "VPN_BLOCKED": "इस साइट के लिए VPN कनेक्शन से अनुरोध की अनुमति नहीं है",
346
347
  "PROXY_BLOCKED": "इस साइट के लिए प्रॉक्सी सर्वर से अनुरोध की अनुमति नहीं है",
347
348
  "TOR_BLOCKED": "इस साइट के लिए Tor एक्ज़िट नोड्स से अनुरोध की अनुमति नहीं है",
@@ -43,6 +43,7 @@
43
43
  "INVALID_BODY": "Érvénytelen test",
44
44
  "PARSE_ERROR": "Hiba az adatkérések elemzése közben",
45
45
  "SPAM_EMAIL_RULE": "Az e-mail cím a spamszűrő szabályai alapján blokkolva",
46
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Túl sok beküldés erről az e-mail címről",
46
47
  "VPN_BLOCKED": "VPN-kapcsolatokról érkező kérések nem engedélyezettek ezen az oldalon",
47
48
  "PROXY_BLOCKED": "Proxy szerverekről érkező kérések nem engedélyezettek ezen az oldalon",
48
49
  "TOR_BLOCKED": "Tor kilépési csomópontokról érkező kérések nem engedélyezettek ezen az oldalon",
@@ -43,6 +43,7 @@
43
43
  "INVALID_BODY": "Invalid body",
44
44
  "PARSE_ERROR": "Error parsing request",
45
45
  "SPAM_EMAIL_RULE": "Alamat email diblokir oleh aturan filter spam",
46
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Terlalu banyak pengiriman dari alamat email ini",
46
47
  "VPN_BLOCKED": "Permintaan dari koneksi VPN tidak diizinkan untuk situs ini",
47
48
  "PROXY_BLOCKED": "Permintaan dari server proxy tidak diizinkan untuk situs ini",
48
49
  "TOR_BLOCKED": "Permintaan dari node keluar Tor tidak diizinkan untuk situs ini",
@@ -43,6 +43,7 @@
43
43
  "INVALID_BODY": "Corpo non valido",
44
44
  "PARSE_ERROR": "Errore nell'analisi della richiesta",
45
45
  "SPAM_EMAIL_RULE": "Indirizzo email bloccato dalle regole del filtro antispam",
46
+ "SPAM_EMAIL_COUNT_EXCEEDED": "Troppi invii da questo indirizzo email",
46
47
  "VPN_BLOCKED": "Le richieste da connessioni VPN non sono consentite per questo sito",
47
48
  "PROXY_BLOCKED": "Le richieste da server proxy non sono consentite per questo sito",
48
49
  "TOR_BLOCKED": "Le richieste da nodi di uscita Tor non sono consentite per questo sito",