From 4c5575307f148b4071f6ece3eae228a1021fabb2 Mon Sep 17 00:00:00 2001 From: Sabrina Tardio Date: Mon, 29 Apr 2024 23:18:22 +0200 Subject: [PATCH] update copy --- .../Common/Extensions/NSAlertExtension.swift | 2 +- DuckDuckGo/Common/Localizables/UserText.swift | 22 ++- DuckDuckGo/Localizable.xcstrings | 172 ++++++++++++++---- DuckDuckGo/Sync/SyncErrorHandler.swift | 42 +++-- 4 files changed, 173 insertions(+), 65 deletions(-) diff --git a/DuckDuckGo/Common/Extensions/NSAlertExtension.swift b/DuckDuckGo/Common/Extensions/NSAlertExtension.swift index 1965b18f93..af916cc6a0 100644 --- a/DuckDuckGo/Common/Extensions/NSAlertExtension.swift +++ b/DuckDuckGo/Common/Extensions/NSAlertExtension.swift @@ -174,7 +174,7 @@ extension NSAlert { alert.informativeText = informative alert.alertStyle = .warning alert.addButton(withTitle: UserText.ok) - alert.addButton(withTitle: UserText.learnMore) + alert.addButton(withTitle: UserText.syncErrorAlertAction) return alert } diff --git a/DuckDuckGo/Common/Localizables/UserText.swift b/DuckDuckGo/Common/Localizables/UserText.swift index f574efb86c..9999fe9496 100644 --- a/DuckDuckGo/Common/Localizables/UserText.swift +++ b/DuckDuckGo/Common/Localizables/UserText.swift @@ -556,18 +556,28 @@ struct UserText { static let general = NSLocalizedString("preferences.general", value: "General", comment: "Title of the option to show the General preferences") static let sync = NSLocalizedString("preferences.sync", value: "Sync & Backup", comment: "Title of the option to show the Sync preferences") static let syncAutoLockPrompt = NSLocalizedString("preferences.sync.auto-lock-prompt", value: "Unlock device to setup Sync & Backup", comment: "Reason for auth when setting up Sync") - static let syncBookmarkPausedAlertTitle = NSLocalizedString("alert.sync-bookmarks-paused-title", value: "Bookmarks Sync is Paused", comment: "Title for alert shown when sync bookmarks paused for too many items") - static let syncBookmarkPausedAlertDescription = NSLocalizedString("alert.sync-bookmarks-paused-description", value: "You have exceeded the bookmarks sync limit. Try deleting some bookmarks. Until this is resolved your bookmarks will not be backed up.", comment: "Description for alert shown when sync bookmarks paused for too many items") - static let syncCredentialsPausedAlertTitle = NSLocalizedString("alert.sync-credentials-paused-title", value: "Passwords Sync is Paused", comment: "Title for alert shown when sync credentials paused for too many items") - static let syncCredentialsPausedAlertDescription = NSLocalizedString("alert.sync-credentials-paused-description", value: "You have exceeded the passwords sync limit. Try deleting some passwords. Until this is resolved your passwords will not be backed up.", comment: "Description for alert shown when sync credentials paused for too many items") + static let syncBookmarkPausedAlertTitle = NSLocalizedString("alert.sync-bookmarks-paused-title", value: "Bookmark Sync is Paused", comment: "Title for alert shown when sync bookmarks paused for too many items") + static let syncBookmarkPausedAlertDescription = NSLocalizedString("alert.sync-bookmarks-paused-description", value: "You've reached the maximum number of bookmarks. Please delete some bookmarks to resume sync.", comment: "Description for alert shown when sync bookmarks paused for too many items") + static let syncCredentialsPausedAlertTitle = NSLocalizedString("alert.sync-credentials-paused-title", value: "Password Sync is Paused", comment: "Title for alert shown when sync credentials paused for too many items") + static let syncCredentialsPausedAlertDescription = NSLocalizedString("alert.sync-credentials-paused-description", value: "You've reached the maximum number of passwords. Please delete some passwords to resume sync.", comment: "Description for alert shown when sync credentials paused for too many items") static let syncPausedTitle = NSLocalizedString("alert.sync.warning.sync-paused", value: "Sync & Backup is Paused", comment: "Title of the warning message") static let syncUnavailableMessage = NSLocalizedString("alert.sync.warning.sync-unavailable-message", value: "Sorry, but Sync & Backup is currently unavailable. Please try again later.", comment: "Data syncing unavailable warning message") static let syncUnavailableMessageUpgradeRequired = NSLocalizedString("alert.sync.warning.data-syncing-disabled-upgrade-required", value: "Sorry, but Sync & Backup is no longer available in this app version. Please update DuckDuckGo to the latest version to continue.", comment: "Data syncing unavailable warning message") + static let syncErrorAlertTitle = NSLocalizedString("alert.sync-error-title", value: "Sync Error", comment: "Title for alert shown when sync error occurs") + static let syncPausedAlertTitle = NSLocalizedString("alert.sync-paused-title", value: "Sync is Paused", comment: "Title for alert shown when sync paused for an error") + static let syncInvalidLoginAlertDescription = NSLocalizedString("alert.sync-invalid-login-error-description", value: "Sync encountered an error. Please disable sync and reconnect using your recovery code.", comment: "Description for alert shown when sync error occurs because of invalid login credentials") + static let syncTooManyRequestsAlertDescription = NSLocalizedString("alert.sync-too-many-requests-error-description", value: "Sync & Backup is temporarily unavailable.", comment: "Description for alert shown when sync error occurs because of too many requests") + static let syncBadRequestAlertDescription = NSLocalizedString("alert.sync-bad-data-error-description", value: "Some bookmarks or passwords are formatted incorrectly or too long and were not synced.", comment: "Description for alert shown when sync error occurs because of bad data") + static let syncErrorAlertAction = NSLocalizedString("alert.sync-error-action", value: "Sync Settings", comment: "Sync error alert action button title, takes the user to the sync settings page.") // Sync Errors static let syncLimitExceededTitle = NSLocalizedString("prefrences.sync.limit-exceeded-title", value: "Sync Paused", comment: "Title for sync limits exceeded warning") - static let bookmarksLimitExceededDescription = NSLocalizedString("prefrences.sync.bookmarks-limit-exceeded-description", value: "Bookmark limit exceeded. Delete some to resume syncing.", comment: "Description for sync bookmarks limits exceeded warning") - static let credentialsLimitExceededDescription = NSLocalizedString("prefrences.sync.credentials-limit-exceeded-description", value: "Logins limit exceeded. Delete some to resume syncing.", comment: "Description for sync credentials limits exceeded warning") + static let syncErrorTitle = NSLocalizedString("alert.sync.warning.sync-error", value: "Sync Error", comment: "Title of the warning message that tells the user that there was an error with the sync feature.") + static let bookmarksLimitExceededDescription = NSLocalizedString("prefrences.sync.bookmarks-limit-exceeded-description", value: "You've reached the maximum number of bookmarks. Please delete some to resume sync.", comment: "Description for sync bookmarks limits exceeded warning") + static let credentialsLimitExceededDescription = NSLocalizedString("prefrences.sync.credentials-limit-exceeded-description", value: "You've reached the maximum number of passwords. Please delete some to resume sync.", comment: "Description for sync credentials limits exceeded warning") + static let invalidLoginCredentialErrorDescription = NSLocalizedString("prefrences.sync.invalid-login-description", value: "Sync encountered an error. Try disabling sync on this device and then reconnect using another device or your recovery code.", comment: "Description invalid credentials error when syncing.") + static let tooManyRequestsErrorDescription = NSLocalizedString("prefrences.sync.invalid-login-description", value: "Sync & Backup is temporarily unavailable.", comment: "Description of too many requests error when syncing.") + static let badRequestErrorDescription = NSLocalizedString("prefrences.sync.invalid-login-description", value: "Some bookmarks or passwords are formatted incorrectly or too long and were not synced.", comment: "Description of incorrectly formatted data error when syncing.") static let bookmarksLimitExceededAction = NSLocalizedString("prefrences.sync.bookmarks-limit-exceeded-action", value: "Manage Bookmarks", comment: "Button title for sync bookmarks limits exceeded warning to go to manage bookmarks") static let credentialsLimitExceededAction = NSLocalizedString("prefrences.sync.credentials-limit-exceeded-action", value: "Manage passwords…", comment: "Button title for sync credentials limits exceeded warning to go to manage passwords") diff --git a/DuckDuckGo/Localizable.xcstrings b/DuckDuckGo/Localizable.xcstrings index 369026b5b0..eac8a095d0 100644 --- a/DuckDuckGo/Localizable.xcstrings +++ b/DuckDuckGo/Localizable.xcstrings @@ -1414,61 +1414,73 @@ } } }, + "alert.sync-bad-data-error-description" : { + "comment" : "Description for alert shown when sync error occurs because of bad data", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Some bookmarks or passwords are formatted incorrectly or too long and were not synced." + } + } + } + }, "alert.sync-bookmarks-paused-description" : { "comment" : "Description for alert shown when sync bookmarks paused for too many items", "extractionState" : "extracted_with_value", "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Du hast das Limit für die Synchronisierung von Lesezeichen überschritten. Versuche, einige Lesezeichen zu löschen. Bis dieses Problem behoben ist, werden deine Lesezeichen nicht gesichert." } }, "en" : { "stringUnit" : { "state" : "new", - "value" : "You have exceeded the bookmarks sync limit. Try deleting some bookmarks. Until this is resolved your bookmarks will not be backed up." + "value" : "You've reached the maximum number of bookmarks. Please delete some bookmarks to resume sync." } }, "es" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Has superado el límite de sincronización de marcadores. Prueba a eliminar algunos marcadores. No se realizará una copia de seguridad de los marcadores hasta que se resuelva esto." } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Vous avez dépassé le nombre maximal de signets à synchroniser. Veuillez en supprimer quelques-uns pour pouvoir sauvegarder vos signets." } }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Hai superato il limite di sincronizzazione dei segnalibri. Prova a eliminarne qualcuno. Fino a quando il problema non verrà risolto, non sarà eseguito il backup dei tuoi segnalibri." } }, "nl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Je hebt de synchronisatielimiet voor bladwijzers overschreden. Probeer enkele bladwijzers te verwijderen. Er wordt geen back-up van je bladwijzers gemaakt totdat dit probleem is opgelost." } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Przekroczono limit synchronizacji zakładek. Spróbuj usunąć niektóre zakładki. Dopóki ten problem nie zostanie rozwiązany, nie będzie tworzona kopia zapasowa zakładek." } }, "pt" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Excedeste o limite de sincronização de favoritos. Experimenta eliminar alguns favoritos. Não é possível fazer uma cópia de segurança dos favoritos até este problema estar resolvido." } }, "ru" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Вы превысили лимит синхронизации закладок. Попробуйте удалить некоторые из них. Пока вы не устраните эту проблему, резервная копия закладок создаваться не будет." } } @@ -1480,55 +1492,55 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Lesezeichen-Synchronisierung ist angehalten" } }, "en" : { "stringUnit" : { "state" : "new", - "value" : "Bookmarks Sync is Paused" + "value" : "Bookmark Sync is Paused" } }, "es" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "La sincronización de marcadores está en pausa" } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "La synchronisation des signets est suspendue" } }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "La sincronizzazione dei segnalibri è in pausa" } }, "nl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Synchronisatie van bladwijzers is gepauzeerd" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Synchronizacja zakładek jest wstrzymana" } }, "pt" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "A sincronização de favoritos está em pausa" } }, "ru" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Синхронизация закладок приостановлена" } } @@ -1540,55 +1552,55 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Du hast das Limit für die Synchronisierung von Passwörtern überschritten. Versuche, einige Passwörter zu löschen. Bis dieses Problem behoben ist, werden deine Passwörter nicht gesichert." } }, "en" : { "stringUnit" : { "state" : "new", - "value" : "You have exceeded the passwords sync limit. Try deleting some passwords. Until this is resolved your passwords will not be backed up." + "value" : "You've reached the maximum number of passwords. Please delete some passwords to resume sync." } }, "es" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Ha superado el límite de sincronización de contraseñas. Prueba a eliminar algunas contraseñas. No se realizará una copia de seguridad de las contraseñas hasta que se resuelva esto." } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Vous avez dépassé le nombre maximal de mots de passe à synchroniser. Veuillez en supprimer quelques-uns pour pouvoir sauvegarder vos mots de passe." } }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Hai superato il limite di sincronizzazione delle password. Prova a eliminarne qualcuna. Fino a quando il problema non verrà risolto, non sarà eseguito il backup delle tue password." } }, "nl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Je hebt de synchronisatielimiet voor wachtwoorden overschreden. Probeer enkele wachtwoorden te verwijderen. Er wordt geen back-up van je wachtwoorden gemaakt totdat dit probleem is opgelost." } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Przekroczono limit synchronizacji haseł. Spróbuj usunąć niektóre hasła. Dopóki ten problem nie zostanie rozwiązany, nie będzie tworzona kopia zapasowa haseł." } }, "pt" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Excedeste o limite de sincronização de palavras-passe. Experimenta eliminar algumas palavras-passe. Não é possível fazer uma cópia de segurança das palavras-passe até este problema estar resolvido." } }, "ru" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Вы превысили лимит синхронизации паролей. Попробуйте удалить некоторые из них. Пока вы не устраните эту проблему, резервная копия закладок создаваться не будет." } } @@ -1600,60 +1612,120 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Passwortsynchronisierung ist angehalten" } }, "en" : { "stringUnit" : { "state" : "new", - "value" : "Passwords Sync is Paused" + "value" : "Password Sync is Paused" } }, "es" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "La sincronización de contraseñas está en pausa" } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "La synchronisation des mots de passe est suspendue" } }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "La sincronizzazione delle password è in pausa" } }, "nl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Synchronisatie van wachtwoorden is gepauzeerd" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Synchronizacja haseł jest wstrzymana" } }, "pt" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "A sincronização de palavras-passe está em pausa" } }, "ru" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Синхронизация паролей приостановлена" } } } }, + "alert.sync-error-action" : { + "comment" : "Sync error alert action button title, takes the user to the sync settings page.", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Sync Settings" + } + } + } + }, + "alert.sync-error-title" : { + "comment" : "Title for alert shown when sync error occurs", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Sync Error" + } + } + } + }, + "alert.sync-invalid-login-error-description" : { + "comment" : "Description for alert shown when sync error occurs because of invalid login credentials", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Sync encountered an error. Please disable sync and reconnect using your recovery code." + } + } + } + }, + "alert.sync-paused-title" : { + "comment" : "Title for alert shown when sync paused for an error", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Sync is Paused" + } + } + } + }, + "alert.sync-too-many-requests-error-description" : { + "comment" : "Description for alert shown when sync error occurs because of too many requests", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Sync & Backup is temporarily unavailable." + } + } + } + }, "alert.sync.warning.data-syncing-disabled-upgrade-required" : { "comment" : "Data syncing unavailable warning message", "extractionState" : "extracted_with_value", @@ -1714,6 +1786,18 @@ } } }, + "alert.sync.warning.sync-error" : { + "comment" : "Title of the warning message that tells the user that there was an error with the sync feature.", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Sync Error" + } + } + } + }, "alert.sync.warning.sync-paused" : { "comment" : "Title of the warning message", "extractionState" : "extracted_with_value", @@ -45703,7 +45787,7 @@ "en" : { "stringUnit" : { "state" : "new", - "value" : "Bookmark limit exceeded. Delete some to resume syncing." + "value" : "You've reached the maximum number of bookmarks. Please delete some to resume sync." } } } @@ -45727,7 +45811,19 @@ "en" : { "stringUnit" : { "state" : "new", - "value" : "Logins limit exceeded. Delete some to resume syncing." + "value" : "You've reached the maximum number of passwords. Please delete some to resume sync." + } + } + } + }, + "prefrences.sync.invalid-login-description" : { + "comment" : "Description invalid credentials error when syncing.\n Description of incorrectly formatted data error when syncing.\n Description of too many requests error when syncing.", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Sync encountered an error. Try disabling sync on this device and then reconnect using another device or your recovery code." } } } diff --git a/DuckDuckGo/Sync/SyncErrorHandler.swift b/DuckDuckGo/Sync/SyncErrorHandler.swift index 23222c2d80..decf0ec6c0 100644 --- a/DuckDuckGo/Sync/SyncErrorHandler.swift +++ b/DuckDuckGo/Sync/SyncErrorHandler.swift @@ -128,36 +128,33 @@ public class SyncErrorHandler: EventMapping, ObservableObject { (areThere10ConsecutiveError || noSuccessfulSyncInLast12h) } - private var syncPausedMessage: String? { + private var syncPausedTitle: String? { guard let error = currentSyncAllPausedError else { return nil } switch error { case .invalidLoginCredentials: - return "Invalid Login" - case .tooManyRequests: - return "Too many requests" - case .unknown: - return "Unknown" + return UserText.syncPausedTitle + case .tooManyRequests, .badRequest: + return UserText.syncErrorTitle default: assertionFailure("Sync Paused error should be one of those listes") return nil } } - private var syncPausedButtonTitle: String? { + private var syncPausedMessage: String? { guard let error = currentSyncAllPausedError else { return nil } switch error { case .invalidLoginCredentials: - return "Invalid Login" + return UserText.invalidLoginCredentialErrorDescription case .tooManyRequests: - return "Too many requests" - case .unknown: - return "Unknown" + return UserText.tooManyRequestsErrorDescription + case .badRequest: + return UserText.badRequestErrorDescription default: assertionFailure("Sync Paused error should be one of those listes") return nil } } - } extension SyncErrorHandler: SyncAdapterErrorHandler { @@ -213,7 +210,7 @@ extension SyncErrorHandler: SyncAdapterErrorHandler { case .unexpectedStatusCode(401): syncIsPaused(errorType: .invalidLoginCredentials) case .unexpectedStatusCode(400): - syncIsPaused(errorType: .unknown) + syncIsPaused(errorType: .badRequest) case .unexpectedStatusCode(418), .unexpectedStatusCode(429): syncIsPaused(errorType: .tooManyRequests) default: @@ -239,7 +236,7 @@ extension SyncErrorHandler: SyncAdapterErrorHandler { case .invalidLoginCredentials: currentSyncAllPausedError = errorType self.isSyncPaused = true - case .tooManyRequests, .unknown: + case .tooManyRequests, .badRequest: currentSyncAllPausedError = errorType self.isSyncPaused = true } @@ -260,11 +257,15 @@ extension SyncErrorHandler: SyncAdapterErrorHandler { didShowCredentialsSyncPausedError = true case .invalidLoginCredentials: guard !didShowInvalidLoginSyncPausedError else { return } - alert = NSAlert.syncPaused(title: "Invalid Credentials", informative: "Invalid Credentials") + alert = NSAlert.syncPaused(title: UserText.syncPausedAlertTitle, informative: UserText.syncInvalidLoginAlertDescription) didShowInvalidLoginSyncPausedError = true - case .tooManyRequests, .unknown: + case .tooManyRequests: guard shouldShowAlertForNonActionableError() == true else { return } - alert = NSAlert.syncPaused(title: "Non Actionable Error", informative: "Non Actionable Error") + alert = NSAlert.syncPaused(title: UserText.syncErrorAlertTitle, informative: UserText.syncTooManyRequestsAlertDescription) + lastErrorNotificationTime = Date() + case .badRequest: + guard shouldShowAlertForNonActionableError() == true else { return } + alert = NSAlert.syncPaused(title: UserText.syncErrorAlertTitle, informative: UserText.syncBadRequestAlertDescription) lastErrorNotificationTime = Date() } alertPresenter.showAlert(alert) @@ -279,7 +280,7 @@ extension SyncErrorHandler: SyncAdapterErrorHandler { case credentialsRequestSizeLimitExceeded case invalidLoginCredentials case tooManyRequests - case unknown + case badRequest } private enum ModelType { @@ -305,9 +306,10 @@ extension SyncErrorHandler: SyncAdapterErrorHandler { extension SyncErrorHandler: SyncPreferencesErrorHandler { var syncPausedMetadata: SyncPausedErrorMetadata? { guard let syncPausedMessage else { return nil } - return SyncPausedErrorMetadata(syncPausedTitle: UserText.syncLimitExceededTitle, + guard let syncPausedTitle else { return nil } + return SyncPausedErrorMetadata(syncPausedTitle: syncPausedTitle, syncPausedMessage: syncPausedMessage, - syncPausedButtonTitle: syncPausedButtonTitle ?? "", + syncPausedButtonTitle: "", syncPausedAction: nil) }