diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2021-07-22 13:08:18 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2021-07-22 13:08:18 +0200 |
| commit | 43a5f956fbc8fc137367fb6676c7c34d3e8f93cf (patch) | |
| tree | 4b51efff61dff08363bca633d932dc1d5f88aad8 | |
| parent | fc34d04f9b7ca18267230be55267f04c82c9c96a (diff) | |
| parent | 97496dd3732958f4c9c9e3599ccf37c8da91f21c (diff) | |
| download | mullvadvpn-43a5f956fbc8fc137367fb6676c7c34d3e8f93cf.tar.xz mullvadvpn-43a5f956fbc8fc137367fb6676c7c34d3e8f93cf.zip | |
Merge branch 'localize-various-errors'
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 108 | ||||
| -rw-r--r-- | ios/MullvadVPN/AccountInputGroupView.swift | 7 | ||||
| -rw-r--r-- | ios/MullvadVPN/AppDelegate.swift | 23 | ||||
| -rw-r--r-- | ios/MullvadVPN/CustomDateComponentsFormatting.swift | 7 | ||||
| -rw-r--r-- | ios/MullvadVPN/DisplayChainedError.swift | 282 | ||||
| -rw-r--r-- | ios/MullvadVPN/HeaderBarView.swift | 7 | ||||
| -rw-r--r-- | ios/MullvadVPN/MullvadRest.swift | 21 | ||||
| -rw-r--r-- | ios/MullvadVPN/UIBarButtonItem+KeyboardNavigation.swift | 14 | ||||
| -rw-r--r-- | ios/MullvadVPN/en.lproj/AccountInput.strings | 2 | ||||
| -rw-r--r-- | ios/MullvadVPN/en.lproj/AppDelegate.strings | 8 | ||||
| -rw-r--r-- | ios/MullvadVPN/en.lproj/AppStorePaymentManager.strings | 17 | ||||
| -rw-r--r-- | ios/MullvadVPN/en.lproj/CustomDateComponentsFormatting.strings | 2 | ||||
| -rw-r--r-- | ios/MullvadVPN/en.lproj/HeaderBar.strings | 2 | ||||
| -rw-r--r-- | ios/MullvadVPN/en.lproj/KeyboardNavigation.strings | 5 | ||||
| -rw-r--r-- | ios/MullvadVPN/en.lproj/MullvadRest.strings | 23 | ||||
| -rw-r--r-- | ios/MullvadVPN/en.lproj/StoreKitErrors.strings | 14 | ||||
| -rw-r--r-- | ios/MullvadVPN/en.lproj/TunnelManager.strings | 53 |
17 files changed, 545 insertions, 50 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index e3c651d6c4..9f9274c748 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -227,9 +227,18 @@ 58F558E32695D1D800F630D0 /* Preferences.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F558E12695D1D800F630D0 /* Preferences.strings */; }; 58F558E62695D1F200F630D0 /* ProblemReport.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F558E42695D1F200F630D0 /* ProblemReport.strings */; }; 58F558E92695D20F00F630D0 /* SelectLocation.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F558E72695D20F00F630D0 /* SelectLocation.strings */; }; + 58F558EC2695D26A00F630D0 /* MullvadRest.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F558EA2695D26A00F630D0 /* MullvadRest.strings */; }; 58F558EF2695D50D00F630D0 /* ProblemReportReview.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F558ED2695D50D00F630D0 /* ProblemReportReview.strings */; }; + 58F558F92696EB1C00F630D0 /* StoreKitErrors.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F558F32696EB1C00F630D0 /* StoreKitErrors.strings */; }; + 58F558FA2696EB1C00F630D0 /* TunnelManager.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F558F52696EB1C00F630D0 /* TunnelManager.strings */; }; + 58F558FB2696EB1C00F630D0 /* AppStorePaymentManager.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F558F72696EB1C00F630D0 /* AppStorePaymentManager.strings */; }; 58F5590E2697002100F630D0 /* Main.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F559052697002000F630D0 /* Main.strings */; }; 58F5590F2697002100F630D0 /* ConnectionPanel.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F559072697002100F630D0 /* ConnectionPanel.strings */; }; + 58F558FE2696F09100F630D0 /* KeyboardNavigation.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F558FC2696F09100F630D0 /* KeyboardNavigation.strings */; }; + 58F5590B2697002100F630D0 /* CustomDateComponentsFormatting.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F558FF2697002000F630D0 /* CustomDateComponentsFormatting.strings */; }; + 58F5590C2697002100F630D0 /* AppDelegate.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F559012697002000F630D0 /* AppDelegate.strings */; }; + 58F5590D2697002100F630D0 /* AccountInput.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F559032697002000F630D0 /* AccountInput.strings */; }; + 58F559102697002100F630D0 /* HeaderBar.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F559092697002100F630D0 /* HeaderBar.strings */; }; 58F61F4F2692F21C00DCFC2B /* WireguardKeys.strings in Resources */ = {isa = PBXBuildFile; fileRef = 58F61F4D2692F21C00DCFC2B /* WireguardKeys.strings */; }; 58F7CA882692E34000FC59FD /* WireguardKeysContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F7CA872692E34000FC59FD /* WireguardKeysContentView.swift */; }; 58F840AF2464382C0044E708 /* KeychainItemRevision.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F840AE2464382C0044E708 /* KeychainItemRevision.swift */; }; @@ -451,9 +460,18 @@ 58F558E22695D1D800F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Preferences.strings; sourceTree = "<group>"; }; 58F558E52695D1F200F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/ProblemReport.strings; sourceTree = "<group>"; }; 58F558E82695D20F00F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/SelectLocation.strings; sourceTree = "<group>"; }; + 58F558EB2695D26A00F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/MullvadRest.strings; sourceTree = "<group>"; }; 58F558EE2695D50D00F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/ProblemReportReview.strings; sourceTree = "<group>"; }; + 58F558F42696EB1C00F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/StoreKitErrors.strings; sourceTree = "<group>"; }; + 58F558F62696EB1C00F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/TunnelManager.strings; sourceTree = "<group>"; }; + 58F558F82696EB1C00F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/AppStorePaymentManager.strings; sourceTree = "<group>"; }; 58F559062697002000F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Main.strings; sourceTree = "<group>"; }; 58F559082697002100F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/ConnectionPanel.strings; sourceTree = "<group>"; }; + 58F558FD2696F09100F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/KeyboardNavigation.strings; sourceTree = "<group>"; }; + 58F559002697002000F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/CustomDateComponentsFormatting.strings; sourceTree = "<group>"; }; + 58F559022697002000F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/AppDelegate.strings; sourceTree = "<group>"; }; + 58F559042697002000F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/AccountInput.strings; sourceTree = "<group>"; }; + 58F5590A2697002100F630D0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/HeaderBar.strings; sourceTree = "<group>"; }; 58F61F4E2692F21C00DCFC2B /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/WireguardKeys.strings; sourceTree = "<group>"; }; 58F7CA872692E34000FC59FD /* WireguardKeysContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WireguardKeysContentView.swift; sourceTree = "<group>"; }; 58F840AE2464382C0044E708 /* KeychainItemRevision.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainItemRevision.swift; sourceTree = "<group>"; }; @@ -559,17 +577,26 @@ isa = PBXGroup; children = ( 581FC4F82695ACE100AA97BA /* Account.strings */, + 58F559032697002000F630D0 /* AccountInput.strings */, + 58F559012697002000F630D0 /* AppDelegate.strings */, + 58F558F72696EB1C00F630D0 /* AppStorePaymentManager.strings */, 582CFEE526945FC30072883A /* AppStoreSubscriptions.strings */, 58F559072697002100F630D0 /* ConnectionPanel.strings */, 58F558DB2695B85E00F630D0 /* Consent.strings */, + 58F558FF2697002000F630D0 /* CustomDateComponentsFormatting.strings */, + 58F559092697002100F630D0 /* HeaderBar.strings */, + 58F558FC2696F09100F630D0 /* KeyboardNavigation.strings */, 587B7543266922BF00DEF7E9 /* Localizable.strings */, 58F558DE2695BD3E00F630D0 /* Login.strings */, 58F559052697002000F630D0 /* Main.strings */, + 58F558EA2695D26A00F630D0 /* MullvadRest.strings */, 58F558E12695D1D800F630D0 /* Preferences.strings */, 58F558E42695D1F200F630D0 /* ProblemReport.strings */, 58F558ED2695D50D00F630D0 /* ProblemReportReview.strings */, 58F558E72695D20F00F630D0 /* SelectLocation.strings */, 582CFEE8269463B80072883A /* Settings.strings */, + 58F558F32696EB1C00F630D0 /* StoreKitErrors.strings */, + 58F558F52696EB1C00F630D0 /* TunnelManager.strings */, 58F61F4D2692F21C00DCFC2B /* WireguardKeys.strings */, ); name = Localizations; @@ -978,8 +1005,10 @@ 58F3C0A624A50157003E76BE /* relays.json in Resources */, 58F558DD2695B85E00F630D0 /* Consent.strings in Resources */, 58727283265D173C00F315B2 /* LaunchScreen.storyboard in Resources */, + 58F558FB2696EB1C00F630D0 /* AppStorePaymentManager.strings in Resources */, 586ADD4723FC13F400CE9E87 /* countries.geo.json in Resources */, 58F5590F2697002100F630D0 /* ConnectionPanel.strings in Resources */, + 58F558FA2696EB1C00F630D0 /* TunnelManager.strings in Resources */, 58F558E02695BD3E00F630D0 /* Login.strings in Resources */, 58CE5E6B224146210008646E /* Assets.xcassets in Resources */, 58F558E92695D20F00F630D0 /* SelectLocation.strings in Resources */, @@ -989,10 +1018,17 @@ 58F558EF2695D50D00F630D0 /* ProblemReportReview.strings in Resources */, 584789B8264D4A2A000E45FB /* old_le_root_cert.cer in Resources */, 58F558E62695D1F200F630D0 /* ProblemReport.strings in Resources */, + 58F5590D2697002100F630D0 /* AccountInput.strings in Resources */, + 58F559102697002100F630D0 /* HeaderBar.strings in Resources */, + 58F558F92696EB1C00F630D0 /* StoreKitErrors.strings in Resources */, 584789BE264D4A2A000E45FB /* new_le_root_cert.cer in Resources */, 58F61F4F2692F21C00DCFC2B /* WireguardKeys.strings in Resources */, + 58F5590B2697002100F630D0 /* CustomDateComponentsFormatting.strings in Resources */, 58F5590E2697002100F630D0 /* Main.strings in Resources */, + 58F558FE2696F09100F630D0 /* KeyboardNavigation.strings in Resources */, + 58F5590C2697002100F630D0 /* AppDelegate.strings in Resources */, 581FC4FA2695ACE100AA97BA /* Account.strings in Resources */, + 58F558EC2695D26A00F630D0 /* MullvadRest.strings in Resources */, 582CFEEA269463B80072883A /* Settings.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1361,6 +1397,14 @@ name = SelectLocation.strings; sourceTree = "<group>"; }; + 58F558EA2695D26A00F630D0 /* MullvadRest.strings */ = { + isa = PBXVariantGroup; + children = ( + 58F558EB2695D26A00F630D0 /* en */, + ); + name = MullvadRest.strings; + sourceTree = "<group>"; + }; 58F558ED2695D50D00F630D0 /* ProblemReportReview.strings */ = { isa = PBXVariantGroup; children = ( @@ -1369,6 +1413,30 @@ name = ProblemReportReview.strings; sourceTree = "<group>"; }; + 58F558F32696EB1C00F630D0 /* StoreKitErrors.strings */ = { + isa = PBXVariantGroup; + children = ( + 58F558F42696EB1C00F630D0 /* en */, + ); + name = StoreKitErrors.strings; + sourceTree = "<group>"; + }; + 58F558F52696EB1C00F630D0 /* TunnelManager.strings */ = { + isa = PBXVariantGroup; + children = ( + 58F558F62696EB1C00F630D0 /* en */, + ); + name = TunnelManager.strings; + sourceTree = "<group>"; + }; + 58F558F72696EB1C00F630D0 /* AppStorePaymentManager.strings */ = { + isa = PBXVariantGroup; + children = ( + 58F558F82696EB1C00F630D0 /* en */, + ); + name = AppStorePaymentManager.strings; + sourceTree = "<group>"; + }; 58F559052697002000F630D0 /* Main.strings */ = { isa = PBXVariantGroup; children = ( @@ -1383,6 +1451,46 @@ 58F559082697002100F630D0 /* en */, ); name = ConnectionPanel.strings; + sourceTree = "<group>"; + }; + 58F558FC2696F09100F630D0 /* KeyboardNavigation.strings */ = { + isa = PBXVariantGroup; + children = ( + 58F558FD2696F09100F630D0 /* en */, + ); + name = KeyboardNavigation.strings; + sourceTree = "<group>"; + }; + 58F558FF2697002000F630D0 /* CustomDateComponentsFormatting.strings */ = { + isa = PBXVariantGroup; + children = ( + 58F559002697002000F630D0 /* en */, + ); + name = CustomDateComponentsFormatting.strings; + sourceTree = "<group>"; + }; + 58F559012697002000F630D0 /* AppDelegate.strings */ = { + isa = PBXVariantGroup; + children = ( + 58F559022697002000F630D0 /* en */, + ); + name = AppDelegate.strings; + sourceTree = "<group>"; + }; + 58F559032697002000F630D0 /* AccountInput.strings */ = { + isa = PBXVariantGroup; + children = ( + 58F559042697002000F630D0 /* en */, + ); + name = AccountInput.strings; + sourceTree = "<group>"; + }; + 58F559092697002100F630D0 /* HeaderBar.strings */ = { + isa = PBXVariantGroup; + children = ( + 58F5590A2697002100F630D0 /* en */, + ); + name = HeaderBar.strings; sourceTree = "<group>"; }; 58F61F4D2692F21C00DCFC2B /* WireguardKeys.strings */ = { diff --git a/ios/MullvadVPN/AccountInputGroupView.swift b/ios/MullvadVPN/AccountInputGroupView.swift index b67a752407..9ca166d383 100644 --- a/ios/MullvadVPN/AccountInputGroupView.swift +++ b/ios/MullvadVPN/AccountInputGroupView.swift @@ -20,7 +20,12 @@ class AccountInputGroupView: UIView { let button = UIButton(type: .custom) button.translatesAutoresizingMaskIntoConstraints = false button.setImage(UIImage(named: "IconArrow"), for: .normal) - button.accessibilityLabel = NSLocalizedString("ACCOUNT_INPUT_LOGIN_BUTTON_ACCESSIBILITY_LABEL", comment: "") + button.accessibilityLabel = NSLocalizedString( + "ACCOUNT_INPUT_LOGIN_BUTTON_ACCESSIBILITY_LABEL", + tableName: "AccountInput", + value: "Log in", + comment: "Accessibility label for submit button in account token input." + ) return button }() diff --git a/ios/MullvadVPN/AppDelegate.swift b/ios/MullvadVPN/AppDelegate.swift index 4f7990d636..c240b4ddf0 100644 --- a/ios/MullvadVPN/AppDelegate.swift +++ b/ios/MullvadVPN/AppDelegate.swift @@ -544,7 +544,12 @@ extension AppDelegate: ConnectViewControllerDelegate { case .failure(let error): self.logger?.error(chainedError: error, message: "Failed to start the VPN tunnel") - self.presentTunnelError(error, alertTitle: NSLocalizedString("Failed to start the VPN tunnel", comment: "")) + self.presentTunnelError(error, alertTitle: NSLocalizedString( + "START_VPN_TUNNEL_ERROR_ALERT_TITLE", + tableName: "AppDelegate", + value: "Failed to start the VPN tunnel", + comment: "" + )) } } } @@ -558,7 +563,12 @@ extension AppDelegate: ConnectViewControllerDelegate { case .failure(let error): self.logger?.error(chainedError: error, message: "Failed to stop the VPN tunnel") - self.presentTunnelError(error, alertTitle: NSLocalizedString("Failed to stop the VPN tunnel", comment: "")) + self.presentTunnelError(error, alertTitle: NSLocalizedString( + "STOP_VPN_TUNNEL_ERROR_ALERT_TITLE", + tableName: "AppDelegate", + value: "Failed to stop the VPN tunnel", + comment: "" + )) } } } @@ -576,7 +586,14 @@ extension AppDelegate: ConnectViewControllerDelegate { preferredStyle: .alert ) alertController.addAction( - UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .cancel) + UIAlertAction( + title: NSLocalizedString( + "TUNNEL_ERROR_ALERT_OK_BUTTON", + tableName: "AppDelegate", + comment: "Dismiss button in tunnel error alert." + ), + style: .cancel + ) ) self.alertPresenter.enqueue(alertController, presentingController: self.rootContainer!) diff --git a/ios/MullvadVPN/CustomDateComponentsFormatting.swift b/ios/MullvadVPN/CustomDateComponentsFormatting.swift index 7ef731a999..d9c12dabff 100644 --- a/ios/MullvadVPN/CustomDateComponentsFormatting.swift +++ b/ios/MullvadVPN/CustomDateComponentsFormatting.swift @@ -42,7 +42,12 @@ extension CustomDateComponentsFormatting { let seconds = dateComponents.second ?? 0 if days == 0 && hours == 0 && minutes == 0 && seconds < 60 { - return NSLocalizedString("Less than a minute", comment: "") + return NSLocalizedString( + "LESS_THAN_ONE_MINUTE", + tableName: "CustomDateComponentsFormatting", + value: "Less than a minute", + comment: "Phrase used for less than 1 minute duration." + ) } else if days == 0 && hours == 23 && minutes >= 30 { return formatter.string(from: DateComponents(calendar: calendar, day: 1)) } else if days >= 1 && days <= 90 { diff --git a/ios/MullvadVPN/DisplayChainedError.swift b/ios/MullvadVPN/DisplayChainedError.swift index c27658b6ce..aeb10a80ef 100644 --- a/ios/MullvadVPN/DisplayChainedError.swift +++ b/ios/MullvadVPN/DisplayChainedError.swift @@ -18,7 +18,12 @@ extension RestError: DisplayChainedError { switch self { case .network(let urlError): return String( - format: NSLocalizedString("Network error: %@", comment: ""), + format: NSLocalizedString( + "NETWORK_ERROR", + tableName: "MullvadRest", + value: "Network error: %@", + comment: "Network error. Use %@ placeholder to place localized failure description." + ), urlError.localizedDescription ) case .server(let serverError): @@ -26,16 +31,36 @@ extension RestError: DisplayChainedError { return knownErrorDescription } else { return String( - format: NSLocalizedString("Server error: %@", comment: ""), + format: NSLocalizedString( + "SERVER_ERROR", + tableName: "MullvadRest", + value: "Server error: %@", + comment: "Server error. Use %@ placeholder to place localized failure description." + ), serverError.error ?? "(empty)" ) } case .encodePayload: - return NSLocalizedString("Server request encoding error", comment: "") + return NSLocalizedString( + "SERVER_REQUEST_ENCODING_ERROR", + tableName: "MullvadRest", + value: "Server request encoding error", + comment: "Failure to encode the server request." + ) case .decodeSuccessResponse: - return NSLocalizedString("Server success response decoding error", comment: "") + return NSLocalizedString( + "SERVER_SUCCESS_RESPONSE_DECODING_ERROR", + tableName: "MullvadRest", + value: "Server success response decoding error", + comment: "Failure to decode the server success response." + ) case .decodeErrorResponse: - return NSLocalizedString("Server error response decoding error", comment: "") + return NSLocalizedString( + "SERVER_FAILURE_RESPONSE_DECODING_ERROR", + tableName: "MullvadRest", + value: "Server error response decoding error", + comment: "Failure to decode the server failure response." + ) } } } @@ -44,59 +69,165 @@ extension TunnelManager.Error: DisplayChainedError { var errorChainDescription: String? { switch self { case .loadAllVPNConfigurations(let systemError): - return String(format: NSLocalizedString("Failed to load system VPN configurations: %@", comment: ""), systemError.localizedDescription) + return String( + format: NSLocalizedString( + "LOAD_ALL_VPN_CONFIGURATIONS_ERROR", + tableName: "TunnelManager", + value: "Failed to load system VPN configurations: %@", + comment: "" + ), + systemError.localizedDescription + ) case .reloadVPNConfiguration(let systemError): - return String(format: NSLocalizedString("Failed to reload a VPN configuration: %@", comment: ""), systemError.localizedDescription) + return String( + format: NSLocalizedString( + "RELOAD_VPN_CONFIGURATIONS_ERROR", + tableName: "TunnelManager", + value: "Failed to reload a VPN configuration: %@", + comment: "" + ), + systemError.localizedDescription + ) case .saveVPNConfiguration(let systemError): - return String(format: NSLocalizedString("Failed to save a VPN tunnel configuration: %@", comment: ""), systemError.localizedDescription) + return String( + format: NSLocalizedString( + "SAVE_VPN_CONFIGURATION_ERROR", + tableName: "TunnelManager", + value: "Failed to save a VPN tunnel configuration: %@", + comment: "" + ), + systemError.localizedDescription + ) case .obtainPersistentKeychainReference(_): - return NSLocalizedString("Failed to obtain the persistent keychain reference for the VPN configuration", comment: "") + return NSLocalizedString( + "OBTAIN_PERSISTENT_KEYCHAIN_REFERENCE_ERROR", + tableName: "TunnelManager", + value: "Failed to obtain the persistent keychain reference for the VPN configuration", + comment: "" + ) case .startVPNTunnel(let systemError): - return String(format: NSLocalizedString("System error when starting the VPN tunnel: %@", comment: ""), systemError.localizedDescription) + return String( + format: NSLocalizedString( + "START_VPN_TUNNEL_ERROR", + tableName: "TunnelManager", + value: "System error when starting the VPN tunnel: %@", + comment: "" + ), + systemError.localizedDescription + ) case .removeVPNConfiguration(let systemError): - return String(format: NSLocalizedString("Failed to remove the system VPN configuration: %@", comment: ""), systemError.localizedDescription) + return String( + format: NSLocalizedString( + "REMOVE_VPN_CONFIGURATION_ERROR", + tableName: "TunnelManager", + value: "Failed to remove the system VPN configuration: %@", + comment: "" + ), + systemError.localizedDescription + ) case .removeInconsistentVPNConfiguration(let systemError): - return String(format: NSLocalizedString("Failed to remove the outdated system VPN configuration: %@", comment: ""), systemError.localizedDescription) + return String( + format: NSLocalizedString( + "REMOVE_INCONSISTENT_VPN_CONFIGURATION", + tableName: "TunnelManager", + value: "Failed to remove the outdated system VPN configuration: %@", + comment: "" + ), + systemError.localizedDescription + ) case .readTunnelSettings(_): - return NSLocalizedString("Failed to read tunnel settings", comment: "") + return NSLocalizedString( + "READ_TUNNEL_SETTINGS_ERROR", + tableName: "TunnelManager", + value: "Failed to read tunnel settings", + comment: "" + ) case .addTunnelSettings(_): - return NSLocalizedString("Failed to add tunnel settings", comment: "") + return NSLocalizedString( + "ADD_TUNNEL_SETTINGS_ERROR", + tableName: "TunnelManager", + value: "Failed to add tunnel settings", + comment: "" + ) case .updateTunnelSettings(_): - return NSLocalizedString("Failed to update tunnel settings", comment: "") + return NSLocalizedString( + "UPDATE_TUNNEL_SETTINGS_ERROR", + tableName: "TunnelManager", + value: "Failed to update tunnel settings", + comment: "" + ) case .removeTunnelSettings(_): - return NSLocalizedString("Failed to remove tunnel settings", comment: "") + return NSLocalizedString( + "REMOVE_TUNNEL_SETTINGS_ERROR", + tableName: "TunnelManager", + value: "Failed to remove tunnel settings", + comment: "" + ) case .migrateTunnelSettings(_): - return NSLocalizedString("Failed to migrate tunnel settings", comment: "") + return NSLocalizedString( + "MIGRATE_TUNNEL_SETTINGS_ERROR", + tableName: "TunnelManager", + value: "Failed to migrate tunnel settings", + comment: "" + ) case .pushWireguardKey(let restError): let reason = restError.errorChainDescription ?? "" - var message = String(format: NSLocalizedString("Failed to send the WireGuard key to server: %@", comment: ""), reason) + var message = String( + format: NSLocalizedString( + "PUSH_WIREGUARD_KEY_ERROR", + tableName: "TunnelManager", + value: "Failed to send the WireGuard key to server: %@", + comment: "" + ), + reason + ) if case .server(.keyLimitReached) = restError { + // TODO: maybe use `restError.recoverySuggestion` instead? message.append("\n\n") - message.append(NSLocalizedString("Remove unused WireGuard keys and try again", comment: "")) + message.append(NSLocalizedString( + "PUSH_WIREGUARD_KEY_RECOVERY_SUGGESTION", + tableName: "TunnelManager", + value: "Remove unused WireGuard keys and try again", + comment: "" + )) } return message case .replaceWireguardKey(let restError): let reason = restError.errorChainDescription ?? "" - var message = String(format: NSLocalizedString("Failed to replace the WireGuard key on server: %@", comment: ""), reason) + var message = String( + format: NSLocalizedString( + "REPLACE_WIREGUARD_KEY_ERROR", + tableName: "TunnelManager", + value: "Failed to replace the WireGuard key on server: %@", + comment: "" + ), + reason + ) if case .server(.keyLimitReached) = restError { + // TODO: maybe use `restError.recoverySuggestion` instead? message.append("\n\n") - message.append(NSLocalizedString("Remove unused WireGuard keys and try again", comment: "")) + message.append(NSLocalizedString( + "REPLACE_WIREGUARD_KEY_RECOVERY_SUGGESTION", + tableName: "TunnelManager", + value: "Remove unused WireGuard keys and try again", + comment: "") + ) } return message @@ -108,10 +239,23 @@ extension TunnelManager.Error: DisplayChainedError { case .verifyWireguardKey(let restError): let reason = restError.errorChainDescription ?? "" - return String(format: NSLocalizedString("Failed to verify the WireGuard key on server: %@", comment: ""), reason) + return String( + format: NSLocalizedString( + "VERIFY_WIREGUARD_KEY_ERROR", + tableName: "TunnelManager", + value: "Failed to verify the WireGuard key on server: %@", + comment: "" + ), + reason + ) case .missingAccount: - return NSLocalizedString("Internal error: missing account", comment: "") + return NSLocalizedString( + "MISSING_ACCOUNT_INTERNAL_ERROR", + tableName: "TunnelManager", + value: "Internal error: missing account", + comment: "" + ) } } } @@ -132,15 +276,40 @@ extension SKError: LocalizedError { public var errorDescription: String? { switch self.code { case .unknown: - return NSLocalizedString("Unknown error", comment: "") + return NSLocalizedString( + "UNKNOWN_ERROR", + tableName: "StoreKitErrors", + value: "Unknown error", + comment: "" + ) case .clientInvalid: - return NSLocalizedString("Client is not allowed to issue the request", comment: "") + return NSLocalizedString( + "CLIENT_INVALID", + tableName: "StoreKitErrors", + value: "Client is not allowed to issue the request", + comment: "" + ) case .paymentCancelled: - return NSLocalizedString("User cancelled the request", comment: "") + return NSLocalizedString( + "PAYMENT_CANCELLED", + tableName: "StoreKitErrors", + value: "User cancelled the request", + comment: "" + ) case .paymentInvalid: - return NSLocalizedString("Invalid purchase identifier", comment: "") + return NSLocalizedString( + "PAYMENT_INVALID", + tableName: "StoreKitErrors", + value: "Invalid purchase identifier", + comment: "" + ) case .paymentNotAllowed: - return NSLocalizedString("This device is not allowed to make the payment", comment: "") + return NSLocalizedString( + "PAYMENT_NOT_ALLOWED", + tableName: "StoreKitErrors", + value: "This device is not allowed to make the payment", + comment: "" + ) default: return self.localizedDescription } @@ -151,29 +320,64 @@ extension AppStorePaymentManager.Error: DisplayChainedError { var errorChainDescription: String? { switch self { case .noAccountSet: - return NSLocalizedString("Internal error: account is not set", comment: "") + return NSLocalizedString( + "NO_ACCOUNT_SET_ERROR", + tableName: "AppStorePaymentManager", + value: "Internal error: account is not set", + comment: "" + ) case .readReceipt(let readReceiptError): switch readReceiptError { case .refresh(let storeError): let skErrorMessage = (storeError as? SKError)?.errorDescription ?? storeError.localizedDescription - return String(format: NSLocalizedString("Cannot refresh the AppStore receipt: %@", comment: ""), skErrorMessage) + return String( + format: NSLocalizedString( + "REFRESH_RECEIPT_ERROR", + tableName: "AppStorePaymentManager", + value: "Cannot refresh the AppStore receipt: %@", + comment: "" + ), + skErrorMessage + ) case .io(let ioError): - return String(format: NSLocalizedString("Cannot read the AppStore receipt from disk: %@", comment: ""), ioError.localizedDescription) + return String( + format: NSLocalizedString( + "READ_RECEIPT_ERROR", + tableName: "AppStorePaymentManager", + value: "Cannot read the AppStore receipt from disk: %@", + comment: "" + ), + ioError.localizedDescription + ) case .doesNotExist: - return NSLocalizedString("AppStore receipt is not found on disk.", comment: "") + return NSLocalizedString( + "RECEIPT_NOT_FOUND_ERROR", + tableName: "AppStorePaymentManager", + value: "AppStore receipt is not found on disk.", + comment: "" + ) } case .sendReceipt(let restError): let reason = restError.errorChainDescription ?? "" - let format = NSLocalizedString(#""" -Failed to send the receipt to server: %@ - -Please retry by using the "Restore purchases" button. -"""#, comment: "") - - return String(format: format, reason) + let errorFormat = NSLocalizedString( + "SEND_RECEIPT_ERROR", + tableName: "AppStorePaymentManager", + value: "Failed to send the receipt to server: %@", + comment: "" + ) + let recoverySuggestion = NSLocalizedString( + "SEND_RECEIPT_RECOVERY_SUGGESTION", + tableName: "AppStorePaymentManager", + value: "Please retry by using the \"Restore purchases\" button.", + comment: "" + ) + var errorString = String(format: errorFormat, reason) + errorString.append("\n\n") + errorString.append(recoverySuggestion) + return errorString case .storePayment(let storeError): return (storeError as? SKError)?.errorDescription ?? storeError.localizedDescription diff --git a/ios/MullvadVPN/HeaderBarView.swift b/ios/MullvadVPN/HeaderBarView.swift index 0912e5c107..4dd1d68ce5 100644 --- a/ios/MullvadVPN/HeaderBarView.swift +++ b/ios/MullvadVPN/HeaderBarView.swift @@ -33,7 +33,12 @@ class HeaderBarView: UIView { settingsButton.setImage(UIImage(named: "IconSettings"), for: .normal) settingsButton.translatesAutoresizingMaskIntoConstraints = false settingsButton.accessibilityIdentifier = "SettingsButton" - settingsButton.accessibilityLabel = NSLocalizedString("HEADER_BAR_SETTINGS_BUTTON_ACCESSIBILITY_LABEL", comment: "") + settingsButton.accessibilityLabel = NSLocalizedString( + "HEADER_BAR_SETTINGS_BUTTON_ACCESSIBILITY_LABEL", + tableName: "HeaderBar", + value: "Settings", + comment: "" + ) return settingsButton } diff --git a/ios/MullvadVPN/MullvadRest.swift b/ios/MullvadVPN/MullvadRest.swift index 2fc99b4d64..0e7abdc239 100644 --- a/ios/MullvadVPN/MullvadRest.swift +++ b/ios/MullvadVPN/MullvadRest.swift @@ -69,9 +69,19 @@ struct ServerErrorResponse: LocalizedError, Decodable, Equatable { var errorDescription: String? { switch code { case Code.keyLimitReached.rawValue: - return NSLocalizedString("Too many WireGuard keys in use.", comment: "") + return NSLocalizedString( + "KEY_LIMIT_REACHED_ERROR_DESCRIPTION", + tableName: "MullvadRest", + value: "Too many WireGuard keys in use.", + comment: "" + ) case Code.invalidAccount.rawValue: - return NSLocalizedString("Invalid account.", comment: "") + return NSLocalizedString( + "INVALID_ACCOUNT_ERROR_DESCRIPTION", + tableName: "MullvadRest", + value: "Invalid account.", + comment: "" + ) default: return nil } @@ -80,7 +90,12 @@ struct ServerErrorResponse: LocalizedError, Decodable, Equatable { var recoverySuggestion: String? { switch code { case Code.keyLimitReached.rawValue: - return NSLocalizedString("Please visit the website to revoke a key before login is possible.", comment: "") + return NSLocalizedString( + "KEY_LIMIT_REACHED_ERROR_RECOVERY_SUGGESTION", + tableName: "MullvadRest", + value: "Please visit the website to revoke a key before login is possible.", + comment: "" + ) default: return nil } diff --git a/ios/MullvadVPN/UIBarButtonItem+KeyboardNavigation.swift b/ios/MullvadVPN/UIBarButtonItem+KeyboardNavigation.swift index 85d2d258a6..ee81308440 100644 --- a/ios/MullvadVPN/UIBarButtonItem+KeyboardNavigation.swift +++ b/ios/MullvadVPN/UIBarButtonItem+KeyboardNavigation.swift @@ -16,9 +16,19 @@ extension UIBarButtonItem { fileprivate var localizedTitle: String { switch self { case .previous: - return NSLocalizedString("Previous", comment: "Keyboard navigation toolbar") + return NSLocalizedString( + "PREVIOUS_BUTTON_TITLE", + tableName: "KeyboardNavigation", + value: "Previous", + comment: "Previous button" + ) case .next: - return NSLocalizedString("Next", comment: "Keyboard navigation toolbar") + return NSLocalizedString( + "NEXT_BUTTON_TITLE", + tableName: "KeyboardNavigation", + value: "Next", + comment: "Next button" + ) } } diff --git a/ios/MullvadVPN/en.lproj/AccountInput.strings b/ios/MullvadVPN/en.lproj/AccountInput.strings new file mode 100644 index 0000000000..51d09cc7e4 --- /dev/null +++ b/ios/MullvadVPN/en.lproj/AccountInput.strings @@ -0,0 +1,2 @@ +/* Accessibility label for submit button in account token input. */ +"ACCOUNT_INPUT_LOGIN_BUTTON_ACCESSIBILITY_LABEL" = "Log in"; diff --git a/ios/MullvadVPN/en.lproj/AppDelegate.strings b/ios/MullvadVPN/en.lproj/AppDelegate.strings new file mode 100644 index 0000000000..4b22937c5a --- /dev/null +++ b/ios/MullvadVPN/en.lproj/AppDelegate.strings @@ -0,0 +1,8 @@ +/* No comment provided by engineer. */ +"START_VPN_TUNNEL_ERROR_ALERT_TITLE" = "Failed to start the VPN tunnel"; + +/* No comment provided by engineer. */ +"STOP_VPN_TUNNEL_ERROR_ALERT_TITLE" = "Failed to stop the VPN tunnel"; + +/* Dismiss button in tunnel error alert. */ +"TUNNEL_ERROR_ALERT_OK_BUTTON" = "OK"; diff --git a/ios/MullvadVPN/en.lproj/AppStorePaymentManager.strings b/ios/MullvadVPN/en.lproj/AppStorePaymentManager.strings new file mode 100644 index 0000000000..54c9c348c4 --- /dev/null +++ b/ios/MullvadVPN/en.lproj/AppStorePaymentManager.strings @@ -0,0 +1,17 @@ +/* No comment provided by engineer. */ +"NO_ACCOUNT_SET_ERROR" = "Internal error: account is not set"; + +/* No comment provided by engineer. */ +"READ_RECEIPT_ERROR" = "Cannot read the AppStore receipt from disk: %@"; + +/* No comment provided by engineer. */ +"RECEIPT_NOT_FOUND_ERROR" = "AppStore receipt is not found on disk."; + +/* No comment provided by engineer. */ +"REFRESH_RECEIPT_ERROR" = "Cannot refresh the AppStore receipt: %@"; + +/* No comment provided by engineer. */ +"SEND_RECEIPT_ERROR" = "Failed to send the receipt to server: %@"; + +/* No comment provided by engineer. */ +"SEND_RECEIPT_RECOVERY_SUGGESTION" = "Please retry by using the \"Restore purchases\" button."; diff --git a/ios/MullvadVPN/en.lproj/CustomDateComponentsFormatting.strings b/ios/MullvadVPN/en.lproj/CustomDateComponentsFormatting.strings new file mode 100644 index 0000000000..8f931d4968 --- /dev/null +++ b/ios/MullvadVPN/en.lproj/CustomDateComponentsFormatting.strings @@ -0,0 +1,2 @@ +/* Phrase used for less than 1 minute duration. */ +"LESS_THAN_ONE_MINUTE" = "Less than a minute"; diff --git a/ios/MullvadVPN/en.lproj/HeaderBar.strings b/ios/MullvadVPN/en.lproj/HeaderBar.strings new file mode 100644 index 0000000000..01b3aea007 --- /dev/null +++ b/ios/MullvadVPN/en.lproj/HeaderBar.strings @@ -0,0 +1,2 @@ +/* No comment provided by engineer. */ +"HEADER_BAR_SETTINGS_BUTTON_ACCESSIBILITY_LABEL" = "Settings"; diff --git a/ios/MullvadVPN/en.lproj/KeyboardNavigation.strings b/ios/MullvadVPN/en.lproj/KeyboardNavigation.strings new file mode 100644 index 0000000000..753599eec9 --- /dev/null +++ b/ios/MullvadVPN/en.lproj/KeyboardNavigation.strings @@ -0,0 +1,5 @@ +/* Next button */ +"NEXT_BUTTON_TITLE" = "Next"; + +/* Previous button */ +"PREVIOUS_BUTTON_TITLE" = "Previous"; diff --git a/ios/MullvadVPN/en.lproj/MullvadRest.strings b/ios/MullvadVPN/en.lproj/MullvadRest.strings new file mode 100644 index 0000000000..f5a83c67a3 --- /dev/null +++ b/ios/MullvadVPN/en.lproj/MullvadRest.strings @@ -0,0 +1,23 @@ +/* No comment provided by engineer. */ +"INVALID_ACCOUNT_ERROR_DESCRIPTION" = "Invalid account."; + +/* No comment provided by engineer. */ +"KEY_LIMIT_REACHED_ERROR_DESCRIPTION" = "Too many WireGuard keys in use."; + +/* No comment provided by engineer. */ +"KEY_LIMIT_REACHED_ERROR_RECOVERY_SUGGESTION" = "Please visit the website to revoke a key before login is possible."; + +/* Network error. Use %@ placeholder to place localized failure description. */ +"NETWORK_ERROR" = "Network error: %@"; + +/* Server error. Use %@ placeholder to place localized failure description. */ +"SERVER_ERROR" = "Server error: %@"; + +/* Failure to decode the server failure response. */ +"SERVER_FAILURE_RESPONSE_DECODING_ERROR" = "Server error response decoding error"; + +/* Failure to encode the server request. */ +"SERVER_REQUEST_ENCODING_ERROR" = "Server request encoding error"; + +/* Failure to decode the server success response. */ +"SERVER_SUCCESS_RESPONSE_DECODING_ERROR" = "Server success response decoding error"; diff --git a/ios/MullvadVPN/en.lproj/StoreKitErrors.strings b/ios/MullvadVPN/en.lproj/StoreKitErrors.strings new file mode 100644 index 0000000000..99ac40881a --- /dev/null +++ b/ios/MullvadVPN/en.lproj/StoreKitErrors.strings @@ -0,0 +1,14 @@ +/* No comment provided by engineer. */ +"CLIENT_INVALID" = "Client is not allowed to issue the request"; + +/* No comment provided by engineer. */ +"PAYMENT_CANCELLED" = "User cancelled the request"; + +/* No comment provided by engineer. */ +"PAYMENT_INVALID" = "Invalid purchase identifier"; + +/* No comment provided by engineer. */ +"PAYMENT_NOT_ALLOWED" = "This device is not allowed to make the payment"; + +/* No comment provided by engineer. */ +"UNKNOWN_ERROR" = "Unknown error"; diff --git a/ios/MullvadVPN/en.lproj/TunnelManager.strings b/ios/MullvadVPN/en.lproj/TunnelManager.strings new file mode 100644 index 0000000000..93ce286a33 --- /dev/null +++ b/ios/MullvadVPN/en.lproj/TunnelManager.strings @@ -0,0 +1,53 @@ +/* No comment provided by engineer. */ +"ADD_TUNNEL_SETTINGS_ERROR" = "Failed to add tunnel settings"; + +/* No comment provided by engineer. */ +"LOAD_ALL_VPN_CONFIGURATIONS_ERROR" = "Failed to load system VPN configurations: %@"; + +/* No comment provided by engineer. */ +"MIGRATE_TUNNEL_SETTINGS_ERROR" = "Failed to migrate tunnel settings"; + +/* No comment provided by engineer. */ +"MISSING_ACCOUNT_INTERNAL_ERROR" = "Internal error: missing account"; + +/* No comment provided by engineer. */ +"OBTAIN_PERSISTENT_KEYCHAIN_REFERENCE_ERROR" = "Failed to obtain the persistent keychain reference for the VPN configuration"; + +/* No comment provided by engineer. */ +"PUSH_WIREGUARD_KEY_ERROR" = "Failed to send the WireGuard key to server: %@"; + +/* No comment provided by engineer. */ +"PUSH_WIREGUARD_KEY_RECOVERY_SUGGESTION" = "Remove unused WireGuard keys and try again"; + +/* No comment provided by engineer. */ +"READ_TUNNEL_SETTINGS_ERROR" = "Failed to read tunnel settings"; + +/* No comment provided by engineer. */ +"RELOAD_VPN_CONFIGURATIONS_ERROR" = "Failed to reload a VPN configuration: %@"; + +/* No comment provided by engineer. */ +"REMOVE_INCONSISTENT_VPN_CONFIGURATION" = "Failed to remove the outdated system VPN configuration: %@"; + +/* No comment provided by engineer. */ +"REMOVE_TUNNEL_SETTINGS_ERROR" = "Failed to remove tunnel settings"; + +/* No comment provided by engineer. */ +"REMOVE_VPN_CONFIGURATION_ERROR" = "Failed to remove the system VPN configuration: %@"; + +/* No comment provided by engineer. */ +"REPLACE_WIREGUARD_KEY_ERROR" = "Failed to replace the WireGuard key on server: %@"; + +/* No comment provided by engineer. */ +"REPLACE_WIREGUARD_KEY_RECOVERY_SUGGESTION" = "Remove unused WireGuard keys and try again"; + +/* No comment provided by engineer. */ +"SAVE_VPN_CONFIGURATION_ERROR" = "Failed to save a VPN tunnel configuration: %@"; + +/* No comment provided by engineer. */ +"START_VPN_TUNNEL_ERROR" = "System error when starting the VPN tunnel: %@"; + +/* No comment provided by engineer. */ +"UPDATE_TUNNEL_SETTINGS_ERROR" = "Failed to update tunnel settings"; + +/* No comment provided by engineer. */ +"VERIFY_WIREGUARD_KEY_ERROR" = "Failed to verify the WireGuard key on server: %@"; |
