diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f29aaeaa9cf8..2db924df7fa6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -90,8 +90,6 @@ android { namespace = "com.owncloud.android" testNamespace = "${namespace}.test" - androidResources.generateLocaleConfig = true - defaultConfig { applicationId = "com.nextcloud.client" minSdk = 28 @@ -176,6 +174,11 @@ android { versionName = "1" } } + + // NMC customization to only include German and English translations and exclude the others + // By doing this no need to delete the other strings which aren't required for NMC + // Refer: https://developer.android.com/guide/topics/resources/providing-resources#AlternativeResources + resConfigs("en", "de_DE", "de") } applicationVariants.configureEach { diff --git a/app/src/androidTest/java/com/nmc/android/LocalizationResourceTest.kt b/app/src/androidTest/java/com/nmc/android/LocalizationResourceTest.kt new file mode 100644 index 000000000000..b259baad2e54 --- /dev/null +++ b/app/src/androidTest/java/com/nmc/android/LocalizationResourceTest.kt @@ -0,0 +1,172 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2025 TSI-mc + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nmc.android + +import android.content.Context +import android.content.res.Configuration +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.owncloud.android.R +import junit.framework.TestCase.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import java.util.Locale + +/** + * Test class to verify the strings customized in this branch PR for NMC + */ +@RunWith(AndroidJUnit4::class) +class LocalizationResourceTest { + + private val baseContext = ApplicationProvider.getApplicationContext() + + private val localizedStringMap = mapOf( + R.string.about_version to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to $$"Version %1$s", + Locale.GERMAN to $$"Version %1$s" + ) + ), + R.string.actionbar_see_details to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Share", + Locale.GERMAN to "Teilen" + ) + ), + R.string.drawer_item_on_device to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Offline files", + Locale.GERMAN to "Offline verfügbare Dateien" + ) + ), + R.string.prefs_lock to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Security", + Locale.GERMAN to "Sicherheit" + ) + ), + R.string.filedetails_download to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Offline availability", + Locale.GERMAN to "Offline Verfügbarkeit" + ) + ), + R.string.filedetails_sync_file to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Offline availability", + Locale.GERMAN to "Offline Verfügbarkeit" + ) + ), + R.string.action_send_share to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Sharing", + Locale.GERMAN to "Teilen" + ) + ), + R.string.common_cancel_sync to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Cancel", + Locale.GERMAN to "Abbrechen" + ) + ), + R.string.instant_upload_path to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "/Camera-Media", + Locale.GERMAN to "/Kamera-Medien" + ) + ), + R.string.prefs_synced_folders_remote_path_title to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Target folder in your MagentaCLOUD", + Locale.GERMAN to "Zielorder in Deiner MagentaCLOUD" + ) + ), + R.string.prefs_e2e_mnemonic to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "End-to-end encryption", + Locale.GERMAN to "Ende-zu-Ende Verschlüsselung" + ) + ), + R.string.storage_choose_location to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Choose Source", + Locale.GERMAN to "Wählen Sie Quelle" + ) + ), + R.string.subtitle_photos_videos to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Images and videos", + Locale.GERMAN to "Fotos und Videos" + ) + ), + R.string.show_images to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Show images", + Locale.GERMAN to "Bilder anzeigen" + ) + ), + R.string.subtitle_photos_only to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Images only", + Locale.GERMAN to "Nur Fotos" + ) + ), + R.string.select_media_folder to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Select the \"Media\" folder", + Locale.GERMAN to "Den Ordner \"Medien\" auswählen", + ) + ), + R.string.file_already_exists to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Filename already exists.", + Locale.GERMAN to "Dateiname bereits vorhanden", + ) + ), + R.string.email_pick_failed to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Failed to pick email address.", + Locale.GERMAN to "Fehler beim Zugriff auf E-Mail Adresse.", + ) + ), + R.string.menu_item_sort_by_date_newest_first to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "Newest first", + Locale.GERMAN to "Neueste zuerst", + ) + ), + R.string.update_link_file_error to ExpectedLocalizedString( + translations = mapOf( + Locale.ENGLISH to "An error occurred while trying to update the share.", + Locale.GERMAN to "Fehler bei der Aktualisierungd der Freigabe aufgetreten.", + ) + ), + ) + + @Test + fun verifyLocalizedStrings() { + localizedStringMap.forEach { (stringRes, expected) -> + expected.translations.forEach { (locale, expectedText) -> + + val config = Configuration(baseContext.resources.configuration) + config.setLocale(locale) + + val localizedContext = baseContext.createConfigurationContext(config) + val actualText = localizedContext.getString(stringRes) + + assertEquals( + "Mismatch for ${baseContext.resources.getResourceEntryName(stringRes)} in $locale", + expectedText, + actualText + ) + } + } + } + + data class ExpectedLocalizedString(val translations: Map) +} \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 63e97d1a9c78..8e284cb38c89 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -10,7 +10,7 @@ Bearbeiten Alle Benachrichtigungen löschen Papierkorb leeren - Senden/Teilen + Teilen Kachelansicht Listenansicht Kontakte und Kalender wiederherstellen @@ -18,7 +18,7 @@ Verschieben oder kopieren Öffnen mit Suche - Details + Teilen Senden Einstellungen Sortieren @@ -146,7 +146,7 @@ Unerwarteter Fehler beim Kopieren in die Zwischenablage Zurück Abbrechen - Synchronisierung abbrechen + Abbrechen Konto auswählen Bestätigen Kopieren @@ -201,7 +201,7 @@ Falls beide Versionen gewählt werden, wird beim lokalen Ordner eine Zahl am Ende des Dateinamens hinzugefügt. Serverdatei Kontakte-Backup - Eine Kontakterlaubnis ist erforderlich. + Zugriff auf Kontakte erforderlich. Nutzericon für Kontaktliste Keine Berechtigung vergeben, es wurde nichts importiert. Kontakte @@ -302,11 +302,11 @@ Gruppenordner Home Benachrichtigungen - Auf dem Gerät + Offline verfügbare Dateien Persönliche Dateien Kürzlich geändert Geteilt - Gelöschte Dateien + Papierkorb Uploads Abmelden Hauptmenü öffnen @@ -324,7 +324,7 @@ Mehr Weitere Nextcloud-Apps Dateiauswahl konnte nicht geöffnet werden - E-Mail-Adresse konnte nicht ausgewählt werden. + Fehler beim Zugriff auf E-Mail Adresse. Als verschlüsselt festlegen Serverzertifikat kann nicht abgerufen werden Der öffentliche Schlüssel konnte nicht verifiziert werden. @@ -475,10 +475,10 @@ %s existiert bereits, kein Konflikt erkannt Fehler beim Wiederherstellen der Dateiversion! Details - Herunterladen + Offline Verfügbarkeit Exportieren Datei während des Hochladens in %1$s umbenannt - Synchronisieren + Offline Verfügbarkeit Keine Datei gewählt Dateiname darf nicht leer sein Verbotene Zeichen: / \\ < > : \" | ? * @@ -541,7 +541,7 @@ %s s Vorhandene Dateien ebenfalls hochladen Nur während des Ladens der Batterie hochladen - /SofortUpload + /Kamera-Medien Interne Freigaben Interne 2-Wege-Synchronisierung Bislang nicht, wird demnächst synchronisiert @@ -592,7 +592,7 @@ Wiedergabe-/Pause Knopf Rückspulknopf %1$s (wird abgespielt) - Neue zuerst + Neueste zuerst Älteste zuerst A - Z Z - A @@ -623,7 +623,7 @@ Nur ein Konto zulässig Keine App zum Öffnen von PDFs verfügbar Keine App zum Senden der ausgewählten Dateien verfügbar - Bitte mindestens eine Berechtigung zum Teilen auswählen. + Senden Notiz konnte nicht versandt werden Notiz-Symbol Aktion konnte nicht ausgeführt werden @@ -718,7 +718,7 @@ Speicherort der Daten verwalten Unerwarteter Fehler beim Einrichten von DAVx⁵ (früher bekannt als DAVdroid) Ende-zu-Ende-Verschlüsselung ist eingerichtet! - E2E-Gedächtnisstütze + Ende-zu-Ende Verschlüsselung Um die Gedächtnisstütze anzuzeigen, aktivieren Sie bitte Geräte-Zugangsdaten Benachrichtigungen der Mediensuche anzeigen Über neu gefundene Medienordner informieren @@ -734,7 +734,7 @@ Unterordneroptionen Diesem Client Ende-zu-Ende-Verschlüsselung hinzufügen Lizenz - App-PIN + Sicherheit Geräte-Anmeldedaten aktiviert Keine Geräte-Anmeldedaten eingerichtet. Nichts @@ -751,7 +751,7 @@ Zum Quellcode Ordner für \"Automatisches Hochladen\" verwalten Lokaler Ordner - Remote-Ordner + Zielorder in Deiner MagentaCLOUD Design Intervall Interne Ordner für 2-Wege-Synchronisierung verwalten @@ -822,11 +822,12 @@ Sicheres teilen ist für diesen Benutzer nicht eingerichtet Sicheres teilen … Alle auswählen - Medien-Ordner auswählen + Den Ordner \"Medien\" auswählen Bitte eine Vorlage auswählen Vorlage auswählen Senden Freigabe senden + Notiz an Empfänger senden Icon für den Senden-Button Inhalt konnte nicht geladen werden Das Gerät scheint nicht mit dem Internet verbunden zu sein @@ -892,7 +893,7 @@ Freigeben fehlgeschlagen Das Hinzufügen der Freigabe ist fehlgeschlagen. Diese Datei oder dieser Ordner wurden bereits für diese Person oder Gruppe freigegeben. Alle anzeigen - Fotos anzeigen + Bilder anzeigen Weniger anzeigen Videos anzeigen Bitte überprüfen Sie die Nutzungsbedingungen selbst! @@ -928,7 +929,7 @@ - Die Adresse stimmt nicht mit dem im Zertifikat angegebenen Hostnamen überein Statusnachricht Kamera - Speicherort auswählen + Wählen Sie Quelle Standard Dokumente Downloads @@ -1026,7 +1027,7 @@ diese Datei nicht mehr zu teilen Freigabe aufheben fehlgeschlagen Zugriff über nicht vertrauenswürdige Domain. Weitere Informationen finden sich in der Dokumentation. - Es ist ein Fehler bei der Aktualisierungd der Freigabe aufgetreten. + Fehler bei der Aktualisierungd der Freigabe aufgetreten. Aktualisierung nicht möglich. Bitte prüfen Sie, ob die Datei existiert. zum Aktualisieren dieser Freigabe Aktualisierung der Freigabe fehlgeschlagen diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a48e76517e0a..99279971d3bb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -13,13 +13,13 @@ Poor connection Check your internet connection or try again later %1$s Android app - version %1$s + Version %1$s version %1$s, build #%2$s Search in %s Open with New folder Settings - Details + Share Send Sort Sort by @@ -95,7 +95,7 @@ Personal files Home Favorites - On device + Offline files Recently modified Shared Uploads @@ -108,7 +108,7 @@ General More Manage accounts - App passcode + Security Protect app using None Passcode @@ -214,16 +214,16 @@ Upload some content or activate auto upload. folder Upload failed. No internet connection - Download - Sync + Offline availability + Offline availability File renamed %1$s during upload Listed layout - Send/share + Sharing Yes No OK Now - Cancel sync + Cancel Cancel Back Save @@ -539,7 +539,7 @@ Only upload on unmetered Wi-Fi Only upload when charging Also upload existing files - /InstantUpload + /Camera-Media /AutoUpload Low battery, upload might take longer @@ -556,7 +556,7 @@ %1$s could not be copied to %2$s local folder Local folder - Remote folder + Target folder in your MagentaCLOUD Use subfolders Store in subfolders based on date Exclude hidden @@ -982,7 +982,7 @@ Adding share failed. This file or folder has already been shared with this person or group. Unsharing failed Updating share failed - E2E mnemonic + End-to-end encryption To show mnemonic please enable device credentials. Log in Sign up with provider @@ -1086,7 +1086,7 @@ Failed to execute action. Remove New notification - Choose storage location + Choose Source Internal storage External storage Camera @@ -1308,19 +1308,19 @@ All files access Media read-only Don\'t ask - Photos and videos - Show photos - Photos only + Images and videos + Show images + Images only Show videos Videos only - Set media folder + Select the \"Media\" folder Lock file Unlock file Error changing file lock status Locked by %1$s Locked by %1$s app Expires: %1$s - Filename already exists + Filename already exists. Export Locate folder Video overlay icon