summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2021-07-06 11:37:59 +0200
committerAndrej Mihajlov <and@mullvad.net>2021-07-21 12:13:04 +0200
commite02f35669084fac78c9a2722c61c7aa48e755baa (patch)
tree46c050e81d9afafbce011cb831e7946454b109ba
parent57104ccc094845bb5b14b38adce829d3c818cf15 (diff)
downloadmullvadvpn-e02f35669084fac78c9a2722c61c7aa48e755baa.tar.xz
mullvadvpn-e02f35669084fac78c9a2722c61c7aa48e755baa.zip
Localize Account
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj15
-rw-r--r--ios/MullvadVPN/AccountViewController.swift168
-rw-r--r--ios/MullvadVPN/en.lproj/Account.strings68
3 files changed, 218 insertions, 33 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 8ff8894616..97d051bd9f 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -51,6 +51,7 @@
581503A624D6F4AE00C9C50E /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581503A524D6F4AE00C9C50E /* Logging.swift */; };
581503A724D6F4AE00C9C50E /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581503A524D6F4AE00C9C50E /* Logging.swift */; };
581CBCEE229826FD00727D7F /* StaticTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581CBCED229826FD00727D7F /* StaticTableViewDataSource.swift */; };
+ 581FC4FA2695ACE100AA97BA /* Account.strings in Resources */ = {isa = PBXBuildFile; fileRef = 581FC4F82695ACE100AA97BA /* Account.strings */; };
58293FAE2510CA58005D0BB5 /* ProblemReportViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58293FAC2510CA58005D0BB5 /* ProblemReportViewController.swift */; };
58293FB125124117005D0BB5 /* CustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58293FB025124117005D0BB5 /* CustomTextField.swift */; };
58293FB3251241B4005D0BB5 /* CustomTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58293FB2251241B3005D0BB5 /* CustomTextView.swift */; };
@@ -318,6 +319,7 @@
581503A224D6F1EC00C9C50E /* ChainedError+Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ChainedError+Logger.swift"; sourceTree = "<group>"; };
581503A524D6F4AE00C9C50E /* Logging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logging.swift; sourceTree = "<group>"; };
581CBCED229826FD00727D7F /* StaticTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticTableViewDataSource.swift; sourceTree = "<group>"; };
+ 581FC4F92695ACE100AA97BA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Account.strings; sourceTree = "<group>"; };
58293FAC2510CA58005D0BB5 /* ProblemReportViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProblemReportViewController.swift; sourceTree = "<group>"; };
58293FB025124117005D0BB5 /* CustomTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTextField.swift; sourceTree = "<group>"; };
58293FB2251241B3005D0BB5 /* CustomTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTextView.swift; sourceTree = "<group>"; };
@@ -542,6 +544,7 @@
582CFEE1269448160072883A /* Localizations */ = {
isa = PBXGroup;
children = (
+ 581FC4F82695ACE100AA97BA /* Account.strings */,
582CFEE526945FC30072883A /* AppStoreSubscriptions.strings */,
58F559072697002100F630D0 /* ConnectionPanel.strings */,
587B7543266922BF00DEF7E9 /* Localizable.strings */,
@@ -549,6 +552,7 @@
58F61F4D2692F21C00DCFC2B /* WireguardKeys.strings */,
);
name = Localizations;
+ path = MullvadVPN;
sourceTree = "<group>";
};
586ADD4323FC13AD00CE9E87 /* GeoJSON */ = {
@@ -586,6 +590,7 @@
58ECD29023F178FD004298B6 /* Configurations */,
0E15C74FDCF763609B367486 /* Frameworks */,
586ADD4323FC13AD00CE9E87 /* GeoJSON */,
+ 582CFEE1269448160072883A /* Localizations */,
58CE5E62224146200008646E /* MullvadVPN */,
58D0C79423F1CE7000FE9BA7 /* MullvadVPNScreenshots */,
58B0A2A1238EE67E00BC001D /* MullvadVPNTests */,
@@ -660,7 +665,6 @@
58FAEDFC24533A5500CB0F5B /* KeychainMatchLimit.swift */,
58FAEDFE24533A7000CB0F5B /* KeychainReturn.swift */,
58727282265D173C00F315B2 /* LaunchScreen.storyboard */,
- 582CFEE1269448160072883A /* Localizations */,
58A1AA8623F43901009F7EA6 /* Location.swift */,
583DA21325FA4B5C00318683 /* LocationDataSource.swift */,
58BA692D23E99EFF009DC256 /* Locking.swift */,
@@ -962,6 +966,7 @@
58F61F4F2692F21C00DCFC2B /* WireguardKeys.strings in Resources */,
58E5BC2624FEB6DB00A53A76 /* AccountViewController.xib in Resources */,
58F5590E2697002100F630D0 /* Main.strings in Resources */,
+ 581FC4FA2695ACE100AA97BA /* Account.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1256,6 +1261,14 @@
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
+ 581FC4F82695ACE100AA97BA /* Account.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 581FC4F92695ACE100AA97BA /* en */,
+ );
+ name = Account.strings;
+ sourceTree = "<group>";
+ };
582CFEE526945FC30072883A /* AppStoreSubscriptions.strings */ = {
isa = PBXVariantGroup;
children = (
diff --git a/ios/MullvadVPN/AccountViewController.swift b/ios/MullvadVPN/AccountViewController.swift
index 398d304f0a..4f29ec250c 100644
--- a/ios/MullvadVPN/AccountViewController.swift
+++ b/ios/MullvadVPN/AccountViewController.swift
@@ -55,7 +55,11 @@ class AccountViewController: UIViewController, AppStorePaymentObserver, AccountO
override func viewDidLoad() {
super.viewDidLoad()
- navigationItem.title = NSLocalizedString("Account", comment: "Navigation title")
+ navigationItem.title = NSLocalizedString(
+ "NAVIGATION_TITLE",
+ tableName: "Account",
+ comment: "Navigation title"
+ )
AppStorePaymentManager.shared.addPaymentObserver(self)
Account.shared.addObserver(self)
@@ -80,7 +84,12 @@ class AccountViewController: UIViewController, AppStorePaymentObserver, AccountO
let accountExpiry = AccountExpiry(date: expiryDate)
if accountExpiry.isExpired {
- expiryLabel.text = NSLocalizedString("OUT OF TIME", comment: "")
+ expiryLabel.text = NSLocalizedString(
+ "ACCOUNT_OUT_OF_TIME_LABEL",
+ tableName: "Account",
+ value: "OUT OF TIME",
+ comment: "Label displayed in place of account expiration when account is out of time."
+ )
expiryLabel.textColor = .dangerColor
} else {
expiryLabel.text = accountExpiry.formattedDate
@@ -123,8 +132,10 @@ class AccountViewController: UIViewController, AppStorePaymentObserver, AccountO
let localizedPrice = product.localizedPrice ?? ""
let format = NSLocalizedString(
- "%1$@ (%2$@)",
- comment: "The buy button title: <TITLE> (<PRICE>). The order can be changed by swapping %1 and %2."
+ "PURCHASE_BUTTON_TITLE_FORMAT",
+ tableName: "Account",
+ value: "%1$@ (%2$@)",
+ comment: "Purchase button title: <TITLE> (<PRICE>). The order can be changed by swapping %1 and %2."
)
let title = String(format: format, localizedTitle, localizedPrice)
@@ -133,15 +144,22 @@ class AccountViewController: UIViewController, AppStorePaymentObserver, AccountO
private func didFailLoadingProducts(with error: Error) {
let title = NSLocalizedString(
- "Cannot connect to AppStore",
- comment: "The buy button title displayed when unable to load the price of subscription"
+ "PURCHASE_BUTTON_CANNOT_CONNECT_TO_APPSTORE_LABEL",
+ tableName: "Account",
+ value: "Cannot connect to AppStore",
+ comment: "Purchase button title displayed when unable to load the price of in-app purchase."
)
purchaseButton.setTitle(title, for: .normal)
}
private func setPaymentsRestricted() {
- let title = NSLocalizedString("Payments restricted", comment: "")
+ let title = NSLocalizedString(
+ "PURCHASE_BUTTON_PAYMENTS_RESTRICTED_LABEL",
+ tableName: "Account",
+ value: "Payments restricted",
+ comment: "Purchase button title displayed when payments are restriced on device."
+ )
purchaseButton.setTitle(title, for: .normal)
purchaseButton.isEnabled = false
@@ -183,25 +201,44 @@ class AccountViewController: UIViewController, AppStorePaymentObserver, AccountO
message: response.alertMessage(context: context),
preferredStyle: .alert
)
- alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .cancel))
+ alertController.addAction(
+ UIAlertAction(
+ title: NSLocalizedString(
+ "TIME_ADDED_ALERT_OK_ACTION",
+ tableName: "Account",
+ value: "OK",
+ comment: ""
+ ),
+ style: .cancel
+ )
+ )
alertPresenter.enqueue(alertController, presentingController: self)
}
private func showLogoutConfirmation(completion: @escaping (Bool) -> Void, animated: Bool) {
- let message = NSLocalizedString(
- "Are you sure you want to log out?\n\nThis will erase the account number from this device. It is not possible for us to recover it for you. Make sure you have your account number saved somewhere, to be able to log back in.",
- comment: "Alert message in log out confirmation")
-
let alertController = UIAlertController(
- title: NSLocalizedString("Log out", comment: "Alert title in log out confirmation"),
- message: message,
+ title: NSLocalizedString(
+ "LOGOUT_CONFIRMATION_ALERT_TITLE",
+ tableName: "Account",
+ comment: "Title for logout dialog"
+ ),
+ message: NSLocalizedString(
+ "LOGOUT_CONFIRMATION_ALERT_MESSAGE",
+ tableName: "Account",
+ comment: "Message for logout dialog"
+ ),
preferredStyle: .alert
)
alertController.addAction(
UIAlertAction(
- title: NSLocalizedString("Cancel", comment: "Log out confirmation action"),
+ title: NSLocalizedString(
+ "LOGOUT_CONFIRMATION_ALERT_CANCEL_ACTION",
+ tableName: "Account",
+ value: "Cancel",
+ comment: "Title for cancel button in logout dialog"
+ ),
style: .cancel,
handler: { (alertAction) in
completion(false)
@@ -210,7 +247,12 @@ class AccountViewController: UIViewController, AppStorePaymentObserver, AccountO
alertController.addAction(
UIAlertAction(
- title: NSLocalizedString("Log out", comment: "Log out confirmation action"),
+ title: NSLocalizedString(
+ "LOGOUT_CONFIRMATION_ALERT_YES_ACTION",
+ tableName: "Account",
+ value: "Log out",
+ comment: "Title for confirmation button in logout dialog"
+ ),
style: .destructive,
handler: { (alertAction) in
completion(true)
@@ -221,8 +263,12 @@ class AccountViewController: UIViewController, AppStorePaymentObserver, AccountO
}
private func confirmLogout() {
- let message = NSLocalizedString("Logging out. Please wait...",
- comment: "A modal message displayed during log out")
+ let message = NSLocalizedString(
+ "LOGGING_OUT_ALERT_TITLE",
+ tableName: "Account",
+ value: "Logging out. Please wait...",
+ comment: "Modal message displayed during logout"
+ )
let alertController = UIAlertController(
title: nil,
@@ -238,12 +284,22 @@ class AccountViewController: UIViewController, AppStorePaymentObserver, AccountO
self.logger.error(chainedError: error, message: "Failed to log out")
let errorAlertController = UIAlertController(
- title: NSLocalizedString("Failed to log out", comment: ""),
+ title: NSLocalizedString(
+ "LOGOUT_FAILURE_ALERT_TITLE",
+ tableName: "Account",
+ value: "Failed to log out",
+ comment: "Title for logout failure alert"
+ ),
message: error.errorChainDescription,
preferredStyle: .alert
)
errorAlertController.addAction(
- UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .cancel)
+ UIAlertAction(title: NSLocalizedString(
+ "LOGOUT_FAILURE_ALERT_OK_ACTION",
+ tableName: "Account",
+ value: "OK",
+ comment: "Message for logout failure alert"
+ ), style: .cancel)
)
self.alertPresenter.enqueue(errorAlertController, presentingController: self)
@@ -275,13 +331,24 @@ class AccountViewController: UIViewController, AppStorePaymentObserver, AccountO
func appStorePaymentManager(_ manager: AppStorePaymentManager, transaction: SKPaymentTransaction, accountToken: String?, didFailWithError error: AppStorePaymentManager.Error) {
DispatchQueue.main.async {
let alertController = UIAlertController(
- title: NSLocalizedString("Cannot complete the purchase", comment: ""),
+ title: NSLocalizedString(
+ "CANNOT_COMPLETE_PURCHASE_ALERT_TITLE",
+ tableName: "Account",
+ value: "Cannot complete the purchase",
+ comment: "Title for purchase failure dialog"
+ ),
message: error.errorChainDescription,
preferredStyle: .alert
)
alertController.addAction(
- UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .cancel)
+ UIAlertAction(
+ title: NSLocalizedString(
+ "CANNOT_COMPLETE_PURCHASE_ALERT_OK_ACTION",
+ tableName: "Account",
+ value: "OK",
+ comment: "Title for OK button in purchase failure dialog"
+ ), style: .cancel)
)
self.alertPresenter.enqueue(alertController, presentingController: self)
@@ -317,8 +384,13 @@ class AccountViewController: UIViewController, AppStorePaymentObserver, AccountO
UIPasteboard.general.string = Account.shared.token
accountTokenButton.setTitle(
- NSLocalizedString("COPIED TO PASTEBOARD!", comment: ""),
- for: .normal)
+ NSLocalizedString(
+ "COPIED_TO_PASTEBOARD_LABEL",
+ tableName: "Account",
+ comment: "Message, temporarily displayed in place account token, after copying the account token to pasteboard on tap."
+ ),
+ for: .normal
+ )
let dispatchWork = DispatchWorkItem { [weak self] in
self?.accountTokenButton.setTitle(Account.shared.formattedToken, for: .normal)
@@ -354,12 +426,22 @@ class AccountViewController: UIViewController, AppStorePaymentObserver, AccountO
case .failure(let error):
let alertController = UIAlertController(
- title: NSLocalizedString("Cannot restore purchases", comment: ""),
+ title: NSLocalizedString(
+ "RESTORE_PURCHASES_FAILURE_ALERT_TITLE",
+ tableName: "Account",
+ value: "Cannot restore purchases",
+ comment: "Title for failure dialog when restoring purchases"
+ ),
message: error.errorChainDescription,
preferredStyle: .alert
)
alertController.addAction(
- UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .cancel)
+ UIAlertAction(title: NSLocalizedString(
+ "RESTORE_PURCHASES_FAILURE_ALERT_OK_ACTION",
+ tableName: "Account",
+ value: "OK",
+ comment: "Title for 'OK' button in failure dialog when restoring purchases"
+ ), style: .cancel)
)
self.alertPresenter.enqueue(alertController, presentingController: self)
}
@@ -381,9 +463,18 @@ private extension CreateApplePaymentResponse {
func alertTitle(context: Context) -> String {
switch context {
case .purchase:
- return NSLocalizedString("Thanks for your purchase", comment: "")
+ return NSLocalizedString(
+ "TIME_ADDED_ALERT_SUCCESS_TITLE",
+ tableName: "Account",
+ value: "Thanks for your purchase",
+ comment: "Title for purchase completion dialog"
+ )
case .restoration:
- return NSLocalizedString("Restore purchases", comment: "")
+ return NSLocalizedString(
+ "RESTORE_PURCHASES_ALERT_TITLE",
+ tableName: "Account", value: "Restore purchases",
+ comment: "Title for purchase restoration dialog"
+ )
}
}
@@ -391,18 +482,31 @@ private extension CreateApplePaymentResponse {
switch context {
case .purchase:
return String(
- format: NSLocalizedString("%@ have been added to your account", comment: ""),
+ format: NSLocalizedString(
+ "TIME_ADDED_ALERT_SUCCESS_MESSAGE",
+ tableName: "Account",
+ value: "%@ have been added to your account",
+ comment: "Message displayed upon successful purchase and containing the time duration credited to user account. Use %@ placeholder to position the localized text with duration added (i.e '30 days')"
+ ),
formattedTimeAdded ?? ""
)
case .restoration:
switch self {
case .noTimeAdded:
return NSLocalizedString(
- "Your previous purchases have already been added to this account.",
- comment: "")
+ "RESTORE_PURCHASES_ALERT_NO_TIME_ADDED_MESSAGE",
+ tableName: "Account",
+ value: "Your previous purchases have already been added to this account.",
+ comment: "Message displayed when no time credited to user account during purchase restoration; communicates that user account has already been credited with all outstanding purchased time duration."
+ )
case .timeAdded:
return String(
- format: NSLocalizedString("%@ have been added to your account", comment: ""),
+ format: NSLocalizedString(
+ "RESTORE_PURCHASES_ALERT_TIME_ADDED_MESSAGE",
+ tableName: "Account",
+ value: "%@ have been added to your account",
+ comment: "Message displayed upon successful restoration of existing purchases, containing the time duration credited to user account. Use %@ placeholder to position the localized text with duration added (i.e '30 days')"
+ ),
self.formattedTimeAdded ?? ""
)
}
diff --git a/ios/MullvadVPN/en.lproj/Account.strings b/ios/MullvadVPN/en.lproj/Account.strings
new file mode 100644
index 0000000000..106b8d60be
--- /dev/null
+++ b/ios/MullvadVPN/en.lproj/Account.strings
@@ -0,0 +1,68 @@
+/* Label displayed in place of account expiration when account is out of time. */
+"ACCOUNT_OUT_OF_TIME_LABEL" = "OUT OF TIME";
+
+/* Title for OK button in purchase failure dialog */
+"CANNOT_COMPLETE_PURCHASE_ALERT_OK_ACTION" = "OK";
+
+/* Title for purchase failure dialog */
+"CANNOT_COMPLETE_PURCHASE_ALERT_TITLE" = "Cannot complete the purchase";
+
+/* Message, temporarily displayed in place account token, after copying the account token to pasteboard on tap. */
+"COPIED_TO_PASTEBOARD_LABEL" = "COPIED TO PASTEBOARD!";
+
+/* Modal message displayed during logout */
+"LOGGING_OUT_ALERT_TITLE" = "Logging out. Please wait...";
+
+/* Title for cancel button in logout dialog */
+"LOGOUT_CONFIRMATION_ALERT_CANCEL_ACTION" = "Cancel";
+
+/* Message for logout dialog */
+"LOGOUT_CONFIRMATION_ALERT_MESSAGE" = "Are you sure you want to log out?\n\nThis will erase the account number from this device. It is not possible for us to recover it for you. Make sure you have your account number saved somewhere, to be able to log back in.";
+
+/* Title for logout dialog */
+"LOGOUT_CONFIRMATION_ALERT_TITLE" = "Log out";
+
+/* Title for confirmation button in logout dialog */
+"LOGOUT_CONFIRMATION_ALERT_YES_ACTION" = "Log out";
+
+/* Message for logout failure alert */
+"LOGOUT_FAILURE_ALERT_OK_ACTION" = "OK";
+
+/* Title for logout failure alert */
+"LOGOUT_FAILURE_ALERT_TITLE" = "Failed to log out";
+
+/* Navigation title */
+"NAVIGATION_TITLE" = "Account";
+
+/* Purchase button title displayed when unable to load the price of in-app purchase. */
+"PURCHASE_BUTTON_CANNOT_CONNECT_TO_APPSTORE_LABEL" = "Cannot connect to AppStore";
+
+/* Purchase button title displayed when payments are restriced on device. */
+"PURCHASE_BUTTON_PAYMENTS_RESTRICTED_LABEL" = "Payments restricted";
+
+/* Purchase button title: <TITLE> (<PRICE>). The order can be changed by swapping %1 and %2. */
+"PURCHASE_BUTTON_TITLE_FORMAT" = "%1$@ (%2$@)";
+
+/* Message displayed when no time credited to user account during purchase restoration; communicates that user account has already been credited with all outstanding purchased time duration. */
+"RESTORE_PURCHASES_ALERT_NO_TIME_ADDED_MESSAGE" = "Your previous purchases have already been added to this account.";
+
+/* Message displayed upon successful restoration of existing purchases, containing the time duration credited to user account. Use %@ placeholder to position the localized text with duration added (i.e '30 days') */
+"RESTORE_PURCHASES_ALERT_TIME_ADDED_MESSAGE" = "%@ have been added to your account";
+
+/* Title for purchase restoration dialog */
+"RESTORE_PURCHASES_ALERT_TITLE" = "Restore purchases";
+
+/* Title for 'OK' button in failure dialog when restoring purchases */
+"RESTORE_PURCHASES_FAILURE_ALERT_OK_ACTION" = "OK";
+
+/* Title for failure dialog when restoring purchases */
+"RESTORE_PURCHASES_FAILURE_ALERT_TITLE" = "Cannot restore purchases";
+
+/* No comment provided by engineer. */
+"TIME_ADDED_ALERT_OK_ACTION" = "OK";
+
+/* Message displayed upon successful purchase and containing the time duration credited to user account. Use %@ placeholder to position the localized text with duration added (i.e '30 days') */
+"TIME_ADDED_ALERT_SUCCESS_MESSAGE" = "%@ have been added to your account";
+
+/* Title for purchase completion dialog */
+"TIME_ADDED_ALERT_SUCCESS_TITLE" = "Thanks for your purchase";