@prosopo/locale 3.1.26 → 3.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build$colon$cjs.log +5 -5
- package/.turbo/turbo-build$colon$tsc.log +14 -0
- package/.turbo/turbo-build.log +9 -5
- package/.turbo/turbo-typecheck.log +1 -1
- package/CHANGELOG.md +81 -0
- package/dist/cjs/i18SharedOptions.cjs +2 -1
- package/dist/cjs/locales/en/translation.json.cjs +3 -3
- package/dist/i18SharedOptions.d.ts.map +1 -1
- package/dist/i18SharedOptions.js +2 -1
- package/dist/i18SharedOptions.js.map +1 -0
- package/dist/i18nBackend.js.map +1 -0
- package/dist/i18nFrontend.js.map +1 -0
- package/dist/i18nMiddleware.js.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/loadI18next.js.map +1 -0
- package/dist/locales/ar/translation.json +19 -3
- package/dist/locales/az/translation.json +19 -3
- package/dist/locales/cs/translation.json +19 -3
- package/dist/locales/de/translation.json +19 -3
- package/dist/locales/el/translation.json +19 -3
- package/dist/locales/en/translation.json +19 -3
- package/dist/locales/en/translation.json.js +3 -3
- package/dist/locales/es/translation.json +20 -4
- package/dist/locales/fi/translation.json +19 -3
- package/dist/locales/fr/translation.json +19 -3
- package/dist/locales/hi/translation.json +19 -3
- package/dist/locales/hu/translation.json +19 -3
- package/dist/locales/id/translation.json +19 -3
- package/dist/locales/it/translation.json +19 -3
- package/dist/locales/ja/translation.json +19 -3
- package/dist/locales/jv/translation.json +19 -3
- package/dist/locales/ko/translation.json +19 -3
- package/dist/locales/ml/translation.json +19 -3
- package/dist/locales/ms/translation.json +19 -3
- package/dist/locales/nl/translation.json +19 -3
- package/dist/locales/no/translation.json +19 -3
- package/dist/locales/pl/translation.json +19 -3
- package/dist/locales/pt/translation.json +19 -3
- package/dist/locales/pt-BR/translation.json +19 -3
- package/dist/locales/ro/translation.json +19 -3
- package/dist/locales/ru/translation.json +19 -3
- package/dist/locales/sr/translation.json +427 -411
- package/dist/locales/sv/translation.json +19 -3
- package/dist/locales/th/translation.json +19 -3
- package/dist/locales/tr/translation.json +19 -3
- package/dist/locales/uk/translation.json +19 -3
- package/dist/locales/vi/translation.json +19 -3
- package/dist/locales/zh-CN/translation.json +19 -3
- package/dist/tests/locales.unit.test.js +49 -0
- package/dist/tests/locales.unit.test.js.map +1 -0
- package/dist/translationKey.js.map +1 -0
- package/dist/translations.js.map +1 -0
- package/dist/useTranslation.js.map +1 -0
- package/dist/util.js.map +1 -0
- package/package.json +6 -4
- package/src/i18SharedOptions.ts +29 -0
- package/src/i18nBackend.ts +53 -0
- package/src/i18nFrontend.ts +81 -0
- package/src/i18nMiddleware.ts +25 -0
- package/src/index.ts +22 -0
- package/src/loadI18next.ts +49 -0
- package/src/locales/ar/translation.json +459 -0
- package/src/locales/az/translation.json +459 -0
- package/src/locales/cs/translation.json +459 -0
- package/src/locales/de/translation.json +459 -0
- package/src/locales/el/translation.json +459 -0
- package/src/locales/en/translation.json +459 -0
- package/src/locales/es/translation.json +459 -0
- package/src/locales/fi/translation.json +459 -0
- package/src/locales/fr/translation.json +459 -0
- package/src/locales/hi/translation.json +459 -0
- package/src/locales/hu/translation.json +459 -0
- package/src/locales/id/translation.json +459 -0
- package/src/locales/it/translation.json +459 -0
- package/src/locales/ja/translation.json +459 -0
- package/src/locales/jv/translation.json +459 -0
- package/src/locales/ko/translation.json +459 -0
- package/src/locales/ml/translation.json +459 -0
- package/src/locales/ms/translation.json +459 -0
- package/src/locales/nl/translation.json +459 -0
- package/src/locales/no/translation.json +459 -0
- package/src/locales/pl/translation.json +459 -0
- package/src/locales/pt/translation.json +459 -0
- package/src/locales/pt-BR/translation.json +459 -0
- package/src/locales/ro/translation.json +459 -0
- package/src/locales/ru/translation.json +459 -0
- package/src/locales/sr/translation.json +459 -0
- package/src/locales/sv/translation.json +459 -0
- package/src/locales/th/translation.json +459 -0
- package/src/locales/tr/translation.json +459 -0
- package/src/locales/uk/translation.json +459 -0
- package/src/locales/vi/translation.json +459 -0
- package/src/locales/zh-CN/translation.json +459 -0
- package/src/tests/locales.unit.test.ts +79 -0
- package/src/translationKey.ts +48 -0
- package/src/translations.ts +54 -0
- package/src/useTranslation.ts +32 -0
- package/src/util.ts +25 -0
- package/tsconfig.cjs.json +18 -0
- package/tsconfig.json +19 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/tsconfig.types.json +9 -0
- package/vite.cjs.config.ts +1 -1
- package/vite.esm.config.ts +1 -1
- package/vite.test.config.ts +1 -1
|
@@ -17,8 +17,11 @@
|
|
|
17
17
|
"MISSING_QUERY_PARAMETERS": "Saknade frågeparametrar",
|
|
18
18
|
"MISSING_AUTHORIZATION_HEADER": "Saknad auktoriseringsrubrik",
|
|
19
19
|
"TIMESTAMP_TOO_OLD": "Tidsstämpel för gammal",
|
|
20
|
+
"FAILED_IP_VALIDATION": "IP-validering misslyckades",
|
|
21
|
+
"ACCESS_POLICY_BLOCK": "Åtkomst blockerad av policy",
|
|
20
22
|
"FORBIDDEN": "Förbjuden",
|
|
21
23
|
"PROVIDER_VERIFY_FAILED": "Leverantörsverifiering misslyckades",
|
|
24
|
+
"SPAM_EMAIL_DOMAIN": "E-postdomänen är inte tillåten",
|
|
22
25
|
"UNAUTHORIZED": "Obehörig",
|
|
23
26
|
"MISSING_BODY": "Saknad kropp",
|
|
24
27
|
"NO_CONTENT_TYPE_HEADER": "Ingen innehållstypshuvud. Antogs JSON-kodad kropp men misslyckades med att tolka.",
|
|
@@ -38,7 +41,17 @@
|
|
|
38
41
|
"INVALID_IP": "Ogiltig IP",
|
|
39
42
|
"INVALID_URL": "Ogiltig URL",
|
|
40
43
|
"INVALID_BODY": "Ogiltig body",
|
|
41
|
-
"PARSE_ERROR": "Fel vid tolkning av förfrågan"
|
|
44
|
+
"PARSE_ERROR": "Fel vid tolkning av förfrågan",
|
|
45
|
+
"SPAM_EMAIL_RULE": "E-postadressen blockerad av spamfilterregler",
|
|
46
|
+
"VPN_BLOCKED": "Förfrågningar från VPN-anslutningar är inte tillåtna för denna webbplats",
|
|
47
|
+
"PROXY_BLOCKED": "Förfrågningar från proxyservrar är inte tillåtna för denna webbplats",
|
|
48
|
+
"TOR_BLOCKED": "Förfrågningar från Tor-utgångsnoder är inte tillåtna för denna webbplats",
|
|
49
|
+
"ABUSER_BLOCKED": "Förfrågningar från nätverk markerade för missbruk är inte tillåtna för denna webbplats",
|
|
50
|
+
"DATACENTER_BLOCKED": "Förfrågningar från datacenter-IP-adresser är inte tillåtna för denna webbplats",
|
|
51
|
+
"MOBILE_BLOCKED": "Förfrågningar från mobilnätverksanslutningar är inte tillåtna för denna webbplats",
|
|
52
|
+
"SATELLITE_BLOCKED": "Förfrågningar från satellitanslutningar är inte tillåtna för denna webbplats",
|
|
53
|
+
"CRAWLER_BLOCKED": "Förfrågningar från kända crawlers är inte tillåtna för denna webbplats",
|
|
54
|
+
"DISALLOWED_WEBVIEW": "Förfrågningar från inbäddade webbläsare (WebView) är inte tillåtna för denna webbplats"
|
|
42
55
|
},
|
|
43
56
|
"PORTAL": {
|
|
44
57
|
"CANNOT_MODIFY_OWNER_USER": "Kan inte ändra ägare användare",
|
|
@@ -46,7 +59,9 @@
|
|
|
46
59
|
"CANNOT_DELETE_LAST_USER": "Kan inte ta bort sista användaren",
|
|
47
60
|
"USER_ALREADY_EXISTS": "Användaren finns redan",
|
|
48
61
|
"NO_SUGGESTIONS_FOUND": "Inga förslag hittades",
|
|
49
|
-
"CANNOT_DEACTIVATE_LAST_SITE": "Kan inte inaktivera den sista aktiva platsen"
|
|
62
|
+
"CANNOT_DEACTIVATE_LAST_SITE": "Kan inte inaktivera den sista aktiva platsen",
|
|
63
|
+
"DUPLICATE_SITE_NAME": "En webbplats med detta namn finns redan",
|
|
64
|
+
"INVALID_SITE_NAME": "Webbplatsnamnet får bara innehålla bokstäver, siffror, bindestreck och understreck"
|
|
50
65
|
},
|
|
51
66
|
"TARGET": {
|
|
52
67
|
"airplanes": "flygplan",
|
|
@@ -359,7 +374,8 @@
|
|
|
359
374
|
"I_AM_HUMAN": "Jag är en människa",
|
|
360
375
|
"NO_ACCOUNTS_FOUND": "Inga konton hittades",
|
|
361
376
|
"ACCOUNT_NOT_FOUND": "Konto hittades inte",
|
|
362
|
-
"NO_EXTENSION_FOUND": "Ingen förlängning hittades"
|
|
377
|
+
"NO_EXTENSION_FOUND": "Ingen förlängning hittades",
|
|
378
|
+
"INSECURE_CONTEXT": "Procaptcha kräver en säker (HTTPS) anslutning"
|
|
363
379
|
},
|
|
364
380
|
"CONTRACT": {
|
|
365
381
|
"INVALID_ADDRESS": "Misslyckades att koda ogiltig adress",
|
|
@@ -17,8 +17,11 @@
|
|
|
17
17
|
"MISSING_QUERY_PARAMETERS": "ขาดพารามิเตอร์การค้นหา",
|
|
18
18
|
"MISSING_AUTHORIZATION_HEADER": "หัวข้อการอนุญาตขาดหาย",
|
|
19
19
|
"TIMESTAMP_TOO_OLD": "ประทับเวลาเก่าเกินไป",
|
|
20
|
+
"FAILED_IP_VALIDATION": "การตรวจสอบ IP ล้มเหลว",
|
|
21
|
+
"ACCESS_POLICY_BLOCK": "การเข้าถึงถูกบล็อกโดยนโยบาย",
|
|
20
22
|
"FORBIDDEN": "ห้าม",
|
|
21
23
|
"PROVIDER_VERIFY_FAILED": "การตรวจสอบผู้ให้บริการล้มเหลว",
|
|
24
|
+
"SPAM_EMAIL_DOMAIN": "โดเมนอีเมลไม่ได้รับอนุญาต",
|
|
22
25
|
"UNAUTHORIZED": "Unauthorized",
|
|
23
26
|
"MISSING_BODY": "Missing body",
|
|
24
27
|
"NO_CONTENT_TYPE_HEADER": "No content-type header. Assumed JSON encoded body but failed to parse.",
|
|
@@ -38,7 +41,17 @@
|
|
|
38
41
|
"INVALID_IP": "IP ไม่ถูกต้อง",
|
|
39
42
|
"INVALID_URL": "URL ไม่ถูกต้อง",
|
|
40
43
|
"INVALID_BODY": "ข้อมูลไม่ถูกต้อง",
|
|
41
|
-
"PARSE_ERROR": "ข้อผิดพลาดในการแปลคำขอ"
|
|
44
|
+
"PARSE_ERROR": "ข้อผิดพลาดในการแปลคำขอ",
|
|
45
|
+
"SPAM_EMAIL_RULE": "ที่อยู่อีเมลถูกบล็อกโดยกฎตัวกรองสแปม",
|
|
46
|
+
"VPN_BLOCKED": "คำขอจากการเชื่อมต่อ VPN ไม่ได้รับอนุญาตสำหรับเว็บไซต์นี้",
|
|
47
|
+
"PROXY_BLOCKED": "คำขอจากเซิร์ฟเวอร์พร็อกซีไม่ได้รับอนุญาตสำหรับเว็บไซต์นี้",
|
|
48
|
+
"TOR_BLOCKED": "คำขอจากโหนดทางออก Tor ไม่ได้รับอนุญาตสำหรับเว็บไซต์นี้",
|
|
49
|
+
"ABUSER_BLOCKED": "คำขอจากเครือข่ายที่ถูกระบุว่ามีการใช้งานในทางที่ผิดไม่ได้รับอนุญาตสำหรับเว็บไซต์นี้",
|
|
50
|
+
"DATACENTER_BLOCKED": "คำขอจากที่อยู่ IP ของศูนย์ข้อมูลไม่ได้รับอนุญาตสำหรับเว็บไซต์นี้",
|
|
51
|
+
"MOBILE_BLOCKED": "คำขอจากการเชื่อมต่อเครือข่ายมือถือไม่ได้รับอนุญาตสำหรับเว็บไซต์นี้",
|
|
52
|
+
"SATELLITE_BLOCKED": "คำขอจากการเชื่อมต่อดาวเทียมไม่ได้รับอนุญาตสำหรับเว็บไซต์นี้",
|
|
53
|
+
"CRAWLER_BLOCKED": "คำขอจากโปรแกรมรวบรวมข้อมูลที่รู้จักไม่ได้รับอนุญาตสำหรับเว็บไซต์นี้",
|
|
54
|
+
"DISALLOWED_WEBVIEW": "ไม่อนุญาตให้ส่งคำขอจากเบราว์เซอร์ในแอป (WebView) สำหรับเว็บไซต์นี้"
|
|
42
55
|
},
|
|
43
56
|
"PORTAL": {
|
|
44
57
|
"CANNOT_MODIFY_OWNER_USER": "ไม่สามารถแก้ไขผู้ใช้เจ้าของ",
|
|
@@ -46,7 +59,9 @@
|
|
|
46
59
|
"CANNOT_DELETE_LAST_USER": "ไม่สามารถลบผู้ใช้สุดท้าย",
|
|
47
60
|
"USER_ALREADY_EXISTS": "ผู้ใช้มีอยู่แล้ว",
|
|
48
61
|
"NO_SUGGESTIONS_FOUND": "ไม่พบข้อเสนอ",
|
|
49
|
-
"CANNOT_DEACTIVATE_LAST_SITE": "ไม่สามารถปิดใช้งานเว็บไซต์ที่ใช้งานอยู่ครั้งสุดท้าย"
|
|
62
|
+
"CANNOT_DEACTIVATE_LAST_SITE": "ไม่สามารถปิดใช้งานเว็บไซต์ที่ใช้งานอยู่ครั้งสุดท้าย",
|
|
63
|
+
"DUPLICATE_SITE_NAME": "มีไซต์ที่ใช้ชื่อนี้อยู่แล้ว",
|
|
64
|
+
"INVALID_SITE_NAME": "ชื่อไซต์ต้องประกอบด้วยตัวอักษร ตัวเลข ขีดกลาง และขีดล่างเท่านั้น"
|
|
50
65
|
},
|
|
51
66
|
"TARGET": {
|
|
52
67
|
"airplanes": "เครื่องบิน",
|
|
@@ -359,7 +374,8 @@
|
|
|
359
374
|
"I_AM_HUMAN": "ฉันเป็นมนุษย์",
|
|
360
375
|
"NO_ACCOUNTS_FOUND": "ไม่พบบัญชี",
|
|
361
376
|
"ACCOUNT_NOT_FOUND": "ไม่พบบัญชี",
|
|
362
|
-
"NO_EXTENSION_FOUND": "ไม่พบส่วนขยาย"
|
|
377
|
+
"NO_EXTENSION_FOUND": "ไม่พบส่วนขยาย",
|
|
378
|
+
"INSECURE_CONTEXT": "Procaptcha ต้องใช้การเชื่อมต่อที่ปลอดภัย (HTTPS)"
|
|
363
379
|
},
|
|
364
380
|
"CONTRACT": {
|
|
365
381
|
"INVALID_ADDRESS": "ล้มเหลวในการเข้ารหัสที่อยู่ไม่ถูกต้อง",
|
|
@@ -17,8 +17,11 @@
|
|
|
17
17
|
"MISSING_QUERY_PARAMETERS": "Missing query parameters",
|
|
18
18
|
"MISSING_AUTHORIZATION_HEADER": "Missing authorization header",
|
|
19
19
|
"TIMESTAMP_TOO_OLD": "Timestamp too old",
|
|
20
|
+
"FAILED_IP_VALIDATION": "IP doğrulaması başarısız oldu",
|
|
21
|
+
"ACCESS_POLICY_BLOCK": "Erişim politika tarafından engellendi",
|
|
20
22
|
"FORBIDDEN": "Forbidden",
|
|
21
23
|
"PROVIDER_VERIFY_FAILED": "Provider verification failed",
|
|
24
|
+
"SPAM_EMAIL_DOMAIN": "E-posta alan adına izin verilmiyor",
|
|
22
25
|
"UNAUTHORIZED": "Yetkisiz",
|
|
23
26
|
"MISSING_BODY": "Eksik gövde",
|
|
24
27
|
"NO_CONTENT_TYPE_HEADER": "İçerik tipi başlığı yok. JSON kodlu gövde varsayılmış ancak ayrıştırılamadı.",
|
|
@@ -38,7 +41,17 @@
|
|
|
38
41
|
"INVALID_IP": "Geçersiz IP",
|
|
39
42
|
"INVALID_URL": "Geçersiz URL",
|
|
40
43
|
"INVALID_BODY": "Geçersiz gövde",
|
|
41
|
-
"PARSE_ERROR": "İstek ayrıştırma hatası"
|
|
44
|
+
"PARSE_ERROR": "İstek ayrıştırma hatası",
|
|
45
|
+
"SPAM_EMAIL_RULE": "E-posta adresi spam filtresi kuralları tarafından engellendi",
|
|
46
|
+
"VPN_BLOCKED": "Bu site için VPN bağlantılarından gelen isteklere izin verilmiyor",
|
|
47
|
+
"PROXY_BLOCKED": "Bu site için proxy sunucularından gelen isteklere izin verilmiyor",
|
|
48
|
+
"TOR_BLOCKED": "Bu site için Tor çıkış düğümlerinden gelen isteklere izin verilmiyor",
|
|
49
|
+
"ABUSER_BLOCKED": "Bu site için kötüye kullanım olarak işaretlenen ağlardan gelen isteklere izin verilmiyor",
|
|
50
|
+
"DATACENTER_BLOCKED": "Bu site için veri merkezi IP adreslerinden gelen isteklere izin verilmiyor",
|
|
51
|
+
"MOBILE_BLOCKED": "Bu site için mobil ağ bağlantılarından gelen isteklere izin verilmiyor",
|
|
52
|
+
"SATELLITE_BLOCKED": "Bu site için uydu bağlantılarından gelen isteklere izin verilmiyor",
|
|
53
|
+
"CRAWLER_BLOCKED": "Bu site için bilinen tarayıcılardan gelen isteklere izin verilmiyor",
|
|
54
|
+
"DISALLOWED_WEBVIEW": "Bu site için uygulama içi tarayıcılardan (WebView) gelen isteklere izin verilmiyor"
|
|
42
55
|
},
|
|
43
56
|
"PORTAL": {
|
|
44
57
|
"CANNOT_MODIFY_OWNER_USER": "Cannot modify owner user",
|
|
@@ -46,7 +59,9 @@
|
|
|
46
59
|
"CANNOT_DELETE_LAST_USER": "Cannot delete last user",
|
|
47
60
|
"USER_ALREADY_EXISTS": "User already exists",
|
|
48
61
|
"NO_SUGGESTIONS_FOUND": "No suggestions found",
|
|
49
|
-
"CANNOT_DEACTIVATE_LAST_SITE": "Cannot deactivate the last active site"
|
|
62
|
+
"CANNOT_DEACTIVATE_LAST_SITE": "Cannot deactivate the last active site",
|
|
63
|
+
"DUPLICATE_SITE_NAME": "Bu ada sahip bir site zaten mevcut",
|
|
64
|
+
"INVALID_SITE_NAME": "Site adı yalnızca harf, rakam, tire ve alt çizgi içermelidir"
|
|
50
65
|
},
|
|
51
66
|
"TARGET": {
|
|
52
67
|
"airplanes": "uçaklar",
|
|
@@ -359,7 +374,8 @@
|
|
|
359
374
|
"I_AM_HUMAN": "Ben bir insanım",
|
|
360
375
|
"NO_ACCOUNTS_FOUND": "Hesap bulunamadı",
|
|
361
376
|
"ACCOUNT_NOT_FOUND": "Hesap bulunamadı",
|
|
362
|
-
"NO_EXTENSION_FOUND": "Eklenti bulunamadı"
|
|
377
|
+
"NO_EXTENSION_FOUND": "Eklenti bulunamadı",
|
|
378
|
+
"INSECURE_CONTEXT": "Procaptcha güvenli bir (HTTPS) bağlantı gerektirir"
|
|
363
379
|
},
|
|
364
380
|
"CONTRACT": {
|
|
365
381
|
"INVALID_ADDRESS": "Geçersiz adresi kodlama başarısız oldu",
|
|
@@ -17,8 +17,11 @@
|
|
|
17
17
|
"MISSING_QUERY_PARAMETERS": "Missing query parameters",
|
|
18
18
|
"MISSING_AUTHORIZATION_HEADER": "Missing authorization header",
|
|
19
19
|
"TIMESTAMP_TOO_OLD": "Timestamp too old",
|
|
20
|
+
"FAILED_IP_VALIDATION": "Перевірка IP не вдалася",
|
|
21
|
+
"ACCESS_POLICY_BLOCK": "Доступ заблоковано політикою",
|
|
20
22
|
"FORBIDDEN": "Forbidden",
|
|
21
23
|
"PROVIDER_VERIFY_FAILED": "Provider verification failed",
|
|
24
|
+
"SPAM_EMAIL_DOMAIN": "Домен електронної пошти не дозволено",
|
|
22
25
|
"UNAUTHORIZED": "Unauthorised",
|
|
23
26
|
"MISSING_BODY": "Missing body",
|
|
24
27
|
"NO_CONTENT_TYPE_HEADER": "No content-type header. Assumed JSON encoded body but failed to parse.",
|
|
@@ -38,7 +41,17 @@
|
|
|
38
41
|
"INVALID_IP": "Invalid IP",
|
|
39
42
|
"INVALID_URL": "Invalid URL",
|
|
40
43
|
"INVALID_BODY": "Invalid body",
|
|
41
|
-
"PARSE_ERROR": "Error parsing request"
|
|
44
|
+
"PARSE_ERROR": "Error parsing request",
|
|
45
|
+
"SPAM_EMAIL_RULE": "Адресу електронної пошти заблоковано правилами спам-фільтра",
|
|
46
|
+
"VPN_BLOCKED": "Запити з VPN-з'єднань не дозволені для цього сайту",
|
|
47
|
+
"PROXY_BLOCKED": "Запити з проксі-серверів не дозволені для цього сайту",
|
|
48
|
+
"TOR_BLOCKED": "Запити з вихідних вузлів Tor не дозволені для цього сайту",
|
|
49
|
+
"ABUSER_BLOCKED": "Запити з мереж, позначених за зловживання, не дозволені для цього сайту",
|
|
50
|
+
"DATACENTER_BLOCKED": "Запити з IP-адрес дата-центрів не дозволені для цього сайту",
|
|
51
|
+
"MOBILE_BLOCKED": "Запити з мобільних мережевих з'єднань не дозволені для цього сайту",
|
|
52
|
+
"SATELLITE_BLOCKED": "Запити із супутникових з'єднань не дозволені для цього сайту",
|
|
53
|
+
"CRAWLER_BLOCKED": "Запити від відомих пошукових роботів не дозволені для цього сайту",
|
|
54
|
+
"DISALLOWED_WEBVIEW": "Запити з вбудованих браузерів (WebView) не дозволені для цього сайту"
|
|
42
55
|
},
|
|
43
56
|
"PORTAL": {
|
|
44
57
|
"CANNOT_MODIFY_OWNER_USER": "Cannot modify owner user",
|
|
@@ -46,7 +59,9 @@
|
|
|
46
59
|
"CANNOT_DELETE_LAST_USER": "Cannot delete last user",
|
|
47
60
|
"USER_ALREADY_EXISTS": "User already exists",
|
|
48
61
|
"NO_SUGGESTIONS_FOUND": "No suggestions found",
|
|
49
|
-
"CANNOT_DEACTIVATE_LAST_SITE": "Cannot deactivate the last active site"
|
|
62
|
+
"CANNOT_DEACTIVATE_LAST_SITE": "Cannot deactivate the last active site",
|
|
63
|
+
"DUPLICATE_SITE_NAME": "Сайт із такою назвою вже існує",
|
|
64
|
+
"INVALID_SITE_NAME": "Назва сайту повинна містити лише літери, цифри, дефіси та символи підкреслення"
|
|
50
65
|
},
|
|
51
66
|
"TARGET": {
|
|
52
67
|
"airplanes": "aeroplanes",
|
|
@@ -359,7 +374,8 @@
|
|
|
359
374
|
"I_AM_HUMAN": "I am human",
|
|
360
375
|
"NO_ACCOUNTS_FOUND": "No accounts found",
|
|
361
376
|
"ACCOUNT_NOT_FOUND": "Account not found",
|
|
362
|
-
"NO_EXTENSION_FOUND": "No extension found"
|
|
377
|
+
"NO_EXTENSION_FOUND": "No extension found",
|
|
378
|
+
"INSECURE_CONTEXT": "Procaptcha потребує безпечного з'єднання (HTTPS)"
|
|
363
379
|
},
|
|
364
380
|
"CONTRACT": {
|
|
365
381
|
"INVALID_ADDRESS": "Failed to encode invalid address",
|
|
@@ -17,8 +17,11 @@
|
|
|
17
17
|
"MISSING_QUERY_PARAMETERS": "Thiếu tham số truy vấn",
|
|
18
18
|
"MISSING_AUTHORIZATION_HEADER": "Thiếu tiêu đề ủy quyền",
|
|
19
19
|
"TIMESTAMP_TOO_OLD": "Mốc thời gian quá cũ",
|
|
20
|
+
"FAILED_IP_VALIDATION": "Xác thực IP thất bại",
|
|
21
|
+
"ACCESS_POLICY_BLOCK": "Truy cập bị chặn bởi chính sách",
|
|
20
22
|
"FORBIDDEN": "Bị cấm",
|
|
21
23
|
"PROVIDER_VERIFY_FAILED": "Xác thực nhà cung cấp không thành công",
|
|
24
|
+
"SPAM_EMAIL_DOMAIN": "Tên miền email không được phép",
|
|
22
25
|
"UNAUTHORIZED": "Không được phép",
|
|
23
26
|
"MISSING_BODY": "Thiếu nội dung",
|
|
24
27
|
"NO_CONTENT_TYPE_HEADER": "Không có tiêu đề content-type. Giả định nội dung được mã hóa JSON nhưng không thể phân tích.",
|
|
@@ -38,7 +41,17 @@
|
|
|
38
41
|
"INVALID_IP": "IP không hợp lệ",
|
|
39
42
|
"INVALID_URL": "URL không hợp lệ",
|
|
40
43
|
"INVALID_BODY": "Nội dung không hợp lệ",
|
|
41
|
-
"PARSE_ERROR": "Lỗi phân tích yêu cầu"
|
|
44
|
+
"PARSE_ERROR": "Lỗi phân tích yêu cầu",
|
|
45
|
+
"SPAM_EMAIL_RULE": "Địa chỉ email bị chặn bởi quy tắc bộ lọc spam",
|
|
46
|
+
"VPN_BLOCKED": "Các yêu cầu từ kết nối VPN không được phép cho trang web này",
|
|
47
|
+
"PROXY_BLOCKED": "Các yêu cầu từ máy chủ proxy không được phép cho trang web này",
|
|
48
|
+
"TOR_BLOCKED": "Các yêu cầu từ nút thoát Tor không được phép cho trang web này",
|
|
49
|
+
"ABUSER_BLOCKED": "Các yêu cầu từ mạng bị gắn cờ lạm dụng không được phép cho trang web này",
|
|
50
|
+
"DATACENTER_BLOCKED": "Các yêu cầu từ địa chỉ IP trung tâm dữ liệu không được phép cho trang web này",
|
|
51
|
+
"MOBILE_BLOCKED": "Các yêu cầu từ kết nối mạng di động không được phép cho trang web này",
|
|
52
|
+
"SATELLITE_BLOCKED": "Các yêu cầu từ kết nối vệ tinh không được phép cho trang web này",
|
|
53
|
+
"CRAWLER_BLOCKED": "Các yêu cầu từ trình thu thập dữ liệu đã biết không được phép cho trang web này",
|
|
54
|
+
"DISALLOWED_WEBVIEW": "Yêu cầu từ trình duyệt trong ứng dụng (WebView) không được phép cho trang web này"
|
|
42
55
|
},
|
|
43
56
|
"PORTAL": {
|
|
44
57
|
"CANNOT_MODIFY_OWNER_USER": "Không thể sửa đổi người dùng chủ sở hữu",
|
|
@@ -46,7 +59,9 @@
|
|
|
46
59
|
"CANNOT_DELETE_LAST_USER": "Không thể xóa người dùng cuối cùng",
|
|
47
60
|
"USER_ALREADY_EXISTS": "Người dùng đã tồn tại",
|
|
48
61
|
"NO_SUGGESTIONS_FOUND": "Không tìm thấy gợi ý nào",
|
|
49
|
-
"CANNOT_DEACTIVATE_LAST_SITE": "Không thể vô hiệu hóa trang cuối cùng hoạt động"
|
|
62
|
+
"CANNOT_DEACTIVATE_LAST_SITE": "Không thể vô hiệu hóa trang cuối cùng hoạt động",
|
|
63
|
+
"DUPLICATE_SITE_NAME": "Đã tồn tại một trang web với tên này",
|
|
64
|
+
"INVALID_SITE_NAME": "Tên trang web chỉ được chứa chữ cái, chữ số, dấu gạch ngang và dấu gạch dưới"
|
|
50
65
|
},
|
|
51
66
|
"TARGET": {
|
|
52
67
|
"airplanes": "máy bay",
|
|
@@ -359,7 +374,8 @@
|
|
|
359
374
|
"I_AM_HUMAN": "Tôi là con người",
|
|
360
375
|
"NO_ACCOUNTS_FOUND": "Không tìm thấy tài khoản",
|
|
361
376
|
"ACCOUNT_NOT_FOUND": "Không tìm thấy tài khoản",
|
|
362
|
-
"NO_EXTENSION_FOUND": "Không tìm thấy tiện ích"
|
|
377
|
+
"NO_EXTENSION_FOUND": "Không tìm thấy tiện ích",
|
|
378
|
+
"INSECURE_CONTEXT": "Procaptcha yêu cầu kết nối an toàn (HTTPS)"
|
|
363
379
|
},
|
|
364
380
|
"CONTRACT": {
|
|
365
381
|
"INVALID_ADDRESS": "Không thể mã hóa địa chỉ không hợp lệ",
|
|
@@ -17,8 +17,11 @@
|
|
|
17
17
|
"MISSING_QUERY_PARAMETERS": "缺少查询参数",
|
|
18
18
|
"MISSING_AUTHORIZATION_HEADER": "缺少授权头",
|
|
19
19
|
"TIMESTAMP_TOO_OLD": "时间戳过旧",
|
|
20
|
+
"FAILED_IP_VALIDATION": "IP验证失败",
|
|
21
|
+
"ACCESS_POLICY_BLOCK": "访问被策略阻止",
|
|
20
22
|
"FORBIDDEN": "禁止",
|
|
21
23
|
"PROVIDER_VERIFY_FAILED": "提供商验证失败",
|
|
24
|
+
"SPAM_EMAIL_DOMAIN": "不允许此电子邮件域名",
|
|
22
25
|
"UNAUTHORIZED": "未授权",
|
|
23
26
|
"MISSING_BODY": "缺少主体",
|
|
24
27
|
"NO_CONTENT_TYPE_HEADER": "没有内容类型标头。假定为JSON编码主体,但无法解析。",
|
|
@@ -38,7 +41,17 @@
|
|
|
38
41
|
"INVALID_IP": "无效的IP",
|
|
39
42
|
"INVALID_URL": "无效的URL",
|
|
40
43
|
"INVALID_BODY": "无效的主体",
|
|
41
|
-
"PARSE_ERROR": "解析请求时出错"
|
|
44
|
+
"PARSE_ERROR": "解析请求时出错",
|
|
45
|
+
"SPAM_EMAIL_RULE": "电子邮件地址被垃圾邮件过滤规则拦截",
|
|
46
|
+
"VPN_BLOCKED": "此网站不允许来自VPN连接的请求",
|
|
47
|
+
"PROXY_BLOCKED": "此网站不允许来自代理服务器的请求",
|
|
48
|
+
"TOR_BLOCKED": "此网站不允许来自Tor出口节点的请求",
|
|
49
|
+
"ABUSER_BLOCKED": "此网站不允许来自被标记为滥用的网络的请求",
|
|
50
|
+
"DATACENTER_BLOCKED": "此网站不允许来自数据中心IP地址的请求",
|
|
51
|
+
"MOBILE_BLOCKED": "此网站不允许来自移动网络连接的请求",
|
|
52
|
+
"SATELLITE_BLOCKED": "此网站不允许来自卫星连接的请求",
|
|
53
|
+
"CRAWLER_BLOCKED": "此网站不允许来自已知爬虫的请求",
|
|
54
|
+
"DISALLOWED_WEBVIEW": "此站点不允许来自应用内浏览器 (WebView) 的请求"
|
|
42
55
|
},
|
|
43
56
|
"PORTAL": {
|
|
44
57
|
"CANNOT_MODIFY_OWNER_USER": "无法修改所有者用户",
|
|
@@ -46,7 +59,9 @@
|
|
|
46
59
|
"CANNOT_DELETE_LAST_USER": "无法删除最后一个用户",
|
|
47
60
|
"USER_ALREADY_EXISTS": "用户已经存在",
|
|
48
61
|
"NO_SUGGESTIONS_FOUND": "未找到建议",
|
|
49
|
-
"CANNOT_DEACTIVATE_LAST_SITE": "无法停用最后一个活动站点"
|
|
62
|
+
"CANNOT_DEACTIVATE_LAST_SITE": "无法停用最后一个活动站点",
|
|
63
|
+
"DUPLICATE_SITE_NAME": "已存在同名站点",
|
|
64
|
+
"INVALID_SITE_NAME": "站点名称只能包含字母、数字、连字符和下划线"
|
|
50
65
|
},
|
|
51
66
|
"TARGET": {
|
|
52
67
|
"airplanes": "飞机",
|
|
@@ -359,7 +374,8 @@
|
|
|
359
374
|
"I_AM_HUMAN": "我是人类",
|
|
360
375
|
"NO_ACCOUNTS_FOUND": "找不到帐户",
|
|
361
376
|
"ACCOUNT_NOT_FOUND": "找不到帐户",
|
|
362
|
-
"NO_EXTENSION_FOUND": "找不到扩展"
|
|
377
|
+
"NO_EXTENSION_FOUND": "找不到扩展",
|
|
378
|
+
"INSECURE_CONTEXT": "Procaptcha 需要安全连接 (HTTPS)"
|
|
363
379
|
},
|
|
364
380
|
"CONTRACT": {
|
|
365
381
|
"INVALID_ADDRESS": "无法编码无效地址",
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { describe, expect, test } from "vitest";
|
|
4
|
+
import { Languages } from "../index.js";
|
|
5
|
+
describe("logging", () => {
|
|
6
|
+
test("Make sure the number of files present in the locales folder is the same size as the Languages array", () => {
|
|
7
|
+
const locales = fs.readdirSync(path.resolve("./src/locales"));
|
|
8
|
+
expect(locales.length).to.equal(Object.keys(Languages).length);
|
|
9
|
+
});
|
|
10
|
+
test("Get all locale JSON files and ensure the keys are identical in each one", () => {
|
|
11
|
+
const locales = Object.values(Languages);
|
|
12
|
+
const sectionKeys = new Set();
|
|
13
|
+
console.log("Local test running at ", path.resolve("."));
|
|
14
|
+
const sectionKeysObj = {};
|
|
15
|
+
const innerKeysObj = {};
|
|
16
|
+
for (const locale of locales) {
|
|
17
|
+
const localeData = fs.readFileSync(path.resolve(`./src/locales/${locale}/translation.json`), "utf8");
|
|
18
|
+
const localeKeys = Object.keys(JSON.parse(localeData));
|
|
19
|
+
for (const sectionKey of localeKeys) {
|
|
20
|
+
sectionKeys.add(sectionKey);
|
|
21
|
+
}
|
|
22
|
+
sectionKeysObj[locale] = new Set(localeKeys);
|
|
23
|
+
for (const sectionKey of localeKeys) {
|
|
24
|
+
const innerKeys = JSON.parse(localeData)[sectionKey];
|
|
25
|
+
if (typeof innerKeys !== "object") {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (!innerKeysObj[locale]) {
|
|
29
|
+
innerKeysObj[locale] = {};
|
|
30
|
+
}
|
|
31
|
+
if (!innerKeysObj[locale][sectionKey]) {
|
|
32
|
+
innerKeysObj[locale][sectionKey] = new Set();
|
|
33
|
+
}
|
|
34
|
+
for (const innerKey of Object.keys(innerKeys)) {
|
|
35
|
+
innerKeysObj[locale][sectionKey].add(innerKey);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
for (const locale of Array.from(locales)) {
|
|
40
|
+
console.log("Checking", locale);
|
|
41
|
+
expect(sectionKeysObj[locale]).to.deep.equal(sectionKeysObj.en);
|
|
42
|
+
for (const sectionKey of Object.keys(innerKeysObj[locale])) {
|
|
43
|
+
console.log(`Checking ${locale} ${sectionKey}`);
|
|
44
|
+
expect(innerKeysObj[locale][sectionKey]).to.deep.equal(innerKeysObj.en[sectionKey]);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=locales.unit.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locales.unit.test.js","sourceRoot":"","sources":["../../src/tests/locales.unit.test.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACxB,IAAI,CAAC,qGAAqG,EAAE,GAAG,EAAE;QAChH,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC;QAC9D,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACpF,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QACzD,MAAM,cAAc,GAAmC,EAAE,CAAC;QAC1D,MAAM,YAAY,GAAsD,EAAE,CAAC;QAC3E,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CACjC,IAAI,CAAC,OAAO,CAAC,iBAAiB,MAAM,mBAAmB,CAAC,EACxD,MAAM,CACN,CAAC;YACF,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;YACvD,KAAK,MAAM,UAAU,IAAI,UAAU,EAAE,CAAC;gBACrC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC7B,CAAC;YACD,cAAc,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;YAC7C,KAAK,MAAM,UAAU,IAAI,UAAU,EAAE,CAAC;gBACrC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,CAAC;gBACrD,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;oBACnC,SAAS;gBACV,CAAC;gBAED,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC3B,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;gBAC3B,CAAC;gBAGD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;oBAEvC,YAAY,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;gBAC9C,CAAC;gBAED,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;oBAE/C,YAAY,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAChD,CAAC;YACF,CAAC;QACF,CAAC;QAED,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1C,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAChC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;YAEhE,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBAC5D,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,IAAI,UAAU,EAAE,CAAC,CAAC;gBAEhD,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAErD,YAAY,CAAC,EAAE,CAAC,UAAU,CAAC,CAC3B,CAAC;YACH,CAAC;QACF,CAAC;IACF,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translationKey.js","sourceRoot":"","sources":["../src/translationKey.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,aAAa,MAAM,+BAA+B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAQhF,SAAS,gBAAgB,CAAC,GAAS;IAClC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO,EAAE,CAAC;IACX,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC3C,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAEzC,OAAO,GAAG,CAAC,MAAM,CAChB,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACtB,OAAO,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;QAC1B,CAAC,CAAC,CACF,CAAC;IACH,CAAC,EAAE,EAAc,CAAC,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAC1C,gBAAgB,CAAC,aAAa,CAA0B,CACxD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translations.js","sourceRoot":"","sources":["../src/translations.ts"],"names":[],"mappings":"AAcA,OAAO,CAAC,MAAM,KAAK,CAAC;AAEpB,MAAM,CAAC,MAAM,SAAS,GAAG;IACxB,MAAM,EAAE,IAAI;IACZ,WAAW,EAAE,IAAI;IACjB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,IAAI;IACb,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,MAAM,EAAE,IAAI;IACZ,SAAS,EAAE,IAAI;IACf,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,IAAI;IACf,MAAM,EAAE,IAAI;IACZ,eAAe,EAAE,OAAO;IACxB,UAAU,EAAE,IAAI;IAChB,QAAQ,EAAE,IAAI;IACd,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,OAAO;CACP,CAAC;AAEX,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CACnC,MAAM,CAAC,MAAM,CAAC,SAAS,CAA0B,CACjD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTranslation.js","sourceRoot":"","sources":["../src/useTranslation.ts"],"names":[],"mappings":"AAcA,OAAO,EAGN,cAAc,IAAI,qBAAqB,GACvC,MAAM,eAAe,CAAC;AACvB,OAAO,cAAc,MAAM,mBAAmB,CAAC;AAE/C,SAAS,cAAc,CACtB,OAA8C;IAK9C,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,OAAO,qBAAqB,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,eAAe,cAAc,CAAC"}
|
package/dist/util.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,MAAM,YAAY,GAAG,GAAY,EAAE;IACzC,OAAO,CAAC,CAAC,CACR,OAAO,MAAM,KAAK,WAAW;QAC7B,MAAM,CAAC,QAAQ;QACf,MAAM,CAAC,QAAQ,CAAC,aAAa,CAC7B,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAY,EAAE;IACzC,OAAO,CAAC,YAAY,EAAE,CAAC;AACxB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prosopo/locale",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.4",
|
|
4
4
|
"description": "Prosopo locale library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
24
|
"clean": "del-cli --verbose dist tsconfig.tsbuildinfo",
|
|
25
|
-
"build": "
|
|
25
|
+
"build": "npm run build:cross-env -- --mode ${NODE_ENV:-development}",
|
|
26
|
+
"build:cross-env": "vite build --config vite.esm.config.ts",
|
|
26
27
|
"build:tsc": "tsc --build --verbose",
|
|
27
28
|
"build:cjs": "NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV",
|
|
28
29
|
"typecheck": "tsc --project tsconfig.types.json",
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
"zod": "3.23.8"
|
|
43
44
|
},
|
|
44
45
|
"devDependencies": {
|
|
45
|
-
"@prosopo/config": "3.1
|
|
46
|
+
"@prosopo/config": "3.3.1",
|
|
46
47
|
"@types/node": "22.10.2",
|
|
47
48
|
"@vitest/coverage-v8": "3.2.4",
|
|
48
49
|
"concurrently": "9.0.1",
|
|
@@ -57,7 +58,8 @@
|
|
|
57
58
|
},
|
|
58
59
|
"repository": {
|
|
59
60
|
"type": "git",
|
|
60
|
-
"url": "git+https://github.com/prosopo/captcha.git"
|
|
61
|
+
"url": "git+https://github.com/prosopo/captcha.git",
|
|
62
|
+
"directory": "packages/locale"
|
|
61
63
|
},
|
|
62
64
|
"bugs": {
|
|
63
65
|
"url": "https://github.com/prosopo/captcha/issues"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
import { LanguageSchema, Languages } from "./translations.js";
|
|
15
|
+
|
|
16
|
+
// Guard the `process.env` read so the module is loadable in a plain browser
|
|
17
|
+
// runtime where `process` is undefined. Without the guard, any side-effectful
|
|
18
|
+
// runtime import of `@prosopo/types` (which transitively reaches here via
|
|
19
|
+
// `LanguageSchema`) crashes the page in Vite's dev/preview mode.
|
|
20
|
+
const logLevel =
|
|
21
|
+
typeof process !== "undefined" ? process.env?.PROSOPO_LOG_LEVEL : undefined;
|
|
22
|
+
|
|
23
|
+
export const i18nSharedOptions = {
|
|
24
|
+
debug: logLevel === "debug",
|
|
25
|
+
fallbackLng: LanguageSchema.enum.en,
|
|
26
|
+
namespace: "translation",
|
|
27
|
+
supportedLngs: Object.values(Languages),
|
|
28
|
+
nonExplicitSupportedLngs: false,
|
|
29
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
import path from "node:path";
|
|
16
|
+
import i18n from "i18next";
|
|
17
|
+
import FSBackend from "i18next-fs-backend/cjs"; // https://github.com/i18next/i18next-fs-backend/issues/57
|
|
18
|
+
import { LanguageDetector as MiddlewareLanguageDetector } from "i18next-http-middleware";
|
|
19
|
+
import { i18nSharedOptions } from "./i18SharedOptions.js";
|
|
20
|
+
import { isServerSide } from "./util.js";
|
|
21
|
+
|
|
22
|
+
const loadPath =
|
|
23
|
+
`${path.dirname(import.meta.url)}/locales/{{lng}}/{{ns}}.json`.replace(
|
|
24
|
+
"file://",
|
|
25
|
+
"",
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export function initializeI18n(
|
|
29
|
+
i18nLoadedCallback?: (value: typeof i18n) => void,
|
|
30
|
+
) {
|
|
31
|
+
if (!i18n.isInitialized && isServerSide()) {
|
|
32
|
+
const lngDetector = new MiddlewareLanguageDetector(null, {
|
|
33
|
+
order: ["header", "query", "cookie"],
|
|
34
|
+
});
|
|
35
|
+
i18n
|
|
36
|
+
// @ts-ignore https://github.com/i18next/i18next-fs-backend/issues/57
|
|
37
|
+
.use(FSBackend)
|
|
38
|
+
.use(lngDetector) // this line should switch the language to the one the user reports in the Accept-Language header
|
|
39
|
+
.init({
|
|
40
|
+
...i18nSharedOptions,
|
|
41
|
+
ns: ["translation"],
|
|
42
|
+
backend: {
|
|
43
|
+
loadPath,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
i18n.on("loaded", () => {
|
|
47
|
+
i18nLoadedCallback?.(i18n);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return i18n;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default initializeI18n;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
import i18n, { type InitOptions } from "i18next";
|
|
16
|
+
import I18nextBrowserLanguageDetector from "i18next-browser-languagedetector";
|
|
17
|
+
import ChainedBackend from "i18next-chained-backend";
|
|
18
|
+
import HttpBackend from "i18next-http-backend";
|
|
19
|
+
import resourcesToBackend from "i18next-resources-to-backend";
|
|
20
|
+
import { initReactI18next } from "react-i18next";
|
|
21
|
+
import { i18nSharedOptions } from "./i18SharedOptions.js";
|
|
22
|
+
|
|
23
|
+
const reactOptions: InitOptions = {
|
|
24
|
+
react: {
|
|
25
|
+
useSuspense: true,
|
|
26
|
+
},
|
|
27
|
+
detection: {
|
|
28
|
+
order: ["navigator", "htmlTag", "path", "subdomain"],
|
|
29
|
+
caches: ["localStorage", "cookie"],
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const getLoadPath = (language: string, namespace: string) => {
|
|
34
|
+
const filename = import.meta.url.split("/").pop();
|
|
35
|
+
return `${import.meta.url.replace(`/${filename}`, "")}/locales/${language}/${namespace}.json`;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export function initializeI18n(
|
|
39
|
+
i18nLoadedCallback?: (value: typeof i18n) => void,
|
|
40
|
+
) {
|
|
41
|
+
if (!i18n.isInitialized) {
|
|
42
|
+
i18n
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
.use(ChainedBackend)
|
|
45
|
+
.use(
|
|
46
|
+
new I18nextBrowserLanguageDetector(null, {
|
|
47
|
+
order: ["cookie", "localStorage", "navigator"],
|
|
48
|
+
lookupQuerystring: "lng",
|
|
49
|
+
lookupCookie: "i18next",
|
|
50
|
+
lookupLocalStorage: "i18nextLng",
|
|
51
|
+
caches: ["localStorage", "cookie"],
|
|
52
|
+
}),
|
|
53
|
+
)
|
|
54
|
+
.use(initReactI18next)
|
|
55
|
+
.init({
|
|
56
|
+
...i18nSharedOptions,
|
|
57
|
+
backend: {
|
|
58
|
+
backends: [
|
|
59
|
+
HttpBackend, // if a namespace can't be loaded via normal http-backend loadPath, then the inMemoryLocalBackend will try to return the correct resources
|
|
60
|
+
// with dynamic import, you have to use the "default" key of the module ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#importing_defaults )
|
|
61
|
+
resourcesToBackend(
|
|
62
|
+
(language: string, namespace: string) =>
|
|
63
|
+
import(getLoadPath(language, namespace)),
|
|
64
|
+
),
|
|
65
|
+
],
|
|
66
|
+
backendOptions: [
|
|
67
|
+
{
|
|
68
|
+
loadPath: getLoadPath("{{lng}}", "{{ns}}"),
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
...reactOptions,
|
|
73
|
+
} as InitOptions);
|
|
74
|
+
i18n.on("loaded", () => {
|
|
75
|
+
i18nLoadedCallback?.(i18n);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return i18n;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default initializeI18n;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
import { type HandleOptions, handle } from "i18next-http-middleware";
|
|
16
|
+
import loadI18next from "./loadI18next.js";
|
|
17
|
+
|
|
18
|
+
async function i18nMiddleware(
|
|
19
|
+
options: HandleOptions,
|
|
20
|
+
): Promise<ReturnType<typeof handle>> {
|
|
21
|
+
const i18n = await loadI18next(true);
|
|
22
|
+
return handle(i18n, { ...options });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default i18nMiddleware;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
export { default as i18nMiddleware } from "./i18nMiddleware.js";
|
|
16
|
+
export { default as loadI18next } from "./loadI18next.js";
|
|
17
|
+
export { Languages, LanguageSchema } from "./translations.js";
|
|
18
|
+
export { isClientSide } from "./util.js";
|
|
19
|
+
export { TranslationKeysSchema } from "./translationKey.js";
|
|
20
|
+
export type { TranslationKey } from "./translationKey.js";
|
|
21
|
+
export { default as useTranslation } from "./useTranslation.js";
|
|
22
|
+
export type { Ti18n } from "./loadI18next.js";
|