feat(v1.5.0): Complete i18n implementation + Language Selector feature
- Added comprehensive English (strings.xml) and German (strings-de.xml) localization with 400+ strings - Created new LanguageSettingsScreen with System Default, English, and German options - Fixed hardcoded German notification toasts in MainActivity and ComposeMainActivity - Integrated Language selector in Settings as top-level menu item - Changed ComposeSettingsActivity from ComponentActivity to AppCompatActivity for AppCompatDelegate compatibility - Added locales_config.xml for Android 13+ Per-App Language support - Updated Extensions.kt with i18n-aware timestamp formatting (toReadableTime with context) - Translated all UI strings including settings, toasts, notifications, and error messages - Added dynamic language display in SettingsMainScreen showing current language Fixes: - Notification permission toast now respects system language setting - Activity correctly restarts when language is changed - All string formatting with parameters properly localized Migration: - MainViewModel: All toast messages now use getString() - SettingsViewModel: All toast and dialog messages localized - NotificationHelper: Notification titles and messages translated - UrlValidator: Error messages now accept Context parameter for translation - NoteCard, DeleteConfirmationDialog, SyncStatusBanner: All strings externalized Testing completed on device with both EN and DE locale switching. Closes #5
This commit is contained in:
@@ -467,10 +467,10 @@ class MainActivity : AppCompatActivity() {
|
||||
val checkboxAlways = dialogView.findViewById<CheckBox>(R.id.checkboxAlwaysDeleteFromServer)
|
||||
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle("Notiz löschen")
|
||||
.setMessage("\"${note.title}\" wird lokal gelöscht.\n\nAuch vom Server löschen?")
|
||||
.setTitle(getString(R.string.legacy_delete_dialog_title))
|
||||
.setMessage(getString(R.string.legacy_delete_dialog_message, note.title))
|
||||
.setView(dialogView)
|
||||
.setNeutralButton("Abbrechen") { _, _ ->
|
||||
.setNeutralButton(getString(R.string.cancel)) { _, _ ->
|
||||
// RESTORE: Re-submit original list (note is NOT deleted from storage)
|
||||
adapter.submitList(originalList)
|
||||
}
|
||||
@@ -485,7 +485,7 @@ class MainActivity : AppCompatActivity() {
|
||||
// NOW actually delete from storage
|
||||
deleteNoteLocally(note, deleteFromServer = false)
|
||||
}
|
||||
.setNegativeButton("Vom Server löschen") { _, _ ->
|
||||
.setNegativeButton(getString(R.string.legacy_delete_from_server)) { _, _ ->
|
||||
if (checkboxAlways.isChecked) {
|
||||
prefs.edit().putBoolean(Constants.KEY_ALWAYS_DELETE_FROM_SERVER, true).apply()
|
||||
}
|
||||
@@ -507,13 +507,13 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
// Show Snackbar with UNDO option
|
||||
val message = if (deleteFromServer) {
|
||||
"\"${note.title}\" wird lokal und vom Server gelöscht"
|
||||
getString(R.string.legacy_delete_with_server, note.title)
|
||||
} else {
|
||||
"\"${note.title}\" lokal gelöscht (Server bleibt)"
|
||||
getString(R.string.legacy_delete_local_only, note.title)
|
||||
}
|
||||
|
||||
Snackbar.make(recyclerViewNotes, message, Snackbar.LENGTH_LONG)
|
||||
.setAction("RÜCKGÄNGIG") {
|
||||
.setAction(getString(R.string.snackbar_undo)) {
|
||||
// UNDO: Restore note
|
||||
storage.saveNote(note)
|
||||
pendingDeletions.remove(note.id)
|
||||
@@ -535,7 +535,7 @@ class MainActivity : AppCompatActivity() {
|
||||
runOnUiThread {
|
||||
Toast.makeText(
|
||||
this@MainActivity,
|
||||
"Vom Server gelöscht",
|
||||
getString(R.string.snackbar_deleted_from_server),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
@@ -543,7 +543,7 @@ class MainActivity : AppCompatActivity() {
|
||||
runOnUiThread {
|
||||
Toast.makeText(
|
||||
this@MainActivity,
|
||||
"Server-Löschung fehlgeschlagen",
|
||||
getString(R.string.snackbar_server_delete_failed),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
@@ -800,10 +800,9 @@ class MainActivity : AppCompatActivity() {
|
||||
REQUEST_NOTIFICATION_PERMISSION -> {
|
||||
if (grantResults.isNotEmpty() &&
|
||||
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
showToast("Benachrichtigungen aktiviert")
|
||||
showToast(getString(R.string.toast_notifications_enabled))
|
||||
} else {
|
||||
showToast("Benachrichtigungen deaktiviert. " +
|
||||
"Du kannst sie in den Einstellungen aktivieren.")
|
||||
showToast(getString(R.string.toast_notifications_disabled))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user