- {section === 'general' &&
}
+ {section === 'general' &&
}
{loading && (
diff --git a/client/src/i18n/locales/am.json b/client/src/i18n/locales/am.json
index f3c150182..9844fff37 100644
--- a/client/src/i18n/locales/am.json
+++ b/client/src/i18n/locales/am.json
@@ -124,7 +124,20 @@
"compressionPreview": "ቀጥታ ቅድመ-እይታ",
"compressionPreviewDescription": "አቅራቢ ምን እንደሚቀበል ለማየት የጥያቄ አካልን በሂደቱ ውስጥ ይላኩ።",
"compressionPreviewPlaceholder": "የጥያቄ JSON ወይም ተራ ጽሑፍ ይለጥፉ",
- "compressionRunPreview": "ቅድመ-እይታ አሂድ"
+ "compressionRunPreview": "ቅድመ-እይታ አሂድ",
+ "updatesTitle": "ዝማኔዎች",
+ "currentVersion": "የአሁኑ ግንባታ:",
+ "updateAvailable": "ዝማኔ አለ",
+ "changelog": "ምን ተለውጧል",
+ "upToDate": "ወቅታዊ ነው",
+ "buildAhead": "ይህ ግንባታ ከይፋዊው main ቀድሟል።",
+ "buildDiverged": "ይህ ግንባታ ከይፋዊው main ተለይቷል።",
+ "buildUnknown": "ይህ ብጁ ግንባታ ከይፋዊው main ጋር ሊነጻጸር አይችልም።",
+ "notGitInstall": "ይህ ጭነት የcommit መረጃን አያካትትም።",
+ "checkFailed": "ዝማኔዎችን መፈተሽ አልተቻለም።",
+ "contactsGithub": "ፍተሻዎች በእጅ የሚከናወኑ ሲሆን GitHubን ያገናኛሉ።",
+ "openReleases": "የGitHub ልቀቶችን ክፈት",
+ "restartAfterUpdate": "ግንባታው ከተጠናቀቀ በኋላ FreeLLMAPIን እንደገና ያስጀምሩ።"
},
"models": {
"title": "ሞዴሎች",
diff --git a/client/src/i18n/locales/ar.json b/client/src/i18n/locales/ar.json
index 190539e88..0e6dd6313 100644
--- a/client/src/i18n/locales/ar.json
+++ b/client/src/i18n/locales/ar.json
@@ -124,7 +124,20 @@
"compressionPreview": "معاينة مباشرة",
"compressionPreviewDescription": "أرسل نص طلب عبر المسار لترى ما سيصل إلى المزوّد.",
"compressionPreviewPlaceholder": "الصق JSON الطلب أو نصًا عاديًا",
- "compressionRunPreview": "تشغيل المعاينة"
+ "compressionRunPreview": "تشغيل المعاينة",
+ "updatesTitle": "التحديثات",
+ "currentVersion": "البنية الحالية:",
+ "updateAvailable": "يتوفر تحديث",
+ "changelog": "ما الذي تغيّر",
+ "upToDate": "محدّث",
+ "buildAhead": "هذه البنية متقدمة على الفرع main الرسمي.",
+ "buildDiverged": "تباعدت هذه البنية عن الفرع main الرسمي.",
+ "buildUnknown": "لا يمكن مقارنة هذه البنية المخصصة بالفرع main الرسمي.",
+ "notGitInstall": "لا يتضمن هذا التثبيت معلومات الالتزام.",
+ "checkFailed": "تعذر التحقق من وجود تحديثات.",
+ "contactsGithub": "تُجرى عمليات التحقق يدويًا وتتصل بـ GitHub.",
+ "openReleases": "فتح إصدارات GitHub",
+ "restartAfterUpdate": "أعد تشغيل FreeLLMAPI بعد اكتمال البنية."
},
"models": {
"title": "نماذج",
diff --git a/client/src/i18n/locales/az.json b/client/src/i18n/locales/az.json
index 0fac80730..9842e3f9e 100644
--- a/client/src/i18n/locales/az.json
+++ b/client/src/i18n/locales/az.json
@@ -124,7 +124,20 @@
"compressionPreview": "Canlı önbaxış",
"compressionPreviewDescription": "Sorğu gövdəsini prosesdən keçirin və təchizatçının nə alacağını görün.",
"compressionPreviewPlaceholder": "Sorğu JSON və ya sadə mətn yapışdırın",
- "compressionRunPreview": "Önbaxışı işə sal"
+ "compressionRunPreview": "Önbaxışı işə sal",
+ "updatesTitle": "Yeniləmələr",
+ "currentVersion": "Cari quruluş:",
+ "updateAvailable": "Yeniləmə mövcuddur",
+ "changelog": "Nələr dəyişib",
+ "upToDate": "Ən son versiyadır",
+ "buildAhead": "Bu quruluş rəsmi main budağından irəlidədir.",
+ "buildDiverged": "Bu quruluş rəsmi main budağından ayrılıb.",
+ "buildUnknown": "Bu xüsusi quruluşu rəsmi main budağı ilə müqayisə etmək mümkün deyil.",
+ "notGitInstall": "Bu quraşdırmada commit məlumatı yoxdur.",
+ "checkFailed": "Yeniləmələri yoxlamaq mümkün olmadı.",
+ "contactsGithub": "Yoxlamalar əl ilə başladılır və GitHub-a qoşulur.",
+ "openReleases": "GitHub buraxılışlarını aç",
+ "restartAfterUpdate": "Quruluş tamamlandıqdan sonra FreeLLMAPI-ni yenidən başladın."
},
"models": {
"title": "Modellər",
diff --git a/client/src/i18n/locales/bg.json b/client/src/i18n/locales/bg.json
index 1d80d223a..113ebe8ca 100644
--- a/client/src/i18n/locales/bg.json
+++ b/client/src/i18n/locales/bg.json
@@ -124,7 +124,20 @@
"compressionPreview": "Преглед на живо",
"compressionPreviewDescription": "Прекарайте тяло на заявка през веригата, за да видите какво би получил доставчикът.",
"compressionPreviewPlaceholder": "Поставете JSON на заявка или обикновен текст",
- "compressionRunPreview": "Изпълни преглед"
+ "compressionRunPreview": "Изпълни преглед",
+ "updatesTitle": "Актуализации",
+ "currentVersion": "Текуща компилация:",
+ "updateAvailable": "Налична е актуализация",
+ "changelog": "Какво се промени",
+ "upToDate": "Актуална версия",
+ "buildAhead": "Тази компилация е пред официалния клон main.",
+ "buildDiverged": "Тази компилация се е отклонила от официалния клон main.",
+ "buildUnknown": "Тази персонализирана компилация не може да бъде сравнена с официалния клон main.",
+ "notGitInstall": "Тази инсталация не съдържа информация за commit.",
+ "checkFailed": "Актуализациите не можаха да бъдат проверени.",
+ "contactsGithub": "Проверките се стартират ръчно и се свързват с GitHub.",
+ "openReleases": "Отвори изданията в GitHub",
+ "restartAfterUpdate": "Рестартирайте FreeLLMAPI след завършване на компилацията."
},
"models": {
"title": "Модели",
diff --git a/client/src/i18n/locales/bn.json b/client/src/i18n/locales/bn.json
index 758eeb94f..5ca3c779e 100644
--- a/client/src/i18n/locales/bn.json
+++ b/client/src/i18n/locales/bn.json
@@ -124,7 +124,20 @@
"compressionPreview": "লাইভ প্রিভিউ",
"compressionPreviewDescription": "প্রদানকারী কী পাবে তা দেখতে একটি অনুরোধ বডি পাইপলাইনের মধ্য দিয়ে পাঠান।",
"compressionPreviewPlaceholder": "অনুরোধের JSON বা সাধারণ টেক্সট পেস্ট করুন",
- "compressionRunPreview": "প্রিভিউ চালান"
+ "compressionRunPreview": "প্রিভিউ চালান",
+ "updatesTitle": "আপডেটসমূহ",
+ "currentVersion": "বর্তমান বিল্ড:",
+ "updateAvailable": "আপডেট উপলব্ধ",
+ "changelog": "কী পরিবর্তন হয়েছে",
+ "upToDate": "হালনাগাদ আছে",
+ "buildAhead": "এই বিল্ডটি অফিসিয়াল main-এর চেয়ে এগিয়ে আছে।",
+ "buildDiverged": "এই বিল্ডটি অফিসিয়াল main থেকে বিচ্যুত হয়েছে।",
+ "buildUnknown": "এই কাস্টম বিল্ডটির সঙ্গে অফিসিয়াল main-এর তুলনা করা যায় না।",
+ "notGitInstall": "এই ইনস্টলেশনে কমিটের তথ্য নেই।",
+ "checkFailed": "আপডেট পরীক্ষা করা যায়নি।",
+ "contactsGithub": "পরীক্ষাগুলি ম্যানুয়ালি করা হয় এবং GitHub-এর সঙ্গে যোগাযোগ করে।",
+ "openReleases": "GitHub রিলিজ খুলুন",
+ "restartAfterUpdate": "বিল্ড সম্পূর্ণ হওয়ার পর FreeLLMAPI পুনরায় চালু করুন।"
},
"models": {
"title": "মডেল",
diff --git a/client/src/i18n/locales/cs.json b/client/src/i18n/locales/cs.json
index 9141a344b..ea456a316 100644
--- a/client/src/i18n/locales/cs.json
+++ b/client/src/i18n/locales/cs.json
@@ -124,7 +124,20 @@
"compressionPreview": "Živý náhled",
"compressionPreviewDescription": "Pošlete tělo požadavku zpracovacím řetězcem a uvidíte, co by obdržel poskytovatel.",
"compressionPreviewPlaceholder": "Vložte JSON požadavku nebo prostý text",
- "compressionRunPreview": "Spustit náhled"
+ "compressionRunPreview": "Spustit náhled",
+ "updatesTitle": "Aktualizace",
+ "currentVersion": "Aktuální sestavení:",
+ "updateAvailable": "Je dostupná aktualizace",
+ "changelog": "Co se změnilo",
+ "upToDate": "Vše je aktuální",
+ "buildAhead": "Toto sestavení je před oficiální větví main.",
+ "buildDiverged": "Toto sestavení se odchýlilo od oficiální větve main.",
+ "buildUnknown": "Toto vlastní sestavení nelze porovnat s oficiální větví main.",
+ "notGitInstall": "Tato instalace neobsahuje informace o commitu.",
+ "checkFailed": "Aktualizace se nepodařilo zkontrolovat.",
+ "contactsGithub": "Kontroly se spouštějí ručně a kontaktují GitHub.",
+ "openReleases": "Otevřít vydání na GitHubu",
+ "restartAfterUpdate": "Po dokončení sestavení restartujte FreeLLMAPI."
},
"models": {
"title": "Modely",
diff --git a/client/src/i18n/locales/da.json b/client/src/i18n/locales/da.json
index 552391009..afb8c6bb4 100644
--- a/client/src/i18n/locales/da.json
+++ b/client/src/i18n/locales/da.json
@@ -124,7 +124,20 @@
"compressionPreview": "Live-forhåndsvisning",
"compressionPreviewDescription": "Send indholdet af en forespørgsel gennem pipelinen for at se, hvad en udbyder ville modtage.",
"compressionPreviewPlaceholder": "Indsæt forespørgsels-JSON eller almindelig tekst",
- "compressionRunPreview": "Kør forhåndsvisning"
+ "compressionRunPreview": "Kør forhåndsvisning",
+ "updatesTitle": "Opdateringer",
+ "currentVersion": "Nuværende build:",
+ "updateAvailable": "Opdatering tilgængelig",
+ "changelog": "Hvad er ændret",
+ "upToDate": "Opdateret",
+ "buildAhead": "Denne build er foran den officielle main-gren.",
+ "buildDiverged": "Denne build er divergeret fra den officielle main-gren.",
+ "buildUnknown": "Denne tilpassede build kan ikke sammenlignes med den officielle main-gren.",
+ "notGitInstall": "Denne installation indeholder ikke commit-oplysninger.",
+ "checkFailed": "Det var ikke muligt at søge efter opdateringer.",
+ "contactsGithub": "Tjek udføres manuelt og kontakter GitHub.",
+ "openReleases": "Åbn GitHub-udgivelser",
+ "restartAfterUpdate": "Genstart FreeLLMAPI, når buildet er færdigt."
},
"models": {
"title": "Modeller",
diff --git a/client/src/i18n/locales/de.json b/client/src/i18n/locales/de.json
index 6e8d371bb..0736b401c 100644
--- a/client/src/i18n/locales/de.json
+++ b/client/src/i18n/locales/de.json
@@ -124,7 +124,20 @@
"compressionPreview": "Live-Vorschau",
"compressionPreviewDescription": "Schicken Sie einen Anfragetext durch die Pipeline, um zu sehen, was ein Anbieter erhalten würde.",
"compressionPreviewPlaceholder": "Anfrage-JSON oder einfachen Text einfügen",
- "compressionRunPreview": "Vorschau ausführen"
+ "compressionRunPreview": "Vorschau ausführen",
+ "updatesTitle": "Aktualisierungen",
+ "currentVersion": "Aktueller Build:",
+ "updateAvailable": "Aktualisierung verfügbar",
+ "changelog": "Was ist neu",
+ "upToDate": "Auf dem neuesten Stand",
+ "buildAhead": "Dieser Build ist dem offiziellen main-Branch voraus.",
+ "buildDiverged": "Dieser Build ist vom offiziellen main-Branch abgewichen.",
+ "buildUnknown": "Dieser benutzerdefinierte Build kann nicht mit dem offiziellen main-Branch verglichen werden.",
+ "notGitInstall": "Diese Installation enthält keine Commit-Informationen.",
+ "checkFailed": "Aktualisierungen konnten nicht geprüft werden.",
+ "contactsGithub": "Prüfungen erfolgen manuell und stellen eine Verbindung zu GitHub her.",
+ "openReleases": "GitHub-Releases öffnen",
+ "restartAfterUpdate": "FreeLLMAPI nach Abschluss des Builds neu starten."
},
"models": {
"title": "Modelle",
diff --git a/client/src/i18n/locales/el.json b/client/src/i18n/locales/el.json
index 6537dc8f2..59b1eda55 100644
--- a/client/src/i18n/locales/el.json
+++ b/client/src/i18n/locales/el.json
@@ -124,7 +124,20 @@
"compressionPreview": "Ζωντανή προεπισκόπηση",
"compressionPreviewDescription": "Στείλτε ένα σώμα αιτήματος μέσα από τη ροή για να δείτε τι θα λάμβανε ένας πάροχος.",
"compressionPreviewPlaceholder": "Επικολλήστε JSON αιτήματος ή απλό κείμενο",
- "compressionRunPreview": "Εκτέλεση προεπισκόπησης"
+ "compressionRunPreview": "Εκτέλεση προεπισκόπησης",
+ "updatesTitle": "Ενημερώσεις",
+ "currentVersion": "Τρέχον build:",
+ "updateAvailable": "Διαθέσιμη ενημέρωση",
+ "changelog": "Τι άλλαξε",
+ "upToDate": "Ενημερωμένο",
+ "buildAhead": "Αυτό το build είναι μπροστά από το επίσημο main.",
+ "buildDiverged": "Αυτό το build έχει αποκλίνει από το επίσημο main.",
+ "buildUnknown": "Αυτό το προσαρμοσμένο build δεν μπορεί να συγκριθεί με το επίσημο main.",
+ "notGitInstall": "Αυτή η εγκατάσταση δεν περιλαμβάνει πληροφορίες commit.",
+ "checkFailed": "Δεν ήταν δυνατός ο έλεγχος για ενημερώσεις.",
+ "contactsGithub": "Οι έλεγχοι γίνονται χειροκίνητα και επικοινωνούν με το GitHub.",
+ "openReleases": "Άνοιγμα εκδόσεων GitHub",
+ "restartAfterUpdate": "Επανεκκινήστε το FreeLLMAPI μετά την ολοκλήρωση του build."
},
"models": {
"title": "Μοντέλα",
diff --git a/client/src/i18n/locales/en.json b/client/src/i18n/locales/en.json
index dc1bbb345..2e02be3e5 100644
--- a/client/src/i18n/locales/en.json
+++ b/client/src/i18n/locales/en.json
@@ -124,7 +124,20 @@
"compressionPreview": "Live preview",
"compressionPreviewDescription": "Send a request body through the pipeline to see what a provider would receive.",
"compressionPreviewPlaceholder": "Paste request JSON or plain text",
- "compressionRunPreview": "Run preview"
+ "compressionRunPreview": "Run preview",
+ "updatesTitle": "Updates",
+ "currentVersion": "Current build:",
+ "updateAvailable": "Update available",
+ "changelog": "What's changed",
+ "upToDate": "Up to date",
+ "buildAhead": "This build is ahead of official main.",
+ "buildDiverged": "This build has diverged from official main.",
+ "buildUnknown": "This custom build cannot be compared with official main.",
+ "notGitInstall": "This installation does not include commit information.",
+ "checkFailed": "Could not check for updates.",
+ "contactsGithub": "Checks are manual and contact GitHub.",
+ "openReleases": "Open GitHub Releases",
+ "restartAfterUpdate": "Restart FreeLLMAPI after the build completes."
},
"models": {
"title": "Models",
diff --git a/client/src/i18n/locales/es.json b/client/src/i18n/locales/es.json
index 2cbb81a28..cd425cdce 100644
--- a/client/src/i18n/locales/es.json
+++ b/client/src/i18n/locales/es.json
@@ -124,7 +124,20 @@
"compressionPreview": "Vista previa en vivo",
"compressionPreviewDescription": "Envía un cuerpo de solicitud por el pipeline para ver lo que recibiría un proveedor.",
"compressionPreviewPlaceholder": "Pega JSON de la solicitud o texto sin formato",
- "compressionRunPreview": "Ejecutar vista previa"
+ "compressionRunPreview": "Ejecutar vista previa",
+ "updatesTitle": "Actualizaciones",
+ "currentVersion": "Compilación actual:",
+ "updateAvailable": "Actualización disponible",
+ "changelog": "Qué ha cambiado",
+ "upToDate": "Al día",
+ "buildAhead": "Esta compilación está por delante de la rama main oficial.",
+ "buildDiverged": "Esta compilación ha divergido de la rama main oficial.",
+ "buildUnknown": "Esta compilación personalizada no se puede comparar con la rama main oficial.",
+ "notGitInstall": "Esta instalación no incluye información de commits.",
+ "checkFailed": "No se pudo comprobar si hay actualizaciones.",
+ "contactsGithub": "Las comprobaciones se realizan manualmente y contactan con GitHub.",
+ "openReleases": "Abrir lanzamientos de GitHub",
+ "restartAfterUpdate": "Reinicia FreeLLMAPI cuando finalice la compilación."
},
"models": {
"title": "Modelos",
diff --git a/client/src/i18n/locales/fa.json b/client/src/i18n/locales/fa.json
index 73fb3ca4f..4bdc9331b 100644
--- a/client/src/i18n/locales/fa.json
+++ b/client/src/i18n/locales/fa.json
@@ -124,7 +124,20 @@
"compressionPreview": "پیشنمایش زنده",
"compressionPreviewDescription": "بدنه یک درخواست را از خط پردازش عبور دهید تا ببینید ارائهدهنده چه چیزی دریافت میکند.",
"compressionPreviewPlaceholder": "JSON درخواست یا متن ساده را جایگذاری کنید",
- "compressionRunPreview": "اجرای پیشنمایش"
+ "compressionRunPreview": "اجرای پیشنمایش",
+ "updatesTitle": "بهروزرسانیها",
+ "currentVersion": "بیلد فعلی:",
+ "updateAvailable": "بهروزرسانی در دسترس است",
+ "changelog": "چه چیزهایی تغییر کرده است",
+ "upToDate": "بهروز است",
+ "buildAhead": "این بیلد از شاخهٔ رسمی main جلوتر است.",
+ "buildDiverged": "این بیلد از شاخهٔ رسمی main واگرا شده است.",
+ "buildUnknown": "این بیلد سفارشی را نمیتوان با شاخهٔ رسمی main مقایسه کرد.",
+ "notGitInstall": "این نصب شامل اطلاعات commit نیست.",
+ "checkFailed": "بررسی بهروزرسانیها ممکن نبود.",
+ "contactsGithub": "بررسیها دستی هستند و با GitHub ارتباط برقرار میکنند.",
+ "openReleases": "باز کردن نسخههای منتشرشده در GitHub",
+ "restartAfterUpdate": "پس از تکمیل بیلد، FreeLLMAPI را راهاندازی مجدد کنید."
},
"models": {
"title": "مدل ها",
diff --git a/client/src/i18n/locales/fi.json b/client/src/i18n/locales/fi.json
index b39d0f7eb..1c4b4bcaa 100644
--- a/client/src/i18n/locales/fi.json
+++ b/client/src/i18n/locales/fi.json
@@ -124,7 +124,20 @@
"compressionPreview": "Live-esikatselu",
"compressionPreviewDescription": "Lähetä pyynnön runko putken läpi nähdäksesi, mitä palveluntarjoaja saisi.",
"compressionPreviewPlaceholder": "Liitä pyynnön JSON tai pelkkä teksti",
- "compressionRunPreview": "Suorita esikatselu"
+ "compressionRunPreview": "Suorita esikatselu",
+ "updatesTitle": "Päivitykset",
+ "currentVersion": "Nykyinen koontiversio:",
+ "updateAvailable": "Päivitys saatavilla",
+ "changelog": "Mikä muuttui",
+ "upToDate": "Ajan tasalla",
+ "buildAhead": "Tämä koontiversio on virallista main-haaraa edellä.",
+ "buildDiverged": "Tämä koontiversio on erkaantunut virallisesta main-haarasta.",
+ "buildUnknown": "Tätä mukautettua koontiversiota ei voi verrata viralliseen main-haaraan.",
+ "notGitInstall": "Tämä asennus ei sisällä commit-tietoja.",
+ "checkFailed": "Päivitysten tarkistaminen epäonnistui.",
+ "contactsGithub": "Tarkistukset tehdään manuaalisesti ja ne ottavat yhteyden GitHubiin.",
+ "openReleases": "Avaa GitHub-julkaisut",
+ "restartAfterUpdate": "Käynnistä FreeLLMAPI uudelleen koonnin valmistuttua."
},
"models": {
"title": "Mallit",
diff --git a/client/src/i18n/locales/fr.json b/client/src/i18n/locales/fr.json
index ddf015244..fe6672792 100644
--- a/client/src/i18n/locales/fr.json
+++ b/client/src/i18n/locales/fr.json
@@ -124,7 +124,20 @@
"compressionPreview": "Aperçu en direct",
"compressionPreviewDescription": "Envoyez un corps de requête dans le pipeline pour voir ce qu'un fournisseur recevrait.",
"compressionPreviewPlaceholder": "Collez le JSON de la requête ou du texte brut",
- "compressionRunPreview": "Lancer l'aperçu"
+ "compressionRunPreview": "Lancer l'aperçu",
+ "updatesTitle": "Mises à jour",
+ "currentVersion": "Build actuel :",
+ "updateAvailable": "Une mise à jour est disponible",
+ "changelog": "Nouveautés",
+ "upToDate": "À jour",
+ "buildAhead": "Ce build est en avance sur la branche main officielle.",
+ "buildDiverged": "Ce build a divergé de la branche main officielle.",
+ "buildUnknown": "Ce build personnalisé ne peut pas être comparé à la branche main officielle.",
+ "notGitInstall": "Cette installation ne contient aucune information de commit.",
+ "checkFailed": "Impossible de rechercher les mises à jour.",
+ "contactsGithub": "Les vérifications sont effectuées manuellement et contactent GitHub.",
+ "openReleases": "Ouvrir les versions GitHub",
+ "restartAfterUpdate": "Redémarrez FreeLLMAPI une fois le build terminé."
},
"models": {
"title": "Modèles",
diff --git a/client/src/i18n/locales/gu.json b/client/src/i18n/locales/gu.json
index df52bb78b..e4d7cf383 100644
--- a/client/src/i18n/locales/gu.json
+++ b/client/src/i18n/locales/gu.json
@@ -124,7 +124,20 @@
"compressionPreview": "લાઇવ પ્રીવ્યૂ",
"compressionPreviewDescription": "પ્રદાતાને શું મળશે તે જોવા માટે વિનંતીનું બોડી પાઇપલાઇનમાંથી પસાર કરો.",
"compressionPreviewPlaceholder": "વિનંતીનું JSON અથવા સાદો ટેક્સ્ટ પેસ્ટ કરો",
- "compressionRunPreview": "પ્રીવ્યૂ ચલાવો"
+ "compressionRunPreview": "પ્રીવ્યૂ ચલાવો",
+ "updatesTitle": "અપડેટ્સ",
+ "currentVersion": "વર્તમાન બિલ્ડ:",
+ "updateAvailable": "અપડેટ ઉપલબ્ધ છે",
+ "changelog": "શું બદલાયું છે",
+ "upToDate": "અદ્યતન છે",
+ "buildAhead": "આ બિલ્ડ અધિકૃત main કરતાં આગળ છે.",
+ "buildDiverged": "આ બિલ્ડ અધિકૃત mainથી વિખૂટું પડ્યું છે.",
+ "buildUnknown": "આ કસ્ટમ બિલ્ડની અધિકૃત main સાથે સરખામણી કરી શકાતી નથી.",
+ "notGitInstall": "આ ઇન્સ્ટોલેશનમાં કમિટની માહિતી શામેલ નથી.",
+ "checkFailed": "અપડેટ્સ તપાસી શકાયા નથી.",
+ "contactsGithub": "તપાસો મેન્યુઅલી કરવામાં આવે છે અને GitHubનો સંપર્ક કરે છે.",
+ "openReleases": "GitHub રિલીઝ ખોલો",
+ "restartAfterUpdate": "બિલ્ડ પૂર્ણ થયા પછી FreeLLMAPI ફરી શરૂ કરો."
},
"models": {
"title": "મોડલ્સ",
diff --git a/client/src/i18n/locales/ha.json b/client/src/i18n/locales/ha.json
index 11b980d1e..682cd584f 100644
--- a/client/src/i18n/locales/ha.json
+++ b/client/src/i18n/locales/ha.json
@@ -124,7 +124,20 @@
"compressionPreview": "Samfoti kai tsaye",
"compressionPreviewDescription": "Turo jikin buƙata ta tsarin domin ganin abin da mai bayarwa zai karɓa.",
"compressionPreviewPlaceholder": "Manna JSON na buƙata ko rubutu kawai",
- "compressionRunPreview": "Gudanar da samfoti"
+ "compressionRunPreview": "Gudanar da samfoti",
+ "updatesTitle": "Sabuntawa",
+ "currentVersion": "Build na yanzu:",
+ "updateAvailable": "Akwai sabuntawa",
+ "changelog": "Abin da ya canza",
+ "upToDate": "An sabunta",
+ "buildAhead": "Wannan build ɗin yana gaba da main na hukuma.",
+ "buildDiverged": "Wannan build ɗin ya rabu da main na hukuma.",
+ "buildUnknown": "Ba za a iya kwatanta wannan build na musamman da main na hukuma ba.",
+ "notGitInstall": "Wannan shigarwar ba ta ƙunshi bayanan commit ba.",
+ "checkFailed": "Ba a iya bincika sabuntawa ba.",
+ "contactsGithub": "Ana yin dubawa da hannu kuma ana tuntuɓar GitHub.",
+ "openReleases": "Buɗe sakin GitHub",
+ "restartAfterUpdate": "Sake kunna FreeLLMAPI bayan an gama build ɗin."
},
"models": {
"title": "Samfura",
diff --git a/client/src/i18n/locales/he.json b/client/src/i18n/locales/he.json
index d29e625ce..181f25c73 100644
--- a/client/src/i18n/locales/he.json
+++ b/client/src/i18n/locales/he.json
@@ -124,7 +124,20 @@
"compressionPreview": "תצוגה מקדימה חיה",
"compressionPreviewDescription": "שלח גוף בקשה דרך הצינור כדי לראות מה הספק יקבל.",
"compressionPreviewPlaceholder": "הדבק JSON של בקשה או טקסט רגיל",
- "compressionRunPreview": "הרץ תצוגה מקדימה"
+ "compressionRunPreview": "הרץ תצוגה מקדימה",
+ "updatesTitle": "עדכונים",
+ "currentVersion": "גרסה נוכחית:",
+ "updateAvailable": "עדכון זמין",
+ "changelog": "מה השתנה",
+ "upToDate": "מעודכן",
+ "buildAhead": "גרסה זו מקדימה את ענף main הרשמי.",
+ "buildDiverged": "גרסה זו התפצלה מענף main הרשמי.",
+ "buildUnknown": "לא ניתן להשוות גרסה מותאמת אישית זו לענף main הרשמי.",
+ "notGitInstall": "התקנה זו אינה כוללת מידע על קומיטים.",
+ "checkFailed": "לא ניתן היה לבדוק אם קיימים עדכונים.",
+ "contactsGithub": "הבדיקות מתבצעות ידנית ויוצרות קשר עם GitHub.",
+ "openReleases": "פתיחת מהדורות GitHub",
+ "restartAfterUpdate": "הפעל מחדש את FreeLLMAPI לאחר השלמת הבנייה."
},
"models": {
"title": "דגמים",
diff --git a/client/src/i18n/locales/hi.json b/client/src/i18n/locales/hi.json
index d39cad32b..c3e466cb3 100644
--- a/client/src/i18n/locales/hi.json
+++ b/client/src/i18n/locales/hi.json
@@ -124,7 +124,20 @@
"compressionPreview": "लाइव पूर्वावलोकन",
"compressionPreviewDescription": "यह देखने के लिए कि प्रदाता को क्या मिलेगा, किसी अनुरोध बॉडी को पाइपलाइन से गुज़ारें।",
"compressionPreviewPlaceholder": "अनुरोध JSON या सादा टेक्स्ट पेस्ट करें",
- "compressionRunPreview": "पूर्वावलोकन चलाएँ"
+ "compressionRunPreview": "पूर्वावलोकन चलाएँ",
+ "updatesTitle": "अपडेट",
+ "currentVersion": "वर्तमान बिल्ड:",
+ "updateAvailable": "अपडेट उपलब्ध है",
+ "changelog": "क्या बदला है",
+ "upToDate": "नवीनतम संस्करण",
+ "buildAhead": "यह बिल्ड आधिकारिक main शाखा से आगे है।",
+ "buildDiverged": "यह बिल्ड आधिकारिक main शाखा से अलग हो गया है।",
+ "buildUnknown": "इस कस्टम बिल्ड की तुलना आधिकारिक main शाखा से नहीं की जा सकती।",
+ "notGitInstall": "इस इंस्टॉलेशन में कमिट की जानकारी शामिल नहीं है।",
+ "checkFailed": "अपडेट की जाँच नहीं की जा सकी।",
+ "contactsGithub": "जाँच मैन्युअल रूप से होती है और GitHub से संपर्क करती है।",
+ "openReleases": "GitHub रिलीज़ खोलें",
+ "restartAfterUpdate": "बिल्ड पूरा होने के बाद FreeLLMAPI को पुनः आरंभ करें।"
},
"models": {
"title": "मॉडल",
diff --git a/client/src/i18n/locales/hr.json b/client/src/i18n/locales/hr.json
index 3f1bb63a6..7d437c653 100644
--- a/client/src/i18n/locales/hr.json
+++ b/client/src/i18n/locales/hr.json
@@ -124,7 +124,20 @@
"compressionPreview": "Pregled uživo",
"compressionPreviewDescription": "Pošaljite tijelo zahtjeva kroz lanac obrade da vidite što bi pružatelj primio.",
"compressionPreviewPlaceholder": "Zalijepite JSON zahtjeva ili običan tekst",
- "compressionRunPreview": "Pokreni pregled"
+ "compressionRunPreview": "Pokreni pregled",
+ "updatesTitle": "Ažuriranja",
+ "currentVersion": "Trenutačna verzija:",
+ "updateAvailable": "Dostupno je ažuriranje",
+ "changelog": "Što se promijenilo",
+ "upToDate": "Ažurno",
+ "buildAhead": "Ova je verzija ispred službene grane main.",
+ "buildDiverged": "Ova se verzija odvojila od službene grane main.",
+ "buildUnknown": "Ovu prilagođenu verziju nije moguće usporediti sa službenom granom main.",
+ "notGitInstall": "Ova instalacija ne sadrži informacije o commitovima.",
+ "checkFailed": "Nije moguće provjeriti ažuriranja.",
+ "contactsGithub": "Provjere se pokreću ručno i kontaktiraju GitHub.",
+ "openReleases": "Otvori izdanja na GitHubu",
+ "restartAfterUpdate": "Ponovno pokrenite FreeLLMAPI nakon dovršetka izgradnje."
},
"models": {
"title": "Modeli",
diff --git a/client/src/i18n/locales/hu.json b/client/src/i18n/locales/hu.json
index e6fb2a57a..d7b0decf0 100644
--- a/client/src/i18n/locales/hu.json
+++ b/client/src/i18n/locales/hu.json
@@ -124,7 +124,20 @@
"compressionPreview": "Élő előnézet",
"compressionPreviewDescription": "Küldjön át egy kéréstörzset a folyamaton, hogy lássa, mit kapna egy szolgáltató.",
"compressionPreviewPlaceholder": "Illessze be a kérés JSON-jét vagy egyszerű szöveget",
- "compressionRunPreview": "Előnézet futtatása"
+ "compressionRunPreview": "Előnézet futtatása",
+ "updatesTitle": "Frissítések",
+ "currentVersion": "Jelenlegi build:",
+ "updateAvailable": "Frissítés érhető el",
+ "changelog": "Mi változott",
+ "upToDate": "Naprakész",
+ "buildAhead": "Ez a build megelőzi a hivatalos main ágat.",
+ "buildDiverged": "Ez a build eltért a hivatalos main ágtól.",
+ "buildUnknown": "Ez az egyéni build nem hasonlítható össze a hivatalos main ággal.",
+ "notGitInstall": "Ez a telepítés nem tartalmaz commitinformációkat.",
+ "checkFailed": "Nem sikerült ellenőrizni a frissítéseket.",
+ "contactsGithub": "Az ellenőrzések manuálisak, és kapcsolatba lépnek a GitHubbal.",
+ "openReleases": "GitHub-kiadások megnyitása",
+ "restartAfterUpdate": "A build befejezése után indítsa újra a FreeLLMAPI-t."
},
"models": {
"title": "Modellek",
diff --git a/client/src/i18n/locales/id.json b/client/src/i18n/locales/id.json
index 96e0259c2..9c7704fed 100644
--- a/client/src/i18n/locales/id.json
+++ b/client/src/i18n/locales/id.json
@@ -124,7 +124,20 @@
"compressionPreview": "Pratinjau langsung",
"compressionPreviewDescription": "Kirim body permintaan melalui alur kompresi untuk melihat apa yang akan diterima penyedia.",
"compressionPreviewPlaceholder": "Tempel JSON permintaan atau teks biasa",
- "compressionRunPreview": "Jalankan pratinjau"
+ "compressionRunPreview": "Jalankan pratinjau",
+ "updatesTitle": "Pembaruan",
+ "currentVersion": "Build saat ini:",
+ "updateAvailable": "Pembaruan tersedia",
+ "changelog": "Yang berubah",
+ "upToDate": "Sudah terbaru",
+ "buildAhead": "Build ini lebih maju dari cabang main resmi.",
+ "buildDiverged": "Build ini telah menyimpang dari cabang main resmi.",
+ "buildUnknown": "Build khusus ini tidak dapat dibandingkan dengan cabang main resmi.",
+ "notGitInstall": "Instalasi ini tidak menyertakan informasi commit.",
+ "checkFailed": "Tidak dapat memeriksa pembaruan.",
+ "contactsGithub": "Pemeriksaan dilakukan secara manual dan menghubungi GitHub.",
+ "openReleases": "Buka Rilis GitHub",
+ "restartAfterUpdate": "Mulai ulang FreeLLMAPI setelah proses build selesai."
},
"models": {
"title": "Model",
diff --git a/client/src/i18n/locales/ig.json b/client/src/i18n/locales/ig.json
index 005260d5f..154cca86a 100644
--- a/client/src/i18n/locales/ig.json
+++ b/client/src/i18n/locales/ig.json
@@ -124,7 +124,20 @@
"compressionPreview": "Nlele ozugbo",
"compressionPreviewDescription": "Zipu ozi arịrịọ site na usoro ahụ ka ị hụ ihe onye na-enye ga-anata.",
"compressionPreviewPlaceholder": "Tinye JSON arịrịọ ma ọ bụ ederede nkịtị",
- "compressionRunPreview": "Mee nlele"
+ "compressionRunPreview": "Mee nlele",
+ "updatesTitle": "Mmelite",
+ "currentVersion": "Build dị ugbu a:",
+ "updateAvailable": "Mmelite dị",
+ "changelog": "Ihe gbanwere",
+ "upToDate": "Ọ dị ọhụrụ",
+ "buildAhead": "Build a dị n'ihu alaka main nke iwu kwadoro.",
+ "buildDiverged": "Build a esiwo na alaka main nke iwu kwadoro kewapụ.",
+ "buildUnknown": "Enweghị ike iji build omenala a tụnyere alaka main nke iwu kwadoro.",
+ "notGitInstall": "Nwụnye a enweghị ozi commit.",
+ "checkFailed": "Enweghị ike ịlele mmelite.",
+ "contactsGithub": "A na-eji aka eme nyocha ndị a, ha na-akpọtụrụ GitHub.",
+ "openReleases": "Mepee GitHub Releases",
+ "restartAfterUpdate": "Malitegharịa FreeLLMAPI mgbe build ahụ gwụchara."
},
"models": {
"title": "Ụdị",
diff --git a/client/src/i18n/locales/it.json b/client/src/i18n/locales/it.json
index ff597f1cc..9dc9bf134 100644
--- a/client/src/i18n/locales/it.json
+++ b/client/src/i18n/locales/it.json
@@ -124,7 +124,20 @@
"compressionPreview": "Anteprima live",
"compressionPreviewDescription": "Invia un corpo di richiesta attraverso la pipeline per vedere che cosa riceverebbe un fornitore.",
"compressionPreviewPlaceholder": "Incolla il JSON della richiesta o testo semplice",
- "compressionRunPreview": "Esegui anteprima"
+ "compressionRunPreview": "Esegui anteprima",
+ "updatesTitle": "Aggiornamenti",
+ "currentVersion": "Build corrente:",
+ "updateAvailable": "Aggiornamento disponibile",
+ "changelog": "Novità",
+ "upToDate": "Aggiornato",
+ "buildAhead": "Questa build è più avanti del ramo main ufficiale.",
+ "buildDiverged": "Questa build si è discostata dal ramo main ufficiale.",
+ "buildUnknown": "Questa build personalizzata non può essere confrontata con il ramo main ufficiale.",
+ "notGitInstall": "Questa installazione non include informazioni sui commit.",
+ "checkFailed": "Impossibile verificare la disponibilità di aggiornamenti.",
+ "contactsGithub": "I controlli sono manuali e contattano GitHub.",
+ "openReleases": "Apri le release di GitHub",
+ "restartAfterUpdate": "Riavvia FreeLLMAPI al termine della build."
},
"models": {
"title": "Modelli",
diff --git a/client/src/i18n/locales/ja.json b/client/src/i18n/locales/ja.json
index 2f15b9c91..c4f0b18c3 100644
--- a/client/src/i18n/locales/ja.json
+++ b/client/src/i18n/locales/ja.json
@@ -124,7 +124,20 @@
"compressionPreview": "ライブプレビュー",
"compressionPreviewDescription": "リクエストのボディをパイプラインに通して、プロバイダーが受け取る内容を確認します。",
"compressionPreviewPlaceholder": "リクエストのJSONまたはプレーンテキストを貼り付け",
- "compressionRunPreview": "プレビューを実行"
+ "compressionRunPreview": "プレビューを実行",
+ "updatesTitle": "アップデート",
+ "currentVersion": "現在のビルド:",
+ "updateAvailable": "アップデートがあります",
+ "changelog": "変更内容",
+ "upToDate": "最新版です",
+ "buildAhead": "このビルドは公式のmainより先行しています。",
+ "buildDiverged": "このビルドは公式のmainから分岐しています。",
+ "buildUnknown": "このカスタムビルドは公式のmainと比較できません。",
+ "notGitInstall": "このインストールにはコミット情報が含まれていません。",
+ "checkFailed": "アップデートを確認できませんでした。",
+ "contactsGithub": "確認は手動で行われ、GitHubに接続します。",
+ "openReleases": "GitHub Releasesを開く",
+ "restartAfterUpdate": "ビルド完了後にFreeLLMAPIを再起動してください。"
},
"models": {
"title": "モデル",
diff --git a/client/src/i18n/locales/ka.json b/client/src/i18n/locales/ka.json
index 4f443aa61..aaf5b07df 100644
--- a/client/src/i18n/locales/ka.json
+++ b/client/src/i18n/locales/ka.json
@@ -124,7 +124,20 @@
"compressionPreview": "ცოცხალი გადახედვა",
"compressionPreviewDescription": "გაატარეთ მოთხოვნის სხეული კონვეიერში, რომ ნახოთ, რას მიიღებდა პროვაიდერი.",
"compressionPreviewPlaceholder": "ჩასვით მოთხოვნის JSON ან უბრალო ტექსტი",
- "compressionRunPreview": "გადახედვის გაშვება"
+ "compressionRunPreview": "გადახედვის გაშვება",
+ "updatesTitle": "განახლებები",
+ "currentVersion": "მიმდინარე ბილდი:",
+ "updateAvailable": "განახლება ხელმისაწვდომია",
+ "changelog": "რა შეიცვალა",
+ "upToDate": "განახლებულია",
+ "buildAhead": "ეს ბილდი ოფიციალურ main შტოს უსწრებს.",
+ "buildDiverged": "ეს ბილდი ოფიციალურ main შტოს ასცდა.",
+ "buildUnknown": "ამ მორგებული ბილდის შედარება ოფიციალურ main შტოსთან შეუძლებელია.",
+ "notGitInstall": "ეს ინსტალაცია კომიტების შესახებ ინფორმაციას არ შეიცავს.",
+ "checkFailed": "განახლებების შემოწმება ვერ მოხერხდა.",
+ "contactsGithub": "შემოწმება ხელით სრულდება და GitHub-ს უკავშირდება.",
+ "openReleases": "GitHub-ის რელიზების გახსნა",
+ "restartAfterUpdate": "ბილდის დასრულების შემდეგ გადატვირთეთ FreeLLMAPI."
},
"models": {
"title": "მოდელები",
diff --git a/client/src/i18n/locales/km.json b/client/src/i18n/locales/km.json
index 2a00233ed..dc3ce7fc6 100644
--- a/client/src/i18n/locales/km.json
+++ b/client/src/i18n/locales/km.json
@@ -124,7 +124,20 @@
"compressionPreview": "មើលជាមុនផ្ទាល់",
"compressionPreviewDescription": "បញ្ជូនតួសំណើឆ្លងកាត់ដំណើរការបង្ហាប់ ដើម្បីមើលថាអ្នកផ្តល់សេវានឹងទទួលបានអ្វី។",
"compressionPreviewPlaceholder": "បិទភ្ជាប់ JSON សំណើ ឬអត្ថបទធម្មតា",
- "compressionRunPreview": "ដំណើរការមើលជាមុន"
+ "compressionRunPreview": "ដំណើរការមើលជាមុន",
+ "updatesTitle": "ការអាប់ដេត",
+ "currentVersion": "ប៊ីលបច្ចុប្បន្ន៖",
+ "updateAvailable": "មានការអាប់ដេត",
+ "changelog": "អ្វីដែលបានផ្លាស់ប្តូរ",
+ "upToDate": "ទាន់សម័យ",
+ "buildAhead": "ប៊ីលនេះនាំមុខសាខា main ផ្លូវការ។",
+ "buildDiverged": "ប៊ីលនេះបានបែកចេញពីសាខា main ផ្លូវការ។",
+ "buildUnknown": "មិនអាចប្រៀបធៀបប៊ីលផ្ទាល់ខ្លួននេះជាមួយសាខា main ផ្លូវការបានទេ។",
+ "notGitInstall": "ការដំឡើងនេះមិនមានព័ត៌មាន commit ទេ។",
+ "checkFailed": "មិនអាចពិនិត្យរកការអាប់ដេតបានទេ។",
+ "contactsGithub": "ការពិនិត្យធ្វើឡើងដោយដៃ និងភ្ជាប់ទៅ GitHub។",
+ "openReleases": "បើក GitHub Releases",
+ "restartAfterUpdate": "ចាប់ផ្តើម FreeLLMAPI ឡើងវិញ បន្ទាប់ពីការបង្កើតបានបញ្ចប់។"
},
"models": {
"title": "ម៉ូដែល",
diff --git a/client/src/i18n/locales/kn.json b/client/src/i18n/locales/kn.json
index 148369e64..62c44c525 100644
--- a/client/src/i18n/locales/kn.json
+++ b/client/src/i18n/locales/kn.json
@@ -124,7 +124,20 @@
"compressionPreview": "ಲೈವ್ ಪೂರ್ವವೀಕ್ಷಣೆ",
"compressionPreviewDescription": "ಒದಗಿಸುವವರಿಗೆ ಏನು ತಲುಪುತ್ತದೆ ಎಂದು ನೋಡಲು ವಿನಂತಿಯ ಬಾಡಿಯನ್ನು ಪೈಪ್ಲೈನ್ ಮೂಲಕ ಕಳುಹಿಸಿ.",
"compressionPreviewPlaceholder": "ವಿನಂತಿಯ JSON ಅಥವಾ ಸರಳ ಪಠ್ಯವನ್ನು ಅಂಟಿಸಿ",
- "compressionRunPreview": "ಪೂರ್ವವೀಕ್ಷಣೆ ರನ್ ಮಾಡಿ"
+ "compressionRunPreview": "ಪೂರ್ವವೀಕ್ಷಣೆ ರನ್ ಮಾಡಿ",
+ "updatesTitle": "ನವೀಕರಣಗಳು",
+ "currentVersion": "ಪ್ರಸ್ತುತ ಬಿಲ್ಡ್:",
+ "updateAvailable": "ನವೀಕರಣ ಲಭ್ಯವಿದೆ",
+ "changelog": "ಏನು ಬದಲಾಗಿದೆ",
+ "upToDate": "ನವೀಕೃತವಾಗಿದೆ",
+ "buildAhead": "ಈ ಬಿಲ್ಡ್ ಅಧಿಕೃತ main ಶಾಖೆಗಿಂತ ಮುಂದಿದೆ.",
+ "buildDiverged": "ಈ ಬಿಲ್ಡ್ ಅಧಿಕೃತ main ಶಾಖೆಯಿಂದ ಬೇರೆಯಾಗಿದೆ.",
+ "buildUnknown": "ಈ ಕಸ್ಟಮ್ ಬಿಲ್ಡ್ ಅನ್ನು ಅಧಿಕೃತ main ಶಾಖೆಯೊಂದಿಗೆ ಹೋಲಿಸಲಾಗುವುದಿಲ್ಲ.",
+ "notGitInstall": "ಈ ಸ್ಥಾಪನೆಯು ಕಮಿಟ್ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಿಲ್ಲ.",
+ "checkFailed": "ನವೀಕರಣಗಳಿಗಾಗಿ ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ.",
+ "contactsGithub": "ಪರಿಶೀಲನೆಗಳನ್ನು ಹಸ್ತಚಾಲಿತವಾಗಿ ಮಾಡಲಾಗುತ್ತದೆ ಮತ್ತು ಅವು GitHub ಅನ್ನು ಸಂಪರ್ಕಿಸುತ್ತವೆ.",
+ "openReleases": "GitHub ಬಿಡುಗಡೆಗಳನ್ನು ತೆರೆಯಿರಿ",
+ "restartAfterUpdate": "ಬಿಲ್ಡ್ ಪೂರ್ಣಗೊಂಡ ನಂತರ FreeLLMAPI ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಿ."
},
"models": {
"title": "ಮಾದರಿಗಳು",
diff --git a/client/src/i18n/locales/ko.json b/client/src/i18n/locales/ko.json
index 25780a5f5..3b1f654e2 100644
--- a/client/src/i18n/locales/ko.json
+++ b/client/src/i18n/locales/ko.json
@@ -124,7 +124,20 @@
"compressionPreview": "실시간 미리보기",
"compressionPreviewDescription": "요청 본문을 파이프라인에 통과시켜 공급자가 받게 될 내용을 확인합니다.",
"compressionPreviewPlaceholder": "요청 JSON 또는 일반 텍스트를 붙여넣으세요",
- "compressionRunPreview": "미리보기 실행"
+ "compressionRunPreview": "미리보기 실행",
+ "updatesTitle": "업데이트",
+ "currentVersion": "현재 빌드:",
+ "updateAvailable": "업데이트 사용 가능",
+ "changelog": "변경 사항",
+ "upToDate": "최신 상태",
+ "buildAhead": "이 빌드는 공식 main 브랜치보다 앞서 있습니다.",
+ "buildDiverged": "이 빌드는 공식 main 브랜치에서 분기되었습니다.",
+ "buildUnknown": "이 사용자 지정 빌드는 공식 main 브랜치와 비교할 수 없습니다.",
+ "notGitInstall": "이 설치에는 커밋 정보가 포함되어 있지 않습니다.",
+ "checkFailed": "업데이트를 확인할 수 없습니다.",
+ "contactsGithub": "확인은 수동으로 진행되며 GitHub에 연결합니다.",
+ "openReleases": "GitHub 릴리스 열기",
+ "restartAfterUpdate": "빌드가 완료되면 FreeLLMAPI를 다시 시작하세요."
},
"models": {
"title": "모델",
diff --git a/client/src/i18n/locales/lt.json b/client/src/i18n/locales/lt.json
index a619df585..6e2c84fe5 100644
--- a/client/src/i18n/locales/lt.json
+++ b/client/src/i18n/locales/lt.json
@@ -124,7 +124,20 @@
"compressionPreview": "Tiesioginė peržiūra",
"compressionPreviewDescription": "Praleiskite užklausos turinį per apdorojimo grandinę ir pamatysite, ką gautų tiekėjas.",
"compressionPreviewPlaceholder": "Įklijuokite užklausos JSON arba paprastą tekstą",
- "compressionRunPreview": "Vykdyti peržiūrą"
+ "compressionRunPreview": "Vykdyti peržiūrą",
+ "updatesTitle": "Naujiniai",
+ "currentVersion": "Dabartinė komponavimo versija:",
+ "updateAvailable": "Yra naujinys",
+ "changelog": "Kas pasikeitė",
+ "upToDate": "Atnaujinta",
+ "buildAhead": "Ši komponavimo versija yra priekyje oficialios main šakos.",
+ "buildDiverged": "Ši komponavimo versija nukrypo nuo oficialios main šakos.",
+ "buildUnknown": "Šios tinkintos komponavimo versijos negalima palyginti su oficialia main šaka.",
+ "notGitInstall": "Šiame diegime nėra informacijos apie Git įrašus.",
+ "checkFailed": "Nepavyko patikrinti, ar yra naujinių.",
+ "contactsGithub": "Tikrinimas atliekamas rankiniu būdu ir susisiekiama su GitHub.",
+ "openReleases": "Atverti GitHub leidimus",
+ "restartAfterUpdate": "Baigę komponuoti paleiskite FreeLLMAPI iš naujo."
},
"models": {
"title": "Modeliai",
diff --git a/client/src/i18n/locales/ml.json b/client/src/i18n/locales/ml.json
index 8d30e980e..e56055d82 100644
--- a/client/src/i18n/locales/ml.json
+++ b/client/src/i18n/locales/ml.json
@@ -124,7 +124,20 @@
"compressionPreview": "ലൈവ് പ്രിവ്യൂ",
"compressionPreviewDescription": "ദാതാവിന് എന്ത് ലഭിക്കുമെന്ന് കാണാൻ ഒരു അഭ്യർത്ഥന ബോഡി പൈപ്പ്ലൈനിലൂടെ അയയ്ക്കുക.",
"compressionPreviewPlaceholder": "അഭ്യർത്ഥന JSON അല്ലെങ്കിൽ സാധാരണ ടെക്സ്റ്റ് പേസ്റ്റ് ചെയ്യുക",
- "compressionRunPreview": "പ്രിവ്യൂ പ്രവർത്തിപ്പിക്കുക"
+ "compressionRunPreview": "പ്രിവ്യൂ പ്രവർത്തിപ്പിക്കുക",
+ "updatesTitle": "അപ്ഡേറ്റുകൾ",
+ "currentVersion": "നിലവിലെ ബിൽഡ്:",
+ "updateAvailable": "അപ്ഡേറ്റ് ലഭ്യമാണ്",
+ "changelog": "എന്താണ് മാറിയത്",
+ "upToDate": "കാലികമാണ്",
+ "buildAhead": "ഈ ബിൽഡ് ഔദ്യോഗിക main ശാഖയേക്കാൾ മുന്നിലാണ്.",
+ "buildDiverged": "ഈ ബിൽഡ് ഔദ്യോഗിക main ശാഖയിൽ നിന്ന് വ്യതിചലിച്ചിരിക്കുന്നു.",
+ "buildUnknown": "ഈ കസ്റ്റം ബിൽഡിനെ ഔദ്യോഗിക main ശാഖയുമായി താരതമ്യം ചെയ്യാനാകില്ല.",
+ "notGitInstall": "ഈ ഇൻസ്റ്റാളേഷനിൽ കമ്മിറ്റ് വിവരങ്ങൾ ഉൾപ്പെട്ടിട്ടില്ല.",
+ "checkFailed": "അപ്ഡേറ്റുകൾ പരിശോധിക്കാനായില്ല.",
+ "contactsGithub": "പരിശോധനകൾ മാനുവലായാണ് നടത്തുന്നത്; അവ GitHub-മായി ബന്ധപ്പെടുന്നു.",
+ "openReleases": "GitHub റിലീസുകൾ തുറക്കുക",
+ "restartAfterUpdate": "ബിൽഡ് പൂർത്തിയായ ശേഷം FreeLLMAPI പുനരാരംഭിക്കുക."
},
"models": {
"title": "മോഡലുകൾ",
diff --git a/client/src/i18n/locales/mr.json b/client/src/i18n/locales/mr.json
index 7db49378f..06b884ab7 100644
--- a/client/src/i18n/locales/mr.json
+++ b/client/src/i18n/locales/mr.json
@@ -124,7 +124,20 @@
"compressionPreview": "लाइव्ह पूर्वावलोकन",
"compressionPreviewDescription": "प्रदात्याला काय मिळेल हे पाहण्यासाठी विनंतीचा बॉडी पाइपलाइनमधून पाठवा.",
"compressionPreviewPlaceholder": "विनंतीचे JSON किंवा साधा मजकूर पेस्ट करा",
- "compressionRunPreview": "पूर्वावलोकन चालवा"
+ "compressionRunPreview": "पूर्वावलोकन चालवा",
+ "updatesTitle": "अपडेट्स",
+ "currentVersion": "सध्याचा बिल्ड:",
+ "updateAvailable": "अपडेट उपलब्ध आहे",
+ "changelog": "काय बदलले",
+ "upToDate": "अद्ययावत",
+ "buildAhead": "हा बिल्ड अधिकृत main शाखेच्या पुढे आहे.",
+ "buildDiverged": "हा बिल्ड अधिकृत main शाखेपासून वेगळा झाला आहे.",
+ "buildUnknown": "या कस्टम बिल्डची अधिकृत main शाखेशी तुलना करता येत नाही.",
+ "notGitInstall": "या इंस्टॉलेशनमध्ये कमिटची माहिती समाविष्ट नाही.",
+ "checkFailed": "अपडेट्स तपासता आले नाहीत.",
+ "contactsGithub": "तपासणी स्वतः सुरू करावी लागते आणि ती GitHub शी संपर्क साधते.",
+ "openReleases": "GitHub रिलीजेस उघडा",
+ "restartAfterUpdate": "बिल्ड पूर्ण झाल्यानंतर FreeLLMAPI पुन्हा सुरू करा."
},
"models": {
"title": "मॉडेल्स",
diff --git a/client/src/i18n/locales/ms.json b/client/src/i18n/locales/ms.json
index 68fe1e016..c54ad8b04 100644
--- a/client/src/i18n/locales/ms.json
+++ b/client/src/i18n/locales/ms.json
@@ -124,7 +124,20 @@
"compressionPreview": "Pratonton langsung",
"compressionPreviewDescription": "Hantar badan permintaan melalui saluran pemampatan untuk melihat apa yang akan diterima oleh penyedia.",
"compressionPreviewPlaceholder": "Tampal JSON permintaan atau teks biasa",
- "compressionRunPreview": "Jalankan pratonton"
+ "compressionRunPreview": "Jalankan pratonton",
+ "updatesTitle": "Kemas kini",
+ "currentVersion": "Binaan semasa:",
+ "updateAvailable": "Kemas kini tersedia",
+ "changelog": "Perubahan",
+ "upToDate": "Sudah dikemas kini",
+ "buildAhead": "Binaan ini mendahului cabang main rasmi.",
+ "buildDiverged": "Binaan ini telah menyimpang daripada cabang main rasmi.",
+ "buildUnknown": "Binaan tersuai ini tidak dapat dibandingkan dengan cabang main rasmi.",
+ "notGitInstall": "Pemasangan ini tidak menyertakan maklumat komit.",
+ "checkFailed": "Tidak dapat menyemak kemas kini.",
+ "contactsGithub": "Semakan dijalankan secara manual dan menghubungi GitHub.",
+ "openReleases": "Buka Keluaran GitHub",
+ "restartAfterUpdate": "Mulakan semula FreeLLMAPI selepas binaan selesai."
},
"models": {
"title": "Model",
diff --git a/client/src/i18n/locales/my.json b/client/src/i18n/locales/my.json
index 6575a6c8f..d6891dd2d 100644
--- a/client/src/i18n/locales/my.json
+++ b/client/src/i18n/locales/my.json
@@ -124,7 +124,20 @@
"compressionPreview": "တိုက်ရိုက် အစမ်းကြည့်ရှုမှု",
"compressionPreviewDescription": "ပံ့ပိုးသူ မည်သည့်အရာ လက်ခံရရှိမည်ကို ကြည့်ရန် တောင်းဆိုမှု အကြောင်းအရာကို လုပ်ငန်းစဉ်ထဲ ဖြတ်သန်း ပို့ကြည့်ပါ။",
"compressionPreviewPlaceholder": "တောင်းဆိုမှု JSON သို့မဟုတ် စာသားရိုးရိုးကို ကူးထည့်ပါ",
- "compressionRunPreview": "အစမ်းကြည့်ရန်"
+ "compressionRunPreview": "အစမ်းကြည့်ရန်",
+ "updatesTitle": "အပ်ဒိတ်များ",
+ "currentVersion": "လက်ရှိ build:",
+ "updateAvailable": "အပ်ဒိတ် ရရှိနိုင်သည်",
+ "changelog": "ပြောင်းလဲထားသည့်အရာများ",
+ "upToDate": "နောက်ဆုံးပေါ် ဖြစ်သည်",
+ "buildAhead": "ဤ build သည် တရားဝင် main ထက် ရှေ့ရောက်နေသည်။",
+ "buildDiverged": "ဤ build သည် တရားဝင် main မှ ကွဲထွက်သွားသည်။",
+ "buildUnknown": "ဤစိတ်ကြိုက် build ကို တရားဝင် main နှင့် နှိုင်းယှဉ်၍ မရပါ။",
+ "notGitInstall": "ဤထည့်သွင်းမှုတွင် commit အချက်အလက် မပါဝင်ပါ။",
+ "checkFailed": "အပ်ဒိတ်များကို စစ်ဆေး၍ မရပါ။",
+ "contactsGithub": "စစ်ဆေးမှုများကို ကိုယ်တိုင်လုပ်ဆောင်ရပြီး GitHub သို့ ဆက်သွယ်သည်။",
+ "openReleases": "GitHub Releases ကို ဖွင့်ရန်",
+ "restartAfterUpdate": "build ပြီးဆုံးပြီးနောက် FreeLLMAPI ကို ပြန်လည်စတင်ပါ။"
},
"models": {
"title": "မော်ဒယ်များ",
diff --git a/client/src/i18n/locales/ne.json b/client/src/i18n/locales/ne.json
index 32e24539a..0d1547fee 100644
--- a/client/src/i18n/locales/ne.json
+++ b/client/src/i18n/locales/ne.json
@@ -124,7 +124,20 @@
"compressionPreview": "प्रत्यक्ष पूर्वावलोकन",
"compressionPreviewDescription": "प्रदायकले के प्राप्त गर्नेछ हेर्न अनुरोधको बडी पाइपलाइनमार्फत पठाउनुहोस्।",
"compressionPreviewPlaceholder": "अनुरोध JSON वा सादा पाठ टाँस्नुहोस्",
- "compressionRunPreview": "पूर्वावलोकन चलाउनुहोस्"
+ "compressionRunPreview": "पूर्वावलोकन चलाउनुहोस्",
+ "updatesTitle": "अद्यावधिकहरू",
+ "currentVersion": "हालको बिल्ड:",
+ "updateAvailable": "अद्यावधिक उपलब्ध छ",
+ "changelog": "के परिवर्तन भयो",
+ "upToDate": "अद्यावधिक छ",
+ "buildAhead": "यो बिल्ड आधिकारिक main शाखाभन्दा अगाडि छ।",
+ "buildDiverged": "यो बिल्ड आधिकारिक main शाखाबाट अलग भएको छ।",
+ "buildUnknown": "यो अनुकूलित बिल्डलाई आधिकारिक main शाखासँग तुलना गर्न सकिँदैन।",
+ "notGitInstall": "यो स्थापनामा commit जानकारी समावेश छैन।",
+ "checkFailed": "अद्यावधिकहरू जाँच गर्न सकिएन।",
+ "contactsGithub": "जाँचहरू म्यानुअल रूपमा गरिन्छन् र GitHub सँग सम्पर्क गर्छन्।",
+ "openReleases": "GitHub रिलीजहरू खोल्नुहोस्",
+ "restartAfterUpdate": "बिल्ड पूरा भएपछि FreeLLMAPI पुनः सुरु गर्नुहोस्।"
},
"models": {
"title": "नमूनाहरू",
diff --git a/client/src/i18n/locales/nl.json b/client/src/i18n/locales/nl.json
index b19c569d9..e22029e6b 100644
--- a/client/src/i18n/locales/nl.json
+++ b/client/src/i18n/locales/nl.json
@@ -124,7 +124,20 @@
"compressionPreview": "Live voorbeeld",
"compressionPreviewDescription": "Stuur een verzoekinhoud door de pipeline om te zien wat een aanbieder zou ontvangen.",
"compressionPreviewPlaceholder": "Plak verzoek-JSON of platte tekst",
- "compressionRunPreview": "Voorbeeld uitvoeren"
+ "compressionRunPreview": "Voorbeeld uitvoeren",
+ "updatesTitle": "Updates",
+ "currentVersion": "Huidige build:",
+ "updateAvailable": "Update beschikbaar",
+ "changelog": "Wat is er veranderd",
+ "upToDate": "Up-to-date",
+ "buildAhead": "Deze build loopt voor op de officiële main-branch.",
+ "buildDiverged": "Deze build is afgeweken van de officiële main-branch.",
+ "buildUnknown": "Deze aangepaste build kan niet worden vergeleken met de officiële main-branch.",
+ "notGitInstall": "Deze installatie bevat geen commitinformatie.",
+ "checkFailed": "Kan niet controleren op updates.",
+ "contactsGithub": "Controles worden handmatig uitgevoerd en maken contact met GitHub.",
+ "openReleases": "GitHub Releases openen",
+ "restartAfterUpdate": "Start FreeLLMAPI opnieuw nadat de build is voltooid."
},
"models": {
"title": "Modellen",
diff --git a/client/src/i18n/locales/no.json b/client/src/i18n/locales/no.json
index 2d803a8f8..c4c39b889 100644
--- a/client/src/i18n/locales/no.json
+++ b/client/src/i18n/locales/no.json
@@ -124,7 +124,20 @@
"compressionPreview": "Direkte forhåndsvisning",
"compressionPreviewDescription": "Send en forespørselstekst gjennom pipelinen for å se hva en leverandør ville motta.",
"compressionPreviewPlaceholder": "Lim inn forespørsels-JSON eller ren tekst",
- "compressionRunPreview": "Kjør forhåndsvisning"
+ "compressionRunPreview": "Kjør forhåndsvisning",
+ "updatesTitle": "Oppdateringer",
+ "currentVersion": "Nåværende bygg:",
+ "updateAvailable": "Oppdatering tilgjengelig",
+ "changelog": "Hva er endret",
+ "upToDate": "Oppdatert",
+ "buildAhead": "Dette bygget ligger foran den offisielle main-grenen.",
+ "buildDiverged": "Dette bygget har skilt lag med den offisielle main-grenen.",
+ "buildUnknown": "Dette egendefinerte bygget kan ikke sammenlignes med den offisielle main-grenen.",
+ "notGitInstall": "Denne installasjonen inneholder ikke commit-informasjon.",
+ "checkFailed": "Kunne ikke se etter oppdateringer.",
+ "contactsGithub": "Oppdateringssjekker kjøres manuelt og kontakter GitHub.",
+ "openReleases": "Åpne GitHub Releases",
+ "restartAfterUpdate": "Start FreeLLMAPI på nytt etter at byggingen er fullført."
},
"models": {
"title": "Modeller",
diff --git a/client/src/i18n/locales/or.json b/client/src/i18n/locales/or.json
index 588f6a3f7..c1cd6cec1 100644
--- a/client/src/i18n/locales/or.json
+++ b/client/src/i18n/locales/or.json
@@ -124,7 +124,20 @@
"compressionPreview": "ଲାଇଭ୍ ପୂର୍ବାବଲୋକନ",
"compressionPreviewDescription": "ପ୍ରଦାନକାରୀ କ'ଣ ପାଇବେ ତାହା ଦେଖିବାକୁ ଏକ ଅନୁରୋଧ ବଡି ପାଇପଲାଇନ ମଧ୍ୟ ଦେଇ ପଠାନ୍ତୁ।",
"compressionPreviewPlaceholder": "ଅନୁରୋଧ JSON କିମ୍ବା ସାଧା ଟେକ୍ସଟ୍ ପେଷ୍ଟ କରନ୍ତୁ",
- "compressionRunPreview": "ପୂର୍ବାବଲୋକନ ଚଲାନ୍ତୁ"
+ "compressionRunPreview": "ପୂର୍ବାବଲୋକନ ଚଲାନ୍ତୁ",
+ "updatesTitle": "ଅପଡେଟ୍ଗୁଡ଼ିକ",
+ "currentVersion": "ବର୍ତ୍ତମାନର ବିଲ୍ଡ:",
+ "updateAvailable": "ଅପଡେଟ୍ ଉପଲବ୍ଧ",
+ "changelog": "କ’ଣ ପରିବର୍ତ୍ତନ ହୋଇଛି",
+ "upToDate": "ଅଦ୍ୟତନ ଅଛି",
+ "buildAhead": "ଏହି ବିଲ୍ଡଟି ଅଧିକାରିକ main ଶାଖାଠାରୁ ଆଗରେ ଅଛି।",
+ "buildDiverged": "ଏହି ବିଲ୍ଡଟି ଅଧିକାରିକ main ଶାଖାଠାରୁ ଅଲଗା ହୋଇଯାଇଛି।",
+ "buildUnknown": "ଏହି କଷ୍ଟମ୍ ବିଲ୍ଡକୁ ଅଧିକାରିକ main ଶାଖା ସହିତ ତୁଳନା କରାଯାଇପାରିବ ନାହିଁ।",
+ "notGitInstall": "ଏହି ଇନ୍ଷ୍ଟଲେସନ୍ରେ commit ସୂଚନା ନାହିଁ।",
+ "checkFailed": "ଅପଡେଟ୍ ଯାଞ୍ଚ କରାଯାଇପାରିଲା ନାହିଁ।",
+ "contactsGithub": "ଯାଞ୍ଚଗୁଡ଼ିକ ମାନୁଆଲ୍ ଭାବେ କରାଯାଏ ଏବଂ GitHub ସହିତ ସଂଯୋଗ କରେ।",
+ "openReleases": "GitHub Releases ଖୋଲନ୍ତୁ",
+ "restartAfterUpdate": "ବିଲ୍ଡ ସମ୍ପୂର୍ଣ୍ଣ ହେବା ପରେ FreeLLMAPI ପୁନଃ ଚାଲୁ କରନ୍ତୁ।"
},
"models": {
"title": "ମଡେଲଗୁଡିକ",
diff --git a/client/src/i18n/locales/pa.json b/client/src/i18n/locales/pa.json
index 7a254df6e..666e19a69 100644
--- a/client/src/i18n/locales/pa.json
+++ b/client/src/i18n/locales/pa.json
@@ -124,7 +124,20 @@
"compressionPreview": "ਲਾਈਵ ਝਲਕ",
"compressionPreviewDescription": "ਇਹ ਵੇਖਣ ਲਈ ਕਿ ਪ੍ਰਦਾਤਾ ਨੂੰ ਕੀ ਮਿਲੇਗਾ, ਬੇਨਤੀ ਦਾ ਬਾਡੀ ਪਾਈਪਲਾਈਨ ਵਿੱਚੋਂ ਲੰਘਾਓ।",
"compressionPreviewPlaceholder": "ਬੇਨਤੀ JSON ਜਾਂ ਸਾਦਾ ਟੈਕਸਟ ਪੇਸਟ ਕਰੋ",
- "compressionRunPreview": "ਝਲਕ ਚਲਾਓ"
+ "compressionRunPreview": "ਝਲਕ ਚਲਾਓ",
+ "updatesTitle": "ਅੱਪਡੇਟ",
+ "currentVersion": "ਮੌਜੂਦਾ ਬਿਲਡ:",
+ "updateAvailable": "ਅੱਪਡੇਟ ਉਪਲਬਧ ਹੈ",
+ "changelog": "ਕੀ ਬਦਲਿਆ ਹੈ",
+ "upToDate": "ਨਵੀਨਤਮ ਹੈ",
+ "buildAhead": "ਇਹ ਬਿਲਡ ਅਧਿਕਾਰਤ main ਸ਼ਾਖਾ ਤੋਂ ਅੱਗੇ ਹੈ।",
+ "buildDiverged": "ਇਹ ਬਿਲਡ ਅਧਿਕਾਰਤ main ਸ਼ਾਖਾ ਤੋਂ ਵੱਖ ਹੋ ਗਿਆ ਹੈ।",
+ "buildUnknown": "ਇਸ ਕਸਟਮ ਬਿਲਡ ਦੀ ਤੁਲਨਾ ਅਧਿਕਾਰਤ main ਸ਼ਾਖਾ ਨਾਲ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।",
+ "notGitInstall": "ਇਸ ਇੰਸਟਾਲੇਸ਼ਨ ਵਿੱਚ commit ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਨਹੀਂ ਹੈ।",
+ "checkFailed": "ਅੱਪਡੇਟਾਂ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ।",
+ "contactsGithub": "ਜਾਂਚਾਂ ਹੱਥੀਂ ਚਲਾਈਆਂ ਜਾਂਦੀਆਂ ਹਨ ਅਤੇ GitHub ਨਾਲ ਸੰਪਰਕ ਕਰਦੀਆਂ ਹਨ।",
+ "openReleases": "GitHub Releases ਖੋਲ੍ਹੋ",
+ "restartAfterUpdate": "ਬਿਲਡ ਪੂਰਾ ਹੋਣ ਤੋਂ ਬਾਅਦ FreeLLMAPI ਨੂੰ ਮੁੜ ਚਾਲੂ ਕਰੋ।"
},
"models": {
"title": "ਮਾਡਲ",
diff --git a/client/src/i18n/locales/pl.json b/client/src/i18n/locales/pl.json
index 0b409eabf..218cd9179 100644
--- a/client/src/i18n/locales/pl.json
+++ b/client/src/i18n/locales/pl.json
@@ -124,7 +124,20 @@
"compressionPreview": "Podgląd na żywo",
"compressionPreviewDescription": "Prześlij treść żądania przez potok, aby zobaczyć, co otrzymałby dostawca.",
"compressionPreviewPlaceholder": "Wklej JSON żądania lub zwykły tekst",
- "compressionRunPreview": "Uruchom podgląd"
+ "compressionRunPreview": "Uruchom podgląd",
+ "updatesTitle": "Aktualizacje",
+ "currentVersion": "Bieżąca kompilacja:",
+ "updateAvailable": "Dostępna aktualizacja",
+ "changelog": "Co się zmieniło",
+ "upToDate": "Aktualne",
+ "buildAhead": "Ta kompilacja wyprzedza oficjalną gałąź main.",
+ "buildDiverged": "Ta kompilacja odbiega od oficjalnej gałęzi main.",
+ "buildUnknown": "Tej niestandardowej kompilacji nie można porównać z oficjalną gałęzią main.",
+ "notGitInstall": "Ta instalacja nie zawiera informacji o commicie.",
+ "checkFailed": "Nie udało się sprawdzić dostępności aktualizacji.",
+ "contactsGithub": "Sprawdzanie jest uruchamiane ręcznie i nawiązuje połączenie z GitHubem.",
+ "openReleases": "Otwórz wydania w GitHubie",
+ "restartAfterUpdate": "Uruchom ponownie FreeLLMAPI po zakończeniu kompilacji."
},
"models": {
"title": "Modele",
diff --git a/client/src/i18n/locales/pt-BR.json b/client/src/i18n/locales/pt-BR.json
index be3008fdc..ff5fa11c3 100644
--- a/client/src/i18n/locales/pt-BR.json
+++ b/client/src/i18n/locales/pt-BR.json
@@ -124,7 +124,20 @@
"compressionPreview": "Prévia ao vivo",
"compressionPreviewDescription": "Envie um corpo de solicitação pelo pipeline para ver o que um provedor receberia.",
"compressionPreviewPlaceholder": "Cole o JSON da solicitação ou texto simples",
- "compressionRunPreview": "Executar prévia"
+ "compressionRunPreview": "Executar prévia",
+ "updatesTitle": "Atualizações",
+ "currentVersion": "Build atual:",
+ "updateAvailable": "Atualização disponível",
+ "changelog": "O que mudou",
+ "upToDate": "Atualizado",
+ "buildAhead": "Esta build está à frente da branch main oficial.",
+ "buildDiverged": "Esta build divergiu da branch main oficial.",
+ "buildUnknown": "Esta build personalizada não pode ser comparada à branch main oficial.",
+ "notGitInstall": "Esta instalação não inclui informações do commit.",
+ "checkFailed": "Não foi possível verificar se há atualizações.",
+ "contactsGithub": "As verificações são manuais e acessam o GitHub.",
+ "openReleases": "Abrir releases no GitHub",
+ "restartAfterUpdate": "Reinicie o FreeLLMAPI após a conclusão da build."
},
"models": {
"title": "Modelos",
diff --git a/client/src/i18n/locales/pt-PT.json b/client/src/i18n/locales/pt-PT.json
index 8de6b5e81..05ae901ca 100644
--- a/client/src/i18n/locales/pt-PT.json
+++ b/client/src/i18n/locales/pt-PT.json
@@ -124,7 +124,20 @@
"compressionPreview": "Pré-visualização em direto",
"compressionPreviewDescription": "Envie um corpo de pedido pelo pipeline para ver o que um fornecedor receberia.",
"compressionPreviewPlaceholder": "Cole o JSON do pedido ou texto simples",
- "compressionRunPreview": "Executar pré-visualização"
+ "compressionRunPreview": "Executar pré-visualização",
+ "updatesTitle": "Atualizações",
+ "currentVersion": "Compilação atual:",
+ "updateAvailable": "Atualização disponível",
+ "changelog": "O que mudou",
+ "upToDate": "Atualizado",
+ "buildAhead": "Esta compilação está à frente do ramo main oficial.",
+ "buildDiverged": "Esta compilação divergiu do ramo main oficial.",
+ "buildUnknown": "Esta compilação personalizada não pode ser comparada com o ramo main oficial.",
+ "notGitInstall": "Esta instalação não inclui informações do commit.",
+ "checkFailed": "Não foi possível procurar atualizações.",
+ "contactsGithub": "As verificações são manuais e contactam o GitHub.",
+ "openReleases": "Abrir lançamentos no GitHub",
+ "restartAfterUpdate": "Reinicie o FreeLLMAPI após a conclusão da compilação."
},
"models": {
"title": "Modelos",
diff --git a/client/src/i18n/locales/ro.json b/client/src/i18n/locales/ro.json
index 967e49e0d..d8cc40e88 100644
--- a/client/src/i18n/locales/ro.json
+++ b/client/src/i18n/locales/ro.json
@@ -124,7 +124,20 @@
"compressionPreview": "Previzualizare live",
"compressionPreviewDescription": "Trimite corpul unei cereri prin lanțul de procesare pentru a vedea ce ar primi un furnizor.",
"compressionPreviewPlaceholder": "Lipește JSON-ul cererii sau text simplu",
- "compressionRunPreview": "Rulează previzualizarea"
+ "compressionRunPreview": "Rulează previzualizarea",
+ "updatesTitle": "Actualizări",
+ "currentVersion": "Versiunea curentă:",
+ "updateAvailable": "Actualizare disponibilă",
+ "changelog": "Ce s-a schimbat",
+ "upToDate": "La zi",
+ "buildAhead": "Această versiune este înaintea ramurii main oficiale.",
+ "buildDiverged": "Această versiune a deviat de la ramura main oficială.",
+ "buildUnknown": "Această versiune personalizată nu poate fi comparată cu ramura main oficială.",
+ "notGitInstall": "Această instalare nu include informații despre commit.",
+ "checkFailed": "Nu s-au putut verifica actualizările.",
+ "contactsGithub": "Verificările sunt inițiate manual și contactează GitHub.",
+ "openReleases": "Deschide versiunile GitHub",
+ "restartAfterUpdate": "Repornește FreeLLMAPI după finalizarea compilării."
},
"models": {
"title": "Modele",
diff --git a/client/src/i18n/locales/ru.json b/client/src/i18n/locales/ru.json
index 1375c7138..a3bbf6b5d 100644
--- a/client/src/i18n/locales/ru.json
+++ b/client/src/i18n/locales/ru.json
@@ -124,7 +124,20 @@
"compressionPreview": "Живой предпросмотр",
"compressionPreviewDescription": "Пропустите тело запроса через конвейер, чтобы увидеть, что получит поставщик.",
"compressionPreviewPlaceholder": "Вставьте JSON запроса или обычный текст",
- "compressionRunPreview": "Запустить предпросмотр"
+ "compressionRunPreview": "Запустить предпросмотр",
+ "updatesTitle": "Обновления",
+ "currentVersion": "Текущая сборка:",
+ "updateAvailable": "Доступно обновление",
+ "changelog": "Что изменилось",
+ "upToDate": "Установлена актуальная версия",
+ "buildAhead": "Эта сборка опережает официальную ветку main.",
+ "buildDiverged": "История этой сборки разошлась с официальной веткой main.",
+ "buildUnknown": "Эту пользовательскую сборку невозможно сравнить с официальной веткой main.",
+ "notGitInstall": "Эта установка не содержит сведений о коммите.",
+ "checkFailed": "Не удалось проверить наличие обновлений.",
+ "contactsGithub": "Проверка запускается вручную и обращается к GitHub.",
+ "openReleases": "Открыть релизы на GitHub",
+ "restartAfterUpdate": "Перезапустите FreeLLMAPI после завершения сборки."
},
"models": {
"title": "Модели",
diff --git a/client/src/i18n/locales/si.json b/client/src/i18n/locales/si.json
index e75a1d616..893f0b066 100644
--- a/client/src/i18n/locales/si.json
+++ b/client/src/i18n/locales/si.json
@@ -124,7 +124,20 @@
"compressionPreview": "සජීවී පෙරදසුන",
"compressionPreviewDescription": "සපයන්නෙකුට ලැබෙන්නේ කුමක්දැයි බැලීමට ඉල්ලීම් ශරීරයක් නල මාර්ගය හරහා යවන්න.",
"compressionPreviewPlaceholder": "ඉල්ලීමේ JSON හෝ සරල පෙළ අලවන්න",
- "compressionRunPreview": "පෙරදසුන ධාවනය කරන්න"
+ "compressionRunPreview": "පෙරදසුන ධාවනය කරන්න",
+ "updatesTitle": "යාවත්කාලීන",
+ "currentVersion": "වත්මන් ගොඩනැගීම:",
+ "updateAvailable": "යාවත්කාලීනයක් තිබේ",
+ "changelog": "වෙනස් වූ දේ",
+ "upToDate": "යාවත්කාලීනයි",
+ "buildAhead": "මෙම ගොඩනැගීම නිල main ශාඛාවට වඩා ඉදිරියෙන් ඇත.",
+ "buildDiverged": "මෙම ගොඩනැගීම නිල main ශාඛාවෙන් අපගමනය වී ඇත.",
+ "buildUnknown": "මෙම අභිරුචි ගොඩනැගීම නිල main ශාඛාව සමඟ සැසඳිය නොහැක.",
+ "notGitInstall": "මෙම ස්ථාපනයේ commit තොරතුරු ඇතුළත් නොවේ.",
+ "checkFailed": "යාවත්කාලීන පරීක්ෂා කිරීමට නොහැකි විය.",
+ "contactsGithub": "පරීක්ෂා කිරීම් අතින් ක්රියාත්මක කරන අතර GitHub සමඟ සම්බන්ධ වේ.",
+ "openReleases": "GitHub Releases විවෘත කරන්න",
+ "restartAfterUpdate": "ගොඩනැගීම සම්පූර්ණ වූ පසු FreeLLMAPI නැවත ආරම්භ කරන්න."
},
"models": {
"title": "ආකෘති",
diff --git a/client/src/i18n/locales/sk.json b/client/src/i18n/locales/sk.json
index 4c026baac..d880f5796 100644
--- a/client/src/i18n/locales/sk.json
+++ b/client/src/i18n/locales/sk.json
@@ -124,7 +124,20 @@
"compressionPreview": "Živý náhľad",
"compressionPreviewDescription": "Pošlite telo požiadavky spracovateľským reťazcom a uvidíte, čo by dostal poskytovateľ.",
"compressionPreviewPlaceholder": "Vložte JSON požiadavky alebo obyčajný text",
- "compressionRunPreview": "Spustiť náhľad"
+ "compressionRunPreview": "Spustiť náhľad",
+ "updatesTitle": "Aktualizácie",
+ "currentVersion": "Aktuálna zostava:",
+ "updateAvailable": "K dispozícii je aktualizácia",
+ "changelog": "Čo sa zmenilo",
+ "upToDate": "Aktuálne",
+ "buildAhead": "Táto zostava je pred oficiálnou vetvou main.",
+ "buildDiverged": "Táto zostava sa odchýlila od oficiálnej vetvy main.",
+ "buildUnknown": "Túto vlastnú zostavu nemožno porovnať s oficiálnou vetvou main.",
+ "notGitInstall": "Táto inštalácia neobsahuje informácie o commite.",
+ "checkFailed": "Nepodarilo sa skontrolovať aktualizácie.",
+ "contactsGithub": "Kontroly sa vykonávajú manuálne a pripájajú sa ku GitHubu.",
+ "openReleases": "Otvoriť vydania na GitHube",
+ "restartAfterUpdate": "Reštartujte FreeLLMAPI po dokončení zostavovania."
},
"models": {
"title": "Modely",
diff --git a/client/src/i18n/locales/sr.json b/client/src/i18n/locales/sr.json
index 022e7693c..ff948c872 100644
--- a/client/src/i18n/locales/sr.json
+++ b/client/src/i18n/locales/sr.json
@@ -124,7 +124,20 @@
"compressionPreview": "Преглед уживо",
"compressionPreviewDescription": "Пошаљите тело захтева кроз ланац обраде да видите шта би провајдер примио.",
"compressionPreviewPlaceholder": "Налепи JSON захтева или обичан текст",
- "compressionRunPreview": "Покрени преглед"
+ "compressionRunPreview": "Покрени преглед",
+ "updatesTitle": "Ажурирања",
+ "currentVersion": "Тренутна верзија:",
+ "updateAvailable": "Доступно је ажурирање",
+ "changelog": "Шта је промењено",
+ "upToDate": "Ажурно",
+ "buildAhead": "Ова верзија је испред званичне гране main.",
+ "buildDiverged": "Ова верзија се разишла са званичном граном main.",
+ "buildUnknown": "Ова прилагођена верзија се не може упоредити са званичном граном main.",
+ "notGitInstall": "Ова инсталација не садржи информације о комиту.",
+ "checkFailed": "Провера ажурирања није успела.",
+ "contactsGithub": "Провере се покрећу ручно и повезују се са GitHub-ом.",
+ "openReleases": "Отвори GitHub издања",
+ "restartAfterUpdate": "Поново покрените FreeLLMAPI након завршетка израде."
},
"models": {
"title": "Модели",
diff --git a/client/src/i18n/locales/sv.json b/client/src/i18n/locales/sv.json
index 5a4f0967b..f1098a6ae 100644
--- a/client/src/i18n/locales/sv.json
+++ b/client/src/i18n/locales/sv.json
@@ -124,7 +124,20 @@
"compressionPreview": "Live-förhandsvisning",
"compressionPreviewDescription": "Skicka en förfrågningskropp genom pipelinen för att se vad en leverantör skulle få.",
"compressionPreviewPlaceholder": "Klistra in förfrågnings-JSON eller vanlig text",
- "compressionRunPreview": "Kör förhandsvisning"
+ "compressionRunPreview": "Kör förhandsvisning",
+ "updatesTitle": "Uppdateringar",
+ "currentVersion": "Aktuell version:",
+ "updateAvailable": "Uppdatering tillgänglig",
+ "changelog": "Vad har ändrats",
+ "upToDate": "Uppdaterad",
+ "buildAhead": "Den här versionen ligger före officiella main.",
+ "buildDiverged": "Den här versionen har avvikit från officiella main.",
+ "buildUnknown": "Den här anpassade versionen kan inte jämföras med officiella main.",
+ "notGitInstall": "Den här installationen innehåller ingen commit-information.",
+ "checkFailed": "Det gick inte att söka efter uppdateringar.",
+ "contactsGithub": "Kontroller görs manuellt och kontaktar GitHub.",
+ "openReleases": "Öppna GitHub Releases",
+ "restartAfterUpdate": "Starta om FreeLLMAPI när bygget är klart."
},
"models": {
"title": "Modeller",
diff --git a/client/src/i18n/locales/sw.json b/client/src/i18n/locales/sw.json
index 7b705a5f7..5e9d49586 100644
--- a/client/src/i18n/locales/sw.json
+++ b/client/src/i18n/locales/sw.json
@@ -124,7 +124,20 @@
"compressionPreview": "Hakikisho la moja kwa moja",
"compressionPreviewDescription": "Pitisha mwili wa ombi kwenye mfumo ili uone kile ambacho mtoa huduma angepokea.",
"compressionPreviewPlaceholder": "Bandika JSON ya ombi au maandishi wazi",
- "compressionRunPreview": "Endesha hakikisho"
+ "compressionRunPreview": "Endesha hakikisho",
+ "updatesTitle": "Masasisho",
+ "currentVersion": "Toleo la sasa:",
+ "updateAvailable": "Sasisho linapatikana",
+ "changelog": "Kilichobadilika",
+ "upToDate": "Imesasishwa",
+ "buildAhead": "Toleo hili liko mbele ya tawi rasmi la main.",
+ "buildDiverged": "Toleo hili limejitenga na tawi rasmi la main.",
+ "buildUnknown": "Toleo hili maalum haliwezi kulinganishwa na tawi rasmi la main.",
+ "notGitInstall": "Usakinishaji huu hauna taarifa za commit.",
+ "checkFailed": "Imeshindikana kuangalia masasisho.",
+ "contactsGithub": "Ukaguzi hufanywa mwenyewe na huwasiliana na GitHub.",
+ "openReleases": "Fungua Matoleo ya GitHub",
+ "restartAfterUpdate": "Anzisha upya FreeLLMAPI baada ya ujenzi kukamilika."
},
"models": {
"title": "Mifano",
diff --git a/client/src/i18n/locales/ta.json b/client/src/i18n/locales/ta.json
index 493673dde..95cf0229c 100644
--- a/client/src/i18n/locales/ta.json
+++ b/client/src/i18n/locales/ta.json
@@ -124,7 +124,20 @@
"compressionPreview": "நேரடி முன்னோட்டம்",
"compressionPreviewDescription": "வழங்குபவருக்கு என்ன கிடைக்கும் என்று பார்க்க ஒரு கோரிக்கை பாடியைப் பைப்லைன் வழியாக அனுப்பவும்.",
"compressionPreviewPlaceholder": "கோரிக்கை JSON அல்லது சாதாரண உரையை ஒட்டவும்",
- "compressionRunPreview": "முன்னோட்டத்தை இயக்கு"
+ "compressionRunPreview": "முன்னோட்டத்தை இயக்கு",
+ "updatesTitle": "புதுப்பிப்புகள்",
+ "currentVersion": "தற்போதைய உருவாக்கம்:",
+ "updateAvailable": "புதுப்பிப்பு கிடைக்கிறது",
+ "changelog": "என்ன மாற்றப்பட்டுள்ளது",
+ "upToDate": "புதுப்பித்த நிலையில் உள்ளது",
+ "buildAhead": "இந்த உருவாக்கம் அதிகாரப்பூர்வ main-ஐ விட முன்னிலையில் உள்ளது.",
+ "buildDiverged": "இந்த உருவாக்கம் அதிகாரப்பூர்வ main-இலிருந்து வேறுபட்டுள்ளது.",
+ "buildUnknown": "இந்தத் தனிப்பயன் உருவாக்கத்தை அதிகாரப்பூர்வ main உடன் ஒப்பிட முடியாது.",
+ "notGitInstall": "இந்த நிறுவலில் commit தகவல் இல்லை.",
+ "checkFailed": "புதுப்பிப்புகளைச் சரிபார்க்க முடியவில்லை.",
+ "contactsGithub": "சரிபார்ப்புகள் கைமுறையாகச் செய்யப்படுகின்றன மற்றும் GitHub-ஐத் தொடர்புகொள்கின்றன.",
+ "openReleases": "GitHub வெளியீடுகளைத் திற",
+ "restartAfterUpdate": "உருவாக்கம் முடிந்ததும் FreeLLMAPI-ஐ மறுதொடக்கம் செய்யவும்."
},
"models": {
"title": "மாதிரிகள்",
diff --git a/client/src/i18n/locales/te.json b/client/src/i18n/locales/te.json
index 104b27a93..dbc84a3f3 100644
--- a/client/src/i18n/locales/te.json
+++ b/client/src/i18n/locales/te.json
@@ -124,7 +124,20 @@
"compressionPreview": "లైవ్ ప్రివ్యూ",
"compressionPreviewDescription": "ప్రొవైడర్కు ఏమి అందుతుందో చూడటానికి ఒక అభ్యర్థన బాడీని పైప్లైన్ ద్వారా పంపండి.",
"compressionPreviewPlaceholder": "అభ్యర్థన JSON లేదా సాదా టెక్స్ట్ అతికించండి",
- "compressionRunPreview": "ప్రివ్యూ అమలు చేయండి"
+ "compressionRunPreview": "ప్రివ్యూ అమలు చేయండి",
+ "updatesTitle": "నవీకరణలు",
+ "currentVersion": "ప్రస్తుత బిల్డ్:",
+ "updateAvailable": "నవీకరణ అందుబాటులో ఉంది",
+ "changelog": "ఏమి మారింది",
+ "upToDate": "తాజా స్థితిలో ఉంది",
+ "buildAhead": "ఈ బిల్డ్ అధికారిక main కంటే ముందుంది.",
+ "buildDiverged": "ఈ బిల్డ్ అధికారిక main నుండి వేరుగా మారింది.",
+ "buildUnknown": "ఈ అనుకూల బిల్డ్ను అధికారిక mainతో పోల్చడం సాధ్యం కాదు.",
+ "notGitInstall": "ఈ ఇన్స్టాలేషన్లో commit సమాచారం లేదు.",
+ "checkFailed": "నవీకరణల కోసం తనిఖీ చేయడం సాధ్యం కాలేదు.",
+ "contactsGithub": "తనిఖీలు మాన్యువల్గా జరుగుతాయి మరియు GitHubను సంప్రదిస్తాయి.",
+ "openReleases": "GitHub విడుదలలను తెరవండి",
+ "restartAfterUpdate": "బిల్డ్ పూర్తయిన తర్వాత FreeLLMAPIని పునఃప్రారంభించండి."
},
"models": {
"title": "మోడల్స్",
diff --git a/client/src/i18n/locales/th.json b/client/src/i18n/locales/th.json
index e5c65e531..7bcb62f32 100644
--- a/client/src/i18n/locales/th.json
+++ b/client/src/i18n/locales/th.json
@@ -124,7 +124,20 @@
"compressionPreview": "ตัวอย่างสด",
"compressionPreviewDescription": "ส่งเนื้อหาคำขอผ่านไปป์ไลน์เพื่อดูว่าผู้ให้บริการจะได้รับอะไร",
"compressionPreviewPlaceholder": "วาง JSON ของคำขอหรือข้อความธรรมดา",
- "compressionRunPreview": "รันตัวอย่าง"
+ "compressionRunPreview": "รันตัวอย่าง",
+ "updatesTitle": "การอัปเดต",
+ "currentVersion": "บิลด์ปัจจุบัน:",
+ "updateAvailable": "มีการอัปเดต",
+ "changelog": "มีอะไรเปลี่ยนแปลง",
+ "upToDate": "เป็นเวอร์ชันล่าสุด",
+ "buildAhead": "บิลด์นี้ล้ำหน้า main อย่างเป็นทางการ",
+ "buildDiverged": "บิลด์นี้แยกออกจาก main อย่างเป็นทางการ",
+ "buildUnknown": "ไม่สามารถเปรียบเทียบบิลด์ที่ปรับแต่งนี้กับ main อย่างเป็นทางการได้",
+ "notGitInstall": "การติดตั้งนี้ไม่มีข้อมูล commit",
+ "checkFailed": "ไม่สามารถตรวจสอบการอัปเดตได้",
+ "contactsGithub": "การตรวจสอบเป็นแบบดำเนินการเองและมีการติดต่อ GitHub",
+ "openReleases": "เปิด GitHub Releases",
+ "restartAfterUpdate": "รีสตาร์ต FreeLLMAPI หลังจากบิลด์เสร็จสิ้น"
},
"models": {
"title": "โมเดล",
diff --git a/client/src/i18n/locales/tl.json b/client/src/i18n/locales/tl.json
index 46127fbc3..04caaa6b6 100644
--- a/client/src/i18n/locales/tl.json
+++ b/client/src/i18n/locales/tl.json
@@ -124,7 +124,20 @@
"compressionPreview": "Live preview",
"compressionPreviewDescription": "Ipadala ang request body sa pipeline para makita kung ano ang matatanggap ng provider.",
"compressionPreviewPlaceholder": "I-paste ang request JSON o plain text",
- "compressionRunPreview": "Patakbuhin ang preview"
+ "compressionRunPreview": "Patakbuhin ang preview",
+ "updatesTitle": "Mga Update",
+ "currentVersion": "Kasalukuyang build:",
+ "updateAvailable": "May available na update",
+ "changelog": "Ano ang nagbago",
+ "upToDate": "Napapanahon",
+ "buildAhead": "Nauuna ang build na ito sa opisyal na main.",
+ "buildDiverged": "Lumihis ang build na ito sa opisyal na main.",
+ "buildUnknown": "Hindi maihahambing ang custom build na ito sa opisyal na main.",
+ "notGitInstall": "Walang impormasyon ng commit ang installation na ito.",
+ "checkFailed": "Hindi masuri kung may mga update.",
+ "contactsGithub": "Manu-mano ang mga pagsusuri at kumokonekta ang mga ito sa GitHub.",
+ "openReleases": "Buksan ang GitHub Releases",
+ "restartAfterUpdate": "I-restart ang FreeLLMAPI kapag natapos ang build."
},
"models": {
"title": "Mga Modelo",
diff --git a/client/src/i18n/locales/tr.json b/client/src/i18n/locales/tr.json
index 0abf480fe..a7d76c0b0 100644
--- a/client/src/i18n/locales/tr.json
+++ b/client/src/i18n/locales/tr.json
@@ -124,7 +124,20 @@
"compressionPreview": "Canlı önizleme",
"compressionPreviewDescription": "Bir istek gövdesini hattan geçirerek sağlayıcının ne alacağını görün.",
"compressionPreviewPlaceholder": "İstek JSON'u veya düz metin yapıştırın",
- "compressionRunPreview": "Önizlemeyi çalıştır"
+ "compressionRunPreview": "Önizlemeyi çalıştır",
+ "updatesTitle": "Güncellemeler",
+ "currentVersion": "Mevcut derleme:",
+ "updateAvailable": "Güncelleme mevcut",
+ "changelog": "Neler değişti",
+ "upToDate": "Güncel",
+ "buildAhead": "Bu derleme resmi main dalının ilerisinde.",
+ "buildDiverged": "Bu derleme resmi main dalından ayrışmış.",
+ "buildUnknown": "Bu özel derleme resmi main dalıyla karşılaştırılamıyor.",
+ "notGitInstall": "Bu kurulum commit bilgisi içermiyor.",
+ "checkFailed": "Güncellemeler denetlenemedi.",
+ "contactsGithub": "Denetimler elle yapılır ve GitHub ile iletişim kurar.",
+ "openReleases": "GitHub Sürümlerini Aç",
+ "restartAfterUpdate": "Derleme tamamlandıktan sonra FreeLLMAPI'yi yeniden başlatın."
},
"models": {
"title": "Modeller",
diff --git a/client/src/i18n/locales/uk.json b/client/src/i18n/locales/uk.json
index 42147bc45..34e3f123b 100644
--- a/client/src/i18n/locales/uk.json
+++ b/client/src/i18n/locales/uk.json
@@ -124,7 +124,20 @@
"compressionPreview": "Попередній перегляд наживо",
"compressionPreviewDescription": "Пропустіть тіло запиту через конвеєр, щоб побачити, що отримає провайдер.",
"compressionPreviewPlaceholder": "Вставте JSON запиту або звичайний текст",
- "compressionRunPreview": "Запустити перегляд"
+ "compressionRunPreview": "Запустити перегляд",
+ "updatesTitle": "Оновлення",
+ "currentVersion": "Поточна збірка:",
+ "updateAvailable": "Доступне оновлення",
+ "changelog": "Що змінилося",
+ "upToDate": "Актуальна версія",
+ "buildAhead": "Ця збірка випереджає офіційну гілку main.",
+ "buildDiverged": "Ця збірка розійшлася з офіційною гілкою main.",
+ "buildUnknown": "Цю користувацьку збірку неможливо порівняти з офіційною гілкою main.",
+ "notGitInstall": "Ця інсталяція не містить інформації про commit.",
+ "checkFailed": "Не вдалося перевірити наявність оновлень.",
+ "contactsGithub": "Перевірки запускаються вручну та звертаються до GitHub.",
+ "openReleases": "Відкрити релізи GitHub",
+ "restartAfterUpdate": "Перезапустіть FreeLLMAPI після завершення збірки."
},
"models": {
"title": "Моделі",
diff --git a/client/src/i18n/locales/ur.json b/client/src/i18n/locales/ur.json
index 2ccb56c7b..9220726ae 100644
--- a/client/src/i18n/locales/ur.json
+++ b/client/src/i18n/locales/ur.json
@@ -124,7 +124,20 @@
"compressionPreview": "لائیو پیش منظر",
"compressionPreviewDescription": "درخواست کی باڈی پائپ لائن سے گزاریں تاکہ دیکھ سکیں کہ فراہم کنندہ کو کیا ملے گا۔",
"compressionPreviewPlaceholder": "درخواست کا JSON یا سادہ متن پیسٹ کریں",
- "compressionRunPreview": "پیش منظر چلائیں"
+ "compressionRunPreview": "پیش منظر چلائیں",
+ "updatesTitle": "اپ ڈیٹس",
+ "currentVersion": "موجودہ بلڈ:",
+ "updateAvailable": "اپ ڈیٹ دستیاب ہے",
+ "changelog": "کیا بدلا ہے",
+ "upToDate": "تازہ ترین",
+ "buildAhead": "یہ بلڈ آفیشل main سے آگے ہے۔",
+ "buildDiverged": "یہ بلڈ آفیشل main سے مختلف ہو گیا ہے۔",
+ "buildUnknown": "اس کسٹم بلڈ کا آفیشل main سے موازنہ نہیں کیا جا سکتا۔",
+ "notGitInstall": "اس انسٹالیشن میں commit کی معلومات شامل نہیں ہیں۔",
+ "checkFailed": "اپ ڈیٹس کی جانچ نہیں ہو سکی۔",
+ "contactsGithub": "جانچ دستی طور پر کی جاتی ہے اور GitHub سے رابطہ کرتی ہے۔",
+ "openReleases": "GitHub ریلیزز کھولیں",
+ "restartAfterUpdate": "بلڈ مکمل ہونے کے بعد FreeLLMAPI کو دوبارہ شروع کریں۔"
},
"models": {
"title": "ماڈلز",
diff --git a/client/src/i18n/locales/uz.json b/client/src/i18n/locales/uz.json
index 190dc8c32..21aa38525 100644
--- a/client/src/i18n/locales/uz.json
+++ b/client/src/i18n/locales/uz.json
@@ -124,7 +124,20 @@
"compressionPreview": "Jonli oldindan ko'rish",
"compressionPreviewDescription": "So'rov tanasini jarayondan o'tkazing va provayder nimani olishini ko'ring.",
"compressionPreviewPlaceholder": "So'rov JSON yoki oddiy matnni joylashtiring",
- "compressionRunPreview": "Oldindan ko'rishni ishga tushirish"
+ "compressionRunPreview": "Oldindan ko'rishni ishga tushirish",
+ "updatesTitle": "Yangilanishlar",
+ "currentVersion": "Joriy build:",
+ "updateAvailable": "Yangilanish mavjud",
+ "changelog": "Nimalar o'zgardi",
+ "upToDate": "Eng so'nggi versiya",
+ "buildAhead": "Bu build rasmiy main tarmog'idan oldinda.",
+ "buildDiverged": "Bu build rasmiy main tarmog'idan ajralib ketgan.",
+ "buildUnknown": "Bu maxsus buildni rasmiy main tarmog'i bilan taqqoslab bo'lmaydi.",
+ "notGitInstall": "Bu o'rnatishda commit ma'lumoti mavjud emas.",
+ "checkFailed": "Yangilanishlarni tekshirib bo'lmadi.",
+ "contactsGithub": "Tekshiruvlar qo'lda bajariladi va GitHub bilan bog'lanadi.",
+ "openReleases": "GitHub relizlarini ochish",
+ "restartAfterUpdate": "Build tugagach, FreeLLMAPI'ni qayta ishga tushiring."
},
"models": {
"title": "Modellar",
diff --git a/client/src/i18n/locales/vi.json b/client/src/i18n/locales/vi.json
index c51a0e7e9..f6f627c02 100644
--- a/client/src/i18n/locales/vi.json
+++ b/client/src/i18n/locales/vi.json
@@ -124,7 +124,20 @@
"compressionPreview": "Xem trước trực tiếp",
"compressionPreviewDescription": "Gửi nội dung yêu cầu qua quy trình nén để xem nhà cung cấp sẽ nhận được gì.",
"compressionPreviewPlaceholder": "Dán JSON yêu cầu hoặc văn bản thuần",
- "compressionRunPreview": "Chạy xem trước"
+ "compressionRunPreview": "Chạy xem trước",
+ "updatesTitle": "Bản cập nhật",
+ "currentVersion": "Bản dựng hiện tại:",
+ "updateAvailable": "Có bản cập nhật",
+ "changelog": "Có gì thay đổi",
+ "upToDate": "Đã cập nhật",
+ "buildAhead": "Bản dựng này đi trước nhánh main chính thức.",
+ "buildDiverged": "Bản dựng này đã phân kỳ khỏi nhánh main chính thức.",
+ "buildUnknown": "Không thể so sánh bản dựng tùy chỉnh này với nhánh main chính thức.",
+ "notGitInstall": "Bản cài đặt này không có thông tin commit.",
+ "checkFailed": "Không thể kiểm tra bản cập nhật.",
+ "contactsGithub": "Việc kiểm tra được thực hiện thủ công và có kết nối với GitHub.",
+ "openReleases": "Mở GitHub Releases",
+ "restartAfterUpdate": "Khởi động lại FreeLLMAPI sau khi hoàn tất bản dựng."
},
"models": {
"title": "Người mẫu",
diff --git a/client/src/i18n/locales/yo.json b/client/src/i18n/locales/yo.json
index 571e7b6f1..37cac5581 100644
--- a/client/src/i18n/locales/yo.json
+++ b/client/src/i18n/locales/yo.json
@@ -124,7 +124,20 @@
"compressionPreview": "Awotẹlẹ laaye",
"compressionPreviewDescription": "Rán ara ìbéèrè kan gba ìlànà náà kọjá láti rí ohun tí olupese yóò gbà.",
"compressionPreviewPlaceholder": "Lẹ JSON ibeere tabi ọrọ lasan",
- "compressionRunPreview": "Ṣiṣe awotẹlẹ"
+ "compressionRunPreview": "Ṣiṣe awotẹlẹ",
+ "updatesTitle": "Àwọn ìmúdójúìwọ̀n",
+ "currentVersion": "Ẹ̀yà ìkọ́lé lọ́wọ́lọ́wọ́:",
+ "updateAvailable": "Ìmúdójúìwọ̀n wà",
+ "changelog": "Ohun tí ó yí padà",
+ "upToDate": "Ó ti mú dójú ìwọ̀n",
+ "buildAhead": "Ẹ̀yà ìkọ́lé yìí ti lọ síwájú main àṣẹ.",
+ "buildDiverged": "Ẹ̀yà ìkọ́lé yìí ti yà kúrò ní main àṣẹ.",
+ "buildUnknown": "A kò lè fi ẹ̀yà ìkọ́lé àkànṣe yìí wé main àṣẹ.",
+ "notGitInstall": "Fífìmọ́lẹ̀ yìí kò ní àlàyé commit.",
+ "checkFailed": "A kò lè ṣàyẹ̀wò àwọn ìmúdójúìwọ̀n.",
+ "contactsGithub": "Ọwọ́ ni a fi ń ṣe àwọn àyẹ̀wò, wọ́n sì ń kan sí GitHub.",
+ "openReleases": "Ṣí àwọn ìtújáde GitHub",
+ "restartAfterUpdate": "Tun FreeLLMAPI bẹ̀rẹ̀ lẹ́yìn tí ìkọ́lé bá parí."
},
"models": {
"title": "Awọn awoṣe",
diff --git a/client/src/i18n/locales/zh-CN.json b/client/src/i18n/locales/zh-CN.json
index 0343da823..bc0322776 100644
--- a/client/src/i18n/locales/zh-CN.json
+++ b/client/src/i18n/locales/zh-CN.json
@@ -124,7 +124,20 @@
"compressionPreview": "实时预览",
"compressionPreviewDescription": "将请求体送入压缩流程,查看提供方实际会收到的内容。",
"compressionPreviewPlaceholder": "粘贴请求 JSON 或纯文本",
- "compressionRunPreview": "运行预览"
+ "compressionRunPreview": "运行预览",
+ "updatesTitle": "更新",
+ "currentVersion": "当前构建:",
+ "updateAvailable": "有可用更新",
+ "changelog": "更新内容",
+ "upToDate": "已是最新版本",
+ "buildAhead": "此构建领先于官方 main 分支。",
+ "buildDiverged": "此构建已偏离官方 main 分支。",
+ "buildUnknown": "无法将此自定义构建与官方 main 分支进行比较。",
+ "notGitInstall": "此安装不包含 commit 信息。",
+ "checkFailed": "无法检查更新。",
+ "contactsGithub": "检查需手动执行,并会连接 GitHub。",
+ "openReleases": "打开 GitHub Releases",
+ "restartAfterUpdate": "构建完成后重启 FreeLLMAPI。"
},
"models": {
"title": "模型",
diff --git a/client/src/i18n/locales/zh-TW.json b/client/src/i18n/locales/zh-TW.json
index b7a28436a..a479369fd 100644
--- a/client/src/i18n/locales/zh-TW.json
+++ b/client/src/i18n/locales/zh-TW.json
@@ -124,7 +124,20 @@
"compressionPreview": "即時預覽",
"compressionPreviewDescription": "將請求主體送入流程,檢視提供者實際會收到的內容。",
"compressionPreviewPlaceholder": "貼上請求 JSON 或純文字",
- "compressionRunPreview": "執行預覽"
+ "compressionRunPreview": "執行預覽",
+ "updatesTitle": "更新",
+ "currentVersion": "目前建置:",
+ "updateAvailable": "有可用更新",
+ "changelog": "更新內容",
+ "upToDate": "已是最新版本",
+ "buildAhead": "此建置領先官方 main 分支。",
+ "buildDiverged": "此建置已偏離官方 main 分支。",
+ "buildUnknown": "無法將此自訂建置與官方 main 分支進行比較。",
+ "notGitInstall": "此安裝不包含 commit 資訊。",
+ "checkFailed": "無法檢查更新。",
+ "contactsGithub": "檢查需手動執行,並會連線至 GitHub。",
+ "openReleases": "開啟 GitHub Releases",
+ "restartAfterUpdate": "建置完成後重新啟動 FreeLLMAPI。"
},
"models": {
"title": "型號",
diff --git a/desktop/scripts/bundle-server.mjs b/desktop/scripts/bundle-server.mjs
index da43a7c56..6e7c1199d 100644
--- a/desktop/scripts/bundle-server.mjs
+++ b/desktop/scripts/bundle-server.mjs
@@ -7,6 +7,8 @@ import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const githubSha = process.env.GITHUB_SHA;
+const hasBuildIdentity = /^[0-9a-f]{40}$/i.test(githubSha ?? '');
await build({
entryPoints: [path.resolve(__dirname, '../src/server-host.ts')],
@@ -16,6 +18,10 @@ await build({
target: 'node20',
outfile: path.resolve(__dirname, '../build/server.mjs'),
external: ['better-sqlite3'],
+ define: {
+ 'process.env.FREELLMAPI_COMMIT_SHA': JSON.stringify(hasBuildIdentity ? githubSha : ''),
+ 'process.env.FREELLMAPI_INSTALL_METHOD': JSON.stringify(hasBuildIdentity ? 'desktop' : ''),
+ },
// Some inlined CJS deps (express internals) reference `require` at runtime;
// give the ESM bundle a working one.
banner: {
diff --git a/server/src/__tests__/routes/auth.test.ts b/server/src/__tests__/routes/auth.test.ts
index 9a43d1775..abb45fc86 100644
--- a/server/src/__tests__/routes/auth.test.ts
+++ b/server/src/__tests__/routes/auth.test.ts
@@ -38,6 +38,7 @@ describe('Dashboard auth (#35)', () => {
expect((await call(app, 'GET', '/api/keys')).status).toBe(401);
expect((await call(app, 'GET', '/api/fallback')).status).toBe(401);
expect((await call(app, 'GET', '/api/settings/api-key')).status).toBe(401);
+ expect((await call(app, 'GET', '/api/update/status')).status).toBe(401);
});
it('leaves /api/ping and the /v1 proxy reachable without a dashboard session', async () => {
diff --git a/server/src/__tests__/routes/update.test.ts b/server/src/__tests__/routes/update.test.ts
new file mode 100644
index 000000000..912d0d6ac
--- /dev/null
+++ b/server/src/__tests__/routes/update.test.ts
@@ -0,0 +1,490 @@
+import { describe, it, expect, vi } from 'vitest';
+import express from 'express';
+import type { Express } from 'express';
+import http from 'node:http';
+import { createUpdateRouter } from '../../routes/update.js';
+
+const LOCAL_SHA = '0123456789abcdef0123456789abcdef01234567';
+const REMOTE_SHA = '89abcdef0123456789abcdef0123456789abcdef';
+const NOW = Date.parse('2026-07-28T14:00:00.000Z');
+
+function httpGet(app: Express, path: string): Promise<{ status: number; body: any }> {
+ return new Promise((resolve, reject) => {
+ const server = app.listen(0, () => {
+ const address = server.address();
+ if (!address || typeof address === 'string') return reject(new Error('No test server address'));
+ const req = http.request(
+ { hostname: '127.0.0.1', port: address.port, path, method: 'GET' },
+ (res) => {
+ let data = '';
+ res.on('data', chunk => { data += chunk; });
+ res.on('end', () => {
+ server.close();
+ resolve({ status: res.statusCode!, body: JSON.parse(data) });
+ });
+ },
+ );
+ req.on('error', (error) => { server.close(); reject(error); });
+ req.end();
+ });
+ });
+}
+
+function response(body: unknown, status = 200): Response {
+ return new Response(body === undefined ? undefined : JSON.stringify(body), {
+ status,
+ headers: { 'Content-Type': 'application/json' },
+ });
+}
+
+function atomResponse(commits: Array<{ sha: string; message: string; date?: string }>, status = 200): Response {
+ const entries = commits.map(commit => `
+
+ tag:github.com,2008:Grit::Commit/${commit.sha}
+ ${commit.message}
+ ${commit.date ? `${commit.date}` : ''}
+ `).join('');
+ return new Response(`${entries}`, {
+ status,
+ headers: { 'Content-Type': 'application/atom+xml' },
+ });
+}
+
+function compareBody(status: 'identical' | 'ahead' | 'behind' | 'diverged', message = 'remote commit') {
+ const commit = {
+ sha: status === 'identical' ? LOCAL_SHA : REMOTE_SHA,
+ commit: {
+ message,
+ committer: { date: '2026-07-28T10:00:00Z' },
+ },
+ };
+ return {
+ status,
+ commits: status === 'identical' || status === 'behind' ? [] : [commit],
+ base_commit: commit,
+ merge_base_commit: commit,
+ };
+}
+
+function createTestApp(overrides: Parameters[0] = {}) {
+ const app = express();
+ const fetchMock = overrides.fetch ?? vi.fn(async () => response(compareBody('identical')));
+ const execMock = overrides.execFileSync ?? vi.fn(() => `${LOCAL_SHA}\n`);
+ const logger = overrides.logger ?? { error: vi.fn() };
+ app.use('/api/update', createUpdateRouter({
+ env: {},
+ cwd: '/worktree/server',
+ now: () => NOW,
+ ...overrides,
+ fetch: fetchMock,
+ execFileSync: execMock,
+ logger,
+ }));
+ return { app, fetchMock, execMock, logger };
+}
+
+describe('Update API', () => {
+ describe('GET /api/update/check', () => {
+ it.each([
+ ['identical', 'current'],
+ ['ahead', 'available'],
+ ['behind', 'ahead'],
+ ['diverged', 'diverged'],
+ ] as const)('maps GitHub %s to %s', async (githubStatus, expectedStatus) => {
+ const fetchMock = vi.fn(async () => response(compareBody(githubStatus)));
+ const { app } = createTestApp({ fetch: fetchMock });
+
+ const result = await httpGet(app, '/api/update/check');
+
+ expect(result.status).toBe(200);
+ expect(result.body).toMatchObject({
+ status: expectedStatus,
+ installation: 'source',
+ localSha: LOCAL_SHA.slice(0, 7),
+ remoteSha: (githubStatus === 'identical' ? LOCAL_SHA : REMOTE_SHA).slice(0, 7),
+ remoteMessage: 'remote commit',
+ remoteDate: '2026-07-28T10:00:00Z',
+ checkedAt: '2026-07-28T14:00:00.000Z',
+ });
+ expect(fetchMock).toHaveBeenCalledWith(
+ `https://api.github.com/repos/tashfeenahmed/freellmapi/compare/${LOCAL_SHA}...main`,
+ expect.any(Object),
+ );
+ });
+
+ it('prefers a validated packaged-build identity and truncates commit messages', async () => {
+ const longMessage = 'x'.repeat(250);
+ const fetchMock = vi.fn(async () => response(compareBody('ahead', longMessage)));
+ const execMock = vi.fn(() => `${REMOTE_SHA}\n`);
+ const { app } = createTestApp({
+ env: {
+ FREELLMAPI_COMMIT_SHA: LOCAL_SHA.toUpperCase(),
+ FREELLMAPI_INSTALL_METHOD: 'docker',
+ },
+ fetch: fetchMock,
+ execFileSync: execMock,
+ });
+
+ const result = await httpGet(app, '/api/update/check');
+
+ expect(result.body.installation).toBe('docker');
+ expect(result.body.remoteMessage).toHaveLength(200);
+ expect(execMock).not.toHaveBeenCalled();
+ });
+
+ it('uses an explicitly configured update-check token for authenticated rate limits', async () => {
+ const fetchMock = vi.fn(async () => response(compareBody('identical')));
+ const { app } = createTestApp({
+ env: { FREELLMAPI_UPDATE_GITHUB_TOKEN: 'test-token' },
+ fetch: fetchMock,
+ });
+
+ await httpGet(app, '/api/update/check');
+
+ expect(fetchMock).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
+ headers: expect.objectContaining({ Authorization: 'Bearer test-token' }),
+ }));
+ });
+
+ it('does not borrow an ambient GitHub token', async () => {
+ const fetchMock = vi.fn(async () => response(compareBody('identical')));
+ const { app } = createTestApp({
+ env: { GITHUB_TOKEN: 'ambient-token' },
+ fetch: fetchMock,
+ });
+
+ await httpGet(app, '/api/update/check');
+
+ const request = fetchMock.mock.calls[0][1];
+ expect(request?.headers).not.toHaveProperty('Authorization');
+ });
+
+ it('reports disabled without resolving Git identity or making a network request', async () => {
+ const fetchMock = vi.fn();
+ const execMock = vi.fn(() => `${LOCAL_SHA}\n`);
+ const { app, logger } = createTestApp({
+ env: { FREELLMAPI_UPDATE_CHECK: ' OFF ' },
+ fetch: fetchMock,
+ execFileSync: execMock,
+ });
+
+ const result = await httpGet(app, '/api/update/check');
+
+ expect(result.status).toBe(200);
+ expect(result.body).toEqual({
+ status: 'disabled',
+ installation: 'unknown',
+ localSha: null,
+ checkedAt: '2026-07-28T14:00:00.000Z',
+ });
+ expect(execMock).not.toHaveBeenCalled();
+ expect(fetchMock).not.toHaveBeenCalled();
+ expect(logger.error).not.toHaveBeenCalled();
+ });
+
+ it('falls back to the public Atom feed when the anonymous API limit is exhausted', async () => {
+ const newestSha = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
+ const middleSha = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
+ const fetchMock = vi.fn()
+ .mockResolvedValueOnce(response({ message: 'API rate limit exceeded' }, 403))
+ .mockResolvedValueOnce(atomResponse([
+ { sha: newestSha, message: 'Newest & safest', date: '2026-07-28T13:00:00Z' },
+ { sha: middleSha, message: 'Middle commit', date: '2026-07-28T12:00:00Z' },
+ { sha: LOCAL_SHA, message: 'Installed commit', date: '2026-07-28T11:00:00Z' },
+ ]));
+ const { app } = createTestApp({ fetch: fetchMock });
+
+ const result = await httpGet(app, '/api/update/check');
+
+ expect(result.status).toBe(200);
+ expect(result.body).toMatchObject({
+ status: 'available',
+ remoteSha: newestSha.slice(0, 7),
+ remoteMessage: 'Newest & safest',
+ remoteDate: '2026-07-28T13:00:00Z',
+ changes: [
+ { sha: newestSha.slice(0, 7), message: 'Newest & safest', date: '2026-07-28T13:00:00Z' },
+ { sha: middleSha.slice(0, 7), message: 'Middle commit', date: '2026-07-28T12:00:00Z' },
+ ],
+ });
+ expect(fetchMock).toHaveBeenNthCalledWith(
+ 2,
+ 'https://github.com/tashfeenahmed/freellmapi/commits/main.atom',
+ expect.any(Object),
+ );
+ });
+
+ it('uses the Atom fallback to recognize the current build', async () => {
+ const fetchMock = vi.fn()
+ .mockResolvedValueOnce(response(undefined, 401))
+ .mockResolvedValueOnce(atomResponse([
+ { sha: LOCAL_SHA, message: 'Current commit', date: '2026-07-28T13:00:00Z' },
+ ]));
+ const { app } = createTestApp({ fetch: fetchMock });
+
+ const result = await httpGet(app, '/api/update/check');
+
+ expect(result.status).toBe(200);
+ expect(result.body.status).toBe('current');
+ expect(result.body.changes).toBeUndefined();
+ });
+
+ it('returns at most eight changes in newest-first order with optional dates', async () => {
+ const commits = Array.from({ length: 10 }, (_, index) => {
+ const number = index + 1;
+ return {
+ sha: number.toString(16).padStart(40, '0'),
+ commit: {
+ message: `subject ${number}\nignored body`,
+ ...(number === 9 ? {} : { committer: { date: `2026-07-${number.toString().padStart(2, '0')}T10:00:00Z` } }),
+ },
+ };
+ });
+ const fetchMock = vi.fn(async () => response({
+ ...compareBody('ahead'),
+ commits,
+ }));
+ const { app } = createTestApp({ fetch: fetchMock });
+
+ const result = await httpGet(app, '/api/update/check');
+
+ expect(result.status).toBe(200);
+ expect(result.body.changes).toHaveLength(8);
+ expect(result.body.changes.map((change: { message: string }) => change.message)).toEqual([
+ 'subject 10',
+ 'subject 9',
+ 'subject 8',
+ 'subject 7',
+ 'subject 6',
+ 'subject 5',
+ 'subject 4',
+ 'subject 3',
+ ]);
+ expect(result.body.changes[0]).toEqual({
+ sha: commits[9].sha.slice(0, 7),
+ message: 'subject 10',
+ date: '2026-07-10T10:00:00Z',
+ });
+ expect(result.body.changes[1]).toEqual({
+ sha: commits[8].sha.slice(0, 7),
+ message: 'subject 9',
+ });
+ });
+
+ it('caps change subjects at 160 characters', async () => {
+ const fetchMock = vi.fn(async () => response(compareBody(
+ 'ahead',
+ `${'x'.repeat(200)}\nignored body`,
+ )));
+ const { app } = createTestApp({ fetch: fetchMock });
+
+ const result = await httpGet(app, '/api/update/check');
+
+ expect(result.status).toBe(200);
+ expect(result.body.changes).toEqual([{
+ sha: REMOTE_SHA.slice(0, 7),
+ message: 'x'.repeat(160),
+ date: '2026-07-28T10:00:00Z',
+ }]);
+ });
+
+ it('rejects malformed commits selected for the changelog', async () => {
+ const validCommit = compareBody('ahead').commits[0];
+ const fetchMock = vi.fn(async () => response({
+ ...compareBody('ahead'),
+ commits: [
+ { sha: LOCAL_SHA, commit: { message: 42 } },
+ validCommit,
+ ],
+ }));
+ const logger = { error: vi.fn() };
+ const { app } = createTestApp({ fetch: fetchMock, logger });
+
+ const result = await httpGet(app, '/api/update/check');
+
+ expect(result.status).toBe(502);
+ expect(result.body).toEqual({
+ error: { message: 'Unable to check for updates', type: 'upstream_error' },
+ });
+ expect(logger.error).toHaveBeenCalledOnce();
+ });
+
+ it('resolves Git identity lazily from the current working directory', async () => {
+ const execMock = vi.fn(() => `${LOCAL_SHA}\n`);
+ const { app } = createTestApp({
+ env: { FREELLMAPI_COMMIT_SHA: 'invalid' },
+ execFileSync: execMock,
+ });
+ expect(execMock).not.toHaveBeenCalled();
+
+ await httpGet(app, '/api/update/status');
+
+ expect(execMock).toHaveBeenCalledWith('git', ['rev-parse', 'HEAD'], {
+ cwd: '/worktree/server',
+ encoding: 'utf8',
+ timeout: 5_000,
+ });
+ });
+
+ it('returns unknown for an unrecognized commit without parsing the 404 body', async () => {
+ const fetchMock = vi.fn(async () => response({ private: 'upstream detail' }, 404));
+ const { app } = createTestApp({ fetch: fetchMock });
+
+ const result = await httpGet(app, '/api/update/check');
+
+ expect(result.status).toBe(200);
+ expect(result.body).toEqual({
+ status: 'unknown',
+ installation: 'source',
+ localSha: LOCAL_SHA.slice(0, 7),
+ checkedAt: '2026-07-28T14:00:00.000Z',
+ });
+ });
+
+ it('returns unsupported without a network request when no identity is available', async () => {
+ const fetchMock = vi.fn();
+ const execMock = vi.fn(() => { throw new Error('not a repository'); });
+ const { app } = createTestApp({ fetch: fetchMock, execFileSync: execMock });
+
+ const result = await httpGet(app, '/api/update/check');
+
+ expect(result.status).toBe(200);
+ expect(result.body).toEqual({
+ status: 'unsupported',
+ installation: 'unknown',
+ localSha: null,
+ checkedAt: '2026-07-28T14:00:00.000Z',
+ });
+ expect(fetchMock).not.toHaveBeenCalled();
+ });
+
+ it('preserves the install method for a self-built Docker image without Git metadata', async () => {
+ const fetchMock = vi.fn();
+ const execMock = vi.fn(() => `${LOCAL_SHA}\n`);
+ const { app } = createTestApp({
+ env: { FREELLMAPI_INSTALL_METHOD: 'docker' },
+ fetch: fetchMock,
+ execFileSync: execMock,
+ });
+
+ const result = await httpGet(app, '/api/update/check');
+
+ expect(result.body).toMatchObject({
+ status: 'unsupported',
+ installation: 'docker',
+ localSha: null,
+ });
+ expect(execMock).not.toHaveBeenCalled();
+ expect(fetchMock).not.toHaveBeenCalled();
+ });
+
+ it.each([
+ ['network failure', vi.fn(async () => { throw new Error('secret network detail'); })],
+ ['non-2xx response', vi.fn(async () => response({ message: 'upstream detail' }, 500))],
+ ['malformed response', vi.fn(async () => response({ status: 'ahead', commits: [{ sha: 'not-a-sha' }] }))],
+ ])('returns a stable 502 for %s and logs details', async (_name, fetchMock) => {
+ const logger = { error: vi.fn() };
+ const { app } = createTestApp({ fetch: fetchMock, logger });
+
+ const result = await httpGet(app, '/api/update/check');
+
+ expect(result.status).toBe(502);
+ expect(result.body).toEqual({
+ error: { message: 'Unable to check for updates', type: 'upstream_error' },
+ });
+ expect(JSON.stringify(result.body)).not.toMatch(/secret|upstream detail|not-a-sha/);
+ expect(logger.error).toHaveBeenCalledOnce();
+ });
+
+ it('caches successful semantic results for five minutes but not errors', async () => {
+ let currentTime = NOW;
+ const fetchMock = vi.fn()
+ .mockResolvedValueOnce(response(compareBody('ahead')))
+ .mockRejectedValueOnce(new Error('temporary failure'))
+ .mockResolvedValueOnce(response(compareBody('identical')));
+ const { app } = createTestApp({ fetch: fetchMock, now: () => currentTime });
+
+ expect((await httpGet(app, '/api/update/check')).body.status).toBe('available');
+ currentTime += 299_999;
+ expect((await httpGet(app, '/api/update/check')).body.status).toBe('available');
+ expect(fetchMock).toHaveBeenCalledTimes(1);
+
+ currentTime += 1;
+ expect((await httpGet(app, '/api/update/check')).status).toBe(502);
+ expect((await httpGet(app, '/api/update/check')).body.status).toBe('current');
+ expect(fetchMock).toHaveBeenCalledTimes(3);
+ });
+
+ it('coalesces concurrent in-flight checks', async () => {
+ let resolveFetch!: (value: Response) => void;
+ const fetchMock = vi.fn(() => new Promise((resolve) => { resolveFetch = resolve; }));
+ const { app } = createTestApp({ fetch: fetchMock });
+
+ const first = httpGet(app, '/api/update/check');
+ const second = httpGet(app, '/api/update/check');
+ await vi.waitFor(() => expect(fetchMock).toHaveBeenCalledOnce());
+ resolveFetch(response(compareBody('ahead')));
+
+ expect((await first).body.status).toBe('available');
+ expect((await second).body.status).toBe('available');
+ expect(fetchMock).toHaveBeenCalledOnce();
+ });
+ });
+
+ describe('GET /api/update/status', () => {
+ it('reports disabled without resolving Git identity or making a network request', async () => {
+ const fetchMock = vi.fn();
+ const execMock = vi.fn(() => `${LOCAL_SHA}\n`);
+ const { app } = createTestApp({
+ env: { FREELLMAPI_UPDATE_CHECK: 'off' },
+ fetch: fetchMock,
+ execFileSync: execMock,
+ });
+
+ expect((await httpGet(app, '/api/update/status')).body).toEqual({
+ status: 'disabled',
+ installation: 'unknown',
+ localSha: null,
+ lastChecked: null,
+ });
+ expect(execMock).not.toHaveBeenCalled();
+ expect(fetchMock).not.toHaveBeenCalled();
+ });
+
+ it('returns idle before a supported installation has checked', async () => {
+ const { app } = createTestApp();
+
+ expect((await httpGet(app, '/api/update/status')).body).toEqual({
+ status: 'idle',
+ installation: 'source',
+ localSha: LOCAL_SHA.slice(0, 7),
+ lastChecked: null,
+ });
+ });
+
+ it('returns unsupported for an unknown installation', async () => {
+ const { app } = createTestApp({ execFileSync: vi.fn(() => 'invalid') });
+
+ expect((await httpGet(app, '/api/update/status')).body).toEqual({
+ status: 'unsupported',
+ installation: 'unknown',
+ localSha: null,
+ lastChecked: null,
+ });
+ });
+
+ it('returns the cached semantic state and last checked time without fetching', async () => {
+ const fetchMock = vi.fn(async () => response(compareBody('diverged')));
+ const { app } = createTestApp({ fetch: fetchMock });
+ await httpGet(app, '/api/update/check');
+
+ expect((await httpGet(app, '/api/update/status')).body).toEqual({
+ status: 'diverged',
+ installation: 'source',
+ localSha: LOCAL_SHA.slice(0, 7),
+ lastChecked: '2026-07-28T14:00:00.000Z',
+ });
+ expect(fetchMock).toHaveBeenCalledOnce();
+ });
+ });
+});
diff --git a/server/src/app.ts b/server/src/app.ts
index c48cbaf38..0e425fb8b 100644
--- a/server/src/app.ts
+++ b/server/src/app.ts
@@ -26,6 +26,7 @@ import { statusRouter, providersRouter } from './routes/status.js';
import { geminiRouter } from './routes/gemini.js';
import { ollamaRouter } from './routes/ollama.js';
import { urlTokenRouter } from './routes/url-tokens.js';
+import { updateRouter } from './routes/update.js';
import { requireAuth } from './middleware/requireAuth.js';
import { createProxyRateLimiter } from './middleware/rateLimit.js';
import { errorHandler } from './middleware/errorHandler.js';
@@ -114,6 +115,7 @@ export function createApp(config?: Config) {
app.use('/api/premium', requireAuth, premiumRouter);
app.use('/api/cache', requireAuth, cacheRouter);
app.use('/api/compression', requireAuth, compressionRouter);
+ app.use('/api/update', requireAuth, updateRouter);
// Static, unauthenticated API reference: GET /v1/docs (viewer) and
// GET /v1/openapi.json (spec). Mounted before the rate limiter so the docs
diff --git a/server/src/routes/update.ts b/server/src/routes/update.ts
new file mode 100644
index 000000000..ece79dc76
--- /dev/null
+++ b/server/src/routes/update.ts
@@ -0,0 +1,416 @@
+import { execFileSync as nodeExecFileSync } from 'node:child_process';
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+
+const REPOSITORY = 'tashfeenahmed/freellmapi';
+const CACHE_TTL_MS = 5 * 60 * 1000;
+const SHA_PATTERN = /^[0-9a-f]{40}$/i;
+const COMPARE_STATUSES = ['identical', 'ahead', 'behind', 'diverged'] as const;
+const MAX_CHANGES = 8;
+const MAX_CHANGE_MESSAGE_LENGTH = 160;
+const MAX_ATOM_FEED_LENGTH = 1_000_000;
+
+type Installation = 'source' | 'docker' | 'desktop' | 'unknown';
+type CheckStatus = 'current' | 'available' | 'ahead' | 'diverged' | 'unknown' | 'unsupported' | 'disabled';
+type CompareStatus = (typeof COMPARE_STATUSES)[number];
+
+interface Identity {
+ sha: string | null;
+ installation: Installation;
+}
+
+interface CheckResult {
+ status: CheckStatus;
+ installation: Installation;
+ localSha: string | null;
+ checkedAt: string;
+ remoteSha?: string;
+ remoteMessage?: string;
+ remoteDate?: string;
+ changes?: Change[];
+}
+
+interface Change {
+ sha: string;
+ message: string;
+ date?: string;
+}
+
+interface CachedResult {
+ result: CheckResult;
+ cachedAt: number;
+}
+
+type ExecFileSync = (
+ file: string,
+ args: string[],
+ options: { cwd: string; encoding: 'utf8'; timeout: number },
+) => string | Buffer;
+
+export interface UpdateRouterOptions {
+ fetch?: typeof globalThis.fetch;
+ execFileSync?: ExecFileSync;
+ env?: NodeJS.ProcessEnv;
+ cwd?: string;
+ now?: () => number;
+ logger?: Pick;
+}
+
+function isRecord(value: unknown): value is Record {
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
+}
+
+function validSha(value: unknown): string | null {
+ return typeof value === 'string' && SHA_PATTERN.test(value.trim())
+ ? value.trim().toLowerCase()
+ : null;
+}
+
+function compareStatus(value: unknown): CompareStatus | null {
+ return typeof value === 'string' && (COMPARE_STATUSES as readonly string[]).includes(value)
+ ? value as CompareStatus
+ : null;
+}
+
+function validDate(value: unknown): value is string {
+ return typeof value === 'string' && value.length <= 64 && !Number.isNaN(Date.parse(value));
+}
+
+function mapCompareStatus(status: CompareStatus): Exclude {
+ switch (status) {
+ case 'identical': return 'current';
+ case 'ahead': return 'available';
+ case 'behind': return 'ahead';
+ case 'diverged': return 'diverged';
+ }
+}
+
+function remoteCommit(body: Record, status: CompareStatus): Record | null {
+ if (!Array.isArray(body.commits)) {
+ throw new Error('GitHub compare response has no commits array');
+ }
+
+ const lastCommit = body.commits.at(-1);
+ const candidate = lastCommit
+ ?? (status === 'behind' ? body.merge_base_commit : body.base_commit);
+
+ if (candidate === undefined || candidate === null) return null;
+ if (!isRecord(candidate)) throw new Error('GitHub compare response has an invalid commit');
+ return candidate;
+}
+
+function parseRemoteMetadata(
+ body: Record,
+ status: CompareStatus,
+ localSha: string,
+): Pick {
+ const candidate = remoteCommit(body, status);
+ if (!candidate) {
+ return status === 'identical' ? { remoteSha: localSha.slice(0, 7) } : {};
+ }
+
+ const sha = validSha(candidate.sha);
+ if (!sha) throw new Error('GitHub compare response has an invalid commit SHA');
+
+ const metadata: Pick = {
+ remoteSha: sha.slice(0, 7),
+ };
+ if (candidate.commit === undefined || candidate.commit === null) return metadata;
+ if (!isRecord(candidate.commit)) throw new Error('GitHub compare response has invalid commit metadata');
+
+ if (candidate.commit.message !== undefined) {
+ if (typeof candidate.commit.message !== 'string') {
+ throw new Error('GitHub compare response has an invalid commit message');
+ }
+ metadata.remoteMessage = candidate.commit.message.slice(0, 200);
+ }
+
+ const committer = candidate.commit.committer;
+ if (committer !== undefined && committer !== null) {
+ if (!isRecord(committer)) throw new Error('GitHub compare response has an invalid committer');
+ if (committer.date !== undefined && committer.date !== null) {
+ if (!validDate(committer.date)) {
+ throw new Error('GitHub compare response has an invalid commit date');
+ }
+ metadata.remoteDate = committer.date;
+ }
+ }
+
+ return metadata;
+}
+
+function parseChanges(body: Record, status: CompareStatus): Change[] | undefined {
+ if (status !== 'ahead') return undefined;
+ if (!Array.isArray(body.commits)) {
+ throw new Error('GitHub compare response has no commits array');
+ }
+
+ return body.commits.slice(-MAX_CHANGES).reverse().map((candidate: unknown) => {
+ if (!isRecord(candidate)) throw new Error('GitHub compare response has an invalid commit');
+ const sha = validSha(candidate.sha);
+ if (!sha) throw new Error('GitHub compare response has an invalid commit SHA');
+ if (!isRecord(candidate.commit)) {
+ throw new Error('GitHub compare response has invalid commit metadata');
+ }
+ if (typeof candidate.commit.message !== 'string') {
+ throw new Error('GitHub compare response has an invalid commit message');
+ }
+
+ const change: Change = {
+ sha: sha.slice(0, 7),
+ message: candidate.commit.message
+ .slice(0, MAX_CHANGE_MESSAGE_LENGTH)
+ .split(/[\r\n]/, 1)[0],
+ };
+ const committer = candidate.commit.committer;
+ if (committer !== undefined && committer !== null) {
+ if (!isRecord(committer)) throw new Error('GitHub compare response has an invalid committer');
+ if (committer.date !== undefined && committer.date !== null) {
+ if (!validDate(committer.date)) {
+ throw new Error('GitHub compare response has an invalid commit date');
+ }
+ change.date = committer.date;
+ }
+ }
+ return change;
+ });
+}
+
+function decodeXmlText(value: string): string {
+ const named: Record = {
+ amp: '&',
+ apos: "'",
+ gt: '>',
+ lt: '<',
+ quot: '"',
+ };
+ return value.replace(/&(?:#(\d+)|#x([0-9a-f]+)|(amp|apos|gt|lt|quot));/gi, (entity, decimal, hex, name) => {
+ if (decimal) return String.fromCodePoint(Number.parseInt(decimal, 10));
+ if (hex) return String.fromCodePoint(Number.parseInt(hex, 16));
+ return named[String(name).toLowerCase()] ?? entity;
+ });
+}
+
+function parseAtomFallback(
+ xml: string,
+ localSha: string,
+ baseResult: Pick,
+): CheckResult {
+ if (xml.length > MAX_ATOM_FEED_LENGTH) throw new Error('GitHub Atom feed is too large');
+
+ const commits: Array = [];
+ for (const match of xml.matchAll(/([\s\S]*?)<\/entry>/gi)) {
+ const entry = match[1];
+ const sha = entry.match(/[^<]*Commit\/([0-9a-f]{40})<\/id>/i)?.[1]?.toLowerCase();
+ const title = entry.match(/\s*([\s\S]*?)\s*<\/title>/i)?.[1];
+ const updated = entry.match(/\s*([^<]+)\s*<\/updated>/i)?.[1]?.trim();
+ if (!sha || title === undefined || (updated !== undefined && !validDate(updated))) {
+ throw new Error('GitHub Atom feed has an invalid commit');
+ }
+
+ commits.push({
+ fullSha: sha,
+ sha: sha.slice(0, 7),
+ message: decodeXmlText(title).replace(/\s+/g, ' ').trim().slice(0, MAX_CHANGE_MESSAGE_LENGTH),
+ ...(updated ? { date: updated } : {}),
+ });
+ }
+
+ if (commits.length === 0 || commits[0].message.length === 0) {
+ throw new Error('GitHub Atom feed has no commits');
+ }
+
+ const latest = commits[0];
+ const localIndex = commits.findIndex(commit => commit.fullSha === localSha);
+ const status: CheckStatus = localIndex === 0
+ ? 'current'
+ : localIndex > 0
+ ? 'available'
+ : 'unknown';
+
+ return {
+ status,
+ ...baseResult,
+ remoteSha: latest.sha,
+ remoteMessage: latest.message,
+ ...(latest.date ? { remoteDate: latest.date } : {}),
+ ...(status === 'available'
+ ? { changes: commits.slice(0, localIndex).slice(0, MAX_CHANGES).map(({ fullSha: _fullSha, ...change }) => change) }
+ : {}),
+ };
+}
+
+export function createUpdateRouter(options: UpdateRouterOptions = {}): Router {
+ const router = Router();
+ const env = options.env ?? process.env;
+ const fetchImpl = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
+ const execFile = options.execFileSync ?? ((file, args, execOptions) => (
+ nodeExecFileSync(file, args, execOptions)
+ ));
+ const now = options.now ?? Date.now;
+ const logger = options.logger ?? console;
+ const updateCheckDisabled = env.FREELLMAPI_UPDATE_CHECK?.trim().toLowerCase() === 'off';
+ const githubToken = env.FREELLMAPI_UPDATE_GITHUB_TOKEN?.trim();
+
+ let identity: Identity | undefined;
+ let cache: CachedResult | null = null;
+ let inFlight: Promise | null = null;
+
+ function resolveIdentity(): Identity {
+ if (identity) return identity;
+
+ const environmentSha = validSha(env.FREELLMAPI_COMMIT_SHA);
+ const installMethod = env.FREELLMAPI_INSTALL_METHOD;
+ if (installMethod === 'docker' || installMethod === 'desktop') {
+ identity = { sha: environmentSha, installation: installMethod };
+ return identity;
+ }
+
+ try {
+ const output = execFile('git', ['rev-parse', 'HEAD'], {
+ cwd: options.cwd ?? process.cwd(),
+ encoding: 'utf8',
+ timeout: 5_000,
+ });
+ const gitSha = validSha(output.toString());
+ if (gitSha) {
+ identity = { sha: gitSha, installation: 'source' };
+ return identity;
+ }
+ } catch {
+ // A packaged or custom build may not have Git metadata.
+ }
+
+ identity = { sha: null, installation: 'unknown' };
+ return identity;
+ }
+
+ async function performCheck(currentIdentity: Identity): Promise {
+ const checkedAtMs = now();
+ const baseResult = {
+ installation: currentIdentity.installation,
+ localSha: currentIdentity.sha!.slice(0, 7),
+ checkedAt: new Date(checkedAtMs).toISOString(),
+ };
+ const url = `https://api.github.com/repos/${REPOSITORY}/compare/${currentIdentity.sha}...main`;
+ const response = await fetchImpl(url, {
+ headers: {
+ Accept: 'application/vnd.github+json',
+ 'User-Agent': 'freellmapi-update-checker',
+ 'X-GitHub-Api-Version': '2022-11-28',
+ ...(githubToken ? { Authorization: `Bearer ${githubToken}` } : {}),
+ },
+ signal: AbortSignal.timeout(10_000),
+ });
+
+ if (response.status === 404) {
+ return { status: 'unknown', ...baseResult };
+ }
+ if (response.status === 401 || response.status === 403 || response.status === 429) {
+ const atomResponse = await fetchImpl(`https://github.com/${REPOSITORY}/commits/main.atom`, {
+ headers: {
+ Accept: 'application/atom+xml',
+ 'User-Agent': 'freellmapi-update-checker',
+ },
+ signal: AbortSignal.timeout(10_000),
+ });
+ if (!atomResponse.ok) {
+ throw new Error(`GitHub Atom request returned HTTP ${atomResponse.status}`);
+ }
+ return parseAtomFallback(await atomResponse.text(), currentIdentity.sha!, baseResult);
+ }
+ if (!response.ok) {
+ throw new Error(`GitHub compare request returned HTTP ${response.status}`);
+ }
+
+ const body: unknown = await response.json();
+ if (!isRecord(body)) throw new Error('GitHub compare response is not an object');
+ const upstreamStatus = compareStatus(body.status);
+ if (!upstreamStatus) throw new Error('GitHub compare response has an invalid status');
+
+ return {
+ status: mapCompareStatus(upstreamStatus),
+ ...baseResult,
+ ...parseRemoteMetadata(body, upstreamStatus, currentIdentity.sha!),
+ ...(upstreamStatus === 'ahead' ? { changes: parseChanges(body, upstreamStatus) } : {}),
+ };
+ }
+
+ function check(currentIdentity: Identity): Promise {
+ const currentTime = now();
+ if (cache && currentTime - cache.cachedAt < CACHE_TTL_MS) {
+ return Promise.resolve(cache.result);
+ }
+ if (inFlight) return inFlight;
+
+ const request = performCheck(currentIdentity)
+ .then((result) => {
+ cache = { result, cachedAt: now() };
+ return result;
+ })
+ .catch((error: unknown) => {
+ logger.error('[update] GitHub compare check failed', error);
+ throw error;
+ })
+ .finally(() => {
+ if (inFlight === request) inFlight = null;
+ });
+ inFlight = request;
+ return request;
+ }
+
+ router.get('/check', async (_req: Request, res: Response) => {
+ if (updateCheckDisabled) {
+ return res.json({
+ status: 'disabled',
+ installation: 'unknown',
+ localSha: null,
+ checkedAt: new Date(now()).toISOString(),
+ } satisfies CheckResult);
+ }
+
+ const currentIdentity = resolveIdentity();
+ if (!currentIdentity.sha) {
+ return res.json({
+ status: 'unsupported',
+ installation: currentIdentity.installation,
+ localSha: null,
+ checkedAt: new Date(now()).toISOString(),
+ } satisfies CheckResult);
+ }
+
+ try {
+ return res.json(await check(currentIdentity));
+ } catch {
+ return res.status(502).json({
+ error: {
+ message: 'Unable to check for updates',
+ type: 'upstream_error',
+ },
+ });
+ }
+ });
+
+ router.get('/status', (_req: Request, res: Response) => {
+ if (updateCheckDisabled) {
+ return res.json({
+ status: 'disabled',
+ installation: 'unknown',
+ localSha: null,
+ lastChecked: null,
+ });
+ }
+
+ const currentIdentity = resolveIdentity();
+ res.json({
+ status: currentIdentity.sha ? (cache?.result.status ?? 'idle') : 'unsupported',
+ installation: currentIdentity.installation,
+ localSha: currentIdentity.sha?.slice(0, 7) ?? null,
+ lastChecked: cache?.result.checkedAt ?? null,
+ });
+ });
+
+ return router;
+}
+
+export const updateRouter = createUpdateRouter();