Use strings from Localazy (#718)

* Adopt strings from Localazy.

* Remove all old Android strings.

* Disable german snapshot tests for now.

* Rebase and add latest strings.
This commit is contained in:
Doug
2023-03-27 18:18:59 +01:00
committed by GitHub
parent 8daa23b27a
commit 2b753b1135
215 changed files with 1911 additions and 118672 deletions
@@ -38,15 +38,15 @@ struct AnalyticsPromptViewState: BindableState {
/// A collection of strings for the UI that need to be parsed from HTML
struct AnalyticsPromptStrings {
let optInContent: AttributedString
let point1 = AttributedStringBuilder().fromHTML(ElementL10n.analyticsOptInListItem1) ?? AttributedString(ElementL10n.analyticsOptInListItem1)
let point2 = AttributedStringBuilder().fromHTML(ElementL10n.analyticsOptInListItem2) ?? AttributedString(ElementL10n.analyticsOptInListItem2)
let point1 = AttributedStringBuilder().fromHTML(UntranslatedL10n.analyticsOptInListItem1) ?? AttributedString(UntranslatedL10n.analyticsOptInListItem1)
let point2 = AttributedStringBuilder().fromHTML(UntranslatedL10n.analyticsOptInListItem2) ?? AttributedString(UntranslatedL10n.analyticsOptInListItem2)
init() {
// Create the opt in content with a placeholder.
let linkPlaceholder = "{link}"
var optInContent = AttributedString(ElementL10n.analyticsOptInContent(InfoPlistReader.main.bundleDisplayName, linkPlaceholder))
var optInContent = AttributedString(UntranslatedL10n.analyticsOptInContent(InfoPlistReader.main.bundleDisplayName, linkPlaceholder))
optInContent.replace(linkPlaceholder,
with: ElementL10n.analyticsOptInContentLink,
with: UntranslatedL10n.analyticsOptInContentLink,
asLinkTo: ServiceLocator.shared.settings.analyticsConfiguration.termsURL)
self.optInContent = optInContent
}
@@ -59,7 +59,7 @@ struct AnalyticsPrompt: View {
Image(uiImage: Asset.Images.analyticsLogo.image)
.padding(.bottom, 25)
Text(ElementL10n.analyticsOptInTitle(InfoPlistReader.main.bundleDisplayName))
Text(UntranslatedL10n.analyticsOptInTitle(InfoPlistReader.main.bundleDisplayName))
.font(.element.title2Bold)
.multilineTextAlignment(.center)
.foregroundColor(.element.primaryContent)
@@ -84,7 +84,7 @@ struct AnalyticsPrompt: View {
VStack(alignment: .leading) {
AnalyticsPromptCheckmarkItem(attributedString: context.viewState.strings.point1)
AnalyticsPromptCheckmarkItem(attributedString: context.viewState.strings.point1)
AnalyticsPromptCheckmarkItem(string: ElementL10n.analyticsOptInListItem3)
AnalyticsPromptCheckmarkItem(string: UntranslatedL10n.analyticsOptInListItem3)
}
.fixedSize(horizontal: false, vertical: true)
.font(.element.body)
@@ -96,13 +96,13 @@ struct AnalyticsPrompt: View {
private var buttons: some View {
VStack {
Button { context.send(viewAction: .enable) } label: {
Text(ElementL10n.actionEnable)
Text(L10n.actionEnable)
.font(.element.bodyBold)
}
.buttonStyle(.elementAction(.xLarge))
Button { context.send(viewAction: .disable) } label: {
Text(ElementL10n.actionNotNow)
Text(L10n.actionNotNow)
.font(.element.bodyBold)
.padding(12)
}
@@ -125,7 +125,7 @@ class AuthenticationCoordinator: CoordinatorProtocol {
private func startLoading() {
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
title: ElementL10n.loading,
title: L10n.commonLoading,
persistent: true))
}
@@ -95,7 +95,7 @@ final class LoginCoordinator: CoordinatorProtocol {
if isInteractionBlocking {
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
title: ElementL10n.loading,
title: L10n.commonLoading,
persistent: true))
} else {
viewModel.update(isLoading: true)
@@ -108,11 +108,11 @@ final class LoginCoordinator: CoordinatorProtocol {
}
private func indicateSuccess() {
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: ElementL10n.dialogTitleSuccess))
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: L10n.commonSuccess))
}
private func indicateFailure() {
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: ElementL10n.dialogTitleError))
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: L10n.commonError))
}
/// Processes an error to either update the flow or display it to the user.
@@ -121,13 +121,13 @@ final class LoginCoordinator: CoordinatorProtocol {
switch error {
case .invalidCredentials:
viewModel.displayError(.alert(ElementL10n.authInvalidLoginParam))
viewModel.displayError(.alert(L10n.screenLoginErrorInvalidCredentials))
case .accountDeactivated:
viewModel.displayError(.alert(ElementL10n.authInvalidLoginDeactivatedAccount))
viewModel.displayError(.alert(L10n.screenLoginErrorDeactivatedAccount))
case .slidingSyncNotAvailable:
viewModel.displayError(.slidingSyncAlert)
default:
viewModel.displayError(.alert(ElementL10n.unknownError))
viewModel.displayError(.alert(L10n.errorUnknown))
}
}
@@ -159,7 +159,7 @@ final class LoginCoordinator: CoordinatorProtocol {
Task {
switch await authenticationService.login(username: username,
password: password,
initialDeviceName: UIDevice.current.initialDisplayName,
initialDeviceName: UIDevice.current.initialDeviceName,
deviceId: nil) {
case .success(let userSession):
callback?(.signedIn(userSession))
@@ -56,19 +56,19 @@ class LoginViewModel: LoginViewModelType, LoginViewModelProtocol {
switch type {
case .alert(let message):
state.bindings.alertInfo = AlertInfo(id: type,
title: ElementL10n.dialogTitleError,
title: L10n.commonError,
message: message)
case .invalidHomeserver:
state.bindings.alertInfo = AlertInfo(id: type,
title: ElementL10n.dialogTitleError,
message: ElementL10n.loginSigninMatrixIdErrorInvalidMatrixId)
title: L10n.commonError,
message: L10n.screenLoginErrorInvalidUserId)
case .slidingSyncAlert:
let openURL = { UIApplication.shared.open(ServiceLocator.shared.settings.slidingSyncLearnMoreURL) }
state.bindings.alertInfo = AlertInfo(id: .slidingSyncAlert,
title: ElementL10n.serverSelectionSlidingSyncAlertTitle,
message: ElementL10n.serverSelectionSlidingSyncAlertMessage,
primaryButton: .init(title: ElementL10n.actionLearnMore, role: .cancel, action: openURL),
secondaryButton: .init(title: ElementL10n.actionCancel, action: nil))
title: L10n.commonServerNotSupported,
message: L10n.screenChangeServerErrorNoSlidingSyncMessage,
primaryButton: .init(title: L10n.actionLearnMore, role: .cancel, action: openURL),
secondaryButton: .init(title: L10n.actionCancel, action: nil))
// Clear out the invalid username to avoid an attempted login to matrix.org
state.bindings.username = ""
@@ -53,7 +53,7 @@ struct LoginScreen: View {
/// The header containing a Welcome Back title.
var header: some View {
Text(ElementL10n.ftueAuthWelcomeBackTitle)
Text(L10n.screenLoginTitle)
.font(.element.title1Bold)
.multilineTextAlignment(.center)
.foregroundColor(.element.primaryContent)
@@ -69,16 +69,16 @@ struct LoginScreen: View {
/// The form with text fields for username and password, along with a submit button.
var loginForm: some View {
VStack(alignment: .leading, spacing: 0) {
Text(ElementL10n.ftueAuthSignInEnterDetails)
Text(L10n.screenLoginFormHeader)
.font(.element.footnote)
.foregroundColor(.element.primaryContent)
.padding(.horizontal, 16)
.padding(.bottom, 8)
TextField(ElementL10n.username,
TextField(L10n.commonUsername,
text: $context.username,
// Prompt colour fixes a flicker that occurs before the text field style introspects the field.
prompt: Text(ElementL10n.username).foregroundColor(.element.tertiaryContent))
prompt: Text(L10n.commonUsername).foregroundColor(.element.tertiaryContent))
.focused($isUsernameFocused)
.textFieldStyle(.elementInput(accessibilityIdentifier: A11yIdentifiers.loginScreen.emailUsername))
.disableAutocorrection(true)
@@ -89,10 +89,10 @@ struct LoginScreen: View {
.onSubmit { isPasswordFocused = true }
.padding(.bottom, 20)
SecureField(ElementL10n.loginSignupPasswordHint,
SecureField(L10n.commonPassword,
text: $context.password,
// Prompt colour fixes a flicker that occurs before the text field style introspects the field.
prompt: Text(ElementL10n.loginSignupPasswordHint).foregroundColor(.element.tertiaryContent))
prompt: Text(L10n.commonPassword).foregroundColor(.element.tertiaryContent))
.focused($isPasswordFocused)
.textFieldStyle(.elementInput(accessibilityIdentifier: A11yIdentifiers.loginScreen.password))
.textContentType(.password)
@@ -102,7 +102,7 @@ struct LoginScreen: View {
Spacer().frame(height: 32)
Button(action: submit) {
Text(ElementL10n.loginContinue)
Text(L10n.actionContinue)
}
.buttonStyle(.elementAction(.xLarge))
.disabled(!context.viewState.canSubmit)
@@ -113,7 +113,7 @@ struct LoginScreen: View {
/// The OIDC button that can be used for login.
var oidcButton: some View {
Button { context.send(viewAction: .continueWithOIDC) } label: {
Text(ElementL10n.loginContinue)
Text(L10n.actionContinue)
}
.buttonStyle(.elementAction(.xLarge))
.accessibilityIdentifier(A11yIdentifiers.loginScreen.oidc)
@@ -121,7 +121,7 @@ struct LoginScreen: View {
/// Text shown if neither password or OIDC login is supported.
var loginUnavailableText: some View {
Text(ElementL10n.autodiscoverWellKnownError)
Text(L10n.screenLoginErrorUnsupportedAuthentication)
.font(.body)
.multilineTextAlignment(.center)
.foregroundColor(.element.primaryContent)
@@ -156,9 +156,13 @@ struct Login_Previews: PreviewProvider {
static var previews: some View {
screen(for: LoginViewModel(homeserver: .mockMatrixDotOrg))
.previewDisplayName("matrix.org")
screen(for: credentialsViewModel)
screen(for: LoginViewModel(homeserver: .mockBasicServer))
.previewDisplayName("Credentials Entered")
screen(for: LoginViewModel(homeserver: .mockOIDC))
.previewDisplayName("OIDC")
screen(for: LoginViewModel(homeserver: .mockUnsupported))
.previewDisplayName("Unsupported")
}
static func screen(for viewModel: LoginViewModel) -> some View {
@@ -30,7 +30,7 @@ struct LoginServerInfoSection: View {
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text(ElementL10n.ftueAuthSignInChooseServerHeader)
Text(L10n.screenLoginServerHeader)
.font(.element.footnote)
.foregroundColor(.element.primaryContent)
.padding(.horizontal, 16)
@@ -34,7 +34,7 @@ enum MockServerSelectionScreenState: CaseIterable {
case .invalidAddress:
let viewModel = ServerSelectionViewModel(homeserverAddress: "thisisbad",
isModallyPresented: true)
viewModel.displayError(.footerMessage(ElementL10n.unknownError))
viewModel.displayError(.footerMessage(L10n.errorUnknown))
return viewModel
case .nonModal:
return ServerSelectionViewModel(homeserverAddress: "https://matrix.org",
@@ -69,7 +69,7 @@ final class ServerSelectionCoordinator: CoordinatorProtocol {
// MARK: - Private
private func startLoading(label: String = ElementL10n.loading) {
private func startLoading(label: String = L10n.commonLoading) {
userIndicatorController.submitIndicator(UserIndicator(type: .modal,
title: label,
persistent: true))
@@ -101,11 +101,11 @@ final class ServerSelectionCoordinator: CoordinatorProtocol {
private func handleError(_ error: AuthenticationServiceError) {
switch error {
case .invalidServer, .invalidHomeserverAddress:
viewModel.displayError(.footerMessage(ElementL10n.loginErrorHomeserverNotFound))
viewModel.displayError(.footerMessage(L10n.screenChangeServerErrorInvalidHomeserver))
case .slidingSyncNotAvailable:
viewModel.displayError(.slidingSyncAlert)
default:
viewModel.displayError(.footerMessage(ElementL10n.unknownError))
viewModel.displayError(.footerMessage(L10n.errorUnknown))
}
}
}
@@ -27,9 +27,9 @@ struct ServerSelectionViewState: BindableState {
/// The message to be shown in the text field footer when no error has occurred.
private let regularFooterMessage = {
let linkPlaceholder = "{link}"
var message = AttributedString(ElementL10n.serverSelectionServerFooter(linkPlaceholder))
var message = AttributedString(L10n.screenChangeServerFormNotice(linkPlaceholder))
message.replace(linkPlaceholder,
with: ElementL10n.actionLearnMore,
with: L10n.actionLearnMore,
asLinkTo: ServiceLocator.shared.settings.slidingSyncLearnMoreURL)
return message
}()
@@ -48,7 +48,7 @@ struct ServerSelectionViewState: BindableState {
/// The title shown on the confirm button.
var buttonTitle: String {
isModallyPresented ? ElementL10n.continue : ElementL10n.actionNext
isModallyPresented ? L10n.actionContinue : L10n.actionNext
}
/// The text field is showing an error.
@@ -48,10 +48,10 @@ class ServerSelectionViewModel: ServerSelectionViewModelType, ServerSelectionVie
case .slidingSyncAlert:
let openURL = { UIApplication.shared.open(ServiceLocator.shared.settings.slidingSyncLearnMoreURL) }
state.bindings.alertInfo = AlertInfo(id: .slidingSyncAlert,
title: ElementL10n.serverSelectionSlidingSyncAlertTitle,
message: ElementL10n.serverSelectionSlidingSyncAlertMessage,
primaryButton: .init(title: ElementL10n.actionLearnMore, role: .cancel, action: openURL),
secondaryButton: .init(title: ElementL10n.actionCancel, action: nil))
title: L10n.commonServerNotSupported,
message: L10n.screenChangeServerErrorNoSlidingSyncMessage,
primaryButton: .init(title: L10n.actionLearnMore, role: .cancel, action: openURL),
secondaryButton: .init(title: L10n.actionCancel, action: nil))
}
}
@@ -43,12 +43,12 @@ struct ServerSelectionScreen: View {
AuthenticationIconImage(image: Image(asset: Asset.Images.serverSelectionIcon), insets: 19)
.padding(.bottom, 8)
Text(ElementL10n.ftueAuthChooseServerTitle)
Text(L10n.commonSelectYourServer)
.font(.element.title2Bold)
.multilineTextAlignment(.center)
.foregroundColor(.element.primaryContent)
Text(ElementL10n.ftueAuthChooseServerSignInSubtitle)
Text(L10n.screenChangeServerSubtitle)
.font(.element.subheadline)
.multilineTextAlignment(.center)
.foregroundColor(.element.tertiaryContent)
@@ -59,8 +59,8 @@ struct ServerSelectionScreen: View {
/// The text field and confirm button where the user enters a server URL.
var serverForm: some View {
VStack(alignment: .leading, spacing: 24) {
TextField(ElementL10n.ftueAuthChooseServerEntryHint, text: $context.homeserverAddress)
.textFieldStyle(.elementInput(labelText: Text(ElementL10n.hsUrl),
TextField(L10n.commonServerUrl, text: $context.homeserverAddress)
.textFieldStyle(.elementInput(labelText: Text(L10n.screenChangeServerFormHeader),
footerText: Text(context.viewState.footerMessage),
isError: context.viewState.isShowingFooterError,
accessibilityIdentifier: A11yIdentifiers.changeServerScreen.server))
@@ -85,7 +85,7 @@ struct ServerSelectionScreen: View {
ToolbarItem(placement: .cancellationAction) {
if context.viewState.isModallyPresented {
Button { context.send(viewAction: .dismiss) } label: {
Text(ElementL10n.actionCancel)
Text(L10n.actionCancel)
}
.accessibilityIdentifier(A11yIdentifiers.changeServerScreen.dismiss)
}
@@ -101,7 +101,7 @@ final class SoftLogoutCoordinator: CoordinatorProtocol {
@MainActor private func startLoading() {
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
title: ElementL10n.loading,
title: L10n.commonLoading,
persistent: true))
}
@@ -124,7 +124,7 @@ final class SoftLogoutCoordinator: CoordinatorProtocol {
Task {
switch await authenticationService.login(username: username,
password: password,
initialDeviceName: UIDevice.current.initialDisplayName,
initialDeviceName: UIDevice.current.initialDeviceName,
deviceId: parameters.credentials.deviceId) {
case .success(let userSession):
callback?(.signedIn(userSession))
@@ -160,11 +160,11 @@ final class SoftLogoutCoordinator: CoordinatorProtocol {
private func handleError(_ error: AuthenticationServiceError) {
switch error {
case .invalidCredentials:
viewModel.displayError(.alert(ElementL10n.authInvalidLoginParam))
viewModel.displayError(.alert(L10n.screenLoginErrorInvalidCredentials))
case .accountDeactivated:
viewModel.displayError(.alert(ElementL10n.authInvalidLoginDeactivatedAccount))
viewModel.displayError(.alert(L10n.screenLoginErrorDeactivatedAccount))
default:
viewModel.displayError(.alert(ElementL10n.unknownError))
viewModel.displayError(.alert(L10n.errorUnknown))
}
}
}
@@ -50,7 +50,7 @@ class SoftLogoutViewModel: SoftLogoutViewModelType, SoftLogoutViewModelProtocol
switch type {
case .alert(let message):
state.bindings.alertInfo = AlertInfo(id: type,
title: ElementL10n.dialogTitleError,
title: L10n.commonError,
message: message)
case .unknown:
state.bindings.alertInfo = AlertInfo(id: type)
@@ -54,20 +54,20 @@ struct SoftLogoutScreen: View {
/// The title, message and icon at the top of the screen.
var header: some View {
VStack(alignment: .leading, spacing: 16) {
Text(ElementL10n.softLogoutSigninTitle)
Text(UntranslatedL10n.softLogoutSigninTitle)
.font(.element.title2Bold)
.multilineTextAlignment(.leading)
.foregroundColor(.element.primaryContent)
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.title)
Text(ElementL10n.softLogoutSigninNotice(context.viewState.credentials.homeserverName, context.viewState.credentials.userDisplayName, context.viewState.credentials.userId))
Text(UntranslatedL10n.softLogoutSigninNotice(context.viewState.credentials.homeserverName, context.viewState.credentials.userDisplayName, context.viewState.credentials.userId))
.font(.element.body)
.multilineTextAlignment(.leading)
.foregroundColor(.element.primaryContent)
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.message)
if context.viewState.showRecoverEncryptionKeysMessage {
Text(ElementL10n.softLogoutSigninE2eWarningNotice)
Text(UntranslatedL10n.softLogoutSigninE2eWarningNotice)
.font(.element.body)
.multilineTextAlignment(.leading)
.foregroundColor(.element.primaryContent)
@@ -78,7 +78,7 @@ struct SoftLogoutScreen: View {
/// The form with text fields for username and password, along with a submit button.
var loginForm: some View {
VStack(spacing: 14) {
SecureField(ElementL10n.loginSignupPasswordHint, text: $context.password)
SecureField(L10n.commonPassword, text: $context.password)
.focused($isPasswordFocused)
.textFieldStyle(.elementInput())
.textContentType(.password)
@@ -87,7 +87,7 @@ struct SoftLogoutScreen: View {
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.password)
Button { context.send(viewAction: .forgotPassword) } label: {
Text(ElementL10n.ftueAuthForgotPassword)
Text(UntranslatedL10n.softLogoutForgotPassword)
.font(.element.body)
}
.frame(maxWidth: .infinity, alignment: .trailing)
@@ -95,7 +95,7 @@ struct SoftLogoutScreen: View {
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.forgotPassword)
Button(action: submit) {
Text(ElementL10n.loginSignupSubmit)
Text(L10n.actionNext)
}
.buttonStyle(.elementAction(.xLarge))
.disabled(!context.viewState.canSubmit)
@@ -106,14 +106,14 @@ struct SoftLogoutScreen: View {
/// The OIDC button that can be used for login.
var oidcButton: some View {
Button { context.send(viewAction: .continueWithOIDC) } label: {
Text(ElementL10n.loginContinue)
Text(L10n.actionContinue)
}
.buttonStyle(.elementAction(.xLarge))
}
/// Text shown if neither password or OIDC login is supported.
var loginUnavailableText: some View {
Text(ElementL10n.autodiscoverWellKnownError)
Text(L10n.screenLoginErrorUnsupportedAuthentication)
.font(.body)
.multilineTextAlignment(.center)
.foregroundColor(.element.primaryContent)
@@ -123,13 +123,13 @@ struct SoftLogoutScreen: View {
/// The text field and submit button where the user enters an email address.
var clearDataForm: some View {
VStack(alignment: .leading, spacing: 12) {
Text(ElementL10n.softLogoutClearDataTitle)
Text(UntranslatedL10n.softLogoutClearDataTitle)
.font(.element.title2Bold)
.multilineTextAlignment(.leading)
.foregroundColor(.element.primaryContent)
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.clearDataTitle)
Text(ElementL10n.softLogoutClearDataNotice)
Text(UntranslatedL10n.softLogoutClearDataNotice)
.font(.element.body)
.multilineTextAlignment(.leading)
.foregroundColor(.element.primaryContent)
@@ -137,17 +137,17 @@ struct SoftLogoutScreen: View {
.padding(.bottom, 12)
Button(action: clearData) {
Text(ElementL10n.softLogoutClearDataSubmit)
Text(UntranslatedL10n.softLogoutClearDataSubmit)
}
.buttonStyle(.elementAction(.xLarge, color: .element.alert))
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.clearData)
.alert(ElementL10n.softLogoutClearDataDialogTitle,
.alert(UntranslatedL10n.softLogoutClearDataDialogTitle,
isPresented: $showingClearDataConfirmation) {
Button(ElementL10n.actionSignOut,
Button(L10n.screenSignoutConfirmationDialogSubmit,
role: .destructive,
action: clearData)
} message: {
Text(ElementL10n.softLogoutClearDataDialogContent)
Text(UntranslatedL10n.softLogoutClearDataDialogContent)
}
}
}
@@ -57,7 +57,7 @@ final class BugReportCoordinator: CoordinatorProtocol {
case .cancel:
self.completion?(.cancel)
case let .submitStarted(progressTracker):
self.startLoading(label: ElementL10n.sending, progressPublisher: progressTracker)
self.startLoading(label: L10n.commonSending, progressPublisher: progressTracker)
case .submitFinished:
self.stopLoading()
self.completion?(.finish)
@@ -80,7 +80,7 @@ final class BugReportCoordinator: CoordinatorProtocol {
static let loadingIndicatorIdentifier = "BugReportLoading"
private func startLoading(label: String = ElementL10n.loading, progressPublisher: ProgressPublisher) {
private func startLoading(label: String = L10n.commonLoading, progressPublisher: ProgressPublisher) {
parameters.userIndicatorController?.submitIndicator(
UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
@@ -33,7 +33,7 @@ struct BugReportScreen: View {
}
.scrollDismissesKeyboard(.immediately)
.compoundForm()
.navigationTitle(ElementL10n.bugReportScreenTitle)
.navigationTitle(L10n.commonReportABug)
.navigationBarTitleDisplayMode(.inline)
.toolbar { toolbar }
.interactiveDismissDisabled()
@@ -51,15 +51,15 @@ struct BugReportScreen: View {
private var textFieldSection: some View {
Section {
TextField(ElementL10n.bugReportScreenEditorPlaceholder,
TextField(L10n.screenBugReportEditorPlaceholder,
text: $context.reportText,
prompt: Text(ElementL10n.bugReportScreenEditorPlaceholder).compoundFormTextFieldPlaceholder(),
prompt: Text(L10n.screenBugReportEditorPlaceholder).compoundFormTextFieldPlaceholder(),
axis: .vertical)
.lineLimit(4, reservesSpace: true)
.textFieldStyle(.compoundForm)
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.report)
} footer: {
Text(ElementL10n.bugReportScreenDescription)
Text(L10n.screenBugReportEditorDescription)
.compoundFormSectionFooter()
}
.compoundFormSection()
@@ -67,11 +67,11 @@ struct BugReportScreen: View {
private var sendLogsSection: some View {
Section {
Toggle(ElementL10n.bugReportScreenIncludeLogs, isOn: $context.sendingLogsEnabled)
Toggle(L10n.screenBugReportIncludeLogs, isOn: $context.sendingLogsEnabled)
.toggleStyle(.compoundForm)
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.sendLogs)
} footer: {
Text(ElementL10n.bugReportScreenLogsDescription)
Text(L10n.screenBugReportLogsDescription)
.compoundFormSectionFooter()
}
.compoundFormSection()
@@ -83,7 +83,7 @@ struct BugReportScreen: View {
PhotosPicker(selection: $selectedScreenshot,
matching: .screenshots,
photoLibrary: .shared()) {
Label(context.viewState.screenshot == nil ? ElementL10n.bugReportScreenAttachScreenshot : ElementL10n.bugReportScreenEditScreenshot, systemImage: "camera")
Label(context.viewState.screenshot == nil ? L10n.screenBugReportAttachScreenshot : L10n.screenBugReportEditScreenshot, systemImage: "camera")
}
.buttonStyle(.compoundForm())
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.attachScreenshot)
@@ -113,14 +113,14 @@ struct BugReportScreen: View {
private var toolbar: some ToolbarContent {
if context.viewState.isModallyPresented {
ToolbarItem(placement: .cancellationAction) {
Button(ElementL10n.actionCancel) {
Button(L10n.actionCancel) {
context.send(viewAction: .cancel)
}
}
}
ToolbarItem(placement: .confirmationAction) {
Button(ElementL10n.actionSend) {
Button(L10n.actionSend) {
context.send(viewAction: .submit)
}
.disabled(context.reportText.count < 5)
@@ -53,7 +53,7 @@ struct DeveloperOptionsScreenScreen: View {
.overlay(effectsView)
.scrollContentBackground(.hidden)
.background(Color.element.formBackground.ignoresSafeArea())
.navigationTitle(ElementL10n.settingsDeveloperOptions)
.navigationTitle(L10n.commonDeveloperOptions)
.navigationBarTitleDisplayMode(.inline)
}
@@ -38,21 +38,21 @@ struct EmojiPickerEmojiCategoryViewData: Identifiable {
var name: String {
switch id {
case "people":
return ElementL10n.emojiPickerPeopleCategory
return L10n.emojiPickerCategoryPeople
case "nature":
return ElementL10n.emojiPickerNatureCategory
return L10n.emojiPickerCategoryNature
case "foods":
return ElementL10n.emojiPickerFoodsCategory
return L10n.emojiPickerCategoryFoods
case "activity":
return ElementL10n.emojiPickerActivityCategory
return L10n.emojiPickerCategoryActivity
case "places":
return ElementL10n.emojiPickerPlacesCategory
return L10n.emojiPickerCategoryPlaces
case "objects":
return ElementL10n.emojiPickerObjectsCategory
return L10n.emojiPickerCategoryObjects
case "symbols":
return ElementL10n.emojiPickerSymbolsCategory
return L10n.emojiPickerCategorySymbols
case "flags":
return ElementL10n.emojiPickerFlagsCategory
return L10n.emojiPickerCategoryFlags
default:
MXLog.failure("Missing translation for emoji category with id \(id)")
return ""
@@ -41,7 +41,7 @@ struct EmojiPickerScreen: View {
}
.padding(.horizontal, 6)
}
.navigationTitle(ElementL10n.reactions)
.navigationTitle(L10n.commonReactions)
.navigationBarTitleDisplayMode(.inline)
.toolbar { toolbar }
.searchable(text: $searchString)
@@ -55,7 +55,7 @@ struct EmojiPickerScreen: View {
var toolbar: some ToolbarContent {
ToolbarItem(placement: .cancellationAction) {
Button { context.send(viewAction: .dismiss) } label: {
Text(ElementL10n.actionCancel)
Text(L10n.actionCancel)
}
}
}
@@ -161,9 +161,9 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
func presentCrashedLastRunAlert() {
state.bindings.alertInfo = AlertInfo(id: UUID(),
title: ElementL10n.sendBugReportAppCrashed,
primaryButton: .init(title: ElementL10n.iosNo, action: nil),
secondaryButton: .init(title: ElementL10n.iosYes) { [weak self] in
title: L10n.crashDetectionDialogContent(InfoPlistReader.main.bundleDisplayName),
primaryButton: .init(title: L10n.actionNo, action: nil),
secondaryButton: .init(title: L10n.actionYes) { [weak self] in
self?.callback?(.presentFeedbackScreen)
})
}
@@ -98,7 +98,7 @@ struct HomeScreen: View {
.animation(.elementDefault, value: context.viewState.showSessionVerificationBanner)
.animation(.elementDefault, value: context.viewState.roomListMode)
.alert(item: $context.alertInfo) { $0.alert }
.navigationTitle(ElementL10n.allChats)
.navigationTitle(L10n.screenRoomlistMainSpaceTitle)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
userMenuButton
@@ -118,22 +118,22 @@ struct HomeScreen: View {
Menu {
Section {
Button(action: settings) {
Label(ElementL10n.settings, systemImage: "gearshape")
Label(L10n.commonSettings, systemImage: "gearshape")
}
}
Section {
Button(action: inviteFriends) {
Label(ElementL10n.actionInvite, systemImage: "square.and.arrow.up")
Label(L10n.actionInvite, systemImage: "square.and.arrow.up")
}
Button(action: feedback) {
Label(ElementL10n.bugReportScreenTitle, systemImage: "questionmark.circle")
Label(L10n.actionReportBug, systemImage: "questionmark.circle")
}
}
Section {
Button(role: .destructive) {
showingLogoutConfirmation = true
} label: {
Label(ElementL10n.actionSignOut, systemImage: "rectangle.portrait.and.arrow.right")
Label(L10n.screenSignoutPreferenceItem, systemImage: "rectangle.portrait.and.arrow.right")
}
}
} label: {
@@ -144,15 +144,15 @@ struct HomeScreen: View {
imageProvider: context.imageProvider)
.accessibilityIdentifier(A11yIdentifiers.homeScreen.userAvatar)
}
.alert(ElementL10n.actionSignOut,
.alert(L10n.screenSignoutConfirmationDialogTitle,
isPresented: $showingLogoutConfirmation) {
Button(ElementL10n.actionSignOut,
Button(L10n.screenSignoutConfirmationDialogSubmit,
role: .destructive,
action: signOut)
} message: {
Text(ElementL10n.actionSignOutConfirmationSimple)
Text(L10n.screenSignoutConfirmationDialogContent)
}
.accessibilityLabel(ElementL10n.a11yAllChatsUserAvatarMenu)
.accessibilityLabel(L10n.a11yUserMenu)
}
private var newRoomButton: some View {
@@ -165,7 +165,7 @@ struct HomeScreen: View {
VStack(alignment: .leading, spacing: 16) {
VStack(alignment: .leading, spacing: 4) {
HStack(spacing: 16) {
Text(ElementL10n.sessionVerificationBannerTitle)
Text(L10n.sessionVerificationBannerTitle)
.font(.element.headline)
.foregroundColor(.element.systemPrimaryLabel)
@@ -179,12 +179,12 @@ struct HomeScreen: View {
.frame(width: 12, height: 12)
}
}
Text(ElementL10n.sessionVerificationBannerMessage)
Text(L10n.sessionVerificationBannerMessage)
.font(.element.subheadline)
.foregroundColor(.element.secondaryContent)
}
Button(ElementL10n.continue) {
Button(L10n.actionContinue) {
context.send(viewAction: .verifySession)
}
.frame(maxWidth: .infinity)
@@ -138,7 +138,7 @@ struct HomeScreenRoomCell: View {
.lastMessageFormatting()
.redacted(reason: .placeholder)
case .unknown:
Text(ElementL10n.message)
Text(L10n.commonMessage)
.lastMessageFormatting()
}
}
@@ -40,8 +40,8 @@ struct OnboardingViewState: BindableState {
init() {
content = [
OnboardingPageContent(title: ElementL10n.ftueAuthCarouselWelcomeTitle.tinting(".", color: .element.accent),
message: ElementL10n.ftueAuthCarouselWelcomeBody(InfoPlistReader.main.bundleDisplayName),
OnboardingPageContent(title: L10n.screenOnboardingWelcomeTitle.tinting(".", color: .element.accent),
message: L10n.screenOnboardingWelcomeSubtitle(InfoPlistReader.main.bundleDisplayName),
image: Asset.Images.onboardingAppLogo)
]
bindings = OnboardingBindings()
@@ -91,7 +91,7 @@ struct OnboardingScreen: View {
var buttons: some View {
VStack(spacing: 12) {
Button { context.send(viewAction: .login) } label: {
Text(ElementL10n.loginContinue)
Text(L10n.actionContinue)
}
.buttonStyle(.elementAction(.xLarge))
.accessibilityIdentifier(A11yIdentifiers.onboardingScreen.signIn)
@@ -27,7 +27,7 @@ class InviteFriendsCoordinator: CoordinatorProtocol {
guard let permalink = try? PermalinkBuilder.permalinkTo(userIdentifier: userId).absoluteString else {
return AnyView(EmptyView())
}
let shareText = ElementL10n.inviteFriendsText(InfoPlistReader.main.bundleDisplayName, permalink)
let shareText = L10n.inviteFriendsText(InfoPlistReader.main.bundleDisplayName, permalink)
return AnyView(UIActivityViewControllerWrapper(activityItems: [shareText])
.presentationDetents([.medium])
@@ -75,7 +75,7 @@ final class ReportContentCoordinator: CoordinatorProtocol {
parameters.userIndicatorController?.submitIndicator(
UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
title: ElementL10n.sending,
title: L10n.commonSending,
persistent: true)
)
}
@@ -33,7 +33,7 @@ struct ReportContentScreen: View {
}
.scrollDismissesKeyboard(.immediately)
.background(Color.element.formBackground.ignoresSafeArea())
.navigationTitle(ElementL10n.reportContent)
.navigationTitle(L10n.actionReportContent)
.navigationBarTitleDisplayMode(.inline)
.toolbar { toolbar }
.interactiveDismissDisabled()
@@ -48,25 +48,25 @@ struct ReportContentScreen: View {
}
private var infoText: some View {
Text(ElementL10n.reportContentInfo)
Text(L10n.reportContentExplanation)
.font(.element.body)
.foregroundColor(Color.element.primaryContent)
}
private var reasonTextEditor: some View {
FormTextEditor(text: $context.reasonText, placeholder: ElementL10n.reportContentCustomHint)
FormTextEditor(text: $context.reasonText, placeholder: L10n.reportContentHint)
}
@ToolbarContentBuilder
private var toolbar: some ToolbarContent {
ToolbarItem(placement: .cancellationAction) {
Button(ElementL10n.actionCancel) {
Button(L10n.actionCancel) {
context.send(viewAction: .cancel)
}
}
ToolbarItem(placement: .confirmationAction) {
Button(ElementL10n.actionSend) {
Button(L10n.actionSend) {
context.send(viewAction: .submit)
}
}
@@ -61,15 +61,15 @@ struct LeaveRoomAlertItem: AlertItem {
}
let state: RoomState
let title = ElementL10n.roomProfileSectionMoreLeave
let confirmationTitle = ElementL10n.actionLeave
let cancelTitle = ElementL10n.actionCancel
let title = L10n.actionLeaveRoom
let confirmationTitle = L10n.actionLeave
let cancelTitle = L10n.actionCancel
var subtitle: String {
switch state {
case .empty: return ElementL10n.roomDetailsLeaveEmptyRoomAlertSubtitle
case .private: return ElementL10n.roomDetailsLeavePrivateRoomAlertSubtitle
case .public: return ElementL10n.roomDetailsLeaveRoomAlertSubtitle
case .empty: return L10n.leaveRoomAlertEmptySubtitle
case .private: return L10n.leaveRoomAlertPrivateSubtitle
case .public: return L10n.leaveRoomAlertSubtitle
}
}
}
@@ -49,7 +49,7 @@ class RoomDetailsViewModel: RoomDetailsViewModelType, RoomDetailsViewModelProtoc
self.members = members
case .failure(let error):
MXLog.error("Failed retrieving room members: \(error)")
state.bindings.alertInfo = AlertInfo(id: .alert(ElementL10n.unknownError))
state.bindings.alertInfo = AlertInfo(id: .alert(L10n.errorUnknown))
}
}
}
@@ -80,14 +80,14 @@ class RoomDetailsViewModel: RoomDetailsViewModelType, RoomDetailsViewModelProtoc
private func copyRoomLink() {
if let roomLink = state.permalink {
UIPasteboard.general.url = roomLink
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: ElementL10n.linkCopiedToClipboard))
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: L10n.commonLinkCopiedToClipboard))
} else {
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: ElementL10n.unknownError))
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: L10n.errorUnknown))
}
}
private func leaveRoom() async {
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(id: Self.leaveRoomLoadingID, type: .modal, title: ElementL10n.loading, persistent: true))
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(id: Self.leaveRoomLoadingID, type: .modal, title: L10n.commonLoading, persistent: true))
let result = await roomProxy.leaveRoom()
ServiceLocator.shared.userIndicatorController.retractIndicatorWithId(Self.leaveRoomLoadingID)
switch result {
@@ -69,12 +69,12 @@ struct RoomDetailsScreen: View {
Button { context.send(viewAction: .copyRoomLink) } label: {
Image(systemName: "link")
}
.buttonStyle(FormActionButtonStyle(title: ElementL10n.actionCopyLink))
.buttonStyle(FormActionButtonStyle(title: L10n.actionCopyLink))
ShareLink(item: permalink) {
Image(systemName: "square.and.arrow.up")
}
.buttonStyle(FormActionButtonStyle(title: ElementL10n.inviteUsersToRoomActionInvite.capitalized))
.buttonStyle(FormActionButtonStyle(title: L10n.actionInvite))
}
.padding(.top, 32)
}
@@ -91,7 +91,7 @@ struct RoomDetailsScreen: View {
.foregroundColor(.element.secondaryContent)
.font(.element.footnote)
} header: {
Text(ElementL10n.roomSettingsTopic)
Text(L10n.commonTopic)
.formSectionHeader()
}
.formSectionStyle()
@@ -112,7 +112,7 @@ struct RoomDetailsScreen: View {
.font(.element.body)
}
} label: {
Label(ElementL10n.bottomActionPeople, systemImage: "person")
Label(L10n.commonPeople, systemImage: "person")
}
}
.buttonStyle(FormButtonStyle(accessory: context.viewState.isLoadingMembers ? nil : .navigationLink))
@@ -120,7 +120,7 @@ struct RoomDetailsScreen: View {
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.people)
.disabled(context.viewState.isLoadingMembers)
} header: {
Text(ElementL10n.roomDetailsAboutSectionTitle)
Text(L10n.commonAbout)
.formSectionHeader()
}
.formSectionStyle()
@@ -131,8 +131,8 @@ struct RoomDetailsScreen: View {
HStack(alignment: .top) {
Label {
VStack(alignment: .leading, spacing: 2) {
Text(ElementL10n.encryptionEnabled)
Text(ElementL10n.encryptionEnabledTileDescription)
Text(L10n.screenRoomDetailsEncryptionEnabledTitle)
Text(L10n.screenRoomDetailsEncryptionEnabledSubtitle)
.foregroundColor(.element.secondaryContent)
.font(.element.footnote)
}
@@ -147,7 +147,7 @@ struct RoomDetailsScreen: View {
.foregroundColor(.element.quaternaryContent)
}
} header: {
Text(ElementL10n.roomProfileSectionSecurity)
Text(L10n.commonSecurity)
.formSectionHeader()
}
.formSectionStyle()
@@ -158,7 +158,7 @@ struct RoomDetailsScreen: View {
Button(role: .destructive) {
context.send(viewAction: .processTapLeave)
} label: {
Label(ElementL10n.roomProfileSectionMoreLeave, systemImage: "door.right.hand.open")
Label(L10n.actionLeaveRoom, systemImage: "door.right.hand.open")
}
.buttonStyle(FormButtonStyle(accessory: nil))
}
@@ -41,26 +41,26 @@ struct IgnoreUserAlertItem: AlertItem {
}
let action: Action
let cancelTitle = ElementL10n.actionCancel
let cancelTitle = L10n.actionCancel
var title: String {
switch action {
case .ignore: return ElementL10n.roomMemberDetailsBlockUser
case .unignore: return ElementL10n.roomMemberDetailsUnblockUser
case .ignore: return L10n.screenRoomMemberDetailsBlockUser
case .unignore: return L10n.screenRoomMemberDetailsUnblockUser
}
}
var confirmationTitle: String {
switch action {
case .ignore: return ElementL10n.roomMemberDetailsBlockAlertAction
case .unignore: return ElementL10n.roomMemberDetailsUnblockAlertAction
case .ignore: return L10n.screenRoomMemberDetailsBlockAlertAction
case .unignore: return L10n.screenRoomMemberDetailsUnblockAlertAction
}
}
var description: String {
switch action {
case .ignore: return ElementL10n.roomMemberDetailsBlockAlertDescription
case .unignore: return ElementL10n.roomMemberDetailsUnblockAlertDescription
case .ignore: return L10n.screenRoomMemberDetailsBlockAlertDescription
case .unignore: return L10n.screenRoomMemberDetailsUnblockAlertDescription
}
}
@@ -57,9 +57,9 @@ class RoomMemberDetailsViewModel: RoomMemberDetailsViewModelType, RoomMemberDeta
private func copyUserLink() {
if let userLink = state.permalink {
UIPasteboard.general.url = userLink
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: ElementL10n.linkCopiedToClipboard))
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: L10n.commonLinkCopiedToClipboard))
} else {
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: ElementL10n.unknownError))
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: L10n.errorUnknown))
}
}
@@ -59,12 +59,12 @@ struct RoomMemberDetailsScreen: View {
Button { context.send(viewAction: .copyUserLink) } label: {
Image(systemName: "link")
}
.buttonStyle(FormActionButtonStyle(title: ElementL10n.actionCopyLink))
.buttonStyle(FormActionButtonStyle(title: L10n.actionCopyLink))
ShareLink(item: permalink) {
Image(systemName: "square.and.arrow.up")
}
.buttonStyle(FormActionButtonStyle(title: ElementL10n.actionShareLink))
.buttonStyle(FormActionButtonStyle(title: L10n.actionShareLink))
}
.padding(.top, 32)
}
@@ -79,14 +79,14 @@ struct RoomMemberDetailsScreen: View {
Button {
context.send(viewAction: .showUnblockAlert)
} label: {
Label(ElementL10n.roomMemberDetailsUnblockUser, systemImage: "slash.circle")
Label(L10n.screenRoomMemberDetailsUnblockUser, systemImage: "slash.circle")
}
.buttonStyle(FormButtonStyle(accessory: nil))
} else {
Button(role: .destructive) {
context.send(viewAction: .showBlockAlert)
} label: {
Label(ElementL10n.roomMemberDetailsBlockUser, systemImage: "slash.circle")
Label(L10n.screenRoomMemberDetailsBlockUser, systemImage: "slash.circle")
}
.buttonStyle(FormButtonStyle(accessory: nil))
}
@@ -30,7 +30,7 @@ struct RoomMembersListScreen: View {
.id(member.id)
}
} header: {
Text(ElementL10n.roomTitleMembers(context.viewState.members.count))
Text(L10n.commonMemberCount(context.viewState.members.count))
.foregroundColor(.element.secondaryContent)
.font(.element.body)
.padding(.vertical, 12)
@@ -41,7 +41,7 @@ struct RoomMembersListScreen: View {
.searchable(text: $context.searchQuery, placement: .navigationBarDrawer(displayMode: .always))
.searchableStyle(.list)
.background(Color.element.background.ignoresSafeArea())
.navigationTitle(ElementL10n.bottomActionPeople)
.navigationTitle(L10n.commonPeople)
.alert(item: $context.alertInfo) { $0.alert }
}
}
@@ -141,7 +141,7 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
switch completion {
case .cancel: break
case .finish:
self?.showSuccess(label: ElementL10n.reportContentSubmitted)
self?.showSuccess(label: L10n.commonReportSubmitted)
}
}
navigationCoordinator.setRootCoordinator(coordinator)
@@ -119,7 +119,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
private func paginateBackwards() async {
switch await timelineController.paginateBackwards(requestSize: Constants.backPaginationEventLimit, untilNumberOfItems: Constants.backPaginationPageSize) {
case .failure:
displayError(.toast(ElementL10n.roomTimelineBackpaginationFailure))
displayError(.toast(L10n.errorFailedLoadingMessages))
default:
break
}
@@ -224,7 +224,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
switch type {
case .alert(let message):
state.bindings.alertInfo = AlertInfo(id: type,
title: ElementL10n.dialogTitleError,
title: L10n.commonError,
message: message)
case .toast(let message):
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(id: Constants.toastErrorID,
@@ -298,7 +298,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
let permalink = try PermalinkBuilder.permalinkTo(eventIdentifier: item.id, roomIdentifier: timelineController.roomID)
UIPasteboard.general.url = permalink
} catch {
displayError(.alert(ElementL10n.roomTimelinePermalinkCreationFailure))
displayError(.alert(L10n.errorFailedCreatingThePermalink))
}
case .redact:
Task {
@@ -34,7 +34,7 @@ struct MessageComposer: View {
VStack(alignment: .leading, spacing: -6) {
header
HStack(alignment: .bottom) {
MessageComposerTextField(placeholder: ElementL10n.roomMessagePlaceholder,
MessageComposerTextField(placeholder: L10n.richTextEditorComposerPlaceholder,
text: $text,
focused: $focused,
isMultiline: $isMultiline,
@@ -94,14 +94,14 @@ struct MessageComposer: View {
Image(systemName: "checkmark")
.opacity(type.isEdit ? 1 : 0)
.fontWeight(.medium)
.accessibilityLabel(ElementL10n.actionConfirm)
.accessibilityLabel(L10n.actionConfirm)
.accessibilityHidden(!type.isEdit)
Image(asset: Asset.Images.timelineComposerSendMessage)
.resizable()
.frame(width: sendButtonIconSize, height: sendButtonIconSize)
.padding(EdgeInsets(top: 7, leading: 8, bottom: 7, trailing: 6))
.opacity(type.isEdit ? 0 : 1)
.accessibilityLabel(ElementL10n.actionSend)
.accessibilityLabel(L10n.actionSend)
.accessibilityHidden(type.isEdit)
}
}
@@ -122,7 +122,7 @@ private struct MessageComposerReplyHeader: View {
var body: some View {
HStack(alignment: .center) {
Label(ElementL10n.roomTimelineReplyingTo(displayName), systemImage: "arrowshape.turn.up.left")
Label(L10n.commonReplyingTo(displayName), systemImage: "arrowshape.turn.up.left")
.labelStyle(MessageComposerHeaderLabelStyle())
Spacer()
Button(action: action) {
@@ -140,7 +140,7 @@ private struct MessageComposerEditHeader: View {
var body: some View {
HStack(alignment: .center) {
Label(ElementL10n.roomTimelineEditing, systemImage: "pencil.line")
Label(L10n.commonEditing, systemImage: "pencil.line")
.labelStyle(MessageComposerHeaderLabelStyle())
Spacer()
Button(action: action) {
@@ -111,7 +111,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
content()
if timelineItem.properties.isEdited {
Text(ElementL10n.editedSuffix)
Text(L10n.commonEditedSuffix)
.font(.element.caption2)
.foregroundColor(.element.tertiaryContent)
}
@@ -66,7 +66,7 @@ struct TimelineItemPlainStylerView<Content: View>: View {
private var supplementaryViews: some View {
VStack {
if timelineItem.properties.isEdited {
Text(ElementL10n.editedSuffix)
Text(L10n.commonEditedSuffix)
.font(.element.footnote)
.foregroundColor(.element.tertiaryContent)
}
@@ -28,8 +28,7 @@ struct CollapsibleRoomTimelineView: View {
}
var body: some View {
DisclosureGroup(ElementL10n.roomTimelineStateChanges(timelineItem.items.count),
isExpanded: $isExpanded) {
DisclosureGroup(L10n.roomTimelineStateChanges(timelineItem.items.count), isExpanded: $isExpanded) {
Group {
ForEach(timelineViews) { timelineView in
timelineView.body
@@ -41,7 +41,7 @@ struct ImageRoomTimelineView: View {
.foregroundColor(.element.systemGray6)
.opacity(0.3)
ProgressView(ElementL10n.loading)
ProgressView(L10n.commonLoading)
.frame(maxWidth: .infinity)
}
}
@@ -49,7 +49,7 @@ struct ImageRoomTimelineView: View {
@ViewBuilder
var overlay: some View {
if timelineItem.contentType == .gif {
Text(ElementL10n.roomTimelineImageGif)
Text(L10n.commonGif)
.font(.element.bodyBold)
.foregroundStyle(.primary)
.padding(.horizontal, 10)
@@ -22,7 +22,7 @@ struct ReadMarkerRoomTimelineView: View {
var body: some View {
VStack(alignment: .trailing, spacing: 2) {
Text(ElementL10n.roomTimelineReadMarkerTitle)
Text(L10n.roomTimelineReadMarkerTitle)
.textCase(.uppercase)
.font(.element.caption2Bold)
.foregroundColor(.element.quaternaryContent)
@@ -34,7 +34,7 @@ struct RedactedRoomTimelineView_Previews: PreviewProvider {
static var previews: some View {
VStack(alignment: .leading, spacing: 20.0) {
RedactedRoomTimelineView(timelineItem: itemWith(text: ElementL10n.eventRedacted,
RedactedRoomTimelineView(timelineItem: itemWith(text: L10n.commonMessageRemoved,
timestamp: "Later",
senderId: "Anne"))
}
@@ -40,7 +40,7 @@ struct StickerRoomTimelineView: View {
.foregroundColor(.element.systemGray6)
.opacity(0.3)
ProgressView(ElementL10n.loading)
ProgressView(L10n.commonLoading)
.frame(maxWidth: .infinity)
}
}
@@ -28,9 +28,9 @@ struct TimelineStartRoomTimelineView: View {
}
var title: String {
var text = ElementL10n.thisIsTheBeginningOfRoomNoName
var text = L10n.roomTimelineBeginningOfRoomNoName
if let name = timelineItem.name {
text = ElementL10n.thisIsTheBeginningOfRoom(name)
text = L10n.roomTimelineBeginningOfRoom(name)
}
return text
}
@@ -50,7 +50,7 @@ struct VideoRoomTimelineView: View {
.foregroundColor(.element.systemGray6)
.opacity(0.3)
ProgressView(ElementL10n.loading)
ProgressView(L10n.commonLoading)
.frame(maxWidth: .infinity)
}
}
@@ -74,43 +74,43 @@ public struct TimelineItemContextMenu: View {
switch action {
case .react:
Button { send(action) } label: {
Label(ElementL10n.reactions, systemImage: "face.smiling")
Label(L10n.commonReactions, systemImage: "face.smiling")
}
case .copy:
Button { send(action) } label: {
Label(ElementL10n.actionCopy, systemImage: "doc.on.doc")
Label(L10n.actionCopy, systemImage: "doc.on.doc")
}
case .edit:
Button { send(action) } label: {
Label(ElementL10n.edit, systemImage: "pencil.line")
Label(L10n.actionEdit, systemImage: "pencil.line")
}
case .quote:
Button { send(action) } label: {
Label(ElementL10n.actionQuote, systemImage: "quote.bubble")
Label(L10n.actionQuote, systemImage: "quote.bubble")
}
case .copyPermalink:
Button { send(action) } label: {
Label(ElementL10n.permalink, systemImage: "link")
Label(L10n.commonPermalink, systemImage: "link")
}
case .reply:
Button { send(action) } label: {
Label(ElementL10n.reply, systemImage: "arrowshape.turn.up.left")
Label(L10n.actionReply, systemImage: "arrowshape.turn.up.left")
}
case .redact:
Button(role: .destructive) { send(action) } label: {
Label(ElementL10n.actionRemove, systemImage: "trash")
Label(L10n.actionRemove, systemImage: "trash")
}
case .viewSource:
Button { send(action) } label: {
Label(ElementL10n.viewSource, systemImage: "doc.text.below.ecg")
Label(L10n.actionViewSource, systemImage: "doc.text.below.ecg")
}
case .retryDecryption:
Button { send(action) } label: {
Label(ElementL10n.roomTimelineContextMenuRetryDecryption, systemImage: "arrow.down.message")
Label(L10n.actionRetryDecryption, systemImage: "arrow.down.message")
}
case .report:
Button(role: .destructive) { send(action) } label: {
Label(ElementL10n.reportContent, systemImage: "exclamationmark.bubble")
Label(L10n.actionReportContent, systemImage: "exclamationmark.bubble")
}
}
}
@@ -40,12 +40,12 @@ struct TimelineItemDebugView: View {
.navigationTitle(info.title)
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button(ElementL10n.actionCancel) {
Button(L10n.actionCancel) {
dismiss()
}
}
ToolbarItem(placement: .secondaryAction) {
Button(ElementL10n.actionCopy) {
Button(L10n.actionCopy) {
UIPasteboard.general.string = info.content
}
}
@@ -26,54 +26,54 @@ struct SessionVerificationViewState: BindableState {
var title: String? {
switch verificationState {
case .initial:
return ElementL10n.verificationOpenOtherToVerifyTitle
return L10n.screenSessionVerificationOpenExistingSessionTitle
case .requestingVerification:
return ElementL10n.verificationRequestWaitingAcceptRequestTitle
return L10n.screenSessionVerificationWaitingToAcceptTitle
case .verificationRequestAccepted:
return ElementL10n.verificationCompareEmojisTitle
return L10n.screenSessionVerificationCompareEmojisTitle
case .startingSasVerification:
return nil
case .sasVerificationStarted:
return nil
case .showingChallenge:
return ElementL10n.verificationCompareEmojisTitle
return L10n.screenSessionVerificationCompareEmojisTitle
case .acceptingChallenge:
return ElementL10n.verificationCompareEmojisTitle
return L10n.screenSessionVerificationCompareEmojisTitle
case .decliningChallenge:
return nil
case .verified:
return ElementL10n.verificationConclusionOkSelfNoticeTitle
return L10n.commonVerificationComplete
case .cancelling:
return nil
case .cancelled:
return ElementL10n.verificationCancelled
return L10n.commonVerificationCancelled
}
}
var message: String {
switch verificationState {
case .initial:
return ElementL10n.verificationOpenOtherToVerifyDetail
return L10n.screenSessionVerificationOpenExistingSessionSubtitle
case .requestingVerification:
return ElementL10n.verificationRequestWaitingAcceptRequestDetail
return L10n.screenSessionVerificationWaitingToAcceptSubtitle
case .verificationRequestAccepted:
return ElementL10n.verificationEmojiNotice
return L10n.screenSessionVerificationRequestAcceptedSubtitle
case .startingSasVerification:
return ElementL10n.verificationRequestWaiting
return L10n.commonWaiting
case .sasVerificationStarted:
return ElementL10n.verificationRequestWaiting
return L10n.commonWaiting
case .acceptingChallenge:
return ElementL10n.verificationCompareEmojisDetail
return L10n.screenSessionVerificationCompareEmojisSubtitle
case .decliningChallenge:
return ElementL10n.verificationRequestWaiting
return L10n.commonWaiting
case .cancelling:
return ElementL10n.verificationRequestWaiting
return L10n.commonWaiting
case .showingChallenge:
return ElementL10n.verificationCompareEmojisDetail
return L10n.screenSessionVerificationCompareEmojisSubtitle
case .verified:
return ElementL10n.verificationConclusionOkSelfNotice
return L10n.screenSessionVerificationCompleteSubtitle
case .cancelled:
return ElementL10n.verificationRequestCancelledDetail
return L10n.screenSessionVerificationCancelledSubtitle
}
}
}
@@ -106,14 +106,16 @@ struct SessionVerificationScreen: View {
@ViewBuilder
private func emojisPanel(with emojis: [SessionVerificationEmoji]) -> some View {
HStack(spacing: 16) {
ForEach(emojis.prefix(4), id: \.self) { emoji in
EmojiView(emoji: emoji)
VStack(spacing: 32) {
HStack(spacing: 16) {
ForEach(emojis.prefix(4), id: \.self) { emoji in
EmojiView(emoji: emoji)
}
}
}
HStack(spacing: 16) {
ForEach(emojis.suffix(from: 4), id: \.self) { emoji in
EmojiView(emoji: emoji)
HStack(spacing: 16) {
ForEach(emojis.suffix(from: 4), id: \.self) { emoji in
EmojiView(emoji: emoji)
}
}
}
}
@@ -122,20 +124,20 @@ struct SessionVerificationScreen: View {
private var actionButtons: some View {
switch context.viewState.verificationState {
case .initial:
Button(ElementL10n.startVerification) {
Button(L10n.actionStartVerification) {
context.send(viewAction: .requestVerification)
}
.buttonStyle(.elementAction(.xLarge))
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.requestVerification)
case .cancelled:
Button(ElementL10n.globalRetry) {
Button(L10n.actionRetry) {
context.send(viewAction: .restart)
}
.buttonStyle(.elementAction(.xLarge))
case .verificationRequestAccepted:
Button(ElementL10n.sessionVerificationStart) {
Button(L10n.actionStart) {
context.send(viewAction: .startSasVerification)
}
.buttonStyle(.elementAction(.xLarge))
@@ -144,12 +146,12 @@ struct SessionVerificationScreen: View {
case .showingChallenge:
VStack(spacing: 30) {
Button { context.send(viewAction: .accept) } label: {
Label(ElementL10n.verificationSasMatch, systemImage: "checkmark")
Label(L10n.screenSessionVerificationTheyMatch, systemImage: "checkmark")
}
.buttonStyle(.elementAction(.xLarge))
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.acceptChallenge)
Button(ElementL10n.verificationSasDoNotMatch) {
Button(L10n.screenSessionVerificationTheyDontMatch) {
context.send(viewAction: .decline)
}
.font(.element.bodyBold)
@@ -162,14 +164,14 @@ struct SessionVerificationScreen: View {
HStack(spacing: 16) {
ProgressView()
.tint(.element.background)
Label(ElementL10n.verificationSasMatch, systemImage: "checkmark")
Label(L10n.screenSessionVerificationTheyMatch, systemImage: "checkmark")
}
}
.buttonStyle(.elementAction(.xLarge))
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.acceptChallenge)
.disabled(true)
Button(ElementL10n.verificationSasDoNotMatch) {
Button(L10n.screenSessionVerificationTheyDontMatch) {
context.send(viewAction: .decline)
}
.font(.element.bodyBold)
@@ -185,7 +187,7 @@ struct SessionVerificationScreen: View {
@ToolbarContentBuilder
private var toolbarContent: some ToolbarContent {
ToolbarItem(placement: .cancellationAction) {
Button(ElementL10n.actionCancel) {
Button(L10n.actionCancel) {
context.send(viewAction: .close)
}
.foregroundColor(.element.accent)
@@ -227,11 +229,18 @@ struct SessionVerificationScreen: View {
struct SessionVerification_Previews: PreviewProvider {
static var previews: some View {
sessionVerificationScreen(state: .initial)
.previewDisplayName("Initial")
sessionVerificationScreen(state: .requestingVerification)
.previewDisplayName("Requesting Verification")
sessionVerificationScreen(state: .verificationRequestAccepted)
.previewDisplayName("Request Accepted")
sessionVerificationScreen(state: .cancelled)
.previewDisplayName("Cancelled")
sessionVerificationScreen(state: .showingChallenge(emojis: SessionVerificationControllerProxyMock.emojis))
.previewDisplayName("Showing Challenge")
sessionVerificationScreen(state: .verified)
.previewDisplayName("Verified")
}
static func sessionVerificationScreen(state: SessionVerificationStateMachine.State) -> some View {
@@ -87,7 +87,7 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
coordinator.completion = { [weak self] result in
switch result {
case .finish:
self?.showSuccess(label: ElementL10n.done)
self?.showSuccess(label: L10n.actionDone)
default:
break
}
@@ -39,7 +39,7 @@ struct SettingsScreen: View {
signOutSection
}
.compoundForm()
.navigationTitle(ElementL10n.settings)
.navigationTitle(L10n.commonSettings)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .confirmationAction) {
@@ -49,7 +49,7 @@ struct SettingsScreen: View {
}
private var versionText: some View {
Text(ElementL10n.settingsVersion + ": " + InfoPlistReader.main.bundleShortVersionString + " (" + InfoPlistReader.main.bundleVersion + ")")
Text(L10n.settingsVersionNumber(InfoPlistReader.main.bundleShortVersionString, InfoPlistReader.main.bundleVersion))
}
private var userSection: some View {
@@ -79,7 +79,7 @@ struct SettingsScreen: View {
private var sessionVerificationSection: some View {
Section {
Button { context.send(viewAction: .sessionVerification) } label: {
Label(ElementL10n.settingsSessionVerification, systemImage: "checkmark.shield")
Label(L10n.actionCompleteVerification, systemImage: "checkmark.shield")
}
.buttonStyle(.compoundForm())
}
@@ -89,7 +89,7 @@ struct SettingsScreen: View {
private var developerOptionsSection: some View {
Section {
Button { context.send(viewAction: .developerOptions) } label: {
Label(ElementL10n.settingsDeveloperOptions, systemImage: "hammer.circle")
Label(L10n.commonDeveloperOptions, systemImage: "hammer.circle")
}
.buttonStyle(.compoundForm(accessory: .navigationLink))
.accessibilityIdentifier("sessionVerificationButton")
@@ -105,7 +105,7 @@ struct SettingsScreen: View {
.tag(style)
}
} label: {
Label(ElementL10n.settingsTimelineStyle, systemImage: "rectangle.grid.1x2")
Label(L10n.commonMessageLayout, systemImage: "rectangle.grid.1x2")
}
.labelStyle(.compoundFormRow())
.accessibilityIdentifier("timelineStylePicker")
@@ -114,7 +114,7 @@ struct SettingsScreen: View {
}
Button { context.send(viewAction: .reportBug) } label: {
Label(ElementL10n.sendBugReport, systemImage: "questionmark.circle")
Label(L10n.actionReportBug, systemImage: "questionmark.circle")
}
.buttonStyle(.compoundForm(accessory: .navigationLink))
.accessibilityIdentifier("reportBugButton")
@@ -125,16 +125,16 @@ struct SettingsScreen: View {
private var signOutSection: some View {
Section {
Button { showingLogoutConfirmation = true } label: {
Label(ElementL10n.actionSignOut, systemImage: "rectangle.portrait.and.arrow.right")
Label(L10n.screenSignoutPreferenceItem, systemImage: "rectangle.portrait.and.arrow.right")
}
.buttonStyle(.compoundForm())
.accessibilityIdentifier("logoutButton")
.alert(ElementL10n.actionSignOut, isPresented: $showingLogoutConfirmation) {
Button(ElementL10n.actionSignOut,
.alert(L10n.screenSignoutConfirmationDialogTitle, isPresented: $showingLogoutConfirmation) {
Button(L10n.screenSignoutConfirmationDialogSubmit,
role: .destructive,
action: logout)
} message: {
Text(ElementL10n.actionSignOutConfirmationSimple)
Text(L10n.screenSignoutConfirmationDialogContent)
}
} footer: {
VStack {
@@ -150,7 +150,7 @@ struct SettingsScreen: View {
}
private var doneButton: some View {
Button(ElementL10n.done, action: close)
Button(L10n.actionDone, action: close)
}
private func close() {
@@ -166,9 +166,9 @@ private extension TimelineStyle {
var name: String {
switch self {
case .plain:
return ElementL10n.roomTimelineStylePlainLongDescription
return L10n.commonModern
case .bubbles:
return ElementL10n.roomTimelineStyleBubbledLongDescription
return L10n.commonBubbles
}
}
}
@@ -41,7 +41,7 @@ enum StartChatUserSectionType {
case .searchResult:
return nil
case .suggestions:
return ElementL10n.directRoomUserListSuggestionsTitle
return L10n.commonSuggestions
}
}
}
@@ -66,12 +66,12 @@ class StartChatViewModel: StartChatViewModelType, StartChatViewModelProtocol {
switch type {
case .failedRetrievingDirectRoom:
state.bindings.alertInfo = AlertInfo(id: type,
title: ElementL10n.dialogTitleError,
message: ElementL10n.retrievingDirectRoomError)
title: L10n.commonError,
message: L10n.screenStartChatErrorStartingChat)
case .failedCreatingRoom:
state.bindings.alertInfo = AlertInfo(id: type,
title: ElementL10n.dialogTitleError,
message: ElementL10n.retrievingDirectRoomError)
title: L10n.commonError,
message: L10n.screenStartChatErrorStartingChat)
default:
state.bindings.alertInfo = AlertInfo(id: type)
}
@@ -122,7 +122,7 @@ class StartChatViewModel: StartChatViewModelType, StartChatViewModelProtocol {
private func showLoadingIndicator() {
userIndicatorController?.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
title: ElementL10n.loading,
title: L10n.commonLoading,
persistent: true))
}
@@ -29,21 +29,21 @@ struct StartChatScreen: View {
}
.scrollContentBackground(.hidden)
.background(Color.element.formBackground.ignoresSafeArea())
.navigationTitle(ElementL10n.startChat)
.navigationTitle(L10n.actionStartChat)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
closeButton
}
}
.searchable(text: $context.searchQuery, placement: .navigationBarDrawer(displayMode: .always), prompt: ElementL10n.searchForSomeone)
.searchable(text: $context.searchQuery, placement: .navigationBarDrawer(displayMode: .always), prompt: L10n.commonSearchForSomeone)
.alert(item: $context.alertInfo) { $0.alert }
}
private var createRoomSection: some View {
Section {
Button(action: createRoom) {
Label(ElementL10n.createARoom, systemImage: "person.3")
Label(L10n.actionCreateARoom, systemImage: "person.3")
}
.buttonStyle(FormButtonStyle(accessory: .navigationLink))
}
@@ -53,7 +53,7 @@ struct StartChatScreen: View {
private var inviteFriendsSection: some View {
Section {
Button(action: inviteFriends) {
Label(ElementL10n.inviteFriendsToElement, systemImage: "square.and.arrow.up")
Label(L10n.actionInviteFriendsToApp(InfoPlistReader.main.bundleDisplayName), systemImage: "square.and.arrow.up")
}
.buttonStyle(FormButtonStyle())
.accessibilityIdentifier(A11yIdentifiers.startChatScreen.inviteFriends)
@@ -78,7 +78,7 @@ struct StartChatScreen: View {
}
private var closeButton: some View {
Button(ElementL10n.actionCancel, action: close)
Button(L10n.actionCancel, action: close)
.accessibilityIdentifier(A11yIdentifiers.startChatScreen.closeStartChat)
}