@prosopo/locale 3.9.0 → 3.10.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 (409) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +267 -14
  2. package/.turbo/turbo-build$colon$tsc.log +5 -5
  3. package/.turbo/turbo-build.log +266 -13
  4. package/CHANGELOG.md +43 -0
  5. package/README.md +203 -0
  6. package/dist/browserUiLanguages.d.ts +10 -0
  7. package/dist/browserUiLanguages.d.ts.map +1 -0
  8. package/dist/browserUiLanguages.js +768 -0
  9. package/dist/browserUiLanguages.js.map +1 -0
  10. package/dist/cjs/browserUiLanguages.cjs +768 -0
  11. package/dist/cjs/direction.cjs +30 -15
  12. package/dist/cjs/errorMessage.cjs +3 -2
  13. package/dist/cjs/i18SharedOptions.cjs +0 -1
  14. package/dist/cjs/i18nBackend.cjs +32 -20
  15. package/dist/cjs/i18nFrontend.cjs +23 -73
  16. package/dist/cjs/index.cjs +23 -2
  17. package/dist/cjs/languagePreference.cjs +142 -0
  18. package/dist/cjs/loadI18next.cjs +4 -4
  19. package/dist/cjs/locales/en/target.cjs +304 -0
  20. package/dist/cjs/locales/en/translation.cjs +1 -459
  21. package/dist/cjs/locales/en/widget.cjs +162 -0
  22. package/dist/cjs/requestLanguageDetector.cjs +24 -0
  23. package/dist/cjs/serverTranslationKeys.cjs +38 -0
  24. package/dist/cjs/translationKey.cjs +29 -7
  25. package/dist/cjs/translations.cjs +63 -2
  26. package/dist/cjs/translator.cjs +2 -1
  27. package/dist/direction.d.ts.map +1 -1
  28. package/dist/direction.js +30 -15
  29. package/dist/direction.js.map +1 -1
  30. package/dist/errorMessage.d.ts.map +1 -1
  31. package/dist/errorMessage.js +4 -3
  32. package/dist/errorMessage.js.map +1 -1
  33. package/dist/i18SharedOptions.d.ts +0 -1
  34. package/dist/i18SharedOptions.d.ts.map +1 -1
  35. package/dist/i18SharedOptions.js +0 -1
  36. package/dist/i18SharedOptions.js.map +1 -1
  37. package/dist/i18nBackend.d.ts +3 -1
  38. package/dist/i18nBackend.d.ts.map +1 -1
  39. package/dist/i18nBackend.js +32 -22
  40. package/dist/i18nBackend.js.map +1 -1
  41. package/dist/i18nFrontend.d.ts.map +1 -1
  42. package/dist/i18nFrontend.js +23 -73
  43. package/dist/i18nFrontend.js.map +1 -1
  44. package/dist/index.d.ts +8 -3
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +5 -2
  47. package/dist/index.js.map +1 -1
  48. package/dist/languagePreference.d.ts +17 -0
  49. package/dist/languagePreference.d.ts.map +1 -0
  50. package/dist/languagePreference.js +132 -0
  51. package/dist/languagePreference.js.map +1 -0
  52. package/dist/loadI18next.js +4 -4
  53. package/dist/locales/af/target.json +301 -0
  54. package/dist/locales/af/translation.json +71 -0
  55. package/dist/locales/af/widget.json +149 -0
  56. package/dist/locales/am/target.json +301 -0
  57. package/dist/locales/am/translation.json +71 -0
  58. package/dist/locales/am/widget.json +149 -0
  59. package/dist/locales/an/target.json +301 -0
  60. package/dist/locales/an/translation.json +71 -0
  61. package/dist/locales/an/widget.json +149 -0
  62. package/dist/locales/ar/target.json +301 -0
  63. package/dist/locales/ar/translation.json +0 -446
  64. package/dist/locales/ar/widget.json +149 -0
  65. package/dist/locales/as/target.json +301 -0
  66. package/dist/locales/as/translation.json +71 -0
  67. package/dist/locales/as/widget.json +149 -0
  68. package/dist/locales/ast/target.json +301 -0
  69. package/dist/locales/ast/translation.json +71 -0
  70. package/dist/locales/ast/widget.json +149 -0
  71. package/dist/locales/az/target.json +301 -0
  72. package/dist/locales/az/translation.json +0 -446
  73. package/dist/locales/az/widget.json +149 -0
  74. package/dist/locales/be/target.json +301 -0
  75. package/dist/locales/be/translation.json +71 -0
  76. package/dist/locales/be/widget.json +149 -0
  77. package/dist/locales/bg/target.json +301 -0
  78. package/dist/locales/bg/translation.json +71 -0
  79. package/dist/locales/bg/widget.json +149 -0
  80. package/dist/locales/bn/target.json +301 -0
  81. package/dist/locales/bn/translation.json +71 -0
  82. package/dist/locales/bn/widget.json +149 -0
  83. package/dist/locales/bs/target.json +301 -0
  84. package/dist/locales/bs/translation.json +71 -0
  85. package/dist/locales/bs/widget.json +149 -0
  86. package/dist/locales/ca/target.json +301 -0
  87. package/dist/locales/ca/translation.json +71 -0
  88. package/dist/locales/ca/widget.json +149 -0
  89. package/dist/locales/cs/target.json +301 -0
  90. package/dist/locales/cs/translation.json +0 -446
  91. package/dist/locales/cs/widget.json +149 -0
  92. package/dist/locales/cy/target.json +301 -0
  93. package/dist/locales/cy/translation.json +71 -0
  94. package/dist/locales/cy/widget.json +149 -0
  95. package/dist/locales/da/target.json +301 -0
  96. package/dist/locales/da/translation.json +71 -0
  97. package/dist/locales/da/widget.json +149 -0
  98. package/dist/locales/de/target.json +301 -0
  99. package/dist/locales/de/translation.json +0 -446
  100. package/dist/locales/de/widget.json +149 -0
  101. package/dist/locales/el/target.json +301 -0
  102. package/dist/locales/el/translation.json +0 -446
  103. package/dist/locales/el/widget.json +149 -0
  104. package/dist/locales/en/target.js +303 -0
  105. package/dist/locales/en/target.json +301 -0
  106. package/dist/locales/en/translation.js +2 -453
  107. package/dist/locales/en/translation.json +0 -446
  108. package/dist/locales/en/widget.js +156 -0
  109. package/dist/locales/en/widget.json +149 -0
  110. package/dist/locales/eo/target.json +301 -0
  111. package/dist/locales/eo/translation.json +71 -0
  112. package/dist/locales/eo/widget.json +149 -0
  113. package/dist/locales/es/target.json +301 -0
  114. package/dist/locales/es/translation.json +0 -446
  115. package/dist/locales/es/widget.json +149 -0
  116. package/dist/locales/et/target.json +301 -0
  117. package/dist/locales/et/translation.json +71 -0
  118. package/dist/locales/et/widget.json +149 -0
  119. package/dist/locales/eu/target.json +301 -0
  120. package/dist/locales/eu/translation.json +71 -0
  121. package/dist/locales/eu/widget.json +149 -0
  122. package/dist/locales/fa/target.json +301 -0
  123. package/dist/locales/fa/translation.json +71 -0
  124. package/dist/locales/fa/widget.json +149 -0
  125. package/dist/locales/fi/target.json +301 -0
  126. package/dist/locales/fi/translation.json +0 -446
  127. package/dist/locales/fi/widget.json +149 -0
  128. package/dist/locales/fil/target.json +301 -0
  129. package/dist/locales/fil/translation.json +71 -0
  130. package/dist/locales/fil/widget.json +149 -0
  131. package/dist/locales/fr/target.json +301 -0
  132. package/dist/locales/fr/translation.json +0 -446
  133. package/dist/locales/fr/widget.json +149 -0
  134. package/dist/locales/fy/target.json +301 -0
  135. package/dist/locales/fy/translation.json +71 -0
  136. package/dist/locales/fy/widget.json +149 -0
  137. package/dist/locales/ga/target.json +301 -0
  138. package/dist/locales/ga/translation.json +71 -0
  139. package/dist/locales/ga/widget.json +149 -0
  140. package/dist/locales/gd/target.json +301 -0
  141. package/dist/locales/gd/translation.json +71 -0
  142. package/dist/locales/gd/widget.json +149 -0
  143. package/dist/locales/gl/target.json +301 -0
  144. package/dist/locales/gl/translation.json +71 -0
  145. package/dist/locales/gl/widget.json +149 -0
  146. package/dist/locales/gu/target.json +301 -0
  147. package/dist/locales/gu/translation.json +71 -0
  148. package/dist/locales/gu/widget.json +149 -0
  149. package/dist/locales/he/target.json +301 -0
  150. package/dist/locales/he/translation.json +71 -0
  151. package/dist/locales/he/widget.json +149 -0
  152. package/dist/locales/hi/target.json +301 -0
  153. package/dist/locales/hi/translation.json +0 -446
  154. package/dist/locales/hi/widget.json +149 -0
  155. package/dist/locales/hr/target.json +301 -0
  156. package/dist/locales/hr/translation.json +71 -0
  157. package/dist/locales/hr/widget.json +149 -0
  158. package/dist/locales/hu/target.json +301 -0
  159. package/dist/locales/hu/translation.json +0 -446
  160. package/dist/locales/hu/widget.json +149 -0
  161. package/dist/locales/hy/target.json +301 -0
  162. package/dist/locales/hy/translation.json +71 -0
  163. package/dist/locales/hy/widget.json +149 -0
  164. package/dist/locales/ia/target.json +301 -0
  165. package/dist/locales/ia/translation.json +71 -0
  166. package/dist/locales/ia/widget.json +149 -0
  167. package/dist/locales/id/target.json +301 -0
  168. package/dist/locales/id/translation.json +10 -456
  169. package/dist/locales/id/widget.json +149 -0
  170. package/dist/locales/is/target.json +301 -0
  171. package/dist/locales/is/translation.json +71 -0
  172. package/dist/locales/is/widget.json +149 -0
  173. package/dist/locales/it/target.json +301 -0
  174. package/dist/locales/it/translation.json +0 -446
  175. package/dist/locales/it/widget.json +149 -0
  176. package/dist/locales/ja/target.json +301 -0
  177. package/dist/locales/ja/translation.json +0 -446
  178. package/dist/locales/ja/widget.json +149 -0
  179. package/dist/locales/jv/target.json +301 -0
  180. package/dist/locales/jv/translation.json +47 -493
  181. package/dist/locales/jv/widget.json +149 -0
  182. package/dist/locales/ka/target.json +301 -0
  183. package/dist/locales/ka/translation.json +71 -0
  184. package/dist/locales/ka/widget.json +149 -0
  185. package/dist/locales/kk/target.json +301 -0
  186. package/dist/locales/kk/translation.json +71 -0
  187. package/dist/locales/kk/widget.json +149 -0
  188. package/dist/locales/km/target.json +301 -0
  189. package/dist/locales/km/translation.json +71 -0
  190. package/dist/locales/km/widget.json +149 -0
  191. package/dist/locales/kn/target.json +301 -0
  192. package/dist/locales/kn/translation.json +71 -0
  193. package/dist/locales/kn/widget.json +149 -0
  194. package/dist/locales/ko/target.json +301 -0
  195. package/dist/locales/ko/translation.json +0 -446
  196. package/dist/locales/ko/widget.json +149 -0
  197. package/dist/locales/ky/target.json +301 -0
  198. package/dist/locales/ky/translation.json +71 -0
  199. package/dist/locales/ky/widget.json +149 -0
  200. package/dist/locales/lo/target.json +301 -0
  201. package/dist/locales/lo/translation.json +71 -0
  202. package/dist/locales/lo/widget.json +149 -0
  203. package/dist/locales/lt/target.json +301 -0
  204. package/dist/locales/lt/translation.json +71 -0
  205. package/dist/locales/lt/widget.json +149 -0
  206. package/dist/locales/lv/target.json +301 -0
  207. package/dist/locales/lv/translation.json +71 -0
  208. package/dist/locales/lv/widget.json +149 -0
  209. package/dist/locales/mk/target.json +301 -0
  210. package/dist/locales/mk/translation.json +71 -0
  211. package/dist/locales/mk/widget.json +149 -0
  212. package/dist/locales/ml/target.json +301 -0
  213. package/dist/locales/ml/translation.json +47 -493
  214. package/dist/locales/ml/widget.json +149 -0
  215. package/dist/locales/mn/target.json +301 -0
  216. package/dist/locales/mn/translation.json +71 -0
  217. package/dist/locales/mn/widget.json +149 -0
  218. package/dist/locales/mr/target.json +301 -0
  219. package/dist/locales/mr/translation.json +71 -0
  220. package/dist/locales/mr/widget.json +149 -0
  221. package/dist/locales/ms/target.json +301 -0
  222. package/dist/locales/ms/translation.json +47 -493
  223. package/dist/locales/ms/widget.json +149 -0
  224. package/dist/locales/my/target.json +301 -0
  225. package/dist/locales/my/translation.json +71 -0
  226. package/dist/locales/my/widget.json +149 -0
  227. package/dist/locales/ne/target.json +301 -0
  228. package/dist/locales/ne/translation.json +71 -0
  229. package/dist/locales/ne/widget.json +149 -0
  230. package/dist/locales/nl/target.json +301 -0
  231. package/dist/locales/nl/translation.json +0 -446
  232. package/dist/locales/nl/widget.json +149 -0
  233. package/dist/locales/nn/target.json +301 -0
  234. package/dist/locales/nn/translation.json +71 -0
  235. package/dist/locales/nn/widget.json +149 -0
  236. package/dist/locales/no/target.json +301 -0
  237. package/dist/locales/no/translation.json +1 -447
  238. package/dist/locales/no/widget.json +149 -0
  239. package/dist/locales/oc/target.json +301 -0
  240. package/dist/locales/oc/translation.json +71 -0
  241. package/dist/locales/oc/widget.json +149 -0
  242. package/dist/locales/or/target.json +301 -0
  243. package/dist/locales/or/translation.json +71 -0
  244. package/dist/locales/or/widget.json +149 -0
  245. package/dist/locales/pa/target.json +301 -0
  246. package/dist/locales/pa/translation.json +71 -0
  247. package/dist/locales/pa/widget.json +149 -0
  248. package/dist/locales/pl/target.json +301 -0
  249. package/dist/locales/pl/translation.json +0 -446
  250. package/dist/locales/pl/widget.json +149 -0
  251. package/dist/locales/pt/target.json +301 -0
  252. package/dist/locales/pt/translation.json +0 -446
  253. package/dist/locales/pt/widget.json +149 -0
  254. package/dist/locales/pt-BR/target.json +301 -0
  255. package/dist/locales/pt-BR/translation.json +0 -446
  256. package/dist/locales/pt-BR/widget.json +149 -0
  257. package/dist/locales/rm/target.json +301 -0
  258. package/dist/locales/rm/translation.json +71 -0
  259. package/dist/locales/rm/widget.json +149 -0
  260. package/dist/locales/ro/target.json +301 -0
  261. package/dist/locales/ro/translation.json +0 -446
  262. package/dist/locales/ro/widget.json +149 -0
  263. package/dist/locales/ru/target.json +301 -0
  264. package/dist/locales/ru/translation.json +0 -446
  265. package/dist/locales/ru/widget.json +149 -0
  266. package/dist/locales/sco/target.json +301 -0
  267. package/dist/locales/sco/translation.json +71 -0
  268. package/dist/locales/sco/widget.json +149 -0
  269. package/dist/locales/si/target.json +301 -0
  270. package/dist/locales/si/translation.json +71 -0
  271. package/dist/locales/si/widget.json +149 -0
  272. package/dist/locales/sk/target.json +301 -0
  273. package/dist/locales/sk/translation.json +71 -0
  274. package/dist/locales/sk/widget.json +149 -0
  275. package/dist/locales/sl/target.json +301 -0
  276. package/dist/locales/sl/translation.json +71 -0
  277. package/dist/locales/sl/widget.json +149 -0
  278. package/dist/locales/sq/target.json +301 -0
  279. package/dist/locales/sq/translation.json +71 -0
  280. package/dist/locales/sq/widget.json +149 -0
  281. package/dist/locales/sr/target.json +301 -0
  282. package/dist/locales/sr/translation.json +0 -446
  283. package/dist/locales/sr/widget.json +149 -0
  284. package/dist/locales/sv/target.json +301 -0
  285. package/dist/locales/sv/translation.json +0 -446
  286. package/dist/locales/sv/widget.json +149 -0
  287. package/dist/locales/sw/target.json +301 -0
  288. package/dist/locales/sw/translation.json +71 -0
  289. package/dist/locales/sw/widget.json +149 -0
  290. package/dist/locales/ta/target.json +301 -0
  291. package/dist/locales/ta/translation.json +71 -0
  292. package/dist/locales/ta/widget.json +149 -0
  293. package/dist/locales/te/target.json +301 -0
  294. package/dist/locales/te/translation.json +71 -0
  295. package/dist/locales/te/widget.json +149 -0
  296. package/dist/locales/tg/target.json +301 -0
  297. package/dist/locales/tg/translation.json +71 -0
  298. package/dist/locales/tg/widget.json +149 -0
  299. package/dist/locales/th/target.json +301 -0
  300. package/dist/locales/th/translation.json +0 -446
  301. package/dist/locales/th/widget.json +149 -0
  302. package/dist/locales/tr/target.json +301 -0
  303. package/dist/locales/tr/translation.json +6 -452
  304. package/dist/locales/tr/widget.json +149 -0
  305. package/dist/locales/uk/target.json +301 -0
  306. package/dist/locales/uk/translation.json +47 -493
  307. package/dist/locales/uk/widget.json +149 -0
  308. package/dist/locales/ur/target.json +301 -0
  309. package/dist/locales/ur/translation.json +71 -0
  310. package/dist/locales/ur/widget.json +149 -0
  311. package/dist/locales/uz/target.json +301 -0
  312. package/dist/locales/uz/translation.json +71 -0
  313. package/dist/locales/uz/widget.json +149 -0
  314. package/dist/locales/vi/target.json +301 -0
  315. package/dist/locales/vi/translation.json +0 -446
  316. package/dist/locales/vi/widget.json +149 -0
  317. package/dist/locales/xh/target.json +301 -0
  318. package/dist/locales/xh/translation.json +71 -0
  319. package/dist/locales/xh/widget.json +149 -0
  320. package/dist/locales/zh/target.json +301 -0
  321. package/dist/locales/zh/translation.json +71 -0
  322. package/dist/locales/zh/widget.json +149 -0
  323. package/dist/locales/zh-CN/target.json +301 -0
  324. package/dist/locales/zh-CN/translation.json +0 -446
  325. package/dist/locales/zh-CN/widget.json +149 -0
  326. package/dist/locales/zh-HK/target.json +301 -0
  327. package/dist/locales/zh-HK/translation.json +71 -0
  328. package/dist/locales/zh-HK/widget.json +149 -0
  329. package/dist/locales/zh-TW/target.json +301 -0
  330. package/dist/locales/zh-TW/translation.json +71 -0
  331. package/dist/locales/zh-TW/widget.json +149 -0
  332. package/dist/locales/zu/target.json +301 -0
  333. package/dist/locales/zu/translation.json +71 -0
  334. package/dist/locales/zu/widget.json +149 -0
  335. package/dist/requestLanguageDetector.d.ts +3 -0
  336. package/dist/requestLanguageDetector.d.ts.map +1 -0
  337. package/dist/requestLanguageDetector.js +24 -0
  338. package/dist/requestLanguageDetector.js.map +1 -0
  339. package/dist/serverTranslationKeys.d.ts +7 -0
  340. package/dist/serverTranslationKeys.d.ts.map +1 -0
  341. package/dist/serverTranslationKeys.js +34 -0
  342. package/dist/serverTranslationKeys.js.map +1 -0
  343. package/dist/tests/browserBundle.unit.test.d.ts +2 -0
  344. package/dist/tests/browserBundle.unit.test.d.ts.map +1 -0
  345. package/dist/tests/browserBundle.unit.test.js +26 -0
  346. package/dist/tests/browserBundle.unit.test.js.map +1 -0
  347. package/dist/tests/browserUiLanguages.unit.test.d.ts +2 -0
  348. package/dist/tests/browserUiLanguages.unit.test.d.ts.map +1 -0
  349. package/dist/tests/browserUiLanguages.unit.test.js +55 -0
  350. package/dist/tests/browserUiLanguages.unit.test.js.map +1 -0
  351. package/dist/tests/catalogues.test-d.d.ts +2 -0
  352. package/dist/tests/catalogues.test-d.d.ts.map +1 -0
  353. package/dist/tests/catalogues.test-d.js +766 -0
  354. package/dist/tests/catalogues.test-d.js.map +1 -0
  355. package/dist/tests/direction.unit.test.js +216 -5
  356. package/dist/tests/direction.unit.test.js.map +1 -1
  357. package/dist/tests/errorMessage.unit.test.js +9 -1
  358. package/dist/tests/errorMessage.unit.test.js.map +1 -1
  359. package/dist/tests/i18SharedOptions.unit.test.js +0 -4
  360. package/dist/tests/i18SharedOptions.unit.test.js.map +1 -1
  361. package/dist/tests/i18nBackend.unit.test.js +100 -21
  362. package/dist/tests/i18nBackend.unit.test.js.map +1 -1
  363. package/dist/tests/i18nBackendFiles.unit.test.d.ts +2 -0
  364. package/dist/tests/i18nBackendFiles.unit.test.d.ts.map +1 -0
  365. package/dist/tests/i18nBackendFiles.unit.test.js +22 -0
  366. package/dist/tests/i18nBackendFiles.unit.test.js.map +1 -0
  367. package/dist/tests/i18nFrontend.unit.test.js +90 -54
  368. package/dist/tests/i18nFrontend.unit.test.js.map +1 -1
  369. package/dist/tests/keptAsIs.d.ts +4 -0
  370. package/dist/tests/keptAsIs.d.ts.map +1 -0
  371. package/dist/tests/keptAsIs.js +1236 -0
  372. package/dist/tests/keptAsIs.js.map +1 -0
  373. package/dist/tests/languagePreference.unit.test.d.ts +2 -0
  374. package/dist/tests/languagePreference.unit.test.d.ts.map +1 -0
  375. package/dist/tests/languagePreference.unit.test.js +204 -0
  376. package/dist/tests/languagePreference.unit.test.js.map +1 -0
  377. package/dist/tests/locale.test-d.js +20 -1
  378. package/dist/tests/locale.test-d.js.map +1 -1
  379. package/dist/tests/localePlaceholders.unit.test.js +5 -2
  380. package/dist/tests/localePlaceholders.unit.test.js.map +1 -1
  381. package/dist/tests/locales.unit.test.js +136 -43
  382. package/dist/tests/locales.unit.test.js.map +1 -1
  383. package/dist/tests/requestLanguageDetector.unit.test.d.ts +2 -0
  384. package/dist/tests/requestLanguageDetector.unit.test.d.ts.map +1 -0
  385. package/dist/tests/requestLanguageDetector.unit.test.js +106 -0
  386. package/dist/tests/requestLanguageDetector.unit.test.js.map +1 -0
  387. package/dist/tests/thrownErrorKeys.unit.test.js +2 -10
  388. package/dist/tests/thrownErrorKeys.unit.test.js.map +1 -1
  389. package/dist/tests/translationKey.unit.test.js +110 -5
  390. package/dist/tests/translationKey.unit.test.js.map +1 -1
  391. package/dist/tests/translations.unit.test.js +9 -5
  392. package/dist/tests/translations.unit.test.js.map +1 -1
  393. package/dist/tests/translator.unit.test.js +8 -2
  394. package/dist/tests/translator.unit.test.js.map +1 -1
  395. package/dist/translationKey.d.ts +16 -4
  396. package/dist/translationKey.d.ts.map +1 -1
  397. package/dist/translationKey.js +27 -6
  398. package/dist/translationKey.js.map +1 -1
  399. package/dist/translations.d.ts +63 -2
  400. package/dist/translations.d.ts.map +1 -1
  401. package/dist/translations.js +63 -2
  402. package/dist/translations.js.map +1 -1
  403. package/dist/translator.d.ts +2 -2
  404. package/dist/translator.d.ts.map +1 -1
  405. package/dist/translator.js +2 -1
  406. package/dist/translator.js.map +1 -1
  407. package/dist/types.d.ts +2 -0
  408. package/dist/types.d.ts.map +1 -1
  409. package/package.json +13 -3
