diff --git a/app/src/main/java/com/dano/test1/DatabaseButtonHandler.kt b/app/src/main/java/com/dano/test1/DatabaseButtonHandler.kt index a19e341..ce50a2b 100644 --- a/app/src/main/java/com/dano/test1/DatabaseButtonHandler.kt +++ b/app/src/main/java/com/dano/test1/DatabaseButtonHandler.kt @@ -23,7 +23,8 @@ class DatabaseButtonHandler( private val exporter = ExcelExportService(activity, headerRepo) fun setup() { - databaseButton.text = "Datenbank" + val lang = safeLang() + databaseButton.text = t(lang, "database") ?: "Datenbank" databaseButton.setOnClickListener { openDatabaseScreen() } } @@ -82,13 +83,13 @@ class DatabaseButtonHandler( // Export: Header aller Clients als Excel // --------------------------- private fun onDownloadHeadersClicked(progress: ProgressBar) { + val lang = safeLang() uiScope.launch { try { progress.visibility = View.VISIBLE val savedUri = exporter.exportHeadersForAllClients() progress.visibility = View.GONE - val lang = safeLang() if (savedUri != null) { Toast.makeText( activity, @@ -101,7 +102,8 @@ class DatabaseButtonHandler( } catch (e: Exception) { progress.visibility = View.GONE Log.e(tag, "Download Header Fehler: ${e.message}", e) - Toast.makeText(activity, "Fehler: ${e.message}", Toast.LENGTH_LONG).show() + val prefix = t(lang, "error") ?: "Fehler" + Toast.makeText(activity, "$prefix: ${e.message}", Toast.LENGTH_LONG).show() } } } @@ -124,7 +126,7 @@ class DatabaseButtonHandler( val tableOrdered: TableLayout = requireView(R.id.tableOrdered, "tableOrdered") title.text = "${t(lang, "client") ?: "Client"}: $clientCode – ${t(lang, "questionnaires") ?: "Fragebögen"}" - headerLabel.text = t(lang, "headers") ?: "header" + headerLabel.text = t(lang, "headers") ?: "Header" backButton.text = t(lang, "previous") ?: "Zurück" backButton.setOnClickListener { openDatabaseScreen() } @@ -418,9 +420,11 @@ class DatabaseButtonHandler( private fun requireView(id: Int, name: String): T { val v = activity.findViewById(id) if (v == null) { - val msg = "View with id '$name' not found in current layout." + val lang = safeLang() + val prefix = t(lang, "view_missing") ?: "Fehlende View: %s" + val msg = prefix.replace("%s", name) Log.e(tag, msg) - Toast.makeText(activity, "Fehlende View: $name", Toast.LENGTH_LONG).show() + Toast.makeText(activity, msg, Toast.LENGTH_LONG).show() throw IllegalStateException(msg) } return v diff --git a/app/src/main/java/com/dano/test1/EditButtonHandler.kt b/app/src/main/java/com/dano/test1/EditButtonHandler.kt index bae1d08..f0fa422 100644 --- a/app/src/main/java/com/dano/test1/EditButtonHandler.kt +++ b/app/src/main/java/com/dano/test1/EditButtonHandler.kt @@ -42,8 +42,7 @@ class EditButtonHandler( val needLoad = GlobalValues.LOADED_CLIENT_CODE?.equals(desiredCode) != true if (needLoad) { - // Zwischenzustände aus dem Load-Handler unterdrücken - setUiFreeze(true) + setUiFreeze(true) // Zwischenzustände unterdrücken triggerLoad() } @@ -51,7 +50,8 @@ class EditButtonHandler( val loadedOk = waitUntilClientLoaded(desiredCode, timeoutMs = 2500, stepMs = 50) if (!loadedOk) { withContext(Dispatchers.Main) { - Toast.makeText(activity, "Bitte den Klienten über \"Laden\" öffnen.", Toast.LENGTH_LONG).show() + val msg = LanguageManager.getText(languageIDProvider(), "open_client_via_load") + Toast.makeText(activity, msg, Toast.LENGTH_LONG).show() setUiFreeze(false) } return@launch @@ -70,7 +70,6 @@ class EditButtonHandler( } withContext(Dispatchers.Main) { - // nur den finalen Zustand anzeigen updateButtonTexts() val enabledButtons = questionnaireFiles.filter { (_, fileName) -> completedFiles.any { completedId -> fileName.lowercase().contains(completedId) } diff --git a/app/src/main/java/com/dano/test1/HandlerOpeningScreen.kt b/app/src/main/java/com/dano/test1/HandlerOpeningScreen.kt index 64797c7..5d1488b 100644 --- a/app/src/main/java/com/dano/test1/HandlerOpeningScreen.kt +++ b/app/src/main/java/com/dano/test1/HandlerOpeningScreen.kt @@ -240,7 +240,10 @@ class HandlerOpeningScreen(private val activity: MainActivity) { dynamicButtons.add(btn) questionnaireFiles[btn] = entry.file cardParts[btn] = CardParts(tvTitle, tvSubtitle, chip) - tvTitle.text = "Questionnaire ${index + 1}" + + // Fallback-Titel lokalisieren + tvTitle.text = "${t("questionnaire")} ${index + 1}" + if (entry.condition is QuestionItem.Condition.AlwaysAvailable) startEnabled.add(btn) } applyUpdateButtonTexts(force = false) @@ -260,7 +263,6 @@ class HandlerOpeningScreen(private val activity: MainActivity) { } } - private fun setupLanguageSpinner() { val languages = listOf("GERMAN", "ENGLISH", "FRENCH", "ROMANIAN", "ARABIC", "POLISH", "TURKISH", "UKRAINIAN", "RUSSIAN", "SPANISH") val adapter = ArrayAdapter(activity, android.R.layout.simple_spinner_item, languages).apply { @@ -437,7 +439,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) { uploadButton.setOnClickListener { val token = TokenStore.getToken(activity) if (token.isNullOrBlank()) { - Toast.makeText(activity, t("login_required") ?: "Bitte zuerst einloggen", Toast.LENGTH_LONG).show() + Toast.makeText(activity, t("login_required"), Toast.LENGTH_LONG).show() return@setOnClickListener } GlobalValues.LAST_CLIENT_CODE = editText.text.toString().trim() @@ -448,7 +450,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) { private fun setupDownloadButton() { downloadButton.text = t("download") downloadButton.setOnClickListener { - Toast.makeText(activity, t("login_required") ?: "Bitte zuerst einloggen", Toast.LENGTH_SHORT).show() + Toast.makeText(activity, t("login_required"), Toast.LENGTH_SHORT).show() } } @@ -540,9 +542,14 @@ class HandlerOpeningScreen(private val activity: MainActivity) { val ageMs = if (ts > 0L) (System.currentTimeMillis() - ts) else 0L val h = TimeUnit.MILLISECONDS.toHours(ageMs) val m = TimeUnit.MILLISECONDS.toMinutes(ageMs) - h * 60 - statusSession.text = if (ts > 0L) "Session: ${h}h ${m}m" else "Session: —" + // Sitzungstext lokalisieren + if (ts > 0L) { + statusSession.text = "${t("session_label")}: ${h}${t("hours_short")} ${m}${t("minutes_short")}" + } else { + statusSession.text = t("session_dash") + } val online = NetworkUtils.isOnline(activity) - statusOnline.text = if (online) "Online" else "Offline" + statusOnline.text = if (online) t("online") else t("offline") statusOnline.setTextColor(if (online) Color.parseColor("#2E7D32") else Color.parseColor("#C62828")) } @@ -562,7 +569,4 @@ class HandlerOpeningScreen(private val activity: MainActivity) { coachEditText.compoundDrawablePadding = dp(8) coachEditText.alpha = 0.95f } - - - } diff --git a/app/src/main/java/com/dano/test1/HeaderOrderRepository.kt b/app/src/main/java/com/dano/test1/HeaderOrderRepository.kt index 9253596..a2b197b 100644 --- a/app/src/main/java/com/dano/test1/HeaderOrderRepository.kt +++ b/app/src/main/java/com/dano/test1/HeaderOrderRepository.kt @@ -7,11 +7,17 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook import org.json.JSONArray import java.nio.charset.Charset -class HeaderOrderRepository(private val context: Context) { +class HeaderOrderRepository( + private val context: Context, + // Sprache abrufen (Standard: Deutsch, damit es ohne OpeningScreen schon sinnvoll ist) + private val languageIDProvider: () -> String = { "GERMAN" } +) { private val tag = "HeaderOrderRepository" private var orderedIdsCache: List? = null + private fun t(key: String): String = LanguageManager.getText(languageIDProvider(), key) + fun loadOrderedIds(): List { orderedIdsCache?.let { return it } @@ -33,7 +39,7 @@ class HeaderOrderRepository(private val context: Context) { list } catch (e: Exception) { Log.e(tag, "Weder header_order.xlsx noch header_order.json verfügbar/gültig: ${e.message}") - Toast.makeText(context, "Keine Header-Vorlage gefunden", Toast.LENGTH_LONG).show() + Toast.makeText(context, t("no_header_template_found"), Toast.LENGTH_LONG).show() emptyList() } } diff --git a/app/src/main/java/com/dano/test1/LanguageManager.kt b/app/src/main/java/com/dano/test1/LanguageManager.kt index e9e0a44..6541f2e 100644 --- a/app/src/main/java/com/dano/test1/LanguageManager.kt +++ b/app/src/main/java/com/dano/test1/LanguageManager.kt @@ -354,7 +354,53 @@ object LanguageManager { "error_generic" to "Fehler", "not_done" to "Nicht Fertog", "none" to "Keine Angabe", - "points" to "Punkte" + "points" to "Punkte", + "saved_pdf_csv" to "PDF und CSV wurden im Ordner \"Downloads\" gespeichert.", + "no_pdf_viewer" to "Kein PDF-Viewer installiert.", + "save_error" to "Fehler beim Speichern: {message}", + "login_required_title" to "Login erforderlich", + "username_hint" to "Benutzername", + "password_hint" to "Passwort", + "login_btn" to "Login", + "exit_btn" to "Beenden", + "please_username_password" to "Bitte Benutzername und Passwort eingeben.", + "download_failed_no_local_db" to "Download fehlgeschlagen – keine lokale Datenbank vorhanden", + "download_failed_use_offline" to "Download fehlgeschlagen – arbeite offline mit vorhandener Datenbank", + "login_failed_with_reason" to "Login fehlgeschlagen: {reason}", + "no_header_template_found" to "Keine Header-Vorlage gefunden", + "login_required" to "Bitte zuerst einloggen", + "questionnaire" to "Fragebogen", + "session_label" to "Sitzung", + "session_dash" to "Sitzung: —", + "hours_short" to "h", + "minutes_short" to "m", + "online" to "Online", + "offline" to "Offline", + "open_client_via_load" to "Bitte den Klienten über „Laden“ öffnen.", + "database" to "Datenbank", + "database_clients_title" to "Datenbank – Clients", + "no_clients_available" to "Keine Clients vorhanden.", + "previous" to "Zurück", + "download_header" to "Header herunterladen", + "client_code" to "Client-Code", + "export_success_downloads" to "Export erfolgreich: Downloads/ClientHeaders.xlsx", + "export_failed" to "Export fehlgeschlagen.", + "error" to "Fehler", + "client" to "Client", + "questionnaires" to "Fragebögen", + "headers" to "Header", + "questionnaire_id" to "Fragebogen-ID", + "status" to "Status", + "id" to "ID", + "value" to "Wert", + "no_questionnaires" to "Keine Fragebögen vorhanden.", + "no_questions_available" to "Keine Fragen vorhanden.", + "question" to "Frage", + "answer" to "Antwort", + "done" to "Erledigt", + "not_done" to "Nicht erledigt", + "none" to "Keine", + "view_missing" to "Fehlende View: %s" ), "ENGLISH" to mapOf( @@ -679,7 +725,53 @@ object LanguageManager { "done" to "Done", "locked" to "Locked", "start" to "Start", - "points" to "Points" + "points" to "Points", + "saved_pdf_csv" to "PDF and CSV were saved in the \"Downloads\" folder.", + "no_pdf_viewer" to "No PDF viewer installed.", + "save_error" to "Error while saving: {message}", + "login_required_title" to "Login required", + "username_hint" to "Username", + "password_hint" to "Password", + "login_btn" to "Login", + "exit_btn" to "Exit", + "please_username_password" to "Please enter username and password.", + "download_failed_no_local_db" to "Download failed – no local database available", + "download_failed_use_offline" to "Download failed – working offline with existing database", + "login_failed_with_reason" to "Login failed: {reason}", + "no_header_template_found" to "No header template found", + "login_required" to "Please log in first", + "questionnaire" to "Questionnaire", + "session_label" to "Session", + "session_dash" to "Session: —", + "hours_short" to "h", + "minutes_short" to "min", + "online" to "Online", + "offline" to "Offline", + "open_client_via_load" to "Please open the client via \"Load\".", + "database" to "Database", + "database_clients_title" to "Database – Clients", + "no_clients_available" to "No clients available.", + "previous" to "Back", + "download_header" to "Download header", + "client_code" to "Client code", + "export_success_downloads" to "Export successful: Downloads/ClientHeaders.xlsx", + "export_failed" to "Export failed.", + "error" to "Error", + "client" to "Client", + "questionnaires" to "Questionnaires", + "headers" to "Headers", + "questionnaire_id" to "Questionnaire ID", + "status" to "Status", + "id" to "ID", + "value" to "Value", + "no_questionnaires" to "No questionnaires available.", + "no_questions_available" to "No questions available.", + "question" to "Question", + "answer" to "Answer", + "done" to "Done", + "not_done" to "Not done", + "none" to "None", + "view_missing" to "Missing view: %s" ), "FRENCH" to mapOf( @@ -1008,7 +1100,53 @@ object LanguageManager { "done" to "Terminé", "locked" to "Verrouillé", "start" to "Commencer", - "points" to "Points" + "points" to "Points", + "saved_pdf_csv" to "Les PDF et CSV ont été enregistrés dans le dossier \"Téléchargements\".", + "no_pdf_viewer" to "Aucun lecteur PDF installé.", + "save_error" to "Erreur lors de l’enregistrement : {message}", + "login_required_title" to "Connexion requise", + "username_hint" to "Nom d’utilisateur", + "password_hint" to "Mot de passe", + "login_btn" to "Se connecter", + "exit_btn" to "Quitter", + "please_username_password" to "Veuillez saisir le nom d’utilisateur et le mot de passe.", + "download_failed_no_local_db" to "Échec du téléchargement – aucune base de données locale disponible", + "download_failed_use_offline" to "Échec du téléchargement – travaillez hors ligne avec la base de données existante", + "login_failed_with_reason" to "Échec de la connexion : {reason}", + "no_header_template_found" to "Aucun modèle d’en-tête trouvé", + "login_required" to "Veuillez d’abord vous connecter", + "questionnaire" to "Questionnaire", + "session_label" to "Session", + "session_dash" to "Session : —", + "hours_short" to "h", + "minutes_short" to "min", + "online" to "En ligne", + "offline" to "Hors ligne", + "open_client_via_load" to "Veuillez ouvrir le client via « Charger ».", + "database" to "Base de données", + "database_clients_title" to "Base de données – Clients", + "no_clients_available" to "Aucun client disponible.", + "previous" to "Retour", + "download_header" to "Télécharger l’en-tête", + "client_code" to "Code client", + "export_success_downloads" to "Export réussi : Téléchargements/ClientHeaders.xlsx", + "export_failed" to "Échec de l’exportation.", + "error" to "Erreur", + "client" to "Client", + "questionnaires" to "Questionnaires", + "headers" to "En-têtes", + "questionnaire_id" to "ID du questionnaire", + "status" to "Statut", + "id" to "ID", + "value" to "Valeur", + "no_questionnaires" to "Aucun questionnaire disponible.", + "no_questions_available" to "Aucune question disponible.", + "question" to "Question", + "answer" to "Réponse", + "done" to "Terminé", + "not_done" to "Non terminé", + "none" to "Aucun", + "view_missing" to "Vue manquante : %s" ), "RUSSIAN" to mapOf( @@ -1333,7 +1471,53 @@ object LanguageManager { "done" to "Готово", "locked" to "Заблокировано", "start" to "Начать", - "points" to "Баллы" + "points" to "Баллы", + "saved_pdf_csv" to "PDF и CSV сохранены в папке «Загрузки».", + "no_pdf_viewer" to "Не установлен просмотрщик PDF.", + "save_error" to "Ошибка при сохранении: {message}", + "login_required_title" to "Требуется вход", + "username_hint" to "Имя пользователя", + "password_hint" to "Пароль", + "login_btn" to "Войти", + "exit_btn" to "Выход", + "please_username_password" to "Введите имя пользователя и пароль.", + "download_failed_no_local_db" to "Сбой загрузки – локальная база данных отсутствует", + "download_failed_use_offline" to "Сбой загрузки – работа офлайн с имеющейся базой данных", + "login_failed_with_reason" to "Не удалось войти: {reason}", + "no_header_template_found" to "Шаблон заголовков не найден", + "login_required" to "Сначала выполните вход", + "questionnaire" to "Опросник", + "session_label" to "Сессия", + "session_dash" to "Сессия: —", + "hours_short" to "ч", + "minutes_short" to "м", + "online" to "В сети", + "offline" to "Не в сети", + "open_client_via_load" to "Откройте клиента через «Загрузить».", + "database" to "База данных", + "database_clients_title" to "База данных – клиенты", + "no_clients_available" to "Клиенты отсутствуют.", + "previous" to "Назад", + "download_header" to "Скачать заголовки", + "client_code" to "Код клиента", + "export_success_downloads" to "Экспорт выполнен: Загрузки/ClientHeaders.xlsx", + "export_failed" to "Ошибка экспорта.", + "error" to "Ошибка", + "client" to "Клиент", + "questionnaires" to "Опросники", + "headers" to "Заголовки", + "questionnaire_id" to "ID опросника", + "status" to "Статус", + "id" to "ID", + "value" to "Значение", + "no_questionnaires" to "Нет доступных опросников.", + "no_questions_available" to "Нет вопросов.", + "question" to "Вопрос", + "answer" to "Ответ", + "done" to "Готово", + "not_done" to "Не выполнено", + "none" to "Нет", + "view_missing" to "Отсутствует представление: %s" ), "UKRAINIAN" to mapOf( @@ -1662,7 +1846,53 @@ object LanguageManager { "done" to "Завершено", "locked" to "Заблоковано", "start" to "Почати", - "points" to "Бали" + "points" to "Бали", + "saved_pdf_csv" to "PDF і CSV збережено в папці «Завантаження».", + "no_pdf_viewer" to "Не встановлено переглядач PDF.", + "save_error" to "Помилка збереження: {message}", + "login_required_title" to "Потрібен вхід", + "username_hint" to "Ім’я користувача", + "password_hint" to "Пароль", + "login_btn" to "Увійти", + "exit_btn" to "Вийти", + "please_username_password" to "Введіть ім’я користувача та пароль.", + "download_failed_no_local_db" to "Завантаження не вдалося — немає локальної бази даних", + "download_failed_use_offline" to "Завантаження не вдалося — працюйте офлайн з наявною базою даних", + "login_failed_with_reason" to "Не вдалося увійти: {reason}", + "no_header_template_found" to "Шаблон заголовків не знайдено", + "login_required" to "Спочатку увійдіть", + "questionnaire" to "Анкета", + "session_label" to "Сесія", + "session_dash" to "Сесія: —", + "hours_short" to "год", + "minutes_short" to "хв", + "online" to "Онлайн", + "offline" to "Офлайн", + "open_client_via_load" to "Відкрийте клієнта через «Завантажити».", + "database" to "База даних", + "database_clients_title" to "База даних – клієнти", + "no_clients_available" to "Немає клієнтів.", + "previous" to "Назад", + "download_header" to "Завантажити заголовки", + "client_code" to "Код клієнта", + "export_success_downloads" to "Експорт виконано: Завантаження/ClientHeaders.xlsx", + "export_failed" to "Помилка експорту.", + "error" to "Помилка", + "client" to "Клієнт", + "questionnaires" to "Анкети", + "headers" to "Заголовки", + "questionnaire_id" to "ID анкети", + "status" to "Статус", + "id" to "ID", + "value" to "Значення", + "no_questionnaires" to "Немає доступних анкет.", + "no_questions_available" to "Немає запитань.", + "question" to "Питання", + "answer" to "Відповідь", + "done" to "Готово", + "not_done" to "Не виконано", + "none" to "Немає", + "view_missing" to "Відсутній елемент інтерфейсу: %s" ), "TURKISH" to mapOf( @@ -1991,7 +2221,53 @@ object LanguageManager { "done" to "Tamamlandı", "locked" to "Kilitli", "start" to "Başlat", - "points" to "Puan" + "points" to "Puan", + "saved_pdf_csv" to "PDF ve CSV \"İndirilenler\" klasörüne kaydedildi.", + "no_pdf_viewer" to "Yüklü bir PDF görüntüleyici yok.", + "save_error" to "Kaydetme hatası: {message}", + "login_required_title" to "Giriş gerekli", + "username_hint" to "Kullanıcı adı", + "password_hint" to "Şifre", + "login_btn" to "Giriş yap", + "exit_btn" to "Çıkış", + "please_username_password" to "Lütfen kullanıcı adı ve şifre girin.", + "download_failed_no_local_db" to "İndirme başarısız – yerel veritabanı yok", + "download_failed_use_offline" to "İndirme başarısız – mevcut veritabanıyla çevrimdışı çalışın", + "login_failed_with_reason" to "Giriş başarısız: {reason}", + "no_header_template_found" to "Başlık şablonu bulunamadı", + "login_required" to "Lütfen önce giriş yapın", + "questionnaire" to "Anket", + "session_label" to "Oturum", + "session_dash" to "Oturum: —", + "hours_short" to "sa", + "minutes_short" to "dk", + "online" to "Çevrimiçi", + "offline" to "Çevrimdışı", + "open_client_via_load" to "Lütfen müşteriyi \"Yükle\" ile açın.", + "database" to "Veritabanı", + "database_clients_title" to "Veritabanı – Müşteriler", + "no_clients_available" to "Kullanılabilir müşteri yok.", + "previous" to "Geri", + "download_header" to "Başlığı indir", + "client_code" to "Müşteri kodu", + "export_success_downloads" to "Dışa aktarma başarılı: İndirilenler/ClientHeaders.xlsx", + "export_failed" to "Dışa aktarma başarısız.", + "error" to "Hata", + "client" to "Müşteri", + "questionnaires" to "Anketler", + "headers" to "Başlıklar", + "questionnaire_id" to "Anket ID", + "status" to "Durum", + "id" to "ID", + "value" to "Değer", + "no_questionnaires" to "Mevcut anket yok.", + "no_questions_available" to "Soru yok.", + "question" to "Soru", + "answer" to "Cevap", + "done" to "Tamamlandı", + "not_done" to "Tamamlanmadı", + "none" to "Yok", + "view_missing" to "Eksik görünüm: %s" ), "POLISH" to mapOf( @@ -2320,7 +2596,53 @@ object LanguageManager { "done" to "Gotowe", "locked" to "Zablokowane", "start" to "Rozpocznij", - "points" to "Punkty" + "points" to "Punkty", + "saved_pdf_csv" to "Pliki PDF i CSV zapisano w folderze \"Pobrane\".", + "no_pdf_viewer" to "Brak zainstalowanej przeglądarki PDF.", + "save_error" to "Błąd zapisu: {message}", + "login_required_title" to "Wymagane logowanie", + "username_hint" to "Nazwa użytkownika", + "password_hint" to "Hasło", + "login_btn" to "Zaloguj", + "exit_btn" to "Zakończ", + "please_username_password" to "Wprowadź nazwę użytkownika i hasło.", + "download_failed_no_local_db" to "Pobieranie nieudane – brak lokalnej bazy danych", + "download_failed_use_offline" to "Pobieranie nieudane – pracuj offline z istniejącą bazą danych", + "login_failed_with_reason" to "Logowanie nie powiodło się: {reason}", + "no_header_template_found" to "Nie znaleziono szablonu nagłówków", + "login_required" to "Najpierw się zaloguj", + "questionnaire" to "Kwestionariusz", + "session_label" to "Sesja", + "session_dash" to "Sesja: —", + "hours_short" to "h", + "minutes_short" to "min", + "online" to "Online", + "offline" to "Offline", + "open_client_via_load" to "Otwórz klienta przez „Wczytaj”.", + "database" to "Baza danych", + "database_clients_title" to "Baza danych – Klienci", + "no_clients_available" to "Brak dostępnych klientów.", + "previous" to "Wstecz", + "download_header" to "Pobierz nagłówki", + "client_code" to "Kod klienta", + "export_success_downloads" to "Eksport zakończony: Pobrane/ClientHeaders.xlsx", + "export_failed" to "Eksport nieudany.", + "error" to "Błąd", + "client" to "Klient", + "questionnaires" to "Kwestionariusze", + "headers" to "Nagłówki", + "questionnaire_id" to "ID kwestionariusza", + "status" to "Status", + "id" to "ID", + "value" to "Wartość", + "no_questionnaires" to "Brak dostępnych kwestionariuszy.", + "no_questions_available" to "Brak pytań.", + "question" to "Pytanie", + "answer" to "Odpowiedź", + "done" to "Zrobione", + "not_done" to "Niezrobione", + "none" to "Brak", + "view_missing" to "Brak widoku: %s" ), "ARABIC" to mapOf( @@ -2649,7 +2971,53 @@ object LanguageManager { "done" to "تم", "locked" to "مقفل", "start" to "ابدأ", - "points" to "النقاط" + "points" to "النقاط", + "saved_pdf_csv" to "تم حفظ ملفات PDF وCSV في مجلد \"التنزيلات\".", + "no_pdf_viewer" to "لا يوجد عارض PDF مثبت.", + "save_error" to "خطأ أثناء الحفظ: {message}", + "login_required_title" to "يلزم تسجيل الدخول", + "username_hint" to "اسم المستخدم", + "password_hint" to "كلمة المرور", + "login_btn" to "تسجيل الدخول", + "exit_btn" to "إنهاء", + "please_username_password" to "يرجى إدخال اسم المستخدم وكلمة المرور.", + "download_failed_no_local_db" to "فشل التنزيل — لا توجد قاعدة بيانات محلية", + "download_failed_use_offline" to "فشل التنزيل — العمل بدون اتصال باستخدام قاعدة البيانات الحالية", + "login_failed_with_reason" to "فشل تسجيل الدخول: {reason}", + "no_header_template_found" to "لم يتم العثور على قالب للرؤوس", + "login_required" to "يرجى تسجيل الدخول أولاً", + "questionnaire" to "استبيان", + "session_label" to "الجلسة", + "session_dash" to "الجلسة: —", + "hours_short" to "س", + "minutes_short" to "د", + "online" to "متصل", + "offline" to "غير متصل", + "open_client_via_load" to "يرجى فتح العميل عبر «تحميل».", + "database" to "قاعدة البيانات", + "database_clients_title" to "قاعدة البيانات – العملاء", + "no_clients_available" to "لا يوجد عملاء.", + "previous" to "رجوع", + "download_header" to "تنزيل الرؤوس", + "client_code" to "رمز العميل", + "export_success_downloads" to "تم التصدير بنجاح: التنزيلات/ClientHeaders.xlsx", + "export_failed" to "فشل التصدير.", + "error" to "خطأ", + "client" to "عميل", + "questionnaires" to "استبيانات", + "headers" to "رؤوس", + "questionnaire_id" to "معرّف الاستبيان", + "status" to "الحالة", + "id" to "المعرّف", + "value" to "القيمة", + "no_questionnaires" to "لا توجد استبيانات متاحة.", + "no_questions_available" to "لا توجد أسئلة.", + "question" to "سؤال", + "answer" to "إجابة", + "done" to "منجز", + "not_done" to "غير منجز", + "none" to "لا شيء", + "view_missing" to "العنصر المفقود: %s" ), "ROMANIAN" to mapOf( @@ -2978,7 +3346,53 @@ object LanguageManager { "done" to "Finalizat", "locked" to "Blocat", "start" to "Începe", - "points" to "Puncte" + "points" to "Puncte", + "saved_pdf_csv" to "PDF și CSV au fost salvate în folderul „Descărcări”.", + "no_pdf_viewer" to "Nu este instalat niciun vizualizator PDF.", + "save_error" to "Eroare la salvare: {message}", + "login_required_title" to "Autentificare necesară", + "username_hint" to "Nume utilizator", + "password_hint" to "Parolă", + "login_btn" to "Autentificare", + "exit_btn" to "Ieșire", + "please_username_password" to "Introduceți numele de utilizator și parola.", + "download_failed_no_local_db" to "Descărcare eșuată – nu există bază de date locală", + "download_failed_use_offline" to "Descărcare eșuată – lucrați offline cu baza de date existentă", + "login_failed_with_reason" to "Autentificarea a eșuat: {reason}", + "no_header_template_found" to "Nu s-a găsit șablon de antet", + "login_required" to "Conectați-vă mai întâi", + "questionnaire" to "Chestionar", + "session_label" to "Sesiune", + "session_dash" to "Sesiune: —", + "hours_short" to "h", + "minutes_short" to "min", + "online" to "Online", + "offline" to "Offline", + "open_client_via_load" to "Deschideți clientul prin „Încărcare”.", + "database" to "Bază de date", + "database_clients_title" to "Bază de date – Clienți", + "no_clients_available" to "Nu există clienți.", + "previous" to "Înapoi", + "download_header" to "Descarcă antetul", + "client_code" to "Cod client", + "export_success_downloads" to "Export reușit: Descărcări/ClientHeaders.xlsx", + "export_failed" to "Export eșuat.", + "error" to "Eroare", + "client" to "Client", + "questionnaires" to "Chestionare", + "headers" to "Antete", + "questionnaire_id" to "ID chestionar", + "status" to "Stare", + "id" to "ID", + "value" to "Valoare", + "no_questionnaires" to "Nu există chestionare disponibile.", + "no_questions_available" to "Nu există întrebări.", + "question" to "Întrebare", + "answer" to "Răspuns", + "done" to "Finalizat", + "not_done" to "Nefinalizat", + "none" to "Nimic", + "view_missing" to "Vizualizare lipsă: %s" ), "SPANISH" to mapOf( @@ -3307,7 +3721,53 @@ object LanguageManager { "done" to "Completado", "locked" to "Bloqueado", "start" to "Iniciar", - "points" to "Puncte" + "points" to "Puncte", + "saved_pdf_csv" to "Los archivos PDF y CSV se han guardado en la carpeta \"Descargas\".", + "no_pdf_viewer" to "No hay un visor de PDF instalado.", + "save_error" to "Error al guardar: {message}", + "login_required_title" to "Se requiere inicio de sesión", + "username_hint" to "Nombre de usuario", + "password_hint" to "Contraseña", + "login_btn" to "Iniciar sesión", + "exit_btn" to "Salir", + "please_username_password" to "Introduce nombre de usuario y contraseña.", + "download_failed_no_local_db" to "La descarga falló: no hay base de datos local", + "download_failed_use_offline" to "La descarga falló: trabaja sin conexión con la base de datos existente", + "login_failed_with_reason" to "Error de inicio de sesión: {reason}", + "no_header_template_found" to "No se encontró una plantilla de encabezados", + "login_required" to "Inicia sesión primero", + "questionnaire" to "Cuestionario", + "session_label" to "Sesión", + "session_dash" to "Sesión: —", + "hours_short" to "h", + "minutes_short" to "min", + "online" to "En línea", + "offline" to "Sin conexión", + "open_client_via_load" to "Abre el cliente mediante «Cargar».", + "database" to "Base de datos", + "database_clients_title" to "Base de datos – Clientes", + "no_clients_available" to "No hay clientes disponibles.", + "previous" to "Atrás", + "download_header" to "Descargar encabezados", + "client_code" to "Código de cliente", + "export_success_downloads" to "Exportación correcta: Descargas/ClientHeaders.xlsx", + "export_failed" to "La exportación falló.", + "error" to "Error", + "client" to "Cliente", + "questionnaires" to "Cuestionarios", + "headers" to "Encabezados", + "questionnaire_id" to "ID del cuestionario", + "status" to "Estado", + "id" to "ID", + "value" to "Valor", + "no_questionnaires" to "No hay cuestionarios disponibles.", + "no_questions_available" to "No hay preguntas.", + "question" to "Pregunta", + "answer" to "Respuesta", + "done" to "Completado", + "not_done" to "No completado", + "none" to "Ninguno", + "view_missing" to "Vista faltante: %s" ) ) } diff --git a/app/src/main/java/com/dano/test1/MainActivity.kt b/app/src/main/java/com/dano/test1/MainActivity.kt index fa58443..fe96e8b 100644 --- a/app/src/main/java/com/dano/test1/MainActivity.kt +++ b/app/src/main/java/com/dano/test1/MainActivity.kt @@ -27,6 +27,10 @@ class MainActivity : AppCompatActivity() { // LIVE: Network-Callback (optional für Statusleiste) private var netCb: ConnectivityManager.NetworkCallback? = null + // Wir kennen hier (vor dem OpeningScreen) noch keine Nutzerwahl → Deutsch als Startsprache. + private val bootLanguageId: String get() = "GERMAN" + private fun t(key: String): String = LanguageManager.getText(bootLanguageId, key) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -57,11 +61,11 @@ class MainActivity : AppCompatActivity() { setPadding(dp(20), dp(8), dp(20), 0) } val etUser = EditText(this).apply { - hint = "Username" + hint = t("username_hint") setSingleLine() } val etPass = EditText(this).apply { - hint = "Passwort" + hint = t("password_hint") setSingleLine() inputType = android.text.InputType.TYPE_CLASS_TEXT or android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD @@ -70,14 +74,14 @@ class MainActivity : AppCompatActivity() { container.addView(etPass) val dialog = AlertDialog.Builder(this) - .setTitle("Login erforderlich") + .setTitle(t("login_required_title")) .setView(container) .setCancelable(false) - .setPositiveButton("Login") { _, _ -> + .setPositiveButton(t("login_btn")) { _, _ -> val user = etUser.text.toString().trim() val pass = etPass.text.toString() if (user.isEmpty() || pass.isEmpty()) { - Toast.makeText(this, "Bitte Username & Passwort eingeben", Toast.LENGTH_SHORT).show() + Toast.makeText(this, t("please_username_password"), Toast.LENGTH_SHORT).show() showLoginThenDownload() return@setPositiveButton } @@ -97,14 +101,14 @@ class MainActivity : AppCompatActivity() { // Wenn Download fehlgeschlagen ist, aber evtl. schon eine DB lokal liegt, // lassen wir den Nutzer trotzdem weiterarbeiten (Offline). if (!ok && !hasLocalDb()) { - Toast.makeText(this, "Download fehlgeschlagen – keine lokale Datenbank vorhanden", Toast.LENGTH_LONG).show() + Toast.makeText(this, t("download_failed_no_local_db"), Toast.LENGTH_LONG).show() // Zurück zum Login, damit man es erneut probieren kann showLoginThenDownload() return@downloadAndReplaceDatabase } if (!ok) { - Toast.makeText(this, "Download fehlgeschlagen – arbeite offline mit vorhandener DB", Toast.LENGTH_LONG).show() + Toast.makeText(this, t("download_failed_use_offline"), Toast.LENGTH_LONG).show() } // Opening-Screen starten @@ -115,12 +119,13 @@ class MainActivity : AppCompatActivity() { }, onError = { msg -> showBusy(false) - Toast.makeText(this, msg, Toast.LENGTH_LONG).show() + val txt = t("login_failed_with_reason").replace("{reason}", msg ?: "") + Toast.makeText(this, txt, Toast.LENGTH_LONG).show() showLoginThenDownload() } ) } - .setNegativeButton("Beenden") { _, _ -> finishAffinity() } + .setNegativeButton(t("exit_btn")) { _, _ -> finishAffinity() } .create() dialog.show() diff --git a/app/src/main/java/com/dano/test1/SaveButtonHandler.kt b/app/src/main/java/com/dano/test1/SaveButtonHandler.kt index 27a06a1..47812fc 100644 --- a/app/src/main/java/com/dano/test1/SaveButtonHandler.kt +++ b/app/src/main/java/com/dano/test1/SaveButtonHandler.kt @@ -98,7 +98,7 @@ class SaveButtonHandler( pdfDocument.finishPage(page) } - Log.d("CSV_OUTPUT", "Generated CSV:\n${csvBuilder.toString()}") + Log.d("CSV_OUTPUT", "Generated CSV:\n${csvBuilder}") val pdfFileName = "DatabaseOutput_${actualClientCode}.pdf" val csvFileName = "DatabaseOutput_${actualClientCode}.csv" @@ -108,12 +108,17 @@ class SaveButtonHandler( val projection = arrayOf(android.provider.MediaStore.MediaColumns._ID) val selection = "${android.provider.MediaStore.MediaColumns.DISPLAY_NAME} = ?" val selectionArgs = arrayOf(name) - val query = resolver.query(android.provider.MediaStore.Downloads.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null) + val query = resolver.query( + android.provider.MediaStore.Downloads.EXTERNAL_CONTENT_URI, + projection, selection, selectionArgs, null + ) query?.use { cursor -> if (cursor.moveToFirst()) { val idColumn = cursor.getColumnIndexOrThrow(android.provider.MediaStore.MediaColumns._ID) val id = cursor.getLong(idColumn) - val deleteUri = android.content.ContentUris.withAppendedId(android.provider.MediaStore.Downloads.EXTERNAL_CONTENT_URI, id) + val deleteUri = android.content.ContentUris.withAppendedId( + android.provider.MediaStore.Downloads.EXTERNAL_CONTENT_URI, id + ) resolver.delete(deleteUri, null, null) } } @@ -153,7 +158,8 @@ class SaveButtonHandler( } withContext(Dispatchers.Main) { - Toast.makeText(activity, "PDF und CSV gespeichert in Downloads", Toast.LENGTH_LONG).show() + val msg = LanguageManager.getText(languageIDProvider(), "saved_pdf_csv") + Toast.makeText(activity, msg, Toast.LENGTH_LONG).show() pdfUri?.let { val intent = android.content.Intent(android.content.Intent.ACTION_VIEW).apply { @@ -163,14 +169,17 @@ class SaveButtonHandler( try { activity.startActivity(intent) } catch (e: android.content.ActivityNotFoundException) { - Toast.makeText(activity, "Kein PDF-Viewer installiert", Toast.LENGTH_SHORT).show() + val noViewer = LanguageManager.getText(languageIDProvider(), "no_pdf_viewer") + Toast.makeText(activity, noViewer, Toast.LENGTH_SHORT).show() } } } } catch (e: Exception) { Log.e("SAVE", "Fehler beim Speichern der Dateien", e) withContext(Dispatchers.Main) { - Toast.makeText(activity, "Fehler beim Speichern: ${e.message}", Toast.LENGTH_LONG).show() + val errTpl = LanguageManager.getText(languageIDProvider(), "save_error") + val msg = (errTpl ?: "Fehler beim Speichern: {message}").replace("{message}", e.message ?: "") + Toast.makeText(activity, msg, Toast.LENGTH_LONG).show() } } }