diff --git a/apps/desktop-ui/messages/af.json b/apps/desktop-ui/messages/af.json index dcf0428c..60159dfe 100644 --- a/apps/desktop-ui/messages/af.json +++ b/apps/desktop-ui/messages/af.json @@ -1931,7 +1931,13 @@ "serviceAccountInvalidJson": "Dit is nie geldige JSON nie.", "serviceAccountNotServiceAccount": "Hierdie JSON is nie 'n diensrekeningsleutel nie (tipe \"service_account\" met project_id en client_email word verwag).", "serviceAccountBadKey": "Die private_key-veld ontbreek of is nie 'n PKCS#8 PEM-sleutel nie.", - "databaseIdInvalid": "Databasis-ID moet 4–63 kleinletters, syfers of koppeltekens wees, of (default)." + "databaseIdInvalid": "Databasis-ID moet 4–63 kleinletters, syfers of koppeltekens wees, of (default).", + "esUrlRequired": "Voer 'n kluster-URL in.", + "esUrlScheme": "Kluster-URL moet begin met http:// of https://.", + "esUrlInvalid": "Dit is nie 'n geldige URL nie.", + "esUsernameRequired": "Voer 'n gebruikersnaam in.", + "esApiKeyRequired": "Voer 'n API-sleutel in.", + "esBearerRequired": "Voer 'n draertoken in." }, "firestore": { "serviceAccount": "Diensrekeningsleutel (JSON)", @@ -2064,6 +2070,62 @@ "bulkDropped": "{count} versamelings laat val", "bulkDropFailed": "Kon nie {count} versamelings laat val nie" } + }, + "elasticsearch": { + "clusterUrl": "Kluster-URL", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Die kluster moet 'n sertifikaat aanbied wat hierdie toestel reeds vertrou — selfondertekende sertifikate (die Elasticsearch https-standaard) word nie ondersteun nie.", + "auth": "Verifikasie", + "authMode": { + "none": "Geen", + "basic": "Gebruikersnaam en wagwoord", + "apiKey": "API-sleutel", + "bearer": "Draertoken" + }, + "username": "Gebruikersnaam", + "password": "Wagwoord", + "apiKey": "API-sleutel (base64)", + "apiKeyHint": "Die base64 id:api_key wat deur die _security/api_key-API uitgereik word.", + "bearerToken": "Draertoken", + "noIndices": "Geen indekse", + "noMatches": "Geen resultate nie", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Wysig die Query DSL hieronder.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Voer uit", + "newDocument": "Nuwe dokument", + "noHits": "Geen ooreenstemmende dokumente nie", + "hitCount": "{count, plural, =0 {Geen treffers} one {# treffer} other {# treffers}}", + "hitCountTotal": "{count} van {total, plural, one {# treffer} other {# treffers}}", + "prevPage": "Vorige", + "nextPage": "Volgende", + "selectDoc": "Kies 'n dokument om dit te bekyk.", + "edit": "Wysig", + "save": "Stoor", + "cancel": "Kanselleer", + "create": "Skep", + "docIdLabel": "Dokument-ID (opsioneel)", + "docIdAutoHint": "Laat leeg om Elasticsearch 'n ID te laat toewys.", + "deleteDocTitle": "Vee dokument uit", + "deleteDocBody": "Vee dokument \"{id}\" permanent uit? Dit kan nie ongedaan gemaak word nie.", + "errAuth": "Verifikasie het misluk. Kontroleer jou geloofsbriewe.", + "errForbidden": "Hierdie gebruiker word nie toegelaat om daardie aksie uit te voer nie.", + "errNotFound": "Die indeks of dokument is nie gevind nie.", + "errBadQuery": "Die navraag kon nie ontleed word nie. Kontroleer die sintaksis.", + "errConflict": "Die dokument is deur 'n ander skryfbewerking verander. Verfris en probeer weer.", + "errNetwork": "Kon nie die kluster bereik nie. Kontroleer die URL en dat dit loop.", + "errDocNotObject": "'n Dokument moet 'n JSON-objek wees.", + "errInvalidDocJson": "Dit is nie geldige JSON nie.", + "toast": { + "docCreated": "Dokument geskep", + "docUpdated": "Dokument gestoor", + "docDeleted": "Dokument uitgevee", + "createFailed": "Kon nie skep nie: {message}", + "saveFailed": "Kon nie stoor nie: {message}", + "deleteFailed": "Kon nie uitvee nie: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/ar.json b/apps/desktop-ui/messages/ar.json index 8b75bc11..36667400 100644 --- a/apps/desktop-ui/messages/ar.json +++ b/apps/desktop-ui/messages/ar.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "هذا ليس JSON صالحًا.", "serviceAccountNotServiceAccount": "هذا JSON ليس مفتاح حساب خدمة (يُتوقع النوع \"service_account\" مع project_id وclient_email).", "serviceAccountBadKey": "حقل private_key مفقود أو ليس مفتاح PEM بتنسيق PKCS#8.", - "databaseIdInvalid": "يجب أن يتكون معرّف قاعدة البيانات من 4–63 حرفًا صغيرًا أو رقمًا أو شرطة، أو أن يكون (default)." + "databaseIdInvalid": "يجب أن يتكون معرّف قاعدة البيانات من 4–63 حرفًا صغيرًا أو رقمًا أو شرطة، أو أن يكون (default).", + "esUrlRequired": "أدخل عنوان URL للعنقود.", + "esUrlScheme": "يجب أن يبدأ عنوان URL للعنقود بـ http:// أو https://.", + "esUrlInvalid": "هذا ليس عنوان URL صالحًا.", + "esUsernameRequired": "أدخل اسم المستخدم.", + "esApiKeyRequired": "أدخل مفتاح API.", + "esBearerRequired": "أدخل رمز Bearer." }, "firestore": { "serviceAccount": "مفتاح حساب الخدمة (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "تم حذف {count} مجموعة", "bulkDropFailed": "تعذّر حذف {count} مجموعة" } + }, + "elasticsearch": { + "clusterUrl": "عنوان URL للعنقود", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "يجب أن يقدّم العنقود شهادة يثق بها هذا الجهاز بالفعل — الشهادات الموقّعة ذاتيًا (الوضع الافتراضي لـ https في Elasticsearch) غير مدعومة.", + "auth": "المصادقة", + "authMode": { + "none": "بدون", + "basic": "اسم المستخدم وكلمة المرور", + "apiKey": "مفتاح API", + "bearer": "رمز Bearer" + }, + "username": "اسم المستخدم", + "password": "كلمة المرور", + "apiKey": "مفتاح API (base64)", + "apiKeyHint": "معرّف id:api_key بترميز base64 الصادر من واجهة _security/api_key.", + "bearerToken": "رمز Bearer", + "noIndices": "لا توجد فهارس", + "noMatches": "لا توجد نتائج مطابقة", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "عدّل Query DSL أدناه.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "تشغيل", + "newDocument": "مستند جديد", + "noHits": "لا توجد مستندات مطابقة", + "hitCount": "{count, plural, =0 {لا نتائج} zero {# نتيجة} one {# نتيجة} two {# نتيجتان} few {# نتائج} many {# نتيجةً} other {# نتيجة}}", + "hitCountTotal": "{count} من {total, plural, zero {# نتيجة} one {# نتيجة} two {# نتيجتان} few {# نتائج} many {# نتيجةً} other {# نتيجة}}", + "prevPage": "السابق", + "nextPage": "التالي", + "selectDoc": "اختر مستندًا لعرضه.", + "edit": "تعديل", + "save": "حفظ", + "cancel": "إلغاء", + "create": "إنشاء", + "docIdLabel": "معرّف المستند (اختياري)", + "docIdAutoHint": "اتركه فارغًا ليعيّن Elasticsearch معرّفًا.", + "deleteDocTitle": "حذف المستند؟", + "deleteDocBody": "حذف المستند \"{id}\" نهائيًا؟ لا يمكن التراجع عن هذا الإجراء.", + "errAuth": "فشلت المصادقة. تحقق من بيانات الاعتماد.", + "errForbidden": "لا يُسمح لهذا المستخدم بتنفيذ هذا الإجراء.", + "errNotFound": "لم يُعثر على الفهرس أو المستند.", + "errBadQuery": "تعذّر تحليل الاستعلام. تحقق من الصياغة.", + "errConflict": "تم تغيير المستند بواسطة عملية كتابة أخرى. حدّث وأعد المحاولة.", + "errNetwork": "تعذّر الوصول إلى العنقود. تحقق من عنوان URL ومن أنه قيد التشغيل.", + "errDocNotObject": "يجب أن يكون المستند كائن JSON.", + "errInvalidDocJson": "هذا ليس JSON صالحًا.", + "toast": { + "docCreated": "تم إنشاء المستند", + "docUpdated": "تم حفظ المستند", + "docDeleted": "تم حذف المستند", + "createFailed": "فشل الإنشاء: {message}", + "saveFailed": "فشل الحفظ: {message}", + "deleteFailed": "فشل الحذف: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/ca.json b/apps/desktop-ui/messages/ca.json index 1e076e99..4c435dcb 100644 --- a/apps/desktop-ui/messages/ca.json +++ b/apps/desktop-ui/messages/ca.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "Això no és JSON vàlid.", "serviceAccountNotServiceAccount": "Aquest JSON no és una clau de compte de servei (s'esperava el tipus \"service_account\" amb project_id i client_email).", "serviceAccountBadKey": "Falta el camp private_key o no és una clau PEM PKCS#8.", - "databaseIdInvalid": "L'ID de la base de dades ha de tenir entre 4 i 63 lletres minúscules, dígits o guionets, o ser (default)." + "databaseIdInvalid": "L'ID de la base de dades ha de tenir entre 4 i 63 lletres minúscules, dígits o guionets, o ser (default).", + "esUrlRequired": "Introdueix una URL del clúster.", + "esUrlScheme": "La URL del clúster ha de començar amb http:// o https://.", + "esUrlInvalid": "Això no és una URL vàlida.", + "esUsernameRequired": "Introdueix un nom d'usuari.", + "esApiKeyRequired": "Introdueix una clau API.", + "esBearerRequired": "Introdueix un token de portador." }, "firestore": { "serviceAccount": "Clau de compte de servei (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "{count} col·leccions eliminades", "bulkDropFailed": "No s'han pogut eliminar {count} col·leccions" } + }, + "elasticsearch": { + "clusterUrl": "URL del clúster", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "El clúster ha de presentar un certificat en què aquest dispositiu ja confiï — els certificats autofirmats (el valor per defecte d'https d'Elasticsearch) no s'admeten.", + "auth": "Autenticació", + "authMode": { + "none": "Cap", + "basic": "Nom d'usuari i contrasenya", + "apiKey": "Clau API", + "bearer": "Token de portador" + }, + "username": "Nom d'usuari", + "password": "Contrasenya", + "apiKey": "Clau API (base64)", + "apiKeyHint": "El base64 id:api_key emès per l'API _security/api_key.", + "bearerToken": "Token de portador", + "noIndices": "Sense índexs", + "noMatches": "Sense coincidències", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Edita la Query DSL a sota.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Executa", + "newDocument": "Document nou", + "noHits": "No hi ha documents coincidents", + "hitCount": "{count, plural, =0 {Cap resultat} one {# resultat} other {# resultats}}", + "hitCountTotal": "{count} de {total, plural, one {# resultat} other {# resultats}}", + "prevPage": "Anterior", + "nextPage": "Següent", + "selectDoc": "Tria un document per veure'l.", + "edit": "Edita", + "save": "Desa", + "cancel": "Cancel·la", + "create": "Crea", + "docIdLabel": "ID del document (opcional)", + "docIdAutoHint": "Deixa-ho buit perquè Elasticsearch assigni un ID.", + "deleteDocTitle": "Elimina el document", + "deleteDocBody": "Vols eliminar permanentment el document \"{id}\"? Aquesta acció no es pot desfer.", + "errAuth": "Ha fallat l'autenticació. Comprova les teves credencials.", + "errForbidden": "Aquest usuari no té permís per fer aquesta acció.", + "errNotFound": "No s'ha trobat l'índex o el document.", + "errBadQuery": "No s'ha pogut analitzar la consulta. Comprova la sintaxi.", + "errConflict": "El document ha estat modificat per una altra escriptura. Actualitza i torna-ho a provar.", + "errNetwork": "No s'ha pogut connectar amb el clúster. Comprova la URL i que estigui en execució.", + "errDocNotObject": "Un document ha de ser un objecte JSON.", + "errInvalidDocJson": "Això no és JSON vàlid.", + "toast": { + "docCreated": "Document creat", + "docUpdated": "Document desat", + "docDeleted": "Document eliminat", + "createFailed": "Error en crear: {message}", + "saveFailed": "Error en desar: {message}", + "deleteFailed": "Error en eliminar: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/cs.json b/apps/desktop-ui/messages/cs.json index c5396233..3372d13d 100644 --- a/apps/desktop-ui/messages/cs.json +++ b/apps/desktop-ui/messages/cs.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "Toto není platný JSON.", "serviceAccountNotServiceAccount": "Tento JSON není klíčem servisního účtu (očekávaný typ \"service_account\" s project_id a client_email).", "serviceAccountBadKey": "Pole private_key chybí nebo není klíčem PKCS#8 PEM.", - "databaseIdInvalid": "Database ID musí obsahovat 4–63 malých písmen, číslic nebo pomlček, nebo být (default)." + "databaseIdInvalid": "Database ID musí obsahovat 4–63 malých písmen, číslic nebo pomlček, nebo být (default).", + "esUrlRequired": "Zadejte URL clusteru.", + "esUrlScheme": "URL clusteru musí začínat http:// nebo https://.", + "esUrlInvalid": "Toto není platná URL.", + "esUsernameRequired": "Zadejte uživatelské jméno.", + "esApiKeyRequired": "Zadejte API klíč.", + "esBearerRequired": "Zadejte bearer token." }, "firestore": { "serviceAccount": "Klíč servisního účtu (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "Zahozeno {count} kolekcí", "bulkDropFailed": "Nepodařilo se zahodit {count} kolekcí" } + }, + "elasticsearch": { + "clusterUrl": "URL clusteru", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Cluster musí předložit certifikát, kterému toto zařízení již důvěřuje — samopodepsané certifikáty (výchozí nastavení https v Elasticsearchu) nejsou podporovány.", + "auth": "Ověření", + "authMode": { + "none": "Žádné", + "basic": "Uživatelské jméno a heslo", + "apiKey": "API klíč", + "bearer": "Bearer token" + }, + "username": "Uživatelské jméno", + "password": "Heslo", + "apiKey": "API klíč (base64)", + "apiKeyHint": "base64 řetězec id:api_key vydaný rozhraním API _security/api_key.", + "bearerToken": "Bearer token", + "noIndices": "Žádné indexy", + "noMatches": "Žádné shody", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Upravte Query DSL níže.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Spustit", + "newDocument": "Nový dokument", + "noHits": "Žádné odpovídající dokumenty", + "hitCount": "{count, plural, =0 {Žádné výsledky} one {# výsledek} few {# výsledky} other {# výsledků}}", + "hitCountTotal": "{count} z {total, plural, one {# výsledek} few {# výsledky} other {# výsledků}}", + "prevPage": "Předchozí", + "nextPage": "Další", + "selectDoc": "Vyberte dokument k zobrazení.", + "edit": "Upravit", + "save": "Uložit", + "cancel": "Zrušit", + "create": "Vytvořit", + "docIdLabel": "ID dokumentu (volitelné)", + "docIdAutoHint": "Ponechte prázdné, aby Elasticsearch přiřadil ID.", + "deleteDocTitle": "Smazat dokument", + "deleteDocBody": "Trvale smazat dokument „{id}“? Tuto akci nelze vrátit zpět.", + "errAuth": "Ověření se nezdařilo. Zkontrolujte přihlašovací údaje.", + "errForbidden": "Tento uživatel nemá oprávnění provést tuto akci.", + "errNotFound": "Index nebo dokument nebyl nalezen.", + "errBadQuery": "Dotaz se nepodařilo zpracovat. Zkontrolujte syntaxi.", + "errConflict": "Dokument byl změněn jiným zápisem. Obnovte a zkuste to znovu.", + "errNetwork": "Nepodařilo se připojit ke clusteru. Zkontrolujte URL a zda běží.", + "errDocNotObject": "Dokument musí být objekt JSON.", + "errInvalidDocJson": "Toto není platný JSON.", + "toast": { + "docCreated": "Dokument vytvořen", + "docUpdated": "Dokument uložen", + "docDeleted": "Dokument smazán", + "createFailed": "Vytvoření se nezdařilo: {message}", + "saveFailed": "Uložení se nezdařilo: {message}", + "deleteFailed": "Smazání se nezdařilo: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/da.json b/apps/desktop-ui/messages/da.json index 5cf883a6..8d77201b 100644 --- a/apps/desktop-ui/messages/da.json +++ b/apps/desktop-ui/messages/da.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "Dette er ikke gyldig JSON.", "serviceAccountNotServiceAccount": "Denne JSON er ikke en tjenestekontonøgle (forventer typen \"service_account\" med project_id og client_email).", "serviceAccountBadKey": "Feltet private_key mangler eller er ikke en PKCS#8 PEM-nøgle.", - "databaseIdInvalid": "Database-ID skal være 4–63 små bogstaver, cifre eller bindestreger, eller (default)." + "databaseIdInvalid": "Database-ID skal være 4–63 små bogstaver, cifre eller bindestreger, eller (default).", + "esUrlRequired": "Indtast en klynge-URL.", + "esUrlScheme": "Klynge-URL skal starte med http:// eller https://.", + "esUrlInvalid": "Dette er ikke en gyldig URL.", + "esUsernameRequired": "Indtast et brugernavn.", + "esApiKeyRequired": "Indtast en API-nøgle.", + "esBearerRequired": "Indtast et bearer-token." }, "firestore": { "serviceAccount": "Tjenestekontonøgle (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "{count} samlinger droppet", "bulkDropFailed": "Kunne ikke droppe {count} samlinger" } + }, + "elasticsearch": { + "clusterUrl": "Klynge-URL", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Klyngen skal fremvise et certifikat, som denne enhed allerede har tillid til — selvsignerede certifikater (Elasticsearch https-standarden) understøttes ikke.", + "auth": "Godkendelse", + "authMode": { + "none": "Ingen", + "basic": "Brugernavn og adgangskode", + "apiKey": "API-nøgle", + "bearer": "Bearer-token" + }, + "username": "Brugernavn", + "password": "Adgangskode", + "apiKey": "API-nøgle (base64)", + "apiKeyHint": "Den base64 id:api_key, der udstedes af _security/api_key-API'et.", + "bearerToken": "Bearer-token", + "noIndices": "Ingen indekser", + "noMatches": "Ingen match", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Rediger Query DSL nedenfor.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Kør", + "newDocument": "Nyt dokument", + "noHits": "Ingen matchende dokumenter", + "hitCount": "{count, plural, =0 {Ingen hits} one {# hit} other {# hits}}", + "hitCountTotal": "{count} af {total, plural, one {# hit} other {# hits}}", + "prevPage": "Forrige", + "nextPage": "Næste", + "selectDoc": "Vælg et dokument for at se det.", + "edit": "Rediger", + "save": "Gem", + "cancel": "Annuller", + "create": "Opret", + "docIdLabel": "Dokument-ID (valgfrit)", + "docIdAutoHint": "Lad stå tom for at lade Elasticsearch tildele et ID.", + "deleteDocTitle": "Slet dokument", + "deleteDocBody": "Vil du slette dokumentet \"{id}\" permanent? Dette kan ikke fortrydes.", + "errAuth": "Godkendelse mislykkedes. Tjek dine legitimationsoplysninger.", + "errForbidden": "Denne bruger har ikke tilladelse til at udføre den handling.", + "errNotFound": "Indekset eller dokumentet blev ikke fundet.", + "errBadQuery": "Forespørgslen kunne ikke fortolkes. Tjek syntaksen.", + "errConflict": "Dokumentet blev ændret af en anden skrivning. Opdater, og prøv igen.", + "errNetwork": "Kunne ikke nå klyngen. Tjek URL'en, og at den kører.", + "errDocNotObject": "Et dokument skal være et JSON-objekt.", + "errInvalidDocJson": "Dette er ikke gyldig JSON.", + "toast": { + "docCreated": "Dokument oprettet", + "docUpdated": "Dokument gemt", + "docDeleted": "Dokument slettet", + "createFailed": "Oprettelse mislykkedes: {message}", + "saveFailed": "Kunne ikke gemme: {message}", + "deleteFailed": "Kunne ikke slette: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/de.json b/apps/desktop-ui/messages/de.json index ae9f08e1..7ccc5fc9 100644 --- a/apps/desktop-ui/messages/de.json +++ b/apps/desktop-ui/messages/de.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "Dies ist kein gültiges JSON.", "serviceAccountNotServiceAccount": "Dieses JSON ist kein Dienstkonto-Schlüssel (erwartet wird der Typ \"service_account\" mit project_id und client_email).", "serviceAccountBadKey": "Das Feld private_key fehlt oder ist kein PKCS#8-PEM-Schlüssel.", - "databaseIdInvalid": "Die Datenbank-ID muss 4–63 Kleinbuchstaben, Ziffern oder Bindestriche enthalten, oder (default) sein." + "databaseIdInvalid": "Die Datenbank-ID muss 4–63 Kleinbuchstaben, Ziffern oder Bindestriche enthalten, oder (default) sein.", + "esUrlRequired": "Geben Sie eine Cluster-URL ein.", + "esUrlScheme": "Die Cluster-URL muss mit http:// oder https:// beginnen.", + "esUrlInvalid": "Dies ist keine gültige URL.", + "esUsernameRequired": "Geben Sie einen Benutzernamen ein.", + "esApiKeyRequired": "Geben Sie einen API-Schlüssel ein.", + "esBearerRequired": "Geben Sie ein Bearer-Token ein." }, "firestore": { "serviceAccount": "Dienstkonto-Schlüssel (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "{count} Sammlungen gelöscht", "bulkDropFailed": "{count} Sammlungen konnten nicht gelöscht werden" } + }, + "elasticsearch": { + "clusterUrl": "Cluster-URL", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Der Cluster muss ein Zertifikat vorweisen, dem dieses Gerät bereits vertraut — selbstsignierte Zertifikate (die https-Standardeinstellung von Elasticsearch) werden nicht unterstützt.", + "auth": "Authentifizierung", + "authMode": { + "none": "Keine", + "basic": "Benutzername und Passwort", + "apiKey": "API-Schlüssel", + "bearer": "Bearer-Token" + }, + "username": "Benutzername", + "password": "Passwort", + "apiKey": "API-Schlüssel (base64)", + "apiKeyHint": "Der base64 id:api_key, der von der _security/api_key-API ausgestellt wird.", + "bearerToken": "Bearer-Token", + "noIndices": "Keine Indizes", + "noMatches": "Keine Treffer", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Bearbeiten Sie die Query DSL unten.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Ausführen", + "newDocument": "Neues Dokument", + "noHits": "Keine übereinstimmenden Dokumente", + "hitCount": "{count, plural, =0 {Keine Treffer} one {# Treffer} other {# Treffer}}", + "hitCountTotal": "{count} von {total, plural, one {# Treffer} other {# Treffer}}", + "prevPage": "Zurück", + "nextPage": "Weiter", + "selectDoc": "Wählen Sie ein Dokument aus, um es anzuzeigen.", + "edit": "Bearbeiten", + "save": "Speichern", + "cancel": "Abbrechen", + "create": "Erstellen", + "docIdLabel": "Dokument-ID (optional)", + "docIdAutoHint": "Leer lassen, damit Elasticsearch eine ID zuweist.", + "deleteDocTitle": "Dokument löschen", + "deleteDocBody": "Dokument \"{id}\" endgültig löschen? Dies kann nicht rückgängig gemacht werden.", + "errAuth": "Authentifizierung fehlgeschlagen. Überprüfen Sie Ihre Anmeldedaten.", + "errForbidden": "Dieser Benutzer darf diese Aktion nicht ausführen.", + "errNotFound": "Der Index oder das Dokument wurde nicht gefunden.", + "errBadQuery": "Die Abfrage konnte nicht geparst werden. Überprüfen Sie die Syntax.", + "errConflict": "Das Dokument wurde durch einen anderen Schreibvorgang geändert. Aktualisieren Sie und versuchen Sie es erneut.", + "errNetwork": "Der Cluster konnte nicht erreicht werden. Überprüfen Sie die URL und ob er läuft.", + "errDocNotObject": "Ein Dokument muss ein JSON-Objekt sein.", + "errInvalidDocJson": "Dies ist kein gültiges JSON.", + "toast": { + "docCreated": "Dokument erstellt", + "docUpdated": "Dokument gespeichert", + "docDeleted": "Dokument gelöscht", + "createFailed": "Erstellen fehlgeschlagen: {message}", + "saveFailed": "Speichern fehlgeschlagen: {message}", + "deleteFailed": "Löschen fehlgeschlagen: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/el.json b/apps/desktop-ui/messages/el.json index f703773d..ca30b687 100644 --- a/apps/desktop-ui/messages/el.json +++ b/apps/desktop-ui/messages/el.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "Αυτό δεν είναι έγκυρο JSON.", "serviceAccountNotServiceAccount": "Αυτό το JSON δεν είναι κλειδί λογαριασμού υπηρεσίας (αναμενόμενος τύπος \"service_account\" με project_id και client_email).", "serviceAccountBadKey": "Το πεδίο private_key λείπει ή δεν είναι κλειδί PKCS#8 PEM.", - "databaseIdInvalid": "Το Database ID πρέπει να έχει 4–63 πεζά γράμματα, ψηφία ή παύλες, ή να είναι (default)." + "databaseIdInvalid": "Το Database ID πρέπει να έχει 4–63 πεζά γράμματα, ψηφία ή παύλες, ή να είναι (default).", + "esUrlRequired": "Εισαγάγετε ένα URL συμπλέγματος.", + "esUrlScheme": "Το URL συμπλέγματος πρέπει να ξεκινά με http:// ή https://.", + "esUrlInvalid": "Αυτό δεν είναι έγκυρο URL.", + "esUsernameRequired": "Εισαγάγετε ένα όνομα χρήστη.", + "esApiKeyRequired": "Εισαγάγετε ένα κλειδί API.", + "esBearerRequired": "Εισαγάγετε ένα διακριτικό bearer." }, "firestore": { "serviceAccount": "Κλειδί λογαριασμού υπηρεσίας (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "{count} συλλογές απορρίφθηκαν", "bulkDropFailed": "Δεν ήταν δυνατή η απόρριψη {count} συλλογών" } + }, + "elasticsearch": { + "clusterUrl": "URL συμπλέγματος", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Το σύμπλεγμα πρέπει να παρουσιάζει ένα πιστοποιητικό που αυτή η συσκευή ήδη εμπιστεύεται — τα αυτο-υπογεγραμμένα πιστοποιητικά (η προεπιλογή https του Elasticsearch) δεν υποστηρίζονται.", + "auth": "Έλεγχος ταυτότητας", + "authMode": { + "none": "Κανένα", + "basic": "Όνομα χρήστη και κωδικός πρόσβασης", + "apiKey": "Κλειδί API", + "bearer": "Διακριτικό bearer" + }, + "username": "Όνομα χρήστη", + "password": "Κωδικός πρόσβασης", + "apiKey": "Κλειδί API (base64)", + "apiKeyHint": "Το base64 id:api_key που εκδίδεται από το API _security/api_key.", + "bearerToken": "Διακριτικό bearer", + "noIndices": "Χωρίς ευρετήρια", + "noMatches": "Καμία αντιστοίχιση", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Επεξεργαστείτε το Query DSL παρακάτω.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Εκτέλεση", + "newDocument": "Νέο έγγραφο", + "noHits": "Δεν υπάρχουν έγγραφα που να ταιριάζουν", + "hitCount": "{count, plural, =0 {Κανένα αποτέλεσμα} one {# αποτέλεσμα} other {# αποτελέσματα}}", + "hitCountTotal": "{count} από {total, plural, one {# αποτέλεσμα} other {# αποτελέσματα}}", + "prevPage": "Προηγούμενο", + "nextPage": "Επόμενο", + "selectDoc": "Επιλέξτε ένα έγγραφο για να το προβάλετε.", + "edit": "Επεξεργασία", + "save": "Αποθήκευση", + "cancel": "Ακύρωση", + "create": "Δημιουργία", + "docIdLabel": "ID εγγράφου (προαιρετικό)", + "docIdAutoHint": "Αφήστε το κενό για να αναθέσει το Elasticsearch ένα ID.", + "deleteDocTitle": "Διαγραφή εγγράφου", + "deleteDocBody": "Μόνιμη διαγραφή του εγγράφου \"{id}\"; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.", + "errAuth": "Ο έλεγχος ταυτότητας απέτυχε. Ελέγξτε τα διαπιστευτήριά σας.", + "errForbidden": "Αυτός ο χρήστης δεν επιτρέπεται να εκτελέσει αυτήν την ενέργεια.", + "errNotFound": "Το ευρετήριο ή το έγγραφο δεν βρέθηκε.", + "errBadQuery": "Δεν ήταν δυνατή η ανάλυση του ερωτήματος. Ελέγξτε τη σύνταξη.", + "errConflict": "Το έγγραφο τροποποιήθηκε από άλλη εγγραφή. Ανανεώστε και δοκιμάστε ξανά.", + "errNetwork": "Δεν ήταν δυνατή η προσέγγιση του συμπλέγματος. Ελέγξτε το URL και ότι εκτελείται.", + "errDocNotObject": "Ένα έγγραφο πρέπει να είναι αντικείμενο JSON.", + "errInvalidDocJson": "Αυτό δεν είναι έγκυρο JSON.", + "toast": { + "docCreated": "Το έγγραφο δημιουργήθηκε", + "docUpdated": "Το έγγραφο αποθηκεύτηκε", + "docDeleted": "Το έγγραφο διαγράφηκε", + "createFailed": "Η δημιουργία απέτυχε: {message}", + "saveFailed": "Η αποθήκευση απέτυχε: {message}", + "deleteFailed": "Η διαγραφή απέτυχε: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/en.json b/apps/desktop-ui/messages/en.json index 6a95c895..f14e891d 100644 --- a/apps/desktop-ui/messages/en.json +++ b/apps/desktop-ui/messages/en.json @@ -1946,7 +1946,13 @@ "serviceAccountInvalidJson": "This is not valid JSON.", "serviceAccountNotServiceAccount": "This JSON is not a service account key (expected type \"service_account\" with project_id and client_email).", "serviceAccountBadKey": "The private_key field is missing or not a PKCS#8 PEM key.", - "databaseIdInvalid": "Database ID must be 4–63 lowercase letters, digits or hyphens, or (default)." + "databaseIdInvalid": "Database ID must be 4–63 lowercase letters, digits or hyphens, or (default).", + "esUrlRequired": "Enter a cluster URL.", + "esUrlScheme": "Cluster URL must start with http:// or https://.", + "esUrlInvalid": "This is not a valid URL.", + "esUsernameRequired": "Enter a username.", + "esApiKeyRequired": "Enter an API key.", + "esBearerRequired": "Enter a bearer token." }, "firestore": { "serviceAccount": "Service account key (JSON)", @@ -2079,6 +2085,62 @@ "bulkDropped": "Dropped {count} collections", "bulkDropFailed": "Could not drop {count} collections" } + }, + "elasticsearch": { + "clusterUrl": "Cluster URL", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "The cluster must present a certificate this device already trusts — self-signed certs (the Elasticsearch https default) are not supported.", + "auth": "Authentication", + "authMode": { + "none": "None", + "basic": "Username & password", + "apiKey": "API key", + "bearer": "Bearer token" + }, + "username": "Username", + "password": "Password", + "apiKey": "API key (base64)", + "apiKeyHint": "The base64 id:api_key issued by the _security/api_key API.", + "bearerToken": "Bearer token", + "noIndices": "No indices", + "noMatches": "No matches", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Edit the Query DSL below.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Run", + "newDocument": "New document", + "noHits": "No matching documents", + "hitCount": "{count, plural, =0 {No hits} one {# hit} other {# hits}}", + "hitCountTotal": "{count} of {total, plural, one {# hit} other {# hits}}", + "prevPage": "Prev", + "nextPage": "Next", + "selectDoc": "Select a document to view it.", + "edit": "Edit", + "save": "Save", + "cancel": "Cancel", + "create": "Create", + "docIdLabel": "Document ID (optional)", + "docIdAutoHint": "Leave blank to let Elasticsearch assign an ID.", + "deleteDocTitle": "Delete document", + "deleteDocBody": "Permanently delete document \"{id}\"? This cannot be undone.", + "errAuth": "Authentication failed. Check your credentials.", + "errForbidden": "This user is not allowed to perform that action.", + "errNotFound": "The index or document was not found.", + "errBadQuery": "The query could not be parsed. Check the syntax.", + "errConflict": "The document was changed by another write. Refresh and retry.", + "errNetwork": "Could not reach the cluster. Check the URL and that it is running.", + "errDocNotObject": "A document must be a JSON object.", + "errInvalidDocJson": "This is not valid JSON.", + "toast": { + "docCreated": "Document created", + "docUpdated": "Document saved", + "docDeleted": "Document deleted", + "createFailed": "Create failed: {message}", + "saveFailed": "Save failed: {message}", + "deleteFailed": "Delete failed: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/es.json b/apps/desktop-ui/messages/es.json index bef84327..05f01406 100644 --- a/apps/desktop-ui/messages/es.json +++ b/apps/desktop-ui/messages/es.json @@ -1931,7 +1931,13 @@ "serviceAccountInvalidJson": "Esto no es JSON válido.", "serviceAccountNotServiceAccount": "Este JSON no es una clave de cuenta de servicio (se esperaba el tipo \"service_account\" con project_id y client_email).", "serviceAccountBadKey": "Falta el campo private_key o no es una clave PEM PKCS#8.", - "databaseIdInvalid": "El ID de la base de datos debe tener entre 4 y 63 letras minúsculas, dígitos o guiones, o ser (default)." + "databaseIdInvalid": "El ID de la base de datos debe tener entre 4 y 63 letras minúsculas, dígitos o guiones, o ser (default).", + "esUrlRequired": "Introduce una URL del clúster.", + "esUrlScheme": "La URL del clúster debe empezar con http:// o https://.", + "esUrlInvalid": "Esto no es una URL válida.", + "esUsernameRequired": "Introduce un nombre de usuario.", + "esApiKeyRequired": "Introduce una clave API.", + "esBearerRequired": "Introduce un token de portador." }, "firestore": { "serviceAccount": "Clave de cuenta de servicio (JSON)", @@ -2064,6 +2070,62 @@ "bulkDropped": "{count} colecciones eliminadas", "bulkDropFailed": "No se pudieron eliminar {count} colecciones" } + }, + "elasticsearch": { + "clusterUrl": "URL del clúster", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "El clúster debe presentar un certificado en el que este dispositivo ya confíe — los certificados autofirmados (el valor predeterminado de https de Elasticsearch) no son compatibles.", + "auth": "Autenticación", + "authMode": { + "none": "Ninguna", + "basic": "Nombre de usuario y contraseña", + "apiKey": "Clave API", + "bearer": "Token de portador" + }, + "username": "Nombre de usuario", + "password": "Contraseña", + "apiKey": "Clave API (base64)", + "apiKeyHint": "El base64 id:api_key emitido por la API _security/api_key.", + "bearerToken": "Token de portador", + "noIndices": "Sin índices", + "noMatches": "Sin coincidencias", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Edita la Query DSL a continuación.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Ejecutar", + "newDocument": "Nuevo documento", + "noHits": "No hay documentos coincidentes", + "hitCount": "{count, plural, =0 {Sin resultados} one {# resultado} other {# resultados}}", + "hitCountTotal": "{count} de {total, plural, one {# resultado} other {# resultados}}", + "prevPage": "Anterior", + "nextPage": "Siguiente", + "selectDoc": "Selecciona un documento para verlo.", + "edit": "Editar", + "save": "Guardar", + "cancel": "Cancelar", + "create": "Crear", + "docIdLabel": "ID del documento (opcional)", + "docIdAutoHint": "Déjalo vacío para que Elasticsearch asigne un ID.", + "deleteDocTitle": "Eliminar documento", + "deleteDocBody": "¿Eliminar permanentemente el documento \"{id}\"? Esta acción no se puede deshacer.", + "errAuth": "Error de autenticación. Comprueba tus credenciales.", + "errForbidden": "Este usuario no tiene permiso para realizar esa acción.", + "errNotFound": "No se encontró el índice o el documento.", + "errBadQuery": "No se pudo analizar la consulta. Comprueba la sintaxis.", + "errConflict": "El documento fue modificado por otra escritura. Actualiza e inténtalo de nuevo.", + "errNetwork": "No se pudo conectar con el clúster. Comprueba la URL y que esté en ejecución.", + "errDocNotObject": "Un documento debe ser un objeto JSON.", + "errInvalidDocJson": "Esto no es JSON válido.", + "toast": { + "docCreated": "Documento creado", + "docUpdated": "Documento guardado", + "docDeleted": "Documento eliminado", + "createFailed": "Error al crear: {message}", + "saveFailed": "Error al guardar: {message}", + "deleteFailed": "Error al eliminar: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/fa.json b/apps/desktop-ui/messages/fa.json index adc05921..2a2b90f4 100644 --- a/apps/desktop-ui/messages/fa.json +++ b/apps/desktop-ui/messages/fa.json @@ -1931,7 +1931,13 @@ "serviceAccountInvalidJson": "این یک JSON معتبر نیست.", "serviceAccountNotServiceAccount": "این JSON یک کلید حساب سرویس نیست (نوع \"service_account\" همراه با project_id و client_email مورد نیاز است).", "serviceAccountBadKey": "فیلد private_key وجود ندارد یا یک کلید PEM با فرمت PKCS#8 نیست.", - "databaseIdInvalid": "شناسه پایگاه داده باید ۴ تا ۶۳ حرف کوچک، رقم یا خط تیره باشد، یا (default) باشد." + "databaseIdInvalid": "شناسه پایگاه داده باید ۴ تا ۶۳ حرف کوچک، رقم یا خط تیره باشد، یا (default) باشد.", + "esUrlRequired": "یک URL خوشه وارد کنید.", + "esUrlScheme": "URL خوشه باید با http:// یا https:// شروع شود.", + "esUrlInvalid": "این یک URL معتبر نیست.", + "esUsernameRequired": "یک نام کاربری وارد کنید.", + "esApiKeyRequired": "یک کلید API وارد کنید.", + "esBearerRequired": "یک توکن Bearer وارد کنید." }, "firestore": { "serviceAccount": "کلید حساب سرویس (JSON)", @@ -2064,6 +2070,62 @@ "bulkDropped": "{count} مجموعه رها شد", "bulkDropFailed": "رها کردن {count} مجموعه ناموفق بود" } + }, + "elasticsearch": { + "clusterUrl": "URL خوشه", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "خوشه باید گواهی‌ای ارائه دهد که این دستگاه از قبل به آن اعتماد دارد — گواهی‌های خودامضا (پیش‌فرض https در Elasticsearch) پشتیبانی نمی‌شوند.", + "auth": "احراز هویت", + "authMode": { + "none": "هیچ‌کدام", + "basic": "نام کاربری و رمز عبور", + "apiKey": "کلید API", + "bearer": "توکن Bearer" + }, + "username": "نام کاربری", + "password": "رمز عبور", + "apiKey": "کلید API (base64)", + "apiKeyHint": "شناسه id:api_key با کدگذاری base64 صادرشده توسط API مربوط به _security/api_key.", + "bearerToken": "توکن Bearer", + "noIndices": "ایندکسی وجود ندارد", + "noMatches": "موردی یافت نشد", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Query DSL را در پایین ویرایش کنید.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "اجرا", + "newDocument": "سند جدید", + "noHits": "سند مطابقی وجود ندارد", + "hitCount": "{count, plural, =0 {نتیجه‌ای نیست} one {# نتیجه} other {# نتیجه}}", + "hitCountTotal": "{count} از {total, plural, one {# نتیجه} other {# نتیجه}}", + "prevPage": "قبلی", + "nextPage": "بعدی", + "selectDoc": "برای مشاهده، یک سند انتخاب کنید.", + "edit": "ویرایش", + "save": "ذخیره", + "cancel": "لغو", + "create": "ایجاد", + "docIdLabel": "شناسه سند (اختیاری)", + "docIdAutoHint": "برای اینکه Elasticsearch یک شناسه اختصاص دهد، خالی بگذارید.", + "deleteDocTitle": "سند حذف شود؟", + "deleteDocBody": "سند \"{id}\" برای همیشه حذف شود؟ این کار قابل بازگشت نیست.", + "errAuth": "احراز هویت ناموفق بود. اعتبارنامه‌های خود را بررسی کنید.", + "errForbidden": "این کاربر مجاز به انجام این عمل نیست.", + "errNotFound": "ایندکس یا سند یافت نشد.", + "errBadQuery": "پرس‌وجو قابل تجزیه نبود. نحو را بررسی کنید.", + "errConflict": "سند توسط نوشتن دیگری تغییر کرده است. تازه‌سازی کنید و دوباره امتحان کنید.", + "errNetwork": "دسترسی به خوشه ممکن نشد. URL و در حال اجرا بودن آن را بررسی کنید.", + "errDocNotObject": "سند باید یک شیء JSON باشد.", + "errInvalidDocJson": "این یک JSON معتبر نیست.", + "toast": { + "docCreated": "سند ایجاد شد", + "docUpdated": "سند ذخیره شد", + "docDeleted": "سند حذف شد", + "createFailed": "ایجاد ناموفق بود: {message}", + "saveFailed": "ذخیره ناموفق بود: {message}", + "deleteFailed": "حذف ناموفق بود: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/fr.json b/apps/desktop-ui/messages/fr.json index 9c45a00e..7de268d4 100644 --- a/apps/desktop-ui/messages/fr.json +++ b/apps/desktop-ui/messages/fr.json @@ -1931,7 +1931,13 @@ "serviceAccountInvalidJson": "Ceci n'est pas un JSON valide.", "serviceAccountNotServiceAccount": "Ce JSON n'est pas une clé de compte de service (le type \"service_account\" avec project_id et client_email est attendu).", "serviceAccountBadKey": "Le champ private_key est manquant ou n'est pas une clé PEM PKCS#8.", - "databaseIdInvalid": "L'ID de la base de données doit comporter entre 4 et 63 lettres minuscules, chiffres ou tirets, ou être (default)." + "databaseIdInvalid": "L'ID de la base de données doit comporter entre 4 et 63 lettres minuscules, chiffres ou tirets, ou être (default).", + "esUrlRequired": "Saisissez une URL de cluster.", + "esUrlScheme": "L'URL du cluster doit commencer par http:// ou https://.", + "esUrlInvalid": "Ceci n'est pas une URL valide.", + "esUsernameRequired": "Saisissez un nom d'utilisateur.", + "esApiKeyRequired": "Saisissez une clé API.", + "esBearerRequired": "Saisissez un jeton bearer." }, "firestore": { "serviceAccount": "Clé de compte de service (JSON)", @@ -2064,6 +2070,62 @@ "bulkDropped": "{count} collections supprimées", "bulkDropFailed": "Impossible de supprimer {count} collections" } + }, + "elasticsearch": { + "clusterUrl": "URL du cluster", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Le cluster doit présenter un certificat déjà approuvé par cet appareil — les certificats auto-signés (le défaut https d'Elasticsearch) ne sont pas pris en charge.", + "auth": "Authentification", + "authMode": { + "none": "Aucune", + "basic": "Nom d'utilisateur et mot de passe", + "apiKey": "Clé API", + "bearer": "Jeton bearer" + }, + "username": "Nom d'utilisateur", + "password": "Mot de passe", + "apiKey": "Clé API (base64)", + "apiKeyHint": "L'identifiant id:api_key en base64 émis par l'API _security/api_key.", + "bearerToken": "Jeton bearer", + "noIndices": "Aucun index", + "noMatches": "Aucune correspondance", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Modifiez le Query DSL ci-dessous.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Exécuter", + "newDocument": "Nouveau document", + "noHits": "Aucun document correspondant", + "hitCount": "{count, plural, =0 {Aucun résultat} one {# résultat} other {# résultats}}", + "hitCountTotal": "{count} sur {total, plural, one {# résultat} other {# résultats}}", + "prevPage": "Précédent", + "nextPage": "Suivant", + "selectDoc": "Sélectionnez un document pour l'afficher.", + "edit": "Modifier", + "save": "Enregistrer", + "cancel": "Annuler", + "create": "Créer", + "docIdLabel": "ID du document (facultatif)", + "docIdAutoHint": "Laissez vide pour qu'Elasticsearch attribue un ID.", + "deleteDocTitle": "Supprimer le document", + "deleteDocBody": "Supprimer définitivement le document « {id} » ? Cette action est irréversible.", + "errAuth": "Échec de l'authentification. Vérifiez vos identifiants.", + "errForbidden": "Cet utilisateur n'est pas autorisé à effectuer cette action.", + "errNotFound": "L'index ou le document est introuvable.", + "errBadQuery": "La requête n'a pas pu être analysée. Vérifiez la syntaxe.", + "errConflict": "Le document a été modifié par une autre écriture. Actualisez et réessayez.", + "errNetwork": "Impossible de joindre le cluster. Vérifiez l'URL et qu'il est en cours d'exécution.", + "errDocNotObject": "Un document doit être un objet JSON.", + "errInvalidDocJson": "Ceci n'est pas un JSON valide.", + "toast": { + "docCreated": "Document créé", + "docUpdated": "Document enregistré", + "docDeleted": "Document supprimé", + "createFailed": "Échec de la création : {message}", + "saveFailed": "Échec de l'enregistrement : {message}", + "deleteFailed": "Échec de la suppression : {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/id.json b/apps/desktop-ui/messages/id.json index d2bf16cf..020c1999 100644 --- a/apps/desktop-ui/messages/id.json +++ b/apps/desktop-ui/messages/id.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "Ini bukan JSON yang valid.", "serviceAccountNotServiceAccount": "JSON ini bukan kunci akun layanan (harus bertipe \"service_account\" dengan project_id dan client_email).", "serviceAccountBadKey": "Kolom private_key tidak ada atau bukan kunci PEM PKCS#8.", - "databaseIdInvalid": "ID database harus terdiri dari 4–63 huruf kecil, angka, atau tanda hubung, atau (default)." + "databaseIdInvalid": "ID database harus terdiri dari 4–63 huruf kecil, angka, atau tanda hubung, atau (default).", + "esUrlRequired": "Masukkan URL cluster.", + "esUrlScheme": "URL cluster harus dimulai dengan http:// atau https://.", + "esUrlInvalid": "Ini bukan URL yang valid.", + "esUsernameRequired": "Masukkan nama pengguna.", + "esApiKeyRequired": "Masukkan kunci API.", + "esBearerRequired": "Masukkan token bearer." }, "firestore": { "serviceAccount": "Kunci akun layanan (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "{count} koleksi dihapus", "bulkDropFailed": "Gagal menghapus {count} koleksi" } + }, + "elasticsearch": { + "clusterUrl": "URL cluster", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Cluster harus menyajikan sertifikat yang sudah dipercaya perangkat ini — sertifikat yang ditandatangani sendiri (default https Elasticsearch) tidak didukung.", + "auth": "Autentikasi", + "authMode": { + "none": "Tidak ada", + "basic": "Nama pengguna & kata sandi", + "apiKey": "Kunci API", + "bearer": "Token bearer" + }, + "username": "Nama pengguna", + "password": "Kata sandi", + "apiKey": "Kunci API (base64)", + "apiKeyHint": "id:api_key base64 yang diterbitkan oleh API _security/api_key.", + "bearerToken": "Token bearer", + "noIndices": "Tidak ada indeks", + "noMatches": "Tidak ada yang cocok", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Edit Query DSL di bawah.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Jalankan", + "newDocument": "Dokumen baru", + "noHits": "Tidak ada dokumen yang cocok", + "hitCount": "{count, plural, =0 {Tidak ada hasil} other {# hasil}}", + "hitCountTotal": "{count} dari {total, plural, other {# hasil}}", + "prevPage": "Sebelumnya", + "nextPage": "Berikutnya", + "selectDoc": "Pilih dokumen untuk melihatnya.", + "edit": "Edit", + "save": "Simpan", + "cancel": "Batal", + "create": "Buat", + "docIdLabel": "ID dokumen (opsional)", + "docIdAutoHint": "Biarkan kosong agar Elasticsearch menetapkan ID.", + "deleteDocTitle": "Hapus dokumen", + "deleteDocBody": "Hapus permanen dokumen \"{id}\"? Ini tidak dapat dibatalkan.", + "errAuth": "Autentikasi gagal. Periksa kredensial Anda.", + "errForbidden": "Pengguna ini tidak diizinkan melakukan tindakan tersebut.", + "errNotFound": "Indeks atau dokumen tidak ditemukan.", + "errBadQuery": "Kueri tidak dapat diurai. Periksa sintaksnya.", + "errConflict": "Dokumen diubah oleh penulisan lain. Segarkan dan coba lagi.", + "errNetwork": "Tidak dapat menjangkau cluster. Periksa URL dan pastikan cluster berjalan.", + "errDocNotObject": "Dokumen harus berupa objek JSON.", + "errInvalidDocJson": "Ini bukan JSON yang valid.", + "toast": { + "docCreated": "Dokumen dibuat", + "docUpdated": "Dokumen disimpan", + "docDeleted": "Dokumen dihapus", + "createFailed": "Gagal membuat: {message}", + "saveFailed": "Gagal menyimpan: {message}", + "deleteFailed": "Gagal menghapus: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/it.json b/apps/desktop-ui/messages/it.json index 9bc3c9fe..c15cf9b2 100644 --- a/apps/desktop-ui/messages/it.json +++ b/apps/desktop-ui/messages/it.json @@ -1931,7 +1931,13 @@ "serviceAccountInvalidJson": "Questo non è un JSON valido.", "serviceAccountNotServiceAccount": "Questo JSON non è una chiave di account di servizio (era previsto il tipo \"service_account\" con project_id e client_email).", "serviceAccountBadKey": "Il campo private_key manca oppure non è una chiave PEM PKCS#8.", - "databaseIdInvalid": "L'ID del database deve avere da 4 a 63 lettere minuscole, cifre o trattini, oppure essere (default)." + "databaseIdInvalid": "L'ID del database deve avere da 4 a 63 lettere minuscole, cifre o trattini, oppure essere (default).", + "esUrlRequired": "Inserisci un URL del cluster.", + "esUrlScheme": "L'URL del cluster deve iniziare con http:// o https://.", + "esUrlInvalid": "Questo non è un URL valido.", + "esUsernameRequired": "Inserisci un nome utente.", + "esApiKeyRequired": "Inserisci una chiave API.", + "esBearerRequired": "Inserisci un token bearer." }, "firestore": { "serviceAccount": "Chiave dell'account di servizio (JSON)", @@ -2064,6 +2070,62 @@ "bulkDropped": "{count} raccolte eliminate", "bulkDropFailed": "Impossibile eliminare {count} raccolte" } + }, + "elasticsearch": { + "clusterUrl": "URL del cluster", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Il cluster deve presentare un certificato già attendibile per questo dispositivo — i certificati autofirmati (il valore predefinito https di Elasticsearch) non sono supportati.", + "auth": "Autenticazione", + "authMode": { + "none": "Nessuna", + "basic": "Nome utente e password", + "apiKey": "Chiave API", + "bearer": "Token bearer" + }, + "username": "Nome utente", + "password": "Password", + "apiKey": "Chiave API (base64)", + "apiKeyHint": "L'id:api_key in base64 emesso dall'API _security/api_key.", + "bearerToken": "Token bearer", + "noIndices": "Nessun indice", + "noMatches": "Nessuna corrispondenza", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Modifica il Query DSL qui sotto.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Esegui", + "newDocument": "Nuovo documento", + "noHits": "Nessun documento corrispondente", + "hitCount": "{count, plural, =0 {Nessun risultato} one {# risultato} other {# risultati}}", + "hitCountTotal": "{count} di {total, plural, one {# risultato} other {# risultati}}", + "prevPage": "Precedente", + "nextPage": "Successivo", + "selectDoc": "Seleziona un documento per visualizzarlo.", + "edit": "Modifica", + "save": "Salva", + "cancel": "Annulla", + "create": "Crea", + "docIdLabel": "ID documento (facoltativo)", + "docIdAutoHint": "Lascia vuoto per far assegnare un ID a Elasticsearch.", + "deleteDocTitle": "Elimina documento", + "deleteDocBody": "Eliminare definitivamente il documento \"{id}\"? Questa azione non può essere annullata.", + "errAuth": "Autenticazione non riuscita. Controlla le tue credenziali.", + "errForbidden": "A questo utente non è consentito eseguire quell'azione.", + "errNotFound": "L'indice o il documento non è stato trovato.", + "errBadQuery": "Impossibile analizzare la query. Controlla la sintassi.", + "errConflict": "Il documento è stato modificato da un'altra scrittura. Aggiorna e riprova.", + "errNetwork": "Impossibile raggiungere il cluster. Controlla l'URL e che sia in esecuzione.", + "errDocNotObject": "Un documento deve essere un oggetto JSON.", + "errInvalidDocJson": "Questo non è un JSON valido.", + "toast": { + "docCreated": "Documento creato", + "docUpdated": "Documento salvato", + "docDeleted": "Documento eliminato", + "createFailed": "Creazione non riuscita: {message}", + "saveFailed": "Salvataggio non riuscito: {message}", + "deleteFailed": "Eliminazione non riuscita: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/ja.json b/apps/desktop-ui/messages/ja.json index 6f3b3346..5a7f25c5 100644 --- a/apps/desktop-ui/messages/ja.json +++ b/apps/desktop-ui/messages/ja.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "これは有効なJSONではありません。", "serviceAccountNotServiceAccount": "このJSONはサービスアカウントキーではありません(\"service_account\"タイプでproject_idとclient_emailが必要です)。", "serviceAccountBadKey": "private_keyフィールドがないか、PKCS#8形式のPEMキーではありません。", - "databaseIdInvalid": "データベースIDは4〜63文字の小文字・数字・ハイフン、または(default)である必要があります。" + "databaseIdInvalid": "データベースIDは4〜63文字の小文字・数字・ハイフン、または(default)である必要があります。", + "esUrlRequired": "クラスターのURLを入力してください。", + "esUrlScheme": "クラスターのURLはhttp://またはhttps://で始まる必要があります。", + "esUrlInvalid": "これは有効なURLではありません。", + "esUsernameRequired": "ユーザー名を入力してください。", + "esApiKeyRequired": "APIキーを入力してください。", + "esBearerRequired": "ベアラートークンを入力してください。" }, "firestore": { "serviceAccount": "サービスアカウントキー(JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "{count}件のコレクションを削除しました", "bulkDropFailed": "{count}件のコレクションの削除に失敗しました" } + }, + "elasticsearch": { + "clusterUrl": "クラスターURL", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "クラスターは、このデバイスがすでに信頼している証明書を提示する必要があります。自己署名証明書(Elasticsearchのhttpsのデフォルト)はサポートされていません。", + "auth": "認証", + "authMode": { + "none": "なし", + "basic": "ユーザー名とパスワード", + "apiKey": "APIキー", + "bearer": "ベアラートークン" + }, + "username": "ユーザー名", + "password": "パスワード", + "apiKey": "APIキー(base64)", + "apiKeyHint": "_security/api_key APIによって発行されたbase64のid:api_key。", + "bearerToken": "ベアラートークン", + "noIndices": "インデックスがありません", + "noMatches": "一致するものがありません", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "下のQuery DSLを編集してください。", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "実行", + "newDocument": "新しいドキュメント", + "noHits": "一致するドキュメントがありません", + "hitCount": "{count, plural, =0 {ヒットなし} other {# 件}}", + "hitCountTotal": "{count}/{total, plural, other {# 件}}", + "prevPage": "前へ", + "nextPage": "次へ", + "selectDoc": "表示するドキュメントを選択してください。", + "edit": "編集", + "save": "保存", + "cancel": "キャンセル", + "create": "作成", + "docIdLabel": "ドキュメントID(任意)", + "docIdAutoHint": "空欄のままにすると、ElasticsearchがIDを割り当てます。", + "deleteDocTitle": "ドキュメントを削除", + "deleteDocBody": "ドキュメント「{id}」を完全に削除しますか?この操作は元に戻せません。", + "errAuth": "認証に失敗しました。資格情報を確認してください。", + "errForbidden": "このユーザーはその操作を実行する権限がありません。", + "errNotFound": "インデックスまたはドキュメントが見つかりませんでした。", + "errBadQuery": "クエリを解析できませんでした。構文を確認してください。", + "errConflict": "ドキュメントが別の書き込みによって変更されました。更新して再試行してください。", + "errNetwork": "クラスターに到達できませんでした。URLと、稼働しているかを確認してください。", + "errDocNotObject": "ドキュメントはJSONオブジェクトである必要があります。", + "errInvalidDocJson": "これは有効なJSONではありません。", + "toast": { + "docCreated": "ドキュメントを作成しました", + "docUpdated": "ドキュメントを保存しました", + "docDeleted": "ドキュメントを削除しました", + "createFailed": "作成に失敗しました: {message}", + "saveFailed": "保存に失敗しました: {message}", + "deleteFailed": "削除に失敗しました: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/ko.json b/apps/desktop-ui/messages/ko.json index 5bab3552..f08f2d8f 100644 --- a/apps/desktop-ui/messages/ko.json +++ b/apps/desktop-ui/messages/ko.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "유효한 JSON이 아닙니다.", "serviceAccountNotServiceAccount": "이 JSON은 서비스 계정 키가 아닙니다(\"service_account\" 유형에 project_id와 client_email이 필요합니다).", "serviceAccountBadKey": "private_key 필드가 없거나 PKCS#8 PEM 키가 아닙니다.", - "databaseIdInvalid": "데이터베이스 ID는 4~63자의 소문자, 숫자, 하이픈으로 구성되거나 (default)여야 합니다." + "databaseIdInvalid": "데이터베이스 ID는 4~63자의 소문자, 숫자, 하이픈으로 구성되거나 (default)여야 합니다.", + "esUrlRequired": "클러스터 URL을 입력하세요.", + "esUrlScheme": "클러스터 URL은 http:// 또는 https://로 시작해야 합니다.", + "esUrlInvalid": "유효한 URL이 아닙니다.", + "esUsernameRequired": "사용자 이름을 입력하세요.", + "esApiKeyRequired": "API 키를 입력하세요.", + "esBearerRequired": "베어러 토큰을 입력하세요." }, "firestore": { "serviceAccount": "서비스 계정 키(JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "컬렉션 {count}개 삭제됨", "bulkDropFailed": "컬렉션 {count}개를 삭제하지 못했습니다" } + }, + "elasticsearch": { + "clusterUrl": "클러스터 URL", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "클러스터는 이 기기가 이미 신뢰하는 인증서를 제시해야 합니다 — 자체 서명 인증서(Elasticsearch의 https 기본값)는 지원되지 않습니다.", + "auth": "인증", + "authMode": { + "none": "없음", + "basic": "사용자 이름 및 비밀번호", + "apiKey": "API 키", + "bearer": "베어러 토큰" + }, + "username": "사용자 이름", + "password": "비밀번호", + "apiKey": "API 키 (base64)", + "apiKeyHint": "_security/api_key API에서 발급한 base64 id:api_key입니다.", + "bearerToken": "베어러 토큰", + "noIndices": "인덱스 없음", + "noMatches": "일치하는 항목 없음", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "아래의 Query DSL을 편집하세요.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "실행", + "newDocument": "새 문서", + "noHits": "일치하는 문서 없음", + "hitCount": "{count, plural, =0 {결과 없음} other {# 건}}", + "hitCountTotal": "{total, plural, other {# 건}} 중 {count}", + "prevPage": "이전", + "nextPage": "다음", + "selectDoc": "문서를 선택하여 확인하세요.", + "edit": "수정", + "save": "저장", + "cancel": "취소", + "create": "생성", + "docIdLabel": "문서 ID (선택 사항)", + "docIdAutoHint": "비워 두면 Elasticsearch가 ID를 할당합니다.", + "deleteDocTitle": "문서 삭제", + "deleteDocBody": "문서 \"{id}\"을(를) 영구적으로 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.", + "errAuth": "인증에 실패했습니다. 자격 증명을 확인하세요.", + "errForbidden": "이 사용자는 해당 작업을 수행할 수 없습니다.", + "errNotFound": "인덱스 또는 문서를 찾을 수 없습니다.", + "errBadQuery": "쿼리를 구문 분석할 수 없습니다. 구문을 확인하세요.", + "errConflict": "다른 쓰기 작업으로 문서가 변경되었습니다. 새로 고침 후 다시 시도하세요.", + "errNetwork": "클러스터에 연결할 수 없습니다. URL과 실행 여부를 확인하세요.", + "errDocNotObject": "문서는 JSON 객체여야 합니다.", + "errInvalidDocJson": "유효한 JSON이 아닙니다.", + "toast": { + "docCreated": "문서가 생성되었습니다", + "docUpdated": "문서가 저장되었습니다", + "docDeleted": "문서가 삭제되었습니다", + "createFailed": "생성 실패: {message}", + "saveFailed": "저장 실패: {message}", + "deleteFailed": "삭제 실패: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/ms.json b/apps/desktop-ui/messages/ms.json index 8463bfae..1ce76c34 100644 --- a/apps/desktop-ui/messages/ms.json +++ b/apps/desktop-ui/messages/ms.json @@ -1931,7 +1931,13 @@ "serviceAccountInvalidJson": "Ini bukan JSON yang sah.", "serviceAccountNotServiceAccount": "JSON ini bukan kunci akaun perkhidmatan (jenis \"service_account\" dengan project_id dan client_email diperlukan).", "serviceAccountBadKey": "Medan private_key tiada atau bukan kunci PEM PKCS#8.", - "databaseIdInvalid": "ID pangkalan data mestilah 4–63 huruf kecil, digit atau sengkang, atau (default)." + "databaseIdInvalid": "ID pangkalan data mestilah 4–63 huruf kecil, digit atau sengkang, atau (default).", + "esUrlRequired": "Masukkan URL kluster.", + "esUrlScheme": "URL kluster mesti bermula dengan http:// atau https://.", + "esUrlInvalid": "Ini bukan URL yang sah.", + "esUsernameRequired": "Masukkan nama pengguna.", + "esApiKeyRequired": "Masukkan kunci API.", + "esBearerRequired": "Masukkan token bearer." }, "firestore": { "serviceAccount": "Kunci akaun perkhidmatan (JSON)", @@ -2064,6 +2070,62 @@ "bulkDropped": "{count} koleksi digugurkan", "bulkDropFailed": "Gagal menggugurkan {count} koleksi" } + }, + "elasticsearch": { + "clusterUrl": "URL kluster", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Kluster mesti mengemukakan sijil yang sudah dipercayai peranti ini — sijil tandatangan sendiri (lalai https Elasticsearch) tidak disokong.", + "auth": "Pengesahan", + "authMode": { + "none": "Tiada", + "basic": "Nama pengguna & kata laluan", + "apiKey": "Kunci API", + "bearer": "Token bearer" + }, + "username": "Nama pengguna", + "password": "Kata laluan", + "apiKey": "Kunci API (base64)", + "apiKeyHint": "id:api_key base64 yang dikeluarkan oleh API _security/api_key.", + "bearerToken": "Token bearer", + "noIndices": "Tiada indeks", + "noMatches": "Tiada padanan", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Edit Query DSL di bawah.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Jalankan", + "newDocument": "Dokumen baharu", + "noHits": "Tiada dokumen yang sepadan", + "hitCount": "{count, plural, =0 {Tiada padanan} other {# padanan}}", + "hitCountTotal": "{count} daripada {total, plural, other {# padanan}}", + "prevPage": "Sebelum", + "nextPage": "Seterusnya", + "selectDoc": "Pilih dokumen untuk melihatnya.", + "edit": "Edit", + "save": "Simpan", + "cancel": "Batal", + "create": "Cipta", + "docIdLabel": "ID dokumen (pilihan)", + "docIdAutoHint": "Biarkan kosong untuk membiarkan Elasticsearch menetapkan ID.", + "deleteDocTitle": "Padam dokumen", + "deleteDocBody": "Padam dokumen \"{id}\" secara kekal? Tindakan ini tidak boleh dibatalkan.", + "errAuth": "Pengesahan gagal. Semak kelayakan anda.", + "errForbidden": "Pengguna ini tidak dibenarkan melakukan tindakan itu.", + "errNotFound": "Indeks atau dokumen tidak ditemui.", + "errBadQuery": "Kueri tidak dapat dihuraikan. Semak sintaksnya.", + "errConflict": "Dokumen telah diubah oleh penulisan lain. Muat semula dan cuba lagi.", + "errNetwork": "Tidak dapat mencapai kluster. Semak URL dan pastikan ia sedang berjalan.", + "errDocNotObject": "Dokumen mestilah objek JSON.", + "errInvalidDocJson": "Ini bukan JSON yang sah.", + "toast": { + "docCreated": "Dokumen dicipta", + "docUpdated": "Dokumen disimpan", + "docDeleted": "Dokumen dipadam", + "createFailed": "Gagal cipta: {message}", + "saveFailed": "Gagal simpan: {message}", + "deleteFailed": "Gagal padam: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/nb.json b/apps/desktop-ui/messages/nb.json index 1bd71666..2cc2b9e7 100644 --- a/apps/desktop-ui/messages/nb.json +++ b/apps/desktop-ui/messages/nb.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "Dette er ikke gyldig JSON.", "serviceAccountNotServiceAccount": "Denne JSON-en er ikke en tjenestekontonøkkel (forventer typen \"service_account\" med project_id og client_email).", "serviceAccountBadKey": "Feltet private_key mangler eller er ikke en PKCS#8 PEM-nøkkel.", - "databaseIdInvalid": "Database-ID må være 4–63 små bokstaver, sifre eller bindestreker, eller (default)." + "databaseIdInvalid": "Database-ID må være 4–63 små bokstaver, sifre eller bindestreker, eller (default).", + "esUrlRequired": "Skriv inn en klynge-URL.", + "esUrlScheme": "Klynge-URL-en må starte med http:// eller https://.", + "esUrlInvalid": "Dette er ikke en gyldig URL.", + "esUsernameRequired": "Skriv inn et brukernavn.", + "esApiKeyRequired": "Skriv inn en API-nøkkel.", + "esBearerRequired": "Skriv inn et bearer-token." }, "firestore": { "serviceAccount": "Tjenestekontonøkkel (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "Slettet {count} samlinger", "bulkDropFailed": "Kunne ikke slette {count} samlinger" } + }, + "elasticsearch": { + "clusterUrl": "Klynge-URL", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Klyngen må presentere et sertifikat som denne enheten allerede stoler på – selvsignerte sertifikater (standarden for Elasticsearch https) støttes ikke.", + "auth": "Autentisering", + "authMode": { + "none": "Ingen", + "basic": "Brukernavn og passord", + "apiKey": "API-nøkkel", + "bearer": "Bearer-token" + }, + "username": "Brukernavn", + "password": "Passord", + "apiKey": "API-nøkkel (base64)", + "apiKeyHint": "Base64 id:api_key utstedt av _security/api_key-API-et.", + "bearerToken": "Bearer-token", + "noIndices": "Ingen indekser", + "noMatches": "Ingen treff", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Rediger Query DSL-en nedenfor.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Kjør", + "newDocument": "Nytt dokument", + "noHits": "Ingen samsvarende dokumenter", + "hitCount": "{count, plural, =0 {Ingen treff} one {# treff} other {# treff}}", + "hitCountTotal": "{count} av {total, plural, one {# treff} other {# treff}}", + "prevPage": "Forrige", + "nextPage": "Neste", + "selectDoc": "Velg et dokument for å vise det.", + "edit": "Rediger", + "save": "Lagre", + "cancel": "Avbryt", + "create": "Opprett", + "docIdLabel": "Dokument-ID (valgfritt)", + "docIdAutoHint": "La stå tomt for å la Elasticsearch tildele en ID.", + "deleteDocTitle": "Slett dokument", + "deleteDocBody": "Slette dokumentet \"{id}\" permanent? Dette kan ikke angres.", + "errAuth": "Autentisering mislyktes. Sjekk legitimasjonen din.", + "errForbidden": "Denne brukeren har ikke tillatelse til å utføre den handlingen.", + "errNotFound": "Indeksen eller dokumentet ble ikke funnet.", + "errBadQuery": "Spørringen kunne ikke tolkes. Sjekk syntaksen.", + "errConflict": "Dokumentet ble endret av en annen skriving. Oppdater og prøv igjen.", + "errNetwork": "Kunne ikke nå klyngen. Sjekk URL-en og at den kjører.", + "errDocNotObject": "Et dokument må være et JSON-objekt.", + "errInvalidDocJson": "Dette er ikke gyldig JSON.", + "toast": { + "docCreated": "Dokument opprettet", + "docUpdated": "Dokument lagret", + "docDeleted": "Dokument slettet", + "createFailed": "Opprettelse mislyktes: {message}", + "saveFailed": "Kunne ikke lagre: {message}", + "deleteFailed": "Kunne ikke slette: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/nl.json b/apps/desktop-ui/messages/nl.json index a1d18dff..ad7cc6ab 100644 --- a/apps/desktop-ui/messages/nl.json +++ b/apps/desktop-ui/messages/nl.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "Dit is geen geldige JSON.", "serviceAccountNotServiceAccount": "Deze JSON is geen serviceaccountsleutel (verwacht type \"service_account\" met project_id en client_email).", "serviceAccountBadKey": "Het veld private_key ontbreekt of is geen PKCS#8 PEM-sleutel.", - "databaseIdInvalid": "Database-ID moet 4–63 kleine letters, cijfers of streepjes bevatten, of (default) zijn." + "databaseIdInvalid": "Database-ID moet 4–63 kleine letters, cijfers of streepjes bevatten, of (default) zijn.", + "esUrlRequired": "Voer een cluster-URL in.", + "esUrlScheme": "De cluster-URL moet beginnen met http:// of https://.", + "esUrlInvalid": "Dit is geen geldige URL.", + "esUsernameRequired": "Voer een gebruikersnaam in.", + "esApiKeyRequired": "Voer een API-sleutel in.", + "esBearerRequired": "Voer een bearertoken in." }, "firestore": { "serviceAccount": "Serviceaccountsleutel (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "{count} collecties verwijderd", "bulkDropFailed": "Kan {count} collecties niet verwijderen" } + }, + "elasticsearch": { + "clusterUrl": "Cluster-URL", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Het cluster moet een certificaat presenteren dat dit apparaat al vertrouwt — zelfondertekende certificaten (de Elasticsearch https-standaard) worden niet ondersteund.", + "auth": "Authenticatie", + "authMode": { + "none": "Geen", + "basic": "Gebruikersnaam en wachtwoord", + "apiKey": "API-sleutel", + "bearer": "Bearertoken" + }, + "username": "Gebruikersnaam", + "password": "Wachtwoord", + "apiKey": "API-sleutel (base64)", + "apiKeyHint": "De base64 id:api_key uitgegeven door de _security/api_key-API.", + "bearerToken": "Bearertoken", + "noIndices": "Geen indexen", + "noMatches": "Geen overeenkomsten", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Bewerk de Query DSL hieronder.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Uitvoeren", + "newDocument": "Nieuw document", + "noHits": "Geen overeenkomende documenten", + "hitCount": "{count, plural, =0 {Geen resultaten} one {# resultaat} other {# resultaten}}", + "hitCountTotal": "{count} van {total, plural, one {# resultaat} other {# resultaten}}", + "prevPage": "Vorige", + "nextPage": "Volgende", + "selectDoc": "Selecteer een document om het te bekijken.", + "edit": "Bewerken", + "save": "Opslaan", + "cancel": "Annuleren", + "create": "Aanmaken", + "docIdLabel": "Document-ID (optioneel)", + "docIdAutoHint": "Laat leeg om Elasticsearch een ID te laten toewijzen.", + "deleteDocTitle": "Document verwijderen", + "deleteDocBody": "Document \"{id}\" permanent verwijderen? Dit kan niet ongedaan worden gemaakt.", + "errAuth": "Authenticatie mislukt. Controleer je inloggegevens.", + "errForbidden": "Deze gebruiker mag die actie niet uitvoeren.", + "errNotFound": "De index of het document is niet gevonden.", + "errBadQuery": "De query kon niet worden geparseerd. Controleer de syntaxis.", + "errConflict": "Het document is gewijzigd door een andere schrijfbewerking. Vernieuw en probeer opnieuw.", + "errNetwork": "Kan het cluster niet bereiken. Controleer de URL en of het actief is.", + "errDocNotObject": "Een document moet een JSON-object zijn.", + "errInvalidDocJson": "Dit is geen geldige JSON.", + "toast": { + "docCreated": "Document aangemaakt", + "docUpdated": "Document opgeslagen", + "docDeleted": "Document verwijderd", + "createFailed": "Aanmaken mislukt: {message}", + "saveFailed": "Opslaan mislukt: {message}", + "deleteFailed": "Verwijderen mislukt: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/pl.json b/apps/desktop-ui/messages/pl.json index 9987771a..ece0e0cd 100644 --- a/apps/desktop-ui/messages/pl.json +++ b/apps/desktop-ui/messages/pl.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "To nie jest poprawny JSON.", "serviceAccountNotServiceAccount": "Ten JSON nie jest kluczem konta usługi (oczekiwany typ \"service_account\" z project_id i client_email).", "serviceAccountBadKey": "Brak pola private_key lub nie jest ono kluczem PKCS#8 PEM.", - "databaseIdInvalid": "Database ID musi zawierać od 4 do 63 małych liter, cyfr lub myślników, albo być (default)." + "databaseIdInvalid": "Database ID musi zawierać od 4 do 63 małych liter, cyfr lub myślników, albo być (default).", + "esUrlRequired": "Wprowadź URL klastra.", + "esUrlScheme": "URL klastra musi zaczynać się od http:// lub https://.", + "esUrlInvalid": "To nie jest prawidłowy URL.", + "esUsernameRequired": "Wprowadź nazwę użytkownika.", + "esApiKeyRequired": "Wprowadź klucz API.", + "esBearerRequired": "Wprowadź token Bearer." }, "firestore": { "serviceAccount": "Klucz konta usługi (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "{count, plural, one {Usunięto # kolekcję} few {Usunięto # kolekcje} many {Usunięto # kolekcji} other {Usunięto # kolekcji}}", "bulkDropFailed": "{count, plural, one {Nie udało się usunąć # kolekcji} few {Nie udało się usunąć # kolekcji} many {Nie udało się usunąć # kolekcji} other {Nie udało się usunąć # kolekcji}}" } + }, + "elasticsearch": { + "clusterUrl": "URL klastra", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Klaster musi przedstawić certyfikat, któremu to urządzenie już ufa — certyfikaty z podpisem własnym (domyślne dla https w Elasticsearchu) nie są obsługiwane.", + "auth": "Uwierzytelnianie", + "authMode": { + "none": "Brak", + "basic": "Nazwa użytkownika i hasło", + "apiKey": "Klucz API", + "bearer": "Token Bearer" + }, + "username": "Nazwa użytkownika", + "password": "Hasło", + "apiKey": "Klucz API (base64)", + "apiKeyHint": "Ciąg base64 id:api_key wydany przez API _security/api_key.", + "bearerToken": "Token Bearer", + "noIndices": "Brak indeksów", + "noMatches": "Brak dopasowań", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Edytuj poniżej Query DSL.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Uruchom", + "newDocument": "Nowy dokument", + "noHits": "Brak pasujących dokumentów", + "hitCount": "{count, plural, =0 {Brak wyników} one {# wynik} few {# wyniki} many {# wyników} other {# wyniku}}", + "hitCountTotal": "{count} z {total, plural, one {# wynik} few {# wyniki} many {# wyników} other {# wyniku}}", + "prevPage": "Poprzednia", + "nextPage": "Następna", + "selectDoc": "Wybierz dokument, aby go wyświetlić.", + "edit": "Edytuj", + "save": "Zapisz", + "cancel": "Anuluj", + "create": "Utwórz", + "docIdLabel": "ID dokumentu (opcjonalne)", + "docIdAutoHint": "Pozostaw puste, aby Elasticsearch przypisał ID.", + "deleteDocTitle": "Usuń dokument", + "deleteDocBody": "Trwale usunąć dokument „{id}“? Tej operacji nie można cofnąć.", + "errAuth": "Uwierzytelnianie nie powiodło się. Sprawdź swoje dane logowania.", + "errForbidden": "Ten użytkownik nie ma uprawnień do wykonania tej akcji.", + "errNotFound": "Nie znaleziono indeksu ani dokumentu.", + "errBadQuery": "Nie udało się przeanalizować zapytania. Sprawdź składnię.", + "errConflict": "Dokument został zmieniony przez inny zapis. Odśwież i spróbuj ponownie.", + "errNetwork": "Nie można połączyć się z klastrem. Sprawdź URL i czy działa.", + "errDocNotObject": "Dokument musi być obiektem JSON.", + "errInvalidDocJson": "To nie jest prawidłowy JSON.", + "toast": { + "docCreated": "Dokument utworzony", + "docUpdated": "Dokument zapisany", + "docDeleted": "Dokument usunięty", + "createFailed": "Nie udało się utworzyć: {message}", + "saveFailed": "Nie udało się zapisać: {message}", + "deleteFailed": "Nie udało się usunąć: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/pt-BR.json b/apps/desktop-ui/messages/pt-BR.json index b6f19582..a54d5da7 100644 --- a/apps/desktop-ui/messages/pt-BR.json +++ b/apps/desktop-ui/messages/pt-BR.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "Isso não é um JSON válido.", "serviceAccountNotServiceAccount": "Este JSON não é uma chave de conta de serviço (era esperado o tipo \"service_account\" com project_id e client_email).", "serviceAccountBadKey": "O campo private_key está ausente ou não é uma chave PEM PKCS#8.", - "databaseIdInvalid": "O ID do banco de dados deve ter de 4 a 63 letras minúsculas, dígitos ou hífens, ou ser (default)." + "databaseIdInvalid": "O ID do banco de dados deve ter de 4 a 63 letras minúsculas, dígitos ou hífens, ou ser (default).", + "esUrlRequired": "Digite uma URL de cluster.", + "esUrlScheme": "A URL do cluster deve começar com http:// ou https://.", + "esUrlInvalid": "Esta não é uma URL válida.", + "esUsernameRequired": "Digite um nome de usuário.", + "esApiKeyRequired": "Digite uma chave de API.", + "esBearerRequired": "Digite um token bearer." }, "firestore": { "serviceAccount": "Chave de conta de serviço (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "{count} coleções descartadas", "bulkDropFailed": "Não foi possível descartar {count} coleções" } + }, + "elasticsearch": { + "clusterUrl": "URL do cluster", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "O cluster deve apresentar um certificado em que este dispositivo já confia — certificados autoassinados (o padrão do https do Elasticsearch) não são suportados.", + "auth": "Autenticação", + "authMode": { + "none": "Nenhuma", + "basic": "Nome de usuário e senha", + "apiKey": "Chave de API", + "bearer": "Token bearer" + }, + "username": "Nome de usuário", + "password": "Senha", + "apiKey": "Chave de API (base64)", + "apiKeyHint": "O id:api_key em base64 emitido pela API _security/api_key.", + "bearerToken": "Token bearer", + "noIndices": "Nenhum índice", + "noMatches": "Nenhuma correspondência", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Edite o Query DSL abaixo.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Executar", + "newDocument": "Novo documento", + "noHits": "Nenhum documento correspondente", + "hitCount": "{count, plural, =0 {Nenhum resultado} one {# resultado} other {# resultados}}", + "hitCountTotal": "{count} de {total, plural, one {# resultado} other {# resultados}}", + "prevPage": "Anterior", + "nextPage": "Próximo", + "selectDoc": "Selecione um documento para visualizá-lo.", + "edit": "Editar", + "save": "Salvar", + "cancel": "Cancelar", + "create": "Criar", + "docIdLabel": "ID do documento (opcional)", + "docIdAutoHint": "Deixe em branco para que o Elasticsearch atribua um ID.", + "deleteDocTitle": "Excluir documento", + "deleteDocBody": "Excluir permanentemente o documento \"{id}\"? Isso não pode ser desfeito.", + "errAuth": "Falha na autenticação. Verifique suas credenciais.", + "errForbidden": "Este usuário não tem permissão para realizar essa ação.", + "errNotFound": "O índice ou documento não foi encontrado.", + "errBadQuery": "Não foi possível analisar a consulta. Verifique a sintaxe.", + "errConflict": "O documento foi alterado por outra gravação. Atualize e tente novamente.", + "errNetwork": "Não foi possível acessar o cluster. Verifique a URL e se ele está em execução.", + "errDocNotObject": "Um documento deve ser um objeto JSON.", + "errInvalidDocJson": "Isso não é um JSON válido.", + "toast": { + "docCreated": "Documento criado", + "docUpdated": "Documento salvo", + "docDeleted": "Documento excluído", + "createFailed": "Falha ao criar: {message}", + "saveFailed": "Falha ao salvar: {message}", + "deleteFailed": "Falha ao excluir: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/pt.json b/apps/desktop-ui/messages/pt.json index 1d97bc27..35d0ddff 100644 --- a/apps/desktop-ui/messages/pt.json +++ b/apps/desktop-ui/messages/pt.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "Isto não é um JSON válido.", "serviceAccountNotServiceAccount": "Este JSON não é uma chave de conta de serviço (esperava-se o tipo \"service_account\" com project_id e client_email).", "serviceAccountBadKey": "O campo private_key está em falta ou não é uma chave PEM PKCS#8.", - "databaseIdInvalid": "O ID da base de dados tem de ter entre 4 e 63 letras minúsculas, dígitos ou hífenes, ou ser (default)." + "databaseIdInvalid": "O ID da base de dados tem de ter entre 4 e 63 letras minúsculas, dígitos ou hífenes, ou ser (default).", + "esUrlRequired": "Introduz um URL de cluster.", + "esUrlScheme": "O URL do cluster tem de começar com http:// ou https://.", + "esUrlInvalid": "Isto não é um URL válido.", + "esUsernameRequired": "Introduz um nome de utilizador.", + "esApiKeyRequired": "Introduz uma chave de API.", + "esBearerRequired": "Introduz um token bearer." }, "firestore": { "serviceAccount": "Chave de conta de serviço (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "{count} coleções descartadas", "bulkDropFailed": "Não foi possível descartar {count} coleções" } + }, + "elasticsearch": { + "clusterUrl": "URL do cluster", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "O cluster tem de apresentar um certificado em que este dispositivo já confia — os certificados autoassinados (a predefinição do https do Elasticsearch) não são suportados.", + "auth": "Autenticação", + "authMode": { + "none": "Nenhuma", + "basic": "Nome de utilizador e palavra-passe", + "apiKey": "Chave de API", + "bearer": "Token bearer" + }, + "username": "Nome de utilizador", + "password": "Palavra-passe", + "apiKey": "Chave de API (base64)", + "apiKeyHint": "O id:api_key em base64 emitido pela API _security/api_key.", + "bearerToken": "Token bearer", + "noIndices": "Sem índices", + "noMatches": "Sem correspondências", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Edita o Query DSL abaixo.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Executar", + "newDocument": "Novo documento", + "noHits": "Nenhum documento correspondente", + "hitCount": "{count, plural, =0 {Sem resultados} one {# resultado} other {# resultados}}", + "hitCountTotal": "{count} de {total, plural, one {# resultado} other {# resultados}}", + "prevPage": "Anterior", + "nextPage": "Seguinte", + "selectDoc": "Seleciona um documento para o veres.", + "edit": "Editar", + "save": "Guardar", + "cancel": "Cancelar", + "create": "Criar", + "docIdLabel": "ID do documento (opcional)", + "docIdAutoHint": "Deixa em branco para que o Elasticsearch atribua um ID.", + "deleteDocTitle": "Eliminar documento", + "deleteDocBody": "Eliminar permanentemente o documento \"{id}\"? Esta ação não pode ser anulada.", + "errAuth": "Falha na autenticação. Verifica as tuas credenciais.", + "errForbidden": "Este utilizador não tem permissão para realizar essa ação.", + "errNotFound": "O índice ou documento não foi encontrado.", + "errBadQuery": "Não foi possível analisar a consulta. Verifica a sintaxe.", + "errConflict": "O documento foi alterado por outra escrita. Atualiza e tenta novamente.", + "errNetwork": "Não foi possível aceder ao cluster. Verifica o URL e se está em execução.", + "errDocNotObject": "Um documento tem de ser um objeto JSON.", + "errInvalidDocJson": "Isto não é um JSON válido.", + "toast": { + "docCreated": "Documento criado", + "docUpdated": "Documento guardado", + "docDeleted": "Documento eliminado", + "createFailed": "Falha ao criar: {message}", + "saveFailed": "Falha ao guardar: {message}", + "deleteFailed": "Falha ao eliminar: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/ru.json b/apps/desktop-ui/messages/ru.json index b7d788ac..ef71c93d 100644 --- a/apps/desktop-ui/messages/ru.json +++ b/apps/desktop-ui/messages/ru.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "Это не является допустимым JSON.", "serviceAccountNotServiceAccount": "Этот JSON не является ключом сервисного аккаунта (ожидается тип \"service_account\" с project_id и client_email).", "serviceAccountBadKey": "Поле private_key отсутствует или не является ключом PKCS#8 PEM.", - "databaseIdInvalid": "Database ID должен содержать от 4 до 63 строчных букв, цифр или дефисов, либо быть (default)." + "databaseIdInvalid": "Database ID должен содержать от 4 до 63 строчных букв, цифр или дефисов, либо быть (default).", + "esUrlRequired": "Введите URL кластера.", + "esUrlScheme": "URL кластера должен начинаться с http:// или https://.", + "esUrlInvalid": "Это недействительный URL.", + "esUsernameRequired": "Введите имя пользователя.", + "esApiKeyRequired": "Введите ключ API.", + "esBearerRequired": "Введите bearer-токен." }, "firestore": { "serviceAccount": "Ключ сервисного аккаунта (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "{count, plural, one {Удалена # коллекция} few {Удалено # коллекции} many {Удалено # коллекций} other {Удалено # коллекций}}", "bulkDropFailed": "{count, plural, one {Не удалось удалить # коллекцию} few {Не удалось удалить # коллекции} many {Не удалось удалить # коллекций} other {Не удалось удалить # коллекций}}" } + }, + "elasticsearch": { + "clusterUrl": "URL кластера", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Кластер должен предъявить сертификат, которому это устройство уже доверяет — самоподписанные сертификаты (используемые в Elasticsearch по умолчанию для https) не поддерживаются.", + "auth": "Аутентификация", + "authMode": { + "none": "Нет", + "basic": "Имя пользователя и пароль", + "apiKey": "Ключ API", + "bearer": "Bearer-токен" + }, + "username": "Имя пользователя", + "password": "Пароль", + "apiKey": "Ключ API (base64)", + "apiKeyHint": "Строка base64 id:api_key, выданная API _security/api_key.", + "bearerToken": "Bearer-токен", + "noIndices": "Нет индексов", + "noMatches": "Нет совпадений", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Отредактируйте Query DSL ниже.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Выполнить", + "newDocument": "Новый документ", + "noHits": "Нет подходящих документов", + "hitCount": "{count, plural, =0 {Нет результатов} one {# результат} few {# результата} many {# результатов} other {# результатов}}", + "hitCountTotal": "{count} из {total, plural, one {# результат} few {# результата} many {# результатов} other {# результатов}}", + "prevPage": "Назад", + "nextPage": "Вперёд", + "selectDoc": "Выберите документ для просмотра.", + "edit": "Редактировать", + "save": "Сохранить", + "cancel": "Отмена", + "create": "Создать", + "docIdLabel": "ID документа (необязательно)", + "docIdAutoHint": "Оставьте пустым, чтобы Elasticsearch назначил ID.", + "deleteDocTitle": "Удалить документ", + "deleteDocBody": "Удалить документ «{id}» безвозвратно? Это действие нельзя отменить.", + "errAuth": "Ошибка аутентификации. Проверьте учётные данные.", + "errForbidden": "Этому пользователю не разрешено выполнять это действие.", + "errNotFound": "Индекс или документ не найден.", + "errBadQuery": "Не удалось разобрать запрос. Проверьте синтаксис.", + "errConflict": "Документ был изменён другой записью. Обновите и повторите попытку.", + "errNetwork": "Не удалось подключиться к кластеру. Проверьте URL и что он запущен.", + "errDocNotObject": "Документ должен быть объектом JSON.", + "errInvalidDocJson": "Это недействительный JSON.", + "toast": { + "docCreated": "Документ создан", + "docUpdated": "Документ сохранён", + "docDeleted": "Документ удалён", + "createFailed": "Не удалось создать: {message}", + "saveFailed": "Не удалось сохранить: {message}", + "deleteFailed": "Не удалось удалить: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/sv.json b/apps/desktop-ui/messages/sv.json index 0f8afc2d..057c095c 100644 --- a/apps/desktop-ui/messages/sv.json +++ b/apps/desktop-ui/messages/sv.json @@ -1931,7 +1931,13 @@ "serviceAccountInvalidJson": "Detta är inte giltig JSON.", "serviceAccountNotServiceAccount": "Denna JSON är inte en tjänstekontonyckel (typen \"service_account\" med project_id och client_email förväntas).", "serviceAccountBadKey": "Fältet private_key saknas eller är inte en PKCS#8 PEM-nyckel.", - "databaseIdInvalid": "Databas-ID måste vara 4–63 gemener, siffror eller bindestreck, eller (default)." + "databaseIdInvalid": "Databas-ID måste vara 4–63 gemener, siffror eller bindestreck, eller (default).", + "esUrlRequired": "Ange en kluster-URL.", + "esUrlScheme": "Kluster-URL:en måste börja med http:// eller https://.", + "esUrlInvalid": "Detta är inte en giltig URL.", + "esUsernameRequired": "Ange ett användarnamn.", + "esApiKeyRequired": "Ange en API-nyckel.", + "esBearerRequired": "Ange en bearer-token." }, "firestore": { "serviceAccount": "Tjänstekontonyckel (JSON)", @@ -2064,6 +2070,62 @@ "bulkDropped": "Tog bort {count} samlingar", "bulkDropFailed": "Det gick inte att ta bort {count} samlingar" } + }, + "elasticsearch": { + "clusterUrl": "Kluster-URL", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Klustret måste uppvisa ett certifikat som den här enheten redan litar på — självsignerade certifikat (standarden för Elasticsearch https) stöds inte.", + "auth": "Autentisering", + "authMode": { + "none": "Ingen", + "basic": "Användarnamn och lösenord", + "apiKey": "API-nyckel", + "bearer": "Bearer-token" + }, + "username": "Användarnamn", + "password": "Lösenord", + "apiKey": "API-nyckel (base64)", + "apiKeyHint": "Den base64-kodade id:api_key som utfärdats av _security/api_key-API:et.", + "bearerToken": "Bearer-token", + "noIndices": "Inga index", + "noMatches": "Inga träffar", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Redigera Query DSL nedan.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Kör", + "newDocument": "Nytt dokument", + "noHits": "Inga matchande dokument", + "hitCount": "{count, plural, =0 {Inga träffar} one {# träff} other {# träffar}}", + "hitCountTotal": "{count} av {total, plural, one {# träff} other {# träffar}}", + "prevPage": "Föregående", + "nextPage": "Nästa", + "selectDoc": "Välj ett dokument för att visa det.", + "edit": "Redigera", + "save": "Spara", + "cancel": "Avbryt", + "create": "Skapa", + "docIdLabel": "Dokument-ID (valfritt)", + "docIdAutoHint": "Lämna tomt för att låta Elasticsearch tilldela ett ID.", + "deleteDocTitle": "Ta bort dokument", + "deleteDocBody": "Ta bort dokumentet \"{id}\" permanent? Detta går inte att ångra.", + "errAuth": "Autentiseringen misslyckades. Kontrollera dina inloggningsuppgifter.", + "errForbidden": "Den här användaren har inte behörighet att utföra åtgärden.", + "errNotFound": "Indexet eller dokumentet hittades inte.", + "errBadQuery": "Frågan kunde inte tolkas. Kontrollera syntaxen.", + "errConflict": "Dokumentet ändrades av en annan skrivning. Uppdatera och försök igen.", + "errNetwork": "Det gick inte att nå klustret. Kontrollera URL:en och att det körs.", + "errDocNotObject": "Ett dokument måste vara ett JSON-objekt.", + "errInvalidDocJson": "Detta är inte giltig JSON.", + "toast": { + "docCreated": "Dokument skapat", + "docUpdated": "Dokument sparat", + "docDeleted": "Dokument borttaget", + "createFailed": "Det gick inte att skapa: {message}", + "saveFailed": "Det gick inte att spara: {message}", + "deleteFailed": "Det gick inte att ta bort: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/tr.json b/apps/desktop-ui/messages/tr.json index fa499134..67673ed0 100644 --- a/apps/desktop-ui/messages/tr.json +++ b/apps/desktop-ui/messages/tr.json @@ -1931,7 +1931,13 @@ "serviceAccountInvalidJson": "Bu geçerli bir JSON değil.", "serviceAccountNotServiceAccount": "Bu JSON bir hizmet hesabı anahtarı değil (project_id ve client_email içeren \"service_account\" türü bekleniyor).", "serviceAccountBadKey": "private_key alanı eksik veya PKCS#8 PEM anahtarı değil.", - "databaseIdInvalid": "Database ID, 4–63 küçük harf, rakam veya tire içermeli ya da (default) olmalıdır." + "databaseIdInvalid": "Database ID, 4–63 küçük harf, rakam veya tire içermeli ya da (default) olmalıdır.", + "esUrlRequired": "Bir küme URL'si girin.", + "esUrlScheme": "Küme URL'si http:// veya https:// ile başlamalıdır.", + "esUrlInvalid": "Bu geçerli bir URL değil.", + "esUsernameRequired": "Bir kullanıcı adı girin.", + "esApiKeyRequired": "Bir API anahtarı girin.", + "esBearerRequired": "Bir bearer belirteci girin." }, "firestore": { "serviceAccount": "Hizmet hesabı anahtarı (JSON)", @@ -2064,6 +2070,62 @@ "bulkDropped": "{count} koleksiyon silindi", "bulkDropFailed": "{count} koleksiyon silinemedi" } + }, + "elasticsearch": { + "clusterUrl": "Küme URL'si", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Küme, bu cihazın halihazırda güvendiği bir sertifika sunmalıdır — kendinden imzalı sertifikalar (Elasticsearch https varsayılanı) desteklenmez.", + "auth": "Kimlik doğrulama", + "authMode": { + "none": "Yok", + "basic": "Kullanıcı adı ve parola", + "apiKey": "API anahtarı", + "bearer": "Bearer belirteci" + }, + "username": "Kullanıcı adı", + "password": "Parola", + "apiKey": "API anahtarı (base64)", + "apiKeyHint": "_security/api_key API'si tarafından verilen base64 id:api_key.", + "bearerToken": "Bearer belirteci", + "noIndices": "Dizin yok", + "noMatches": "Eşleşme yok", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Aşağıdaki Query DSL'i düzenleyin.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Çalıştır", + "newDocument": "Yeni belge", + "noHits": "Eşleşen belge yok", + "hitCount": "{count, plural, =0 {Sonuç yok} one {# sonuç} other {# sonuç}}", + "hitCountTotal": "{count} / {total, plural, one {# sonuç} other {# sonuç}}", + "prevPage": "Önceki", + "nextPage": "Sonraki", + "selectDoc": "Görüntülemek için bir belge seçin.", + "edit": "Düzenle", + "save": "Kaydet", + "cancel": "İptal", + "create": "Oluştur", + "docIdLabel": "Belge kimliği (isteğe bağlı)", + "docIdAutoHint": "Elasticsearch'ün bir kimlik atamasına izin vermek için boş bırakın.", + "deleteDocTitle": "Belgeyi sil", + "deleteDocBody": "\"{id}\" belgesi kalıcı olarak silinsin mi? Bu işlem geri alınamaz.", + "errAuth": "Kimlik doğrulama başarısız oldu. Kimlik bilgilerinizi kontrol edin.", + "errForbidden": "Bu kullanıcının bu işlemi gerçekleştirme izni yok.", + "errNotFound": "Dizin veya belge bulunamadı.", + "errBadQuery": "Sorgu ayrıştırılamadı. Söz dizimini kontrol edin.", + "errConflict": "Belge başka bir yazma işlemiyle değiştirildi. Yenileyip yeniden deneyin.", + "errNetwork": "Kümeye ulaşılamadı. URL'yi ve çalışıp çalışmadığını kontrol edin.", + "errDocNotObject": "Bir belge JSON nesnesi olmalıdır.", + "errInvalidDocJson": "Bu geçerli bir JSON değil.", + "toast": { + "docCreated": "Belge oluşturuldu", + "docUpdated": "Belge kaydedildi", + "docDeleted": "Belge silindi", + "createFailed": "Oluşturma başarısız oldu: {message}", + "saveFailed": "Kaydetme başarısız oldu: {message}", + "deleteFailed": "Silme başarısız oldu: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/uk.json b/apps/desktop-ui/messages/uk.json index f7a388fe..988d8804 100644 --- a/apps/desktop-ui/messages/uk.json +++ b/apps/desktop-ui/messages/uk.json @@ -1931,7 +1931,13 @@ "serviceAccountInvalidJson": "Це не є коректним JSON.", "serviceAccountNotServiceAccount": "Цей JSON не є ключем сервісного облікового запису (очікується тип \"service_account\" з project_id і client_email).", "serviceAccountBadKey": "Поле private_key відсутнє або не є ключем PKCS#8 PEM.", - "databaseIdInvalid": "Database ID має містити від 4 до 63 малих літер, цифр або дефісів, або бути (default)." + "databaseIdInvalid": "Database ID має містити від 4 до 63 малих літер, цифр або дефісів, або бути (default).", + "esUrlRequired": "Введіть URL кластера.", + "esUrlScheme": "URL кластера має починатися з http:// або https://.", + "esUrlInvalid": "Це недійсний URL.", + "esUsernameRequired": "Введіть ім'я користувача.", + "esApiKeyRequired": "Введіть ключ API.", + "esBearerRequired": "Введіть bearer-токен." }, "firestore": { "serviceAccount": "Ключ сервісного облікового запису (JSON)", @@ -2064,6 +2070,62 @@ "bulkDropped": "Видалено {count} колекцій", "bulkDropFailed": "Не вдалося видалити {count} колекцій" } + }, + "elasticsearch": { + "clusterUrl": "URL кластера", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Кластер повинен надати сертифікат, якому цей пристрій уже довіряє — самопідписані сертифікати (типове налаштування https в Elasticsearch) не підтримуються.", + "auth": "Автентифікація", + "authMode": { + "none": "Немає", + "basic": "Ім'я користувача та пароль", + "apiKey": "Ключ API", + "bearer": "Bearer-токен" + }, + "username": "Ім'я користувача", + "password": "Пароль", + "apiKey": "Ключ API (base64)", + "apiKeyHint": "Рядок base64 id:api_key, виданий API _security/api_key.", + "bearerToken": "Bearer-токен", + "noIndices": "Немає індексів", + "noMatches": "Немає збігів", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Відредагуйте Query DSL нижче.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Виконати", + "newDocument": "Новий документ", + "noHits": "Немає відповідних документів", + "hitCount": "{count, plural, =0 {Немає результатів} one {# результат} few {# результати} many {# результатів} other {# результатів}}", + "hitCountTotal": "{count} з {total, plural, one {# результат} few {# результати} many {# результатів} other {# результатів}}", + "prevPage": "Назад", + "nextPage": "Далі", + "selectDoc": "Виберіть документ для перегляду.", + "edit": "Редагувати", + "save": "Зберегти", + "cancel": "Скасувати", + "create": "Створити", + "docIdLabel": "ID документа (необов'язково)", + "docIdAutoHint": "Залиште порожнім, щоб Elasticsearch призначив ID.", + "deleteDocTitle": "Видалити документ", + "deleteDocBody": "Остаточно видалити документ «{id}»? Цю дію не можна скасувати.", + "errAuth": "Помилка автентифікації. Перевірте облікові дані.", + "errForbidden": "Цьому користувачу не дозволено виконувати цю дію.", + "errNotFound": "Індекс або документ не знайдено.", + "errBadQuery": "Не вдалося розібрати запит. Перевірте синтаксис.", + "errConflict": "Документ було змінено іншим записом. Оновіть і повторіть спробу.", + "errNetwork": "Не вдалося підключитися до кластера. Перевірте URL і що він запущений.", + "errDocNotObject": "Документ має бути об'єктом JSON.", + "errInvalidDocJson": "Це недійсний JSON.", + "toast": { + "docCreated": "Документ створено", + "docUpdated": "Документ збережено", + "docDeleted": "Документ видалено", + "createFailed": "Не вдалося створити: {message}", + "saveFailed": "Не вдалося зберегти: {message}", + "deleteFailed": "Не вдалося видалити: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/vi.json b/apps/desktop-ui/messages/vi.json index 86cd40df..ca27b500 100644 --- a/apps/desktop-ui/messages/vi.json +++ b/apps/desktop-ui/messages/vi.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "Đây không phải là JSON hợp lệ.", "serviceAccountNotServiceAccount": "JSON này không phải là khóa tài khoản dịch vụ (cần loại \"service_account\" với project_id và client_email).", "serviceAccountBadKey": "Thiếu trường private_key hoặc trường này không phải khóa PEM định dạng PKCS#8.", - "databaseIdInvalid": "ID cơ sở dữ liệu phải gồm 4–63 chữ thường, chữ số hoặc dấu gạch nối, hoặc là (default)." + "databaseIdInvalid": "ID cơ sở dữ liệu phải gồm 4–63 chữ thường, chữ số hoặc dấu gạch nối, hoặc là (default).", + "esUrlRequired": "Nhập URL cụm.", + "esUrlScheme": "URL cụm phải bắt đầu bằng http:// hoặc https://.", + "esUrlInvalid": "Đây không phải là URL hợp lệ.", + "esUsernameRequired": "Nhập tên người dùng.", + "esApiKeyRequired": "Nhập khóa API.", + "esBearerRequired": "Nhập token bearer." }, "firestore": { "serviceAccount": "Khóa tài khoản dịch vụ (JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "Đã xóa {count} bộ sưu tập", "bulkDropFailed": "Không thể xóa {count} bộ sưu tập" } + }, + "elasticsearch": { + "clusterUrl": "URL cụm", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "Cụm phải xuất trình chứng chỉ mà thiết bị này đã tin cậy — chứng chỉ tự ký (mặc định của https Elasticsearch) không được hỗ trợ.", + "auth": "Xác thực", + "authMode": { + "none": "Không", + "basic": "Tên người dùng và mật khẩu", + "apiKey": "Khóa API", + "bearer": "Token bearer" + }, + "username": "Tên người dùng", + "password": "Mật khẩu", + "apiKey": "Khóa API (base64)", + "apiKeyHint": "id:api_key ở dạng base64 do API _security/api_key cấp.", + "bearerToken": "Token bearer", + "noIndices": "Không có chỉ mục", + "noMatches": "Không có kết quả khớp", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "Chỉnh sửa Query DSL bên dưới.", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "Chạy", + "newDocument": "Tài liệu mới", + "noHits": "Không có tài liệu khớp", + "hitCount": "{count, plural, =0 {Không có kết quả} other {# kết quả}}", + "hitCountTotal": "{count} trên {total, plural, other {# kết quả}}", + "prevPage": "Trước", + "nextPage": "Sau", + "selectDoc": "Chọn một tài liệu để xem.", + "edit": "Sửa", + "save": "Lưu", + "cancel": "Hủy", + "create": "Tạo", + "docIdLabel": "ID tài liệu (tùy chọn)", + "docIdAutoHint": "Để trống để Elasticsearch gán ID.", + "deleteDocTitle": "Xóa tài liệu", + "deleteDocBody": "Xóa vĩnh viễn tài liệu \"{id}\"? Không thể hoàn tác.", + "errAuth": "Xác thực thất bại. Kiểm tra thông tin đăng nhập của bạn.", + "errForbidden": "Người dùng này không được phép thực hiện hành động đó.", + "errNotFound": "Không tìm thấy chỉ mục hoặc tài liệu.", + "errBadQuery": "Không thể phân tích truy vấn. Kiểm tra cú pháp.", + "errConflict": "Tài liệu đã bị thay đổi bởi một thao tác ghi khác. Làm mới và thử lại.", + "errNetwork": "Không thể kết nối tới cụm. Kiểm tra URL và đảm bảo nó đang chạy.", + "errDocNotObject": "Tài liệu phải là một đối tượng JSON.", + "errInvalidDocJson": "Đây không phải là JSON hợp lệ.", + "toast": { + "docCreated": "Đã tạo tài liệu", + "docUpdated": "Đã lưu tài liệu", + "docDeleted": "Đã xóa tài liệu", + "createFailed": "Tạo thất bại: {message}", + "saveFailed": "Lưu thất bại: {message}", + "deleteFailed": "Xóa thất bại: {message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/messages/zh.json b/apps/desktop-ui/messages/zh.json index 7ced4825..fcb9e242 100644 --- a/apps/desktop-ui/messages/zh.json +++ b/apps/desktop-ui/messages/zh.json @@ -1920,7 +1920,13 @@ "serviceAccountInvalidJson": "这不是有效的 JSON。", "serviceAccountNotServiceAccount": "此 JSON 不是服务账号密钥(应为 \"service_account\" 类型,并包含 project_id 和 client_email)。", "serviceAccountBadKey": "缺少 private_key 字段,或该字段不是 PKCS#8 格式的 PEM 密钥。", - "databaseIdInvalid": "数据库 ID 必须是 4–63 位小写字母、数字或连字符,或为 (default)。" + "databaseIdInvalid": "数据库 ID 必须是 4–63 位小写字母、数字或连字符,或为 (default)。", + "esUrlRequired": "请输入集群 URL。", + "esUrlScheme": "集群 URL 必须以 http:// 或 https:// 开头。", + "esUrlInvalid": "这不是有效的 URL。", + "esUsernameRequired": "请输入用户名。", + "esApiKeyRequired": "请输入 API 密钥。", + "esBearerRequired": "请输入 Bearer 令牌。" }, "firestore": { "serviceAccount": "服务账号密钥(JSON)", @@ -2053,6 +2059,62 @@ "bulkDropped": "已删除 {count} 个集合", "bulkDropFailed": "无法删除 {count} 个集合" } + }, + "elasticsearch": { + "clusterUrl": "集群 URL", + "clusterUrlPlaceholder": "https://localhost:9200", + "clusterUrlHint": "集群必须提供此设备已信任的证书 — 不支持自签名证书(Elasticsearch https 的默认设置)。", + "auth": "身份验证", + "authMode": { + "none": "无", + "basic": "用户名和密码", + "apiKey": "API 密钥", + "bearer": "Bearer 令牌" + }, + "username": "用户名", + "password": "密码", + "apiKey": "API 密钥(base64)", + "apiKeyHint": "由 _security/api_key API 签发的 base64 编码 id:api_key。", + "bearerToken": "Bearer 令牌", + "noIndices": "没有索引", + "noMatches": "没有匹配项", + "modeLucene": "Lucene", + "modeDsl": "Query DSL", + "lucenePlaceholder": "status:active AND age:>30", + "dslBelow": "在下方编辑 Query DSL。", + "dslPlaceholder": "{ \"query\": { \"match_all\": {} } }", + "run": "运行", + "newDocument": "新建文档", + "noHits": "没有匹配的文档", + "hitCount": "{count, plural, =0 {没有命中} other {# 条命中}}", + "hitCountTotal": "{count},共 {total, plural, other {# 条命中}}", + "prevPage": "上一页", + "nextPage": "下一页", + "selectDoc": "选择一个文档以查看。", + "edit": "编辑", + "save": "保存", + "cancel": "取消", + "create": "创建", + "docIdLabel": "文档 ID(可选)", + "docIdAutoHint": "留空则由 Elasticsearch 分配 ID。", + "deleteDocTitle": "删除文档?", + "deleteDocBody": "永久删除文档 \"{id}\"?此操作无法撤销。", + "errAuth": "身份验证失败。请检查您的凭据。", + "errForbidden": "此用户无权执行该操作。", + "errNotFound": "未找到索引或文档。", + "errBadQuery": "无法解析查询。请检查语法。", + "errConflict": "该文档已被另一次写入更改。请刷新后重试。", + "errNetwork": "无法连接到集群。请检查 URL 及其是否正在运行。", + "errDocNotObject": "文档必须是 JSON 对象。", + "errInvalidDocJson": "这不是有效的 JSON。", + "toast": { + "docCreated": "文档已创建", + "docUpdated": "文档已保存", + "docDeleted": "文档已删除", + "createFailed": "创建失败:{message}", + "saveFailed": "保存失败:{message}", + "deleteFailed": "删除失败:{message}" + } } }, "ApiClient": { diff --git a/apps/desktop-ui/src/components/data-explorer/__tests__/elasticsearch-adapter.test.ts b/apps/desktop-ui/src/components/data-explorer/__tests__/elasticsearch-adapter.test.ts new file mode 100644 index 00000000..71943225 --- /dev/null +++ b/apps/desktop-ui/src/components/data-explorer/__tests__/elasticsearch-adapter.test.ts @@ -0,0 +1,159 @@ +// elasticsearch.tsx imports next-intl's useTranslations and (via its pane) +// @/components/ui/resizable — same mocks as the other adapter tests. +jest.mock("next-intl", () => ({ useTranslations: () => (k: string) => k })) +jest.mock("react-resizable-panels", () => ({ + Panel: () => null, + PanelGroup: () => null, + PanelResizeHandle: () => null, +})) + +import { elasticsearchAdapter } from "../adapters/elasticsearch" +import { + authHeader, + mapElasticsearchError, + prepareDocSource, + prepareSearchBody, + sanitizeElasticsearchError, + type ElasticsearchConfig, +} from "@/lib/data-explorer/elasticsearch-api" + +const base: ElasticsearchConfig = { baseUrl: "https://es.example.com:9200", authMode: "none" } + +describe("elasticsearch adapter", () => { + it("starts blank with no auth", () => { + expect(elasticsearchAdapter.blankConfig()).toEqual({ baseUrl: "", authMode: "none" }) + }) + + it("rejects bad configs with the right i18n keys", () => { + expect(elasticsearchAdapter.validate({ baseUrl: "", authMode: "none" })).toBe( + "validation.esUrlRequired", + ) + expect(elasticsearchAdapter.validate({ baseUrl: "ftp://x", authMode: "none" })).toBe( + "validation.esUrlScheme", + ) + expect(elasticsearchAdapter.validate({ baseUrl: "not a url", authMode: "none" })).toBe( + "validation.esUrlInvalid", + ) + expect(elasticsearchAdapter.validate({ ...base, authMode: "basic" })).toBe( + "validation.esUsernameRequired", + ) + expect(elasticsearchAdapter.validate({ ...base, authMode: "apiKey" })).toBe( + "validation.esApiKeyRequired", + ) + expect(elasticsearchAdapter.validate({ ...base, authMode: "bearer" })).toBe( + "validation.esBearerRequired", + ) + }) + + it("accepts valid configs across auth modes", () => { + expect(elasticsearchAdapter.validate(base)).toBeNull() + expect( + elasticsearchAdapter.validate({ ...base, authMode: "basic", username: "elastic", password: "p" }), + ).toBeNull() + expect(elasticsearchAdapter.validate({ ...base, authMode: "apiKey", apiKey: "abc" })).toBeNull() + expect(elasticsearchAdapter.validate({ ...base, authMode: "bearer", bearerToken: "tok" })).toBeNull() + }) + + it("builds the right Authorization header per mode", () => { + expect(authHeader(base)).toBeNull() + expect(authHeader({ ...base, authMode: "basic", username: "elastic", password: "pw" })).toBe( + "Basic " + Buffer.from("elastic:pw").toString("base64"), + ) + expect(authHeader({ ...base, authMode: "apiKey", apiKey: "SGVsbG8=" })).toBe("ApiKey SGVsbG8=") + expect(authHeader({ ...base, authMode: "bearer", bearerToken: "tok" })).toBe("Bearer tok") + }) + + it("maps HTTP status + error type to typed kinds", () => { + expect(mapElasticsearchError(401, {}).kind).toBe("auth") + expect(mapElasticsearchError(403, {}).kind).toBe("forbidden") + expect( + mapElasticsearchError(404, { error: { type: "index_not_found_exception" } }).kind, + ).toBe("notFound") + expect(mapElasticsearchError(409, {}).kind).toBe("conflict") + expect(mapElasticsearchError(400, { error: { type: "parsing_exception" } }).kind).toBe( + "badQuery", + ) + expect(mapElasticsearchError(500, {}).kind).toBe("unknown") + }) + + it("scrubs the Authorization credential from error text", () => { + expect(sanitizeElasticsearchError("failed with Basic ZWxhc3RpYzpwdw== header")).toBe( + "failed with Basic *** header", + ) + expect(sanitizeElasticsearchError("ApiKey SGVsbG8gd29ybGQ= rejected")).toBe( + "ApiKey *** rejected", + ) + }) + + it("wraps Lucene text in query_string and blank in match_all", () => { + const luceneEmpty = prepareSearchBody({ + index: "i", mode: "lucene", queryString: " ", dslText: "", size: 25, from: 0, + }) + expect(luceneEmpty).toEqual({ + body: { query: { match_all: {} }, size: 25, from: 0, track_total_hits: true }, + }) + const lucene = prepareSearchBody({ + index: "i", mode: "lucene", queryString: "status:active", dslText: "", size: 10, from: 5, + }) + expect((lucene as { body: Record }).body.query).toEqual({ + query_string: { query: "status:active" }, + }) + }) + + it("passes DSL through but injects paging when omitted", () => { + const dsl = prepareSearchBody({ + index: "i", mode: "dsl", queryString: "", dslText: '{"query":{"term":{"a":1}}}', size: 25, from: 0, + }) + expect(dsl).toEqual({ + body: { query: { term: { a: 1 } }, size: 25, from: 0, track_total_hits: true }, + }) + // Explicit size/from in the DSL win over the pane controls. + const explicit = prepareSearchBody({ + index: "i", mode: "dsl", queryString: "", dslText: '{"size":3,"from":9}', size: 25, from: 0, + }) + expect((explicit as { body: Record }).body).toMatchObject({ size: 3, from: 9 }) + expect(prepareSearchBody({ + index: "i", mode: "dsl", queryString: "", dslText: "{bad", size: 25, from: 0, + })).toEqual({ error: "invalidJson" }) + expect(prepareSearchBody({ + index: "i", mode: "dsl", queryString: "", dslText: "[1,2]", size: 25, from: 0, + })).toEqual({ error: "notObject" }) + }) + + it("validates document source is a JSON object", () => { + expect(prepareDocSource('{"a":1}')).toEqual({ source: { a: 1 } }) + expect(prepareDocSource("{bad")).toEqual({ error: "invalidJson" }) + expect(prepareDocSource("[1]")).toEqual({ error: "notObject" }) + expect(prepareDocSource("42")).toEqual({ error: "notObject" }) + }) + + // A misspelled key renders as a broken path to the user — assert every + // key the adapter/pane can return resolves in en.json. + it("returns only keys that resolve in messages/en.json", () => { + const messages = require("../../../../messages/en.json") + for (const key of [ + "validation.esUrlRequired", + "validation.esUrlScheme", + "validation.esUrlInvalid", + "validation.esUsernameRequired", + "validation.esApiKeyRequired", + "validation.esBearerRequired", + ]) { + const resolved = key + .split(".") + .reduce((node, part) => (node as Record)?.[part], + messages.DataExplorer) + expect(typeof resolved).toBe("string") + expect(resolved).not.toBe("") + } + }) + + it("identifies itself consistently and satisfies the contract", () => { + expect(elasticsearchAdapter.id).toBe("elasticsearch") + expect(elasticsearchAdapter.label).toBe("Elasticsearch") + expect(typeof elasticsearchAdapter.testConnection).toBe("function") + expect(elasticsearchAdapter.ConnectionForm).toBeTruthy() + expect(elasticsearchAdapter.SidebarTree).toBeTruthy() + expect(elasticsearchAdapter.Pane).toBeTruthy() + }) +}) diff --git a/apps/desktop-ui/src/components/data-explorer/adapters/elasticsearch.tsx b/apps/desktop-ui/src/components/data-explorer/adapters/elasticsearch.tsx new file mode 100644 index 00000000..acf23c4b --- /dev/null +++ b/apps/desktop-ui/src/components/data-explorer/adapters/elasticsearch.tsx @@ -0,0 +1,433 @@ +"use client"; + +import React, { useEffect, useState, type FormEvent } from "react"; +import { useTranslations } from "next-intl"; +import { IconSearch, IconStack2, IconX } from "@tabler/icons-react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Switch } from "@/components/ui/switch"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { cn } from "@/lib/utils"; +import { CONNECTION_COLORS } from "@/components/nosql-explorer/connection-form"; +import { ElasticsearchSearchPane } from "@/components/data-explorer/elasticsearch/search-pane"; +import { + listIndices, + pingCluster, + sanitizeElasticsearchError, + type ElasticsearchAuthMode, + type ElasticsearchConfig, + type IndexInfo, +} from "@/lib/data-explorer/elasticsearch-api"; +import type { ConnectionFormProps, PaneProps, SidebarTreeProps, SourceAdapter } from "../types"; + +export type { ElasticsearchConfig }; + +export interface ElasticsearchTabState { + index: string; + mode: "lucene" | "dsl"; + /** Lucene query_string text (mode === "lucene"). */ + queryString: string; + /** Raw Query DSL body (mode === "dsl"). */ + dslText: string; + size: number; + from: number; + /** Bumped to force a refetch. */ + refreshTick: number; +} + +export function blankTabState(index: string): ElasticsearchTabState { + return { + index, + mode: "lucene", + queryString: "", + dslText: '{\n "query": {\n "match_all": {}\n }\n}', + size: 25, + from: 0, + refreshTick: 0, + }; +} + +function blankConfig(): ElasticsearchConfig { + return { baseUrl: "", authMode: "none" }; +} + +function validate(config: ElasticsearchConfig): string | null { + const url = config.baseUrl.trim(); + if (!url) return "validation.esUrlRequired"; + try { + const parsed = new URL(url); + if (parsed.protocol !== "http:" && parsed.protocol !== "https:") + return "validation.esUrlScheme"; + } catch { + return "validation.esUrlInvalid"; + } + if (config.authMode === "basic" && !config.username?.trim()) return "validation.esUsernameRequired"; + if (config.authMode === "apiKey" && !config.apiKey?.trim()) return "validation.esApiKeyRequired"; + if (config.authMode === "bearer" && !config.bearerToken?.trim()) return "validation.esBearerRequired"; + return null; +} + +/** Cheap authed cluster-info call: surfaces a bad URL, wrong creds, or an + * unreachable/self-signed-TLS host before anything is saved. */ +async function testConnection(config: ElasticsearchConfig): Promise { + try { + await pingCluster(config); + } catch (err) { + throw new Error(sanitizeElasticsearchError(err instanceof Error ? err.message : String(err))); + } +} + +/* ------------------------------------------------------------------ form */ + +const AUTH_MODES: ElasticsearchAuthMode[] = ["none", "basic", "apiKey", "bearer"]; + +function ElasticsearchConnectionForm({ + initial, + saving, + error, + onTest, + testState, + onSubmit, + onCancel, +}: ConnectionFormProps) { + const t = useTranslations("DataExplorer.connectionDialog"); + const te = useTranslations("DataExplorer.elasticsearch"); + const [name, setName] = useState(initial.name); + const [folder, setFolder] = useState(initial.folder ?? ""); + const [color, setColor] = useState(initial.color ?? null); + const [readOnly, setReadOnly] = useState(initial.readOnly ?? false); + const [baseUrl, setBaseUrl] = useState(initial.config.baseUrl); + const [authMode, setAuthMode] = useState(initial.config.authMode); + const [username, setUsername] = useState(initial.config.username ?? ""); + const [password, setPassword] = useState(initial.config.password ?? ""); + const [apiKey, setApiKey] = useState(initial.config.apiKey ?? ""); + const [bearerToken, setBearerToken] = useState(initial.config.bearerToken ?? ""); + + function currentConfig(): ElasticsearchConfig { + return { + baseUrl: baseUrl.trim(), + authMode, + username: authMode === "basic" ? username : undefined, + password: authMode === "basic" ? password : undefined, + apiKey: authMode === "apiKey" ? apiKey : undefined, + bearerToken: authMode === "bearer" ? bearerToken : undefined, + }; + } + + function handleSubmit(e: FormEvent) { + e.preventDefault(); + onSubmit({ name, folder, color, readOnly, config: currentConfig() }); + } + + return ( +
+
+ + setName(e.target.value)} + placeholder={t("namePlaceholder")} + disabled={saving} + /> +
+ +
+ + setFolder(e.target.value)} + placeholder={t("folderPlaceholder")} + disabled={saving} + /> +
+ +
+ + setBaseUrl(e.target.value)} + placeholder={te("clusterUrlPlaceholder")} + disabled={saving} + className="font-mono text-sm" + /> +

{te("clusterUrlHint")}

+
+ +
+ + +
+ + {authMode === "basic" && ( +
+
+ + setUsername(e.target.value)} + disabled={saving} + className="h-8 font-mono text-xs" + placeholder="elastic" + /> +
+
+ + setPassword(e.target.value)} + disabled={saving} + className="h-8 font-mono text-xs" + /> +
+
+ )} + + {authMode === "apiKey" && ( +
+ + setApiKey(e.target.value)} + disabled={saving} + className="h-8 font-mono text-xs" + /> +

{te("apiKeyHint")}

+
+ )} + + {authMode === "bearer" && ( +
+ + setBearerToken(e.target.value)} + disabled={saving} + className="h-8 font-mono text-xs" + /> +
+ )} + +
+ +
+ + {CONNECTION_COLORS.map((c) => ( +
+
+ +
+
+ +

{t("readOnlyHint")}

+
+ +
+ + {error && ( +
+ {error} +
+ )} + {testState === "ok" && !error && ( +
+ {t("testOk")} +
+ )} + +
+ + + +
+
+ ); +} + +/* ------------------------------------------------------------------ tree */ + +interface IndexRowProps { + info: IndexInfo; + onOpen: (index: string) => void; +} + +const IndexRow = React.memo(function IndexRow({ info, onOpen }: IndexRowProps) { + return ( + + ); +}); + +function ElasticsearchSidebarTree({ + connection, + config, + openTab, + searchQuery, +}: SidebarTreeProps) { + const t = useTranslations("DataExplorer.elasticsearch"); + const [indices, setIndices] = useState(null); + const [error, setError] = useState(null); + + useEffect(() => { + let cancelled = false; + const load = async () => { + try { + const list = await listIndices(config); + if (!cancelled) setIndices(list); + } catch (err) { + if (!cancelled) + setError( + sanitizeElasticsearchError(err instanceof Error ? err.message : String(err)), + ); + } + }; + void load(); + return () => { + cancelled = true; + }; + // Refetch when the connection's config changes (e.g. edited URL/creds). + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [config.baseUrl, config.authMode, config.username, config.password, config.apiKey, config.bearerToken]); + + const openIndex = React.useCallback( + (index: string) => { + openTab({ + key: index, + title: index, + subtitle: connection.name, + state: blankTabState(index), + }); + }, + [openTab, connection.name], + ); + + if (error) { + return

{error}

; + } + if (indices === null) { + return

; + } + if (indices.length === 0) { + return

{t("noIndices")}

; + } + + // Same search rule as the other trees: a connection whose own name matches + // shows everything; otherwise rows filter on the index name. + const q = searchQuery.trim().toLowerCase(); + const showAll = !q || connection.name.toLowerCase().includes(q); + const rows = indices.filter((info) => showAll || info.index.toLowerCase().includes(q)); + + if (rows.length === 0) { + return

{t("noMatches")}

; + } + + return ( +
+ {rows.map((info) => ( + + ))} +
+ ); +} + +/* ------------------------------------------------------------------ pane */ + +function ElasticsearchPane(props: PaneProps) { + return ; +} + +export const elasticsearchAdapter: SourceAdapter = { + id: "elasticsearch", + label: "Elasticsearch", + icon: IconSearch, + accent: "text-teal-500", + blankConfig, + validate, + testConnection, + ConnectionForm: ElasticsearchConnectionForm, + SidebarTree: ElasticsearchSidebarTree, + Pane: ElasticsearchPane, +}; diff --git a/apps/desktop-ui/src/components/data-explorer/elasticsearch/search-pane.tsx b/apps/desktop-ui/src/components/data-explorer/elasticsearch/search-pane.tsx new file mode 100644 index 00000000..344ff745 --- /dev/null +++ b/apps/desktop-ui/src/components/data-explorer/elasticsearch/search-pane.tsx @@ -0,0 +1,563 @@ +"use client"; + +import React, { useCallback, useEffect, useState } from "react"; +import { useTranslations } from "next-intl"; +import { toast } from "sonner"; +import { IconPencil, IconPlus, IconRefresh, IconTrash } from "@tabler/icons-react"; +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, +} from "@/components/ui/alert-dialog"; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Textarea } from "@/components/ui/textarea"; +import { + ResizableHandle, + ResizablePanel, + ResizablePanelGroup, +} from "@/components/ui/resizable"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { cn } from "@/lib/utils"; +import { + ElasticsearchApiError, + deleteDoc, + indexDoc, + prepareDocSource, + prepareSearchBody, + sanitizeElasticsearchError, + search, + type DocWriteError, + type ElasticsearchConfig, + type EsHit, + type SearchPrepError, +} from "@/lib/data-explorer/elasticsearch-api"; +import type { PaneProps } from "../types"; +import type { ElasticsearchTabState } from "../adapters/elasticsearch"; + +const PAGE_SIZES = [10, 25, 50, 100]; + +/** Translated banner text for an ElasticsearchApiError; falls back to its sanitized message. */ +function useErrorText() { + const t = useTranslations("DataExplorer.elasticsearch"); + return useCallback( + (err: unknown): string => { + if (err instanceof ElasticsearchApiError) { + switch (err.kind) { + case "auth": + return t("errAuth"); + case "forbidden": + return t("errForbidden"); + case "notFound": + return t("errNotFound"); + case "badQuery": + return t("errBadQuery"); + case "conflict": + return t("errConflict"); + case "network": + return t("errNetwork"); + } + } + return sanitizeElasticsearchError(err instanceof Error ? err.message : String(err)); + }, + [t], + ); +} + +export function ElasticsearchSearchPane({ + connection, + config, + state, + setState, +}: PaneProps) { + const t = useTranslations("DataExplorer.elasticsearch"); + const errorText = useErrorText(); + const readOnly = !!connection.readOnly; + + const [hits, setHits] = useState([]); + const [total, setTotal] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [selected, setSelected] = useState(null); + + // Draft query controls; Run copies them into tab state (persisted). + const [draftQueryString, setDraftQueryString] = useState(state.queryString); + const [draftDsl, setDraftDsl] = useState(state.dslText); + + const load = useCallback(async () => { + setLoading(true); + setError(null); + const prepared = prepareSearchBody({ + index: state.index, + mode: state.mode, + queryString: state.queryString, + dslText: state.dslText, + size: state.size, + from: state.from, + }); + if ("error" in prepared) { + setError( + new ElasticsearchApiError( + "badQuery", + prepared.error === "notObject" ? "query body must be an object" : "invalid query JSON", + ), + ); + setHits([]); + setTotal(null); + setLoading(false); + return; + } + try { + const out = await search(config, state.index, prepared.body); + setHits(out.hits); + setTotal(out.total); + } catch (err) { + setError(err); + setHits([]); + setTotal(null); + } finally { + setLoading(false); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + config.baseUrl, + config.authMode, + config.username, + config.password, + config.apiKey, + config.bearerToken, + state.index, + state.mode, + state.queryString, + state.dslText, + state.size, + state.from, + ]); + + useEffect(() => { + setSelected(null); + void load(); + }, [load, state.refreshTick]); + + const runQuery = () => + setState((prev) => ({ + ...prev, + queryString: draftQueryString, + dslText: draftDsl, + from: 0, + })); + + const setMode = (mode: "lucene" | "dsl") => setState((prev) => ({ ...prev, mode, from: 0 })); + + const goNext = () => setState((prev) => ({ ...prev, from: prev.from + prev.size })); + const goPrev = () => + setState((prev) => ({ ...prev, from: Math.max(0, prev.from - prev.size) })); + + // ------------------------------------------------------------- writes + const [editing, setEditing] = useState(false); + const [editText, setEditText] = useState(""); + const [newDocOpen, setNewDocOpen] = useState(false); + const [newDocId, setNewDocId] = useState(""); + const [newDocText, setNewDocText] = useState("{\n}"); + const [deleteOpen, setDeleteOpen] = useState(false); + const [mutating, setMutating] = useState(false); + + const writeErrorText = (code: DocWriteError | SearchPrepError): string => + code === "notObject" ? t("errDocNotObject") : t("errInvalidDocJson"); + + const mutationMessage = (err: unknown): string => + err instanceof ElasticsearchApiError + ? errorText(err) + : sanitizeElasticsearchError(err instanceof Error ? err.message : String(err)); + + async function saveEdit() { + if (readOnly || !selected) return; + const prepared = prepareDocSource(editText); + if ("error" in prepared) { + toast.error(writeErrorText(prepared.error)); + return; + } + setMutating(true); + try { + await indexDoc(config, selected._index, selected._id, prepared.source); + const updated = { ...selected, _source: prepared.source }; + setSelected(updated); + setHits((prev) => prev.map((h) => (h._id === updated._id ? updated : h))); + setEditing(false); + toast.success(t("toast.docUpdated")); + } catch (err) { + toast.error(t("toast.saveFailed", { message: mutationMessage(err) })); + } finally { + setMutating(false); + } + } + + async function createDoc() { + if (readOnly) return; + const prepared = prepareDocSource(newDocText); + if ("error" in prepared) { + toast.error(writeErrorText(prepared.error)); + return; + } + setMutating(true); + try { + await indexDoc(config, state.index, newDocId.trim() || undefined, prepared.source); + setNewDocOpen(false); + setNewDocId(""); + setNewDocText("{\n}"); + toast.success(t("toast.docCreated")); + setState((prev) => ({ ...prev, refreshTick: prev.refreshTick + 1 })); + } catch (err) { + toast.error(t("toast.createFailed", { message: mutationMessage(err) })); + } finally { + setMutating(false); + } + } + + async function confirmDelete() { + if (readOnly || !selected) return; + setMutating(true); + try { + await deleteDoc(config, selected._index, selected._id); + setHits((prev) => prev.filter((h) => h._id !== selected._id)); + setSelected(null); + setDeleteOpen(false); + toast.success(t("toast.docDeleted")); + } catch (err) { + toast.error(t("toast.deleteFailed", { message: mutationMessage(err) })); + } finally { + setMutating(false); + } + } + + const banner = error ? errorText(error) : null; + const page = Math.floor(state.from / state.size) + 1; + + return ( +
+ {/* Query toolbar */} +
+ + {state.mode === "lucene" ? ( + setDraftQueryString(e.target.value)} + onKeyDown={(e) => { + if (e.key === "Enter") runQuery(); + }} + placeholder={t("lucenePlaceholder")} + className="h-7 min-w-0 flex-1 font-mono text-xs" + /> + ) : ( + + {t("dslBelow")} + + )} + + + + {!readOnly && ( + + )} +
+ + {state.mode === "dsl" && ( +
+