From bcfbf4f97e5898e7a3414e1a7a6a698b4b7f69a5 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 30 Apr 2025 09:17:28 +0100 Subject: [PATCH 01/16] feat: utilise string localisations --- .../Sources/Utils/StringUtils.swift | 23 ++++++++++++------- .../Sources/Views/AuthPickerView.swift | 4 ++++ .../Sources/Views/EmailAuthView.swift | 4 ++-- .../Sources/Views/SignedInView.swift | 5 +++- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index 3bcb9ca738..6fe84492fc 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -1,6 +1,13 @@ import FirebaseAuth import SwiftUI +let kAuthPickerTitle = "AuthPickerTitle" + +let kEnterYourEmail = "EnterYourEmail" +let kEnterYourPassword = "EnterYourPassword" + +let kSignedInTitle = "SignedIn" + let kKeyNotFound = "Key not found" let kUsersNotFoundError = "UserNotFoundError" @@ -19,7 +26,7 @@ public class StringUtils { self.bundle = bundle } - public func localizedString(forKey key: String) -> String { + public func localizedString(for key: String) -> String { let keyLocale = String.LocalizationValue(key) let value = String(localized: keyLocale, bundle: bundle) return value @@ -31,27 +38,27 @@ public class StringUtils { switch errorCode { case .emailAlreadyInUse: return localizedString( - forKey: kEmailAlreadyInUseError + for: kEmailAlreadyInUseError ) case .invalidEmail: - return localizedString(forKey: kInvalidEmailError) + return localizedString(for: kInvalidEmailError) case .weakPassword: - return localizedString(forKey: kWeakPasswordError) + return localizedString(for: kWeakPasswordError) case .tooManyRequests: return localizedString( - forKey: kSignUpTooManyTimesError + for: kSignUpTooManyTimesError ) case .wrongPassword: return localizedString( - forKey: kWrongPasswordError + for: kWrongPasswordError ) case .userNotFound: return localizedString( - forKey: kUsersNotFoundError + for: kUsersNotFoundError ) case .userDisabled: return localizedString( - forKey: kAccountDisabledError + for: kAccountDisabledError ) default: return error.localizedDescription diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift index 517149ce98..0f54c80345 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift @@ -18,6 +18,10 @@ public struct AuthPickerView { extension AuthPickerView: View { public var body: some View { VStack { + Text(authService.string.localizedString(for: kAuthPickerTitle)) + .font(.largeTitle) + .fontWeight(.bold) + .padding() if authService.authenticationState == .authenticated { SignedInView() } else if authService.authView == .passwordRecovery { diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift index f09a043226..866e5fd615 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift @@ -50,7 +50,7 @@ extension EmailAuthView: View { public var body: some View { VStack { LabeledContent { - TextField("Email", text: $email) + TextField(authService.string.localizedString(for: kEnterYourEmail), text: $email) .textInputAutocapitalization(.never) .disableAutocorrection(true) .focused($focus, equals: .email) @@ -66,7 +66,7 @@ extension EmailAuthView: View { .padding(.bottom, 4) LabeledContent { - SecureField("Password", text: $password) + SecureField(authService.string.localizedString(for: kEnterYourPassword), text: $password) .focused($focus, equals: .password) .submitLabel(.go) .onSubmit { diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift index 6b27315eb1..3c1f2b4b9f 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift @@ -15,7 +15,10 @@ extension SignedInView: View { public var body: some View { VStack { - Text("Signed in") + Text(authService.string.localizedString(for: kSignedInTitle)) + .font(.largeTitle) + .fontWeight(.bold) + .padding() Text("User: \(authService.currentUser?.email ?? "Unknown")") if authService.currentUser?.isEmailVerified == false { From d0c20c37bfb4417baa68412410b38c5cd44c1830 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 30 Apr 2025 10:32:36 +0100 Subject: [PATCH 02/16] password recovery string localisation --- .../Sources/Utils/StringUtils.swift | 15 ++++++++++ .../Sources/Views/EmailAuthView.swift | 2 +- .../Sources/Views/PasswordRecoveryView.swift | 29 ++++++++++++++----- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index 6fe84492fc..b2f7289e95 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -1,15 +1,30 @@ import FirebaseAuth import SwiftUI +// Auth Picker (not signed-in) let kAuthPickerTitle = "AuthPickerTitle" +// Used across multiple Views let kEnterYourEmail = "EnterYourEmail" let kEnterYourPassword = "EnterYourPassword" +let kOK = "OK" +let kBack = "Back" +// Signed-in let kSignedInTitle = "SignedIn" +let kForgotPasswordButtonLabel = "ForgotPasswordTitle" +let kForgotPasswordInputLabel = "ForgotPassword" + +// Password recovery +let kPasswordRecoveryTitle = "PasswordRecoveryTitle" +let kPasswordRecoveryEmailSentTitle = "PasswordRecoveryEmailSentTitle" +let kPasswordRecoveryMessage = "PasswordRecoveryMessage" +let kPasswordRecoveryEmailSentMessage = "PasswordRecoveryEmailSentMessage" + let kKeyNotFound = "Key not found" +// Errors let kUsersNotFoundError = "UserNotFoundError" let kEmailAlreadyInUseError = "EmailAlreadyInUseError" let kInvalidEmailError = "InvalidEmailError" diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift index 866e5fd615..d433264f03 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift @@ -83,7 +83,7 @@ extension EmailAuthView: View { Button(action: { authService.authView = .passwordRecovery }) { - Text("Forgotten Password?") + Text(authService.string.localizedString(for: kForgotPasswordButtonLabel)) } } diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordRecoveryView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordRecoveryView.swift index c53a6969e7..6aeccf52d3 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordRecoveryView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordRecoveryView.swift @@ -18,9 +18,15 @@ public struct PasswordRecoveryView { extension PasswordRecoveryView: View { public var body: some View { VStack { - Text("Password Recovery") + Text(authService.string.localizedString(for: kPasswordRecoveryTitle)) + .font(.largeTitle) + .fontWeight(.bold) + .padding() + + Divider() + LabeledContent { - TextField("Email", text: $email) + TextField(authService.string.localizedString(for: kEnterYourEmail), text: $email) .textInputAutocapitalization(.never) .disableAutocorrection(true) .submitLabel(.next) @@ -34,7 +40,7 @@ extension PasswordRecoveryView: View { await sendPasswordRecoveryEmail() } }) { - Text("Password Recovery") + Text(authService.string.localizedString(for: kForgotPasswordInputLabel)) .padding(.vertical, 8) .frame(maxWidth: .infinity) } @@ -44,11 +50,18 @@ extension PasswordRecoveryView: View { .buttonStyle(.borderedProminent) }.sheet(isPresented: $showModal) { VStack { - Text("Instructions") - .font(.headline) - Text("Please check your email for password recovery instructions.") + Text(authService.string.localizedString(for: kPasswordRecoveryEmailSentTitle)) + .font(.largeTitle) + .fontWeight(.bold) + .padding() + Text(authService.string.localizedString(for: kPasswordRecoveryMessage)) + .padding() + + Divider() + + Text(authService.string.localizedString(for: kPasswordRecoveryEmailSentMessage)) .padding() - Button("Dismiss") { + Button(authService.string.localizedString(for: kOK)) { showModal = false } .padding() @@ -62,7 +75,7 @@ extension PasswordRecoveryView: View { }) { Image(systemName: "chevron.left") .foregroundColor(.blue) - Text("Back") + Text(authService.string.localizedString(for: kBack)) .foregroundColor(.blue) }) } From 8d787fc344500ce2c161021bd915b4e0401bc694 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 30 Apr 2025 11:04:45 +0100 Subject: [PATCH 03/16] refactor: used computed properties for string localisation --- .../Sources/Utils/StringUtils.swift | 85 +++++++++++++++++++ .../Sources/Views/AuthPickerView.swift | 2 +- .../Sources/Views/EmailAuthView.swift | 6 +- .../Sources/Views/PasswordRecoveryView.swift | 16 ++-- .../Sources/Views/SignedInView.swift | 2 +- 5 files changed, 98 insertions(+), 13 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index b2f7289e95..db8e0d9af7 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -79,4 +79,89 @@ public class StringUtils { return error.localizedDescription } } + + /// Auth Picker title + /// found in: + /// - AuthPickerView + public var authPickerTitle: String { + return localizedString(for: kAuthPickerTitle) + } + + /// Email input label + /// found in: + /// - EmailAuthView + /// - PasswordRecoveryView + public var emailInputLabel: String { + return localizedString(for: kEnterYourEmail) + } + + /// Password button action label + /// found in: + /// - EmailAuthView + public var passwordButtonLabel: String { + return localizedString(for: kForgotPasswordButtonLabel) + } + + /// Password input label + /// found in: + /// - EmailAuthView + public var passwordInputLabel: String { + return localizedString(for: kEnterYourPassword) + } + + /// Password recovery title + /// found in: + /// - PasswordRecoveryView + public var passwordRecoveryTitle: String { + return localizedString(for: kPasswordRecoveryTitle) + } + + /// Password recovery email sent title + /// found in: + /// - PasswordRecoveryView + public var passwordRecoveryEmailSentTitle: String { + return localizedString(for: kPasswordRecoveryEmailSentTitle) + } + + /// Password recovery helper message + /// found in: + /// - PasswordRecoveryView + public var passwordRecoveryHelperMessage: String { + return localizedString(for: kPasswordRecoveryMessage) + } + + /// Password recovery email sent message + /// found in: + /// - PasswordRecoveryView + public var passwordRecoveryEmailSentMessage: String { + return localizedString(for: kPasswordRecoveryEmailSentMessage) + } + + /// Forgot password input label + /// found in: + /// - PasswordRecoveryView + public var forgotPasswordInputLabel: String { + return localizedString(for: kForgotPasswordInputLabel) + } + + /// Signed in title + /// found in: + /// - SignedInView + public var signedInTitle: String { + return localizedString(for: kSignedInTitle) + } + + /// General string - Back button label + /// found in: + /// - PasswordRecoveryView + public var backButtonLabel: String { + return localizedString(for: kBack) + } + + /// General string - OK button label + /// found in: + /// - PasswordRecoveryView + public var okButtonLabel: String { + return localizedString(for: kOK) + } } diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift index 0f54c80345..5e7b51d8be 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift @@ -18,7 +18,7 @@ public struct AuthPickerView { extension AuthPickerView: View { public var body: some View { VStack { - Text(authService.string.localizedString(for: kAuthPickerTitle)) + Text(authService.string.authPickerTitle) .font(.largeTitle) .fontWeight(.bold) .padding() diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift index d433264f03..5ce931bffc 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift @@ -50,7 +50,7 @@ extension EmailAuthView: View { public var body: some View { VStack { LabeledContent { - TextField(authService.string.localizedString(for: kEnterYourEmail), text: $email) + TextField(authService.string.emailInputLabel, text: $email) .textInputAutocapitalization(.never) .disableAutocorrection(true) .focused($focus, equals: .email) @@ -66,7 +66,7 @@ extension EmailAuthView: View { .padding(.bottom, 4) LabeledContent { - SecureField(authService.string.localizedString(for: kEnterYourPassword), text: $password) + SecureField(authService.string.passwordInputLabel, text: $password) .focused($focus, equals: .password) .submitLabel(.go) .onSubmit { @@ -83,7 +83,7 @@ extension EmailAuthView: View { Button(action: { authService.authView = .passwordRecovery }) { - Text(authService.string.localizedString(for: kForgotPasswordButtonLabel)) + Text(authService.string.passwordButtonLabel) } } diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordRecoveryView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordRecoveryView.swift index 6aeccf52d3..906aa93c4d 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordRecoveryView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordRecoveryView.swift @@ -18,7 +18,7 @@ public struct PasswordRecoveryView { extension PasswordRecoveryView: View { public var body: some View { VStack { - Text(authService.string.localizedString(for: kPasswordRecoveryTitle)) + Text(authService.string.passwordRecoveryTitle) .font(.largeTitle) .fontWeight(.bold) .padding() @@ -26,7 +26,7 @@ extension PasswordRecoveryView: View { Divider() LabeledContent { - TextField(authService.string.localizedString(for: kEnterYourEmail), text: $email) + TextField(authService.string.emailInputLabel, text: $email) .textInputAutocapitalization(.never) .disableAutocorrection(true) .submitLabel(.next) @@ -40,7 +40,7 @@ extension PasswordRecoveryView: View { await sendPasswordRecoveryEmail() } }) { - Text(authService.string.localizedString(for: kForgotPasswordInputLabel)) + Text(authService.string.forgotPasswordInputLabel) .padding(.vertical, 8) .frame(maxWidth: .infinity) } @@ -50,18 +50,18 @@ extension PasswordRecoveryView: View { .buttonStyle(.borderedProminent) }.sheet(isPresented: $showModal) { VStack { - Text(authService.string.localizedString(for: kPasswordRecoveryEmailSentTitle)) + Text(authService.string.passwordRecoveryEmailSentTitle) .font(.largeTitle) .fontWeight(.bold) .padding() - Text(authService.string.localizedString(for: kPasswordRecoveryMessage)) + Text(authService.string.passwordRecoveryMessage) .padding() Divider() - Text(authService.string.localizedString(for: kPasswordRecoveryEmailSentMessage)) + Text(authService.string.passwordRecoveryEmailSentMessage) .padding() - Button(authService.string.localizedString(for: kOK)) { + Button(authService.string.okButtonLabel) { showModal = false } .padding() @@ -75,7 +75,7 @@ extension PasswordRecoveryView: View { }) { Image(systemName: "chevron.left") .foregroundColor(.blue) - Text(authService.string.localizedString(for: kBack)) + Text(authService.string.backButtonLabel) .foregroundColor(.blue) }) } diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift index 3c1f2b4b9f..0cb4b1f2f3 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift @@ -15,7 +15,7 @@ extension SignedInView: View { public var body: some View { VStack { - Text(authService.string.localizedString(for: kSignedInTitle)) + Text(authService.string.signedInTitle) .font(.largeTitle) .fontWeight(.bold) .padding() From 2c57d97b7ec299714a23e9a6d9add6f1ebba4dc3 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 30 Apr 2025 11:05:36 +0100 Subject: [PATCH 04/16] chore: fix wrong property name --- .../Sources/Views/PasswordRecoveryView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordRecoveryView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordRecoveryView.swift index 906aa93c4d..a8bf56f262 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordRecoveryView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordRecoveryView.swift @@ -54,7 +54,7 @@ extension PasswordRecoveryView: View { .font(.largeTitle) .fontWeight(.bold) .padding() - Text(authService.string.passwordRecoveryMessage) + Text(authService.string.passwordRecoveryHelperMessage) .padding() Divider() From 29051e7619cb68111dcdee3a4b9f8a80ac13473a Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 30 Apr 2025 11:11:14 +0100 Subject: [PATCH 05/16] rm constant strings and use computed properties --- .../Sources/Utils/StringUtils.swift | 45 +++++-------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index db8e0d9af7..9d0d0cdabc 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -1,27 +1,6 @@ import FirebaseAuth import SwiftUI -// Auth Picker (not signed-in) -let kAuthPickerTitle = "AuthPickerTitle" - -// Used across multiple Views -let kEnterYourEmail = "EnterYourEmail" -let kEnterYourPassword = "EnterYourPassword" -let kOK = "OK" -let kBack = "Back" - -// Signed-in -let kSignedInTitle = "SignedIn" - -let kForgotPasswordButtonLabel = "ForgotPasswordTitle" -let kForgotPasswordInputLabel = "ForgotPassword" - -// Password recovery -let kPasswordRecoveryTitle = "PasswordRecoveryTitle" -let kPasswordRecoveryEmailSentTitle = "PasswordRecoveryEmailSentTitle" -let kPasswordRecoveryMessage = "PasswordRecoveryMessage" -let kPasswordRecoveryEmailSentMessage = "PasswordRecoveryEmailSentMessage" - let kKeyNotFound = "Key not found" // Errors @@ -84,7 +63,7 @@ public class StringUtils { /// found in: /// - AuthPickerView public var authPickerTitle: String { - return localizedString(for: kAuthPickerTitle) + return localizedString(for: "AuthPickerTitle") } /// Email input label @@ -92,76 +71,76 @@ public class StringUtils { /// - EmailAuthView /// - PasswordRecoveryView public var emailInputLabel: String { - return localizedString(for: kEnterYourEmail) + return localizedString(for: "EnterYourEmail") } /// Password button action label /// found in: /// - EmailAuthView public var passwordButtonLabel: String { - return localizedString(for: kForgotPasswordButtonLabel) + return localizedString(for: "ForgotPasswordTitle") } /// Password input label /// found in: /// - EmailAuthView public var passwordInputLabel: String { - return localizedString(for: kEnterYourPassword) + return localizedString(for: "EnterYourPassword") } /// Password recovery title /// found in: /// - PasswordRecoveryView public var passwordRecoveryTitle: String { - return localizedString(for: kPasswordRecoveryTitle) + return localizedString(for: "PasswordRecoveryTitle") } /// Password recovery email sent title /// found in: /// - PasswordRecoveryView public var passwordRecoveryEmailSentTitle: String { - return localizedString(for: kPasswordRecoveryEmailSentTitle) + return localizedString(for: "PasswordRecoveryEmailSentTitle") } /// Password recovery helper message /// found in: /// - PasswordRecoveryView public var passwordRecoveryHelperMessage: String { - return localizedString(for: kPasswordRecoveryMessage) + return localizedString(for: "PasswordRecoveryMessage") } /// Password recovery email sent message /// found in: /// - PasswordRecoveryView public var passwordRecoveryEmailSentMessage: String { - return localizedString(for: kPasswordRecoveryEmailSentMessage) + return localizedString(for: "PasswordRecoveryEmailSentMessage") } /// Forgot password input label /// found in: /// - PasswordRecoveryView public var forgotPasswordInputLabel: String { - return localizedString(for: kForgotPasswordInputLabel) + return localizedString(for: "ForgotPassword") } /// Signed in title /// found in: /// - SignedInView public var signedInTitle: String { - return localizedString(for: kSignedInTitle) + return localizedString(for: "SignedIn") } /// General string - Back button label /// found in: /// - PasswordRecoveryView public var backButtonLabel: String { - return localizedString(for: kBack) + return localizedString(for: "Back") } /// General string - OK button label /// found in: /// - PasswordRecoveryView public var okButtonLabel: String { - return localizedString(for: kOK) + return localizedString(for: "OK") } } From 61f461bb7d2b8433d69703ebdf6986ed80c4979e Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 30 Apr 2025 11:48:29 +0100 Subject: [PATCH 06/16] email auth view string localisation --- .../Sources/Strings/Localizable.xcstrings | 48 +++++++++++++------ .../Sources/Utils/StringUtils.swift | 28 +++++++++++ .../Sources/Views/EmailAuthView.swift | 7 +-- 3 files changed, 65 insertions(+), 18 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings index a4b95dde64..5a2c6047f9 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings @@ -249,6 +249,18 @@ } } }, + "ConfirmPasswordInputLabel" : { + "comment" : "Input label for confirming password when signing up", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Confirm Password" + } + } + } + }, "Delete" : { "comment" : "Text of Delete action button.", "extractionState" : "manual", @@ -381,6 +393,18 @@ } } }, + "EmailLinkSignInLabel" : { + "comment" : "Button label for email link sign-in", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prefer Email link sign-in?" + } + } + } + }, "EmailsDontMatch" : { "comment" : "Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars.", "extractionState" : "manual", @@ -404,6 +428,9 @@ } } } + }, + "Enter Password" : { + }, "EnterYourEmail" : { "comment" : "Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars.", @@ -488,9 +515,6 @@ } } } - }, - "Forgotten Password?" : { - }, "Instructions" : { @@ -519,6 +543,9 @@ } } }, + "Key" : { + "extractionState" : "manual" + }, "Log in" : { }, @@ -563,12 +590,6 @@ } } } - }, - "Password" : { - "comment" : "Label next to a password text field." - }, - "Password Recovery" : { - }, "PasswordRecoveryEmailSentMessage" : { "comment" : "Message displayed when the email for password recovery has been sent.", @@ -692,9 +713,6 @@ }, "Please check your email for email sign-in link." : { - }, - "Please check your email for password recovery instructions." : { - }, "Please check your email for verification link." : { @@ -833,9 +851,6 @@ }, "Sign up" : { - }, - "Signed in" : { - }, "SignedIn" : { "comment" : "Title of successfully signed in label.", @@ -932,6 +947,9 @@ } } } + }, + "Submit" : { + }, "TermsOfService" : { "comment" : "Text linked to a web page with the Terms of Service content.", diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index 9d0d0cdabc..fb29a49a74 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -130,6 +130,34 @@ public class StringUtils { return localizedString(for: "SignedIn") } + /// Confirm password + /// found in: + /// - EmailAuthView + public var confirmPasswordInputLabel: String { + return localizedString(for: "ConfirmPasswordInputLabel") + } + + /// Sign in with email button label or can be used as title + /// found in: + /// EmailAuthView + public var signInWithEmailButtonLabel: String { + return localizedString(for: "SignInWithEmail") + } + + /// Sign up with email button label + /// found in: + /// - EmailAuthView + public var signUpWithEmailButtonLabel: String { + return localizedString(for: "SignUpTitle") + } + + /// Sign up with email link button label + /// found in: + /// - EmailAuthView + public var signUpWithEmailLinkButtonLabel: String { + return localizedString(for: "EmailLinkSignInLabel") + } + /// General string - Back button label /// found in: /// - PasswordRecoveryView diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift index 5ce931bffc..633d66c9c1 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailAuthView.swift @@ -89,7 +89,7 @@ extension EmailAuthView: View { if authService.authenticationFlow == .signUp { LabeledContent { - SecureField("Confirm password", text: $confirmPassword) + SecureField(authService.string.confirmPasswordInputLabel, text: $confirmPassword) .focused($focus, equals: .confirmPassword) .submitLabel(.go) .onSubmit { @@ -110,7 +110,8 @@ extension EmailAuthView: View { } }) { if authService.authenticationState != .authenticating { - Text(authService.authenticationFlow == .login ? "Log in with password" : "Sign up") + Text(authService.authenticationFlow == .login ? authService.string + .signInWithEmailButtonLabel : authService.string.signUpWithEmailButtonLabel) .padding(.vertical, 8) .frame(maxWidth: .infinity) } else { @@ -127,7 +128,7 @@ extension EmailAuthView: View { Button(action: { authService.authView = .passwordRecovery }) { - Text("Prefer Email link sign-in?") + Text(authService.string.signUpWithEmailLinkButtonLabel) } } } From c115f7c93cff24ee4f260567486fc19ab55e4b9b Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 30 Apr 2025 13:10:19 +0100 Subject: [PATCH 07/16] email link view --- .../Sources/Strings/Localizable.xcstrings | 29 ++++++++++++++++--- .../Sources/Utils/StringUtils.swift | 28 ++++++++++++++++-- .../Sources/Views/EmailLinkView.swift | 14 ++++----- 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings index 5a2c6047f9..58d333e36d 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings @@ -394,7 +394,7 @@ } }, "EmailLinkSignInLabel" : { - "comment" : "Button label for email link sign-in", + "comment" : "Button label to push user to email link sign-in", "extractionState" : "manual", "localizations" : { "en" : { @@ -405,6 +405,18 @@ } } }, + "EmailLinkSignInTitle" : { + "comment" : "Sign in with email link View title", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sign in with email link" + } + } + } + }, "EmailsDontMatch" : { "comment" : "Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars.", "extractionState" : "manual", @@ -543,9 +555,6 @@ } } }, - "Key" : { - "extractionState" : "manual" - }, "Log in" : { }, @@ -842,6 +851,18 @@ }, "Send email sign-in link" : { + }, + "SendEmailSignInLinkButtonLabel" : { + "comment" : "Button label for sending email sign-in link", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Send email sign-in link" + } + } + } }, "Sign in with email link" : { diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index fb29a49a74..25c91e65f6 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -70,6 +70,7 @@ public class StringUtils { /// found in: /// - EmailAuthView /// - PasswordRecoveryView + /// - EmailLinkView public var emailInputLabel: String { return localizedString(for: "EnterYourEmail") } @@ -139,7 +140,7 @@ public class StringUtils { /// Sign in with email button label or can be used as title /// found in: - /// EmailAuthView + /// - EmailAuthView public var signInWithEmailButtonLabel: String { return localizedString(for: "SignInWithEmail") } @@ -151,16 +152,38 @@ public class StringUtils { return localizedString(for: "SignUpTitle") } - /// Sign up with email link button label + /// Sign-in with email link button label to push user to email link view /// found in: /// - EmailAuthView public var signUpWithEmailLinkButtonLabel: String { return localizedString(for: "EmailLinkSignInLabel") } + /// send email link sign-in button label + /// found in: + /// - EmailLinkView + public var sendEmailLinkButtonLabel: String { + return localizedString(for: "SendEmailSignInLinkButtonLabel") + } + + /// Sign in with email link View title + /// found in: + /// - EmailLinkView + public var signInWithEmailLinkViewTitle: String { + return localizedString(for: "EmailLinkSignInTitle") + } + + /// Sign in with email link View message + /// found in: + /// - EmailLinkView + public var signInWithEmailLinkViewMessage: String { + return localizedString(for: "SignInEmailSent") + } + /// General string - Back button label /// found in: /// - PasswordRecoveryView + /// - EmailLinkView public var backButtonLabel: String { return localizedString(for: "Back") } @@ -168,6 +191,7 @@ public class StringUtils { /// General string - OK button label /// found in: /// - PasswordRecoveryView + /// - EmailLinkView public var okButtonLabel: String { return localizedString(for: "OK") } diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailLinkView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailLinkView.swift index b8dbcce8f6..366686a3e4 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailLinkView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EmailLinkView.swift @@ -19,9 +19,9 @@ public struct EmailLinkView { extension EmailLinkView: View { public var body: some View { VStack { - Text("Sign in with email link") + Text(authService.string.signInWithEmailLinkViewTitle) LabeledContent { - TextField("Email", text: $email) + TextField(authService.string.emailInputLabel, text: $email) .textInputAutocapitalization(.never) .disableAutocorrection(true) .submitLabel(.next) @@ -36,7 +36,7 @@ extension EmailLinkView: View { authService.emailLink = email } }) { - Text("Send email sign-in link") + Text(authService.string.sendEmailLinkButtonLabel) .padding(.vertical, 8) .frame(maxWidth: .infinity) } @@ -47,11 +47,9 @@ extension EmailLinkView: View { Text(authService.errorMessage).foregroundColor(.red) }.sheet(isPresented: $showModal) { VStack { - Text("Instructions") - .font(.headline) - Text("Please check your email for email sign-in link.") + Text(authService.string.signInWithEmailLinkViewMessage) .padding() - Button("Dismiss") { + Button(authService.string.okButtonLabel) { showModal = false } .padding() @@ -69,7 +67,7 @@ extension EmailLinkView: View { }) { Image(systemName: "chevron.left") .foregroundColor(.blue) - Text("Back") + Text(authService.string.backButtonLabel) .foregroundColor(.blue) }) } From 77762b860f35abcbebf75b88c675afe0e4b1025a Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 30 Apr 2025 13:14:20 +0100 Subject: [PATCH 08/16] password prompt sheet --- .../Sources/Strings/Localizable.xcstrings | 21 ------------------- .../Sources/Utils/StringUtils.swift | 9 ++++++++ .../Sources/Views/PasswordPromptView.swift | 7 ++++--- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings index 58d333e36d..fb5bbe6e7c 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings @@ -233,9 +233,6 @@ } } } - }, - "Confirm password" : { - }, "ConfirmEmail" : { "comment" : "Title of confirm email label.", @@ -378,9 +375,6 @@ } } }, - "Email" : { - "comment" : "Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars." - }, "EmailAlreadyInUseError" : { "comment" : "Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars.", "extractionState" : "migrated", @@ -557,9 +551,6 @@ }, "Log in" : { - }, - "Log in with password" : { - }, "Login" : { @@ -719,15 +710,9 @@ } } } - }, - "Please check your email for email sign-in link." : { - }, "Please check your email for verification link." : { - }, - "Prefer Email link sign-in?" : { - }, "PrivacyPolicy" : { "comment" : "Text linked to a web page with the Privacy Policy content.", @@ -848,9 +833,6 @@ } } } - }, - "Send email sign-in link" : { - }, "SendEmailSignInLinkButtonLabel" : { "comment" : "Button label for sending email sign-in link", @@ -863,9 +845,6 @@ } } } - }, - "Sign in with email link" : { - }, "Sign out" : { diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index 25c91e65f6..018a73fb3a 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -85,6 +85,7 @@ public class StringUtils { /// Password input label /// found in: /// - EmailAuthView + /// - PasswordPromptView public var passwordInputLabel: String { return localizedString(for: "EnterYourPassword") } @@ -192,7 +193,15 @@ public class StringUtils { /// found in: /// - PasswordRecoveryView /// - EmailLinkView + /// - PasswordPromptView public var okButtonLabel: String { return localizedString(for: "OK") } + + /// General string - Cancel button label + /// found in: + /// - PasswordPromptView + public var cancelButtonLabel: String { + return localizedString(for: "Cancel") + } } diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordPromptView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordPromptView.swift index 0af5733d90..9566cd9254 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordPromptView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/PasswordPromptView.swift @@ -1,6 +1,7 @@ import SwiftUI struct PasswordPromptSheet { + @Environment(AuthService.self) private var authService @Bindable var coordinator: PasswordPromptCoordinator @State private var password = "" } @@ -8,16 +9,16 @@ struct PasswordPromptSheet { extension PasswordPromptSheet: View { var body: some View { VStack(spacing: 20) { - SecureField("Enter Password", text: $password) + SecureField(authService.string.passwordInputLabel, text: $password) .textFieldStyle(.roundedBorder) .padding() HStack { - Button("Cancel") { + Button(authService.string.cancelButtonLabel) { coordinator.cancel() } Spacer() - Button("Submit") { + Button(authService.string.okButtonLabel) { coordinator.submit(password: password) } .disabled(password.isEmpty) From 8908d95078cb3a3399d1fd431e003405a20b69f8 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Wed, 30 Apr 2025 13:19:15 +0100 Subject: [PATCH 09/16] signed in view --- .../Sources/Utils/StringUtils.swift | 21 +++++++++++++++++++ .../Sources/Views/SignedInView.swift | 7 ++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index 018a73fb3a..54ebc0b04d 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -181,6 +181,27 @@ public class StringUtils { return localizedString(for: "SignInEmailSent") } + /// Account settings - Delete button label + /// found in: + /// - SignedInView + public var deleteAccountButtonLabel: String { + return localizedString(for: "AS_DeleteAccount") + } + + /// Account settings - Email label + /// found in: + /// SignedInView + public var accountSettingsEmailLabel: String { + return localizedString(for: "AS_Email") + } + + /// Account settings - sign out button label + /// found in: + /// - SignedInView + public var signOutButtonLabel: String { + return localizedString(for: "AS_SignOut") + } + /// General string - Back button label /// found in: /// - PasswordRecoveryView diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift index 0cb4b1f2f3..1cfb1d432c 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift @@ -19,13 +19,14 @@ extension SignedInView: View { .font(.largeTitle) .fontWeight(.bold) .padding() - Text("User: \(authService.currentUser?.email ?? "Unknown")") + Text(authService.string.accountSettingsEmailLabel) + Text("\(authService.currentUser?.email ?? "Unknown")") if authService.currentUser?.isEmailVerified == false { VerifyEmailView() } - Button("Sign out") { + Button(authService.string.signOutButtonLabel) { Task { do { try await authService.signOut() @@ -33,7 +34,7 @@ extension SignedInView: View { } } Divider() - Button("Delete account") { + Button(authService.string.deleteAccountButtonLabel) { Task { do { try await authService.deleteUser() From 2c37c5309d3a4ff3ce558ca19cd6e14350a8c55d Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 8 May 2025 12:28:46 +0100 Subject: [PATCH 10/16] update password button label --- .../FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift | 8 ++++++++ .../FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index 54ebc0b04d..3005dd44c9 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -201,6 +201,14 @@ public class StringUtils { public var signOutButtonLabel: String { return localizedString(for: "AS_SignOut") } + + /// Account settings - update password button label + /// found in: + /// SignedInView + public var updatePasswordButtonLabel: String { + return localizedString(for: "Update password") + } + /// General string - Back button label /// found in: diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift index 4d16d4f0cb..e1e6d97c24 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift @@ -30,7 +30,7 @@ extension SignedInView: View { VerifyEmailView() } Divider() - Button("Update password") { + Button(authService.string.updatePasswordButtonLabel) { authService.authView = .updatePassword } Divider() From eed57b8355edab1af0a3b58ef6c22d34a8711867 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 8 May 2025 13:03:52 +0100 Subject: [PATCH 11/16] chore: rm var constants - not needed --- .../Sources/Utils/StringUtils.swift | 70 ++++++++----------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index 3005dd44c9..7b7ddb7e3e 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -3,16 +3,6 @@ import SwiftUI let kKeyNotFound = "Key not found" -// Errors -let kUsersNotFoundError = "UserNotFoundError" -let kEmailAlreadyInUseError = "EmailAlreadyInUseError" -let kInvalidEmailError = "InvalidEmailError" -let kWeakPasswordError = "WeakPasswordError" -let kSignUpTooManyTimesError = "SignUpTooManyTimesError" -let kWrongPasswordError = "WrongPasswordError" -let kAccountDisabledError = "AccountDisabledError" -let kEmailsDoNotMatchError = "EmailsDoNotMatchError" -let kUnknownError = "UnknownError" public class StringUtils { let bundle: Bundle @@ -27,37 +17,37 @@ public class StringUtils { } public func localizedErrorMessage(for error: Error) -> String { - let authError = error as NSError - let errorCode = AuthErrorCode(rawValue: authError.code) - switch errorCode { - case .emailAlreadyInUse: - return localizedString( - for: kEmailAlreadyInUseError - ) - case .invalidEmail: - return localizedString(for: kInvalidEmailError) - case .weakPassword: - return localizedString(for: kWeakPasswordError) - case .tooManyRequests: - return localizedString( - for: kSignUpTooManyTimesError - ) - case .wrongPassword: - return localizedString( - for: kWrongPasswordError - ) - case .userNotFound: - return localizedString( - for: kUsersNotFoundError - ) - case .userDisabled: - return localizedString( - for: kAccountDisabledError - ) - default: - return error.localizedDescription + let authError = error as NSError + let errorCode = AuthErrorCode(rawValue: authError.code) + switch errorCode { + case .emailAlreadyInUse: + return localizedString( + for: "EmailAlreadyInUseError" + ) + case .invalidEmail: + return localizedString(for: "InvalidEmailError") + case .weakPassword: + return localizedString(for: "WeakPasswordError") + case .tooManyRequests: + return localizedString( + for: "SignUpTooManyTimesError" + ) + case .wrongPassword: + return localizedString( + for: "WrongPasswordError" + ) + case .userNotFound: + return localizedString( + for: "UserNotFoundError" + ) + case .userDisabled: + return localizedString( + for: "AccountDisabledError" + ) + default: + return error.localizedDescription + } } - } /// Auth Picker title /// found in: From 683f08e2dbe391b548cb063f8c41967b4133d22a Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 8 May 2025 13:12:19 +0100 Subject: [PATCH 12/16] update verify email --- .../Sources/Strings/Localizable.xcstrings | 45 ++++++++++++------- .../Sources/Utils/StringUtils.swift | 14 ++++++ .../Sources/Views/VerifyEmailView.swift | 8 ++-- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings index 5b391dce64..111c5437c0 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings @@ -1,6 +1,9 @@ { "sourceLanguage" : "en", "strings" : { + "%@" : { + + }, "AccountDisabledError" : { "comment" : "Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars.", "extractionState" : "migrated", @@ -234,6 +237,9 @@ } } } + }, + "Confirm password" : { + }, "ConfirmEmail" : { "comment" : "Title of confirm email label.", @@ -270,9 +276,6 @@ } } } - }, - "Delete account" : { - }, "DeleteAccountBody" : { "comment" : "Alert message body shown to confirm account deletion action.", @@ -435,9 +438,6 @@ } } } - }, - "Enter Password" : { - }, "EnterYourEmail" : { "comment" : "Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars.", @@ -591,6 +591,9 @@ } } } + }, + "Password" : { + }, "PasswordRecoveryEmailSentMessage" : { "comment" : "Message displayed when the email for password recovery has been sent.", @@ -846,9 +849,6 @@ } } } - }, - "Sign out" : { - }, "Sign up" : { @@ -948,9 +948,6 @@ } } } - }, - "Submit" : { - }, "TermsOfService" : { "comment" : "Text linked to a web page with the Terms of Service content.", @@ -1060,6 +1057,17 @@ } } }, + "Update password" : { + "comment" : "Update password button label", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Update password" + } + } + } + }, "UpdateEmailAlertMessage" : { "comment" : "Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars.", "extractionState" : "manual", @@ -1083,9 +1091,6 @@ } } } - }, - "User: %@" : { - }, "UserNotFoundError" : { "comment" : "Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars.", @@ -1100,7 +1105,15 @@ } }, "Verify email address?" : { - + "comment" : "Label for sending email verification to user.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verify email address?" + } + } + } }, "VerifyItsYou" : { "comment" : "Alert message title show for re-authorization.", diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index 7b7ddb7e3e..80c425c242 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -198,6 +198,20 @@ public class StringUtils { public var updatePasswordButtonLabel: String { return localizedString(for: "Update password") } + + /// Account settings - send email verification label + /// found in: + /// VerifyEmailView + public var sendEmailVerificationButtonLabel: String { + return localizedString(for: "Verify email address?") + } + + /// Account settings - verify email sheet message + /// found in: + /// VerifyEmailView + public var verifyEmailSheetMessage: String { + return localizedString(for: "Verification email sent") + } /// General string - Back button label diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/VerifyEmailView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/VerifyEmailView.swift index ddf246c915..ca95ee1387 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/VerifyEmailView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/VerifyEmailView.swift @@ -21,7 +21,7 @@ extension VerifyEmailView: View { await sendEmailVerification() } }) { - Text("Verify email address?") + Text(authService.string.sendEmailVerificationButtonLabel) .padding(.vertical, 8) .frame(maxWidth: .infinity) } @@ -30,11 +30,9 @@ extension VerifyEmailView: View { .buttonStyle(.borderedProminent) }.sheet(isPresented: $showModal) { VStack { - Text("Instructions") + Text(authService.string.verifyEmailSheetMessage) .font(.headline) - Text("Please check your email for verification link.") - .padding() - Button("Dismiss") { + Button(authService.string.okButtonLabel) { showModal = false } .padding() From 57060722b223e859381169c915e660d19cea6d1c Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 9 May 2025 10:40:27 +0100 Subject: [PATCH 13/16] chore: facebook string localization --- .../Sources/Utils/StringUtils.swift | 99 ++++++++++++------- .../Sources/Views/SignedInView.swift | 10 +- .../Views/SignInWithFacebookButton.swift | 16 +-- 3 files changed, 79 insertions(+), 46 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index 80c425c242..4b54902a8c 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -3,7 +3,6 @@ import SwiftUI let kKeyNotFound = "Key not found" - public class StringUtils { let bundle: Bundle init(bundle: Bundle) { @@ -17,37 +16,37 @@ public class StringUtils { } public func localizedErrorMessage(for error: Error) -> String { - let authError = error as NSError - let errorCode = AuthErrorCode(rawValue: authError.code) - switch errorCode { - case .emailAlreadyInUse: - return localizedString( - for: "EmailAlreadyInUseError" - ) - case .invalidEmail: - return localizedString(for: "InvalidEmailError") - case .weakPassword: - return localizedString(for: "WeakPasswordError") - case .tooManyRequests: - return localizedString( - for: "SignUpTooManyTimesError" - ) - case .wrongPassword: - return localizedString( - for: "WrongPasswordError" - ) - case .userNotFound: - return localizedString( - for: "UserNotFoundError" - ) - case .userDisabled: - return localizedString( - for: "AccountDisabledError" - ) - default: - return error.localizedDescription - } + let authError = error as NSError + let errorCode = AuthErrorCode(rawValue: authError.code) + switch errorCode { + case .emailAlreadyInUse: + return localizedString( + for: "EmailAlreadyInUseError" + ) + case .invalidEmail: + return localizedString(for: "InvalidEmailError") + case .weakPassword: + return localizedString(for: "WeakPasswordError") + case .tooManyRequests: + return localizedString( + for: "SignUpTooManyTimesError" + ) + case .wrongPassword: + return localizedString( + for: "WrongPasswordError" + ) + case .userNotFound: + return localizedString( + for: "UserNotFoundError" + ) + case .userDisabled: + return localizedString( + for: "AccountDisabledError" + ) + default: + return error.localizedDescription } + } /// Auth Picker title /// found in: @@ -191,7 +190,7 @@ public class StringUtils { public var signOutButtonLabel: String { return localizedString(for: "AS_SignOut") } - + /// Account settings - update password button label /// found in: /// SignedInView @@ -212,7 +211,6 @@ public class StringUtils { public var verifyEmailSheetMessage: String { return localizedString(for: "Verification email sent") } - /// General string - Back button label /// found in: @@ -237,4 +235,39 @@ public class StringUtils { public var cancelButtonLabel: String { return localizedString(for: "Cancel") } + + /// Facebook provider + /// found in: + /// - SignInWithFacebookButton + public var facebookLoginButtonLabel: String { + return localizedString(for: "Continue with Facebook") + } + + /// Facebook provider + /// found in: + /// - SignInWithFacebookButton + public var facebookLoginCancelledLabel: String { + return localizedString(for: "Facebook login cancelled") + } + + /// Facebook provider + /// found in: + /// - SignInWithFacebookButton + public var authorizeUserTrackingLabel: String { + return localizedString(for: "Authorize User Tracking") + } + + /// Facebook provider + /// found in: + /// - SignInWithFacebookButton + public var facebookLimitedLoginLabel: String { + return localizedString(for: "Limited Login") + } + + /// Facebook provider + /// found in: + /// - SignInWithFacebookButton + public var facebookAuthorizeUserTrackingMessage: String { + return localizedString(for: "For classic Facebook login, please authorize user tracking.") + } } diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift index e1e6d97c24..a42ecc90bc 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/SignedInView.swift @@ -20,11 +20,11 @@ extension SignedInView: View { } else { VStack { Text(authService.string.signedInTitle) - .font(.largeTitle) - .fontWeight(.bold) - .padding() - Text(authService.string.accountSettingsEmailLabel) - Text("\(authService.currentUser?.email ?? "Unknown")") + .font(.largeTitle) + .fontWeight(.bold) + .padding() + Text(authService.string.accountSettingsEmailLabel) + Text("\(authService.currentUser?.email ?? "Unknown")") if authService.currentUser?.isEmailVerified == false { VerifyEmailView() diff --git a/FirebaseSwiftUI/FirebaseFacebookSwiftUI/Sources/Views/SignInWithFacebookButton.swift b/FirebaseSwiftUI/FirebaseFacebookSwiftUI/Sources/Views/SignInWithFacebookButton.swift index 3520fe67c7..c04b3e0898 100644 --- a/FirebaseSwiftUI/FirebaseFacebookSwiftUI/Sources/Views/SignInWithFacebookButton.swift +++ b/FirebaseSwiftUI/FirebaseFacebookSwiftUI/Sources/Views/SignInWithFacebookButton.swift @@ -66,7 +66,7 @@ extension SignInWithFacebookButton: View { Image(systemName: "f.circle.fill") .font(.title) .foregroundColor(.white) - Text("Continue with Facebook") + Text(authService.string.facebookLoginButtonLabel) .fontWeight(.semibold) .foregroundColor(.white) } @@ -77,13 +77,13 @@ extension SignInWithFacebookButton: View { } .alert(isPresented: $showCanceledAlert) { Alert( - title: Text("Facebook login cancelled"), - dismissButton: .default(Text("OK")) + title: Text(authService.string.facebookLoginCancelledLabel), + dismissButton: .default(Text(authService.string.okButtonLabel)) ) } HStack { - Text("Authorize User Tracking") + Text(authService.string.authorizeUserTrackingLabel) .font(.footnote) .foregroundColor(.blue) .underline() @@ -93,16 +93,16 @@ extension SignInWithFacebookButton: View { Toggle(isOn: limitedLoginBinding) { HStack { Spacer() // This will push the text to the left of the toggle - Text("Limited Login") + Text(authService.string.facebookLimitedLoginLabel) .foregroundColor(.blue) } } .toggleStyle(SwitchToggleStyle(tint: .green)) .alert(isPresented: $showUserTrackingAlert) { Alert( - title: Text("Authorize User Tracking"), - message: Text("For classic Facebook login, please authorize user tracking."), - dismissButton: .default(Text("OK")) + title: Text(authService.string.authorizeUserTrackingLabel), + message: Text(authService.string.facebookAuthorizeUserTrackingMessage), + dismissButton: .default(Text(authService.string.okButtonLabel)) ) } } From fda744851a866045c8782471c794e91f78ae344c Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 9 May 2025 10:54:48 +0100 Subject: [PATCH 14/16] auth picker view labels --- .../Sources/Strings/Localizable.xcstrings | 18 ++++++++++-- .../Sources/Utils/StringUtils.swift | 28 +++++++++++++++++++ .../Sources/Views/AuthPickerView.swift | 10 ++++--- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings index 111c5437c0..ce1a25b183 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Strings/Localizable.xcstrings @@ -329,7 +329,14 @@ }, "Don't have an account yet?" : { - + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Don't have an account yet?" + } + } + } }, "EditEmailTitle" : { "comment" : "Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars.", @@ -554,7 +561,14 @@ }, "Login" : { - + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Login" + } + } + } }, "Name" : { "comment" : "Label next to a name text field.", diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index 4b54902a8c..3eb83e8290 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -236,6 +236,34 @@ public class StringUtils { return localizedString(for: "Cancel") } + /// Email provider + /// found in: + /// - AuthPickerView + public var emailLoginFlowLabel: String { + return localizedString(for: "Login") + } + + /// Email provider + /// found in: + /// - AuthPickerView + public var emailSignUpFlowLabel: String { + return localizedString(for: "Sign up") + } + + /// Email provider + /// found in: + /// - AuthPickerView + public var dontHaveAnAccountYetLabel: String { + return localizedString(for: "Don't have an account yet?") + } + + /// Email provider + /// found in: + /// - AuthPickerView + public var alreadyHaveAnAccountLabel: String { + return localizedString(for: "Already have an account?") + } + /// Facebook provider /// found in: /// - SignInWithFacebookButton diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift index 8be646e64c..232e853aef 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift @@ -29,21 +29,23 @@ extension AuthPickerView: View { } else if authService.authView == .emailLink { EmailLinkView() } else { - Text(authService.authenticationFlow == .login ? "Login" : "Sign up") + Text(authService.authenticationFlow == .login ? authService.string + .emailLoginFlowLabel : authService.string.emailSignUpFlowLabel) VStack { Divider() } EmailAuthView() authService.renderButtons() VStack { Divider() } HStack { Text(authService - .authenticationFlow == .login ? "Don't have an account yet?" : - "Already have an account?") + .authenticationFlow == .login ? authService.string.dontHaveAnAccountYetLabel : + authService.string.alreadyHaveAnAccountLabel) Button(action: { withAnimation { switchFlow() } }) { - Text(authService.authenticationFlow == .signUp ? "Log in" : "Sign up") + Text(authService.authenticationFlow == .signUp ? authService.string + .emailLoginFlowLabel : authService.string.emailSignUpFlowLabel) .fontWeight(.semibold) .foregroundColor(.blue) } From a25bb95e94e49b79530de8cf24c43108e6e75876 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 9 May 2025 11:07:53 +0100 Subject: [PATCH 15/16] update password --- .../FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift | 5 ++++- .../FirebaseAuthSwiftUI/Sources/Views/UpdatePassword.swift | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index 3eb83e8290..0eaebdec38 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -75,6 +75,7 @@ public class StringUtils { /// found in: /// - EmailAuthView /// - PasswordPromptView + /// - UpdatePassword public var passwordInputLabel: String { return localizedString(for: "EnterYourPassword") } @@ -124,6 +125,7 @@ public class StringUtils { /// Confirm password /// found in: /// - EmailAuthView + /// - UpdatePassword public var confirmPasswordInputLabel: String { return localizedString(for: "ConfirmPasswordInputLabel") } @@ -193,7 +195,8 @@ public class StringUtils { /// Account settings - update password button label /// found in: - /// SignedInView + /// - SignedInView + /// - UpdatePassword public var updatePasswordButtonLabel: String { return localizedString(for: "Update password") } diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/UpdatePassword.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/UpdatePassword.swift index cb7925197e..bb22706e72 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/UpdatePassword.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/UpdatePassword.swift @@ -35,7 +35,7 @@ extension UpdatePasswordView: View { public var body: some View { VStack { LabeledContent { - SecureField("Password", text: $password) + SecureField(authService.string.passwordInputLabel, text: $password) .focused($focus, equals: .password) .submitLabel(.go) } label: { @@ -48,7 +48,7 @@ extension UpdatePasswordView: View { Divider() LabeledContent { - SecureField("Confirm password", text: $confirmPassword) + SecureField(authService.string.confirmPasswordInputLabel, text: $confirmPassword) .focused($focus, equals: .confirmPassword) .submitLabel(.go) } label: { @@ -66,7 +66,7 @@ extension UpdatePasswordView: View { authService.authView = .authPicker } }, label: { - Text("Update password") + Text(authService.string.updatePasswordButtonLabel) .padding(.vertical, 8) .frame(maxWidth: .infinity) From 6c461523cb71f2a44fe1db66a61c1cc8c640e19b Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 9 May 2025 11:25:27 +0100 Subject: [PATCH 16/16] chore: update phone number labels --- .../Sources/Utils/StringUtils.swift | 26 +++++++++++++++++++ .../Sources/Views/PhoneAuthButtonView.swift | 8 +++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift index 0eaebdec38..170632b512 100644 --- a/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift +++ b/FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift @@ -301,4 +301,30 @@ public class StringUtils { public var facebookAuthorizeUserTrackingMessage: String { return localizedString(for: "For classic Facebook login, please authorize user tracking.") } + + /// Phone provider + /// found in: + /// - PhoneAuthButtonView + public var enterPhoneNumberLabel: String { + return localizedString(for: "Enter phone number") + } + /// Phone provider + /// found in: + /// - PhoneAuthButtonView + public var phoneNumberVerificationCodeLabel: String { + return localizedString(for: "Enter verification code") + } + /// Phone provider + /// found in: + /// - PhoneAuthButtonView + public var smsCodeSentLabel: String { + return localizedString(for: "SMS code sent") + } + + /// Phone provider + /// found in: + /// - PhoneAuthButtonView + public var verifyPhoneNumberAndSignInLabel: String { + return localizedString(for: "Verify phone number and sign-in") + } } diff --git a/FirebaseSwiftUI/FirebasePhoneAuthSwiftUI/Sources/Views/PhoneAuthButtonView.swift b/FirebaseSwiftUI/FirebasePhoneAuthSwiftUI/Sources/Views/PhoneAuthButtonView.swift index 4e971dcdea..5b71b156bc 100644 --- a/FirebaseSwiftUI/FirebasePhoneAuthSwiftUI/Sources/Views/PhoneAuthButtonView.swift +++ b/FirebaseSwiftUI/FirebasePhoneAuthSwiftUI/Sources/Views/PhoneAuthButtonView.swift @@ -19,7 +19,7 @@ extension PhoneAuthButtonView: View { if authService.authenticationState != .authenticating { VStack { LabeledContent { - TextField("Enter phone number", text: $phoneNumber) + TextField(authService.string.enterPhoneNumberLabel, text: $phoneNumber) .textInputAutocapitalization(.never) .disableAutocorrection(true) .submitLabel(.next) @@ -41,7 +41,7 @@ extension PhoneAuthButtonView: View { } } }) { - Text("Send SMS code") + Text(authService.string.smsCodeSentLabel) .padding(.vertical, 8) .frame(maxWidth: .infinity) } @@ -51,7 +51,7 @@ extension PhoneAuthButtonView: View { .buttonStyle(.borderedProminent) Text(errorMessage).foregroundColor(.red) }.sheet(isPresented: $showVerificationCodeInput) { - TextField("Enter verification code", text: $verificationCode) + TextField(authService.string.phoneNumberVerificationCodeLabel, text: $verificationCode) .keyboardType(.numberPad) .padding() .background(Color(.systemGray6)) @@ -71,7 +71,7 @@ extension PhoneAuthButtonView: View { showVerificationCodeInput = false } }) { - Text("Verify phone number and sign-in") + Text(authService.string.verifyPhoneNumberAndSignInLabel) .foregroundColor(.white) .padding() .frame(maxWidth: .infinity)