瀏覽代碼

@uppy/locales: use TypeScript for source files (#4779)

Antoine du Hamel 1 年之前
父節點
當前提交
c60ece4dc7
共有 45 個文件被更改,包括 1002 次插入677 次删除
  1. 1 1
      packages/@uppy/locales/README.md
  2. 3 0
      packages/@uppy/locales/package.json
  3. 8 13
      packages/@uppy/locales/src/ar_SA.ts
  4. 32 14
      packages/@uppy/locales/src/bg_BG.ts
  5. 28 12
      packages/@uppy/locales/src/cs_CZ.ts
  6. 20 19
      packages/@uppy/locales/src/da_DK.ts
  7. 44 20
      packages/@uppy/locales/src/de_DE.ts
  8. 28 23
      packages/@uppy/locales/src/el_GR.ts
  9. 34 15
      packages/@uppy/locales/src/en_US.ts
  10. 46 21
      packages/@uppy/locales/src/es_ES.ts
  11. 48 25
      packages/@uppy/locales/src/es_MX.ts
  12. 26 11
      packages/@uppy/locales/src/fa_IR.ts
  13. 16 17
      packages/@uppy/locales/src/fi_FI.ts
  14. 32 14
      packages/@uppy/locales/src/fr_FR.ts
  15. 24 21
      packages/@uppy/locales/src/gl_ES.ts
  16. 12 15
      packages/@uppy/locales/src/he_IL.ts
  17. 14 8
      packages/@uppy/locales/src/hi_IN.ts
  18. 22 20
      packages/@uppy/locales/src/hr_HR.ts
  19. 29 64
      packages/@uppy/locales/src/hu_HU.ts
  20. 18 18
      packages/@uppy/locales/src/id_ID.ts
  21. 19 21
      packages/@uppy/locales/src/is_IS.ts
  22. 22 23
      packages/@uppy/locales/src/it_IT.ts
  23. 30 24
      packages/@uppy/locales/src/ja_JP.ts
  24. 20 8
      packages/@uppy/locales/src/ko_KR.ts
  25. 21 9
      packages/@uppy/locales/src/nb_NO.ts
  26. 40 18
      packages/@uppy/locales/src/nl_NL.ts
  27. 22 20
      packages/@uppy/locales/src/pl_PL.ts
  28. 8 2
      packages/@uppy/locales/src/pt_BR.ts
  29. 8 2
      packages/@uppy/locales/src/pt_PT.ts
  30. 27 12
      packages/@uppy/locales/src/ro_RO.ts
  31. 24 10
      packages/@uppy/locales/src/ru_RU.ts
  32. 28 21
      packages/@uppy/locales/src/sk_SK.ts
  33. 32 29
      packages/@uppy/locales/src/sr_RS_Cyrillic.ts
  34. 32 29
      packages/@uppy/locales/src/sr_RS_Latin.ts
  35. 24 21
      packages/@uppy/locales/src/sv_SE.ts
  36. 15 6
      packages/@uppy/locales/src/th_TH.ts
  37. 20 19
      packages/@uppy/locales/src/tr_TR.ts
  38. 46 25
      packages/@uppy/locales/src/uk_UA.ts
  39. 12 4
      packages/@uppy/locales/src/uz_UZ.ts
  40. 14 16
      packages/@uppy/locales/src/vi_VN.ts
  41. 13 3
      packages/@uppy/locales/src/zh_CN.ts
  42. 11 4
      packages/@uppy/locales/src/zh_TW.ts
  43. 14 0
      packages/@uppy/locales/tsconfig.build.json
  44. 13 0
      packages/@uppy/locales/tsconfig.json
  45. 2 0
      yarn.lock

+ 1 - 1
packages/@uppy/locales/README.md

@@ -23,7 +23,7 @@ $ npm install @uppy/core @uppy/locales
 
 ```js
 import Uppy from '@uppy/core'
-import Russian from '@uppy/locales/lib/ru_RU'
+import Russian from '@uppy/locales/lib/ru_RU.js'
 
 const uppy = new Uppy({
   debug: true,

+ 3 - 0
packages/@uppy/locales/package.json

@@ -16,5 +16,8 @@
   "repository": {
     "type": "git",
     "url": "git+https://github.com/transloadit/uppy.git"
+  },
+  "dependencies": {
+    "@uppy/utils": "workspace:^"
   }
 }

+ 8 - 13
packages/@uppy/locales/src/ar_SA.js → packages/@uppy/locales/src/ar_SA.ts

@@ -1,5 +1,8 @@
-const ar_SA = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const ar_SA: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -55,14 +58,12 @@ ar_SA.strings = {
   filesUploadedOfTotal: {
     '0': '%{complete} من %{smart_count} تم رفع ملف',
     '1': '%{complete} من %{smart_count} تم رفع ملفات',
-    '2': '%{complete} من %{smart_count} تم رفع ملفات',
   },
   filter: 'تصفيه',
   finishEditingFile: 'انهاء تعديل الملف',
   folderAdded: {
     '0': '%{folder} ملف من %{smart_count} تم اضافة',
     '1': '%{folder} ملفات من %{smart_count} تم اضافة',
-    '2': '%{folder} ملفات من %{smart_count} تم اضافة',
   },
   import: 'استيراد',
   importFrom: 'استيراد من %{name}',
@@ -78,7 +79,6 @@ ar_SA.strings = {
   processingXFiles: {
     '0': 'ملف %{smart_count} جاري معالجة',
     '1': 'ملفات %{smart_count}  جاري معالجة',
-    '2': 'ملفات %{smart_count} جاري معالجة ',
   },
   removeFile: 'امسح الملف',
   resetFilter: 'اعادة ضبط التصفيه',
@@ -90,7 +90,6 @@ ar_SA.strings = {
   selectX: {
     '0': '%{smart_count} اختر',
     '1': '%{smart_count} اختر',
-    '2': '%{smart_count} اختر',
   },
   smile: 'ابتسم!',
   startRecording: 'بدء تسجيل الفيديو',
@@ -104,47 +103,43 @@ ar_SA.strings = {
   uploadXFiles: {
     '0': 'رفع %{smart_count} ملف',
     '1': 'رفع %{smart_count} ملفات',
-    '2': 'رفع %{smart_count} ملفات',
   },
   uploadXNewFiles: {
     '0': 'رفع +%{smart_count} ملف',
     '1': 'رفع +%{smart_count} ملفات',
-    '2': 'رفع +%{smart_count} ملفات',
   },
   uploading: 'يتم الرفع',
   uploadingXFiles: {
     '0': 'يتم رفع %{smart_count} ملف',
     '1': 'يتم رفع %{smart_count} ملفات',
-    '2': 'يتم رفع %{smart_count} ملفات',
   },
   xFilesSelected: {
     '0': '%{smart_count} ملف محددة',
     '1': '%{smart_count} ملفات محددة',
-    '2': '%{smart_count} ملفات محددة',
   },
   xMoreFilesAdded: {
     '0': '%{smart_count} ملف اضافي جديد',
     '1': '%{smart_count} ملفات اضافيه جديده',
-    '2': '%{smart_count} ملفات اضافيه جديده',
   },
   xTimeLeft: '%{time} متبقي',
   youCanOnlyUploadFileTypes: 'تستطيع فقط رفع : %{types}',
   youCanOnlyUploadX: {
     '0': 'تستطيع فقط رفع %{smart_count} الملف',
     '1': 'تستطيع فقط رفع %{smart_count} ملفات',
-    '2': 'تستطيع فقط رفع %{smart_count} ملفات',
   },
   youHaveToAtLeastSelectX: {
     '0': 'يجب ان تختار على الاقل  %{smart_count} ملف',
     '1': 'يجب ان تختار على الاقل  %{smart_count} ملفات',
-    '2': 'يجب ان تختار على الاقل  %{smart_count} ملفات',
   },
   selectFileNamed: '%{name} اختر الملف',
   unselectFileNamed: '%{name} إلغاء تحديد الملف',
   openFolderNamed: '%{name} افتح المجلد',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.ar_SA = ar_SA
 }
 

+ 32 - 14
packages/@uppy/locales/src/bg_BG.js → packages/@uppy/locales/src/bg_BG.ts

@@ -1,5 +1,8 @@
-const bg_BG = {
-  pluralize (count) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const bg_BG: Locale<0 | 1> = {
+  strings: {},
+  pluralize(count) {
     if (count === 1) {
       return 0
     }
@@ -15,10 +18,12 @@ bg_BG.strings = {
   addMore: 'Добави повече',
   addMoreFiles: 'Добави повече файлове',
   addingMoreFiles: 'Добавяне на повече файлове',
-  allowAccessDescription: 'За да правите изображения или запишете видео с камерата моля, разшерете достъп до камерата за този сайт',
+  allowAccessDescription:
+    'За да правите изображения или запишете видео с камерата моля, разшерете достъп до камерата за този сайт',
   allowAccessTitle: 'Моля, разрешете достъп до камерата',
   authenticateWith: 'Свържете се с %{pluginName}',
-  authenticateWithTitle: 'Моля, впишете се с %{pluginName}, за да изберете файлове',
+  authenticateWithTitle:
+    'Моля, впишете се с %{pluginName}, за да изберете файлове',
   back: 'Назад',
   browse: 'преглед',
   browseFiles: 'преглед',
@@ -27,7 +32,8 @@ bg_BG.strings = {
   chooseFiles: 'Изберете файлове',
   closeModal: 'Затваряне на прозорец',
   companionError: 'Неуспешна връзка с Companion',
-  companionUnauthorizeHint: 'За да се отпишете от акаута си в %{provider} посетете %{url}',
+  companionUnauthorizeHint:
+    'За да се отпишете от акаута си в %{provider} посетете %{url}',
   complete: 'Завършен',
   connectedToInternet: 'Свързан с интернет',
   copyLink: 'Копиране на линк',
@@ -36,7 +42,8 @@ bg_BG.strings = {
   creatingAssembly: 'Подготовка за качване...',
   creatingAssemblyFailed: 'Transloadit: библиотеката не може да се създаде',
   dashboardTitle: 'Качване на файлове',
-  dashboardWindowTitle: 'Прозорец за качване на файлове (Натиснете ESC за затваряне)',
+  dashboardWindowTitle:
+    'Прозорец за качване на файлове (Натиснете ESC за затваряне)',
   dataUploadedOfTotal: '%{complete} от %{total}',
   done: 'Готово',
   dropHereOr: 'Пуснете файлове тук или %{browse}',
@@ -44,17 +51,23 @@ bg_BG.strings = {
   dropPasteBoth: 'Пуснете файловете си тук, поставете или %{browse}',
   dropPasteFiles: 'Пуснете файловете си тук, поставете или %{browse}',
   dropPasteFolders: 'Пуснете файловете си тук, поставете или %{browse}',
-  dropPasteImportBoth: 'Пуснете файловете си тук, поставете, %{browse} или импортирайте от:',
-  dropPasteImportFiles: 'Пуснете файловете си тук, поставете, %{browse} или импортирайте от:',
-  dropPasteImportFolders: 'Пуснете файловете си тук, поставете, %{browse} или импортирайте от:',
+  dropPasteImportBoth:
+    'Пуснете файловете си тук, поставете, %{browse} или импортирайте от:',
+  dropPasteImportFiles:
+    'Пуснете файловете си тук, поставете, %{browse} или импортирайте от:',
+  dropPasteImportFolders:
+    'Пуснете файловете си тук, поставете, %{browse} или импортирайте от:',
   editFile: 'Редакция файл',
   editing: 'Редактиране %{file}',
   emptyFolderAdded: 'Не са добавени файлове от празна директория',
   encoding: 'Кодиране...',
-  enterCorrectUrl: 'Неправилен адрес: Моля, уверете се, че въвеждате директна връзка към файл',
+  enterCorrectUrl:
+    'Неправилен адрес: Моля, уверете се, че въвеждате директна връзка към файл',
   enterUrlToImport: 'Въведете адрес за да импортиране файл',
-  exceedsSize: 'Размерът на файла надвишава максимално разрешения размер от %{size}',
-  failedToFetch: 'Companion не успя да достъпи този адрес, уверете се че е правилен',
+  exceedsSize:
+    'Размерът на файла надвишава максимално разрешения размер от %{size}',
+  failedToFetch:
+    'Companion не успя да достъпи този адрес, уверете се че е правилен',
   failedToUpload: 'Грешка при качване на %{file}',
   fileSource: 'Име на сорс файл: %{name}',
   filesUploadedOfTotal: {
@@ -74,7 +87,8 @@ bg_BG.strings = {
   logOut: 'Изход',
   micDisabled: 'Достъп до микрофонът е отказан от потребителя',
   myDevice: 'Моето устройство',
-  noDuplicates: 'Файлът \'%{fileName}\' съществува. Не може да добавите дублиращи файлове',
+  noDuplicates:
+    "Файлът '%{fileName}' съществува. Не може да добавите дублиращи файлове",
   noFilesFound: 'Тук нямате файлове или директории',
   noInternetConnection: 'Няма връзка с интернет',
   noMoreFilesAllowed: 'Не може да се добавят нови файлове: в процес на качване',
@@ -89,7 +103,8 @@ bg_BG.strings = {
   },
   recording: 'Записване',
   recordingLength: 'Дължина на записа %{recording_length}',
-  recordingStoppedMaxSize: 'Записът е прекъснат, защото размерът на файла наближава максимално допустимия размер',
+  recordingStoppedMaxSize:
+    'Записът е прекъснат, защото размерът на файла наближава максимално допустимия размер',
   removeFile: 'Премахване на файл',
   resetFilter: 'Изчистване на филтър',
   resume: 'Възстановяване',
@@ -150,7 +165,10 @@ bg_BG.strings = {
   },
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.bg_BG = bg_BG
 }
 

+ 28 - 12
packages/@uppy/locales/src/cs_CZ.js → packages/@uppy/locales/src/cs_CZ.ts

@@ -1,5 +1,8 @@
-const cs_CZ = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const cs_CZ: Locale<0 | 1 | 2> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -14,10 +17,12 @@ cs_CZ.strings = {
   addMore: 'Přidat další',
   addMoreFiles: 'Přidat další soubory',
   addingMoreFiles: 'Přidávání dalších souborů',
-  allowAccessDescription: 'Pokud chcete pořizovat fotografie vaším zařízením, povolte prosím přístup ke kameře.',
+  allowAccessDescription:
+    'Pokud chcete pořizovat fotografie vaším zařízením, povolte prosím přístup ke kameře.',
   allowAccessTitle: 'Povolte prosím přístup ke kameře.',
   authenticateWith: 'Připojit k %{pluginName}',
-  authenticateWithTitle: 'Prosím přihlaste se k %{pluginName} pro výběr souborů',
+  authenticateWithTitle:
+    'Prosím přihlaste se k %{pluginName} pro výběr souborů',
   back: 'Zpět',
   browse: 'procházet',
   browseFiles: 'procházet',
@@ -34,7 +39,8 @@ cs_CZ.strings = {
   creatingAssembly: 'Nahrávání se připravuje...',
   creatingAssemblyFailed: 'Transloadit: Nelze vytvořit Assembly',
   dashboardTitle: 'Nahrát soubory',
-  dashboardWindowTitle: 'Okno pro nahrání souborů. (Stiskněte ESC pro zavření.)',
+  dashboardWindowTitle:
+    'Okno pro nahrání souborů. (Stiskněte ESC pro zavření.)',
   dataUploadedOfTotal: '%{complete} z %{total}',
   done: 'Dokončeno',
   dropHereOr: 'Přetáhněte soubory sem nebo %{browse}',
@@ -42,17 +48,22 @@ cs_CZ.strings = {
   dropPasteBoth: 'Přetáhněte soubory sem, vložte je, nebo %{browse}',
   dropPasteFiles: 'Přetáhněte soubory sem, vložte je, nebo %{browse}',
   dropPasteFolders: 'Přetáhněte soubory sem, vložte je, nebo %{browse}',
-  dropPasteImportBoth: 'Přetáhněte soubory sem, vložte je, %{browse} nebo je importujte',
-  dropPasteImportFiles: 'Přetáhněte soubory sem, vložte je, %{browse} nebo je importujte',
-  dropPasteImportFolders: 'Přetáhněte soubory sem, vložte je, %{browse} nebo je importujte',
+  dropPasteImportBoth:
+    'Přetáhněte soubory sem, vložte je, %{browse} nebo je importujte',
+  dropPasteImportFiles:
+    'Přetáhněte soubory sem, vložte je, %{browse} nebo je importujte',
+  dropPasteImportFolders:
+    'Přetáhněte soubory sem, vložte je, %{browse} nebo je importujte',
   editFile: 'Upravit soubor',
   editing: 'Upravujete %{file}',
   emptyFolderAdded: 'Nebyly přidány žádné soubory, adresář je prázdný.',
   encoding: 'Převádění...',
-  enterCorrectUrl: 'Chybná URL: Ujistěte se, že vkládáte přímý odkaz na soubor.',
+  enterCorrectUrl:
+    'Chybná URL: Ujistěte se, že vkládáte přímý odkaz na soubor.',
   enterUrlToImport: 'Vložte URL pro import souboru.',
   exceedsSize: 'Tento soubor překračuje maximální povolenou velikost: %{size}',
-  failedToFetch: 'Modulu Companion se nepodařilo stáhnout soubor z této URL, zkontrolujte prosím, jestli je URL správná.',
+  failedToFetch:
+    'Modulu Companion se nepodařilo stáhnout soubor z této URL, zkontrolujte prosím, jestli je URL správná.',
   failedToUpload: 'Nepodařilo se nahrát soubor %{file}',
   fileSource: 'Zdroj souboru: %{name}',
   filesUploadedOfTotal: {
@@ -102,7 +113,8 @@ cs_CZ.strings = {
   startRecording: 'Spustit nahrávání videa',
   stopRecording: 'Zastavit nahrávání videa',
   takePicture: 'Pořídit fotografii',
-  timedOut: 'Stav nahrávání se nezměnil %{seconds} sekund, nahrávání se ukončuje.',
+  timedOut:
+    'Stav nahrávání se nezměnil %{seconds} sekund, nahrávání se ukončuje.',
   unselectFileNamed: 'Zrušit výběr souboru %{name}',
   upload: 'Nahrát',
   uploadComplete: 'Nahrání dokončeno',
@@ -135,7 +147,8 @@ cs_CZ.strings = {
     '2': '%{smart_count} dalších souborů přidáno',
   },
   xTimeLeft: '%{time} zbývá',
-  youCanOnlyUploadFileTypes: 'Lze nahrát pouze následující typy souborů: %{types}',
+  youCanOnlyUploadFileTypes:
+    'Lze nahrát pouze následující typy souborů: %{types}',
   youCanOnlyUploadX: {
     '0': 'Lze nahrát pouze %{smart_count} soubor',
     '1': 'Lze nahrát pouze %{smart_count} soubory',
@@ -148,7 +161,10 @@ cs_CZ.strings = {
   },
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.cs_CZ = cs_CZ
 }
 

+ 20 - 19
packages/@uppy/locales/src/da_DK.js → packages/@uppy/locales/src/da_DK.ts

@@ -1,5 +1,8 @@
-const da_DK = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const da_DK: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -11,10 +14,12 @@ da_DK.strings = {
   addMore: 'Tilføj flere',
   addMoreFiles: 'Tilføj flere filer',
   addingMoreFiles: 'Tilføj flere filer',
-  allowAccessDescription: 'For at kunne tage billeder eller video med dit kamera, skal du tillade adgang til dit kamera for denne side.',
+  allowAccessDescription:
+    'For at kunne tage billeder eller video med dit kamera, skal du tillade adgang til dit kamera for denne side.',
   allowAccessTitle: 'Venligst giv adgang til dit kamera',
   authenticateWith: 'Forbind til %{pluginName}',
-  authenticateWithTitle: 'Venligst autentificer med %{pluginName} for at vælge filer',
+  authenticateWithTitle:
+    'Venligst autentificer med %{pluginName} for at vælge filer',
   back: 'Tilbage',
   browse: 'gennemse',
   browseFiles: 'gennemse',
@@ -41,28 +46,30 @@ da_DK.strings = {
   dropPasteFolders: 'Træk filer her, sæt ind eller %{browse}',
   dropPasteImportBoth: 'Træk filer her, sæt ind, %{browse} eller importer fra',
   dropPasteImportFiles: 'Træk filer her, sæt ind, %{browse} eller importer fra',
-  dropPasteImportFolders: 'Træk filer her, sæt ind, %{browse} eller importer fra',
+  dropPasteImportFolders:
+    'Træk filer her, sæt ind, %{browse} eller importer fra',
   editFile: 'Rediger fil',
   editing: 'Redigerer %{file}',
   emptyFolderAdded: 'Ingen filer blev tilføjet fra en tom mappe',
   encoding: 'Encoding...',
-  enterCorrectUrl: 'Forkert URL: Venligst sørg for at du indtaster et direkte link til en fil',
+  enterCorrectUrl:
+    'Forkert URL: Venligst sørg for at du indtaster et direkte link til en fil',
   enterUrlToImport: 'Indtast URL for at importerer en fil',
-  exceedsSize: 'Denne fil overskrider den maksimale tilladte størrelse af %{size}',
-  failedToFetch: 'Companion kunne ikke hente denne URL, venligst undersøg om denne er korrekt',
+  exceedsSize:
+    'Denne fil overskrider den maksimale tilladte størrelse af %{size}',
+  failedToFetch:
+    'Companion kunne ikke hente denne URL, venligst undersøg om denne er korrekt',
   failedToUpload: 'Fejlede upload af %{file}',
   fileSource: 'Fil kilde: %{name}',
   filesUploadedOfTotal: {
     '0': '%{complete} af %{smart_count} filer uploaded',
     '1': '%{complete} af %{smart_count} fil uploaded',
-    '2': '%{complete} af %{smart_count} filer uploaded',
   },
   filter: 'Filter',
   finishEditingFile: 'Færddiggør redigering af fil',
   folderAdded: {
     '0': 'Tilføjet %{smart_count} filer fra %{folder}',
     '1': 'Tilføjet %{smart_count} fil fra %{folder}',
-    '2': 'Tilføjet %{smart_count} filer fra %{folder}',
   },
   import: 'Importer',
   importFrom: 'Importer fra %{name}',
@@ -79,7 +86,6 @@ da_DK.strings = {
   processingXFiles: {
     '0': 'Behandler %{smart_count} filer',
     '1': 'Behandler %{smart_count} fil',
-    '2': 'Behandler %{smart_count} filer',
   },
   removeFile: 'Fjern fil',
   resetFilter: 'Nulstil filter',
@@ -92,7 +98,6 @@ da_DK.strings = {
   selectX: {
     '0': 'Vælg %{smart_count}',
     '1': 'Vælg %{smart_count}',
-    '2': 'Vælg %{smart_count}',
   },
   smile: 'Smil!',
   startRecording: 'Start video optagelse',
@@ -107,44 +112,40 @@ da_DK.strings = {
   uploadXFiles: {
     '0': 'Upload %{smart_count} fil',
     '1': 'Upload %{smart_count} filer',
-    '2': 'Upload %{smart_count} filer',
   },
   uploadXNewFiles: {
     '0': 'Upload +%{smart_count} fil',
     '1': 'Upload +%{smart_count} filer',
-    '2': 'Upload +%{smart_count} filer',
   },
   uploading: 'Uploader',
   uploadingXFiles: {
     '0': 'Uploader %{smart_count} fil',
     '1': 'Uploader %{smart_count} filer',
-    '2': 'Uploader %{smart_count} filer',
   },
   xFilesSelected: {
     '0': '%{smart_count} fil valgt',
     '1': '%{smart_count} filer valgt',
-    '2': '%{smart_count} filer valgt',
   },
   xMoreFilesAdded: {
     '0': '%{smart_count} flere filer tilføjet',
     '1': '%{smart_count} flere filer tilføjet',
-    '2': '%{smart_count} flere filer tilføjet',
   },
   xTimeLeft: '%{time} tilbage',
   youCanOnlyUploadFileTypes: 'Du kan kun uploade: %{types}',
   youCanOnlyUploadX: {
     '0': 'Du kan kun uploade %{smart_count} fil',
     '1': 'Du kan kun uploade %{smart_count} filer',
-    '2': 'Du kan kun uploade %{smart_count} filer',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Du skal vælge mindst %{smart_count} fil',
     '1': 'Du skal vælge mindst %{smart_count} filer',
-    '2': 'Du skal vælge mindst %{smart_count} filer',
   },
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.da_DK = da_DK
 }
 

+ 44 - 20
packages/@uppy/locales/src/de_DE.js → packages/@uppy/locales/src/de_DE.ts

@@ -1,5 +1,8 @@
-const de_DE = {
-  pluralize (count) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const de_DE: Locale<0 | 1> = {
+  strings: {},
+  pluralize(count) {
     if (count === 1) {
       return 0
     }
@@ -16,13 +19,15 @@ de_DE.strings = {
   addMore: 'Mehr hinzufügen',
   addMoreFiles: 'Dateien hinzufügen',
   allFilesFromFolderNamed: 'Alle Dateien vom Ordner %{name}',
-  allowAccessDescription: 'Um Bilder oder Videos mit Ihrer Kamera aufzunehmen, erlauben Sie dieser Website bitte den Zugriff auf Ihre Kamera.',
+  allowAccessDescription:
+    'Um Bilder oder Videos mit Ihrer Kamera aufzunehmen, erlauben Sie dieser Website bitte den Zugriff auf Ihre Kamera.',
   allowAccessTitle: 'Bitte erlauben Sie Zugriff auf Ihre Kamera',
   aspectRatioLandscape: 'Zuschneiden auf Querformat (16:9)',
   aspectRatioPortrait: 'Zuschneiden auf Hochformat (9:16)',
   aspectRatioSquare: 'Zuschneiden auf Quadrat',
   authenticateWith: 'Mit %{pluginName} verbinden',
-  authenticateWithTitle: 'Bitte authentifizieren Sie sich mit %{pluginName}, um Dateien auszuwählen',
+  authenticateWithTitle:
+    'Bitte authentifizieren Sie sich mit %{pluginName}, um Dateien auszuwählen',
   back: 'Zurück',
   backToSearch: 'Zurück zur Suche',
   browse: 'durchsuchen',
@@ -33,7 +38,8 @@ de_DE.strings = {
   chooseFiles: 'Dateien auswählen',
   closeModal: 'Fenster schließen',
   companionError: 'Verbindung zu Companion fehlgeschlagen',
-  companionUnauthorizeHint: 'Um die Autorisierung für Ihr %{provider} Konto aufzuheben, gehen Sie bitte zu %{url}',
+  companionUnauthorizeHint:
+    'Um die Autorisierung für Ihr %{provider} Konto aufzuheben, gehen Sie bitte zu %{url}',
   complete: 'Fertig',
   connectedToInternet: 'Mit dem Internet verbunden',
   copyLink: 'Link kopieren',
@@ -48,22 +54,29 @@ de_DE.strings = {
   done: 'Abgeschlossen',
   dropHereOr: 'Dateien hier ablegen oder %{browse}',
   dropHint: 'Dateien hier ablegen',
-  dropPasteBoth: 'Dateien hier ablegen/einfügen, %{browseFiles} oder %{browseFolders}',
+  dropPasteBoth:
+    'Dateien hier ablegen/einfügen, %{browseFiles} oder %{browseFolders}',
   dropPasteFiles: 'Dateien hier ablegen/einfügen oder %{browseFiles}',
   dropPasteFolders: 'Dateien hier ablegen/einfügen oder %{browseFolders}',
-  dropPasteImportBoth: 'Dateien hier ablegen/einfügen, %{browse} oder von folgenden Quellen importieren:',
-  dropPasteImportFiles: 'Dateien hier ablegen/einfügen, %{browseFiles} oder von folgenden Quellen importieren:',
-  dropPasteImportFolders: 'Dateien hier ablegen/einfügen, %{browseFolders} oder von folgenden Quellen importieren:',
+  dropPasteImportBoth:
+    'Dateien hier ablegen/einfügen, %{browse} oder von folgenden Quellen importieren:',
+  dropPasteImportFiles:
+    'Dateien hier ablegen/einfügen, %{browseFiles} oder von folgenden Quellen importieren:',
+  dropPasteImportFolders:
+    'Dateien hier ablegen/einfügen, %{browseFolders} oder von folgenden Quellen importieren:',
   editFile: 'Datei bearbeiten',
   editFileWithFilename: 'Datei %{file} bearbeiten',
   editing: '%{file} bearbeiten',
   emptyFolderAdded: 'Keine Dateien hinzugefügt, da der Ordner leer war',
   encoding: 'Kodieren...',
-  enterCorrectUrl: 'Falsche URL: Bitte stellen Sie sicher, dass Sie einen direkten Link zu einer Datei eingeben',
+  enterCorrectUrl:
+    'Falsche URL: Bitte stellen Sie sicher, dass Sie einen direkten Link zu einer Datei eingeben',
   enterTextToSearch: 'Text zum Suchen von Bildern eingeben',
   enterUrlToImport: 'URL zum Importieren einer Datei eingeben',
-  exceedsSize: 'Datei %{file} ist größer als die maximal erlaubte Dateigröße von %{size}',
-  failedToFetch: 'Companion konnte diese URL nicht verarbeiten - stellen Sie bitte sicher, dass sie korrekt ist',
+  exceedsSize:
+    'Datei %{file} ist größer als die maximal erlaubte Dateigröße von %{size}',
+  failedToFetch:
+    'Companion konnte diese URL nicht verarbeiten - stellen Sie bitte sicher, dass sie korrekt ist',
   failedToUpload: 'Fehler beim Hochladen der Datei %{file}',
   filesUploadedOfTotal: {
     '0': '%{complete} von %{smart_count} Datei hochgeladen',
@@ -81,23 +94,28 @@ de_DE.strings = {
   import: 'Importieren',
   importFiles: 'Importiere Dateien von:',
   importFrom: 'Importieren von %{name}',
-  inferiorSize: 'Diese Datei ist kleiner als die minimal erlaubte Dateigröße von %{size}',
+  inferiorSize:
+    'Diese Datei ist kleiner als die minimal erlaubte Dateigröße von %{size}',
   loading: 'Laden...',
   logOut: 'Abmelden',
   micDisabled: 'Zugriff auf Mikrofon von Benutzer abgelehnt',
   missingRequiredMetaField: 'Fehlende erforderliche Meta-Felder',
-  missingRequiredMetaFieldOnFile: 'Fehlende erforderliche Meta-Felder in %{fileName}',
+  missingRequiredMetaFieldOnFile:
+    'Fehlende erforderliche Meta-Felder in %{fileName}',
   missingRequiredMetaFields: {
     '0': 'Fehlendes erforderliches Meta-Feld: %{fields}.',
     '1': 'Fehlende erforderliche Meta-Felder: %{fields}.',
   },
   myDevice: 'Mein Gerät',
-  noCameraDescription: 'Bitte Kamera anschließen, um Bilder oder Videos aufzunehmen',
+  noCameraDescription:
+    'Bitte Kamera anschließen, um Bilder oder Videos aufzunehmen',
   noCameraTitle: 'Kamera nicht verfügbar',
-  noDuplicates: 'Datei \'%{fileName}\' existiert bereits und kann nicht erneut hinzugefügt werden',
+  noDuplicates:
+    "Datei '%{fileName}' existiert bereits und kann nicht erneut hinzugefügt werden",
   noFilesFound: 'Sie haben hier keine Dateien oder Ordner',
   noInternetConnection: 'Keine Internetverbindung',
-  noMoreFilesAllowed: 'Während der Upload läuft, können keine weiteren Dateien hinzugefügt werden',
+  noMoreFilesAllowed:
+    'Während der Upload läuft, können keine weiteren Dateien hinzugefügt werden',
   openFolderNamed: 'Ordner %{name} öffnen',
   pause: 'Pausieren',
   paused: 'Pausiert',
@@ -117,8 +135,10 @@ de_DE.strings = {
   },
   recording: 'Aufnahme',
   recordingLength: 'Aufnahmedauer %{recording_length}',
-  recordingStoppedMaxSize: 'Die Aufnahme wurde gestoppt, weil die Dateigröße das Limit überschritten hat',
-  recoveredAllFiles: 'Wir haben alle Dateien wiederhergestellt. Sie können mit dem Hochladen fortfahren.',
+  recordingStoppedMaxSize:
+    'Die Aufnahme wurde gestoppt, weil die Dateigröße das Limit überschritten hat',
+  recoveredAllFiles:
+    'Wir haben alle Dateien wiederhergestellt. Sie können mit dem Hochladen fortfahren.',
   recoveredXFiles: {
     '0': 'Wir konnten eine Datei nicht vollständig wiederherstellen. Bitte wählen Sie sie erneut aus und fahren Sie dann mit dem Hochladen fort.',
     '1': 'Wir konnten %{smart_count} Dateien nicht vollständig wiederherstellen. Bitte wählen Sie sie erneut aus und fahren Sie dann mit dem Hochladen fort.',
@@ -176,7 +196,8 @@ de_DE.strings = {
     '1': '%{smart_count} weitere Dateien hinzugefügt',
   },
   xTimeLeft: '%{time} verbleibend',
-  youCanOnlyUploadFileTypes: 'Sie können nur folgende Dateitypen hochladen: %{types}',
+  youCanOnlyUploadFileTypes:
+    'Sie können nur folgende Dateitypen hochladen: %{types}',
   youCanOnlyUploadX: {
     '0': 'Sie können nur eine Datei hochladen',
     '1': 'Sie können nur %{smart_count} Dateien hochladen',
@@ -189,7 +210,10 @@ de_DE.strings = {
   zoomOut: 'Verkleinern',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.de_DE = de_DE
 }
 

+ 28 - 23
packages/@uppy/locales/src/el_GR.js → packages/@uppy/locales/src/el_GR.ts

@@ -1,5 +1,8 @@
-const el_GR = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const el_GR: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 1
     }
@@ -11,10 +14,12 @@ el_GR.strings = {
   addMore: 'Προσθέστε περισσότερα',
   addMoreFiles: 'Προσθέστε περισσότερα αρχεία',
   addingMoreFiles: 'Προσθήκη αρχείων',
-  allowAccessDescription: 'Για να βγάλετε φωτογραφίες ή βίντεο με την κάμερά σας, παρακαλούμε επιτρέψτε την πρόσβαση στην κάμερά σας για αυτόν τον ιστότοπο.',
+  allowAccessDescription:
+    'Για να βγάλετε φωτογραφίες ή βίντεο με την κάμερά σας, παρακαλούμε επιτρέψτε την πρόσβαση στην κάμερά σας για αυτόν τον ιστότοπο.',
   allowAccessTitle: 'Παρακαλούμε επιτρέψτε την πρόσβαση στην κάμερά σας',
   authenticateWith: 'Σύνδεση με %{pluginName}',
-  authenticateWithTitle: 'Παρακαλούμε συνδεθείτε με %{pluginName} για να επιλέξετε αρχεία',
+  authenticateWithTitle:
+    'Παρακαλούμε συνδεθείτε με %{pluginName} για να επιλέξετε αρχεία',
   back: 'Πίσω',
   browse: 'Περιήγηση',
   browseFiles: 'Περιήγηση',
@@ -31,7 +36,8 @@ el_GR.strings = {
   creatingAssembly: 'Προετοιμασία μεταφόρτωσης...',
   creatingAssemblyFailed: 'Transloadit: Σφάλμα κατά την προετοιμασία',
   dashboardTitle: 'Μεταφόρτωση αρχείων',
-  dashboardWindowTitle: 'Παράθυρο μεταφόρτωσης αρχείων (Πατήστε escape για να κλείσει)',
+  dashboardWindowTitle:
+    'Παράθυρο μεταφόρτωσης αρχείων (Πατήστε escape για να κλείσει)',
   dataUploadedOfTotal: '%{complete} από %{total}',
   done: 'Τέλος',
   dropHereOr: 'Σύρετε τα αρχεία εδώ ή %{browse}',
@@ -39,30 +45,34 @@ el_GR.strings = {
   dropPasteBoth: 'Σύρετε τα αρχεία εδώ, κάντε επικόλληση ή %{browse}',
   dropPasteFiles: 'Σύρετε τα αρχεία εδώ, κάντε επικόλληση ή %{browse}',
   dropPasteFolders: 'Σύρετε τα αρχεία εδώ, κάντε επικόλληση ή %{browse}',
-  dropPasteImportBoth: 'Σύρετε αρχεία εδώ, κάντε επικόλληση, %{browse} ή εισαγωγή από',
-  dropPasteImportFiles: 'Σύρετε αρχεία εδώ, κάντε επικόλληση, %{browse} ή εισαγωγή από',
-  dropPasteImportFolders: 'Σύρετε αρχεία εδώ, κάντε επικόλληση, %{browse} ή εισαγωγή από',
+  dropPasteImportBoth:
+    'Σύρετε αρχεία εδώ, κάντε επικόλληση, %{browse} ή εισαγωγή από',
+  dropPasteImportFiles:
+    'Σύρετε αρχεία εδώ, κάντε επικόλληση, %{browse} ή εισαγωγή από',
+  dropPasteImportFolders:
+    'Σύρετε αρχεία εδώ, κάντε επικόλληση, %{browse} ή εισαγωγή από',
   editFile: 'Επεξεργασία αρχείου',
   editing: 'Γίνεται επεξεργασία %{file}',
   emptyFolderAdded: 'Δεν προστέθηκαν αρχεία από τον άδειο φάκελο',
   encoding: 'Γίνεται κωδικοποίηση...',
-  enterCorrectUrl: 'Λανθασμένο URL: Παρακαλούμε βεβαιωθείτε ότι εισάγετε έναν άμεσο σύνδεσμο προς κάποιο αρχείο',
+  enterCorrectUrl:
+    'Λανθασμένο URL: Παρακαλούμε βεβαιωθείτε ότι εισάγετε έναν άμεσο σύνδεσμο προς κάποιο αρχείο',
   enterUrlToImport: 'Εισάγετε URL για να γίνει εισαγωγή του αρχείου',
-  exceedsSize: 'Το αρχείο υπερβαίνει το μέγιστο επιτρεπτό όριο που είναι %{size}',
-  failedToFetch: 'Δεν ήταν δυνατή η λήψη από το URL, παρακαλούμε βεβαιωθείτε ότι είναι σωστό',
+  exceedsSize:
+    'Το αρχείο υπερβαίνει το μέγιστο επιτρεπτό όριο που είναι %{size}',
+  failedToFetch:
+    'Δεν ήταν δυνατή η λήψη από το URL, παρακαλούμε βεβαιωθείτε ότι είναι σωστό',
   failedToUpload: 'Δεν ήταν δυνατή η μεταφόρτωση %{file}',
   fileSource: 'Πηγή αρχείου: %{name}',
   filesUploadedOfTotal: {
     '0': '%{complete} από %{smart_count} αρχεία ανέβηκαν',
     '1': '%{complete} από %{smart_count} αρχείο ανέβηκε',
-    '2': '%{complete} από %{smart_count} αρχεία ανέβηκαν',
   },
   filter: 'Φιλτράρισμα',
   finishEditingFile: 'Ολοκλήρωση επεξεργασίας αρχείου',
   folderAdded: {
     '0': 'Προστέθηκαν %{smart_count} αρχεία από %{folder}',
     '1': 'Προστέθηκε %{smart_count} αρχείο από %{folder}',
-    '2': 'Προστέθηκαν %{smart_count} αρχεία από %{folder}',
   },
   import: 'Εισαγωγή',
   importFrom: 'Εισαγωγή από %{name}',
@@ -79,7 +89,6 @@ el_GR.strings = {
   processingXFiles: {
     '0': 'Προετοιμασία %{smart_count} αρχείων',
     '1': 'Προετοιμασία %{smart_count} αρχείου',
-    '2': 'Προετοιμασία %{smart_count} αρχείων',
   },
   removeFile: 'Αφαίρεση αρχείου',
   resetFilter: 'Επαναφορά φίλτρου',
@@ -92,13 +101,13 @@ el_GR.strings = {
   selectX: {
     '0': 'Επιλογή %{smart_count}',
     '1': 'Επιλογή %{smart_count}',
-    '2': 'Επιλογή %{smart_count}',
   },
   smile: 'Χαμογελάστε!',
   startRecording: 'Ξεκίνημα εγγραφής βίντεο',
   stopRecording: 'Σταμάτημα εγγραφής βίντεο',
   takePicture: 'Βγάλτε μια φωτογραφία',
-  timedOut: 'Η μεταφόρτωση σταμάτησε για %{seconds} δευτερόλεπτα, γίνεται ακύρωση.',
+  timedOut:
+    'Η μεταφόρτωση σταμάτησε για %{seconds} δευτερόλεπτα, γίνεται ακύρωση.',
   unselectFileNamed: 'Αποεπιλογή αρχείου %{name}',
   upload: 'Μεταφόρτωση',
   uploadComplete: 'Μεταφόρτωση ολοκληρώθηκε',
@@ -107,44 +116,40 @@ el_GR.strings = {
   uploadXFiles: {
     '0': 'Μεταφόρτωση %{smart_count} αρχείων',
     '1': 'Μεταφόρτωση %{smart_count} αρχείου',
-    '2': 'Μεταφόρτωση %{smart_count} αρχείων',
   },
   uploadXNewFiles: {
     '0': 'Μεταφόρτωση +%{smart_count} αρχείων',
     '1': 'Μεταφόρτωση +%{smart_count} αρχείου',
-    '2': 'Μεταφόρτωση +%{smart_count} αρχείων',
   },
   uploading: 'Γίνεται μεταφόρτωση',
   uploadingXFiles: {
     '0': 'Μεταφορτώνονται %{smart_count} αρχεία',
     '1': 'Μεταφορτώνεται %{smart_count} αρχείο',
-    '2': 'Μεταφορτώνονται %{smart_count} αρχεία',
   },
   xFilesSelected: {
     '0': '%{smart_count} επιλεγμένα αρχεία',
     '1': '%{smart_count} επιλεγμένο αρχείο',
-    '2': '%{smart_count} επιλεγμένα αρχεία',
   },
   xMoreFilesAdded: {
     '0': '%{smart_count} ακόμα αρχεία προστέθηκαν',
     '1': '%{smart_count} ακόμα αρχείο προστέθηκε',
-    '2': '%{smart_count} ακόμα αρχεία προστέθηκαν',
   },
   xTimeLeft: '%{time} απομένουν',
   youCanOnlyUploadFileTypes: 'Μπορείτε να ανεβάσετε μόνο: %{types}',
   youCanOnlyUploadX: {
     '0': 'Μπορείτε να ανεβάσετε μόνο %{smart_count} αρχεία',
     '1': 'Μπορείτε να ανεβάσετε μόνο %{smart_count} αρχείο',
-    '2': 'Μπορείτε να ανεβάσετε μόνο %{smart_count} αρχεία',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Πρέπει να επιλέξετε τουλάχιστον %{smart_count} αρχεία',
     '1': 'Πρέπει να επιλέξετε τουλάχιστον %{smart_count} αρχείο',
-    '2': 'Πρέπει να επιλέξετε τουλάχιστον %{smart_count} αρχεία',
   },
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.el_GR = el_GR
 }
 

+ 34 - 15
packages/@uppy/locales/src/en_US.js → packages/@uppy/locales/src/en_US.ts

@@ -1,5 +1,8 @@
-const en_US = {
-  pluralize (count) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const en_US: Locale<0 | 1> = {
+  strings: {},
+  pluralize(count) {
     if (count === 1) {
       return 0
     }
@@ -14,20 +17,24 @@ en_US.strings = {
   },
   addedNumFiles: 'Added %{numFiles} file(s)',
   addingMoreFiles: 'Adding more files',
-  additionalRestrictionsFailed: '%{count} additional restrictions were not fulfilled',
+  additionalRestrictionsFailed:
+    '%{count} additional restrictions were not fulfilled',
   addMore: 'Add more',
   addMoreFiles: 'Add more files',
   allFilesFromFolderNamed: 'All files from folder %{name}',
-  allowAccessDescription: 'In order to take pictures or record video with your camera, please allow camera access for this site.',
+  allowAccessDescription:
+    'In order to take pictures or record video with your camera, please allow camera access for this site.',
   allowAccessTitle: 'Please allow access to your camera',
-  allowAudioAccessDescription: 'In order to record audio, please allow microphone access for this site.',
+  allowAudioAccessDescription:
+    'In order to record audio, please allow microphone access for this site.',
   allowAudioAccessTitle: 'Please allow access to your microphone',
   aspectRatioLandscape: 'Crop landscape (16:9)',
   aspectRatioPortrait: 'Crop portrait (9:16)',
   aspectRatioSquare: 'Crop square',
   authAborted: 'Authentication aborted',
   authenticateWith: 'Connect to %{pluginName}',
-  authenticateWithTitle: 'Please authenticate with %{pluginName} to select files',
+  authenticateWithTitle:
+    'Please authenticate with %{pluginName} to select files',
   back: 'Back',
   browse: 'browse',
   browseFiles: 'browse files',
@@ -37,7 +44,8 @@ en_US.strings = {
   chooseFiles: 'Choose files',
   closeModal: 'Close Modal',
   companionError: 'Connection with Companion failed',
-  companionUnauthorizeHint: 'To unauthorize to your %{provider} account, please go to %{url}',
+  companionUnauthorizeHint:
+    'To unauthorize to your %{provider} account, please go to %{url}',
   complete: 'Complete',
   compressedX: 'Saved %{size} by compressing images',
   compressingImages: 'Compressing images...',
@@ -57,7 +65,8 @@ en_US.strings = {
   dropPasteBoth: 'Drop files here, %{browseFiles} or %{browseFolders}',
   dropPasteFiles: 'Drop files here or %{browseFiles}',
   dropPasteFolders: 'Drop files here or %{browseFolders}',
-  dropPasteImportBoth: 'Drop files here, %{browseFiles}, %{browseFolders} or import from:',
+  dropPasteImportBoth:
+    'Drop files here, %{browseFiles}, %{browseFolders} or import from:',
   dropPasteImportFiles: 'Drop files here, %{browseFiles} or import from:',
   dropPasteImportFolders: 'Drop files here, %{browseFolders} or import from:',
   editFile: 'Edit file',
@@ -65,12 +74,14 @@ en_US.strings = {
   editing: 'Editing %{file}',
   emptyFolderAdded: 'No files were added from empty folder',
   encoding: 'Encoding...',
-  enterCorrectUrl: 'Incorrect URL: Please make sure you are entering a direct link to a file',
+  enterCorrectUrl:
+    'Incorrect URL: Please make sure you are entering a direct link to a file',
   enterTextToSearch: 'Enter text to search for images',
   enterUrlToImport: 'Enter URL to import a file',
   error: 'Error',
   exceedsSize: '%{file} exceeds maximum allowed size of %{size}',
-  failedToFetch: 'Companion failed to fetch this URL, please make sure it’s correct',
+  failedToFetch:
+    'Companion failed to fetch this URL, please make sure it’s correct',
   failedToUpload: 'Failed to upload %{file}',
   filesUploadedOfTotal: {
     '0': '%{complete} of %{smart_count} file uploaded',
@@ -100,11 +111,14 @@ en_US.strings = {
     '1': 'Missing required meta fields: %{fields}.',
   },
   myDevice: 'My Device',
-  noAudioDescription: 'In order to record audio, please connect a microphone or another audio input device',
+  noAudioDescription:
+    'In order to record audio, please connect a microphone or another audio input device',
   noAudioTitle: 'Microphone Not Available',
-  noCameraDescription: 'In order to take pictures or record video, please connect a camera device',
+  noCameraDescription:
+    'In order to take pictures or record video, please connect a camera device',
   noCameraTitle: 'Camera Not Available',
-  noDuplicates: "Cannot add the duplicate file '%{fileName}', it already exists",
+  noDuplicates:
+    "Cannot add the duplicate file '%{fileName}', it already exists",
   noFilesFound: 'You have no files or folders here',
   noInternetConnection: 'No Internet connection',
   noMoreFilesAllowed: 'Cannot add more files',
@@ -129,7 +143,8 @@ en_US.strings = {
   },
   recording: 'Recording',
   recordingLength: 'Recording length %{recording_length}',
-  recordingStoppedMaxSize: 'Recording stopped because the file size is about to exceed the limit',
+  recordingStoppedMaxSize:
+    'Recording stopped because the file size is about to exceed the limit',
   recordVideoBtn: 'Record Video',
   recoveredAllFiles: 'We restored all files. You can now resume the upload.',
   recoveredXFiles: {
@@ -179,7 +194,8 @@ en_US.strings = {
     '1': 'Uploading %{smart_count} files',
   },
   uploadPaused: 'Upload paused',
-  uploadStalled: 'Upload has not made any progress for %{seconds} seconds. You may want to retry it.',
+  uploadStalled:
+    'Upload has not made any progress for %{seconds} seconds. You may want to retry it.',
   uploadXFiles: {
     '0': 'Upload %{smart_count} file',
     '1': 'Upload %{smart_count} files',
@@ -210,7 +226,10 @@ en_US.strings = {
   zoomOut: 'Zoom out',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.en_US = en_US
 }
 

+ 46 - 21
packages/@uppy/locales/src/es_ES.js → packages/@uppy/locales/src/es_ES.ts

@@ -1,5 +1,8 @@
-const es_ES = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const es_ES: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -14,20 +17,24 @@ es_ES.strings = {
   },
   addedNumFiles: 'Se agregó %{numFiles} archivo(s)',
   addingMoreFiles: 'Agregando más archivos',
-  additionalRestrictionsFailed: 'No se cumplieron %{count} restricciones adicionales',
+  additionalRestrictionsFailed:
+    'No se cumplieron %{count} restricciones adicionales',
   addMore: 'Agregar más',
   addMoreFiles: 'Agregar más archivos',
   allFilesFromFolderNamed: 'Todos los archivos de la carpeta %{name}',
-  allowAccessDescription: 'Para tomar fotos o grabar videos con tu cámara, por favor permite el acceso a la cámara para este sitio.',
+  allowAccessDescription:
+    'Para tomar fotos o grabar videos con tu cámara, por favor permite el acceso a la cámara para este sitio.',
   allowAccessTitle: 'Por favor, permite el acceso a tu cámara',
-  allowAudioAccessDescription: 'Para grabar audio, por favor permite el acceso al micrófono para este sitio.',
+  allowAudioAccessDescription:
+    'Para grabar audio, por favor permite el acceso al micrófono para este sitio.',
   allowAudioAccessTitle: 'Por favor, permite el acceso a tu micrófono',
   aspectRatioLandscape: 'Recortar horizontal (16:9)',
   aspectRatioPortrait: 'Recortar vertical (9:16)',
   aspectRatioSquare: 'Recortar cuadrado',
   authAborted: 'Autenticación cancelada',
   authenticateWith: 'Conectar con %{pluginName}',
-  authenticateWithTitle: 'Por favor, autentícate con %{pluginName} para seleccionar archivos',
+  authenticateWithTitle:
+    'Por favor, autentícate con %{pluginName} para seleccionar archivos',
   back: 'Atrás',
   browse: 'Navegar',
   browseFiles: 'Navegar por archivos',
@@ -37,7 +44,8 @@ es_ES.strings = {
   chooseFiles: 'Seleccionar archivos',
   closeModal: 'Cerrar ventana',
   companionError: 'Error en la conexión con Companion',
-  companionUnauthorizeHint: 'Para desautorizar tu cuenta de %{provider}, por favor ve a %{url}',
+  companionUnauthorizeHint:
+    'Para desautorizar tu cuenta de %{provider}, por favor ve a %{url}',
   complete: 'Completado',
   compressedX: 'Se ahorró %{size} comprimiendo imágenes',
   compressingImages: 'Comprimiendo imágenes...',
@@ -48,7 +56,8 @@ es_ES.strings = {
   creatingAssembly: 'Preparando subida...',
   creatingAssemblyFailed: 'No se pudo crear un Assembly',
   dashboardTitle: 'Cargador de archivos',
-  dashboardWindowTitle: 'Ventana para cargar archivos (Presiona escape para cerrar)',
+  dashboardWindowTitle:
+    'Ventana para cargar archivos (Presiona escape para cerrar)',
   dataUploadedOfTotal: '%{complete} de %{total}',
   discardRecordedFile: 'Descartar archivo grabado',
   done: 'Hecho',
@@ -57,20 +66,25 @@ es_ES.strings = {
   dropPasteBoth: 'Suelta archivos aquí, %{browseFiles} o %{browseFolders}',
   dropPasteFiles: 'Suelta archivos aquí o %{browseFiles}',
   dropPasteFolders: 'Suelta archivos aquí o %{browseFolders}',
-  dropPasteImportBoth: 'Suelta archivos aquí, %{browseFiles}, %{browseFolders} o importar desde:',
-  dropPasteImportFiles: 'Suelta archivos aquí, %{browseFiles} o importar desde:',
-  dropPasteImportFolders: 'Suelta archivos aquí, %{browseFolders} o importar desde:',
+  dropPasteImportBoth:
+    'Suelta archivos aquí, %{browseFiles}, %{browseFolders} o importar desde:',
+  dropPasteImportFiles:
+    'Suelta archivos aquí, %{browseFiles} o importar desde:',
+  dropPasteImportFolders:
+    'Suelta archivos aquí, %{browseFolders} o importar desde:',
   editFile: 'Editar archivo',
   editFileWithFilename: 'Editar archivo %{file}',
   editing: 'Editando %{file}',
   emptyFolderAdded: 'No se agregaron archivos desde la carpeta vacía',
   encoding: 'Codificando...',
-  enterCorrectUrl: 'URL incorrecta: Por favor, asegúrate de ingresar un enlace directo a un archivo',
+  enterCorrectUrl:
+    'URL incorrecta: Por favor, asegúrate de ingresar un enlace directo a un archivo',
   enterTextToSearch: 'Ingresa texto para buscar imágenes',
   enterUrlToImport: 'Ingresa la URL para importar un archivo',
   error: 'Error',
   exceedsSize: '%{file} excede el tamaño máximo permitido de %{size}',
-  failedToFetch: 'Companion no pudo recuperar esta URL, por favor asegúrate de que sea correcta',
+  failedToFetch:
+    'Companion no pudo recuperar esta URL, por favor asegúrate de que sea correcta',
   failedToUpload: 'No se pudo subir %{file}',
   fileSource: 'Fuente de archivo: %{name}',
   filesUploadedOfTotal: {
@@ -89,22 +103,27 @@ es_ES.strings = {
   import: 'Importar',
   importFiles: 'Importar archivos desde:',
   importFrom: 'Importar desde %{name}',
-  inferiorSize: 'Este archivo es más pequeño que el tamaño permitido de %{size}',
+  inferiorSize:
+    'Este archivo es más pequeño que el tamaño permitido de %{size}',
   loading: 'Cargando...',
   logOut: 'Cerrar sesión',
   micDisabled: 'El acceso al micrófono fue denegado por el usuario',
   missingRequiredMetaField: 'Faltan campos de metadatos obligatorios',
-  missingRequiredMetaFieldOnFile: 'Faltan campos de metadatos obligatorios en %{fileName}',
+  missingRequiredMetaFieldOnFile:
+    'Faltan campos de metadatos obligatorios en %{fileName}',
   missingRequiredMetaFields: {
     '0': 'Falta el campo de metadatos obligatorio: %{fields}.',
     '1': 'Faltan los campos de metadatos obligatorios: %{fields}.',
   },
   myDevice: 'Mi dispositivo',
-  noAudioDescription: 'Para grabar audio, por favor conecta un micrófono u otro dispositivo de entrada de audio',
+  noAudioDescription:
+    'Para grabar audio, por favor conecta un micrófono u otro dispositivo de entrada de audio',
   noAudioTitle: 'Micrófono no disponible',
-  noCameraDescription: 'Para tomar fotos o grabar video, por favor conecta un dispositivo de cámara',
+  noCameraDescription:
+    'Para tomar fotos o grabar video, por favor conecta un dispositivo de cámara',
   noCameraTitle: 'Cámara no disponible',
-  noDuplicates: "No se puede agregar el archivo duplicado '%{fileName}', ya existe",
+  noDuplicates:
+    "No se puede agregar el archivo duplicado '%{fileName}', ya existe",
   noFilesFound: 'No tienes archivos o carpetas aquí',
   noInternetConnection: 'Sin conexión a Internet',
   noMoreFilesAllowed: 'No se pueden agregar más archivos',
@@ -129,9 +148,11 @@ es_ES.strings = {
   },
   recording: 'Grabando',
   recordingLength: 'Duración de la grabación %{recording_length}',
-  recordingStoppedMaxSize: 'La grabación se detuvo porque el tamaño del archivo está a punto de exceder el límite',
+  recordingStoppedMaxSize:
+    'La grabación se detuvo porque el tamaño del archivo está a punto de exceder el límite',
   recordVideoBtn: 'Grabar video',
-  recoveredAllFiles: 'Se restauraron todos los archivos. Ahora puedes reanudar la subida.',
+  recoveredAllFiles:
+    'Se restauraron todos los archivos. Ahora puedes reanudar la subida.',
   recoveredXFiles: {
     '0': 'No pudimos recuperar completamente 1 archivo. Por favor, vuelve a seleccionarlo y reanuda la subida.',
     '1': 'No pudimos recuperar completamente %{smart_count} archivos. Por favor, vuelve a seleccionarlos y reanuda la subida.',
@@ -179,7 +200,8 @@ es_ES.strings = {
     '1': 'Subiendo %{smart_count} archivos',
   },
   uploadPaused: 'Subida en pausa',
-  uploadStalled: 'La subida no ha realizado ningún progreso durante %{seconds} segundos. Puedes intentarlo de nuevo.',
+  uploadStalled:
+    'La subida no ha realizado ningún progreso durante %{seconds} segundos. Puedes intentarlo de nuevo.',
   uploadXFiles: {
     '0': 'Subir %{smart_count} archivo',
     '1': 'Subir %{smart_count} archivos',
@@ -212,7 +234,10 @@ es_ES.strings = {
   unselectFileNamed: 'Deseleccionar archivo %{name}',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.es_ES = es_ES
 }
 

+ 48 - 25
packages/@uppy/locales/src/es_MX.js → packages/@uppy/locales/src/es_MX.ts

@@ -1,4 +1,14 @@
-const es_MX = {}
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const es_MX: Locale<0 | 1> = {
+  strings: {},
+  pluralize(count) {
+    if (count === 1) {
+      return 0
+    }
+    return 1
+  },
+}
 
 es_MX.strings = {
   addBulkFilesFailed: {
@@ -8,13 +18,15 @@ es_MX.strings = {
   addMore: 'Agregar más',
   addMoreFiles: 'Agregar más archivos',
   addingMoreFiles: 'Agregando más archivos',
-  allowAccessDescription: 'Para tomar fotos o grabar video con su cámara, por favor permita el acceso a la cámara para este sitio.',
+  allowAccessDescription:
+    'Para tomar fotos o grabar video con su cámara, por favor permita el acceso a la cámara para este sitio.',
   allowAccessTitle: 'Por favor permita el acceso a su cámara',
   aspectRatioLandscape: 'Recortar horizontal (16:9)',
   aspectRatioPortrait: 'Recortar vertical (9:16)',
   aspectRatioSquare: 'Recortar cuadrado',
   authenticateWith: 'Conectar a %{pluginName}',
-  authenticateWithTitle: 'Por favor autentíquese con %{pluginName} para seleccionar archivos',
+  authenticateWithTitle:
+    'Por favor autentíquese con %{pluginName} para seleccionar archivos',
   back: 'Atrás',
   backToSearch: 'Volver a buscar',
   browse: 'explorar',
@@ -25,7 +37,8 @@ es_MX.strings = {
   chooseFiles: 'Elegir archivos',
   closeModal: 'Cerrar ventana emergente',
   companionError: 'La conexión con Companion falló',
-  companionUnauthorizeHint: 'Para desautorizar su cuenta de %{provider}, por favor vaya a %{url}',
+  companionUnauthorizeHint:
+    'Para desautorizar su cuenta de %{provider}, por favor vaya a %{url}',
   complete: 'Completo',
   connectedToInternet: 'Conectado a Internet',
   copyLink: 'Copiar enlace',
@@ -34,7 +47,8 @@ es_MX.strings = {
   creatingAssembly: 'Preparando subida...',
   creatingAssemblyFailed: 'Transloadit: No se pudo crear el ensamblado',
   dashboardTitle: 'Cargador de archivos',
-  dashboardWindowTitle: 'Ventana de cargador de archivos (Presione escape para cerrar)',
+  dashboardWindowTitle:
+    'Ventana de cargador de archivos (Presione escape para cerrar)',
   dataUploadedOfTotal: '%{complete} de %{total}',
   discardRecordedFile: 'Descartar archivo grabado',
   done: 'Hecho',
@@ -43,19 +57,24 @@ es_MX.strings = {
   dropPasteBoth: 'Suelte archivos aquí, %{browseFiles} o %{browseFolders}',
   dropPasteFiles: 'Suelte archivos aquí o %{browseFiles}',
   dropPasteFolders: 'Suelte archivos aquí o %{browseFolders}',
-  dropPasteImportBoth: 'Suelte archivos aquí, %{browseFiles}, %{browseFolders} o importar desde:',
-  dropPasteImportFiles: 'Suelte archivos aquí, %{browseFiles} o importar desde:',
-  dropPasteImportFolders: 'Suelte archivos aquí, %{browseFolders} o importar desde:',
+  dropPasteImportBoth:
+    'Suelte archivos aquí, %{browseFiles}, %{browseFolders} o importar desde:',
+  dropPasteImportFiles:
+    'Suelte archivos aquí, %{browseFiles} o importar desde:',
+  dropPasteImportFolders:
+    'Suelte archivos aquí, %{browseFolders} o importar desde:',
   editFile: 'Editar archivo',
   editing: 'Editando %{file}',
   emptyFolderAdded: 'No se agregaron archivos desde la carpeta vacía',
   encoding: 'Codificando...',
-  enterCorrectUrl: 'URL incorrecta: Asegúrese de ingresar un enlace directo a un archivo',
+  enterCorrectUrl:
+    'URL incorrecta: Asegúrese de ingresar un enlace directo a un archivo',
   enterTextToSearch: 'Ingrese texto para buscar imágenes',
   enterUrlToImport: 'Ingrese URL para importar un archivo',
   exceedsSize: '%{file} excede el tamaño máximo permitido de',
   exceedsSize2: '%{backwardsCompat} %{size}',
-  failedToFetch: 'Companion no pudo obtener esta URL, asegúrese de que sea correcta',
+  failedToFetch:
+    'Companion no pudo obtener esta URL, asegúrese de que sea correcta',
   failedToUpload: 'Error al subir %{file}',
   fileSource: 'Fuente del archivo: %{name}',
   filesUploadedOfTotal: {
@@ -73,17 +92,21 @@ es_MX.strings = {
   import: 'Importar',
   importFiles: 'Importar archivos desde:',
   importFrom: 'Importar desde %{name}',
-  inferiorSize: 'Este archivo es más pequeño que el tamaño permitido de %{size}',
+  inferiorSize:
+    'Este archivo es más pequeño que el tamaño permitido de %{size}',
   loading: 'Cargando...',
   logOut: 'Cerrar sesión',
   micDisabled: 'Acceso al micrófono denegado por el usuario',
   myDevice: 'Mi dispositivo',
-  noCameraDescription: 'Para tomar fotos o grabar videos, conecte un dispositivo de cámara',
+  noCameraDescription:
+    'Para tomar fotos o grabar videos, conecte un dispositivo de cámara',
   noCameraTitle: 'Cámara no disponible',
-  noDuplicates: 'No se puede agregar el archivo duplicado \'%{fileName}\', ya existe',
+  noDuplicates:
+    "No se puede agregar el archivo duplicado '%{fileName}', ya existe",
   noFilesFound: 'No tiene archivos o carpetas aquí',
   noInternetConnection: 'Sin conexión a Internet',
-  noNewAlreadyUploading: 'No se pueden agregar nuevos archivos: ya se están subiendo',
+  noNewAlreadyUploading:
+    'No se pueden agregar nuevos archivos: ya se están subiendo',
   openFolderNamed: 'Abrir carpeta %{name}',
   pause: 'Pausar',
   pauseUpload: 'Pausar subida',
@@ -97,8 +120,10 @@ es_MX.strings = {
   reSelect: 'Volver a seleccionar',
   recording: 'Grabando',
   recordingLength: 'Duración de la grabación %{recording_length}',
-  recordingStoppedMaxSize: 'La grabación se detuvo porque el tamaño del archivo está a punto de exceder el límite',
-  recoveredAllFiles: 'Restauramos todos los archivos. Ahora puede reanudar la subida.',
+  recordingStoppedMaxSize:
+    'La grabación se detuvo porque el tamaño del archivo está a punto de exceder el límite',
+  recoveredAllFiles:
+    'Restauramos todos los archivos. Ahora puede reanudar la subida.',
   recoveredXFiles: {
     '0': 'No pudimos recuperar completamente 1 archivo. Vuelva a seleccionarlo y reanude la subida.',
     '1': 'No pudimos recuperar completamente %{smart_count} archivos. Vuelva a seleccionarlos y reanude la subida.',
@@ -114,7 +139,8 @@ es_MX.strings = {
   save: 'Guardar',
   saveChanges: 'Guardar cambios',
   searchImages: 'Buscar imágenes',
-  selectAllFilesFromFolderNamed: 'Seleccionar todos los archivos de la carpeta %{name}',
+  selectAllFilesFromFolderNamed:
+    'Seleccionar todos los archivos de la carpeta %{name}',
   selectFileNamed: 'Seleccionar archivo %{name}',
   selectX: {
     '0': 'Seleccionar %{smart_count}',
@@ -131,7 +157,8 @@ es_MX.strings = {
   submitRecordedFile: 'Enviar archivo grabado',
   takePicture: 'Tomar una foto',
   timedOut: 'Subida estancada durante %{seconds} segundos, abortando.',
-  unselectAllFilesFromFolderNamed: 'Deseleccionar todos los archivos de la carpeta %{name}',
+  unselectAllFilesFromFolderNamed:
+    'Deseleccionar todos los archivos de la carpeta %{name}',
   unselectFileNamed: 'Deseleccionar archivo %{name}',
   upload: 'Subir',
   uploadComplete: 'Subida completa',
@@ -172,14 +199,10 @@ es_MX.strings = {
   zoomOut: 'Alejar',
 }
 
-es_MX.pluralize = (count) => {
-  if (count === 1) {
-    return 0
-  }
-  return 1
-}
-
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.es_MX = es_MX
 }
 

+ 26 - 11
packages/@uppy/locales/src/fa_IR.js → packages/@uppy/locales/src/fa_IR.ts

@@ -1,5 +1,8 @@
-const fa_IR = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const fa_IR: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -21,7 +24,8 @@ fa_IR.strings = {
   allowAccessDescription:
     'برای گرفتن عکس یا ضبط ویدیو با دوربین خود، لطفاً اجازه دسترسی به دوربین را برای این سایت بدهید.',
   allowAccessTitle: 'لطفا به دوربین اجازه‌ی دسترسی بدهید',
-  allowAudioAccessDescription: 'برای ضبط صدا، لطفاً اجازه دسترسی به میکروفون را برای این سایت بدهید.',
+  allowAudioAccessDescription:
+    'برای ضبط صدا، لطفاً اجازه دسترسی به میکروفون را برای این سایت بدهید.',
   allowAudioAccessTitle: 'لطفا اجازه دسترسی به میکروفون خود را بدهید',
   aspectRatioLandscape: 'برش منظره (16:9)',
   aspectRatioPortrait: 'برش پرتره (9:16)',
@@ -38,7 +42,8 @@ fa_IR.strings = {
   chooseFiles: 'انتخاب فایل',
   closeModal: 'بستن پنجره',
   companionError: 'اتصال با طرق مقابل با شکست روبرو شد',
-  companionUnauthorizeHint: 'برای قطع احراز هویت حساب %{provider}, لطفا به آدرس %{url} بروید',
+  companionUnauthorizeHint:
+    'برای قطع احراز هویت حساب %{provider}, لطفا به آدرس %{url} بروید',
   complete: 'کامل شد',
   compressedX: '%{size} با فشرده‌سازی تصاویر ذخیره شد',
   compressingImages: 'فشرده سازی تصاویر ...',
@@ -66,12 +71,14 @@ fa_IR.strings = {
   editing: 'در حال ویرایش %{file}',
   emptyFolderAdded: 'از پوشه‌ی خالی هیچ فایلی افزوده نشد',
   encoding: 'رمزگذاری...',
-  enterCorrectUrl: 'آدرس نامعتبر. لطفا مطمئن شوید که آدرس مستقیم به یک فایل را انتخاب کرده‌اید.',
+  enterCorrectUrl:
+    'آدرس نامعتبر. لطفا مطمئن شوید که آدرس مستقیم به یک فایل را انتخاب کرده‌اید.',
   enterTextToSearch: 'متن را جهت جستجوی تصویر وارد کنید',
   enterUrlToImport: 'آدرس فایل را برای بارگذاری بنویسید',
   error: 'خطا',
   exceedsSize: 'اندازه‌ی این فایل از حد مجاز بیشتر است! %{size}',
-  failedToFetch: 'Companion نتوانست این URL را واکشی کند، لطفاً مطمئن شوید که درست است',
+  failedToFetch:
+    'Companion نتوانست این URL را واکشی کند، لطفاً مطمئن شوید که درست است',
   failedToUpload: 'شکست در بارگذاری %{file}',
   filesUploadedOfTotal: {
     '0': '%{complete} از %{smart_count} فایل بارگذاری شد.',
@@ -101,11 +108,13 @@ fa_IR.strings = {
     '1': 'فیلدهای متا لازم وجود ندارد: %{fields}.',
   },
   myDevice: 'دستگاه من',
-  noAudioDescription: 'برای ضبط صدا، لطفاً یک میکروفون یا دستگاه ورودی صوتی دیگری را وصل کنید',
+  noAudioDescription:
+    'برای ضبط صدا، لطفاً یک میکروفون یا دستگاه ورودی صوتی دیگری را وصل کنید',
   noAudioTitle: 'میکروفون در دسترس نیست',
   noCameraDescription: 'جهت گرفتن عکس یا ضبط ویدیو لطفا یک دوربین متصل نمایید',
   noCameraTitle: 'دوربین در دسترس نیست',
-  noDuplicates: "نمی‌توان فایل تکراری بارگذاری کرد،'%{fileName}' قبلا بارگذاری شده است.",
+  noDuplicates:
+    "نمی‌توان فایل تکراری بارگذاری کرد،'%{fileName}' قبلا بارگذاری شده است.",
   noFilesFound: 'هیچ فایل یا پوشه‌ای اینجا ندارید',
   noInternetConnection: 'عدم اتصال به اینترنت',
   noMoreFilesAllowed: 'نمی توان فایل جدید بارگذاری کرد',
@@ -130,9 +139,11 @@ fa_IR.strings = {
   },
   recording: 'درحال ضبط',
   recordingLength: 'مدت ضبط شده %{recording_length}',
-  recordingStoppedMaxSize: 'ضبط به دلیل رسیدن اندازه فایل به حدود حداکثر اندازه مجاز متوقف شد',
+  recordingStoppedMaxSize:
+    'ضبط به دلیل رسیدن اندازه فایل به حدود حداکثر اندازه مجاز متوقف شد',
   recordVideoBtn: 'ضبط تصویر',
-  recoveredAllFiles: 'ما همه فایل‌ها را بازیابی کردیم. اکنون می توانید بارگذاری را از سر بگیرید.',
+  recoveredAllFiles:
+    'ما همه فایل‌ها را بازیابی کردیم. اکنون می توانید بارگذاری را از سر بگیرید.',
   recoveredXFiles: {
     '0': 'امکان بازیابی %{smart_count} فایل وجود ندارد. لطفا مجددا انتخابش کنید و بارگذاری را ازسر بگیرید.',
     '1': 'امکان بازیابی %{smart_count} فایل‌ها وجود ندارد. لطفا مجددا انتخابش کنید و بارگذاری را ازسر بگیرید.',
@@ -180,7 +191,8 @@ fa_IR.strings = {
     '1': 'بارگذاری %{smart_count} فایل',
   },
   uploadPaused: 'بارگذاری متوقف شد',
-  uploadStalled: 'آپلود برای %{seconds} ثانیه هیچ پیشرفتی نداشته است. ممکن است بخواهید دوباره آن را امتحان کنید.',
+  uploadStalled:
+    'آپلود برای %{seconds} ثانیه هیچ پیشرفتی نداشته است. ممکن است بخواهید دوباره آن را امتحان کنید.',
   uploadXNewFiles: {
     '0': 'بارگذاری +%{smart_count} فایل',
     '1': 'بارگذاری +%{smart_count} فایل',
@@ -211,7 +223,10 @@ fa_IR.strings = {
   zoomOut: 'کوچک‌نمایی',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.fa_IR = fa_IR
 }
 export default fa_IR

+ 16 - 17
packages/@uppy/locales/src/fi_FI.js → packages/@uppy/locales/src/fi_FI.ts

@@ -1,5 +1,8 @@
-const fi_FI = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const fi_FI: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -11,10 +14,12 @@ fi_FI.strings = {
   addMore: 'Lisää',
   addMoreFiles: 'Lisää tiedostoja',
   addingMoreFiles: 'Lisätään tiedostoja',
-  allowAccessDescription: 'Jotta voit lähettää kuvia tai videota kamerastasi, sinun tulee antaa tälle sivustolle oikeus käyttää kameraasi.',
+  allowAccessDescription:
+    'Jotta voit lähettää kuvia tai videota kamerastasi, sinun tulee antaa tälle sivustolle oikeus käyttää kameraasi.',
   allowAccessTitle: 'Salli kameran käyttö, kiitos',
   authenticateWith: 'Mene %{pluginName}',
-  authenticateWithTitle: '%{pluginName} vaadittu tunnistautumiseen, jotta voit valita tiedostoja',
+  authenticateWithTitle:
+    '%{pluginName} vaadittu tunnistautumiseen, jotta voit valita tiedostoja',
   back: 'Takaisin',
   browse: 'selaa',
   browseFiles: 'selaa',
@@ -46,23 +51,23 @@ fi_FI.strings = {
   editing: 'Muokataan %{file}',
   emptyFolderAdded: 'Ei lisätty tiedostoja tyhjästä kansiosta',
   encoding: 'Koodataan...',
-  enterCorrectUrl: 'Epäkelpo osoite: Varmista, että osoite osoittaa suoraan tiedostoon',
+  enterCorrectUrl:
+    'Epäkelpo osoite: Varmista, että osoite osoittaa suoraan tiedostoon',
   enterUrlToImport: 'Anna osoite tuodaksesi tiedoston',
   exceedsSize: 'Tiedoston koko ylittää sallitun maksimin %{size}',
-  failedToFetch: 'Companion ei voinut ladata tiedostoa osoitteesta, onko osoite varmasti oikea?',
+  failedToFetch:
+    'Companion ei voinut ladata tiedostoa osoitteesta, onko osoite varmasti oikea?',
   failedToUpload: 'Ei voitu lähettää tiedostoa %{file}',
   fileSource: 'Tiedoston lähde: %{name}',
   filesUploadedOfTotal: {
     '0': '%{complete} / %{smart_count} tiedostosta lähetetty',
     '1': '%{complete} / %{smart_count} tiedostoa lähetetty',
-    '2': '%{complete} / %{smart_count} tiedostoa lähetetty',
   },
   filter: 'Suodata',
   finishEditingFile: 'Lopeta tiedoston muokkaus',
   folderAdded: {
     '0': 'Lisätty %{smart_count} tiedosto kansiosta %{folder}',
     '1': 'Lisätty %{smart_count} tiedostoa kansiosta %{folder}',
-    '2': 'Lisätty %{smart_count} tiedostoa kansiosta %{folder}',
   },
   import: 'Tuo',
   importFrom: 'Tuo %{name}',
@@ -79,7 +84,6 @@ fi_FI.strings = {
   processingXFiles: {
     '0': 'Käsitellään %{smart_count} tiedostoa',
     '1': 'Käsitellään %{smart_count} tiedostoa',
-    '2': 'Käsitellään %{smart_count} tiedostoa',
   },
   removeFile: 'Poista tiedosto',
   resetFilter: 'Resetoi suodatin',
@@ -92,7 +96,6 @@ fi_FI.strings = {
   selectX: {
     '0': 'Valitse %{smart_count}',
     '1': 'Valitse %{smart_count}',
-    '2': 'Valitse %{smart_count}',
   },
   smile: 'Hymyile!',
   startRecording: 'Aloita videon tallennus',
@@ -107,40 +110,33 @@ fi_FI.strings = {
   uploadXFiles: {
     '0': 'Lähetä %{smart_count} tiedosto',
     '1': 'Lähetä %{smart_count} tiedostoa',
-    '2': 'Lähetä %{smart_count} tiedostoa',
   },
   uploadXNewFiles: {
     '0': 'Lähetä +%{smart_count} tiedosto',
     '1': 'Lähetä +%{smart_count} tiedostoa',
-    '2': 'Lähetä +%{smart_count} tiedostoa',
   },
   uploading: 'Lähetetään',
   uploadingXFiles: {
     '0': 'Lähetetään %{smart_count} tiedosto',
     '1': 'Lähetetään %{smart_count} tiedostoa',
-    '2': 'Lähetetään %{smart_count} tiedostoa',
   },
   xFilesSelected: {
     '0': '%{smart_count} tiedosto valittu',
     '1': '%{smart_count} tiedostoa valittu',
-    '2': '%{smart_count} tiedostoa valittu',
   },
   xMoreFilesAdded: {
     '0': '%{smart_count} tiedosto added',
     '1': '%{smart_count} tiedostoa added',
-    '2': '%{smart_count} tiedostoa added',
   },
   xTimeLeft: '%{time} jäljellä',
   youCanOnlyUploadFileTypes: 'Sallitut tiedostomuodot: %{types}',
   youCanOnlyUploadX: {
     '0': 'Voit lähettää vain %{smart_count} tiedosto',
     '1': 'Voit lähettää vain %{smart_count} tiedostoa',
-    '2': 'Voit lähettää vain %{smart_count} tiedostoa',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Sinun pitää valita vähintään %{smart_count} tiedosto',
     '1': 'Sinun pitää valita vähintään %{smart_count} tiedostoa',
-    '2': 'Sinun pitää valita vähintään %{smart_count} tiedostoa',
   },
   startCapturing: 'Aloita tallennus',
   stopCapturing: 'Lopeta tallennus',
@@ -151,7 +147,10 @@ fi_FI.strings = {
   recording: 'Tallennetaan',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.fi_FI = fi_FI
 }
 

+ 32 - 14
packages/@uppy/locales/src/fr_FR.js → packages/@uppy/locales/src/fr_FR.ts

@@ -1,5 +1,8 @@
-const fr_FR = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const fr_FR: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n <= 1) {
       return 0
     }
@@ -17,11 +20,13 @@ fr_FR.strings = {
   addMore: 'Ajouter d’autres',
   addMoreFiles: 'Ajouter d’autres fichiers',
   allFilesFromFolderNamed: 'Tous les fichiers du dossier %{name}',
-  allowAccessDescription: 'Pour prendre des photos ou enregistrer une vidéo, veuillez autoriser l’accès à votre caméra pour ce site.',
+  allowAccessDescription:
+    'Pour prendre des photos ou enregistrer une vidéo, veuillez autoriser l’accès à votre caméra pour ce site.',
   allowAccessTitle: 'Veuillez autoriser l’accès à votre caméra',
   authAborted: 'Authentification interrompue',
   authenticateWith: 'Se connecter à %{pluginName}',
-  authenticateWithTitle: 'Veuillez vous authentifier avec %{pluginName} pour sélectionner les fichiers',
+  authenticateWithTitle:
+    'Veuillez vous authentifier avec %{pluginName} pour sélectionner les fichiers',
   back: 'Retour',
   browse: 'naviguer',
   browseFiles: 'naviguer',
@@ -30,7 +35,8 @@ fr_FR.strings = {
   chooseFiles: 'Choisir des fichiers',
   closeModal: 'Fermer la fenêtre',
   companionError: 'Connexion à Companion a échoué',
-  companionUnauthorizeHint: 'Pour vous déconnecter de votre compte %{provider}, veuillez aller à %{url}',
+  companionUnauthorizeHint:
+    'Pour vous déconnecter de votre compte %{provider}, veuillez aller à %{url}',
   complete: 'Terminé',
   compressedX: '%{size} économisé(s) par la compression',
   compressingImages: 'Compression des images…',
@@ -41,7 +47,8 @@ fr_FR.strings = {
   creatingAssembly: 'Préparation du téléversement…',
   creatingAssemblyFailed: 'Transloadit: Impossible de créer Assembly',
   dashboardTitle: 'Téléverseur de fichiers',
-  dashboardWindowTitle: 'Fenêtre de téléversement de fichiers (Appuyez sur Échap pour fermer)',
+  dashboardWindowTitle:
+    'Fenêtre de téléversement de fichiers (Appuyez sur Échap pour fermer)',
   dataUploadedOfTotal: '%{complete} sur %{total}',
   done: 'Terminé',
   dropHereOr: 'Déposer les fichiers ici ou %{browse}',
@@ -49,18 +56,23 @@ fr_FR.strings = {
   dropPasteBoth: 'Déposer les fichiers ici, coller ou %{browse}',
   dropPasteFiles: 'Déposer les fichiers ici, coller ou %{browse}',
   dropPasteFolders: 'Déposer les fichiers ici, coller ou %{browse}',
-  dropPasteImportBoth: 'Déposer les fichiers ici, coller, %{browse} ou importer de',
-  dropPasteImportFiles: 'Déposer les fichiers ici, coller, %{browse} ou importer de',
-  dropPasteImportFolders: 'Déposer les fichiers ici, coller, %{browse} ou importer de',
+  dropPasteImportBoth:
+    'Déposer les fichiers ici, coller, %{browse} ou importer de',
+  dropPasteImportFiles:
+    'Déposer les fichiers ici, coller, %{browse} ou importer de',
+  dropPasteImportFolders:
+    'Déposer les fichiers ici, coller, %{browse} ou importer de',
   editFile: 'Modifier le fichier',
   editFileWithFilename: 'Modifier le fichier %{file}',
   editing: 'Modification en cours de %{file}',
   emptyFolderAdded: 'Aucun fichier n’a été ajouté depuis un dossier vide',
   encoding: 'Traitement…',
-  enterCorrectUrl: 'Lien incorrect: Assurez-vous que vous entrez un lien direct vers le fichier',
+  enterCorrectUrl:
+    'Lien incorrect: Assurez-vous que vous entrez un lien direct vers le fichier',
   enterUrlToImport: 'Entrez le lien pour importer un fichier',
   exceedsSize: 'Ce fichier dépasse la taille maximale autorisée de %{size}',
-  failedToFetch: 'Companion a échoué à récupérer ce lien, assurez-vous qu’il est correct',
+  failedToFetch:
+    'Companion a échoué à récupérer ce lien, assurez-vous qu’il est correct',
   failedToUpload: 'Le téléversement de %{file} a échoué',
   fileSource: 'Fichier source: %{name}',
   filesUploadedOfTotal: {
@@ -83,7 +95,8 @@ fr_FR.strings = {
   noDuplicates: 'Impossible d’ajouter le fichier "%{fileName}", il existe déjà',
   noFilesFound: 'Vous n’avez aucun fichier ou dossier ici',
   noInternetConnection: 'Pas de connexion à Internet',
-  noMoreFilesAllowed: 'Impossible d’ajouter de nouveaux fichiers: en cours de chargement ',
+  noMoreFilesAllowed:
+    'Impossible d’ajouter de nouveaux fichiers: en cours de chargement ',
   openFolderNamed: 'Ouvrir %{name}',
   pause: 'Pause',
   pauseUpload: 'Mettre en pause le téléversement',
@@ -95,7 +108,8 @@ fr_FR.strings = {
   },
   recording: 'Enregistrement',
   recordingLength: 'Durée d’enregistrement %{recording_length}',
-  recordingStoppedMaxSize: 'L’enregistrement s’est arrété car la taille du fichier dépasse la limite',
+  recordingStoppedMaxSize:
+    'L’enregistrement s’est arrété car la taille du fichier dépasse la limite',
   removeFile: 'Effacer le fichier %{file}',
   resetFilter: 'Réinitialiser filtre',
   resume: 'Reprendre',
@@ -122,7 +136,8 @@ fr_FR.strings = {
   uploadComplete: 'Téléversement terminé',
   uploadFailed: 'Le téléversement a échoué',
   uploadPaused: 'Téléversement mis en pause',
-  uploadStalled: 'Téléversement bloqué depuis %{seconds} secondes. Il est peut-être nécessaire de recommencer l’opération.',
+  uploadStalled:
+    'Téléversement bloqué depuis %{seconds} secondes. Il est peut-être nécessaire de recommencer l’opération.',
   uploadXFiles: {
     '0': 'Téléverser %{smart_count} fichier',
     '1': 'Téléverser %{smart_count} fichiers',
@@ -156,7 +171,10 @@ fr_FR.strings = {
   },
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.fr_FR = fr_FR
 }
 

+ 24 - 21
packages/@uppy/locales/src/gl_ES.js → packages/@uppy/locales/src/gl_ES.ts

@@ -1,5 +1,8 @@
-const gl_ES = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const gl_ES: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -11,10 +14,12 @@ gl_ES.strings = {
   addMore: 'Engadir máis',
   addMoreFiles: 'Engadir máis arquivos',
   addingMoreFiles: 'Engadir máis arquivos',
-  allowAccessDescription: 'Para tomar fotos ou grabar video coa túa cámara, por favor permite a este sitio o acceso á cámara.',
+  allowAccessDescription:
+    'Para tomar fotos ou grabar video coa túa cámara, por favor permite a este sitio o acceso á cámara.',
   allowAccessTitle: 'Por favor permite o acceso á tua cámara',
   authenticateWith: 'Conectar a %{pluginName}',
-  authenticateWithTitle: 'Por favor autentícate con %{pluginName} para seleccionar arquivos',
+  authenticateWithTitle:
+    'Por favor autentícate con %{pluginName} para seleccionar arquivos',
   back: 'Atrás',
   browse: 'navegar',
   browseFiles: 'navegar',
@@ -31,7 +36,8 @@ gl_ES.strings = {
   creatingAssembly: 'Preparando subida...',
   creatingAssemblyFailed: 'Transloadit: Non se puido crear un Assembly',
   dashboardTitle: 'Cargador de arquivos',
-  dashboardWindowTitle: 'Xanela para cargar arquivos (Presiona escape para cerrar)',
+  dashboardWindowTitle:
+    'Xanela para cargar arquivos (Presiona escape para cerrar)',
   dataUploadedOfTotal: '%{complete} de %{total}',
   done: 'Feito',
   dropHereOr: 'Soltar arquivos aquí ou %{browse}',
@@ -39,30 +45,33 @@ gl_ES.strings = {
   dropPasteBoth: 'Soltar arquivos aquí, pegar ou %{browse}',
   dropPasteFiles: 'Soltar arquivos aquí, pegar ou %{browse}',
   dropPasteFolders: 'Soltar arquivos aquí, pegar ou %{browse}',
-  dropPasteImportBoth: 'Soltar arquivos aquí, pegar, %{browse} ou importar dende',
-  dropPasteImportFiles: 'Soltar arquivos aquí, pegar, %{browse} ou importar dende',
-  dropPasteImportFolders: 'Soltar arquivos aquí, pegar, %{browse} ou importar dende',
+  dropPasteImportBoth:
+    'Soltar arquivos aquí, pegar, %{browse} ou importar dende',
+  dropPasteImportFiles:
+    'Soltar arquivos aquí, pegar, %{browse} ou importar dende',
+  dropPasteImportFolders:
+    'Soltar arquivos aquí, pegar, %{browse} ou importar dende',
   editFile: 'Editar arquivo',
   editing: 'Editando %{file}',
   emptyFolderAdded: 'Ningún arquivo foi agregado dende o cartafol vacía',
   encoding: 'Codificando...',
-  enterCorrectUrl: 'URL incorrecta: Por favor asegúrate que estás ingresando un enlace a un arquivo',
+  enterCorrectUrl:
+    'URL incorrecta: Por favor asegúrate que estás ingresando un enlace a un arquivo',
   enterUrlToImport: 'Ingresa unha URL para importar un arquivo',
   exceedsSize: 'Este arquivo excede el tamaño máximo de %{size}',
-  failedToFetch: 'Companion non puido recuperar esta URL, por favor asegúrate que sexa correcta',
+  failedToFetch:
+    'Companion non puido recuperar esta URL, por favor asegúrate que sexa correcta',
   failedToUpload: 'Error ao subir %{file}',
   fileSource: 'Fonte de arquivo: %{name}',
   filesUploadedOfTotal: {
     '0': '%{complete} de %{smart_count} arquivo subido',
     '1': '%{complete} de %{smart_count} arquivos subidos',
-    '2': '%{complete} de %{smart_count} arquivos subidos',
   },
   filter: 'Filtrar',
   finishEditingFile: 'Rematar edición de arquivo',
   folderAdded: {
     '0': 'Engadido %{smart_count} arquivo dende %{folder}',
     '1': 'Engadidos %{smart_count} arquivos dende %{folder}',
-    '2': 'Engadidos %{smart_count} arquivos dende %{folder}',
   },
   import: 'Importar',
   importFrom: 'Importar dende %{name}',
@@ -78,7 +87,6 @@ gl_ES.strings = {
   processingXFiles: {
     '0': 'Procesando %{smart_count} arquivo',
     '1': 'Procesando %{smart_count} arquivos',
-    '2': 'Procesando %{smart_count} arquivos',
   },
   removeFile: 'Eliminar arquivo',
   resetFilter: 'Limpar filtro',
@@ -90,7 +98,6 @@ gl_ES.strings = {
   selectX: {
     '0': 'Seleccionar %{smart_count}',
     '1': 'Seleccionar %{smart_count}',
-    '2': 'Seleccionar %{smart_count}',
   },
   smile: 'Sorrí!',
   startRecording: 'Comezar a grabación de vídeo',
@@ -104,47 +111,43 @@ gl_ES.strings = {
   uploadXFiles: {
     '0': 'Subir %{smart_count} arquivo',
     '1': 'Subir %{smart_count} arquivos',
-    '2': 'Subir %{smart_count} arquivos',
   },
   uploadXNewFiles: {
     '0': 'Subir +%{smart_count} arquivo',
     '1': 'Subir +%{smart_count} arquivos',
-    '2': 'Subir +%{smart_count} arquivos',
   },
   uploading: 'Subindo',
   uploadingXFiles: {
     '0': 'Subindo %{smart_count} arquivo',
     '1': 'Subindo %{smart_count} arquivos',
-    '2': 'Subindo %{smart_count} arquivos',
   },
   xFilesSelected: {
     '0': '%{smart_count} arquivo seleccionado',
     '1': '%{smart_count} arquivos seleccionados',
-    '2': '%{smart_count} arquivos seleccionados',
   },
   xMoreFilesAdded: {
     '0': '%{smart_count} arquivo máis engadido',
     '1': '%{smart_count} arquivos máis engadidos',
-    '2': '%{smart_count} arquivos máis engadidos',
   },
   xTimeLeft: '%{time} restantes',
   youCanOnlyUploadFileTypes: 'Soamente podes subir: %{types}',
   youCanOnlyUploadX: {
     '0': 'Soamente podes subir %{smart_count} arquivo',
     '1': 'Soamente podes subir %{smart_count} arquivos',
-    '2': 'Soamente podes subir %{smart_count} arquivos',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Tes que seleccionar polo menos %{smart_count} arquivo',
     '1': 'Tes que seleccionar polo menos %{smart_count} arquivos',
-    '2': 'Tes que seleccionar polo menos %{smart_count} arquivos',
   },
   selectFileNamed: 'Seleccione arquivo %{name}',
   unselectFileNamed: 'Deseleccionar arquivo %{name}',
   openFolderNamed: 'Cartafol aberto %{name}',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.gl_ES = gl_ES
 }
 

+ 12 - 15
packages/@uppy/locales/src/he_IL.js → packages/@uppy/locales/src/he_IL.ts

@@ -1,5 +1,8 @@
-const he_IL = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const he_IL: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -11,7 +14,8 @@ he_IL.strings = {
   addMore: 'הוסף עוד',
   addMoreFiles: 'הוסף עוד קבצים',
   addingMoreFiles: 'מוסיף עוד קבצים',
-  allowAccessDescription: 'על מנת לצלם תמונה או להקליט ווידאו עם המצלמה, בבקשה אפשר גישה למצלמה באתר זה.',
+  allowAccessDescription:
+    'על מנת לצלם תמונה או להקליט ווידאו עם המצלמה, בבקשה אפשר גישה למצלמה באתר זה.',
   allowAccessTitle: 'אנא אפשר גישה למצלמה',
   authenticateWith: 'התחבר ל %{pluginName}',
   authenticateWithTitle: 'אנא בצע הזדהות עם %{pluginName} על מנת לבחור קבצים',
@@ -23,7 +27,8 @@ he_IL.strings = {
   chooseFiles: 'בחר קבצים',
   closeModal: 'חלון',
   companionError: 'הזדהות מול השירות נכשלה',
-  companionUnauthorizeHint: 'על מנת לבטל הזדהות חשבון %{provider}, אנא גלוש ל %{url}',
+  companionUnauthorizeHint:
+    'על מנת לבטל הזדהות חשבון %{provider}, אנא גלוש ל %{url}',
   complete: 'הסתיים',
   connectedToInternet: 'מחובר לאינטרנט',
   copyLink: 'העתק קישור',
@@ -56,14 +61,12 @@ he_IL.strings = {
   filesUploadedOfTotal: {
     '0': 'קובץ %{complete} מתוך %{smart_count} הועלה',
     '1': '%{complete} מתוך %{smart_count} קבצים הועלו',
-    '2': '%{complete} מתוך %{smart_count} קבצים הועלו',
   },
   filter: 'סינון',
   finishEditingFile: 'סיים לעדכן את הקובץ',
   folderAdded: {
     '0': 'נוסף קובץ %{smart_count} מ %{folder}',
     '1': 'נוספו %{smart_count} קבצים מ %{folder}',
-    '2': 'נוספו %{smart_count} קבצים מ %{folder}',
   },
   generatingThumbnails: 'יוצר תמונות ממוזערות...',
   import: 'ייבוא',
@@ -81,7 +84,6 @@ he_IL.strings = {
   processingXFiles: {
     '0': 'מעבד קובץ %{smart_count}',
     '1': 'מעבד %{smart_count} קבצים',
-    '2': 'מעבד %{smart_count} קבצים',
   },
   removeFile: 'מחק קובץ',
   resetFilter: 'אפס סינון',
@@ -94,7 +96,6 @@ he_IL.strings = {
   selectX: {
     '0': 'בחר %{smart_count}',
     '1': 'בחר %{smart_count}',
-    '2': 'בחר %{smart_count}',
   },
   smile: 'Smile!',
   startRecording: 'מתחיל הסרטת ווידאו',
@@ -109,44 +110,40 @@ he_IL.strings = {
   uploadXFiles: {
     '0': 'העלה קובץ %{smart_count}',
     '1': 'העלה %{smart_count} קבצים',
-    '2': 'העלה %{smart_count} קבצים',
   },
   uploadXNewFiles: {
     '0': 'העלה קובץ +%{smart_count}',
     '1': 'העלה +%{smart_count} קבצים',
-    '2': 'העלה +%{smart_count} קבצים',
   },
   uploading: 'Uploading',
   uploadingXFiles: {
     '0': 'מעלה קובץ %{smart_count}',
     '1': 'מעלה %{smart_count} קבצים',
-    '2': 'מעלה %{smart_count} קבצים',
   },
   xFilesSelected: {
     '0': 'קובץ %{smart_count} נבחר',
     '1': '%{smart_count} קבצים נבחרו',
-    '2': '%{smart_count} קבצים נבחרו',
   },
   xMoreFilesAdded: {
     '0': 'עוד %{smart_count} קובץ נוסף',
     '1': 'עוד %{smart_count} קבצים נוספו',
-    '2': 'עוד %{smart_count} קבצים נוספו',
   },
   xTimeLeft: '%{time} left',
   youCanOnlyUploadFileTypes: 'You can only upload: %{types}',
   youCanOnlyUploadX: {
     '0': 'ניתן העלות רק קובץ %{smart_count}',
     '1': 'ניתן להעלות רק %{smart_count} קבצים',
-    '2': 'ניתן להעלות רק %{smart_count} קבצים',
   },
   youHaveToAtLeastSelectX: {
     '0': 'עליך לבחור לפחות בקובץ %{smart_count}',
     '1': 'עליך לבחור לפחות ב %{smart_count} קבצים',
-    '2': 'עליך לבחור לפחות ב %{smart_count} קבצים',
   },
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.he_IL = he_IL
 }
 

+ 14 - 8
packages/@uppy/locales/src/hi_IN.js → packages/@uppy/locales/src/hi_IN.ts

@@ -1,4 +1,14 @@
-const hi_IN = {}
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const hi_IN: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
+    if (n === 1) {
+      return 0
+    }
+    return 1
+  },
+}
 
 hi_IN.strings = {
   addBulkFilesFailed: {
@@ -185,14 +195,10 @@ hi_IN.strings = {
   zoomOut: 'ज़ूम आउट',
 }
 
-hi_IN.pluralize = (count) => {
-  if (count === 1) {
-    return 0
-  }
-  return 1
-}
-
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.hi_IN = hi_IN
 }
 

+ 22 - 20
packages/@uppy/locales/src/hr_HR.js → packages/@uppy/locales/src/hr_HR.ts

@@ -1,5 +1,8 @@
-const hr_HR = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const hr_HR: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -11,10 +14,12 @@ hr_HR.strings = {
   addMore: 'Dodaj još',
   addMoreFiles: 'Dodaj još datoteka',
   addingMoreFiles: 'Dodavanje datoteka',
-  allowAccessDescription: 'Molimo Vas, dozvolite pristup Vašoj kameri kako biste je mogli koristiti za snimanje fotografija i video zapisa.',
+  allowAccessDescription:
+    'Molimo Vas, dozvolite pristup Vašoj kameri kako biste je mogli koristiti za snimanje fotografija i video zapisa.',
   allowAccessTitle: 'Molimo Vas dozvolite pristup Vašoj kameri',
   authenticateWith: 'Poveži se putem %{pluginName}',
-  authenticateWithTitle: 'Molimo Vas da se prijavite putem %{pluginName} kako biste preuzeli datoteke',
+  authenticateWithTitle:
+    'Molimo Vas da se prijavite putem %{pluginName} kako biste preuzeli datoteke',
   back: 'Natrag',
   browse: 'pretraži',
   browseFiles: 'pretraži',
@@ -39,9 +44,12 @@ hr_HR.strings = {
   dropPasteBoth: 'Ispusti datoteke ovdje, zalijepi ili %{browse}',
   dropPasteFiles: 'Ispusti datoteke ovdje, zalijepi ili %{browse}',
   dropPasteFolders: 'Ispusti datoteke ovdje, zalijepi ili %{browse}',
-  dropPasteImportBoth: 'Ispusti datoteke ovdje, zalijepi (eng. "paste"), %{browse} ili preuzmi s',
-  dropPasteImportFiles: 'Ispusti datoteke ovdje, zalijepi (eng. "paste"), %{browse} ili preuzmi s',
-  dropPasteImportFolders: 'Ispusti datoteke ovdje, zalijepi (eng. "paste"), %{browse} ili preuzmi s',
+  dropPasteImportBoth:
+    'Ispusti datoteke ovdje, zalijepi (eng. "paste"), %{browse} ili preuzmi s',
+  dropPasteImportFiles:
+    'Ispusti datoteke ovdje, zalijepi (eng. "paste"), %{browse} ili preuzmi s',
+  dropPasteImportFolders:
+    'Ispusti datoteke ovdje, zalijepi (eng. "paste"), %{browse} ili preuzmi s',
   editFile: 'Izmijeni datoteku',
   editing: 'Uredi %{file}',
   emptyFolderAdded: 'Ni jedna datoteka nije dodana iz prazne mape',
@@ -49,20 +57,19 @@ hr_HR.strings = {
   enterCorrectUrl: 'Pogrešan URL: unesite točnu putanju do datoteke',
   enterUrlToImport: 'Unesite URL do datoteke',
   exceedsSize: 'Ova datoteka premašuje najveću dozvoljenu veličinu od %{size}',
-  failedToFetch: 'Companion nije uspio dohvatiti traženi URL, provjerite ispravnost adrese',
+  failedToFetch:
+    'Companion nije uspio dohvatiti traženi URL, provjerite ispravnost adrese',
   failedToUpload: 'Broj neuspješno prenesenih datoteka: %{file}',
   fileSource: 'Datoteka: %{name}',
   filesUploadedOfTotal: {
     '0': '%{complete}. Ukupno prenesenih datoteka: %{smart_count}',
     '1': '%{complete}. Ukupno prenesenih datoteka: %{smart_count}',
-    '2': '%{complete}. Ukupno prenesenih datoteka: %{smart_count}',
   },
   filter: 'Filtriraj',
   finishEditingFile: 'Završi uređivanje datoteke',
   folderAdded: {
     '0': 'Broj datoteka preuzetih iz %{folder}: %{smart_count}',
     '1': 'Broj datoteka preuzetih iz %{folder}: %{smart_count}',
-    '2': 'Broj datoteka preuzetih iz %{folder}: %{smart_count}',
   },
   import: 'Preuzmi',
   importFrom: 'Preuzmi s %{name}',
@@ -78,7 +85,6 @@ hr_HR.strings = {
   processingXFiles: {
     '0': 'Obrada datoteke',
     '1': 'Broj datoteka koje se obrađuju: %{smart_count}',
-    '2': 'Broj datoteka koje se obrađuju: %{smart_count}',
   },
   removeFile: 'Ukloni datoteku',
   resetFilter: 'Izbriši filter',
@@ -90,13 +96,13 @@ hr_HR.strings = {
   selectX: {
     '0': 'Izaberi datoteku',
     '1': 'Izaberi %{smart_count}',
-    '2': 'Izaberi %{smart_count}',
   },
   smile: 'Osmijeh!',
   startRecording: 'Započni snimanje video zapisa',
   stopRecording: 'Zaustavi snimanje video zapisa',
   takePicture: 'Snimi fotografiju',
-  timedOut: 'Prekidamo prijenos radi poteškoća. Broj sekundi zastoja: %{seconds}.',
+  timedOut:
+    'Prekidamo prijenos radi poteškoća. Broj sekundi zastoja: %{seconds}.',
   upload: 'Prenesi',
   uploadComplete: 'Prijenos uspio',
   uploadFailed: 'Prijenos nije uspio',
@@ -104,47 +110,43 @@ hr_HR.strings = {
   uploadXFiles: {
     '0': 'Prenesi datoteku',
     '1': 'Prenesi datoteke. Ukupno: %{smart_count}',
-    '2': 'Prenesi datoteke. Ukupno: %{smart_count}',
   },
   uploadXNewFiles: {
     '0': 'Prenesi +%{smart_count} datoteku',
     '1': 'Prenesi datoteke. Ukupno: +%{smart_count}',
-    '2': 'Prenesi datoteke. Ukupno: +%{smart_count}',
   },
   uploading: 'Datoteka se prenosi',
   uploadingXFiles: {
     '0': 'Broj datoteka koje se trenutno prenose: %{smart_count}',
     '1': 'Broj datoteka koje se trenutno prenose: %{smart_count}',
-    '2': 'Broj datoteka koje se trenutno prenose: %{smart_count}',
   },
   xFilesSelected: {
     '0': 'Broj datoteka za prijenos: %{smart_count}',
     '1': 'Broj datoteka za prijenos: %{smart_count}',
-    '2': 'Broj datoteka za prijenos: %{smart_count}',
   },
   xMoreFilesAdded: {
     '0': 'Broj dodatih datoteka: %{smart_count}',
     '1': 'Broj dodatih datoteka: %{smart_count}',
-    '2': 'Broj dodatih datoteka: %{smart_count}',
   },
   xTimeLeft: 'Preostalo vrijeme %{time} ',
   youCanOnlyUploadFileTypes: 'Moguće je prenijeti samo: %{types}',
   youCanOnlyUploadX: {
     '0': 'Dozvoljeni broj datoteka za prijenos: %{smart_count}',
     '1': 'Dozvoljeni broj datoteka za prijenos: %{smart_count}',
-    '2': 'Dozvoljeni broj datoteka za prijenos: %{smart_count}',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Izaberite bar jednu datoteku',
     '1': 'Izaberite datoteke. Najmanje: %{smart_count}',
-    '2': 'Izaberite datoteke. Najmanje: %{smart_count}',
   },
   selectFileNamed: 'Izaberite datoteku %{name}',
   unselectFileNamed: 'Isključite datoteku %{name}',
   openFolderNamed: 'Otvori mapu %{name}',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.hr_HR = hr_HR
 }
 

+ 29 - 64
packages/@uppy/locales/src/hu_HU.js → packages/@uppy/locales/src/hu_HU.ts

@@ -1,19 +1,22 @@
-const hu_HU = {
-  pluralize () {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const hu_HU: Locale<0> = {
+  strings: {},
+  pluralize() {
     return 0
   },
 }
 
-hu_HU.contributors = ['nagyv']
-
 hu_HU.strings = {
   addMore: 'Adj hozzá többet',
   addMoreFiles: 'További fájlok hozzáadása',
   addingMoreFiles: 'További fájlok hozzáadása',
-  allowAccessDescription: 'A képek vagy videó felvételéhez, kérjük engedélyezze a kamera használatát ezen az oldalon.',
+  allowAccessDescription:
+    'A képek vagy videó felvételéhez, kérjük engedélyezze a kamera használatát ezen az oldalon.',
   allowAccessTitle: 'Engedélyezze a kamera használatát',
   authenticateWith: 'Kapcsolódás a %{pluginName}-val',
-  authenticateWithTitle: 'Kérjük lépjen be a %{pluginName}-ba a fájlok kiválasztásához',
+  authenticateWithTitle:
+    'Kérjük lépjen be a %{pluginName}-ba a fájlok kiválasztásához',
   back: 'Vissza',
   browse: 'válasszon',
   browseFiles: 'válasszon',
@@ -41,29 +44,24 @@ hu_HU.strings = {
   dropPasteFolders: 'Húzza ide a fájlokat vagy %{browseFolders}',
   dropPasteImportBoth: 'Húzza ide a fájlokat, %{browse} vagy importáljon:',
   dropPasteImportFiles: 'Húzza ide a fájlokat, %{browse} vagy importáljon:',
-  dropPasteImportFolders: 'Húzza ide a fájlokat, %{browseFolders} vagy importáljon:',
+  dropPasteImportFolders:
+    'Húzza ide a fájlokat, %{browseFolders} vagy importáljon:',
   editFile: 'Fájl szerkesztése',
   editing: '%{file} szerkesztése',
   emptyFolderAdded: 'Az üres mappából nem kerültek fájlok hozzáadásra',
   encoding: 'Kódolás...',
-  enterCorrectUrl: 'Érvénytelen URL: Bizonyosodjon meg róla, hogy egy fájlra mutató közvetlen linket ír be',
+  enterCorrectUrl:
+    'Érvénytelen URL: Bizonyosodjon meg róla, hogy egy fájlra mutató közvetlen linket ír be',
   enterUrlToImport: 'Adjon meg egy URL-t a fájl importálásához',
   exceedsSize: 'Ez a fájl meghaladja a maximális megengedett méretet %{size}',
-  failedToFetch: 'A Companion-nak nem sikerült az URL letöltése, győzödjön meg az URL helyességéről',
+  failedToFetch:
+    'A Companion-nak nem sikerült az URL letöltése, győzödjön meg az URL helyességéről',
   failedToUpload: '%{file}-t nem sikerült feltölteni',
   fileSource: 'Fájl forrása: %{name}',
-  filesUploadedOfTotal: {
-    '0': 'A %{smart_count}-ból %{complete} fájl feltöltve',
-    '1': 'A %{smart_count}-ból %{complete} fájl feltöltve',
-    '2': 'A %{smart_count}-ból %{complete} fájl feltöltve',
-  },
+  filesUploadedOfTotal: 'A %{smart_count}-ból %{complete} fájl feltöltve',
   filter: 'Szűrő',
   finishEditingFile: 'Fájl szerkesztésének befejezése',
-  folderAdded: {
-    '0': 'A %{folder}-ból %{smart_count} fájl hozzáadva',
-    '1': 'A %{folder}-ból %{smart_count} fájl hozzáadva',
-    '2': 'A %{folder}-ból %{smart_count} fájl hozzáadva',
-  },
+  folderAdded: 'A %{folder}-ból %{smart_count} fájl hozzáadva',
   import: 'Importálás',
   importFrom: 'Importálás innen: %{name}',
   loading: 'Töltés...',
@@ -75,11 +73,7 @@ hu_HU.strings = {
   pauseUpload: 'Feltöltés szüneteltetése',
   paused: 'Szüneteltetve',
   poweredBy: 'Meghajtja az %{uppy}',
-  processingXFiles: {
-    '0': '%{smart_count} fájl feldolgozása',
-    '1': '%{smart_count} fájl feldolgozása',
-    '2': '%{smart_count} fájl feldolgozása',
-  },
+  processingXFiles: '%{smart_count} fájl feldolgozása',
   removeFile: 'Fájl törlése',
   resetFilter: 'Szűrő visszaállítása',
   resume: 'Folytatás',
@@ -87,11 +81,7 @@ hu_HU.strings = {
   retry: 'Újra',
   retryUpload: 'Próbálja újra a feltöltést',
   saveChanges: 'Változtatások mentése',
-  selectX: {
-    '0': 'Válassza az %{smart_count} lehetőséget',
-    '1': 'Válassza az %{smart_count} lehetőséget',
-    '2': 'Válassza az %{smart_count} lehetőséget',
-  },
+  selectX: 'Válassza az %{smart_count} lehetőséget',
   smile: 'Csíííz!',
   startRecording: 'Videófeltével indul',
   stopRecording: 'Videófelvétel megáll',
@@ -101,50 +91,25 @@ hu_HU.strings = {
   uploadComplete: 'A feltöltés kész',
   uploadFailed: 'Sikertelen feltöltés',
   uploadPaused: 'Szüneteltetett feltöltés',
-  uploadXFiles: {
-    '0': '%{smart_count} fájl feltöltése',
-    '1': '%{smart_count} fájl feltöltése',
-    '2': '%{smart_count} fájl feltöltése',
-  },
-  uploadXNewFiles: {
-    '0': '+%{smart_count} fájl feltöltése',
-    '1': '+%{smart_count} fájl feltöltése',
-    '2': '+%{smart_count} fájl feltöltése',
-  },
+  uploadXFiles: '%{smart_count} fájl feltöltése',
+  uploadXNewFiles: '+%{smart_count} fájl feltöltése',
   uploading: 'Feltölés',
-  uploadingXFiles: {
-    '0': '+%{smart_count} fájl feltöltése',
-    '1': '+%{smart_count} fájl feltöltése',
-    '2': '+%{smart_count} fájl feltöltése',
-  },
-  xFilesSelected: {
-    '0': '%{smart_count} fájl kiválasztva',
-    '1': '%{smart_count} fájl kiválasztva',
-    '2': '%{smart_count} fájl kiválasztva',
-  },
-  xMoreFilesAdded: {
-    '0': 'további %{smart_count} fájl hozzáadva',
-    '1': 'további %{smart_count} fájl hozzáadva',
-    '2': 'további %{smart_count} fájl hozzáadva',
-  },
+  uploadingXFiles: '+%{smart_count} fájl feltöltése',
+  xFilesSelected: '%{smart_count} fájl kiválasztva',
+  xMoreFilesAdded: 'további %{smart_count} fájl hozzáadva',
   xTimeLeft: '%{time} van hátra',
   youCanOnlyUploadFileTypes: 'Feltölthető formátumok: %{types}',
-  youCanOnlyUploadX: {
-    '0': 'Csak %{smart_count} fájl tölthető fel',
-    '1': 'Csak %{smart_count} fájl tölthető fel',
-    '2': 'Csak %{smart_count} fájl tölthető fel',
-  },
-  youHaveToAtLeastSelectX: {
-    '0': 'Legalább %{smart_count} fájlt ki kell választania',
-    '1': 'Legalább %{smart_count} fájlt ki kell választania',
-    '2': 'Legalább %{smart_count} fájlt ki kell választania',
-  },
+  youCanOnlyUploadX: 'Csak %{smart_count} fájl tölthető fel',
+  youHaveToAtLeastSelectX: 'Legalább %{smart_count} fájlt ki kell választania',
   selectFileNamed: 'Válaszd ki a fájlt %{name}',
   unselectFileNamed: 'A fájl törlése %{name}',
   openFolderNamed: 'Nyitott mappa %{name}',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.hu_HU = hu_HU
 }
 

+ 18 - 18
packages/@uppy/locales/src/id_ID.js → packages/@uppy/locales/src/id_ID.ts

@@ -1,5 +1,8 @@
-const id_ID = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const id_ID: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -11,10 +14,12 @@ id_ID.strings = {
   addMore: 'Tambahkan lebih banyak',
   addMoreFiles: 'Tambahkan lebih banyak berkas',
   addingMoreFiles: 'Menambahkan lebih banyak berkas',
-  allowAccessDescription: 'Untuk mengambil gambar atau merekam video menggunakan kamera Anda, mohon izinkan akses kamera untuk situs ini.',
+  allowAccessDescription:
+    'Untuk mengambil gambar atau merekam video menggunakan kamera Anda, mohon izinkan akses kamera untuk situs ini.',
   allowAccessTitle: 'Mohon izinkan akses ke kamera Anda.',
   authenticateWith: 'Menghubungkan ke %{pluginName}',
-  authenticateWithTitle: 'Silahkan mengotentifikasi menggunakan %{pluginName} untuk memilih berkas',
+  authenticateWithTitle:
+    'Silahkan mengotentifikasi menggunakan %{pluginName} untuk memilih berkas',
   back: 'Kembali',
   browse: 'Telusuri',
   browseFiles: 'Telusuri',
@@ -31,7 +36,8 @@ id_ID.strings = {
   creatingAssembly: 'Menyiapkan unggahan...',
   creatingAssemblyFailed: 'Transloadit: Tidak dapat membuat Assembly',
   dashboardTitle: 'Pengunggah Berkas',
-  dashboardWindowTitle: 'Jendela Pengunggah Berkas (Tekan escape untuk menutup)',
+  dashboardWindowTitle:
+    'Jendela Pengunggah Berkas (Tekan escape untuk menutup)',
   dataUploadedOfTotal: '%{complete} dari %{total}',
   done: 'Selesai',
   dropHereOr: 'Letakkan berkas di sini atau %{browse}',
@@ -41,12 +47,14 @@ id_ID.strings = {
   dropPasteFolders: 'Letakkan berkas di sini, tempelkan atau %{browse}',
   dropPasteImportBoth: 'Letakkan berkas, tempelkan, %{browse} atau impor dari',
   dropPasteImportFiles: 'Letakkan berkas, tempelkan, %{browse} atau impor dari',
-  dropPasteImportFolders: 'Letakkan berkas, tempelkan, %{browse} atau impor dari',
+  dropPasteImportFolders:
+    'Letakkan berkas, tempelkan, %{browse} atau impor dari',
   editFile: 'Ubah berkas',
   editing: 'Mengubah %{file}',
   emptyFolderAdded: 'Tidak ada berkas yang ditambahkan dari direktori kosong',
   encoding: 'Pengkodean...',
-  enterCorrectUrl: 'URL salah: Mohon pastikan Anda memasukkan tautan langsung ke berkas',
+  enterCorrectUrl:
+    'URL salah: Mohon pastikan Anda memasukkan tautan langsung ke berkas',
   enterUrlToImport: 'Masukkan URL untuk mengimpor berkas',
   exceedsSize: 'Berkas ini melebihi ukuran maksimum yang dibolehkan %{size}',
   failedToFetch: 'Companion gagal mengambil URL ini, pastikan sudah benar',
@@ -55,14 +63,12 @@ id_ID.strings = {
   filesUploadedOfTotal: {
     '0': '%{complete} dari %{smart_count} berkas terunggah',
     '1': '%{complete} dari %{smart_count} berkas terunggah',
-    '2': '%{complete} dari %{smart_count} berkas terunggah',
   },
   filter: 'Penyaring',
   finishEditingFile: 'Selesai mengubah berkas',
   folderAdded: {
     '0': 'Menambahkan %{smart_count} berkas dari %{folder}',
     '1': 'Menambahkan %{smart_count} berkas dari %{folder}',
-    '2': 'Menambahkan %{smart_count} berkas dari %{folder}',
   },
   import: 'Impor',
   importFrom: 'Impor dari %{name}',
@@ -79,7 +85,6 @@ id_ID.strings = {
   processingXFiles: {
     '0': 'Pemrosesan %{smart_count} berkas',
     '1': 'Pemrosesan %{smart_count} berkas',
-    '2': 'Pemrosesan %{smart_count} berkas',
   },
   removeFile: 'Hapus berkas',
   resetFilter: 'Setel ulang penyaring',
@@ -92,7 +97,6 @@ id_ID.strings = {
   selectX: {
     '0': 'Pilih %{smart_count}',
     '1': 'Pilih %{smart_count}',
-    '2': 'Pilih %{smart_count}',
   },
   smile: 'Senyum!',
   startRecording: 'Memulai perekaman video',
@@ -107,44 +111,40 @@ id_ID.strings = {
   uploadXFiles: {
     '0': 'Unggah %{smart_count} berkas',
     '1': 'Unggah %{smart_count} berkas',
-    '2': 'Unggah %{smart_count} berkas',
   },
   uploadXNewFiles: {
     '0': 'Mengunggah +%{smart_count} berkas baru',
     '1': 'Mengunggah +%{smart_count} berkas baru',
-    '2': 'Mengunggah +%{smart_count} berkas baru',
   },
   uploading: 'Mengunggah',
   uploadingXFiles: {
     '0': 'Mengunggah %{smart_count} berkas',
     '1': 'Mengunggah %{smart_count} berkas',
-    '2': 'Mengunggah %{smart_count} berkas',
   },
   xFilesSelected: {
     '0': '%{smart_count} berkas terpilih',
     '1': '%{smart_count} berkas terpilih',
-    '2': '%{smart_count} berkas terpilih',
   },
   xMoreFilesAdded: {
     '0': '%{smart_count} berkas lagi ditambahkan',
     '1': '%{smart_count} berkas lagi ditambahkan',
-    '2': '%{smart_count} berkas lagi ditambahkan',
   },
   xTimeLeft: 'Tersisa %{time}',
   youCanOnlyUploadFileTypes: 'Anda hanya dapat menggunggah: %{types}',
   youCanOnlyUploadX: {
     '0': 'Anda hanya dapat mengunggah %{smart_count} berkas',
     '1': 'Anda hanya dapat mengunggah %{smart_count} berkas',
-    '2': 'Anda hanya dapat mengunggah %{smart_count} berkas',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Anda harus memilih minimal %{smart_count} berkas',
     '1': 'Anda harus memilih minimal %{smart_count} berkas',
-    '2': 'Anda harus memilih minimal %{smart_count} berkas',
   },
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.id_ID = id_ID
 }
 

+ 19 - 21
packages/@uppy/locales/src/is_IS.js → packages/@uppy/locales/src/is_IS.ts

@@ -1,5 +1,8 @@
-const is_IS = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const is_IS: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -12,11 +15,11 @@ is_IS.strings = {
   addMoreFiles: 'Bæta við fleiri skrám',
   addingMoreFiles: 'Bæti við fleiri skrám',
   allowAccessDescription:
-        'Vinsamlegast gefðu aðgang að myndavélinni þinni, til þess að taka myndir eða taka upp myndband með myndavélinni þinni.',
+    'Vinsamlegast gefðu aðgang að myndavélinni þinni, til þess að taka myndir eða taka upp myndband með myndavélinni þinni.',
   allowAccessTitle: 'Vinsamlegast gefðu aðgang að myndavélinni þinni.',
   authenticateWith: 'Tengjast %{pluginName}',
   authenticateWithTitle:
-        'Vinsamlegast auðkenndu %{pluginName} til þess að velja skrár',
+    'Vinsamlegast auðkenndu %{pluginName} til þess að velja skrár',
   back: 'Til baka',
   browse: 'skoða',
   browseFiles: 'skoða',
@@ -26,7 +29,7 @@ is_IS.strings = {
   closeModal: 'Loka glugga',
   companionError: 'Tengin mistókst',
   companionUnauthorizeHint:
-        'Til þess að leyfa aðgang að %{provider}, vinsamlegast smelltu hér: %{url}',
+    'Til þess að leyfa aðgang að %{provider}, vinsamlegast smelltu hér: %{url}',
   complete: 'Lokið',
   connectedToInternet: 'Tengdur við internet',
   copyLink: 'Afrita hlekk',
@@ -43,32 +46,33 @@ is_IS.strings = {
   dropPasteBoth: 'Slepptu skrám hérna, límdu (paste) eða %{browse}',
   dropPasteFiles: 'Slepptu skrám hérna, límdu (paste) eða %{browse}',
   dropPasteFolders: 'Slepptu skrám hérna, límdu (paste) eða %{browse}',
-  dropPasteImportBoth: 'Slepptu skrám hérna, límdu (paste), %{browse} eða bættu við frá',
-  dropPasteImportFiles: 'Slepptu skrám hérna, límdu (paste), %{browse} eða bættu við frá',
-  dropPasteImportFolders: 'Slepptu skrám hérna, límdu (paste), %{browse} eða bættu við frá',
+  dropPasteImportBoth:
+    'Slepptu skrám hérna, límdu (paste), %{browse} eða bættu við frá',
+  dropPasteImportFiles:
+    'Slepptu skrám hérna, límdu (paste), %{browse} eða bættu við frá',
+  dropPasteImportFolders:
+    'Slepptu skrám hérna, límdu (paste), %{browse} eða bættu við frá',
   editFile: 'Breyta skrá',
   editing: 'Breyti %{file}',
   emptyFolderAdded: 'Engum skrám var bætt við frá tómri möppu',
   encoding: 'Dulkóða...',
   enterCorrectUrl:
-        'Röng slóð: Vinsamlegast passaðu að þú sért að bæta við hlekk sem vísar beint á skrá',
+    'Röng slóð: Vinsamlegast passaðu að þú sért að bæta við hlekk sem vísar beint á skrá',
   enterUrlToImport: 'Settu inn hlekk til að bæta við skrá',
   exceedsSize: 'Þessi skrá er stærri en hún má vera  %{size}',
   failedToFetch:
-        'Það tókst ekki að sækja þennan hlekk, vinsamlegast passaðu að hann sé réttur',
+    'Það tókst ekki að sækja þennan hlekk, vinsamlegast passaðu að hann sé réttur',
   failedToUpload: 'Mistókst að upphala %{file}',
   fileSource: 'Uppruni skráar: %{name}',
   filesUploadedOfTotal: {
     '0': '%{complete} af %{smart_count} skrá upphalað',
     '1': '%{complete} af %{smart_count} skrám upphalað',
-    '2': '%{complete} af %{smart_count} skrám upphalað',
   },
   filter: 'Sía',
   finishEditingFile: 'Klára að breyta skrá',
   folderAdded: {
     '0': 'Bætt við %{smart_count} skrá frá %{folder}',
     '1': 'Bætt við %{smart_count} skrám frá %{folder}',
-    '2': 'Bætt við %{smart_count} skrám frá %{folder}',
   },
   generatingThumbnails: 'Bý til smámynd ...',
   import: 'Flytja inn',
@@ -86,7 +90,6 @@ is_IS.strings = {
   processingXFiles: {
     '0': 'Vinn %{smart_count} skrá',
     '1': 'Vinn %{smart_count} skrár',
-    '2': 'Vinn %{smart_count} skrár',
   },
   removeFile: 'Fjarlægja skrá',
   resetFilter: 'Endurstilla síu',
@@ -99,7 +102,6 @@ is_IS.strings = {
   selectX: {
     '0': 'Velja %{smart_count}',
     '1': 'Velja %{smart_count}',
-    '2': 'Velja %{smart_count}',
   },
   smile: 'Brostu!',
   startRecording: 'Byrja myndbandsupptöku',
@@ -114,44 +116,40 @@ is_IS.strings = {
   uploadXFiles: {
     '0': 'Upphala %{smart_count} skrá',
     '1': 'Upphala %{smart_count} skrám',
-    '2': 'Upphala %{smart_count} skrám',
   },
   uploadXNewFiles: {
     '0': 'Upphala +%{smart_count} skrá',
     '1': 'Upphala +%{smart_count} skrám',
-    '2': 'Upphala +%{smart_count} skrám',
   },
   uploading: 'Upphala',
   uploadingXFiles: {
     '0': 'Upphala %{smart_count} skrá',
     '1': 'Upphala %{smart_count} skrám',
-    '2': 'Upphala %{smart_count} skrám',
   },
   xFilesSelected: {
     '0': '%{smart_count} skrá valin',
     '1': '%{smart_count} skrár valdar',
-    '2': '%{smart_count} skrár valdar',
   },
   xMoreFilesAdded: {
     '0': '%{smart_count} fleiri skrá bætt við',
     '1': '%{smart_count} fleiri skrám bætt við',
-    '2': '%{smart_count} fleiri skrám bætt við',
   },
   xTimeLeft: '%{time} eftir',
   youCanOnlyUploadFileTypes: 'Þú getur aðeins upphalað: %{types}',
   youCanOnlyUploadX: {
     '0': 'Þú getur aðeins upphalað %{smart_count} skrá',
     '1': 'Þú getur aðeins upphalað %{smart_count} skrám',
-    '2': 'Þú getur aðeins upphalað %{smart_count} skrám',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Þú verður að velja lágmark %{smart_count} skrá',
     '1': 'Þú verður að velja lágmark %{smart_count} skrár',
-    '2': 'Þú verður að velja lágmark %{smart_count} skrár',
   },
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.is_IS = is_IS
 }
 

+ 22 - 23
packages/@uppy/locales/src/it_IT.js → packages/@uppy/locales/src/it_IT.ts

@@ -1,5 +1,8 @@
-const it_IT = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const it_IT: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -10,8 +13,9 @@ const it_IT = {
 it_IT.strings = {
   addMoreFiles: 'Aggiungi più file',
   addingMoreFiles: 'Sto aggiungendo altri file',
-  allowAccessDescription: 'Per acquisire foto o video con la tua fotocamera, abilitane l\'accesso da questo sito.',
-  allowAccessTitle: 'Abilita l\'accesso alla fotocamera',
+  allowAccessDescription:
+    "Per acquisire foto o video con la tua fotocamera, abilitane l'accesso da questo sito.",
+  allowAccessTitle: "Abilita l'accesso alla fotocamera",
   authenticateWith: 'Connetti a %{pluginName}',
   authenticateWithTitle: 'Autenticati con %{pluginName} per selezionare i file',
   back: 'Indietro',
@@ -26,10 +30,10 @@ it_IT.strings = {
   complete: 'Completato',
   connectedToInternet: 'Connesso a internet',
   copyLink: 'Copia link',
-  copyLinkToClipboardFallback: 'Copia l\'URL sottostante',
+  copyLinkToClipboardFallback: "Copia l'URL sottostante",
   copyLinkToClipboardSuccess: 'Link copiato',
   creatingAssembly: 'Upload in preparazione...',
-  creatingAssemblyFailed: 'Transloadit: Non ho potuto creare l\'Assembly',
+  creatingAssemblyFailed: "Transloadit: Non ho potuto creare l'Assembly",
   dashboardTitle: 'File Uploader',
   dashboardWindowTitle: 'File Uploader (Premi Esc per chiudere)',
   dataUploadedOfTotal: '%{complete} di %{total}',
@@ -41,28 +45,29 @@ it_IT.strings = {
   dropPasteFolders: 'Trascina i file qui, incolla o %{browse}',
   dropPasteImportBoth: 'Trascina i file qui, incolla, %{browse} o importa da',
   dropPasteImportFiles: 'Trascina i file qui, incolla, %{browse} o importa da',
-  dropPasteImportFolders: 'Trascina i file qui, incolla, %{browse} o importa da',
+  dropPasteImportFolders:
+    'Trascina i file qui, incolla, %{browse} o importa da',
   editFile: 'Modifica file',
   editing: 'Modifica %{file}',
   emptyFolderAdded: 'Nessun file aggiunto dalla cartella vuota',
   encoding: 'Encoding...',
-  enterCorrectUrl: 'URL non corretta: assicurati che sia un link diretto ad un file',
-  enterUrlToImport: 'Immetti l\'URL per importare un file',
+  enterCorrectUrl:
+    'URL non corretta: assicurati che sia un link diretto ad un file',
+  enterUrlToImport: "Immetti l'URL per importare un file",
   exceedsSize: 'Questo file supera la dimensione massima di %{size}',
-  failedToFetch: 'Impossibile verificare questa URL, assicurati che sia corretta',
+  failedToFetch:
+    'Impossibile verificare questa URL, assicurati che sia corretta',
   failedToUpload: 'Upload del file %{file} non riuscito',
   fileSource: 'Sorgente file: %{name}',
   filesUploadedOfTotal: {
     '0': '%{complete} di %{smart_count} file caricato',
     '1': '%{complete} di %{smart_count} file caricati',
-    '2': '%{complete} di %{smart_count} file caricati',
   },
   filter: 'Filter',
   finishEditingFile: 'Finish editing file',
   folderAdded: {
     '0': 'Aggiunto %{smart_count} file da %{folder}',
     '1': 'Aggiunti %{smart_count} file da %{folder}',
-    '2': 'Aggiunti %{smart_count} file da %{folder}',
   },
   import: 'Importa',
   importFrom: 'Importa da %{name}',
@@ -78,19 +83,17 @@ it_IT.strings = {
   processingXFiles: {
     '0': 'Sto processando %{smart_count} file',
     '1': 'Sto processando %{smart_count} file',
-    '2': 'Sto processando %{smart_count} file',
   },
   removeFile: 'Rimuovi il file',
   resetFilter: 'Ripristina filtro',
   resume: 'Riprendi',
-  resumeUpload: 'Riprendi l\'upload',
+  resumeUpload: "Riprendi l'upload",
   retry: 'Riprova',
-  retryUpload: 'Riprova l\'upload',
+  retryUpload: "Riprova l'upload",
   saveChanges: 'Salva le modifiche',
   selectX: {
     '0': 'Seleziona %{smart_count}',
     '1': 'Seleziona %{smart_count}',
-    '2': 'Seleziona %{smart_count}',
   },
   smile: 'Sorridi!',
   startRecording: 'Inizia la registrazione del video',
@@ -104,47 +107,43 @@ it_IT.strings = {
   uploadXFiles: {
     '0': 'Upload di %{smart_count} file',
     '1': 'Upload di %{smart_count} file',
-    '2': 'Upload di %{smart_count} file',
   },
   uploadXNewFiles: {
     '0': 'Upload +%{smart_count} file',
     '1': 'Upload +%{smart_count} file',
-    '2': 'Upload +%{smart_count} file',
   },
   uploading: 'In caricamento',
   uploadingXFiles: {
     '0': 'Caricando %{smart_count} file',
     '1': 'Caricando %{smart_count} file',
-    '2': 'Caricando %{smart_count} file',
   },
   xFilesSelected: {
     '0': '%{smart_count} file selezionato',
     '1': '%{smart_count} file selezionati',
-    '2': '%{smart_count} file selezionati',
   },
   xMoreFilesAdded: {
     '0': '%{smart_count} alto file aggiunto',
     '1': '%{smart_count} altri file aggiunti',
-    '2': '%{smart_count} ltri file aggiunti',
   },
   xTimeLeft: '%{time} rimasto',
   youCanOnlyUploadFileTypes: 'Puoi caricare solamente: %{types}',
   youCanOnlyUploadX: {
     '0': 'Puoi caricare %{smart_count} solo file',
     '1': 'Puoi caricare solo %{smart_count} file',
-    '2': 'Puoi caricare solo %{smart_count} file',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Devi selezionare almeno %{smart_count} file',
     '1': 'Devi selezionare almeno %{smart_count} file',
-    '2': 'Devi selezionare almeno %{smart_count} file',
   },
   selectFileNamed: 'Seleziona il file %{name}',
   unselectFileNamed: 'Deseleziona il file %{name}',
   openFolderNamed: 'Cartella aperta %{name}',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.it_IT = it_IT
 }
 

+ 30 - 24
packages/@uppy/locales/src/ja_JP.js → packages/@uppy/locales/src/ja_JP.ts

@@ -1,5 +1,8 @@
-const ja_JP = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const ja_JP: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -11,10 +14,12 @@ ja_JP.strings = {
   addMore: 'さらに追加',
   addMoreFiles: 'ファイルを追加',
   addingMoreFiles: 'ファイルを追加しています',
-  allowAccessDescription: 'カメラやビデオの機能を使用するには、カメラへのアクセスを許可してください。',
+  allowAccessDescription:
+    'カメラやビデオの機能を使用するには、カメラへのアクセスを許可してください。',
   allowAccessTitle: 'カメラへのアクセスを許可してください',
   authenticateWith: '%{pluginName}に接続します',
-  authenticateWithTitle: 'ファイルを選択するには%{pluginName}で認証してください',
+  authenticateWithTitle:
+    'ファイルを選択するには%{pluginName}で認証してください',
   back: '戻る',
   browse: '参照',
   browseFiles: '参照',
@@ -33,38 +38,45 @@ ja_JP.strings = {
   creatingAssembly: 'アップロードの準備をしています...',
   creatingAssemblyFailed: 'Transloadit: アセンブリを作成できませんでした',
   dashboardTitle: 'ファイルアップローダー',
-  dashboardWindowTitle: 'ファイルアップローダーウィンドウ(閉じるにはEscapeキーを押してください)',
+  dashboardWindowTitle:
+    'ファイルアップローダーウィンドウ(閉じるにはEscapeキーを押してください)',
   dataUploadedOfTotal: '%{total} %{complete}',
   done: '完了しました',
   dropHereOr: 'ここにファイルをドロップするか%{browse}してください',
   dropHint: 'ここにファイルをドロップしてください',
-  dropPasteBoth: 'ここにファイルをドロップするか、貼り付けるか、%{browse}してください',
-  dropPasteFiles: 'ここにファイルをドロップするか、貼り付けるか、%{browse}してください',
-  dropPasteFolders: 'ここにファイルをドロップするか、貼り付けるか、%{browse}してください',
-  dropPasteImportBoth: 'ここにファイルをドロップするか、貼り付けるか、%{browse}するか、以下からインポートしてください',
-  dropPasteImportFiles: 'ここにファイルをドロップするか、貼り付けるか、%{browse}するか、以下からインポートしてください',
-  dropPasteImportFolders: 'ここにファイルをドロップするか、貼り付けるか、%{browse}するか、以下からインポートしてください',
+  dropPasteBoth:
+    'ここにファイルをドロップするか、貼り付けるか、%{browse}してください',
+  dropPasteFiles:
+    'ここにファイルをドロップするか、貼り付けるか、%{browse}してください',
+  dropPasteFolders:
+    'ここにファイルをドロップするか、貼り付けるか、%{browse}してください',
+  dropPasteImportBoth:
+    'ここにファイルをドロップするか、貼り付けるか、%{browse}するか、以下からインポートしてください',
+  dropPasteImportFiles:
+    'ここにファイルをドロップするか、貼り付けるか、%{browse}するか、以下からインポートしてください',
+  dropPasteImportFolders:
+    'ここにファイルをドロップするか、貼り付けるか、%{browse}するか、以下からインポートしてください',
   editFile: 'ファイルを編集',
   editing: '%{file}を編集しています',
   emptyFolderAdded: 'フォルダが空なためファイルが追加されませんでした',
   encoding: 'エンコードしています...',
-  enterCorrectUrl: '不正なURL: ファイルへの直接リンクが入力されていることを確認してください',
+  enterCorrectUrl:
+    '不正なURL: ファイルへの直接リンクが入力されていることを確認してください',
   enterUrlToImport: 'ファイルをインポートするためのURLを入力してください',
   exceedsSize: 'ファイルサイズが大きすぎます %{size}',
-  failedToFetch: 'CompanionがURLを取得できませんでした。URLが正しいか確認してください',
+  failedToFetch:
+    'CompanionがURLを取得できませんでした。URLが正しいか確認してください',
   failedToUpload: '%{file}のアップロードに失敗しました',
   fileSource: '元ファイル:%{name}',
   filesUploadedOfTotal: {
     '0': '%{smart_count} 個のファイルのアップロードが%{complete}',
     '1': '%{smart_count} 個のファイルのアップロードが%{complete}',
-    '2': '%{cmart_count} 個のファイルのアップロードが%{complete}',
   },
   filter: 'フィルタ',
   finishEditingFile: 'ファイルの編集を終了',
   folderAdded: {
     '0': '%{folder} から% {smart_count} 個のファイルを追加しました',
     '1': '%{folder} から% {smart_count} 個のファイルを追加しました',
-    '2': '%{folder} から% {smart_count} 個のファイルを追加しました',
   },
   import: 'インポート',
   importFrom: '%{name}からインポート',
@@ -80,7 +92,6 @@ ja_JP.strings = {
   processingXFiles: {
     '0': '%{smart_count} ファイル処理中',
     '1': '%{smart_count} ファイル処理中',
-    '2': '%{smart_count} ファイル処理中',
   },
   removeFile: 'ファイルを消す',
   resetFilter: 'フィルタをリセット',
@@ -92,7 +103,6 @@ ja_JP.strings = {
   selectX: {
     '0': '%{smart_count} を選択',
     '1': '%{smart_count} を選択',
-    '2': '%{smart_count} を選択',
   },
   smile: 'スマイル〜!',
   startRecording: '録画開始',
@@ -106,47 +116,43 @@ ja_JP.strings = {
   uploadXFiles: {
     '0': '%{smart_count} ファイルをアップロード',
     '1': '%{smart_count} ファイルをアップロード',
-    '2': '%{smart_count} ファイルをアップロード',
   },
   uploadXNewFiles: {
     '0': '+%{smart_count} ファイルをアップロード',
     '1': '+%{smart_count} ファイルをアップロード',
-    '2': '+%{smart_count} ファイルをアップロード',
   },
   uploading: 'アップロード中',
   uploadingXFiles: {
     '0': '%{smart_count} ファイルアップロード中',
     '1': '%{smart_count} ファイルアップロード中',
-    '2': '%{smart_count} ファイルアップロード中',
   },
   xFilesSelected: {
     '0': '%{smart_count} ファイルを選択',
     '1': '%{smart_count} ファイルを選択',
-    '2': '%{smart_count} ファイルを選択',
   },
   xMoreFilesAdded: {
     '0': '%{smart_count} ファイルを追加',
     '1': '%{smart_count} ファイルを追加',
-    '2': '%{smart_count} ファイルを追加',
   },
   xTimeLeft: '残り %{time}',
   youCanOnlyUploadFileTypes: '許可されているファイル形式は次の物です: %{types}',
   youCanOnlyUploadX: {
     '0': '%{smart_count} ファイル数のみアップロード可能です',
     '1': '%{smart_count} ファイル数のみアップロード可能です',
-    '2': '%{smart_count} ファイル数のみアップロード可能です',
   },
   youHaveToAtLeastSelectX: {
     '0': '最低でも %{smart_count} ファイル選択してください',
     '1': '最低でも %{smart_count} ファイル選択してください',
-    '2': '最低でも %{smart_count} ファイル選択してください',
   },
   selectFileNamed: 'ファイルを選ぶ %{name}',
   unselectFileNamed: 'ファイルの選択を解除 %{name}',
   openFolderNamed: '開いたフォルダ %{name}',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.ja_JP = ja_JP
 }
 

+ 20 - 8
packages/@uppy/locales/src/ko_KR.js → packages/@uppy/locales/src/ko_KR.ts

@@ -1,5 +1,8 @@
-const ko_KR = {
-  pluralize () {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const ko_KR: Locale<0> = {
+  strings: {},
+  pluralize() {
     return 0
   },
 }
@@ -8,7 +11,8 @@ ko_KR.strings = {
   addMore: '파일 추가',
   addMoreFiles: '파일 추가',
   addingMoreFiles: '파일 추가 중',
-  allowAccessDescription: '카메라를 이용해 사진이나 영상을 찍기 위해서 이 사이트의 카메라 접근 권한을 허용해 주세요.',
+  allowAccessDescription:
+    '카메라를 이용해 사진이나 영상을 찍기 위해서 이 사이트의 카메라 접근 권한을 허용해 주세요.',
   allowAccessTitle: '카메라 사용 권한을 허용해 주세요.',
   authenticateWith: '%{pluginName} 연결',
   authenticateWithTitle: '파일을 선택하기 위해 %{pluginName}에 연결해 주세요.',
@@ -21,7 +25,8 @@ ko_KR.strings = {
   chooseFiles: '파일 선택',
   closeModal: '창 닫기',
   companionError: '연결 실패',
-  companionUnauthorizeHint: '%{provider} 연결 해제를 원하시면 %{url}에 방문하세요',
+  companionUnauthorizeHint:
+    '%{provider} 연결 해제를 원하시면 %{url}에 방문하세요',
   complete: '완료',
   connectedToInternet: '인터넷에 연결됨',
   copyLink: '링크 복사',
@@ -35,12 +40,16 @@ ko_KR.strings = {
   done: '완료',
   dropHereOr: '파일을 드래그 앤 드롭 또는 %{browse}',
   dropHint: '여기에 파일을 드래그 앤 드롭 해주세요.',
-  dropPasteBoth: '여기에 파일을 드래그 앤 드롭 하거나, %{browseFiles}, %{browseFolders}',
+  dropPasteBoth:
+    '여기에 파일을 드래그 앤 드롭 하거나, %{browseFiles}, %{browseFolders}',
   dropPasteFiles: '여기에 파일을 드래그 앤 드롭 하거나, %{browseFiles}',
   dropPasteFolders: '여기에 파일을 드래그 앤 드롭 하거나, %{browseFolders}',
-  dropPasteImportBoth: '여기에 파일을 드래그 앤 드롭 하거나, %{browseFiles}, %{browseFolders}, 이 경로에서 입수 :',
-  dropPasteImportFiles: '여기에 파일을 드래그 앤 드롭 하거나, %{browseFiles}, 이 경로에서 입수 :',
-  dropPasteImportFolders: '여기에 파일을 드래그 앤 드롭 하거나, %{browseFolders}, 이 경로에서 입수 :',
+  dropPasteImportBoth:
+    '여기에 파일을 드래그 앤 드롭 하거나, %{browseFiles}, %{browseFolders}, 이 경로에서 입수 :',
+  dropPasteImportFiles:
+    '여기에 파일을 드래그 앤 드롭 하거나, %{browseFiles}, 이 경로에서 입수 :',
+  dropPasteImportFolders:
+    '여기에 파일을 드래그 앤 드롭 하거나, %{browseFolders}, 이 경로에서 입수 :',
   editFile: '파일 수정',
   editing: '%{file} 수정 중',
   emptyFolderAdded: '빈 폴더입니다.',
@@ -100,7 +109,10 @@ ko_KR.strings = {
   youHaveToAtLeastSelectX: '최소 %{smart_count}개의 파일을 선택해야 합니다',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.ko_KR = ko_KR
 }
 

+ 21 - 9
packages/@uppy/locales/src/nb_NO.js → packages/@uppy/locales/src/nb_NO.ts

@@ -1,5 +1,8 @@
-const nb_NO = {
-  pluralize (count) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const nb_NO: Locale<0 | 1> = {
+  strings: {},
+  pluralize(count) {
     if (count === 1) {
       return 0
     }
@@ -15,7 +18,8 @@ nb_NO.strings = {
   addMore: 'Legg til',
   addMoreFiles: 'Legg til filer',
   addingMoreFiles: 'Legger til flere filer',
-  allowAccessDescription: 'For å kunne ta bilder eller spille inn video må du gi siden tilgang til å bruke ditt kamera.',
+  allowAccessDescription:
+    'For å kunne ta bilder eller spille inn video må du gi siden tilgang til å bruke ditt kamera.',
   allowAccessTitle: 'Vennligst gi tilgang til ditt kamera',
   authAborted: 'Autentisering avbrutt',
   aspectRatioLandscape: 'Beskjær landskap (16:9)',
@@ -33,7 +37,8 @@ nb_NO.strings = {
   chooseFiles: 'Velg filer',
   closeModal: 'Lukk vindu',
   companionError: 'Kobling til Companion feilet',
-  companionUnauthorizeHint: 'For å logge ut av din %{provider}-konto, gå til %{url}',
+  companionUnauthorizeHint:
+    'For å logge ut av din %{provider}-konto, gå til %{url}',
   complete: 'Fullført',
   connectedToInternet: 'Koblet til internett',
   copyLink: 'Kopier lenke',
@@ -50,18 +55,21 @@ nb_NO.strings = {
   dropPasteBoth: 'Dra filer hit, %{browseFiles} eller %{browseFolders}',
   dropPasteFiles: 'Dra filer hit eller %{browseFiles}',
   dropPasteFolders: 'Dra filer hit eller %{browseFolders}',
-  dropPasteImportBoth: 'Dra filer hit %{browseFiles}, %{browseFolders} eller importer fra:',
+  dropPasteImportBoth:
+    'Dra filer hit %{browseFiles}, %{browseFolders} eller importer fra:',
   dropPasteImportFiles: 'Dra filer hit %{browseFiles} eller importer fra:',
   dropPasteImportFolders: 'Dra filer hit %{browseFolders} eller importer fra:',
   editFile: 'Rediger fil',
   editing: 'Redigerer %{file}',
   emptyFolderAdded: 'Ingen filer ble lagt til fra tom mappe',
   encoding: 'Koder...',
-  enterCorrectUrl: 'Ugyldig URL: Kontroller at adressen du angir er en direkte lenke til ei fil',
+  enterCorrectUrl:
+    'Ugyldig URL: Kontroller at adressen du angir er en direkte lenke til ei fil',
   enterTextToSearch: 'Skriv tekst for å søke etter bilder',
   enterUrlToImport: 'Angi URL for å importere fil',
   exceedsSize: 'Fila er større enn tillatt størrelse på %{size}',
-  failedToFetch: 'Companion kunne ikke hente denne URLen, kontroller at den er riktig',
+  failedToFetch:
+    'Companion kunne ikke hente denne URLen, kontroller at den er riktig',
   failedToUpload: 'Opplasting feilet for %{file}',
   fileSource: 'Filkilde: %{name}',
   filesUploadedOfTotal: {
@@ -85,7 +93,7 @@ nb_NO.strings = {
   myDevice: 'Min Enhet',
   noCameraDescription: 'Koble til kamera for å ta bilder eller ta opp video',
   noCameraTitle: 'Kamera ikke tilgjengelig',
-  noDuplicates: 'Kan ikke legge til \'%{fileName}\', da den allerede eksisterer',
+  noDuplicates: "Kan ikke legge til '%{fileName}', da den allerede eksisterer",
   noFilesFound: 'Du har ingen filer eller mapper her',
   noInternetConnection: 'Ingen internettilgang',
   noMoreFilesAllowed: 'Kan ikke legge til nye filer mens opplasting pågår',
@@ -100,7 +108,8 @@ nb_NO.strings = {
   },
   recording: 'Opptak pågår',
   recordingLength: 'Lengde på opptak: %{recording_length}',
-  recordingStoppedMaxSize: 'Opptak stoppet fordi fila er i ferd med å overskride tillatt størrelse',
+  recordingStoppedMaxSize:
+    'Opptak stoppet fordi fila er i ferd med å overskride tillatt størrelse',
   removeFile: 'Fjern fil',
   resetFilter: 'Nullstill filter',
   resume: 'Fortsett',
@@ -167,7 +176,10 @@ nb_NO.strings = {
   zoomOut: 'Zoom ut',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.nb_NO = nb_NO
 }
 

+ 40 - 18
packages/@uppy/locales/src/nl_NL.js → packages/@uppy/locales/src/nl_NL.ts

@@ -1,5 +1,8 @@
-const nl_NL = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const nl_NL: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -16,9 +19,11 @@ nl_NL.strings = {
   addMore: 'Meer toevoegen',
   addMoreFiles: 'Extra bestanden toevoegen',
   allFilesFromFolderNamed: 'Alle bestanden uit de map %{name}',
-  allowAccessDescription: 'Geef toestemming om foto\'s of videobeelden te kunnen maken.',
+  allowAccessDescription:
+    "Geef toestemming om foto's of videobeelden te kunnen maken.",
   allowAccessTitle: 'Geef toestemming om je camera te gebruiken',
-  allowAudioAccessDescription: 'Om geluidsopnamen te maken moet U toestemming geven voor deze website',
+  allowAudioAccessDescription:
+    'Om geluidsopnamen te maken moet U toestemming geven voor deze website',
   allowAudioAccessTitle: 'Geef toestemming om uw microfoon te gebruiken',
   aspectRatioLandscape: 'Landschap knippen (16:9)',
   aspectRatioPortrait: 'Portret knippen (9:16)',
@@ -35,7 +40,8 @@ nl_NL.strings = {
   chooseFiles: 'Kies bestanden',
   closeModal: 'Sluit Venster',
   companionError: 'Verbinding met Companion mislukt',
-  companionUnauthorizeHint: 'Om toegang te ontnemen voor uw %{provider} account, ga naar %{url}',
+  companionUnauthorizeHint:
+    'Om toegang te ontnemen voor uw %{provider} account, ga naar %{url}',
   complete: 'Voltooid',
   compressedX: '%{size} bespaard door het comprimeren van afbeeldingen',
   compressingImages: 'Afbeeldingen aan het comprimeren...',
@@ -55,19 +61,25 @@ nl_NL.strings = {
   dropPasteBoth: 'Sleep hier je bestanden naartoe, plak of %{browse}',
   dropPasteFiles: 'Sleep hier je bestanden naartoe, plak of %{browse}',
   dropPasteFolders: 'Sleep hier je bestanden naartoe, plak of %{browse}',
-  dropPasteImportBoth: 'Sleep hier je bestanden naartoe, plak, %{browse} of importeer vanuit',
-  dropPasteImportFiles: 'Sleep hier je bestanden naartoe, plak, %{browse} of importeer vanuit',
-  dropPasteImportFolders: 'Sleep hier je bestanden naartoe, plak, %{browse} of importeer vanuit',
+  dropPasteImportBoth:
+    'Sleep hier je bestanden naartoe, plak, %{browse} of importeer vanuit',
+  dropPasteImportFiles:
+    'Sleep hier je bestanden naartoe, plak, %{browse} of importeer vanuit',
+  dropPasteImportFolders:
+    'Sleep hier je bestanden naartoe, plak, %{browse} of importeer vanuit',
   editFile: 'Bestand aanpassen',
   editFileWithFilename: 'Bestand aanpassen %{file}',
   editing: 'Bezig %{file} aan te passen',
   emptyFolderAdded: 'Er werden geen bestanden toegevoegd uit de lege map',
   encoding: 'Coderen...',
-  enterCorrectUrl: 'Ongeldige URL: Zorg dat je een directe link naar een bestand invoert',
+  enterCorrectUrl:
+    'Ongeldige URL: Zorg dat je een directe link naar een bestand invoert',
   enterTextToSearch: 'Type hier om te zoeken naar plaatjes',
   enterUrlToImport: 'Voeg URL toe om een bestand te importeren',
-  exceedsSize: '%{file} overschrijdt de maximaal toegelaten bestandsgrootte van %{size}',
-  failedToFetch: 'Companion kan deze URL niet laden, controleer of de URL correct is',
+  exceedsSize:
+    '%{file} overschrijdt de maximaal toegelaten bestandsgrootte van %{size}',
+  failedToFetch:
+    'Companion kan deze URL niet laden, controleer of de URL correct is',
   failedToUpload: 'Kon %{file} niet uploaden',
   fileSource: 'Bronbestand: %{name}',
   filesUploadedOfTotal: {
@@ -91,17 +103,21 @@ nl_NL.strings = {
   logOut: 'Uitloggen',
   micDisabled: 'Microfoon toegang geweigerd door de gebruiker',
   missingRequiredMetaField: 'De vereiste metadata ontbreekt',
-  missingRequiredMetaFieldOnFile: 'De vereiste metadata ontbreekt voor %{fileName}',
+  missingRequiredMetaFieldOnFile:
+    'De vereiste metadata ontbreekt voor %{fileName}',
   missingRequiredMetaFields: {
     '0': 'Deze vereiste metadata ontbreekt: %{fields}.',
     '1': 'Deze vereiste metadata ontbreekt: %{fields}.',
   },
   myDevice: 'Mijn apparaat',
-  noAudioDescription: 'Om audio op te nemen, sluit een microfoon of andere geluidsinput aan',
+  noAudioDescription:
+    'Om audio op te nemen, sluit een microfoon of andere geluidsinput aan',
   noAudioTitle: 'Microfoon niet beschikbaar',
-  noCameraDescription: 'Om foto\'s en/of video op te nemen, sluit een camera aan',
+  noCameraDescription:
+    "Om foto's en/of video op te nemen, sluit een camera aan",
   noCameraTitle: 'Camera niet beschikbaar',
-  noDuplicates: "Kan het dubbele bestand '%{fileName}' niet toevoegen, deze bestaat al",
+  noDuplicates:
+    "Kan het dubbele bestand '%{fileName}' niet toevoegen, deze bestaat al",
   noFilesFound: 'Geen bestanden of mappen gevonden',
   noInternetConnection: 'Geen internetverbinding',
   noMoreFilesAllowed: 'Meer bestanden kunnen niet worden toegevoegd',
@@ -116,8 +132,10 @@ nl_NL.strings = {
   },
   recording: 'Aan het opnemen',
   recordingLength: 'Opnameduur %{recording_length}',
-  recordingStoppedMaxSize: 'Opname gestopt omdat de bestandsgrootte de limiet bijna overschrijdt',
-  recoveredAllFiles: 'Alle bestanden zijn herstel. U kunt doorgaan me de upload.',
+  recordingStoppedMaxSize:
+    'Opname gestopt omdat de bestandsgrootte de limiet bijna overschrijdt',
+  recoveredAllFiles:
+    'Alle bestanden zijn herstel. U kunt doorgaan me de upload.',
   recoveredXFiles: {
     '0': 'We konden 1 bestand niet herstellen. Kies het bestand opnieuw en vervolg de upload',
     '1': 'We konden %{smart_count} bestanden niet herstellen. Kies de bestanden opnieuw en vervolg de upload.',
@@ -154,7 +172,8 @@ nl_NL.strings = {
   streamPassive: 'Stream passief',
   submitRecordedFile: 'Stuur opgenomen bestand',
   takePicture: 'Neem een foto',
-  timedOut: 'Upload al gedurende %{seconds} seconden vastgelopen, bezig afbreken upload.',
+  timedOut:
+    'Upload al gedurende %{seconds} seconden vastgelopen, bezig afbreken upload.',
   unselectFileNamed: 'Deselecteer bestand %{name}',
   upload: 'Upload',
   uploadComplete: 'Upload voltooid',
@@ -195,7 +214,10 @@ nl_NL.strings = {
   zoomOut: 'Zoom uit',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.nl_NL = nl_NL
 }
 

+ 22 - 20
packages/@uppy/locales/src/pl_PL.js → packages/@uppy/locales/src/pl_PL.ts

@@ -1,5 +1,8 @@
-const pl_PL = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const pl_PL: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -15,7 +18,8 @@ pl_PL.strings = {
   addMore: 'Dodaj więcej',
   addMoreFiles: 'Dodaj więcej plików',
   addingMoreFiles: 'Dodawanie kolejnych plików',
-  allowAccessDescription: 'Aby zrobić zdjęcie lub nagrać filmik z użyciem wbudowanego aparatu, zezwól stronie na dostęp do aparatu',
+  allowAccessDescription:
+    'Aby zrobić zdjęcie lub nagrać filmik z użyciem wbudowanego aparatu, zezwól stronie na dostęp do aparatu',
   allowAccessTitle: 'Zezwól na dostęp do aparatu',
   authenticateWith: 'Połącz z %{pluginName}',
   authenticateWithTitle: 'Zaloguj się do %{pluginName} aby wybrać pliki',
@@ -27,7 +31,8 @@ pl_PL.strings = {
   chooseFiles: 'Wybierz pliki',
   closeModal: 'Zamknij',
   companionError: 'Połączenie z serwisem nie powiodło się',
-  companionUnauthorizeHint: 'Aby wylogować się z konta %{provider}, przejdź pod adres %{url}',
+  companionUnauthorizeHint:
+    'Aby wylogować się z konta %{provider}, przejdź pod adres %{url}',
   complete: 'Ukończono',
   connectedToInternet: 'Połączono z Internetem',
   copyLink: 'Skopiuj link',
@@ -46,28 +51,29 @@ pl_PL.strings = {
   dropPasteFolders: 'Upuść foldery tutaj, wklej, albo %{browse}',
   dropPasteImportBoth: 'Upuść pliki tutaj, wklej, %{browse} albo zaimportuj z',
   dropPasteImportFiles: 'Upuść pliki tutaj, wklej, %{browse} albo zaimportuj z',
-  dropPasteImportFolders: 'Upuść foldery tutaj, wklej, %{browse} albo zaimportuj z',
+  dropPasteImportFolders:
+    'Upuść foldery tutaj, wklej, %{browse} albo zaimportuj z',
   editFile: 'Edytuj plik',
   editing: 'Edycja %{file}',
   emptyFolderAdded: 'Z pustego folderu nie zostały dodane żadne pliki',
   encoding: 'Transkodowanie...',
-  enterCorrectUrl: 'Niepoprawny URL: Upewnij się, że wprowadzasz bezpośredni adres pliku',
+  enterCorrectUrl:
+    'Niepoprawny URL: Upewnij się, że wprowadzasz bezpośredni adres pliku',
   enterUrlToImport: 'Wprowadź URL, aby zaimportować plik',
   exceedsSize: 'Plik ma rozmiar większy od dozwolonego %{size}',
-  failedToFetch: 'Serwis nie mógł przetworzyć podanego linku, zweryfikuj jego poprawność',
+  failedToFetch:
+    'Serwis nie mógł przetworzyć podanego linku, zweryfikuj jego poprawność',
   failedToUpload: 'Przesyłanie %{file} nie powiodło się',
   fileSource: 'Źródło pliku: %{name}',
   filesUploadedOfTotal: {
     '0': 'wysłano %{complete} z %{smart_count} pliku',
     '1': 'wysłano %{complete} z %{smart_count} plików',
-    '2': 'wysłano %{complete} z %{smart_count} plików',
   },
   filter: 'Filtr',
   finishEditingFile: 'Zakończ edycję',
   folderAdded: {
     '0': 'Dodano %{smart_count} plik z folderu %{folder}',
     '1': 'Dodano %{smart_count} plików z folderu %{folder}',
-    '2': 'Dodano %{smart_count} plików z folderu %{folder}',
   },
   generatingThumbnails: 'Generowanie miniaturek...',
   import: 'Importuj',
@@ -75,7 +81,8 @@ pl_PL.strings = {
   loading: 'Ładowanie...',
   logOut: 'Wyloguj',
   myDevice: 'Moje urządzenie',
-  noDuplicates: 'Nie można dodać i zduplikować pliku \'%{fileName}\', już istnieje',
+  noDuplicates:
+    "Nie można dodać i zduplikować pliku '%{fileName}', już istnieje",
   noFilesFound: 'Nie znaleziono plików',
   noInternetConnection: 'Brak połączenia z Internetem',
   noMoreFilesAllowed: 'Nie można dodać nowych plików: trwa przesyłanie',
@@ -87,7 +94,6 @@ pl_PL.strings = {
   processingXFiles: {
     '0': 'Przetwarzanie %{smart_count} pliku',
     '1': 'Przetwarzanie %{smart_count} plików',
-    '2': 'Przetwarzanie %{smart_count} plików',
   },
   recordingLength: 'Długość nagrania %{recording_length}',
   removeFile: 'Usuń filtr',
@@ -101,13 +107,13 @@ pl_PL.strings = {
   selectX: {
     '0': 'Wybierz %{smart_count}',
     '1': 'Wybierz %{smart_count}',
-    '2': 'Wybierz %{smart_count}',
   },
   smile: 'Uśmiech!',
   startRecording: 'Zacznij nagrywanie wideo',
   stopRecording: 'Zatrzymaj nagrywanie wideo',
   takePicture: 'Zrób zdjęcie',
-  timedOut: 'Przesyłanie wstrzymane przez %{seconds} sekund, przerywanie przesyłania.',
+  timedOut:
+    'Przesyłanie wstrzymane przez %{seconds} sekund, przerywanie przesyłania.',
   unselectFileNamed: 'Odznacz plik %{name}',
   upload: 'Wgrywanie',
   uploadComplete: 'Wgrywanie ukończone',
@@ -116,44 +122,40 @@ pl_PL.strings = {
   uploadXFiles: {
     '0': 'Wgraj %{smart_count} plik',
     '1': 'Wgraj %{smart_count} pliki',
-    '2': 'Wgraj %{smart_count} pliki',
   },
   uploadXNewFiles: {
     '0': 'Wgraj +%{smart_count} plik',
     '1': 'Wgraj +%{smart_count} pliki',
-    '2': 'Wgraj +%{smart_count} pliki',
   },
   uploading: 'Wgrywanie',
   uploadingXFiles: {
     '0': 'Wgrywanie %{smart_count} pliku',
     '1': 'Wgrywanie %{smart_count} plików',
-    '2': 'Wgrywanie %{smart_count} plików',
   },
   xFilesSelected: {
     '0': '%{smart_count} plik zaznaczony',
     '1': '%{smart_count} plików zaznaczonych',
-    '2': '%{smart_count} plików zaznaczonych',
   },
   xMoreFilesAdded: {
     '0': 'dodano %{smart_count} 1 plik więcej',
     '1': 'dodano %{smart_count} pliki więcej',
-    '2': 'dodano %{smart_count} pliki więcej',
   },
   xTimeLeft: '%{time} zostało',
   youCanOnlyUploadFileTypes: 'Możesz przesłać tylko: %{types}',
   youCanOnlyUploadX: {
     '0': 'Możesz wgrać tylko %{smart_count} plik',
     '1': 'Możesz wgrać tylko %{smart_count} pliki',
-    '2': 'Możesz wgrać tylko %{smart_count} pliki',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Musisz wybrać przynajmniej %{smart_count} plik',
     '1': 'Musisz wybrać przynajmniej %{smart_count} pliki',
-    '2': 'Musisz wybrać przynajmniej %{smart_count} pliki',
   },
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.pl_PL = pl_PL
 }
 

+ 8 - 2
packages/@uppy/locales/src/pt_BR.js → packages/@uppy/locales/src/pt_BR.ts

@@ -1,5 +1,8 @@
-const pt_BR = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const pt_BR: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -147,7 +150,10 @@ pt_BR.strings = {
   openFolderNamed: 'Pasta aberta %{name}',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.pt_BR = pt_BR
 }
 

+ 8 - 2
packages/@uppy/locales/src/pt_PT.js → packages/@uppy/locales/src/pt_PT.ts

@@ -1,5 +1,8 @@
-const pt_PT = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const pt_PT: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -138,7 +141,10 @@ pt_PT.strings = {
   openFolderNamed: 'Pasta aberta %{name}',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.pt_PT = pt_PT
 }
 

+ 27 - 12
packages/@uppy/locales/src/ro_RO.js → packages/@uppy/locales/src/ro_RO.ts

@@ -1,5 +1,8 @@
-const ro_RO = {
-  pluralize (count) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const ro_RO: Locale<0 | 1> = {
+  strings: {},
+  pluralize(count) {
     if (count === 1) {
       return 0
     }
@@ -15,10 +18,12 @@ ro_RO.strings = {
   addMore: 'Adaugă mai multe',
   addMoreFiles: 'Adaugă mai multe fișiere',
   addingMoreFiles: 'Se adaugă mai multe fișiere',
-  allowAccessDescription: 'Pentru a face poze sau înregistra video trebuie să permiți accesul la cameră.',
+  allowAccessDescription:
+    'Pentru a face poze sau înregistra video trebuie să permiți accesul la cameră.',
   allowAccessTitle: 'Vă rugăm permiteți accesul la cameră',
   authenticateWith: 'Conectați-vă cu %{pluginName}',
-  authenticateWithTitle: 'Vă rugăm conectați-vă cu %{pluginName} pentru a selecta fișiere',
+  authenticateWithTitle:
+    'Vă rugăm conectați-vă cu %{pluginName} pentru a selecta fișiere',
   back: 'Înapoi',
   browse: 'rasfoiește',
   browseFiles: 'rasfoiește',
@@ -27,7 +32,8 @@ ro_RO.strings = {
   chooseFiles: 'Selectează fișiere',
   closeModal: 'Închide fereastra',
   companionError: 'Conexiunea către Companion nu a reuși',
-  companionUnauthorizeHint: 'Pentru a autoriza contul %{provider}, navigați către %{url}',
+  companionUnauthorizeHint:
+    'Pentru a autoriza contul %{provider}, navigați către %{url}',
   complete: 'Complet',
   connectedToInternet: 'Conectat la Internet',
   copyLink: 'Copiază link',
@@ -36,7 +42,8 @@ ro_RO.strings = {
   creatingAssembly: 'Se pregătește încărcarea...',
   creatingAssemblyFailed: 'Transloadit: Nu se poate crea un Assembly',
   dashboardTitle: 'Încărcare fișier',
-  dashboardWindowTitle: 'Fereastră încărcare fișier (Apasă tasta escape pentru a închide)',
+  dashboardWindowTitle:
+    'Fereastră încărcare fișier (Apasă tasta escape pentru a închide)',
   dataUploadedOfTotal: '%{complete} din %{total}',
   done: 'Finalizat',
   dropHereOr: 'Trage fișierele aici sau %{browse}',
@@ -44,9 +51,12 @@ ro_RO.strings = {
   dropPasteBoth: 'Trage fișierele aici, copy/paste sau %{browse}',
   dropPasteFiles: 'Trage fișierele aici, copy/paste sau %{browse}',
   dropPasteFolders: 'Trage fișierele aici, copy/paste sau %{browse}',
-  dropPasteImportBoth: 'Trage fișierele aici, copy/paste, %{browse} sau importă din:',
-  dropPasteImportFiles: 'Trage fișierele aici, copy/paste, %{browse} sau importă din:',
-  dropPasteImportFolders: 'Trage fișierele aici, copy/paste, %{browse} sau importă din:',
+  dropPasteImportBoth:
+    'Trage fișierele aici, copy/paste, %{browse} sau importă din:',
+  dropPasteImportFiles:
+    'Trage fișierele aici, copy/paste, %{browse} sau importă din:',
+  dropPasteImportFolders:
+    'Trage fișierele aici, copy/paste, %{browse} sau importă din:',
   editFile: 'Editează fișier',
   editing: 'Se editează %{file}',
   emptyFolderAdded: 'Nu s-au adăugat fișiere, directorul este gol',
@@ -54,7 +64,8 @@ ro_RO.strings = {
   enterCorrectUrl: 'URL incorect: Introduceți un link direct către fișier',
   enterUrlToImport: 'Introduceți URL pentru a importa fișierul',
   exceedsSize: 'Fișierul depășește dimensiunea maximă permisă de %{size}',
-  failedToFetch: 'Companion-ul nu a putut procesa URL-ul, asigură-te că e corect introdus',
+  failedToFetch:
+    'Companion-ul nu a putut procesa URL-ul, asigură-te că e corect introdus',
   failedToUpload: '%{file} nu a putut fi încărcat',
   fileSource: 'Sursă fișier: %{name}',
   filesUploadedOfTotal: {
@@ -73,7 +84,7 @@ ro_RO.strings = {
   loading: 'Încărcare...',
   logOut: 'Delogare',
   myDevice: 'Dispozitivul meu',
-  noDuplicates: 'Nu se poate adăuga fișierul \'%{fileName}\', acesta există deja',
+  noDuplicates: "Nu se poate adăuga fișierul '%{fileName}', acesta există deja",
   noFilesFound: 'Nu sunt fișiere sau directoare aici',
   noInternetConnection: 'Fără conexiune la internet',
   noMoreFilesAllowed: 'Nu se pot adăuga fișiere noi: încărcare în curs',
@@ -87,7 +98,8 @@ ro_RO.strings = {
     '1': 'Se procesează %{smart_count} fișiere',
   },
   recordingLength: 'Durată înregistrare %{recording_length}',
-  recordingStoppedMaxSize: 'Înregistrarea a fost oprită pentru că a depășit dimensiunea maximă permisă',
+  recordingStoppedMaxSize:
+    'Înregistrarea a fost oprită pentru că a depășit dimensiunea maximă permisă',
   removeFile: 'Elimină fișier',
   resetFilter: 'Resetează filtre',
   resume: 'Reia',
@@ -143,7 +155,10 @@ ro_RO.strings = {
   },
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.ro_RO = ro_RO
 }
 

+ 24 - 10
packages/@uppy/locales/src/ru_RU.js → packages/@uppy/locales/src/ru_RU.ts

@@ -1,5 +1,8 @@
-const ru_RU = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const ru_RU: Locale<0 | 1 | 2> = {
+  strings: {},
+  pluralize(n) {
     if (n % 10 === 1 && n % 100 !== 11) {
       return 0
     }
@@ -15,9 +18,11 @@ const ru_RU = {
 ru_RU.strings = {
   addMoreFiles: 'Добавить еще файлы',
   addingMoreFiles: 'Добавление дополнительных файлов',
-  allowAccessDescription: 'Чтобы сделать фото или видео, пожалуйста, разрешите доступ к камере для этого сайта',
+  allowAccessDescription:
+    'Чтобы сделать фото или видео, пожалуйста, разрешите доступ к камере для этого сайта',
   allowAccessTitle: 'Пожалуйста, разрешите доступ к вашей камере',
-  authenticateWithTitle: 'Пожалуйста, авторизуйтесь в %{pluginName}, чтобы выбрать файлы',
+  authenticateWithTitle:
+    'Пожалуйста, авторизуйтесь в %{pluginName}, чтобы выбрать файлы',
   authenticateWith: 'Подключиться к %{pluginName}',
   back: 'Назад',
   addMore: 'Добавить еще',
@@ -38,7 +43,8 @@ ru_RU.strings = {
   creatingAssembly: 'Подготовка загрузки...',
   creatingAssemblyFailed: 'Transloadit: не удалось создать Assembly',
   dashboardTitle: 'Загрузчик файлов',
-  dashboardWindowTitle: 'Окно загрузчика файлов (нажмите escape, чтобы закрыть)',
+  dashboardWindowTitle:
+    'Окно загрузчика файлов (нажмите escape, чтобы закрыть)',
   dataUploadedOfTotal: '%{complete} из %{total}',
   done: 'Готово',
   dropHereOr: 'Перетащите файлы или %{browse}',
@@ -46,17 +52,22 @@ ru_RU.strings = {
   dropPasteBoth: 'Перетащите файлы, вставьте или %{browse}',
   dropPasteFiles: 'Перетащите файлы, вставьте или %{browse}',
   dropPasteFolders: 'Перетащите файлы, вставьте или %{browse}',
-  dropPasteImportBoth: 'Перетащите файлы, вставьте, %{browse} или импортируйте из:',
-  dropPasteImportFiles: 'Перетащите файлы, вставьте, %{browse} или импортируйте из:',
-  dropPasteImportFolders: 'Перетащите файлы, вставьте, %{browse} или импортируйте из:',
+  dropPasteImportBoth:
+    'Перетащите файлы, вставьте, %{browse} или импортируйте из:',
+  dropPasteImportFiles:
+    'Перетащите файлы, вставьте, %{browse} или импортируйте из:',
+  dropPasteImportFolders:
+    'Перетащите файлы, вставьте, %{browse} или импортируйте из:',
   editFile: 'Редактировать файл',
   editing: 'Редактируется %{file}',
   emptyFolderAdded: 'Файлы не были добавлены — папка пуста',
   encoding: 'Обработка...',
-  enterCorrectUrl: 'Неправильный адрес: пожалуйста, убедитесь что вы используете прямую ссылку на файл',
+  enterCorrectUrl:
+    'Неправильный адрес: пожалуйста, убедитесь что вы используете прямую ссылку на файл',
   enterUrlToImport: 'Введите адрес, чтобы импортировать файл',
   exceedsSize: 'Этот файл больше максимально разрешенного размера в %{size}',
-  failedToFetch: 'Companion не смог загрузить файл по ссылке, пожалуйста, убедитесь, что адрес верный',
+  failedToFetch:
+    'Companion не смог загрузить файл по ссылке, пожалуйста, убедитесь, что адрес верный',
   failedToUpload: 'Ошибка загрузки %{file}',
   fileSource: 'Источник файла: %{name}',
   filesUploadedOfTotal: {
@@ -152,7 +163,10 @@ ru_RU.strings = {
   openFolderNamed: 'Открыть папку %{name}',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.ru_RU = ru_RU
 }
 

+ 28 - 21
packages/@uppy/locales/src/sk_SK.js → packages/@uppy/locales/src/sk_SK.ts

@@ -1,5 +1,8 @@
-const sk_SK = {
-  pluralize (count) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const sk_SK: Locale<0 | 1> = {
+  strings: {},
+  pluralize(count) {
     if (count === 1) {
       return 0
     }
@@ -11,18 +14,19 @@ sk_SK.strings = {
   addBulkFilesFailed: {
     '0': 'Súbor %{smart_count} sa nepodarilo pridať z dôvodu vnútornej chyby',
     '1': 'Nepodarilo sa pridať %{smart_count} súbory z dôvodu vnútorných chýb',
-    '2': 'Nepodarilo sa pridať %{smart_count} súborov z dôvodu vnútorných chýb',
   },
   addMore: 'Pridať ďalšie',
   addMoreFiles: 'Pridať ďalšie súbory',
   addingMoreFiles: 'Pridávajú sa ďalšie súbory',
-  allowAccessDescription: 'Pokiaľ chcete urobiť fotografiu alebo nahrať video vaším zariadením, povoľte prosím prístup ku kamere.',
+  allowAccessDescription:
+    'Pokiaľ chcete urobiť fotografiu alebo nahrať video vaším zariadením, povoľte prosím prístup ku kamere.',
   allowAccessTitle: 'Povoľte prístup ku kamere',
   aspectRatioLandscape: 'Orezať na šírku (16:9)',
   aspectRatioPortrait: 'Orezať na výšku (9:16)',
   aspectRatioSquare: 'Orezať do štvorca',
   authenticateWith: 'Pripojiť k %{pluginName}',
-  authenticateWithTitle: 'Prosím príhláste sa k %{pluginName} pre výber súborov',
+  authenticateWithTitle:
+    'Prosím príhláste sa k %{pluginName} pre výber súborov',
   back: 'Späť',
   backToSearch: 'Späť na vyhľadávanie',
   browse: 'vyberte',
@@ -32,7 +36,8 @@ sk_SK.strings = {
   chooseFiles: 'Vyberte súbory',
   closeModal: 'Zavrieť okno',
   companionError: 'Spojenie s modulom Companion sa nepodarilo',
-  companionUnauthorizeHint: 'Pokiaľ nechcete povoliť prístup k účtu %{provider}, prosím prejdite na túto adresu %{url}',
+  companionUnauthorizeHint:
+    'Pokiaľ nechcete povoliť prístup k účtu %{provider}, prosím prejdite na túto adresu %{url}',
   complete: 'Hotovo',
   connectedToInternet: 'Pripojené k internetu',
   copyLink: 'Kopírovať odkaz',
@@ -41,7 +46,8 @@ sk_SK.strings = {
   creatingAssembly: 'Pripravuje sa nahrávanie...',
   creatingAssemblyFailed: 'Transloadit: Nepodarilo sa vytvoriť Assembly',
   dashboardTitle: 'Nahrať súbory',
-  dashboardWindowTitle: 'Okno na nahrávanie súborov. (Stlačením ESC ho zavriete)',
+  dashboardWindowTitle:
+    'Okno na nahrávanie súborov. (Stlačením ESC ho zavriete)',
   dataUploadedOfTotal: '%{complete} z %{total}',
   done: 'Dokončené',
   dropHereOr: 'Presuňte sem súbory alebo %{browse}',
@@ -56,11 +62,14 @@ sk_SK.strings = {
   editing: 'Úprava %{file}',
   emptyFolderAdded: 'Neboli pridané žiadne súbory, pretože adresár je prázdny.',
   encoding: 'Konvertovanie...',
-  enterCorrectUrl: 'Nesprávna adresa URL: Uistite sa, že zadávate priamy odkaz na súbor',
+  enterCorrectUrl:
+    'Nesprávna adresa URL: Uistite sa, že zadávate priamy odkaz na súbor',
   enterTextToSearch: 'Zadajte text pre vyhľadanie obrázkov',
   enterUrlToImport: 'Ak chcete importovať súbor, zadajte adresu URL',
-  exceedsSize: 'Tento súbor presahuje maximálnu povolenú veľkosť súboru %{size}',
-  failedToFetch: 'Nepodarilo sa načítať túto webovú adresu. Skontrolujte, či je správna',
+  exceedsSize:
+    'Tento súbor presahuje maximálnu povolenú veľkosť súboru %{size}',
+  failedToFetch:
+    'Nepodarilo sa načítať túto webovú adresu. Skontrolujte, či je správna',
   failedToUpload: 'Nepodarilo sa nahrať súbor %{file}',
   fileSource: 'Zdroj súboru: %{name}',
   filesUploadedOfTotal: {
@@ -73,7 +82,6 @@ sk_SK.strings = {
   folderAdded: {
     '0': 'Pridaný %{smart_count} súbor zo zložky %{folder}',
     '1': 'Pridané %{smart_count} súbory zo zložky %{folder}',
-    '2': 'Pridaných %{smart_count} súborov zo zložky %{folder}',
   },
   generatingThumbnails: 'Vytváram miniatury...',
   import: 'Importovať',
@@ -83,9 +91,11 @@ sk_SK.strings = {
   logOut: 'Odhlásiť',
   micDisabled: 'Užívateľ odmietol prístup k mikrofónu',
   myDevice: 'Moje zariadenie',
-  noCameraDescription: 'Ak chcete urobiť fotku alebo nahrať video, zapnite kameru',
+  noCameraDescription:
+    'Ak chcete urobiť fotku alebo nahrať video, zapnite kameru',
   noCameraTitle: 'Kamera nie je k dispozícii',
-  noDuplicates: 'Nemôžete pridať duplikátny súbor \'%{fileName}\', ktorý už existuje',
+  noDuplicates:
+    "Nemôžete pridať duplikátny súbor '%{fileName}', ktorý už existuje",
   noFilesFound: 'Nemáte pridané žiadne súbory ani zložky',
   noInternetConnection: 'Žiadne internetové pripojenie',
   noMoreFilesAllowed: 'Počas nahrávania nemôžete pridať ďalšie súbory',
@@ -100,7 +110,8 @@ sk_SK.strings = {
   },
   recording: 'Nahrávanie',
   recordingLength: 'Dĺžka záznamu %{recording_length}',
-  recordingStoppedMaxSize: 'Nahrávanie sa zastavilo, pretože veľkosť súboru sa chystá prekročiť limit',
+  recordingStoppedMaxSize:
+    'Nahrávanie sa zastavilo, pretože veľkosť súboru sa chystá prekročiť limit',
   removeFile: 'Odstrániť súbor',
   resetFilter: 'Zrušiť filter',
   resume: 'Pokračovať',
@@ -135,46 +146,42 @@ sk_SK.strings = {
   uploadXFiles: {
     '0': 'Nahrať %{smart_count} súbor',
     '1': 'Nahrať %{smart_count} súbory',
-    '2': 'Nahrať %{smart_count} súborov',
   },
   uploadXNewFiles: {
     '0': 'Nahrať +%{smart_count} súbor',
     '1': 'Nahrať +%{smart_count} súbory',
-    '2': 'Nahrať +%{smart_count} súborov',
   },
   uploading: 'Nahrávanie',
   uploadingXFiles: {
     '0': 'Nahrávám %{smart_count} súbor',
     '1': 'Nahrávám %{smart_count} súbory',
-    '2': 'Nahrávám %{smart_count} súborov',
   },
   xFilesSelected: {
     '0': '%{smart_count} vybratý súbor',
     '1': '%{smart_count} vybrané súbory',
-    '2': '%{smart_count} vybraných súborov',
   },
   xMoreFilesAdded: {
     '0': '%{smart_count} ďalší pridaný súbor',
     '1': '%{smart_count} ďalšie pridané súbory',
-    '2': '%{smart_count} ďalších pridaných súborov',
   },
   xTimeLeft: '%{time} zostáva',
   youCanOnlyUploadFileTypes: 'Môžete nahrať iba tieto typy súborov: %{types}',
   youCanOnlyUploadX: {
     '0': 'Môžete nahrať iba %{smart_count} súbor',
     '1': 'Môžete nahrať iba %{smart_count} súbory',
-    '2': 'Môžete nahrať iba %{smart_count} súborov',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Musíte vybrať aspoň %{smart_count} súbor',
     '1': 'Musíte vybrať aspoň %{smart_count} súbory',
-    '2': 'Musíte vybrať aspoň %{smart_count} súborov',
   },
   zoomIn: 'Priblížiť',
   zoomOut: 'Oddialiť',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.sk_SK = sk_SK
 }
 

+ 32 - 29
packages/@uppy/locales/src/sr_RS_Cyrillic.js → packages/@uppy/locales/src/sr_RS_Cyrillic.ts

@@ -1,13 +1,25 @@
-const sr_RS_Cyrillic = {}
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const sr_RS_Cyrillic: Locale<0 | 1> = {
+  strings: {},
+  pluralize(count) {
+    if (count === 1) {
+      return 0
+    }
+    return 1
+  },
+}
 
 sr_RS_Cyrillic.strings = {
   addMore: 'Додај још',
   addMoreFiles: 'Додај још датотека',
   addingMoreFiles: 'Додавање датотека',
-  allowAccessDescription: 'Молимо Вас, дозволите приступ Вашој камери, како бисте могли да је користите за снимање фотографија и видео записа.',
+  allowAccessDescription:
+    'Молимо Вас, дозволите приступ Вашој камери, како бисте могли да је користите за снимање фотографија и видео записа.',
   allowAccessTitle: 'Молимо Вас, дозволите приступ Вашој камери',
   authenticateWith: 'Повежи се путем %{pluginName}',
-  authenticateWithTitle: 'Молимо Вас да се пријавите путем %{pluginName} како бисте преузели датотеке',
+  authenticateWithTitle:
+    'Молимо Вас да се пријавите путем %{pluginName} како бисте преузели датотеке',
   back: 'Назад',
   browse: 'потражи',
   browseFiles: 'потражи',
@@ -24,7 +36,8 @@ sr_RS_Cyrillic.strings = {
   creatingAssembly: 'Припремање отпремања...',
   creatingAssemblyFailed: 'Transloadit: не могу да направим Assembly',
   dashboardTitle: 'Отпремање датотека',
-  dashboardWindowTitle: 'Прозор за отпремање датотека (притирните ESC за излаз)',
+  dashboardWindowTitle:
+    'Прозор за отпремање датотека (притирните ESC за излаз)',
   dataUploadedOfTotal: '%{complete} од %{total}',
   done: 'Завршено',
   dropHereOr: 'Спусти датотеке овде или %{browse}',
@@ -32,9 +45,12 @@ sr_RS_Cyrillic.strings = {
   dropPasteBoth: 'Спусти датотеке овде, уметни или %{browse}',
   dropPasteFiles: 'Спусти датотеке овде, уметни или %{browse}',
   dropPasteFolders: 'Спусти датотеке овде, уметни или %{browse}',
-  dropPasteImportBoth: 'Спусти датотеке овде, уметни (енг. "paste"), %{browse} или преузми са',
-  dropPasteImportFiles: 'Спусти датотеке овде, уметни (енг. "paste"), %{browse} или преузми са',
-  dropPasteImportFolders: 'Спусти датотеке овде, уметни (енг. "paste"), %{browse} или преузми са',
+  dropPasteImportBoth:
+    'Спусти датотеке овде, уметни (енг. "paste"), %{browse} или преузми са',
+  dropPasteImportFiles:
+    'Спусти датотеке овде, уметни (енг. "paste"), %{browse} или преузми са',
+  dropPasteImportFolders:
+    'Спусти датотеке овде, уметни (енг. "paste"), %{browse} или преузми са',
   editFile: 'Измени датотеку',
   editing: 'Мењање  %{file}',
   emptyFolderAdded: 'Ни једна датотека није додата из празног фолдера',
@@ -42,20 +58,19 @@ sr_RS_Cyrillic.strings = {
   enterCorrectUrl: 'Погрешан URL: унесите тачну путању до датотеке',
   enterUrlToImport: 'Унесите URL (путању) до датотеке',
   exceedsSize: 'Ова датотека премашује највећу дозвољену величину од %{size}',
-  failedToFetch: 'Companion није успео да допре до дате адресе (URL), проверите исправност адресе',
+  failedToFetch:
+    'Companion није успео да допре до дате адресе (URL), проверите исправност адресе',
   failedToUpload: 'Број неуспело отпремљених датотека: %{file}',
   fileSource: 'Датотека: %{name}',
   filesUploadedOfTotal: {
     '0': '%{complete}. Укупно отремљених датотека: %{smart_count}',
     '1': '%{complete}. Укупно отремљених датотека: %{smart_count}',
-    '2': '%{complete}. Укупно отремљених датотека: %{smart_count}',
   },
   filter: 'Филтер',
   finishEditingFile: 'Заврши мењање фајла',
   folderAdded: {
     '0': 'Број датотека преузетих из %{folder}: %{smart_count}',
     '1': 'Број датотека преузетих из %{folder}: %{smart_count}',
-    '2': 'Број датотека преузетих из %{folder}: %{smart_count}',
   },
   import: 'Преузми',
   importFrom: 'Преузми са %{name}',
@@ -71,7 +86,6 @@ sr_RS_Cyrillic.strings = {
   processingXFiles: {
     '0': 'Обрада датотеке',
     '1': 'Број датотека које се обрађују: %{smart_count}',
-    '2': 'Број датотека које се обрађују: %{smart_count}',
   },
   removeFile: 'Уклони дадотеку',
   resetFilter: 'Избриши филтер',
@@ -83,13 +97,13 @@ sr_RS_Cyrillic.strings = {
   selectX: {
     '0': 'Изабери датотеку',
     '1': 'Изабери %{smart_count}',
-    '2': 'Изабери %{smart_count}',
   },
   smile: 'Осмех!',
   startRecording: 'Започни снимање видео записа',
   stopRecording: 'Заустави снимање видео записа',
   takePicture: 'Сними фотографију',
-  timedOut: 'Прекидамо отпремање јер је застало. Број секунди застоја: %{seconds}.',
+  timedOut:
+    'Прекидамо отпремање јер је застало. Број секунди застоја: %{seconds}.',
   upload: 'Отпреми',
   uploadComplete: 'Отпремање је завршено у целости',
   uploadFailed: 'Отпремање није успело',
@@ -97,55 +111,44 @@ sr_RS_Cyrillic.strings = {
   uploadXFiles: {
     '0': 'Отпреми датотеку',
     '1': 'Отпреми датотеке. Укупно: %{smart_count}',
-    '2': 'Отпреми датотеке. Укупно: %{smart_count}',
   },
   uploadXNewFiles: {
     '0': 'Отпреми +%{smart_count} datoteku',
     '1': 'Отпреми датотеке. Укупно: +%{smart_count}',
-    '2': 'Отпреми датотеке. Укупно: +%{smart_count}',
   },
   uploading: 'Отпремање',
   uploadingXFiles: {
     '0': 'Број датотека које се тренутно отпремају: %{smart_count}',
     '1': 'Број датотека које се тренутно отпремају: %{smart_count}',
-    '2': 'Број датотека које се тренутно отпремају: %{smart_count}',
   },
   xFilesSelected: {
     '0': 'Број датотека за отпремање: %{smart_count}',
     '1': 'Број датотека за отпремање: %{smart_count}',
-    '2': 'Број датотека за отпремање: %{smart_count}',
   },
   xMoreFilesAdded: {
     '0': 'Број додатих датотека: %{smart_count}',
     '1': 'Број додатих датотека: %{smart_count}',
-    '2': 'Број додатих датотека: %{smart_count}',
   },
   xTimeLeft: 'Преостало време %{time} ',
   youCanOnlyUploadFileTypes: 'Можете да отпремите само: %{types}',
   youCanOnlyUploadX: {
     '0': 'Дозвољени број датотека за отпремање: %{smart_count}',
     '1': 'Дозвољени број датотека за отпремање: %{smart_count}',
-    '2': 'Дозвољени број датотека за отпремање: %{smart_count}',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Изаберите бар једну датотеку',
     '1': 'Изаберите датотеке. Најмање: %{smart_count}',
-    '2': 'Изаберите датотеке. Најмање: %{smart_count}',
   },
   selectFileNamed: 'Изаберите фајл %{name}',
   unselectFileNamed: 'Искључите фајл %{name}',
   openFolderNamed: 'Отвори фолдер %{name}',
 }
 
-sr_RS_Cyrillic.pluralize = function pluralize (n) {
-  if (n === 1) {
-    return 0
-  }
-  return 1
-}
-
-if (typeof window !== 'undefined' && typeof window.Uppy !== 'undefined') {
-  window.Uppy.locales.sr_RS_Cyrillic = sr_RS_Cyrillic
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
+if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
+  globalThis.Uppy.locales.sr_RS_Cyrillic = sr_RS_Cyrillic
 }
 
 export default sr_RS_Cyrillic

+ 32 - 29
packages/@uppy/locales/src/sr_RS_Latin.js → packages/@uppy/locales/src/sr_RS_Latin.ts

@@ -1,13 +1,25 @@
-const sr_RS_Latin = {}
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const sr_RS_Latin: Locale<0 | 1> = {
+  strings: {},
+  pluralize(count) {
+    if (count === 1) {
+      return 0
+    }
+    return 1
+  },
+}
 
 sr_RS_Latin.strings = {
   addMore: 'Dodaj još',
   addMoreFiles: 'Dodaj još datoteka',
   addingMoreFiles: 'Dodavanje datoteka',
-  allowAccessDescription: 'Molimo Vas, dozvolite pristup Vašoj kameri, kako biste mogli da je koristite za snimanje fotografija i video zapisa.',
+  allowAccessDescription:
+    'Molimo Vas, dozvolite pristup Vašoj kameri, kako biste mogli da je koristite za snimanje fotografija i video zapisa.',
   allowAccessTitle: 'Molimo Vas, dozvolite pristup Vašoj kameri',
   authenticateWith: 'Poveži se putem %{pluginName}',
-  authenticateWithTitle: 'Molimo Vas da se prijavite putem %{pluginName} kako biste preuzeli datoteke',
+  authenticateWithTitle:
+    'Molimo Vas da se prijavite putem %{pluginName} kako biste preuzeli datoteke',
   back: 'Nazad',
   browse: 'potraži',
   browseFiles: 'potraži',
@@ -24,7 +36,8 @@ sr_RS_Latin.strings = {
   creatingAssembly: 'Pripremanje otpremanja...',
   creatingAssemblyFailed: 'Transloadit: ne mogu da napravim Assembly',
   dashboardTitle: 'Otpremanje datoteka',
-  dashboardWindowTitle: 'Prozor za otpremanje datoteka (pritirnite ESC za izlaz)',
+  dashboardWindowTitle:
+    'Prozor za otpremanje datoteka (pritirnite ESC za izlaz)',
   dataUploadedOfTotal: '%{complete} od %{total}',
   done: 'Završeno',
   dropHereOr: 'Spusti datoteke ovde ili %{browse}',
@@ -32,9 +45,12 @@ sr_RS_Latin.strings = {
   dropPasteBoth: 'Spusti datoteke ovde, umetni ili %{browse}',
   dropPasteFiles: 'Spusti datoteke ovde, umetni ili %{browse}',
   dropPasteFolders: 'Spusti datoteke ovde, umetni ili %{browse}',
-  dropPasteImportBoth: 'Spusti datoteke ovde, umetni (eng. "paste"), %{browse} ili preuzmi sa',
-  dropPasteImportFiles: 'Spusti datoteke ovde, umetni (eng. "paste"), %{browse} ili preuzmi sa',
-  dropPasteImportFolders: 'Spusti datoteke ovde, umetni (eng. "paste"), %{browse} ili preuzmi sa',
+  dropPasteImportBoth:
+    'Spusti datoteke ovde, umetni (eng. "paste"), %{browse} ili preuzmi sa',
+  dropPasteImportFiles:
+    'Spusti datoteke ovde, umetni (eng. "paste"), %{browse} ili preuzmi sa',
+  dropPasteImportFolders:
+    'Spusti datoteke ovde, umetni (eng. "paste"), %{browse} ili preuzmi sa',
   editFile: 'Izmeni datoteku',
   editing: 'Menjanje %{file}',
   emptyFolderAdded: 'Ni jedna datoteka nije dodata iz praznog foldera',
@@ -42,20 +58,19 @@ sr_RS_Latin.strings = {
   enterCorrectUrl: 'Pogrešan URL: unesite tačnu putanju do datoteke',
   enterUrlToImport: 'Unesite URL (putanju) do datoteke',
   exceedsSize: 'Ova datoteka premašuje najveću dozvoljenu veličinu od %{size}',
-  failedToFetch: 'Companion nije uspeo da dopre do date adrese (URL), proverite ispravnost adrese',
+  failedToFetch:
+    'Companion nije uspeo da dopre do date adrese (URL), proverite ispravnost adrese',
   failedToUpload: 'Broj neuspelo otpremljenih datoteka: %{file}',
   fileSource: 'Datoteka: %{name}',
   filesUploadedOfTotal: {
     '0': '%{complete}. Ukupno otremljenih datoteka: %{smart_count}',
     '1': '%{complete}. Ukupno otremljenih datoteka: %{smart_count}',
-    '2': '%{complete}. Ukupno otremljenih datoteka: %{smart_count}',
   },
   filter: 'Filter',
   finishEditingFile: 'Završi menjanje fajla',
   folderAdded: {
     '0': 'Broj datoteka preuzetih iz %{folder}: %{smart_count}',
     '1': 'Broj datoteka preuzetih iz %{folder}: %{smart_count}',
-    '2': 'Broj datoteka preuzetih iz %{folder}: %{smart_count}',
   },
   import: 'Preuzmi',
   importFrom: 'Preuzmi sa %{name}',
@@ -71,7 +86,6 @@ sr_RS_Latin.strings = {
   processingXFiles: {
     '0': 'Obrada datoteke',
     '1': 'Broj datoteka koje se obrađuju: %{smart_count}',
-    '2': 'Broj datoteka koje se obrađuju: %{smart_count}',
   },
   removeFile: 'Ukloni dadoteku',
   resetFilter: 'Izbriši filter',
@@ -83,13 +97,13 @@ sr_RS_Latin.strings = {
   selectX: {
     '0': 'Izaberi datoteku',
     '1': 'Izaberi %{smart_count}',
-    '2': 'Izaberi %{smart_count}',
   },
   smile: 'Osmeh!',
   startRecording: 'Započni snimanje video zapisa',
   stopRecording: 'Zaustavi snimanje video zapisa',
   takePicture: 'Snimi fotografiju',
-  timedOut: 'Prekidamo otpremanje jer je zastalo. Broj sekundi zastoja: %{seconds}.',
+  timedOut:
+    'Prekidamo otpremanje jer je zastalo. Broj sekundi zastoja: %{seconds}.',
   upload: 'Otpremi',
   uploadComplete: 'Otpremanje je završeno u celosti',
   uploadFailed: 'Otpremanje nije uspelo',
@@ -97,55 +111,44 @@ sr_RS_Latin.strings = {
   uploadXFiles: {
     '0': 'Otpremi datoteku',
     '1': 'Otpremi datoteke. Ukupno: %{smart_count}',
-    '2': 'Otpremi datoteke. Ukupno: %{smart_count}',
   },
   uploadXNewFiles: {
     '0': 'Otpremi +%{smart_count} datoteku',
     '1': 'Otpremi datoteke. Ukupno: +%{smart_count}',
-    '2': 'Otpremi datoteke. Ukupno: +%{smart_count}',
   },
   uploading: 'Otpremanje',
   uploadingXFiles: {
     '0': 'Broj datoteka koje se trenutno otpremaju: %{smart_count}',
     '1': 'Broj datoteka koje se trenutno otpremaju: %{smart_count}',
-    '2': 'Broj datoteka koje se trenutno otpremaju: %{smart_count}',
   },
   xFilesSelected: {
     '0': 'Broj datoteka za otpremanje: %{smart_count}',
     '1': 'Broj datoteka za otpremanje: %{smart_count}',
-    '2': 'Broj datoteka za otpremanje: %{smart_count}',
   },
   xMoreFilesAdded: {
     '0': 'Broj dodatih datoteka: %{smart_count}',
     '1': 'Broj dodatih datoteka: %{smart_count}',
-    '2': 'Broj dodatih datoteka: %{smart_count}',
   },
   xTimeLeft: 'Preostalo vreme %{time} ',
   youCanOnlyUploadFileTypes: 'Možete da otpremite samo: %{types}',
   youCanOnlyUploadX: {
     '0': 'Dozvoljeni broj datoteka za otpremanje: %{smart_count}',
     '1': 'Dozvoljeni broj datoteka za otpremanje: %{smart_count}',
-    '2': 'Dozvoljeni broj datoteka za otpremanje: %{smart_count}',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Izaberite bar jednu datoteku',
     '1': 'Izaberite datoteke. Najmanje: %{smart_count}',
-    '2': 'Izaberite datoteke. Najmanje: %{smart_count}',
   },
   selectFileNamed: 'Izaberite fajl %{name}',
   unselectFileNamed: 'Isključite fajl %{name}',
   openFolderNamed: 'Otvori folder %{name}',
 }
 
-sr_RS_Latin.pluralize = function pluralize (n) {
-  if (n === 1) {
-    return 0
-  }
-  return 1
-}
-
-if (typeof window !== 'undefined' && typeof window.Uppy !== 'undefined') {
-  window.Uppy.locales.sr_RS_Latin = sr_RS_Latin
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
+if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
+  globalThis.Uppy.locales.sr_RS_Latin = sr_RS_Latin
 }
 
 export default sr_RS_Latin

+ 24 - 21
packages/@uppy/locales/src/sv_SE.js → packages/@uppy/locales/src/sv_SE.ts

@@ -1,5 +1,8 @@
-const sv_SE = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const sv_SE: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -11,7 +14,8 @@ sv_SE.strings = {
   addMore: 'Lägg till',
   addMoreFiles: 'Lägg till filer',
   addingMoreFiles: 'Lägger till fler filer',
-  allowAccessDescription: 'För att kunna ta bilder eller spela in video behöver du ge sidan behörighet att använda din kamera.',
+  allowAccessDescription:
+    'För att kunna ta bilder eller spela in video behöver du ge sidan behörighet att använda din kamera.',
   allowAccessTitle: 'Tillåt användning av kameran',
   authenticateWith: 'Anslut till %{pluginName}',
   authenticateWithTitle: 'Anslut till %{pluginName} för att välja filer',
@@ -31,7 +35,8 @@ sv_SE.strings = {
   creatingAssembly: 'Förbereder uppladdning...',
   creatingAssemblyFailed: 'Transloadit: Kunde inte skapa Assembly',
   dashboardTitle: 'Filuppladdare',
-  dashboardWindowTitle: 'Uppladdningsfönster (Tryck på Esc-tangenten för att stänga)',
+  dashboardWindowTitle:
+    'Uppladdningsfönster (Tryck på Esc-tangenten för att stänga)',
   dataUploadedOfTotal: '%{complete} av %{total}',
   done: 'Klart',
   dropHereOr: 'Släpp filer här eller %{browse}',
@@ -39,30 +44,34 @@ sv_SE.strings = {
   dropPasteBoth: 'Släpp filer här, klistra in eller %{browse}',
   dropPasteFiles: 'Släpp filer här, klistra in eller %{browse}',
   dropPasteFolders: 'Släpp filer här, klistra in eller %{browse}',
-  dropPasteImportBoth: 'Släpp filer här, klistra in, %{browse} eller importera från',
-  dropPasteImportFiles: 'Släpp filer här, klistra in, %{browse} eller importera från',
-  dropPasteImportFolders: 'Släpp filer här, klistra in, %{browse} eller importera från',
+  dropPasteImportBoth:
+    'Släpp filer här, klistra in, %{browse} eller importera från',
+  dropPasteImportFiles:
+    'Släpp filer här, klistra in, %{browse} eller importera från',
+  dropPasteImportFolders:
+    'Släpp filer här, klistra in, %{browse} eller importera från',
   editFile: 'Redigera fil',
   editing: 'Redigerar %{file}',
   emptyFolderAdded: 'Inga filer lades till från en tom mapp',
   encoding: 'Kodar...',
-  enterCorrectUrl: 'Ogiltig URL: Kontrollera att adressen du anger är en direktlänk till en fil.',
+  enterCorrectUrl:
+    'Ogiltig URL: Kontrollera att adressen du anger är en direktlänk till en fil.',
   enterUrlToImport: 'Ange URL för att importera en fil',
-  exceedsSize: 'Storleken på filen överstiger den tillåtna maxgränsen på %{size}',
-  failedToFetch: 'Companion kunde inte ladda ner filen, kontrollera att adressen är korrekt',
+  exceedsSize:
+    'Storleken på filen överstiger den tillåtna maxgränsen på %{size}',
+  failedToFetch:
+    'Companion kunde inte ladda ner filen, kontrollera att adressen är korrekt',
   failedToUpload: 'Kunde inte ladda upp %{file}',
   fileSource: 'Källa: %{name}',
   filesUploadedOfTotal: {
     '0': '%{complete} av %{smart_count} fil uppladdad',
     '1': '%{complete} av %{smart_count} filer uppladdade',
-    '2': '%{complete} av %{smart_count} filer uppladdade',
   },
   filter: 'Filtrera',
   finishEditingFile: 'Avsluta redigering av filen',
   folderAdded: {
     '0': 'La till %{smart_count} fil från %{folder}',
     '1': 'La till %{smart_count} filer från %{folder}',
-    '2': 'La till %{smart_count} filer från %{folder}',
   },
   import: 'Importera',
   importFrom: 'Importera från %{name}',
@@ -79,7 +88,6 @@ sv_SE.strings = {
   processingXFiles: {
     '0': 'Processerar %{smart_count} fil',
     '1': 'Processerar %{smart_count} filer',
-    '2': 'Processerar %{smart_count} filer',
   },
   removeFile: 'Ta bort fil',
   resetFilter: 'Nollställ filter',
@@ -92,7 +100,6 @@ sv_SE.strings = {
   selectX: {
     '0': 'Välj %{smart_count}',
     '1': 'Välj %{smart_count}',
-    '2': 'Välj %{smart_count}',
   },
   smile: 'Säg omelett!', // translates to "Say cheese!" - which works well in this context in Swedish
   startRecording: 'Starta inspelning',
@@ -107,44 +114,40 @@ sv_SE.strings = {
   uploadXFiles: {
     '0': 'Ladda upp %{smart_count} fil',
     '1': 'Ladda upp %{smart_count} filer',
-    '2': 'Ladda upp %{smart_count} filer',
   },
   uploadXNewFiles: {
     '0': 'Ladda upp %{smart_count} fil',
     '1': 'Ladda upp %{smart_count} filer',
-    '2': 'Ladda upp %{smart_count} filer',
   },
   uploading: 'Laddar upp',
   uploadingXFiles: {
     '0': 'Ladda upp %{smart_count} fil',
     '1': 'Ladda upp %{smart_count} filer',
-    '2': 'Ladda upp %{smart_count} filer',
   },
   xFilesSelected: {
     '0': '%{smart_count} fil vald',
     '1': '%{smart_count} filer valda',
-    '2': '%{smart_count} filer valda',
   },
   xMoreFilesAdded: {
     '0': '%{smart_count} fil tillagd',
     '1': '%{smart_count} filer tillagda',
-    '2': '%{smart_count} filer tillagda',
   },
   xTimeLeft: '%{time} återstår',
   youCanOnlyUploadFileTypes: 'Du kan endast ladda upp: %{types}',
   youCanOnlyUploadX: {
     '0': 'Du kan endast ladda upp %{smart_count} fil',
     '1': 'Du kan endast ladda upp %{smart_count} filer',
-    '2': 'Du kan endast ladda upp %{smart_count} filer',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Du måste välja minst %{smart_count} fil',
     '1': 'Du måste välja minst %{smart_count} filer',
-    '2': 'Du måste välja minst %{smart_count} filer',
   },
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.sv_SE = sv_SE
 }
 

+ 15 - 6
packages/@uppy/locales/src/th_TH.js → packages/@uppy/locales/src/th_TH.ts

@@ -1,5 +1,8 @@
-const th_TH = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const th_TH: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -15,7 +18,8 @@ th_TH.strings = {
   addMore: 'เพิ่ม',
   addMoreFiles: 'เพิ่มไฟล์',
   addingMoreFiles: 'กำลังเพิ่มไฟล์',
-  allowAccessDescription: 'ในการถ่ายภาพหรือบันทึกวิดีโอด้วยกล้องของคุณ โปรดอนุญาตการเข้าถึงกล้อง',
+  allowAccessDescription:
+    'ในการถ่ายภาพหรือบันทึกวิดีโอด้วยกล้องของคุณ โปรดอนุญาตการเข้าถึงกล้อง',
   allowAccessTitle: 'กรุณากดปุ่มยอมรับเพื่อใช้งานกล้อง',
   aspectRatioLandscape: 'ครอบตัดภาพทิวทัศน์ (16:9)',
   aspectRatioPortrait: 'ครอบตัดภาพบุคคล (9:16)',
@@ -31,7 +35,8 @@ th_TH.strings = {
   chooseFiles: 'เลือกไฟล์',
   closeModal: 'ปิดหน้าต่างนี้',
   companionError: 'การเชื่อมต่อกับ Companion ล้มเหลว',
-  companionUnauthorizeHint: 'หากคุณต้องการลงชื่อออกจาก %{provider}, กรุณาไปที่ %{url}',
+  companionUnauthorizeHint:
+    'หากคุณต้องการลงชื่อออกจาก %{provider}, กรุณาไปที่ %{url}',
   complete: 'สำเร็จ',
   connectedToInternet: 'เชื่อมต่อกับอินเทอร์เน็ตสำเร็จ',
   copyLink: 'คัดลอกลิงค์',
@@ -58,7 +63,8 @@ th_TH.strings = {
   enterCorrectUrl: 'URL ไม่ถูกต้อง: โปรดตรวจสอบให้แน่ใจว่าคุณป้อน direct link',
   enterUrlToImport: 'ป้อน URL เพื่อนำเข้าไฟล์',
   exceedsSize: 'ไฟล์นี้มีขนาดเกินขนาดสูงสุดที่อนุญาต %{size}',
-  failedToFetch: 'Companion ไม่สามารถเรียก URL นี้ได้, กรุณาตรวจสอบว่า URL ถูกต้อง',
+  failedToFetch:
+    'Companion ไม่สามารถเรียก URL นี้ได้, กรุณาตรวจสอบว่า URL ถูกต้อง',
   failedToUpload: 'ไม่สามารถอัปโหลด %{file}',
   fileSource: 'ตำแหน่งของไฟล์: %{name}',
   filesUploadedOfTotal: {
@@ -82,7 +88,7 @@ th_TH.strings = {
   myDevice: 'ภาพในเครื่อง',
   noCameraDescription: 'ในการถ่ายภาพหรือบันทึกวิดีโอโปรดเชื่อมต่ออุปกรณ์กล้อง',
   noCameraTitle: 'กล้องไม่พร้อมใช้งาน',
-  noDuplicates: 'ไม่สามารถเพิ่มไฟล์ซ้ำได้ ไฟล์ \'%{fileName}\', มีอยู่แล้ว',
+  noDuplicates: "ไม่สามารถเพิ่มไฟล์ซ้ำได้ ไฟล์ '%{fileName}', มีอยู่แล้ว",
   noFilesFound: 'คุณไม่มีไฟล์หรือโฟลเดอร์ที่นี่',
   noInternetConnection: 'ไม่มีการเชื่อมต่ออินเทอร์เน็ต',
   noMoreFilesAllowed: 'ไม่สามารถเพิ่มไฟล์ใหม่: กำลังอยู่ระหว่างอัพโหลด',
@@ -163,7 +169,10 @@ th_TH.strings = {
   zoomOut: 'ซูมออก',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.th_TH = th_TH
 }
 

+ 20 - 19
packages/@uppy/locales/src/tr_TR.js → packages/@uppy/locales/src/tr_TR.ts

@@ -1,5 +1,8 @@
-const tr_TR = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const tr_TR: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -11,10 +14,12 @@ tr_TR.strings = {
   addMore: 'Daha ekle',
   addMoreFiles: 'Daha fazla dosya ekle',
   addingMoreFiles: 'Daha fazla dosya ekleniyor',
-  allowAccessDescription: 'Kameranızla fotoğraf çekmek veya video kaydetmek için lütfen erişim izni verin.',
+  allowAccessDescription:
+    'Kameranızla fotoğraf çekmek veya video kaydetmek için lütfen erişim izni verin.',
   allowAccessTitle: 'Lütfen kameranıza erişim izni verin',
   authenticateWith: '%{pluginName} ile bağlan',
-  authenticateWithTitle: 'Lütfen dosyaları seçmek için %{pluginName} ile bağlanın',
+  authenticateWithTitle:
+    'Lütfen dosyaları seçmek için %{pluginName} ile bağlanın',
   back: 'Geri',
   browse: 'gözat',
   browseFiles: 'gözat',
@@ -40,13 +45,16 @@ tr_TR.strings = {
   dropPasteFiles: 'Sürükleyip bırak, yapıştır veya %{browse}',
   dropPasteFolders: 'Sürükleyip bırak, yapıştır veya %{browse}',
   dropPasteImportBoth: 'Sürükleyip bırak, yapıştır, %{browse} veya içeri aktar',
-  dropPasteImportFiles: 'Sürükleyip bırak, yapıştır, %{browse} veya içeri aktar',
-  dropPasteImportFolders: 'Sürükleyip bırak, yapıştır, %{browse} veya içeri aktar',
+  dropPasteImportFiles:
+    'Sürükleyip bırak, yapıştır, %{browse} veya içeri aktar',
+  dropPasteImportFolders:
+    'Sürükleyip bırak, yapıştır, %{browse} veya içeri aktar',
   editFile: 'Dosyayı düzenle',
   editing: '%{file} düzenleniyor',
   emptyFolderAdded: 'Klasör boş',
   encoding: 'Çözümleniyor...',
-  enterCorrectUrl: 'Hatalı URL: Lütfen bir dosyaya doğrudan bağlantı girdiğinizden emin olun.',
+  enterCorrectUrl:
+    'Hatalı URL: Lütfen bir dosyaya doğrudan bağlantı girdiğinizden emin olun.',
   enterUrlToImport: 'Dosya URL’sini buraya yapıştırın',
   exceedsSize: 'Bu dosya izin verilen maksimum boyutu aşıyor %{size}',
   failedToFetch: 'Bu URL’den alınamadı, lütfen doğru olduğundan emin olun',
@@ -55,14 +63,12 @@ tr_TR.strings = {
   filesUploadedOfTotal: {
     '0': '%{complete} / %{smart_count} dosya yüklendi',
     '1': '%{complete} / %{smart_count} dosya yüklendi',
-    '2': '%{complete} / %{smart_count} dosya yüklendi',
   },
   filter: 'Filtre',
   finishEditingFile: 'Düzenlemeyi bitir',
   folderAdded: {
     '0': '%{folder} klasöründen %{smart_count} dosya eklendi',
     '1': '%{folder} klasöründen %{smart_count} dosya eklendi',
-    '2': '%{folder} klasöründen %{smart_count} dosya eklendi',
   },
   import: 'Ekle',
   importFrom: '%{name} Ekle',
@@ -78,7 +84,6 @@ tr_TR.strings = {
   processingXFiles: {
     '0': '%{smart_count} dosya işleniyor',
     '1': '%{smart_count} dosya işleniyor',
-    '2': '%{smart_count} dosya işleniyor',
   },
   removeFile: 'Dosyayı kaldır',
   resetFilter: 'Filtreyi temizle',
@@ -90,13 +95,13 @@ tr_TR.strings = {
   selectX: {
     '0': '%{smart_count} seç',
     '1': '%{smart_count} seç',
-    '2': '%{smart_count} seç',
   },
   smile: 'Gülümse!',
   startRecording: 'Video kaydına başla',
   stopRecording: 'Video kaydını durdur',
   takePicture: 'Fotoğraf çek',
-  timedOut: 'Yükleme işlemi %{seconds} saniyeden fazla sürdüğü için iptal edildi.',
+  timedOut:
+    'Yükleme işlemi %{seconds} saniyeden fazla sürdüğü için iptal edildi.',
   upload: 'Yükle',
   uploadComplete: 'Yükleme tamamlandı',
   uploadFailed: 'Yükleme başarısız',
@@ -104,47 +109,43 @@ tr_TR.strings = {
   uploadXFiles: {
     '0': '%{smart_count} dosyayı yükle',
     '1': '%{smart_count} dosyayı yükle',
-    '2': '%{smart_count} dosyayı yükle',
   },
   uploadXNewFiles: {
     '0': '+%{smart_count} dosyayı yükle',
     '1': '+%{smart_count} dosyayı yükle',
-    '2': '+%{smart_count} dosyayı yükle',
   },
   uploading: 'Yükleniyor',
   uploadingXFiles: {
     '0': '%{smart_count} dosya yükleniyor',
     '1': '%{smart_count} dosya yükleniyor',
-    '2': '%{smart_count} dosya yükleniyor',
   },
   xFilesSelected: {
     '0': '%{smart_count} dosya seçildi',
     '1': '%{smart_count} dosya seçildi',
-    '2': '%{smart_count} dosya seçildi',
   },
   xMoreFilesAdded: {
     '0': '%{smart_count} dosya daha eklendi',
     '1': '%{smart_count} dosya daha eklendi',
-    '2': '%{smart_count} dosya daha eklendi',
   },
   xTimeLeft: 'kalan süre %{time}',
   youCanOnlyUploadFileTypes: 'Sadece %{types} yükleyebilirsiniz',
   youCanOnlyUploadX: {
     '0': 'Sadece %{smart_count} dosya yükleyebilirsiniz',
     '1': 'Sadece %{smart_count} dosya yükleyebilirsiniz',
-    '2': 'Sadece %{smart_count} dosya yükleyebilirsiniz',
   },
   youHaveToAtLeastSelectX: {
     '0': 'En az %{smart_count} dosya seçmelisin',
     '1': 'En az %{smart_count} dosya seçmelisin',
-    '2': 'En az %{smart_count} dosya seçmelisin',
   },
   selectFileNamed: 'Dosya Seç %{name}',
   unselectFileNamed: 'Dosya seçimini kaldır %{name}',
   openFolderNamed: 'Açık dosya %{name}',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.tr_TR = tr_TR
 }
 

+ 46 - 25
packages/@uppy/locales/src/uk_UA.js → packages/@uppy/locales/src/uk_UA.ts

@@ -1,5 +1,8 @@
-const uk_UA = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const uk_UA: Locale<0 | 1 | 2> = {
+  strings: {},
+  pluralize(n) {
     if (n % 10 === 1 && n % 100 !== 11) {
       return 0
     }
@@ -22,16 +25,19 @@ uk_UA.strings = {
   addMore: 'Додати ще',
   addMoreFiles: 'Додати ще файли',
   allFilesFromFolderNamed: 'Всі файли з папки %{name}',
-  allowAccessDescription: 'Щоб зробити фото або відео, будь ласка, дозвольте доступ до камери для цього сайту',
+  allowAccessDescription:
+    'Щоб зробити фото або відео, будь ласка, дозвольте доступ до камери для цього сайту',
   allowAccessTitle: 'Будь ласка, дозвольте доступ до вашої камери',
-  allowAudioAccessDescription: 'Для запису звуку, будь ласка, надайте доступ до мікрофону для цього сайту.',
+  allowAudioAccessDescription:
+    'Для запису звуку, будь ласка, надайте доступ до мікрофону для цього сайту.',
   allowAudioAccessTitle: 'Дозвольте доступ до мікрофону',
   aspectRatioLandscape: 'Обрізати альбомний режим (16:9)',
   aspectRatioPortrait: 'Обрізати портрет (9:16)',
   aspectRatioSquare: 'Обрізати квадрат',
   authAborted: 'Автентифікація перервана',
-  authenticateWith: 'Під\'єднатися до %{pluginName}',
-  authenticateWithTitle: 'Будь ласка, авторизуйтесь у %{pluginName}, щоб обрати файли',
+  authenticateWith: "Під'єднатися до %{pluginName}",
+  authenticateWithTitle:
+    'Будь ласка, авторизуйтесь у %{pluginName}, щоб обрати файли',
   back: 'Назад',
   browse: 'оберіть',
   browseFiles: 'оберіть',
@@ -40,19 +46,21 @@ uk_UA.strings = {
   cancelUpload: 'Скасувати завантаження',
   chooseFiles: 'Обрати файли',
   closeModal: 'Закрити вікно',
-  companionError: 'Не вдалося під\'єднатися до Companion',
-  companionUnauthorizeHint: 'Щоб скасувати авторизацію вашого облікового запису %{provider}, перейдіть на %{url}',
+  companionError: "Не вдалося під'єднатися до Companion",
+  companionUnauthorizeHint:
+    'Щоб скасувати авторизацію вашого облікового запису %{provider}, перейдіть на %{url}',
   complete: 'Готово',
   compressedX: 'Збережено %{size} шляхом стискання зображень',
   compressingImages: 'Стиснення зображень...',
-  connectedToInternet: 'Під\'єднано до інтернету',
+  connectedToInternet: "Під'єднано до інтернету",
   copyLink: 'Копіювати посилання',
   copyLinkToClipboardFallback: 'Скопіюйте посилання',
   copyLinkToClipboardSuccess: 'Посилання скопійована в буфер обміну',
   creatingAssembly: 'Підготовка до завантаження...',
   creatingAssemblyFailed: 'Transloadit: не вдалося згенерувати Assembly',
   dashboardTitle: 'Завантажувач файлів',
-  dashboardWindowTitle: 'Вікно завантажувача файлів (натисніть escape, щоб закрити)',
+  dashboardWindowTitle:
+    'Вікно завантажувача файлів (натисніть escape, щоб закрити)',
   dataUploadedOfTotal: '%{complete} із %{total}',
   discardRecordedFile: 'Відкинути записаний файл',
   done: 'Готово',
@@ -61,19 +69,24 @@ uk_UA.strings = {
   dropPasteBoth: 'Перетягніть файли, вставте або %{browse}',
   dropPasteFiles: 'Перетягніть файли, вставте або %{browse}',
   dropPasteFolders: 'Перетягніть файли, вставте або %{browse}',
-  dropPasteImportBoth: 'Перетягніть файли, вставте, %{browse} або імпортуйте з:',
-  dropPasteImportFiles: 'Перетягніть файли, вставте, %{browse} або імпортуйте з:',
-  dropPasteImportFolders: 'Перетягніть файли, вставте, %{browse} або імпортуйте з:',
+  dropPasteImportBoth:
+    'Перетягніть файли, вставте, %{browse} або імпортуйте з:',
+  dropPasteImportFiles:
+    'Перетягніть файли, вставте, %{browse} або імпортуйте з:',
+  dropPasteImportFolders:
+    'Перетягніть файли, вставте, %{browse} або імпортуйте з:',
   editFile: 'Редагувати файл',
   editFileWithFilename: 'Редагувати файл %{file}',
   editing: 'Редагується %{file}',
   emptyFolderAdded: 'Файли не додано — тека порожня',
   encoding: 'Обробка...',
-  enterCorrectUrl: 'Невірна адреса: будь ласка, переконайтеся що ви використовуєте пряме посилання на файл',
+  enterCorrectUrl:
+    'Невірна адреса: будь ласка, переконайтеся що ви використовуєте пряме посилання на файл',
   enterTextToSearch: 'Введіть текст для пошуку зображень',
   enterUrlToImport: 'Введіть адресу, щоб імпортувати файл',
   exceedsSize: 'Цей файл більше максимально дозволеного розміру в %{size}',
-  failedToFetch: 'Companion не зміг завантажити файл за посиланням, будь ласка, переконайтеся, що адреса вірна',
+  failedToFetch:
+    'Companion не зміг завантажити файл за посиланням, будь ласка, переконайтеся, що адреса вірна',
   failedToUpload: 'Помилка завантаження %{file}',
   filesUploadedOfTotal: {
     '0': '%{complete} із %{smart_count} файл завантажено',
@@ -97,19 +110,22 @@ uk_UA.strings = {
   loading: 'Завантаження...',
   logOut: 'Вийти',
   micDisabled: 'Доступ до мікрофона заборонений користувачем',
-  missingRequiredMetaField: 'Відсутні обов\'язкові поля meta',
-  missingRequiredMetaFieldOnFile: 'У %{fileName} відсутні обов\'язкові поля meta',
+  missingRequiredMetaField: "Відсутні обов'язкові поля meta",
+  missingRequiredMetaFieldOnFile:
+    "У %{fileName} відсутні обов'язкові поля meta",
   missingRequiredMetaFields: {
-    '0': 'Відсутнє обов\'язкове поле meta: %{fields}.',
-    '1': 'Відсутні обов\'язкові поля meta: %{fields}.',
-    '2': 'Відсутні обов\'язкові поля meta: %{fields}.',
+    '0': "Відсутнє обов'язкове поле meta: %{fields}.",
+    '1': "Відсутні обов'язкові поля meta: %{fields}.",
+    '2': "Відсутні обов'язкові поля meta: %{fields}.",
   },
   myDevice: 'Мій пристрій',
-  noAudioDescription: 'Для запису аудіо, підключіть мікрофон або інший пристрій введення звуку',
+  noAudioDescription:
+    'Для запису аудіо, підключіть мікрофон або інший пристрій введення звуку',
   noAudioTitle: 'Мікрофон недоступний',
-  noCameraDescription: 'Для того, щоб робити зображення чи запис відео, будь ласка, підключіть пристрій камери',
+  noCameraDescription:
+    'Для того, щоб робити зображення чи запис відео, будь ласка, підключіть пристрій камери',
   noCameraTitle: 'Камера недоступна',
-  noDuplicates: 'Не вдається додати дублікат файлу \'%{fileName}, він уже існує',
+  noDuplicates: "Не вдається додати дублікат файлу '%{fileName}, він уже існує",
   noFilesFound: 'Тут відсутні файли або теки',
   noInternetConnection: 'Відсутнє підключення до мережі Інтернет',
   noMoreFilesAllowed: 'Не вдалося додати більше файлів',
@@ -134,9 +150,11 @@ uk_UA.strings = {
   },
   recording: 'Запис',
   recordingLength: 'Тривалість запису %{recording_length}',
-  recordingStoppedMaxSize: 'Запис зупинено, оскільки розмір файлу перевищить ліміт',
+  recordingStoppedMaxSize:
+    'Запис зупинено, оскільки розмір файлу перевищить ліміт',
   recordVideoBtn: 'Записати Відео',
-  recoveredAllFiles: 'Ми відновили всі файли. Ви можете продовжити завантаження.',
+  recoveredAllFiles:
+    'Ми відновили всі файли. Ви можете продовжити завантаження.',
   recoveredXFiles: {
     '0': 'Ми не змогли повністю відновити 1 файл. Будь ласка, повторно виберіть його і відновіть завантаження.',
     '1': 'Ми не змогли повністю відновити %{smart_count} файли. Будь ласка, повторно виберіть їх і відновіть завантаження.',
@@ -222,7 +240,10 @@ uk_UA.strings = {
   zoomOut: 'Зменшити',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.uk_UA = uk_UA
 }
 

+ 12 - 4
packages/@uppy/locales/src/uz_UZ.js → packages/@uppy/locales/src/uz_UZ.ts

@@ -1,5 +1,8 @@
-const uz_UZ = {
-  pluralize (count) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const uz_UZ: Locale<0 | 1> = {
+  strings: {},
+  pluralize(count) {
     if (count === 1) {
       return 0
     }
@@ -57,12 +60,14 @@ uz_UZ.strings = {
   done: 'Bajarildi',
   dropHereOr: 'Bu yerga tashlang yoki %{browse}',
   dropHint: 'Fayllaringizni shu yerga tashlang',
-  dropPasteBoth: 'Fayllarni bu yerga, %{browseFiles} yoki %{browseFolders} qoldiring.',
+  dropPasteBoth:
+    'Fayllarni bu yerga, %{browseFiles} yoki %{browseFolders} qoldiring.',
   dropPasteFiles: "Fayllarni bu yerga qo'ying yoki %{browseFiles}",
   dropPasteFolders: 'Fayllarni shu yerga yoki %{browseFolders} qoldiring',
   dropPasteImportBoth:
     'Fayllarni bu yerga tashlang, %{browseFiles}, %{browseFolders} yoki import qiling:',
-  dropPasteImportFiles: 'Fayllarni bu yerga tashlang, %{browseFiles} yoki import qiling:',
+  dropPasteImportFiles:
+    'Fayllarni bu yerga tashlang, %{browseFiles} yoki import qiling:',
   dropPasteImportFolders:
     'Fayllarni bu yerga tashlang, %{browseFolders} yoki import qiling:',
   editFile: 'Faylni tahrirlash',
@@ -218,7 +223,10 @@ uz_UZ.strings = {
   zoomOut: 'Kichraytirish',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.uz_UZ = uz_UZ
 }
 

+ 14 - 16
packages/@uppy/locales/src/vi_VN.js → packages/@uppy/locales/src/vi_VN.ts

@@ -1,5 +1,8 @@
-const vi_VN = {
-  pluralize (n) {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const vi_VN: Locale<0 | 1> = {
+  strings: {},
+  pluralize(n) {
     if (n === 1) {
       return 0
     }
@@ -11,7 +14,8 @@ vi_VN.strings = {
   addMore: 'Thêm',
   addMoreFiles: 'Thêm tập tin',
   addingMoreFiles: 'Đang thêm các tập tin',
-  allowAccessDescription: 'Để chụp ảnh hoặc quay video bằng camera, vui lòng cho phép trang web truy cập camera.',
+  allowAccessDescription:
+    'Để chụp ảnh hoặc quay video bằng camera, vui lòng cho phép trang web truy cập camera.',
   allowAccessTitle: 'Vui lòng cho phép truy cập camera',
   authenticateWith: 'Kết nối đến %{pluginName}',
   authenticateWithTitle: 'Xác thực với %{pluginName} để chọn tập tin',
@@ -23,7 +27,8 @@ vi_VN.strings = {
   chooseFiles: 'Chọn tập tin',
   closeModal: 'Đóng cửa sổ',
   companionError: 'Kết nối thất bại',
-  companionUnauthorizeHint: 'Để huỷ uỷ quyền tài khoản %{provider}, truy cập %{url}',
+  companionUnauthorizeHint:
+    'Để huỷ uỷ quyền tài khoản %{provider}, truy cập %{url}',
   complete: 'Xong',
   connectedToInternet: 'Đã kết nối Internet',
   copyLink: 'Sao chép liên kết',
@@ -47,7 +52,8 @@ vi_VN.strings = {
   editing: 'Đang sửa %{file}',
   emptyFolderAdded: 'Không có tập tin nào được thêm từ thư mục trống',
   encoding: 'Đang encode...',
-  enterCorrectUrl: 'URL sai: Đảm bảo rằng bạn đang nhập một liên kết trực tiếp đến một tập tin',
+  enterCorrectUrl:
+    'URL sai: Đảm bảo rằng bạn đang nhập một liên kết trực tiếp đến một tập tin',
   enterUrlToImport: 'Nhập URL để nhập tập tin',
   exceedsSize: 'Tập tin này vượt quá kích thước tối đa cho phép của %{size}',
   failedToFetch: 'Thất bại khi lấy từ URL, hãy sửa lại cho đúng',
@@ -56,14 +62,12 @@ vi_VN.strings = {
   filesUploadedOfTotal: {
     '0': '%{complete} trong số %{smart_count} tập tin đã được tải lên',
     '1': '%{complete} trong số %{smart_count} tập tin đã được tải lên',
-    '2': '%{complete} trong số %{smart_count} tập tin đã được tải lên',
   },
   filter: 'Bộ lọc',
   finishEditingFile: 'Hoàn tất chỉnh sửa tập tin',
   folderAdded: {
     '0': 'Đã thêm %{smart_count} tập tin từ %{folder}',
     '1': 'Đã thêm %{smart_count} tập tin từ %{folder}',
-    '2': 'Đã thêm %{smart_count} tập tin từ %{folder}',
   },
   generatingThumbnails: 'Đang tạo ảnh thu nhỏ...',
   import: 'Nhập',
@@ -81,7 +85,6 @@ vi_VN.strings = {
   processingXFiles: {
     '0': 'Đang xử lí %{smart_count} tập tin',
     '1': 'Đang xử lí %{smart_count} tập tin',
-    '2': 'Đang xử lí %{smart_count} tập tin',
   },
   recordingLength: 'Thời lượng ghi %{recording_length}',
   removeFile: 'Bỏ tập tin',
@@ -95,7 +98,6 @@ vi_VN.strings = {
   selectX: {
     '0': 'Chọn %{smart_count}',
     '1': 'Chọn %{smart_count}',
-    '2': 'Chọn %{smart_count}',
   },
   smile: 'Cười lên!',
   startRecording: 'Bắt đầu thu hình',
@@ -110,44 +112,40 @@ vi_VN.strings = {
   uploadXFiles: {
     '0': 'Tải lên %{smart_count} tập tin',
     '1': 'Tải lên %{smart_count} tập tin',
-    '2': 'Tải lên %{smart_count} tập tin',
   },
   uploadXNewFiles: {
     '0': 'Tải lên +%{smart_count} tập tin',
     '1': 'Tải lên +%{smart_count} tập tin',
-    '2': 'Tải lên +%{smart_count} tập tin',
   },
   uploading: 'Uploading',
   uploadingXFiles: {
     '0': 'Đang tải lên %{smart_count} tập tin',
     '1': 'Đang tải lên %{smart_count} tập tin',
-    '2': 'Đang tải lên %{smart_count} tập tin',
   },
   xFilesSelected: {
     '0': 'Đã chọn %{smart_count} tập tin',
     '1': 'Đã chọn %{smart_count} tập tin',
-    '2': 'Đã chọn %{smart_count} tập tin',
   },
   xMoreFilesAdded: {
     '0': 'Đã thêm %{smart_count} tập tin',
     '1': 'Đã thêm %{smart_count} tập tin',
-    '2': 'Đã thêm %{smart_count} tập tin',
   },
   xTimeLeft: '%{time} left',
   youCanOnlyUploadFileTypes: 'Chỉ có thể tải lên: %{types}',
   youCanOnlyUploadX: {
     '0': 'Chỉ có thể tải lên %{smart_count} tập tin',
     '1': 'Chỉ có thể tải lên %{smart_count} tập tin',
-    '2': 'Chỉ có thể tải lên %{smart_count} tập tin',
   },
   youHaveToAtLeastSelectX: {
     '0': 'Chọn ít nhất %{smart_count} tập tin',
     '1': 'Chọn ít nhất %{smart_count} tập tin',
-    '2': 'Chọn ít nhất %{smart_count} tập tin',
   },
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.vi_VN = vi_VN
 }
 

+ 13 - 3
packages/@uppy/locales/src/zh_CN.js → packages/@uppy/locales/src/zh_CN.ts

@@ -1,11 +1,19 @@
-const zh_CN = { pluralize () { return 0 } }
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const zh_CN: Locale<0> = {
+  strings: {},
+  pluralize() {
+    return 0
+  },
+}
 
 zh_CN.strings = {
   addBulkFilesFailed: '内部错误导致添加 %{smart_count} 个文件失败',
   addMore: '添加更多文件',
   addMoreFiles: '添加更多文件',
   addingMoreFiles: '添加更多文件',
-  allowAccessDescription: '为了通过您的相机进行拍照或录像,请给网站相机的访问权限',
+  allowAccessDescription:
+    '为了通过您的相机进行拍照或录像,请给网站相机的访问权限',
   allowAccessTitle: '请允许对相机的访问权限',
   authenticateWith: '连接到 %{pluginName}',
   authenticateWithTitle: '请使用 %{pluginName} 进行认证以选择文件',
@@ -110,8 +118,10 @@ zh_CN.strings = {
   youHaveToAtLeastSelectX: '您至少要选择 %{smart_count} 个文件',
 }
 
-// There is just one form.
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.zh_CN = zh_CN
 }
 

+ 11 - 4
packages/@uppy/locales/src/zh_TW.js → packages/@uppy/locales/src/zh_TW.ts

@@ -1,5 +1,8 @@
-const zh_TW = {
-  pluralize () {
+import type { Locale } from '@uppy/utils/lib/Translator'
+
+const zh_TW: Locale<0> = {
+  strings: {},
+  pluralize() {
     return 0
   },
 }
@@ -88,7 +91,7 @@ zh_TW.strings = {
   noAudioTitle: '無法使用麥克風',
   noCameraDescription: '請連接相機以拍照或錄影',
   noCameraTitle: '無法使用相機',
-  noDuplicates: '無法新增重複檔案,\'%{fileName}\' 已存在',
+  noDuplicates: "無法新增重複檔案,'%{fileName}' 已存在",
   noFilesFound: '這裡空空如也',
   noInternetConnection: '無網路連線',
   noMoreFilesAllowed: '無法新增更多檔案',
@@ -113,7 +116,8 @@ zh_TW.strings = {
   recordingStoppedMaxSize: '因檔案大小即將超出限制而停止錄製',
   recordVideoBtn: '錄影',
   recoveredAllFiles: '我們還原了所有檔案。您現在可以繼續上傳了。',
-  recoveredXFiles: '我們無法完全復原 %{smart_count} 個檔案。請重新選擇檔案並繼續上傳。',
+  recoveredXFiles:
+    '我們無法完全復原 %{smart_count} 個檔案。請重新選擇檔案並繼續上傳。',
   removeFile: '移除檔案',
   reSelect: '重新選擇',
   resetFilter: '重設篩選器',
@@ -164,7 +168,10 @@ zh_TW.strings = {
   zoomOut: '縮小',
 }
 
+// TODO: remove this in the next major?
+// @ts-expect-error Uppy can be a global in legacy bundle
 if (typeof Uppy !== 'undefined') {
+  // @ts-expect-error Uppy can be a global in legacy bundle
   globalThis.Uppy.locales.zh_TW = zh_TW
 }
 

+ 14 - 0
packages/@uppy/locales/tsconfig.build.json

@@ -0,0 +1,14 @@
+{
+  "extends": "../../../tsconfig.shared",
+  "compilerOptions": {
+    "outDir": "./lib",
+    "rootDir": "./src",
+    "skipLibCheck": true
+  },
+  "include": ["./src/**/*.*"],
+  "references": [
+    {
+      "path": "../utils/tsconfig.build.json"
+    }
+  ]
+}

+ 13 - 0
packages/@uppy/locales/tsconfig.json

@@ -0,0 +1,13 @@
+{
+  "extends": "../../../tsconfig.shared",
+  "compilerOptions": {
+    "emitDeclarationOnly": false,
+    "noEmit": true
+  },
+  "include": ["./package.json", "./src/**/*.*"],
+  "references": [
+    {
+      "path": "../utils/tsconfig.build.json"
+    }
+  ]
+}

+ 2 - 0
yarn.lock

@@ -9559,6 +9559,8 @@ __metadata:
 "@uppy/locales@workspace:packages/@uppy/locales":
   version: 0.0.0-use.local
   resolution: "@uppy/locales@workspace:packages/@uppy/locales"
+  dependencies:
+    "@uppy/utils": "workspace:^"
   languageName: unknown
   linkType: soft