From 192086546abc280fae514e4fd0a73e1410a236b7 Mon Sep 17 00:00:00 2001 From: "Alexander \"PapaTutuWawa" Date: Thu, 17 Nov 2022 23:25:05 +0100 Subject: [PATCH] feat(ui): Translate the entire UI --- assets/i18n/strings.i18n.json | 123 ++++++++++++++++- assets/i18n/strings_de.i18n.json | 125 +++++++++++++++++- lib/ui/helpers.dart | 9 +- lib/ui/pages/blocklist.dart | 23 ++-- lib/ui/pages/conversation/topbar.dart | 19 +-- lib/ui/pages/intro.dart | 2 +- lib/ui/pages/profile/devices.dart | 9 +- lib/ui/pages/profile/own_devices.dart | 37 +++--- lib/ui/pages/settings/about.dart | 21 +-- lib/ui/pages/settings/conversation.dart | 21 +-- lib/ui/pages/settings/debugging.dart | 32 ++--- lib/ui/pages/settings/licenses.dart | 5 +- lib/ui/pages/settings/network.dart | 15 ++- lib/ui/pages/settings/privacy/privacy.dart | 29 ++-- .../settings/privacy/redirect_dialog.dart | 13 +- lib/ui/pages/settings/privacy/tile.dart | 18 ++- lib/ui/pages/settings/settings.dart | 31 ++--- 17 files changed, 398 insertions(+), 134 deletions(-) diff --git a/assets/i18n/strings.i18n.json b/assets/i18n/strings.i18n.json index a147518a..cbaeffda 100644 --- a/assets/i18n/strings.i18n.json +++ b/assets/i18n/strings.i18n.json @@ -1,7 +1,14 @@ { + "global": { + "title": "Moxxy", + "moxxySubtitle": "An experiment into building a modern, easy and beautiful XMPP client.", + "dialogAccept": "Okay", + "dialogCancel": "Cancel", + "yes": "Yes", + "no": "No" + }, "pages": { "intro": { - "subtitle": "An experiment into building a modern, easy and beautiful XMPP client.", "noAccount": "Have no XMPP account? No worries, creating one is really easy.", "loginButton": "Login", "registerButton": "Register" @@ -20,6 +27,15 @@ "noOpenChats": "You have no open chats", "startChat": "Start a chat" }, + "conversation": { + "unencrypted": "Unencrypted", + "encrypted": "Encrypted", + "closeChat": "Close chat", + "closeChatConfirmTitle": "Close chat", + "closeChatConfirmSubtext": "Are you sure you want to close this chat?", + "blockUser": "Block user", + "online": "Online" + }, "addcontact": { "title": "Add new contact", "xmppAddress": "XMPP-Address", @@ -49,6 +65,111 @@ "muteChat": "Mute", "unmuteChat": "Unmute", "devices": "Devices" + }, + "owndevices": { + "title": "Own Devices", + "thisDevice": "This device", + "otherDevices": "Other devices", + "deleteDeviceConfirmTitle": "Delete device", + "deleteDeviceConfirmBody": "This means that contacts will not be able to encrypt for that device. Continue?", + "recreateOwnSessions": "Rebuild sessions", + "recreateOwnSessionsConfirmTitle": "Recreate own sessions?", + "recreateOwnSessionsConfirmBody": "This will recreate the cryptographic sessions with your own devices. Use only if your own devices throw decryption errors.", + "recreateOwnDevice": "Recreate device", + "recreateOwnDeviceConfirmTitle": "Recreate own device?", + "recreateOwnDeviceConfirmBody": "This will recreate this device's cryptographic identity. It will take some time. If contacts verified your device, they will have to do it again. Continue?" + }, + "devices": { + "title": "Devices", + "recreateSessions": "Rebuild sessions", + "recreateSessionsConfirmTitle": "Rebuild sessions?", + "recreateSessionsConfirmBody": "This will recreate the cryptographic sessions with your own devices. Use only if your own devices throw decryption errors." + } + }, + "blocklist": { + "title": "Blocklist", + "noUsersBlocked": "You have no users blocked", + "unblockAll": "Unblock all", + "unblockAllConfirmTitle": "Are you sure?", + "unblockAllConfirmBody": "Are you sure you want to unblock all users?", + "unblockJidConfirmTitle": "Unblock ${jid}?", + "unblockJidConfirmBody": "Are you sure you want to unblock ${jid}? You will receive messages from this user again." + }, + "settings": { + "settings": { + "title": "Settings", + "conversationsSection": "Conversations", + "accountSection": "Account", + "signOut": "Sign out", + "signOutConfirmTitle": "Sign Out", + "signOutConfirmBody": "You are about to sign out. Proceed?", + "miscellaneousSection": "Miscellaneous", + "debuggingSection": "Debugging" + }, + "about": { + "title": "About", + "licensed": "Licensed under GPL3", + "viewSourceCode": "View source code" + }, + "licenses": { + "title": "Open-Source Licenses", + "licensedUnder": "Licensed under $license" + }, + "conversation": { + "title": "Chat", + "appearance": "Appearance", + "selectBackgroundImage": "Select background image", + "selectBackgroundImageDescription": "This image will be the background of all your chats", + "removeBackgroundImage": "Remove background image", + "removeBackgroundImageConfirmTitle": "Remove background image", + "removeBackgroundImageConfirmBody": "Are you sure you want to remove your conversation background image?", + "newChatsSection": "New Conversations", + "newChatsMuteByDefault": "Mute new chats by default", + "newChatsE2EE": "Enable end-to-end encryption by default. WARNING: Experimental" + }, + "debugging": { + "title": "Debugging options", + "generalSection": "General", + "generalEnableDebugging": "Enable debugging", + "generalEncryptionPassword": "Encryption password", + "generalEncryptionPasswordSubtext": "The logs may contain sensitive information so pick a strong passphrase", + "generalLoggingIp": "Logging IP", + "generalLoggingIpSubtext": "The IP the logs should be sent to", + "generalLoggingPort": "Logging Port", + "generalLoggingPortSubtext": "The IP the logs should be sent to" + }, + "network": { + "title": "Network", + "automaticDownloadsSection": "Automatic Downloads", + "automaticDownloadsText": "Moxxy will automatically download files on...", + "automaticDownloadsMaximumSize": "Maximum Download Size", + "automaticDownloadsMaximumSizeSubtext": "The maximum file size for a file to be automatically downloaded", + "wifi": "Wifi", + "mobileData": "Mobile data" + }, + "privacy": { + "title": "Pricacy", + "generalSection": "General", + "showContactRequests": "Show contact requests", + "showContactRequestsSubtext": "This will show people who added you to their contact list but sent no message yet", + "profilePictureVisibility": "Make profile picture public", + "profilePictureVisibilitSubtext": "If enabled, everyone can see your profile picture. If disabled, only users on your contact list can see your profile picture.", + "autoAcceptSubscriptionRequests": "Auto-accept subscription requests", + "autoAcceptSubscriptionRequestsSubtext": "If enabled, subscription requests will be automatically accepted if the user is in the contact list.", + "conversationsSection": "Conversation", + "sendChatMarkers": "Send chat markers", + "sendChatMarkersSubtext": "This will tell your conversation partner if you received or read a message", + "sendChatStates": "Send chat states", + "sendChatStatesSubtext": "This will show your conversation partner if you are typing or looking at the chat", + "redirectsSection": "Redirects", + "redirectText": "This will redirect $serviceName links that you tap to a proxy service, e.g. $exampleProxy", + "currentlySelected": "Currently selected: $proxy", + "redirectsTitle": "$serviceName Redirect", + "cannotEnableRedirect": "Cannot enable $serviceName redirects", + "cannotEnableRedirectSubtext": "You must first set a proxy service to redirect to. To do so, tap the field next to the switch.", + "urlEmpty": "URL cannot be empty", + "urlInvalid": "Invalid URL", + "redirectDialogTitle": "$serviceName Redirect" } } } diff --git a/assets/i18n/strings_de.i18n.json b/assets/i18n/strings_de.i18n.json index ba7c5d2c..8e10a771 100644 --- a/assets/i18n/strings_de.i18n.json +++ b/assets/i18n/strings_de.i18n.json @@ -1,7 +1,14 @@ { + "global": { + "title": "Moxxy", + "moxxySubtitle": "Ein Experiment im Entwickeln eines modernen, einfachen und schönen XMPP-Clients.", + "dialogAccept": "Okay", + "dialogCancel": "Abbrechen", + "yes": "Ja", + "no": "Nein" + }, "pages": { "intro": { - "subtitle": "Ein Experiment im Entwickeln eines modernen, einfachen und schönen XMPP-Clients.", "noAccount": "Kein XMPP-Account vorhanden? Einen zu erstellen ist sehr einfach.", "loginButton": "Einloggen", "registerButton": "Registrieren" @@ -20,6 +27,15 @@ "noOpenChats": "Du hast keine offenen chats", "startChat": "Einen chat anfangen" }, + "conversation": { + "unencrypted": "Unverschlüsselt", + "encrypted": "Verschlüsselt", + "closeChat": "Chat schließen", + "closeChatConfirmTitle": "Chat schließen", + "closeChatConfirmSubtext": "Bist Du dir sicher, dass du den Chat schließen möchtest?", + "blockUser": "Nutzer blockieren", + "online": "Online" + }, "addcontact": { "title": "Neuen Kontakt hinzufügen", "xmppAddress": "XMPP-Adresse", @@ -37,7 +53,7 @@ "shareselection": { "shareWith": "Teilen mit...", "confirmTitle": "Dateien senden?", - "confirmTitle": "Einer oder mehr Chats sind unverschlüsselt. Das bedeutet, dass die Dateien dem Server unverschlüsselt vorliegen. Dateien trotzdem senden?" + "confirmBody": "Einer oder mehr Chats sind unverschlüsselt. Das bedeutet, dass die Dateien dem Server unverschlüsselt vorliegen. Dateien trotzdem senden?" }, "profile": { "self": { @@ -49,6 +65,111 @@ "muteChat": "Stummschalten", "unmuteChat": "Lautstellen", "devices": "Geräte" + }, + "owndevices": { + "title": "Eigene Geräte", + "thisDevice": "Dieses Gerät", + "otherDevices": "Andere Geräte", + "deleteDeviceConfirmTitle": "Gerät löschen", + "deleteDeviceConfirmBody": "Das bedeutet, dass Kontakte für dieses Gerät nichtmehr verschlüsseln können. Fortfahren?", + "recreateOwnSessions": "Sessions neuerstellen", + "recreateOwnSessionsConfirmTitle": "Eigene Sessions neuerstellen?", + "recreateOwnSessionsConfirmBody": "Das wird alle kryptographischen Sessions mit den eigenen Geräten neuerstellen. Verwende dies nur, wenn deine eigenen Geräte Entschlüsselungsfehler erzeugen.", + "recreateOwnDevice": "Gerät neuerstellen", + "recreateOwnDeviceConfirmTitle": "Gerät neuerstellen?", + "recreateOwnDeviceConfirmBody": "Das wird die kryptographische Identität dieses Geräts neu erstellen. Wenn Kontakte die kryptographische Indentität verifiziert haben, dann müssen diese es erneut tun. Fortfahren?" + }, + "devices": { + "title": "Devices", + "recreateSessions": "Rebuild sessions", + "recreateSessionsConfirmTitle": "Rebuild sessions?", + "recreateSessionsConfirmBody": "This will recreate the cryptographic sessions with your own devices. Use only if your own devices throw decryption errors." + } + }, + "blocklist": { + "title": "Blockliste", + "noUsersBlocked": "Du hast niemanden blockiert", + "unblockAll": "Alle entblocken", + "unblockAllConfirmTitle": "Alle entblocken", + "unblockAllConfirmBody": "Bist Du dir sicher, dass du alle geblockten Personen entblocken möchtest?", + "unblockJidConfirmTitle": "${jid} entblocken?", + "unblockJidConfirmBody": "Bist du dir sicher, dass du ${jid} entblocken möchtest? Du wirst wieder Nachrichten von dieser Person erhalten können." + }, + "settings": { + "settings": { + "title": "Einstellungen", + "conversationsSection": "Unterhaltungen", + "accountSection": "Account", + "signOut": "Abmelden", + "signOutConfirmTitle": "Abmelden", + "signOutConfirmBody": "Du bist dabei dich abzumelden. Fortfahren?", + "miscellaneousSection": "Unterschiedlich", + "debuggingSection": "Debugging" + }, + "about": { + "title": "Über", + "licensed": "Lizensiert unter GPL3", + "viewSourceCode": "Quellcode anschauen" + }, + "licenses": { + "title": "Open-Source Lizenzen", + "licensedUnder": "Lizensiert unter $license" + }, + "conversation": { + "title": "Chat", + "appearance": "Aussehen", + "selectBackgroundImage": "Hintergrundbild auswählen", + "selectBackgroundImageDescription": "Dieses Bild wird als Hintergrundbild in allen Chats verwendet", + "removeBackgroundImage": "Hintergrundbild entfernen", + "removeBackgroundImageConfirmTitle": "Hintergrundbild entfernen", + "removeBackgroundImageConfirmBody": "Bist Du dir sicher, dass Du das Hintergrundbild entfernen möchtest?", + "newChatsSection": "Neue Chats", + "newChatsMuteByDefault": "Neue Chats standardmäßig stummschalten", + "newChatsE2EE": "Ende-zu-Ende-Verschlüsselung standardmäßig aktivieren. WARNUNG: Experimentell" + }, + "debugging": { + "title": "Debuggingoptionen", + "generalSection": "Generell", + "generalEnableDebugging": "Debugging einschalten", + "generalEncryptionPassword": "Verschlüsselungspasswort", + "generalEncryptionPasswordSubtext": "Die Logs enthalten eventuell sensible Daten. Wähle also daher eine starke Passphrase", + "generalLoggingIp": "Logging-IP", + "generalLoggingIpSubtext": "Die IP-Adresse an die die Logs gesendet werden", + "generalLoggingPort": "Logging-Port", + "generalLoggingPortSubtext": "Der Port an den die Logs gesendet werden" + }, + "network": { + "title": "Netzwerk", + "automaticDownloadsSection": "Automatische Downloads", + "automaticDownloadsText": "Moxxy läd Dateien automatisch herunter, wenn verbunden mit...", + "automaticDownloadsMaximumSize": "Maximale Downloadgröße", + "automaticDownloadsMaximumSizeSubtext": "Die maximale Dateigröße, die automatisch heruntergeladen werden soll", + "wifi": "Wifi", + "mobileData": "Mobile Daten" + }, + "privacy": { + "title": "Privatsphäre", + "generalSection": "Generell", + "showContactRequests": "Kontaktanfragen zeigen", + "showContactRequestsSubtext": "Dies zeigt Personen in der Chatübersicht an, die Dich zu ihrer Kontaktliste hinzugefügt haben, aber noch keine Nachricht gesendet haben", + "profilePictureVisibility": "Öffentliches Profilbild", + "profilePictureVisibilitSubtext": "Wenn aktiviert, dann kann jeder Dein Profilbild sehen. Wenn deaktiviert, dann können nur Personen aus deiner Kontaktliste kein Profilbild sehen", + "autoAcceptSubscriptionRequests": "Subscriptionanfragen automatisch annehmen", + "autoAcceptSubscriptionRequestsSubtext": "Wenn aktiviert, dann werden Subscriptionanfragen automatisch angenommen, wenn die Person in deiner Kontaktliste ist", + "conversationsSection": "Unterhaltungen", + "sendChatMarkers": "Chatmarker senden", + "sendChatMarkersSubtext": "Dies teilt Deinem Gesprächspartner mit, ob du Nachrichten empfangen oder gelesen hast", + "sendChatStates": "Chatstates senden", + "sendChatStatesSubtext": "Dies teilt Deinem Gesprächspartner mit, ob du gerade im Chat aktiv bist oder schreibst", + "redirectsSection": "Weiterleitungen", + "redirectText": "Dies leitet Links von $serviceName, die du öffnest, an einen Proxydienst weiter, wie zum Beispiel $exampleProxy", + "currentlySelected": "Aktuell ausgewählt: $proxy", + "redirectsTitle": "${serviceName}weiterleitung", + "cannotEnableRedirect": "Kann ${serviceName}weiterleitung nicht aktivieren", + "cannotEnableRedirectSubtext": "Du must zuerst einen Proxydienst auswählen. Dazu berühre das Feld neben dem Schalter.", + "urlEmpty": "URL kann nicht leer sein", + "urlInvalid": "Ungültige URL", + "redirectDialogTitle": "${serviceName}weiterleitung" } } } diff --git a/lib/ui/helpers.dart b/lib/ui/helpers.dart index a71fdfb2..3eb59c0e 100644 --- a/lib/ui/helpers.dart +++ b/lib/ui/helpers.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_image_compress/flutter_image_compress.dart'; import 'package:get_it/get_it.dart'; import 'package:hex/hex.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/shared/avatar.dart'; import 'package:moxxyv2/ui/bloc/crop_bloc.dart'; import 'package:moxxyv2/ui/constants.dart'; @@ -28,11 +29,11 @@ Future showConfirmationDialog(String title, String body, BuildContext cont Navigator.of(context).pop(); callback(); }, - child: const Text('Yes'), + child: Text(t.global.yes), ), TextButton( onPressed: Navigator.of(context).pop, - child: const Text('No'), + child: Text(t.global.no), ) ], ), @@ -59,7 +60,7 @@ Future showNotImplementedDialog(String feature, BuildContext context) asyn ), actions: [ TextButton( - child: const Text('Okay'), + child: Text(t.global.dialogAccept), onPressed: () => Navigator.of(context).pop(), ) ], @@ -82,7 +83,7 @@ Future showInfoDialog(String title, String body, BuildContext context) asy actions: [ TextButton( onPressed: Navigator.of(context).pop, - child: const Text('Okay'), + child: Text(t.global.dialogAccept), ) ], ), diff --git a/lib/ui/pages/blocklist.dart b/lib/ui/pages/blocklist.dart index 07d1d53d..d029bd5e 100644 --- a/lib/ui/pages/blocklist.dart +++ b/lib/ui/pages/blocklist.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/ui/bloc/blocklist_bloc.dart'; import 'package:moxxyv2/ui/constants.dart'; import 'package:moxxyv2/ui/helpers.dart'; @@ -30,9 +31,9 @@ class BlocklistPage extends StatelessWidget { padding: const EdgeInsets.only(top: 8), child: Image.asset('assets/images/happy_news.png'), ), - const Padding( - padding: EdgeInsets.only(top: 8), - child: Text('You have no users blocked'), + Padding( + padding: const EdgeInsets.only(top: 8), + child: Text(t.pages.blocklist.noUsersBlocked), ) ], ), @@ -59,8 +60,8 @@ class BlocklistPage extends StatelessWidget { icon: const Icon(Icons.delete), color: Colors.red, onPressed: () => showConfirmationDialog( - 'Unblock $jid?', - 'Are you sure you want to unblock $jid? You will receive messages from this user again.', + t.pages.blocklist.unblockJidConfirmTitle(jid: jid), + t.pages.blocklist.unblockJidConfirmBody(jid: jid), context, () { context.read().add(UnblockedJidEvent(jid)); @@ -79,15 +80,15 @@ class BlocklistPage extends StatelessWidget { return BlocBuilder( builder: (context, state) => Scaffold( appBar: BorderlessTopbar.simple( - 'Blocklist', + t.pages.blocklist.title, extra: [ Expanded(child: Container()), PopupMenuButton( onSelected: (BlocklistOptions result) { if (result == BlocklistOptions.unblockAll) { showConfirmationDialog( - 'Are you sure?', - 'Are you sure you want to unblock all users?', + t.pages.blocklist.unblockAllConfirmTitle, + t.pages.blocklist.unblockAllConfirmBody, context, () { context.read().add(UnblockedAllEvent()); @@ -98,10 +99,10 @@ class BlocklistPage extends StatelessWidget { }, icon: const Icon(Icons.more_vert), itemBuilder: (BuildContext context) => [ - const PopupMenuItem( + PopupMenuItem( value: BlocklistOptions.unblockAll, - child: Text('Unblock all'), - ) + child: Text(t.pages.blocklist.unblockAll), + ), ], ) ], diff --git a/lib/ui/pages/conversation/topbar.dart b/lib/ui/pages/conversation/topbar.dart index 0368e9c0..da282231 100644 --- a/lib/ui/pages/conversation/topbar.dart +++ b/lib/ui/pages/conversation/topbar.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:get_it/get_it.dart'; import 'package:moxxmpp/moxxmpp.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/ui/bloc/conversation_bloc.dart'; import 'package:moxxyv2/ui/bloc/conversations_bloc.dart'; import 'package:moxxyv2/ui/bloc/profile_bloc.dart' as profile; @@ -59,9 +60,9 @@ class ConversationTopbar extends StatelessWidget implements PreferredSizeWidget switch (state) { case ChatState.paused: case ChatState.active: - return const Text( - 'Online', - style: TextStyle( + return Text( + t.pages.conversation.online, + style: const TextStyle( color: Colors.green, ), ); @@ -130,8 +131,8 @@ class ConversationTopbar extends StatelessWidget implements PreferredSizeWidget const Icon(Icons.lock) : const Icon(Icons.lock_open), itemBuilder: (BuildContext c) => [ - popupItemWithIcon(EncryptionOption.none, 'Unencrypted', Icons.lock_open), - popupItemWithIcon(EncryptionOption.omemo, 'Encrypted', Icons.lock), + popupItemWithIcon(EncryptionOption.none, t.pages.conversation.unencrypted, Icons.lock_open), + popupItemWithIcon(EncryptionOption.omemo, t.pages.conversation.encrypted, Icons.lock), ], ), // ignore: implicit_dynamic_type @@ -140,8 +141,8 @@ class ConversationTopbar extends StatelessWidget implements PreferredSizeWidget switch (result) { case ConversationOption.close: { showConfirmationDialog( - 'Close Chat', - 'Are you sure you want to close this chat?', + t.pages.conversation.closeChatConfirmTitle, + t.pages.conversation.closeChatConfirmSubtext, context, () { context.read().add( @@ -159,8 +160,8 @@ class ConversationTopbar extends StatelessWidget implements PreferredSizeWidget }, icon: const Icon(Icons.more_vert), itemBuilder: (BuildContext c) => [ - popupItemWithIcon(ConversationOption.close, 'Close chat', Icons.close), - popupItemWithIcon(ConversationOption.block, 'Block contact', Icons.block) + popupItemWithIcon(ConversationOption.close, t.pages.conversation.closeChat, Icons.close), + popupItemWithIcon(ConversationOption.block, t.pages.conversation.blockUser, Icons.block) ], ), ], diff --git a/lib/ui/pages/intro.dart b/lib/ui/pages/intro.dart index 05337391..e57d9191 100644 --- a/lib/ui/pages/intro.dart +++ b/lib/ui/pages/intro.dart @@ -40,7 +40,7 @@ class Intro extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: paddingVeryLarge), child: Text( - t.pages.intro.subtitle, + t.global.moxxySubtitle, style: const TextStyle( fontSize: fontsizeBody, ), diff --git a/lib/ui/pages/profile/devices.dart b/lib/ui/pages/profile/devices.dart index 05e1434a..e680470e 100644 --- a/lib/ui/pages/profile/devices.dart +++ b/lib/ui/pages/profile/devices.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/ui/bloc/devices_bloc.dart'; import 'package:moxxyv2/ui/constants.dart'; import 'package:moxxyv2/ui/helpers.dart'; @@ -60,8 +61,8 @@ class DevicesPage extends StatelessWidget { void _recreateSessions(BuildContext context) { showConfirmationDialog( - 'Recreate sessions?', - "This will recreate the cryptographic sessions with the contact. Use only if this device throws decryption errors or your contact's devices throw decryption errors.", + t.pages.profile.devices.recreateSessionsConfirmTitle, + t.pages.profile.devices.recreateSessionsConfirmBody, context, () { context.read().add(SessionsRecreatedEvent()); @@ -74,7 +75,7 @@ class DevicesPage extends StatelessWidget { return BlocBuilder( builder: (context, state) => Scaffold( appBar: BorderlessTopbar.simple( - 'Devices', + t.pages.profile.devices.title, extra: [ const Spacer(), PopupMenuButton( @@ -88,7 +89,7 @@ class DevicesPage extends StatelessWidget { PopupMenuItem( value: DevicesOptions.recreateSessions, enabled: state.devices.isNotEmpty, - child: const Text('Rebuild sessions'), + child: Text(t.pages.profile.devices.recreateSessions), ) ], ), diff --git a/lib/ui/pages/profile/own_devices.dart b/lib/ui/pages/profile/own_devices.dart index 2f54ad73..ffbd5917 100644 --- a/lib/ui/pages/profile/own_devices.dart +++ b/lib/ui/pages/profile/own_devices.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:get_it/get_it.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/ui/bloc/own_devices_bloc.dart'; import 'package:moxxyv2/ui/constants.dart'; import 'package:moxxyv2/ui/helpers.dart'; @@ -65,15 +66,15 @@ class OwnDevicesPage extends StatelessWidget { return Column( mainAxisSize: MainAxisSize.min, children: [ - const Align( + Align( alignment: Alignment.centerLeft, child: Padding( - padding: EdgeInsets.only( + padding: const EdgeInsets.only( left: 16, ), child: Text( - 'This device', - style: TextStyle( + t.pages.profile.owndevices.thisDevice, + style: const TextStyle( fontSize: fontsizeSubtitle, ), ), @@ -90,16 +91,16 @@ class OwnDevicesPage extends StatelessWidget { ), ...state.keys.isNotEmpty ? [ - const Align( + Align( alignment: Alignment.centerLeft, child: Padding( - padding: EdgeInsets.only( + padding: const EdgeInsets.only( top: 32, left: 16, ), child: Text( - 'Other devices', - style: TextStyle( + t.pages.profile.owndevices.otherDevices, + style: const TextStyle( fontSize: fontsizeSubtitle, ), ), @@ -139,8 +140,8 @@ class OwnDevicesPage extends StatelessWidget { }, onDeletePressed: () { showConfirmationDialog( - 'Delete device', - 'This means that contacts will not be able to encrypt for that device. Continue?', + t.pages.profile.owndevices.deleteDeviceConfirmTitle, + t.pages.profile.owndevices.deleteDeviceConfirmBody, context, () { context.read().add(OwnDeviceRemovedEvent(item.deviceId)); @@ -154,8 +155,8 @@ class OwnDevicesPage extends StatelessWidget { void _recreateSessions(BuildContext context) { showConfirmationDialog( - 'Recreate own sessions?', - 'This will recreate the cryptographic sessions with your own devices. Use only if your own devices throw decryption errors.', + t.pages.profile.owndevices.recreateOwnSessionsConfirmTitle, + t.pages.profile.owndevices.recreateOwnSessionsConfirmBody, context, () { context.read().add(OwnSessionsRecreatedEvent()); @@ -165,8 +166,8 @@ class OwnDevicesPage extends StatelessWidget { void _recreateDevice(BuildContext context) { showConfirmationDialog( - 'Recreate own device?', - "This will recreate this device's cryptographic identity. It might take some time and will cause decryption errors until you sent a message to your contacts. If they verified your device, they will have to do it again. Continue?", + t.pages.profile.owndevices.recreateOwnDeviceConfirmTitle, + t.pages.profile.owndevices.recreateOwnDeviceConfirmBody, context, () { context.read().add(OwnDeviceRegeneratedEvent()); @@ -179,7 +180,7 @@ class OwnDevicesPage extends StatelessWidget { return BlocBuilder( builder: (context, state) => Scaffold( appBar: BorderlessTopbar.simple( - 'Own Devices', + t.pages.profile.owndevices.title, extra: [ const Spacer(), PopupMenuButton( @@ -198,11 +199,11 @@ class OwnDevicesPage extends StatelessWidget { PopupMenuItem( value: OwnDevicesOptions.recreateSessions, enabled: state.keys.isNotEmpty, - child: const Text('Rebuild sessions'), + child: Text(t.pages.profile.owndevices.recreateOwnSessions), ), - const PopupMenuItem( + PopupMenuItem( value: OwnDevicesOptions.recreateDevice, - child: Text('Recreate identity'), + child: Text(t.pages.profile.owndevices.recreateOwnDevice), ), ], ), diff --git a/lib/ui/pages/settings/about.dart b/lib/ui/pages/settings/about.dart index 98402d0f..e93bfbba 100644 --- a/lib/ui/pages/settings/about.dart +++ b/lib/ui/pages/settings/about.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/ui/constants.dart'; import 'package:moxxyv2/ui/widgets/topbar.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -24,7 +25,7 @@ class SettingsAboutPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: BorderlessTopbar.simple('About'), + appBar: BorderlessTopbar.simple(t.pages.settings.about.title), body: Padding( padding: const EdgeInsets.symmetric(horizontal: paddingVeryLarge), child: Column( @@ -33,26 +34,26 @@ class SettingsAboutPage extends StatelessWidget { 'assets/images/logo.png', width: 200, height: 200, ), - const Text( - 'moxxy', - style: TextStyle( + Text( + t.global.title, + style: const TextStyle( fontSize: 40, ), ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 8), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), child: Text( - 'An experimental XMPP client that is beautiful, modern and easy to use', - style: TextStyle( + t.global.moxxySubtitle, + style: const TextStyle( fontSize: 15, ), ), ), - const Text('Licensed under GPL3'), + Text(t.pages.settings.about.licensed), Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: ElevatedButton( - child: const Text('View source code'), + child: Text(t.pages.settings.about.viewSourceCode), onPressed: () => _openUrl('https://github.com/PapaTutuWawa/moxxyv2'), ), ) diff --git a/lib/ui/pages/settings/conversation.dart b/lib/ui/pages/settings/conversation.dart index 9a32d4a5..4ca0de7d 100644 --- a/lib/ui/pages/settings/conversation.dart +++ b/lib/ui/pages/settings/conversation.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/shared/models/preferences.dart'; import 'package:moxxyv2/ui/bloc/cropbackground_bloc.dart'; import 'package:moxxyv2/ui/bloc/preferences_bloc.dart'; @@ -63,16 +64,16 @@ class ConversationSettingsPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: BorderlessTopbar.simple('Chat'), + appBar: BorderlessTopbar.simple(t.pages.settings.conversation.title), body: BlocBuilder( builder: (context, state) => SettingsList( sections: [ SettingsSection( - title: const Text('Appearance'), + title: Text(t.pages.settings.conversation.appearance), tiles: [ SettingsTile( - title: const Text('Select background image'), - description: const Text('This image will be the background of all your chats'), + title: Text(t.pages.settings.conversation.selectBackgroundImage), + description: Text(t.pages.settings.conversation.selectBackgroundImageDescription), onPressed: (context) async { final backgroundPath = await _pickBackgroundImage(); @@ -85,11 +86,11 @@ class ConversationSettingsPage extends StatelessWidget { }, ), SettingsTile( - title: const Text('Remove background image'), + title: Text(t.pages.settings.conversation.removeBackgroundImage), onPressed: (context) { showConfirmationDialog( - 'Are you sure?', - 'Are you sure you want to remove your conversation background image?', + t.pages.settings.conversation.removeBackgroundImageConfirmTitle, + t.pages.settings.conversation.removeBackgroundImageConfirmBody, context, () async { await _removeBackgroundImage(context, state); @@ -100,10 +101,10 @@ class ConversationSettingsPage extends StatelessWidget { ], ), SettingsSection( - title: const Text('New Conversations'), + title: Text(t.pages.settings.conversation.newChatsSection), tiles: [ SettingsTile.switchTile( - title: const Text('Mute new chats by default'), + title: Text(t.pages.settings.conversation.newChatsMuteByDefault), initialValue: state.defaultMuteState, onToggle: (value) => context.read().add( PreferencesChangedEvent( @@ -112,7 +113,7 @@ class ConversationSettingsPage extends StatelessWidget { ), ), SettingsTile.switchTile( - title: const Text('Enable end-to-end encryption by default. WARNING: Experimental'), + title: Text(t.pages.settings.conversation.newChatsE2EE), initialValue: state.enableOmemoByDefault, onToggle: (value) => context.read().add( PreferencesChangedEvent( diff --git a/lib/ui/pages/settings/debugging.dart b/lib/ui/pages/settings/debugging.dart index f3015e81..c31af2aa 100644 --- a/lib/ui/pages/settings/debugging.dart +++ b/lib/ui/pages/settings/debugging.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/shared/models/preferences.dart'; import 'package:moxxyv2/ui/bloc/preferences_bloc.dart'; import 'package:moxxyv2/ui/constants.dart'; @@ -7,7 +8,6 @@ import 'package:moxxyv2/ui/widgets/topbar.dart'; import 'package:settings_ui/settings_ui.dart'; class DebuggingPage extends StatelessWidget { - DebuggingPage({ super.key }) : _ipController = TextEditingController(), _passphraseController = TextEditingController(), @@ -26,15 +26,15 @@ class DebuggingPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: BorderlessTopbar.simple('Debugging'), + appBar: BorderlessTopbar.simple(t.pages.settings.debugging.title), body: BlocBuilder( builder: (context, state) => SettingsList( sections: [ SettingsSection( - title: const Text('General'), + title: Text(t.pages.settings.debugging.generalSection), tiles: [ SettingsTile.switchTile( - title: const Text('Enable debugging'), + title: Text(t.pages.settings.debugging.generalEnableDebugging), onToggle: (value) => context.read().add( PreferencesChangedEvent( state.copyWith(debugEnabled: value), @@ -43,14 +43,14 @@ class DebuggingPage extends StatelessWidget { initialValue: state.debugEnabled, ), SettingsTile( - title: const Text('Encryption password'), - description: const Text('The logs may contain sensitive information so pick a strong passphrase'), + title: Text(t.pages.settings.debugging.generalEncryptionPassword), + description: Text(t.pages.settings.debugging.generalEncryptionPasswordSubtext), onPressed: (context) { showDialog( context: context, barrierDismissible: true, builder: (BuildContext context) => AlertDialog( - title: const Text('Debug Passphrase'), + title: Text(t.pages.settings.debugging.generalEncryptionPassword), content: TextField( minLines: 1, obscureText: true, @@ -58,7 +58,7 @@ class DebuggingPage extends StatelessWidget { ), actions: [ TextButton( - child: const Text('Okay'), + child: Text(t.global.dialogAccept), onPressed: () { context.read().add( PreferencesChangedEvent( @@ -74,21 +74,21 @@ class DebuggingPage extends StatelessWidget { }, ), SettingsTile( - title: const Text('Logging IP'), - description: const Text('The IP the logs should be sent to'), + title: Text(t.pages.settings.debugging.generalLoggingIp), + description: Text(t.pages.settings.debugging.generalLoggingIpSubtext), onPressed: (context) { showDialog( context: context, barrierDismissible: true, builder: (BuildContext context) => AlertDialog( - title: const Text('Logging IP'), + title: Text(t.pages.settings.debugging.generalLoggingIp), content: TextField( minLines: 1, controller: _ipController, ), actions: [ TextButton( - child: const Text('Okay'), + child: Text(t.global.dialogAccept), onPressed: () { context.read().add( PreferencesChangedEvent( @@ -104,14 +104,14 @@ class DebuggingPage extends StatelessWidget { }, ), SettingsTile( - title: const Text('Logging Port'), - description: const Text('The Port the logs should be sent to'), + title: Text(t.pages.settings.debugging.generalLoggingPort), + description: Text(t.pages.settings.debugging.generalLoggingPortSubtext), onPressed: (context) { showDialog( context: context, barrierDismissible: true, builder: (BuildContext context) => AlertDialog( - title: const Text('Logging Port'), + title: Text(t.pages.settings.debugging.generalLoggingPort), content: TextField( minLines: 1, controller: _portController, @@ -119,7 +119,7 @@ class DebuggingPage extends StatelessWidget { ), actions: [ TextButton( - child: const Text('Okay'), + child: Text(t.global.dialogAccept), onPressed: () { context.read().add( PreferencesChangedEvent( diff --git a/lib/ui/pages/settings/licenses.dart b/lib/ui/pages/settings/licenses.dart index 64f805a0..87e6cc79 100644 --- a/lib/ui/pages/settings/licenses.dart +++ b/lib/ui/pages/settings/licenses.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/ui/constants.dart'; import 'package:moxxyv2/ui/widgets/topbar.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -31,7 +32,7 @@ class LicenseRow extends StatelessWidget { Widget build(BuildContext context) { return ListTile( title: Text(library.name), - subtitle: Text('Licensed under ${library.license}'), + subtitle: Text(t.pages.settings.licenses.licensedUnder(license: library.license)), onTap: _openUrl, ); } @@ -50,7 +51,7 @@ class SettingsLicensesPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: BorderlessTopbar.simple('Licenses'), + appBar: BorderlessTopbar.simple(t.pages.settings.licenses.title), body: ListView.builder( itemCount: usedLibraryList.length, itemBuilder: (context, index) => LicenseRow(library: usedLibraryList[index]), diff --git a/lib/ui/pages/settings/network.dart b/lib/ui/pages/settings/network.dart index 380855f1..a4fc424e 100644 --- a/lib/ui/pages/settings/network.dart +++ b/lib/ui/pages/settings/network.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/shared/models/preferences.dart'; import 'package:moxxyv2/ui/bloc/preferences_bloc.dart'; import 'package:moxxyv2/ui/constants.dart'; @@ -66,18 +67,18 @@ class NetworkPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: BorderlessTopbar.simple('Network'), + appBar: BorderlessTopbar.simple(t.pages.settings.network.title), body: BlocBuilder( builder: (context, state) => SettingsList( sections: [ SettingsSection( - title: const Text('Automatic Downloads'), + title: Text(t.pages.settings.network.automaticDownloadsSection), tiles: [ SettingsTile( - title: const Text('Moxxy will automatically download files on...'), + title: Text(t.pages.settings.network.automaticDownloadsText), ), SettingsTile.switchTile( - title: const Text('Wifi'), + title: Text(t.pages.settings.network.wifi), initialValue: state.autoDownloadWifi, onToggle: (value) => context.read().add( PreferencesChangedEvent( @@ -86,7 +87,7 @@ class NetworkPage extends StatelessWidget { ), ), SettingsTile.switchTile( - title: const Text('Mobile Data'), + title: Text(t.pages.settings.network.mobileData), initialValue: state.autoDownloadMobile, onToggle: (value) => context.read().add( PreferencesChangedEvent( @@ -95,8 +96,8 @@ class NetworkPage extends StatelessWidget { ), ), SettingsTile( - title: const Text('Maximum Download Size'), - description: const Text('The maximum file size for a file to be automatically downloaded'), + title: Text(t.pages.settings.network.automaticDownloadsMaximumSize), + description: Text(t.pages.settings.network.automaticDownloadsMaximumSizeSubtext), onPressed: (context) { showModalBottomSheet( context: context, diff --git a/lib/ui/pages/settings/privacy/privacy.dart b/lib/ui/pages/settings/privacy/privacy.dart index 216b611d..463da2e7 100644 --- a/lib/ui/pages/settings/privacy/privacy.dart +++ b/lib/ui/pages/settings/privacy/privacy.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/shared/models/preferences.dart'; import 'package:moxxyv2/ui/bloc/preferences_bloc.dart'; import 'package:moxxyv2/ui/constants.dart'; @@ -20,16 +21,16 @@ class PrivacyPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: BorderlessTopbar.simple('Privacy'), + appBar: BorderlessTopbar.simple(t.pages.settings.privacy.title), body: BlocBuilder( builder: (context, state) => SettingsList( sections: [ SettingsSection( - title: const Text('General'), + title: Text(t.pages.settings.privacy.generalSection), tiles: [ SettingsTile.switchTile( - title: const Text('Show contact requests'), - description: const Text('This will show people who added you to their contact list but sent no message yet'), + title: Text(t.pages.settings.privacy.showContactRequests), + description: Text(t.pages.settings.privacy.showContactRequestsSubtext), initialValue: state.showSubscriptionRequests, onToggle: (value) => context.read().add( PreferencesChangedEvent( @@ -38,8 +39,8 @@ class PrivacyPage extends StatelessWidget { ), ), SettingsTile.switchTile( - title: const Text('Make profile picture public'), - description: const Text('If enabled, everyone can see your profile picture. If disabled, only users on your contact list can see your profile picture.'), + title: Text(t.pages.settings.privacy.profilePictureVisibility), + description: Text(t.pages.settings.privacy.profilePictureVisibilitSubtext), initialValue: state.isAvatarPublic, onToggle: (value) => context.read().add( PreferencesChangedEvent( @@ -48,8 +49,8 @@ class PrivacyPage extends StatelessWidget { ), ), SettingsTile.switchTile( - title: const Text('Auto-accept subscription requests'), - description: const Text('If enabled, subscription requests will be automatically accepted if the user is in the contact list.'), + title: Text(t.pages.settings.privacy.autoAcceptSubscriptionRequests), + description: Text(t.pages.settings.privacy.autoAcceptSubscriptionRequestsSubtext), initialValue: state.autoAcceptSubscriptionRequests, onToggle: (value) => context.read().add( PreferencesChangedEvent( @@ -60,11 +61,11 @@ class PrivacyPage extends StatelessWidget { ], ), SettingsSection( - title: const Text('Conversation'), + title: Text(t.pages.settings.privacy.conversationsSection), tiles: [ SettingsTile.switchTile( - title: const Text('Send chat markers'), - description: const Text('This will tell your conversation partner if you received or read a message'), + title: Text(t.pages.settings.privacy.sendChatMarkers), + description: Text(t.pages.settings.privacy.sendChatMarkersSubtext), initialValue: state.sendChatMarkers, onToggle: (value) => context.read().add( PreferencesChangedEvent( @@ -73,8 +74,8 @@ class PrivacyPage extends StatelessWidget { ), ), SettingsTile.switchTile( - title: const Text('Send chat states'), - description: const Text('This will show your conversation partner if you are typing or looking at the chat'), + title: Text(t.pages.settings.privacy.sendChatStates), + description: Text(t.pages.settings.privacy.sendChatStatesSubtext), initialValue: state.sendChatStates, onToggle: (value) => context.read().add( PreferencesChangedEvent( @@ -85,7 +86,7 @@ class PrivacyPage extends StatelessWidget { ], ), SettingsSection( - title: const Text('Redirects'), + title: Text(t.pages.settings.privacy.redirectsSection), tiles: [ RedirectSettingsTile( 'Youtube', diff --git a/lib/ui/pages/settings/privacy/redirect_dialog.dart b/lib/ui/pages/settings/privacy/redirect_dialog.dart index 29aa4bc1..2a08b2a9 100644 --- a/lib/ui/pages/settings/privacy/redirect_dialog.dart +++ b/lib/ui/pages/settings/privacy/redirect_dialog.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/ui/constants.dart'; import 'package:moxxyv2/ui/widgets/textfield.dart'; @@ -22,7 +23,7 @@ class RedirectDialogState extends State { if (value.isEmpty) { setState(() { - errorText = 'URL cannot be empty'; + errorText = t.pages.settings.privacy.urlEmpty; }); return false; } @@ -30,7 +31,7 @@ class RedirectDialogState extends State { final parsed = Uri.tryParse(value); if (parsed == null) { setState(() { - errorText = 'Invalid URL'; + errorText = t.pages.settings.privacy.urlInvalid; }); return false; } @@ -48,7 +49,9 @@ class RedirectDialogState extends State { @override Widget build(BuildContext context) { return AlertDialog( - title: Text('${widget.serviceName} Redirect'), + title: Text( + t.pages.settings.privacy.redirectDialogTitle(serviceName: widget.serviceName), + ), content: Padding( padding: const EdgeInsets.all(16), child: Column( @@ -76,7 +79,7 @@ class RedirectDialogState extends State { ), actions: [ TextButton( - child: const Text('Okay'), + child: Text(t.global.dialogAccept), onPressed: () { if (_validateUrl()) { Navigator.of(context).pop(); @@ -86,7 +89,7 @@ class RedirectDialogState extends State { }, ), TextButton( - child: const Text('Cancel'), + child: Text(t.global.dialogCancel), onPressed: () => Navigator.of(context).pop(), ), ], diff --git a/lib/ui/pages/settings/privacy/tile.dart b/lib/ui/pages/settings/privacy/tile.dart index 02f2a0f2..74ff105a 100644 --- a/lib/ui/pages/settings/privacy/tile.dart +++ b/lib/ui/pages/settings/privacy/tile.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/shared/models/preferences.dart'; import 'package:moxxyv2/ui/bloc/preferences_bloc.dart'; import 'package:moxxyv2/ui/helpers.dart'; @@ -27,16 +28,23 @@ class RedirectSettingsTile extends AbstractSettingsTile { Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) => SettingsTile( - title: Text('$serviceName Redirect'), + title: Text(t.pages.settings.privacy.redirectsTitle(serviceName: serviceName)), description: Column( children: [ Align( alignment: Alignment.centerLeft, - child: Text('This will redirect $serviceName links that you tap to a proxy service, e.g. $exampleProxy'), + child: Text( + t.pages.settings.privacy.redirectText( + serviceName: serviceName, + exampleProxy: exampleProxy, + ), + ), ), Align( alignment: Alignment.centerLeft, - child: Text('Currently selected: ${getProxy(state)}'), + child: Text( + t.pages.settings.privacy.currentlySelected(proxy: getProxy(state)), + ), ), ], ), @@ -58,8 +66,8 @@ class RedirectSettingsTile extends AbstractSettingsTile { onChanged: (value) { if (getProxy(state).isEmpty) { showInfoDialog( - 'Cannot enable $serviceName redirects', - 'You must first set a proxy service to redirect to. To do so, tap the field next to the switch.', + t.pages.settings.privacy.cannotEnableRedirect(serviceName: serviceName), + t.pages.settings.privacy.cannotEnableRedirectSubtext, context, ); return; diff --git a/lib/ui/pages/settings/settings.dart b/lib/ui/pages/settings/settings.dart index 9fabe1fe..f0086252 100644 --- a/lib/ui/pages/settings/settings.dart +++ b/lib/ui/pages/settings/settings.dart @@ -1,6 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; +import 'package:moxxyv2/i18n/strings.g.dart'; import 'package:moxxyv2/ui/bloc/preferences_bloc.dart'; import 'package:moxxyv2/ui/constants.dart'; import 'package:moxxyv2/ui/helpers.dart'; @@ -20,43 +21,43 @@ class SettingsPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: BorderlessTopbar.simple('Settings'), + appBar: BorderlessTopbar.simple(t.pages.settings.settings.title), body: SettingsList( sections: [ SettingsSection( - title: const Text('Conversations'), + title: Text(t.pages.settings.settings.conversationsSection), tiles: [ SettingsTile( - title: const Text('Chat'), + title: Text(t.pages.settings.conversation.title), leading: const Icon(Icons.chat_bubble), onPressed: (context) => Navigator.pushNamed(context, conversationSettingsRoute), ), SettingsTile( - title: const Text('Network'), + title: Text(t.pages.settings.network.title), leading: const Icon(Icons.network_wifi), onPressed: (context) => Navigator.pushNamed(context, networkRoute), ), SettingsTile( - title: const Text('Privacy'), + title: Text(t.pages.settings.privacy.title), leading: const Icon(Icons.shield), onPressed: (context) => Navigator.pushNamed(context, privacyRoute), ) ], ), SettingsSection( - title: const Text('Account'), + title: Text(t.pages.settings.settings.accountSection), tiles: [ SettingsTile( - title: const Text('Blocklist'), + title: Text(t.pages.blocklist.title), leading: const Icon(Icons.block), onPressed: (context) => Navigator.pushNamed(context, blocklistRoute), ), SettingsTile( - title: const Text('Sign out'), + title: Text(t.pages.settings.settings.signOut), leading: const Icon(Icons.logout), onPressed: (context) => showConfirmationDialog( - 'Sign Out', - 'You are about to sign out. Proceed?', + t.pages.settings.settings.signOutConfirmTitle, + t.pages.settings.settings.signOutConfirmBody, context, () async { GetIt.I.get().add(SignedOutEvent()); @@ -66,15 +67,15 @@ class SettingsPage extends StatelessWidget { ], ), SettingsSection( - title: const Text('Miscellaneous'), + title: Text(t.pages.settings.settings.miscellaneousSection), tiles: [ SettingsTile( - title: const Text('About'), + title: Text(t.pages.settings.about.title), leading: const Icon(Icons.info), onPressed: (context) => Navigator.pushNamed(context, aboutRoute), ), SettingsTile( - title: const Text('Open-Source licenses'), + title: Text(t.pages.settings.licenses.title), leading: const Icon(Icons.description), onPressed: (context) => Navigator.pushNamed(context, licensesRoute), ) @@ -83,10 +84,10 @@ class SettingsPage extends StatelessWidget { // TODO(Unknown): Maybe also have a switch somewhere ...kDebugMode ? [ SettingsSection( - title: const Text('Debugging'), + title: Text(t.pages.settings.settings.debuggingSection), tiles: [ SettingsTile( - title: const Text('Debugging options'), + title: Text(t.pages.settings.debugging.title), leading: const Icon(Icons.info), onPressed: (context) => Navigator.pushNamed(context, debuggingRoute), )