mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 11:18:41 +00:00
translate #121
This commit is contained in:
parent
0b1f51713c
commit
2ecebb2429
10 changed files with 618 additions and 104 deletions
|
|
@ -156,6 +156,8 @@
|
|||
"close": "Schließen",
|
||||
"cancel": "Abbrechen",
|
||||
"ok": "Ok",
|
||||
"disable": "Deaktiviern",
|
||||
"enable": "Aktivieren",
|
||||
"switchFrontAndBackCamera": "Zwischen Front- und Rückkamera wechseln.",
|
||||
"addTextItem": "Text",
|
||||
"protectAsARealTwonly": "Als echtes twonly senden!",
|
||||
|
|
@ -263,5 +265,35 @@
|
|||
"backupNoticeTitle": "Kein Backup konfiguriert",
|
||||
"backupNoticeDesc": "Wenn du dein Gerät wechselst oder verlierst, kann ohne Backup niemand dein Account wiederherstellen. Sichere deshalb deine Daten.",
|
||||
"backupNoticeLater": "Später erinnern",
|
||||
"backupNoticeOpenBackup": "Backup erstellen"
|
||||
"backupNoticeOpenBackup": "Backup erstellen",
|
||||
"backupPending": "Ausstehend",
|
||||
"backupFailed": "Fehlgeschlagen",
|
||||
"backupSuccess": "Erfolgreich",
|
||||
"backupTwonlySafeDesc": "Sichere deine twonly-Identität, da dies die einzige Möglichkeit ist, dein Konto wiederherzustellen, wenn du die App deinstallierst oder dein Handy verlierst.",
|
||||
"backupServer": "Server",
|
||||
"backupMaxBackupSize": "max. Backup-Größe",
|
||||
"backupStorageRetention": "Speicheraufbewahrung",
|
||||
"backupLastBackupDate": "Letztes Backup",
|
||||
"backupLastBackupSize": "Backup-Größe",
|
||||
"backupLastBackupResult": "Ergebnis",
|
||||
"deleteBackupTitle": "Bist du sicher?",
|
||||
"deleteBackupBody": "Ohne ein Backup kannst du dein Benutzerkonto nicht wiederherstellen.",
|
||||
"backupData": "Daten-Backup",
|
||||
"backupDataDesc": "Das Daten-Backup enthält neben deiner twonly-Identität auch alle deine Mediendateien. Dieses Backup ist ebenfalls verschlüsselt, wird jedoch lokal gespeichert. Du musst es dann manuell auf deinen Laptop oder ein Gerät deiner Wahl kopieren.",
|
||||
"backupInsecurePassword": "Unsicheres Passwort",
|
||||
"backupInsecurePasswordDesc": "Das gewählte Passwort ist sehr unsicher und kann daher leicht von Angreifern erraten werden. Bitte wähle ein sicheres Passwort.",
|
||||
"backupInsecurePasswordOk": "Trotzdem fortfahren",
|
||||
"backupInsecurePasswordCancel": "Erneut versuchen",
|
||||
"backupTwonlySafeLongDesc": "twonly hat keine zentralen Benutzerkonten. Ein Schlüsselpaar wird während der Installation erstellt, das aus einem öffentlichen und einem privaten Schlüssel besteht. Der private Schlüssel wird nur auf deinem Gerät gespeichert, um ihn vor unbefugtem Zugriff zu schützen. Der öffentliche Schlüssel wird auf den Server hochgeladen und mit deinem gewählten Benutzernamen verknüpft, damit andere dich finden können.\n\ntwonly Safe erstellt regelmäßig ein verschlüsseltes, anonymes Backup deines privaten Schlüssels zusammen mit deinen Kontakten und Einstellungen. Dein Benutzername und das gewählte Passwort reichen aus, um diese Daten auf einem anderen Gerät wiederherzustellen.",
|
||||
"backupSelectStrongPassword": "Wähle ein sicheres Passwort. Dies ist erforderlich, wenn du dein twonly Safe-Backup wiederherstellen möchtest.",
|
||||
"password": "Passwort",
|
||||
"passwordRepeated": "Passwort wiederholen",
|
||||
"passwordRepeatedNotEqual": "Passwörter stimmen nicht überein.",
|
||||
"backupPasswordRequirement": "Das Passwort muss mindestens 8 Zeichen lang sein.",
|
||||
"backupExpertSettings": "Experteneinstellungen",
|
||||
"backupEnableBackup": "Automatische Sicherung aktivieren",
|
||||
"backupOwnServerDesc": "Speichere dein twonly Safe-Backups auf einem Server deiner Wahl.",
|
||||
"backupUseOwnServer": "Server verwenden",
|
||||
"backupResetServer": "Standardserver verwenden",
|
||||
"backupTwonlySaveNow": "Jetzt speichern"
|
||||
}
|
||||
|
|
@ -274,17 +274,13 @@
|
|||
"contactRemoveTitle": "Remove {username}",
|
||||
"contactRemoveBody": "Remove the user and permanently delete the chat and all associated media files. This will also delete YOUR ACCOUNT FROM YOUR CONTACT'S PHONE.",
|
||||
"undo": "Undo",
|
||||
"@undo": {},
|
||||
"redo": "Redo",
|
||||
"@redo": {},
|
||||
"next": "Next",
|
||||
"@next": {},
|
||||
"close": "Close",
|
||||
"@close": {},
|
||||
"disable": "Disable",
|
||||
"enable": "Enable",
|
||||
"cancel": "Cancel",
|
||||
"@cancel": {},
|
||||
"ok": "Ok",
|
||||
"@ok": {},
|
||||
"switchFrontAndBackCamera": "Switch between front and back camera.",
|
||||
"@switchFrontAndBackCamera": {},
|
||||
"addTextItem": "Text",
|
||||
|
|
@ -423,5 +419,35 @@
|
|||
"backupNoticeTitle": "No backup configured",
|
||||
"backupNoticeDesc": "If you change or lose your device, no one can restore your account without a backup. Therefore, back up your data.",
|
||||
"backupNoticeLater": "Remind later",
|
||||
"backupNoticeOpenBackup": "Create backup"
|
||||
"backupNoticeOpenBackup": "Create backup",
|
||||
"backupPending": "Pending",
|
||||
"backupFailed": "Failed",
|
||||
"backupSuccess": "Success",
|
||||
"backupTwonlySafeDesc": "Back up your twonly identity, as this is the only way to restore your account if you uninstall the app or lose your phone.",
|
||||
"backupServer": "Server",
|
||||
"backupMaxBackupSize": "max. backup size",
|
||||
"backupStorageRetention": "Storage retention",
|
||||
"backupLastBackupDate": "Last backup",
|
||||
"backupLastBackupSize": "Backup size",
|
||||
"backupLastBackupResult": "Result",
|
||||
"deleteBackupTitle": "Are you sure?",
|
||||
"deleteBackupBody": "Without an backup, you can not restore your user account.",
|
||||
"backupData": "Data-Backup",
|
||||
"backupDataDesc": "This backup contains besides of your twonly-Identity also all of your media files. This backup will is also encrypted but stored locally. You then have to ensure to manually copy it onto your laptop or device of your choice.",
|
||||
"backupInsecurePassword": "Insecure password",
|
||||
"backupInsecurePasswordDesc": "The chosen password is very insecure and can therefore easily be guessed by attackers. Please choose a secure password.",
|
||||
"backupInsecurePasswordOk": "Continue anyway",
|
||||
"backupInsecurePasswordCancel": "Try again",
|
||||
"backupTwonlySafeLongDesc": "twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Safe regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.",
|
||||
"backupSelectStrongPassword": "Choose a secure password. This is required if you want to restore your twonly Safe backup.",
|
||||
"password": "Password",
|
||||
"passwordRepeated": "Repeat password",
|
||||
"passwordRepeatedNotEqual": "Passwords do not match.",
|
||||
"backupPasswordRequirement": "Password must be at least 8 characters long.",
|
||||
"backupExpertSettings": "Expert settings",
|
||||
"backupEnableBackup": "Activate automatic backup",
|
||||
"backupOwnServerDesc": "Save your twonly safe backups at twonly or on any server of your choice.",
|
||||
"backupUseOwnServer": "Use server",
|
||||
"backupResetServer": "Use standard server",
|
||||
"backupTwonlySaveNow": "Save now"
|
||||
}
|
||||
|
|
@ -926,6 +926,18 @@ abstract class AppLocalizations {
|
|||
/// **'Close'**
|
||||
String get close;
|
||||
|
||||
/// No description provided for @disable.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Disable'**
|
||||
String get disable;
|
||||
|
||||
/// No description provided for @enable.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Enable'**
|
||||
String get enable;
|
||||
|
||||
/// No description provided for @cancel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
@ -1603,6 +1615,186 @@ abstract class AppLocalizations {
|
|||
/// In en, this message translates to:
|
||||
/// **'Create backup'**
|
||||
String get backupNoticeOpenBackup;
|
||||
|
||||
/// No description provided for @backupPending.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Pending'**
|
||||
String get backupPending;
|
||||
|
||||
/// No description provided for @backupFailed.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed'**
|
||||
String get backupFailed;
|
||||
|
||||
/// No description provided for @backupSuccess.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Success'**
|
||||
String get backupSuccess;
|
||||
|
||||
/// No description provided for @backupTwonlySafeDesc.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Back up your twonly identity, as this is the only way to restore your account if you uninstall the app or lose your phone.'**
|
||||
String get backupTwonlySafeDesc;
|
||||
|
||||
/// No description provided for @backupServer.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Server'**
|
||||
String get backupServer;
|
||||
|
||||
/// No description provided for @backupMaxBackupSize.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'max. backup size'**
|
||||
String get backupMaxBackupSize;
|
||||
|
||||
/// No description provided for @backupStorageRetention.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Storage retention'**
|
||||
String get backupStorageRetention;
|
||||
|
||||
/// No description provided for @backupLastBackupDate.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Last backup'**
|
||||
String get backupLastBackupDate;
|
||||
|
||||
/// No description provided for @backupLastBackupSize.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Backup size'**
|
||||
String get backupLastBackupSize;
|
||||
|
||||
/// No description provided for @backupLastBackupResult.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Result'**
|
||||
String get backupLastBackupResult;
|
||||
|
||||
/// No description provided for @deleteBackupTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Are you sure?'**
|
||||
String get deleteBackupTitle;
|
||||
|
||||
/// No description provided for @deleteBackupBody.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Without an backup, you can not restore your user account.'**
|
||||
String get deleteBackupBody;
|
||||
|
||||
/// No description provided for @backupData.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Data-Backup'**
|
||||
String get backupData;
|
||||
|
||||
/// No description provided for @backupDataDesc.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'This backup contains besides of your twonly-Identity also all of your media files. This backup will is also encrypted but stored locally. You then have to ensure to manually copy it onto your laptop or device of your choice.'**
|
||||
String get backupDataDesc;
|
||||
|
||||
/// No description provided for @backupInsecurePassword.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Insecure password'**
|
||||
String get backupInsecurePassword;
|
||||
|
||||
/// No description provided for @backupInsecurePasswordDesc.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'The chosen password is very insecure and can therefore easily be guessed by attackers. Please choose a secure password.'**
|
||||
String get backupInsecurePasswordDesc;
|
||||
|
||||
/// No description provided for @backupInsecurePasswordOk.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Continue anyway'**
|
||||
String get backupInsecurePasswordOk;
|
||||
|
||||
/// No description provided for @backupInsecurePasswordCancel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Try again'**
|
||||
String get backupInsecurePasswordCancel;
|
||||
|
||||
/// No description provided for @backupTwonlySafeLongDesc.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Safe regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.'**
|
||||
String get backupTwonlySafeLongDesc;
|
||||
|
||||
/// No description provided for @backupSelectStrongPassword.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Choose a secure password. This is required if you want to restore your twonly Safe backup.'**
|
||||
String get backupSelectStrongPassword;
|
||||
|
||||
/// No description provided for @password.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Password'**
|
||||
String get password;
|
||||
|
||||
/// No description provided for @passwordRepeated.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Repeat password'**
|
||||
String get passwordRepeated;
|
||||
|
||||
/// No description provided for @passwordRepeatedNotEqual.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Passwords do not match.'**
|
||||
String get passwordRepeatedNotEqual;
|
||||
|
||||
/// No description provided for @backupPasswordRequirement.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Password must be at least 8 characters long.'**
|
||||
String get backupPasswordRequirement;
|
||||
|
||||
/// No description provided for @backupExpertSettings.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Expert settings'**
|
||||
String get backupExpertSettings;
|
||||
|
||||
/// No description provided for @backupEnableBackup.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Activate automatic backup'**
|
||||
String get backupEnableBackup;
|
||||
|
||||
/// No description provided for @backupOwnServerDesc.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Save your twonly safe backups at twonly or on any server of your choice.'**
|
||||
String get backupOwnServerDesc;
|
||||
|
||||
/// No description provided for @backupUseOwnServer.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Use server'**
|
||||
String get backupUseOwnServer;
|
||||
|
||||
/// No description provided for @backupResetServer.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Use standard server'**
|
||||
String get backupResetServer;
|
||||
|
||||
/// No description provided for @backupTwonlySaveNow.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Save now'**
|
||||
String get backupTwonlySaveNow;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
|
|
|||
|
|
@ -468,6 +468,12 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
@override
|
||||
String get close => 'Schließen';
|
||||
|
||||
@override
|
||||
String get disable => 'Deaktiviern';
|
||||
|
||||
@override
|
||||
String get enable => 'Aktivieren';
|
||||
|
||||
@override
|
||||
String get cancel => 'Abbrechen';
|
||||
|
||||
|
|
@ -849,4 +855,102 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get backupNoticeOpenBackup => 'Backup erstellen';
|
||||
|
||||
@override
|
||||
String get backupPending => 'Ausstehend';
|
||||
|
||||
@override
|
||||
String get backupFailed => 'Fehlgeschlagen';
|
||||
|
||||
@override
|
||||
String get backupSuccess => 'Erfolgreich';
|
||||
|
||||
@override
|
||||
String get backupTwonlySafeDesc =>
|
||||
'Sichere deine twonly-Identität, da dies die einzige Möglichkeit ist, dein Konto wiederherzustellen, wenn du die App deinstallierst oder dein Handy verlierst.';
|
||||
|
||||
@override
|
||||
String get backupServer => 'Server';
|
||||
|
||||
@override
|
||||
String get backupMaxBackupSize => 'max. Backup-Größe';
|
||||
|
||||
@override
|
||||
String get backupStorageRetention => 'Speicheraufbewahrung';
|
||||
|
||||
@override
|
||||
String get backupLastBackupDate => 'Letztes Backup';
|
||||
|
||||
@override
|
||||
String get backupLastBackupSize => 'Backup-Größe';
|
||||
|
||||
@override
|
||||
String get backupLastBackupResult => 'Ergebnis';
|
||||
|
||||
@override
|
||||
String get deleteBackupTitle => 'Bist du sicher?';
|
||||
|
||||
@override
|
||||
String get deleteBackupBody =>
|
||||
'Ohne ein Backup kannst du dein Benutzerkonto nicht wiederherstellen.';
|
||||
|
||||
@override
|
||||
String get backupData => 'Daten-Backup';
|
||||
|
||||
@override
|
||||
String get backupDataDesc =>
|
||||
'Das Daten-Backup enthält neben deiner twonly-Identität auch alle deine Mediendateien. Dieses Backup ist ebenfalls verschlüsselt, wird jedoch lokal gespeichert. Du musst es dann manuell auf deinen Laptop oder ein Gerät deiner Wahl kopieren.';
|
||||
|
||||
@override
|
||||
String get backupInsecurePassword => 'Unsicheres Passwort';
|
||||
|
||||
@override
|
||||
String get backupInsecurePasswordDesc =>
|
||||
'Das gewählte Passwort ist sehr unsicher und kann daher leicht von Angreifern erraten werden. Bitte wähle ein sicheres Passwort.';
|
||||
|
||||
@override
|
||||
String get backupInsecurePasswordOk => 'Trotzdem fortfahren';
|
||||
|
||||
@override
|
||||
String get backupInsecurePasswordCancel => 'Erneut versuchen';
|
||||
|
||||
@override
|
||||
String get backupTwonlySafeLongDesc =>
|
||||
'twonly hat keine zentralen Benutzerkonten. Ein Schlüsselpaar wird während der Installation erstellt, das aus einem öffentlichen und einem privaten Schlüssel besteht. Der private Schlüssel wird nur auf deinem Gerät gespeichert, um ihn vor unbefugtem Zugriff zu schützen. Der öffentliche Schlüssel wird auf den Server hochgeladen und mit deinem gewählten Benutzernamen verknüpft, damit andere dich finden können.\n\ntwonly Safe erstellt regelmäßig ein verschlüsseltes, anonymes Backup deines privaten Schlüssels zusammen mit deinen Kontakten und Einstellungen. Dein Benutzername und das gewählte Passwort reichen aus, um diese Daten auf einem anderen Gerät wiederherzustellen.';
|
||||
|
||||
@override
|
||||
String get backupSelectStrongPassword =>
|
||||
'Wähle ein sicheres Passwort. Dies ist erforderlich, wenn du dein twonly Safe-Backup wiederherstellen möchtest.';
|
||||
|
||||
@override
|
||||
String get password => 'Passwort';
|
||||
|
||||
@override
|
||||
String get passwordRepeated => 'Passwort wiederholen';
|
||||
|
||||
@override
|
||||
String get passwordRepeatedNotEqual => 'Passwörter stimmen nicht überein.';
|
||||
|
||||
@override
|
||||
String get backupPasswordRequirement =>
|
||||
'Das Passwort muss mindestens 8 Zeichen lang sein.';
|
||||
|
||||
@override
|
||||
String get backupExpertSettings => 'Experteneinstellungen';
|
||||
|
||||
@override
|
||||
String get backupEnableBackup => 'Automatische Sicherung aktivieren';
|
||||
|
||||
@override
|
||||
String get backupOwnServerDesc =>
|
||||
'Speichere dein twonly Safe-Backups auf einem Server deiner Wahl.';
|
||||
|
||||
@override
|
||||
String get backupUseOwnServer => 'Server verwenden';
|
||||
|
||||
@override
|
||||
String get backupResetServer => 'Standardserver verwenden';
|
||||
|
||||
@override
|
||||
String get backupTwonlySaveNow => 'Jetzt speichern';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -463,6 +463,12 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
@override
|
||||
String get close => 'Close';
|
||||
|
||||
@override
|
||||
String get disable => 'Disable';
|
||||
|
||||
@override
|
||||
String get enable => 'Enable';
|
||||
|
||||
@override
|
||||
String get cancel => 'Cancel';
|
||||
|
||||
|
|
@ -843,4 +849,102 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get backupNoticeOpenBackup => 'Create backup';
|
||||
|
||||
@override
|
||||
String get backupPending => 'Pending';
|
||||
|
||||
@override
|
||||
String get backupFailed => 'Failed';
|
||||
|
||||
@override
|
||||
String get backupSuccess => 'Success';
|
||||
|
||||
@override
|
||||
String get backupTwonlySafeDesc =>
|
||||
'Back up your twonly identity, as this is the only way to restore your account if you uninstall the app or lose your phone.';
|
||||
|
||||
@override
|
||||
String get backupServer => 'Server';
|
||||
|
||||
@override
|
||||
String get backupMaxBackupSize => 'max. backup size';
|
||||
|
||||
@override
|
||||
String get backupStorageRetention => 'Storage retention';
|
||||
|
||||
@override
|
||||
String get backupLastBackupDate => 'Last backup';
|
||||
|
||||
@override
|
||||
String get backupLastBackupSize => 'Backup size';
|
||||
|
||||
@override
|
||||
String get backupLastBackupResult => 'Result';
|
||||
|
||||
@override
|
||||
String get deleteBackupTitle => 'Are you sure?';
|
||||
|
||||
@override
|
||||
String get deleteBackupBody =>
|
||||
'Without an backup, you can not restore your user account.';
|
||||
|
||||
@override
|
||||
String get backupData => 'Data-Backup';
|
||||
|
||||
@override
|
||||
String get backupDataDesc =>
|
||||
'This backup contains besides of your twonly-Identity also all of your media files. This backup will is also encrypted but stored locally. You then have to ensure to manually copy it onto your laptop or device of your choice.';
|
||||
|
||||
@override
|
||||
String get backupInsecurePassword => 'Insecure password';
|
||||
|
||||
@override
|
||||
String get backupInsecurePasswordDesc =>
|
||||
'The chosen password is very insecure and can therefore easily be guessed by attackers. Please choose a secure password.';
|
||||
|
||||
@override
|
||||
String get backupInsecurePasswordOk => 'Continue anyway';
|
||||
|
||||
@override
|
||||
String get backupInsecurePasswordCancel => 'Try again';
|
||||
|
||||
@override
|
||||
String get backupTwonlySafeLongDesc =>
|
||||
'twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Safe regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.';
|
||||
|
||||
@override
|
||||
String get backupSelectStrongPassword =>
|
||||
'Choose a secure password. This is required if you want to restore your twonly Safe backup.';
|
||||
|
||||
@override
|
||||
String get password => 'Password';
|
||||
|
||||
@override
|
||||
String get passwordRepeated => 'Repeat password';
|
||||
|
||||
@override
|
||||
String get passwordRepeatedNotEqual => 'Passwords do not match.';
|
||||
|
||||
@override
|
||||
String get backupPasswordRequirement =>
|
||||
'Password must be at least 8 characters long.';
|
||||
|
||||
@override
|
||||
String get backupExpertSettings => 'Expert settings';
|
||||
|
||||
@override
|
||||
String get backupEnableBackup => 'Activate automatic backup';
|
||||
|
||||
@override
|
||||
String get backupOwnServerDesc =>
|
||||
'Save your twonly safe backups at twonly or on any server of your choice.';
|
||||
|
||||
@override
|
||||
String get backupUseOwnServer => 'Use server';
|
||||
|
||||
@override
|
||||
String get backupResetServer => 'Use standard server';
|
||||
|
||||
@override
|
||||
String get backupTwonlySaveNow => 'Save now';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,6 +94,11 @@ Future performTwonlySafeBackup({bool force = false}) async {
|
|||
if (userBackup == null) return;
|
||||
// FILTER settings which should not be in the backup
|
||||
userBackup.twonlySafeBackup = null;
|
||||
userBackup.lastImageSend = null;
|
||||
userBackup.todaysImageCounter = null;
|
||||
userBackup.lastPlanBallance = "";
|
||||
userBackup.additionalUserInvites = "";
|
||||
userBackup.signalLastSignedPreKeyUpdated = null;
|
||||
|
||||
secureStorageBackup[SecureStorageKeys.userData] = jsonEncode(userBackup);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,16 @@ import 'package:flutter/material.dart';
|
|||
import 'package:twonly/src/utils/misc.dart';
|
||||
|
||||
Future<bool> showAlertDialog(
|
||||
BuildContext context, String title, String content) async {
|
||||
BuildContext context,
|
||||
String title,
|
||||
String content, {
|
||||
String? customOk,
|
||||
String? customCancel,
|
||||
}) async {
|
||||
Completer<bool> completer = Completer<bool>();
|
||||
|
||||
Widget okButton = TextButton(
|
||||
child: Text(context.lang.ok),
|
||||
child: Text(customOk ?? context.lang.ok),
|
||||
onPressed: () {
|
||||
completer.complete(true);
|
||||
Navigator.pop(context);
|
||||
|
|
@ -16,7 +21,7 @@ Future<bool> showAlertDialog(
|
|||
);
|
||||
|
||||
Widget cancelButton = TextButton(
|
||||
child: Text(context.lang.cancel),
|
||||
child: Text(customCancel ?? context.lang.cancel),
|
||||
onPressed: () {
|
||||
completer.complete(false);
|
||||
Navigator.pop(context);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ BackupServer defaultBackupServer = BackupServer(
|
|||
class _BackupViewState extends State<BackupView> {
|
||||
TwonlySafeBackup? twonlySafeBackup;
|
||||
BackupServer backupServer = defaultBackupServer;
|
||||
bool isLoading = false;
|
||||
|
||||
int activePageIdx = 0;
|
||||
|
||||
|
|
@ -57,13 +58,13 @@ class _BackupViewState extends State<BackupView> {
|
|||
String backupStatus(LastBackupUploadState status) {
|
||||
switch (status) {
|
||||
case LastBackupUploadState.none:
|
||||
return '-';
|
||||
return '';
|
||||
case LastBackupUploadState.pending:
|
||||
return 'Pending';
|
||||
return context.lang.backupPending;
|
||||
case LastBackupUploadState.failed:
|
||||
return 'Failed';
|
||||
return context.lang.backupFailed;
|
||||
case LastBackupUploadState.success:
|
||||
return 'Success';
|
||||
return context.lang.backupSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -83,37 +84,43 @@ class _BackupViewState extends State<BackupView> {
|
|||
children: [
|
||||
BackupOption(
|
||||
title: 'twonly Safe',
|
||||
description:
|
||||
'Back up your twonly identity, as this is the only way to restore your account if you uninstall or lose your phone.',
|
||||
description: context.lang.backupTwonlySafeDesc,
|
||||
autoBackupEnabled: twonlySafeBackup != null,
|
||||
child: (twonlySafeBackup != null)
|
||||
? Table(
|
||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||
child: (twonlySafeBackup == null)
|
||||
? null
|
||||
: Column(
|
||||
children: [
|
||||
Table(
|
||||
defaultVerticalAlignment:
|
||||
TableCellVerticalAlignment.middle,
|
||||
children: [
|
||||
...[
|
||||
(
|
||||
"Server",
|
||||
context.lang.backupServer,
|
||||
(backupServer.serverUrl.contains("@"))
|
||||
? backupServer.serverUrl.split("@")[1]
|
||||
: backupServer.serverUrl
|
||||
.replaceAll("https://", "")
|
||||
),
|
||||
(
|
||||
"Max. Backup-Größe",
|
||||
context.lang.backupMaxBackupSize,
|
||||
formatBytes(backupServer.maxBackupBytes)
|
||||
),
|
||||
("Speicherdauer", "${backupServer.retentionDays} Days"),
|
||||
(
|
||||
"Letztes Backup",
|
||||
context.lang.backupStorageRetention,
|
||||
"${backupServer.retentionDays} Days"
|
||||
),
|
||||
(
|
||||
context.lang.backupLastBackupDate,
|
||||
formatDateTime(
|
||||
context, twonlySafeBackup!.lastBackupDone)
|
||||
),
|
||||
(
|
||||
"Backup-Größe",
|
||||
context.lang.backupLastBackupSize,
|
||||
formatBytes(twonlySafeBackup!.lastBackupSize)
|
||||
),
|
||||
(
|
||||
"Ergebnis",
|
||||
context.lang.backupLastBackupResult,
|
||||
backupStatus(twonlySafeBackup!.backupUploadState)
|
||||
)
|
||||
].map((pair) {
|
||||
|
|
@ -136,16 +143,37 @@ class _BackupViewState extends State<BackupView> {
|
|||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
FilledButton(
|
||||
onPressed: (isLoading)
|
||||
? null
|
||||
: () async {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
await performTwonlySafeBackup(force: true);
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
},
|
||||
child: Text(context.lang.backupTwonlySaveNow),
|
||||
)
|
||||
: null,
|
||||
],
|
||||
),
|
||||
onTap: () async {
|
||||
if (twonlySafeBackup != null) {
|
||||
bool disable = await showAlertDialog(context, "Are you sure?",
|
||||
"Without an backup, you can not restore your user account.");
|
||||
bool disable = await showAlertDialog(
|
||||
context,
|
||||
context.lang.deleteBackupTitle,
|
||||
context.lang.deleteBackupBody);
|
||||
if (disable) {
|
||||
await disableTwonlySafe();
|
||||
}
|
||||
} else {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
await Navigator.push(context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return TwonlyIdentityBackupView();
|
||||
|
|
@ -155,9 +183,8 @@ class _BackupViewState extends State<BackupView> {
|
|||
},
|
||||
),
|
||||
BackupOption(
|
||||
title: 'Daten-Backup (Coming Soon)',
|
||||
description:
|
||||
'This backup contains besides of your twonly-Identity also all of your media files. This backup will also be encrypted using a password chosen by the user but stored locally on the smartphone. You then have to ensure to manually copy it onto your laptop or device of your choice.',
|
||||
title: "${context.lang.backupData} (Coming Soon)",
|
||||
description: context.lang.backupDataDesc,
|
||||
autoBackupEnabled: false,
|
||||
onTap: null,
|
||||
),
|
||||
|
|
@ -177,7 +204,7 @@ class _BackupViewState extends State<BackupView> {
|
|||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: FaIcon(FontAwesomeIcons.boxArchive, size: 17),
|
||||
label: "Daten-Backup",
|
||||
label: context.lang.backupData,
|
||||
),
|
||||
],
|
||||
onTap: (int index) {
|
||||
|
|
@ -237,11 +264,11 @@ class BackupOption extends StatelessWidget {
|
|||
child: (autoBackupEnabled)
|
||||
? OutlinedButton(
|
||||
onPressed: onTap,
|
||||
child: Text("Disable"),
|
||||
child: Text(context.lang.disable),
|
||||
)
|
||||
: FilledButton(
|
||||
onPressed: onTap,
|
||||
child: Text("Enable"),
|
||||
child: Text(context.lang.enable),
|
||||
),
|
||||
)
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:flutter/services.dart' show rootBundle;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
|
|
@ -21,6 +22,21 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
|||
final TextEditingController repeatedPasswordCtrl = TextEditingController();
|
||||
|
||||
Future onPressedEnableTwonlySafe() async {
|
||||
if (!mounted) return;
|
||||
if (!await isSecurePassword(passwordCtrl.text)) {
|
||||
if (!mounted) return;
|
||||
bool ignore = await showAlertDialog(
|
||||
context,
|
||||
context.lang.backupInsecurePassword,
|
||||
context.lang.backupInsecurePasswordDesc,
|
||||
customCancel: context.lang.backupInsecurePasswordOk,
|
||||
customOk: context.lang.backupInsecurePasswordCancel,
|
||||
);
|
||||
if (ignore) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
|
|
@ -45,7 +61,7 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
|||
IconButton(
|
||||
onPressed: () {
|
||||
showAlertDialog(context, "twonly Safe",
|
||||
"twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen user name so that others can find you.\n\ntwonly Safe regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device. ");
|
||||
context.lang.backupTwonlySafeLongDesc);
|
||||
},
|
||||
icon: FaIcon(FontAwesomeIcons.circleInfo),
|
||||
iconSize: 18,
|
||||
|
|
@ -57,7 +73,7 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
|||
child: ListView(
|
||||
children: [
|
||||
Text(
|
||||
"Wähle ein sicheres Passwort. Dieses wird benötigt, wenn du dein twonly Safe-Backup wiederherstellen möchtest.",
|
||||
context.lang.backupSelectStrongPassword,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
|
|
@ -67,16 +83,12 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
|||
controller: passwordCtrl,
|
||||
onChanged: (value) {
|
||||
setState(() {});
|
||||
// usernameController.text = value.toLowerCase();
|
||||
// usernameController.selection = TextSelection.fromPosition(
|
||||
// TextPosition(offset: usernameController.text.length),
|
||||
// );
|
||||
},
|
||||
style: TextStyle(fontSize: 17),
|
||||
obscureText: obscureText,
|
||||
decoration: getInputDecoration(
|
||||
context,
|
||||
"Password",
|
||||
context.lang.password,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
|
|
@ -102,9 +114,9 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
|||
Padding(
|
||||
padding: EdgeInsetsGeometry.all(5),
|
||||
child: Text(
|
||||
"Passwort muss mind. 10 Zeichen lang sein.",
|
||||
context.lang.backupPasswordRequirement,
|
||||
style: TextStyle(
|
||||
color: ((passwordCtrl.text.length <= 10 &&
|
||||
color: ((passwordCtrl.text.length < 8 &&
|
||||
passwordCtrl.text.isNotEmpty))
|
||||
? Colors.red
|
||||
: Colors.transparent),
|
||||
|
|
@ -115,22 +127,18 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
|||
controller: repeatedPasswordCtrl,
|
||||
onChanged: (value) {
|
||||
setState(() {});
|
||||
// usernameController.text = value.toLowerCase();
|
||||
// usernameController.selection = TextSelection.fromPosition(
|
||||
// TextPosition(offset: usernameController.text.length),
|
||||
// );
|
||||
},
|
||||
style: TextStyle(fontSize: 17),
|
||||
obscureText: true,
|
||||
decoration: getInputDecoration(
|
||||
context,
|
||||
"Passwordwiederholung",
|
||||
context.lang.passwordRepeated,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsetsGeometry.all(5),
|
||||
child: Text(
|
||||
"Passwörter stimmen nicht überein.",
|
||||
context.lang.passwordRepeatedNotEqual,
|
||||
style: TextStyle(
|
||||
color: (passwordCtrl.text != repeatedPasswordCtrl.text &&
|
||||
repeatedPasswordCtrl.text.isNotEmpty)
|
||||
|
|
@ -146,7 +154,7 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
|||
return TwonlySafeServerView();
|
||||
}));
|
||||
},
|
||||
child: Text("Experten Einstellungen"),
|
||||
child: Text(context.lang.backupExpertSettings),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
|
|
@ -165,7 +173,7 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
|||
child: CircularProgressIndicator(strokeWidth: 1),
|
||||
)
|
||||
: Icon(Icons.lock_clock_rounded),
|
||||
label: Text("Automatisches Backup aktivieren"),
|
||||
label: Text(context.lang.backupEnableBackup),
|
||||
))
|
||||
],
|
||||
),
|
||||
|
|
@ -173,3 +181,16 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> isSecurePassword(String password) async {
|
||||
String badPasswordsStr =
|
||||
await rootBundle.loadString('assets/passwords/bad_passwords.txt');
|
||||
List<String> badPasswords = badPasswordsStr.split("\n");
|
||||
if (badPasswords.contains(password)) {
|
||||
return false;
|
||||
}
|
||||
// Check if the password meets all criteria
|
||||
return RegExp(r'[A-Z]').hasMatch(password) &&
|
||||
RegExp(r'[a-z]').hasMatch(password) &&
|
||||
RegExp(r'[0-9]').hasMatch(password);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:twonly/src/model/json/userdata.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/utils/storage.dart';
|
||||
|
||||
class TwonlySafeServerView extends StatefulWidget {
|
||||
|
|
@ -58,8 +58,8 @@ class _TwonlySafeServerViewState extends State<TwonlySafeServerView> {
|
|||
serverUrl = "https://$username@$password$serverUrl";
|
||||
}
|
||||
|
||||
try {
|
||||
final uri = Uri.parse("${serverUrl}config");
|
||||
|
||||
final response = await http.get(
|
||||
uri,
|
||||
headers: {
|
||||
|
|
@ -67,8 +67,6 @@ class _TwonlySafeServerViewState extends State<TwonlySafeServerView> {
|
|||
'Accept': 'application/json',
|
||||
},
|
||||
);
|
||||
|
||||
try {
|
||||
if (response.statusCode == 200) {
|
||||
// If the server returns a 200 OK response, parse the JSON.
|
||||
final data = jsonDecode(response.body);
|
||||
|
|
@ -111,7 +109,7 @@ class _TwonlySafeServerViewState extends State<TwonlySafeServerView> {
|
|||
child: ListView(
|
||||
children: [
|
||||
Text(
|
||||
"Speichere dein twonly Safe-Backup bei twonly oder auf einem beliebigen Server deiner Wahl.",
|
||||
context.lang.backupOwnServerDesc,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
|
|
@ -156,7 +154,7 @@ class _TwonlySafeServerViewState extends State<TwonlySafeServerView> {
|
|||
? checkAndUpdateBackupServer
|
||||
: null,
|
||||
icon: FaIcon(FontAwesomeIcons.server),
|
||||
label: Text('Server verwenden'),
|
||||
label: Text(context.lang.backupUseOwnServer),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10.0),
|
||||
|
|
@ -169,7 +167,7 @@ class _TwonlySafeServerViewState extends State<TwonlySafeServerView> {
|
|||
});
|
||||
if (context.mounted) Navigator.pop(context);
|
||||
},
|
||||
child: Text("Standardserver verwenden"),
|
||||
child: Text(context.lang.backupResetServer),
|
||||
),
|
||||
)
|
||||
],
|
||||
|
|
|
|||
Loading…
Reference in a new issue