@@ -1,19 +1,34 @@
1
1
  //#region src/direction.ts
2
- var RTL_LANGUAGES = /* @__PURE__ */ new Set([
3
- "ar",
4
- "ckb",
5
- "dv",
6
- "fa",
7
- "he",
8
- "ps",
9
- "sd",
10
- "ug",
11
- "ur",
12
- "yi"
13
- ]);
14
- var getLanguageDirection = (language) => {
15
- const primary = language.split(/[-_]/)[0]?.toLowerCase() ?? "";
16
- return RTL_LANGUAGES.has(primary) ? "rtl" : "ltr";
2
+ var words = (list) => new Set(list.split(" "));
3
+ var RTL_SCRIPTS = words("adlm arab armi avst chrs cprt elym gara hatr hebr hung khar lydi mand mani mend merc mero narb nbat nkoo orkh ougr palm phli phlp phnx prti rohg samr sarb sidt sogd sogo syrc thaa yezi");
4
+ var RTL_LANGUAGES = words("aao abh abv acm acq acw acx adf ae aeb aec aee aeq afb aib aii aij aiq ajp ajt aju amw apc apd ar ara arb arc arq ars ary arz ask atn auj auz avd ave avl ayh ayl ayn ayp azb bal bcc bdz bej bft bgn bgp bhe bhm bhn bjf bjm bqi brh brk bsh bsk chg cja ckb cld clh czk dcc def deh dgl div dmk dml drw dv ecy esh fa fas fay faz fia fub gbz ggg gha ghr gig gjk gju glh glk grr gwc gwf gwt gzi hac haz hbo he heb hkh hnd hno hoh hrt hrz hss huy isk itk iw jad jat jbe jbn jdg ji jnd jog jpa jpr jrb jye kas kbu kby kcy kfm khw klj kmz kqd ks ktl kvx kxp kzh lad lah lhs lki lrc lrk lrl lsa lsd lss luv luz mby mde mey mfa mfi mhj mid mki mnj mve mvy myz mzb mzn nli nlm nqo ntz nyq oar obm odk oru ota otk oui pal pbt pbu per pes pgd phl phn phr phv plk pmu pnb prc prd prs prx ps psh psi pst pus qxq rdb rhg rmt sam sbn scl sd sdb sdf sdg sdh sds sgl sgr sgy shd shm shu shv siy siz skr smp smy snd sog sqo sqt srh srz ssh sts swb syc syn syr tjo tks tmr tnf tov tra trg trm trw ug uig ur urd ush uzs vaf vgr vmh wbk wlo wne wni wsv xco xhe xka xkc xkj xkp xld xly xmn xmr xna xpr xsa xsd xvi ydd ydg yhd yi yid yih yud zba zdj zrp zum");
5
+ var RTL_LANGUAGE_REGIONS = words("az-iq az-ir ha-cm ha-sd kk-af kk-cn kk-ir kk-mn ku-iq ku-ir ku-lb ky-cn ms-cc pa-pk tg-pk uz-af");
6
+ var isRtlByIntl = (tag) => {
7
+ try {
8
+ const locale = new Intl.Locale(tag);
9
+ return (typeof locale.getTextInfo === "function" ? locale.getTextInfo() : locale.textInfo)?.direction === "rtl";
10
+ } catch {
11
+ return false;
12
+ }
17
13
  };
14
+ var SCRIPT_SUBTAG = /^[a-z]{4}$/;
15
+ var REGION_SUBTAG = /^([a-z]{2}|[0-9]{3})$/;
16
+ var isRtlByList = (tag) => {
17
+ const [language = "", ...subtags] = tag.toLowerCase().split(/[-_]/);
18
+ const extensionStart = subtags.findIndex((subtag) => subtag.length === 1);
19
+ const own = extensionStart === -1 ? subtags : subtags.slice(0, extensionStart);
20
+ const script = own.find((subtag) => SCRIPT_SUBTAG.test(subtag));
21
+ if (script) return RTL_SCRIPTS.has(script);
22
+ const region = own.find((subtag) => REGION_SUBTAG.test(subtag));
23
+ return RTL_LANGUAGES.has(language) || region !== void 0 && RTL_LANGUAGE_REGIONS.has(`${language}-${region}`);
24
+ };
25
+ /**
26
+ * The direction a BCP 47 tag is written in. Right to left if our CLDR lists
27
+ * say so or the browser's Intl does: the lists give every browser the same
28
+ * answer for the languages they know, and Intl covers languages CLDR adds
29
+ * after them. An explicit script wins over the language and region (`pa-Arab`
30
+ * is rtl, `az-Latn-IR` ltr).
31
+ */
32
+ var getLanguageDirection = (language) => isRtlByList(language) || isRtlByIntl(language) ? "rtl" : "ltr";
18
33
  //#endregion
19
34
  exports.getLanguageDirection = getLanguageDirection;
@@ -4,11 +4,12 @@ const require_translationKey = require("./translationKey.cjs");
4
4
  * The provider translates error messages into the request's Accept-Language,
5
5
  * which is the browser's language rather than the widget's. Re-translating the
6
6
  * error key on the client shows the error in the language the widget renders
7
- * in. Free text and keys the catalogue doesn't have keep the server's message.
7
+ * in. Free text and keys outside the widget namespace (which the browser has no
8
+ * text for) keep the server's message.
8
9
  */
9
10
  var localiseErrorMessage = (i18n, error) => {
10
11
  const { key, message } = error;
11
- if (!key || !require_translationKey.isTranslationKey(key) || !i18n?.isInitialized) return message;
12
+ if (!key || !require_translationKey.isWidgetTranslationKey(key) || !i18n?.isInitialized) return message;
12
13
  return i18n.t(key, { defaultValue: message });
13
14
  };
14
15
  //#endregion
@@ -2,7 +2,6 @@ const require_translations = require("./translations.cjs");
2
2
  var i18nSharedOptions = {
3
3
  debug: require("./process.cjs").getProcess()?.env?.PROSOPO_LOG_LEVEL === "debug",
4
4
  fallbackLng: require_translations.Languages.english,
5
- namespace: "translation",
6
5
  supportedLngs: require_translations.LanguageCodes,
7
6
  nonExplicitSupportedLngs: false
8
7
  };
@@ -1,36 +1,48 @@
1
1
  const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
2
2
  const require_util = require("./util.cjs");
3
+ const require_translationKey = require("./translationKey.cjs");
3
4
  const require_i18SharedOptions = require("./i18SharedOptions.cjs");
5
+ const require_requestLanguageDetector = require("./requestLanguageDetector.cjs");
4
6
  let i18next = require("i18next");
5
7
  i18next = require_runtime.__toESM(i18next, 1);
6
- let i18next_http_middleware = require("i18next-http-middleware");
8
+ let node_fs = require("node:fs");
7
9
  let node_path = require("node:path");
8
10
  node_path = require_runtime.__toESM(node_path, 1);
11
+ let node_url = require("node:url");
9
12
  let i18next_fs_backend_cjs = require("i18next-fs-backend/cjs");
10
13
  i18next_fs_backend_cjs = require_runtime.__toESM(i18next_fs_backend_cjs, 1);
11
14
  //#region src/i18nBackend.ts
12
- var loadPath = `${node_path.default.dirname(require("url").pathToFileURL(__filename).href)}/locales/{{lng}}/{{ns}}.json`.replace("file://", "");
15
+ var localesDirectory = (moduleDirectory, exists = node_fs.existsSync) => {
16
+ const beside = node_path.default.join(moduleDirectory, "locales");
17
+ const above = node_path.default.join(moduleDirectory, "..", "locales");
18
+ const hasCatalogues = (directory) => exists(node_path.default.join(directory, "en", `${require_translationKey.NAMESPACES.server}.json`));
19
+ return !hasCatalogues(beside) && hasCatalogues(above) ? above : beside;
20
+ };
21
+ var loadPath = node_path.default.join(localesDirectory(node_path.default.dirname((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href))), "{{lng}}", "{{ns}}.json");
22
+ var isBackendClass = (value) => typeof value === "function" && "type" in value && value.type === "backend";
23
+ var fsBackend = (loaded = i18next_fs_backend_cjs.default) => {
24
+ if (!isBackendClass(loaded)) throw new Error("i18next-fs-backend/cjs did not export a backend class");
25
+ return loaded;
26
+ };
13
27
  function initializeI18n(i18nLoadedCallback) {
14
- if (!i18next.default.isInitialized && require_util.isServerSide()) {
15
- const lngDetector = new i18next_http_middleware.LanguageDetector(null, { order: [
16
- "header",
17
- "query",
18
- "cookie"
19
- ] });
20
- i18next.default.use(i18next_fs_backend_cjs.default).use(lngDetector).init({
21
- ...require_i18SharedOptions.i18nSharedOptions,
22
- ns: ["translation"],
23
- backend: { loadPath }
24
- });
25
- let notified = false;
26
- i18next.default.on("loaded", () => {
27
- if (notified) return;
28
- notified = true;
29
- i18nLoadedCallback?.(i18next.default);
30
- });
31
- } else i18nLoadedCallback?.(i18next.default);
28
+ if (!i18next.default.isInitialized && require_util.isServerSide()) i18next.default.use(fsBackend()).use(require_requestLanguageDetector.createRequestLanguageDetector()).init({
29
+ ...require_i18SharedOptions.i18nSharedOptions,
30
+ ns: [
31
+ require_translationKey.NAMESPACES.server,
32
+ require_translationKey.NAMESPACES.widget,
33
+ require_translationKey.NAMESPACES.target
34
+ ],
35
+ defaultNS: require_translationKey.NAMESPACES.server,
36
+ fallbackNS: [require_translationKey.NAMESPACES.widget, require_translationKey.NAMESPACES.target],
37
+ backend: { loadPath }
38
+ }, () => {
39
+ i18nLoadedCallback?.(i18next.default);
40
+ });
41
+ else i18nLoadedCallback?.(i18next.default);
32
42
  return i18next.default;
33
43
  }
34
44
  //#endregion
35
45
  exports.default = initializeI18n;
36
46
  exports.initializeI18n = initializeI18n;
47
+ exports.fsBackend = fsBackend;
48
+ exports.localesDirectory = localesDirectory;
@@ -1,11 +1,11 @@
1
+ const require_languagePreference = require("./languagePreference.cjs");
2
+ const require_widget = require("./locales/en/widget.cjs");
3
+ const require_translationKey = require("./translationKey.cjs");
1
4
  const require_i18SharedOptions = require("./i18SharedOptions.cjs");
2
5
  let _prosopo_util = require("@prosopo/util");
3
6
  //#region src/i18nFrontend.ts
4
- var NAMESPACE = "translation";
7
+ var NAMESPACE = require_translationKey.NAMESPACES.widget;
5
8
  var FALLBACK_LANGUAGE = require_i18SharedOptions.i18nSharedOptions.fallbackLng;
6
- var STORAGE_KEY = "i18nextLng";
7
- var COOKIE_KEY = "i18next";
8
- var COOKIE_MAX_AGE_SECONDS = 10080 * 60;
9
9
  /**
10
10
  * How long to wait for a catalogue before rendering untranslated.
11
11
  *
@@ -14,7 +14,12 @@ var COOKIE_MAX_AGE_SECONDS = 10080 * 60;
14
14
  * catalogue that never arrives degrades rather than blocks.
15
15
  */
16
16
  var CATALOGUE_FETCH_TIMEOUT_MS = 1e4;
17
- var SUPPORTED_LANGUAGES = require_i18SharedOptions.i18nSharedOptions.supportedLngs;
17
+ /**
18
+ * English ships inside the bundle: the key checks in translationKey.ts import
19
+ * it anyway, and it means the widget always has English text, for its own
20
+ * fallback and for logs and crash reports, without a second fetch.
21
+ */
22
+ var bundledEnglish = (0, _prosopo_util.flatten)(require_widget.default);
18
23
  /**
19
24
  * Locale JSON sits next to the bundle that asked for it. The widget is embedded
20
25
  * by third parties and cannot know a base URL, but it does know where its own
@@ -25,63 +30,11 @@ var catalogueUrl = (language) => {
25
30
  return `${moduleUrl.slice(0, moduleUrl.lastIndexOf("/"))}/locales/${language}/${NAMESPACE}.json`;
26
31
  };
27
32
  /**
28
- * `en-GB` is not in the catalogue list but `en` is, so a regional tag resolves
29
- * to its base language rather than falling all the way back to English.
30
- */
31
- var resolveLanguage = (candidate) => {
32
- if (!candidate) return;
33
- if (SUPPORTED_LANGUAGES.includes(candidate)) return candidate;
34
- const base = candidate.split("-")[0];
35
- return base && SUPPORTED_LANGUAGES.includes(base) ? base : void 0;
36
- };
37
- var readCookie = () => {
38
- try {
39
- const match = document.cookie.match(new RegExp(`(?:^|; )${COOKIE_KEY}=([^;]*)`));
40
- return match?.[1] ? decodeURIComponent(match[1]) : void 0;
41
- } catch {
42
- return;
43
- }
44
- };
45
- var readStorage = () => {
46
- try {
47
- return localStorage.getItem(STORAGE_KEY) ?? void 0;
48
- } catch {
49
- return;
50
- }
51
- };
52
- var navigatorLanguages = () => {
53
- try {
54
- return navigator.languages?.length ? navigator.languages : [navigator.language];
55
- } catch {
56
- return [];
57
- }
58
- };
59
- /**
60
- * Cookie and localStorage are both written, matching what the widget did when
61
- * i18next-browser-languagedetector handled this, so a visitor's choice survives
62
- * across pages that embed the widget. Either store can throw in a sandboxed
63
- * iframe or with third-party storage blocked; neither is load-bearing.
33
+ * Only the browser's own list. Nothing is read from or written to cookies or
34
+ * storage: the widget runs on other people's sites, where the i18next cookie
35
+ * and `i18nextLng` key may belong to the site's own i18n.
64
36
  */
65
- var cacheLanguage = (language) => {
66
- try {
67
- localStorage.setItem(STORAGE_KEY, language);
68
- } catch {}
69
- try {
70
- document.cookie = `${COOKIE_KEY}=${encodeURIComponent(language)};max-age=${COOKIE_MAX_AGE_SECONDS};path=/`;
71
- } catch {}
72
- };
73
- var detectLanguage = () => {
74
- const candidates = [
75
- readCookie(),
76
- readStorage(),
77
- ...navigatorLanguages()
78
- ];
79
- for (const candidate of candidates) {
80
- const resolved = resolveLanguage(candidate);
81
- if (resolved) return resolved;
82
- }
83
- return FALLBACK_LANGUAGE;
84
- };
37
+ var detectLanguage = () => require_languagePreference.matchLanguage(require_languagePreference.browserLanguages()) ?? FALLBACK_LANGUAGE;
85
38
  var fetchCatalogue = async (language) => {
86
39
  const controller = new AbortController();
87
40
  const timer = setTimeout(() => controller.abort(), CATALOGUE_FETCH_TIMEOUT_MS);
@@ -98,26 +51,23 @@ var fetchCatalogue = async (language) => {
98
51
  };
99
52
  var interpolate = (template, options) => options ? template.replace(/\{\{(\w+)\}\}/g, (placeholder, name) => name in options ? String(options[name]) : placeholder) : template;
100
53
  var createBrowserI18n = (requested) => {
101
- const catalogues = /* @__PURE__ */ new Map();
54
+ const catalogues = /* @__PURE__ */ new Map([[FALLBACK_LANGUAGE, bundledEnglish]]);
102
55
  const listeners = /* @__PURE__ */ new Map();
103
- let language = resolveLanguage(requested) ?? detectLanguage();
56
+ let language = require_languagePreference.resolveLanguageList(requested) ?? detectLanguage();
104
57
  let initialised = false;
105
58
  const emit = (event) => {
106
59
  for (const listener of listeners.get(event) ?? []) listener();
107
60
  };
108
61
  /**
109
- * The fallback catalogue is fetched alongside the active one so a key
110
- * missing from a translation still renders English rather than its key —
111
- * the same key-level fallback i18next gave us via `fallbackLng`.
62
+ * Only the active language's widget namespace is fetched. English is
63
+ * already loaded, so a key missing from a translation still renders
64
+ * English rather than its key, the key-level fallback i18next gives via
65
+ * `fallbackLng`.
112
66
  */
113
67
  const loadCatalogues = async (target) => {
114
- const wanted = [.../* @__PURE__ */ new Set([target, FALLBACK_LANGUAGE])].filter((candidate) => !catalogues.has(candidate));
115
- await Promise.all(wanted.map(async (candidate) => {
116
- catalogues.set(candidate, await fetchCatalogue(candidate));
117
- }));
68
+ if (!catalogues.has(target)) catalogues.set(target, await fetchCatalogue(target));
118
69
  };
119
70
  const lookup = (candidate, key) => catalogues.get(candidate)?.[key];
120
- cacheLanguage(language);
121
71
  const loading = loadCatalogues(language).then(() => {
122
72
  initialised = true;
123
73
  emit("initialized");
@@ -131,12 +81,12 @@ var createBrowserI18n = (requested) => {
131
81
  return initialised;
132
82
  },
133
83
  t: (key, options) => interpolate(lookup(language, key) ?? lookup(FALLBACK_LANGUAGE, key) ?? options?.defaultValue ?? key, options),
84
+ exists: (key) => lookup(language, key) !== void 0 || lookup(FALLBACK_LANGUAGE, key) !== void 0,
134
85
  hasLoadedNamespace: (namespace) => namespace === NAMESPACE && catalogues.has(language),
135
86
  changeLanguage: async (next) => {
136
- const resolved = resolveLanguage(next) ?? FALLBACK_LANGUAGE;
87
+ const resolved = require_languagePreference.resolveLanguageList(next) ?? FALLBACK_LANGUAGE;
137
88
  if (resolved !== language) {
138
89
  language = resolved;
139
- cacheLanguage(resolved);
140
90
  await loadCatalogues(resolved);
141
91
  emit("loaded");
142
92
  emit("languageChanged");
@@ -1,20 +1,41 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_browserUiLanguages = require("./browserUiLanguages.cjs");
2
3
  const require_direction = require("./direction.cjs");
3
4
  const require_loadI18next = require("./loadI18next.cjs");
4
5
  const require_i18nMiddleware = require("./i18nMiddleware.cjs");
5
6
  const require_translations = require("./translations.cjs");
7
+ const require_languagePreference = require("./languagePreference.cjs");
6
8
  const require_util = require("./util.cjs");
7
9
  const require_translationKey = require("./translationKey.cjs");
10
+ const require_serverTranslationKeys = require("./serverTranslationKeys.cjs");
8
11
  const require_translator = require("./translator.cjs");
9
12
  const require_errorMessage = require("./errorMessage.cjs");
13
+ exports.BROWSER_UI_LANGUAGES = require_browserUiLanguages.BROWSER_UI_LANGUAGES;
14
+ exports.LANGUAGE_HEADER = require_languagePreference.LANGUAGE_HEADER;
15
+ exports.LANGUAGE_QUERY_PARAM = require_languagePreference.LANGUAGE_QUERY_PARAM;
10
16
  exports.LanguageCodes = require_translations.LanguageCodes;
11
17
  exports.Languages = require_translations.Languages;
18
+ exports.NAMESPACES = require_translationKey.NAMESPACES;
19
+ exports.browserLanguages = require_languagePreference.browserLanguages;
20
+ exports.canTranslate = require_translationKey.canTranslate;
12
21
  exports.createTranslator = require_translator.createTranslator;
22
+ exports.englishText = require_serverTranslationKeys.englishText;
13
23
  exports.getLanguageDirection = require_direction.getLanguageDirection;
14
24
  exports.i18nMiddleware = require_i18nMiddleware.default;
15
25
  exports.isClientSide = require_util.isClientSide;
16
26
  exports.isLanguage = require_translations.isLanguage;
17
- exports.isTranslationKey = require_translationKey.isTranslationKey;
27
+ exports.isTargetKey = require_serverTranslationKeys.isTargetKey;
28
+ exports.isTranslationKey = require_serverTranslationKeys.isTranslationKey;
29
+ exports.isWidgetTranslationKey = require_translationKey.isWidgetTranslationKey;
30
+ exports.languageHeaders = require_languagePreference.languageHeaders;
18
31
  exports.loadI18next = require_loadI18next.default;
19
32
  exports.localiseErrorMessage = require_errorMessage.localiseErrorMessage;
20
- exports.translationKeys = require_translationKey.translationKeys;
33
+ exports.matchLanguage = require_languagePreference.matchLanguage;
34
+ exports.matchLanguageTag = require_languagePreference.matchLanguageTag;
35
+ exports.negotiateLanguage = require_languagePreference.negotiateLanguage;
36
+ exports.parseLanguageList = require_languagePreference.parseLanguageList;
37
+ exports.requestLanguage = require_languagePreference.requestLanguage;
38
+ exports.resolveLanguageList = require_languagePreference.resolveLanguageList;
39
+ exports.targetKeys = require_serverTranslationKeys.targetKeys;
40
+ exports.translationKeys = require_serverTranslationKeys.translationKeys;
41
+ exports.widgetLanguageHeaders = require_languagePreference.widgetLanguageHeaders;
@@ -0,0 +1,142 @@
1
+ const require_translations = require("./translations.cjs");
2
+ //#region src/languagePreference.ts
3
+ /** Our own header for the widget's language list, beside the browser's Accept-Language. */
4
+ var LANGUAGE_HEADER = "Prosopo-Lang";
5
+ /** Query parameter for clients that cannot set headers. Wins over both. */
6
+ var LANGUAGE_QUERY_PARAM = "lng";
7
+ var MAX_PREFERENCES = 10;
8
+ var LANGUAGE_TAG = /^[A-Za-z]{1,8}(?:-[A-Za-z0-9]{1,8})*$/;
9
+ /**
10
+ * Primary subtags we do not have a catalogue for but can serve from one we
11
+ * do: Norwegian Bokmål and Nynorsk read the `no` catalogue, and browsers
12
+ * still send the withdrawn codes for Indonesian and Javanese.
13
+ */
14
+ var ALIASES = {
15
+ nb: require_translations.Languages.norwegian,
16
+ in: require_translations.Languages.indonesian,
17
+ iw: require_translations.Languages.hebrew,
18
+ jw: require_translations.Languages.javanese,
19
+ tl: require_translations.Languages.filipino
20
+ };
21
+ var byLowerCase = new Map(Object.values(require_translations.Languages).map((code) => [code.toLowerCase(), code]));
22
+ /**
23
+ * A comma-separated list in Accept-Language form ("tr-TR, tr;q=0.9, en;q=0.8")
24
+ * as tags, most preferred first. Order is kept between equal weights,
25
+ * `q=0` and `*` entries are dropped, and anything malformed is skipped.
26
+ */
27
+ var parseLanguageList = (value) => {
28
+ if (!value) return [];
29
+ return value.split(",").map((entry, index) => {
30
+ const [tag = "", ...params] = entry.split(";").map((part) => part.trim());
31
+ const weight = params.find((param) => /^q=/i.test(param));
32
+ return {
33
+ tag,
34
+ q: weight === void 0 ? 1 : /^q=[0-9]+(?:\.[0-9]*)?$/i.test(weight) ? Number(weight.slice(2)) : NaN,
35
+ index
36
+ };
37
+ }).filter(({ tag, q }) => LANGUAGE_TAG.test(tag) && Number.isFinite(q) && q > 0 && q <= 1).sort((a, b) => b.q - a.q || a.index - b.index).map(({ tag }) => tag).slice(0, MAX_PREFERENCES);
38
+ };
39
+ var TRADITIONAL_CHINESE_SUBTAGS = /* @__PURE__ */ new Set([
40
+ "hant",
41
+ "tw",
42
+ "hk",
43
+ "mo"
44
+ ]);
45
+ var HONG_KONG_CHINESE_SUBTAGS = /* @__PURE__ */ new Set(["hk", "mo"]);
46
+ var isTraditionalChinese = (subtags) => subtags[0] === "zh" && !subtags.includes("hans") && subtags.some((subtag) => TRADITIONAL_CHINESE_SUBTAGS.has(subtag));
47
+ var traditionalChinese = (subtags) => subtags.some((subtag) => HONG_KONG_CHINESE_SUBTAGS.has(subtag)) ? require_translations.Languages.chineseHongKong : require_translations.Languages.chineseTaiwan;
48
+ /**
49
+ * The catalogue for one tag: the exact code, then the tag with its last subtag
50
+ * dropped, and so on (RFC 4647 lookup), so `zh-Hans-SG` reaches `zh` and
51
+ * `pt-BR` stays `pt-BR`. Traditional Chinese (`zh-Hant`, `zh-MO`) goes to
52
+ * `zh-TW` or `zh-HK`, never `zh`. Case is ignored. Aliases apply to the primary subtag.
53
+ */
54
+ var matchLanguageTag = (tag) => {
55
+ if (!LANGUAGE_TAG.test(tag)) return;
56
+ const subtags = tag.toLowerCase().split("-");
57
+ if (isTraditionalChinese(subtags)) return traditionalChinese(subtags);
58
+ for (let length = subtags.length; length >= 1; length--) {
59
+ const match = byLowerCase.get(subtags.slice(0, length).join("-"));
60
+ if (match) return match;
61
+ }
62
+ return subtags[0] === void 0 ? void 0 : ALIASES[subtags[0]];
63
+ };
64
+ /** The first preference we have a catalogue for, or undefined if none. */
65
+ var matchLanguage = (preferences) => {
66
+ for (const tag of preferences) {
67
+ const match = matchLanguageTag(tag);
68
+ if (match) return match;
69
+ }
70
+ };
71
+ /**
72
+ * A site-supplied list such as `data-language="xx, tr-TR"`: the first entry we
73
+ * have a catalogue for, or undefined if none.
74
+ */
75
+ var resolveLanguageList = (value) => matchLanguage(parseLanguageList(value ?? void 0));
76
+ /** Like matchLanguage, but falls back to English. */
77
+ var negotiateLanguage = (preferences) => matchLanguage(preferences) ?? require_translations.Languages.english;
78
+ /**
79
+ * The headers the widget sends with every provider request: Prosopo-Lang
80
+ * only. The browser's own Accept-Language is left as it is, because the
81
+ * provider's bot rules read it and a value set by script would hide the real
82
+ * one. Prosopo-Lang beats Accept-Language on the provider, so the site's
83
+ * data-language still wins.
84
+ */
85
+ var languageHeaders = (preferences) => {
86
+ const tags = preferences.filter((tag) => LANGUAGE_TAG.test(tag)).slice(0, MAX_PREFERENCES);
87
+ return tags.length === 0 ? {} : { [LANGUAGE_HEADER]: tags.join(",") };
88
+ };
89
+ /**
90
+ * navigator.languages, most preferred first. Empty outside a browser, and
91
+ * where navigator access throws (some sandboxed iframes).
92
+ */
93
+ var browserLanguages = () => {
94
+ try {
95
+ if (typeof navigator === "undefined") return [];
96
+ return navigator.languages?.length ? navigator.languages : [navigator.language];
97
+ } catch {
98
+ return [];
99
+ }
100
+ };
101
+ /**
102
+ * The language headers for the widget's provider requests: the site's choice
103
+ * when it made one (already resolved, so the provider cannot pick otherwise),
104
+ * else the browser's list, which the provider negotiates exactly as the
105
+ * widget did.
106
+ */
107
+ var widgetLanguageHeaders = (siteLanguage) => languageHeaders(siteLanguage ? [siteLanguage] : browserLanguages());
108
+ var firstString = (value) => {
109
+ if (typeof value === "string") return value;
110
+ if (Array.isArray(value) && typeof value[0] === "string") return value[0];
111
+ };
112
+ /**
113
+ * The provider's choice for one request: `?lng=` beats the Prosopo-Lang
114
+ * header, which beats Accept-Language. A source naming only languages we do
115
+ * not have is skipped, not taken as English, so the next one still counts.
116
+ * No cookie: the widget runs on other people's sites and must not set one.
117
+ */
118
+ var requestLanguage = (request) => {
119
+ const headers = request.headers ?? {};
120
+ const sources = [
121
+ firstString(request.query?.["lng"]),
122
+ firstString(headers[LANGUAGE_HEADER.toLowerCase()]),
123
+ firstString(headers["accept-language"])
124
+ ];
125
+ for (const source of sources) {
126
+ const match = matchLanguage(parseLanguageList(source));
127
+ if (match) return match;
128
+ }
129
+ return require_translations.Languages.english;
130
+ };
131
+ //#endregion
132
+ exports.LANGUAGE_HEADER = LANGUAGE_HEADER;
133
+ exports.LANGUAGE_QUERY_PARAM = LANGUAGE_QUERY_PARAM;
134
+ exports.browserLanguages = browserLanguages;
135
+ exports.languageHeaders = languageHeaders;
136
+ exports.matchLanguage = matchLanguage;
137
+ exports.matchLanguageTag = matchLanguageTag;
138
+ exports.negotiateLanguage = negotiateLanguage;
139
+ exports.parseLanguageList = parseLanguageList;
140
+ exports.requestLanguage = requestLanguage;
141
+ exports.resolveLanguageList = resolveLanguageList;
142
+ exports.widgetLanguageHeaders = widgetLanguageHeaders;
@@ -3,10 +3,10 @@ var i18nInstance;
3
3
  /**
4
4
  * How long to wait for i18next to report `loaded` before giving up on it.
5
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
6
+ * Resolution is driven by an event, and events are not guaranteed: a catalogue
7
+ * that never arrives (the widget's fetch against a dead CDN, the fs backend
8
+ * against a missing locales dir) leaves the listener armed and the promise
9
+ * pending for the lifetime of the process. `cli.ts` calls loadI18next(true).then(...) with
10
10
  * nothing to time it out, so a pending promise there is a silent boot hang with
11
11
  * no log line to explain it.
12
12
  */