[#617] Use L10n for all the texts in the app (#627)

Closes #617

- All the texts that weren't in the Localisable.strings file are now
  there.
- L10n is used for all the texts in the code.
- Fixed paths in SwiftGen build phase so L10n.swift is now correctly
  generated when Localisable.strings file change.
This commit is contained in:
Michal Fousek 2023-03-07 22:18:17 +01:00 committed by GitHub
parent effa4b304a
commit c6b222ff46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 590 additions and 148 deletions

View File

@ -1138,12 +1138,12 @@
2E35F99027B28E6800EB79CD /* TextFields */ = {
isa = PBXGroup;
children = (
2E35F99127B28E7600EB79CD /* SingleLineTextField.swift */,
2EDA07A527EDE31100D6F09B /* Components */,
9E7225F4288AC6F300DF7F17 /* MultiLineTextField */,
9E7FE0F0282E80C100C374E8 /* TCATextField */,
2E35F99127B28E7600EB79CD /* SingleLineTextField.swift */,
9E5BF64C2823E84300BA3F17 /* TransactionAddress */,
9E5BF64B2823C91200BA3F17 /* TransactionAmount */,
2EDA07A527EDE31100D6F09B /* Components */,
);
path = TextFields;
sourceTree = "<group>";
@ -1622,7 +1622,6 @@
9E7FE0BB282D1DC200C374E8 /* Utils */ = {
isa = PBXGroup;
children = (
9E0F573F297E7F00005304FA /* Logging */,
9E7FE0D4282D281800C374E8 /* Array+Chunked.swift */,
F9C165B3274031F600592F76 /* Bindings.swift */,
0DACFA7E27208CE00039EEA5 /* Clamped.swift */,
@ -1640,6 +1639,7 @@
0DACFA8027208D940039EEA5 /* UInt+SuperscriptText.swift */,
0D7CE63327349B5D0020E050 /* View+WhenDraggable.swift */,
F9EEB8152742C2210032EEB8 /* WithStateBinding.swift */,
9E0F573F297E7F00005304FA /* Logging */,
);
path = Utils;
sourceTree = "<group>";
@ -2405,9 +2405,10 @@
inputFileListPaths = (
);
inputPaths = (
"$(SRCROOT)/swiftlint.yml",
"$(SRCROOT)/secant/Resources/Colors.xcassets",
"$(SRCROOT)/secant/Resources/Assets/xcassets",
"$(SRCROOT)/secant/Resources/Localizable.strings",
"$(SRCROOT)/swiftgen.yml",
);
name = SwiftGen;
outputFileListPaths = (
@ -2415,6 +2416,7 @@
outputPaths = (
"$(DERIVED_FILE_DIR)/Resources/Generated/XCAssets+Generated.swift",
"$(DERIVED_FILE_DIR)/Resources/Generated/Fonts+Generated.swift",
"$(DERIVED_FILE_DIR)/Resources/Generated/L10n.swift",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@ -2503,10 +2505,10 @@
inputFileListPaths = (
);
inputPaths = (
"$(SRCROOT)/swiftlint.yml",
"$(SRCROOT)/secant/Resources/Colors.xcassets",
"$(SRCROOT)/secant/Resources/Assets/xcassets",
"$(SRCROOT)/Resources/Localizable.strings",
"$(SRCROOT)/secant/Resources/Localizable.strings",
"$(SRCROOT)/swiftgen.yml",
);
name = SwiftGen;
outputFileListPaths = (

View File

@ -13,7 +13,7 @@ extension LocalAuthenticationClient: DependencyKey {
authenticate: {
let context = LAContext()
var error: NSError?
let reason = "The Following content requires authentication."
let reason = L10n.LocalAuthentication.reason
do {
/// Biometrics validation

View File

@ -166,9 +166,12 @@ class MockSDKSynchronizerClient: SDKSynchronizerClient {
}
func getUnifiedAddress(account: Int) -> UnifiedAddress? {
// swiftlint:disable line_length force_try
// swiftlint:disable force_try
try! UnifiedAddress(
encoding: "utest1zkkkjfxkamagznjr6ayemffj2d2gacdwpzcyw669pvg06xevzqslpmm27zjsctlkstl2vsw62xrjktmzqcu4yu9zdhdxqz3kafa4j2q85y6mv74rzjcgjg8c0ytrg7dwyzwtgnuc76h",
encoding: """
utest1zkkkjfxkamagznjr6ayemffj2d2gacdwpzcyw669pvg06xevzqslpmm27zjsctlkstl2vsw62xrjktmzqcu4yu9zdhdxqz3kafa4j2q85y6mv74rzjcgjg8c0ytrg7dwyz\
wtgnuc76h
""",
network: .testnet
)
}

View File

@ -44,7 +44,7 @@ private protocol SupportDataGeneratorItem {
private struct TimeItem: SupportDataGeneratorItem {
private enum Constants {
static let timeKey = "Current time"
static let timeKey = L10n.SupportData.TimeItem.time
}
let dateFormatter: DateFormatter
@ -62,9 +62,9 @@ private struct TimeItem: SupportDataGeneratorItem {
private struct AppVersionItem: SupportDataGeneratorItem {
private enum Constants {
static let bundleIdentifierKey = "App identifier"
static let versionKey = "App version"
static let unknownVersion = "Unknown"
static let bundleIdentifierKey = L10n.SupportData.AppVersionItem.bundleIdentifier
static let versionKey = L10n.SupportData.AppVersionItem.version
static let unknownVersion = L10n.General.unknown
}
func generate() -> [(String, String)] {
@ -88,7 +88,7 @@ private struct AppVersionItem: SupportDataGeneratorItem {
private struct SystemVersionItem: SupportDataGeneratorItem {
private enum Constants {
static let systemVersionKey = "iOS version"
static let systemVersionKey = L10n.SupportData.SystemVersionItem.version
}
func generate() -> [(String, String)] {
@ -98,8 +98,8 @@ private struct SystemVersionItem: SupportDataGeneratorItem {
private struct DeviceModelItem: SupportDataGeneratorItem {
private enum Constants {
static let deviceModelKey = "Device"
static let unknownDevice = "unknown"
static let deviceModelKey = L10n.SupportData.DeviceModelItem.device
static let unknownDevice = L10n.General.unknown
}
func generate() -> [(String, String)] {
@ -117,17 +117,17 @@ private struct DeviceModelItem: SupportDataGeneratorItem {
private struct LocaleItem: SupportDataGeneratorItem {
private enum Constants {
static let localKey = "Locale"
static let groupingSeparatorKey = "Currency grouping separato"
static let decimalSeparatorKey = "Currency decimal separator"
static let unknownSeparator = "unknown"
static let localeKey = L10n.SupportData.LocaleItem.locale
static let groupingSeparatorKey = L10n.SupportData.LocaleItem.groupingSeparator
static let decimalSeparatorKey = L10n.SupportData.LocaleItem.decimalSeparator
static let unknownSeparator = L10n.General.unknown
}
func generate() -> [(String, String)] {
let locale = Locale.current
return [
(Constants.localKey, locale.identifier),
(Constants.localeKey, locale.identifier),
(Constants.groupingSeparatorKey, locale.groupingSeparator ?? Constants.unknownSeparator),
(Constants.decimalSeparatorKey, locale.decimalSeparator ?? Constants.unknownSeparator)
]
@ -136,8 +136,8 @@ private struct LocaleItem: SupportDataGeneratorItem {
private struct FreeDiskSpaceItem: SupportDataGeneratorItem {
private enum Constants {
static let freeDiskSpaceKey = "Usable storage"
static let freeDiskSpaceUnknown = "unknown"
static let freeDiskSpaceKey = L10n.SupportData.FreeDiskSpaceItem.freeDiskSpace
static let freeDiskSpaceUnknown = L10n.General.unknown
}
func generate() -> [(String, String)] {
@ -162,12 +162,12 @@ private struct FreeDiskSpaceItem: SupportDataGeneratorItem {
private struct PermissionsItems: SupportDataGeneratorItem {
private enum Constants {
static let permissionsKey = "Permissions"
static let cameraPermKey = "Camera access"
static let faceIDAvailable = "FaceID available"
static let touchIDAvailable = "TouchID available"
static let yesText = "yes"
static let noText = "no"
static let permissionsKey = L10n.SupportData.PermissionItem.permissions
static let cameraPermKey = L10n.SupportData.PermissionItem.camera
static let faceIDAvailable = L10n.SupportData.PermissionItem.faceID
static let touchIDAvailable = L10n.SupportData.PermissionItem.touchID
static let yesText = L10n.General.yes
static let noText = L10n.General.no
}
func generate() -> [(String, String)] {

View File

@ -29,7 +29,7 @@ struct UserDefaultsWalletConfigStorage {
let rawFlags = try PropertyListDecoder().decode(WalletConfig.RawFlags.self, from: data)
return WalletConfig(flags: rawFlags)
} catch {
LoggerProxy.debug("Error when deocding feature flags from user defaults: \(error)")
LoggerProxy.debug("Error when decoding feature flags from user defaults: \(error)")
throw InternalError.unableToDeserializeData
}
}

View File

@ -16,15 +16,15 @@ struct AddressDetailsReducer: ReducerProtocol {
var uAddress: UnifiedAddress?
var unifiedAddress: String {
uAddress?.stringEncoded ?? "could not extract UA"
uAddress?.stringEncoded ?? L10n.AddressDetails.Error.cantExtractUnifiedAddress
}
var transparentAddress: String {
uAddress?.transparentReceiver()?.stringEncoded ?? "could not extract transparent receiver from UA"
uAddress?.transparentReceiver()?.stringEncoded ?? L10n.AddressDetails.Error.cantExtractTransparentAddress
}
var saplingAddress: String {
uAddress?.saplingReceiver()?.stringEncoded ?? "could not extract sapling receiver from UA"
uAddress?.saplingReceiver()?.stringEncoded ?? L10n.AddressDetails.Error.cantExtractSaplingAddress
}
}

View File

@ -19,7 +19,7 @@ struct AddressDetailsView: View {
qrCode(viewStore.unifiedAddress)
.padding(30)
Text("\(viewStore.unifiedAddress)")
Text(viewStore.unifiedAddress)
.onTapGesture {
viewStore.send(.copyUnifiedAddressToPastboard)
}
@ -30,7 +30,7 @@ struct AddressDetailsView: View {
qrCode(viewStore.saplingAddress)
.padding(30)
Text("\(viewStore.saplingAddress)")
Text(viewStore.saplingAddress)
.onTapGesture {
viewStore.send(.copySaplingAddressToPastboard)
}
@ -41,7 +41,7 @@ struct AddressDetailsView: View {
qrCode(viewStore.transparentAddress)
.padding(30)
Text("\(viewStore.transparentAddress)")
Text(viewStore.transparentAddress)
.onTapGesture {
viewStore.send(.copyTransparentAddressToPastboard)
}

View File

@ -65,7 +65,7 @@ struct BalanceBreakdownReducer: ReducerProtocol {
case .updateLatestBlock:
guard let latestBlockNumber = sdkSynchronizer.latestScannedSynchronizerState?.latestScannedHeight,
let latestBlock = numberFormatter.string(NSDecimalNumber(value: latestBlockNumber)) else {
state.latestBlock = "unknown"
state.latestBlock = L10n.General.unknown
return .none
}
state.latestBlock = "\(latestBlock)"
@ -79,7 +79,7 @@ struct BalanceBreakdownReducer: ReducerProtocol {
extension BalanceBreakdownReducer.State {
static let placeholder = BalanceBreakdownReducer.State(
autoShieldingThreshold: Zatoshi(1_000_000),
latestBlock: "unknown",
latestBlock: L10n.General.unknown,
shieldedBalance: Balance.zero,
transparentBalance: Balance.zero
)

View File

@ -81,9 +81,9 @@ struct ExportLogsReducer: ReducerProtocol {
case let .failed(errorDescription):
// TODO: [#527] address the error here https://github.com/zcash/secant-ios-wallet/issues/527
state.alert = AlertState(
title: TextState("Error when exporting logs"),
message: TextState("Error: \(errorDescription)"),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.ExportLogs.Alert.Failed.title),
message: TextState(L10n.ExportLogs.Alert.Failed.message(errorDescription)),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
return .none

View File

@ -112,7 +112,7 @@ extension HomeView {
.font(.system(size: 20))
}
Text("\(viewStore.synchronizerStatusSnapshot.message)")
Text(viewStore.synchronizerStatusSnapshot.message)
}
.foregroundColor(Asset.Colors.Mfp.primary.color)
}

View File

@ -14,20 +14,20 @@ struct ImportBirthdayView: View {
var body: some View {
WithViewStore(store) { viewStore in
VStack {
Text("importWallet.birthday.description")
Text(L10n.ImportWallet.Birthday.description)
.font(.system(size: 16))
.fontWeight(.bold)
.foregroundColor(Asset.Colors.Mfp.fontDark.color)
TextField(
"importWallet.birthday.placeholder",
L10n.ImportWallet.Birthday.placeholder,
text: viewStore.bindingForRedactableBirthday(viewStore.birthdayHeight)
)
.keyboardType(.numberPad)
.autocapitalization(.none)
.importSeedEditorModifier()
Button("importWallet.button.restoreWallet") {
Button(L10n.ImportWallet.Button.restoreWallet) {
viewStore.send(.restoreWallet)
}
.activeButtonStyle

View File

@ -30,7 +30,7 @@ struct ImportWalletReducer: ReducerProtocol {
var mnemonicStatus: String {
if isValidMnemonic {
return "VALID SEED PHRASE"
return L10n.ImportWallet.Seed.valid
} else {
return "\(wordsCount)/\(maxWordsCount)"
}
@ -118,10 +118,10 @@ struct ImportWalletReducer: ReducerProtocol {
// notify user
// TODO: [#221] Proper Error/Success handling (https://github.com/zcash/secant-ios-wallet/issues/221)
state.alert = AlertState(
title: TextState("Success"),
message: TextState("The wallet has been successfully recovered."),
title: TextState(L10n.General.success),
message: TextState(L10n.ImportWallet.Alert.Success.message),
dismissButton: .default(
TextState("Ok"),
TextState(L10n.General.ok),
action: .send(.successfullyRecovered)
)
)
@ -130,10 +130,10 @@ struct ImportWalletReducer: ReducerProtocol {
} catch {
// TODO: [#221] Proper Error/Success handling (https://github.com/zcash/secant-ios-wallet/issues/221)
state.alert = AlertState(
title: TextState("Failed to restore wallet"),
message: TextState("Error: \(error.localizedDescription)"),
title: TextState(L10n.ImportWallet.Alert.Failed.title),
message: TextState(L10n.ImportWallet.Alert.Failed.message(error.localizedDescription)),
dismissButton: .default(
TextState("Ok"),
TextState(L10n.General.ok),
action: .send(.dismissAlert)
)
)

View File

@ -18,7 +18,7 @@ struct ProfileReducer: ReducerProtocol {
var sdkVersion = ""
var unifiedAddress: String {
addressDetailsState.uAddress?.stringEncoded ?? "could not extract UA"
addressDetailsState.uAddress?.stringEncoded ?? L10n.ReceiveZec.Error.cantExtractUnifiedAddress
}
}

View File

@ -39,12 +39,12 @@ extension RootReducer {
case .debug(.rescanBlockchain):
state.debugState.rescanDialog = .init(
title: TextState("Rescan"),
message: TextState("Select the rescan you want"),
title: TextState(L10n.Root.Debug.Dialog.Rescan.title),
message: TextState(L10n.Root.Debug.Dialog.Rescan.message),
buttons: [
.default(TextState("Quick rescan"), action: .send(.debug(.quickRescan))),
.default(TextState("Full rescan"), action: .send(.debug(.fullRescan))),
.cancel(TextState("Cancel"))
.default(TextState(L10n.Root.Debug.Dialog.Rescan.Option.quick), action: .send(.debug(.quickRescan))),
.default(TextState(L10n.Root.Debug.Dialog.Rescan.Option.full), action: .send(.debug(.fullRescan))),
.cancel(TextState(L10n.General.cancel))
]
)
return .none
@ -65,9 +65,9 @@ extension RootReducer {
if let errorDescription {
// TODO: [#221] Handle error more properly (https://github.com/zcash/secant-ios-wallet/issues/221)
state.alert = AlertState(
title: TextState("Rewind failed"),
message: TextState("Error: \(errorDescription)"),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.Root.Debug.Alert.Rewind.Failed.title),
message: TextState(L10n.Root.Debug.Alert.Rewind.Failed.message(errorDescription)),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
} else {
do {
@ -75,9 +75,9 @@ extension RootReducer {
} catch {
// TODO: [#221] Handle error more properly (https://github.com/zcash/secant-ios-wallet/issues/221)
state.alert = AlertState(
title: TextState("Can't start sync process after rewind"),
message: TextState("Error: \(error.localizedDescription)"),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.Root.Debug.Alert.Rewind.CantStartSync.title),
message: TextState(L10n.Root.Debug.Alert.Rewind.CantStartSync.message(error.localizedDescription)),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
}
}
@ -108,7 +108,7 @@ extension RootReducer {
private func rewind(policy: RewindPolicy, sourceAction: DebugAction) -> EffectPublisher<RootReducer.Action, Never> {
guard let rewindPublisher = sdkSynchronizer.rewind(policy) else {
return EffectTask(value: .debug(.rewindDone("SDKSynchronizer not initilized. rewindPublisher is nil", .debug(sourceAction))))
return EffectTask(value: .debug(.rewindDone(L10n.Root.Debug.Error.Rewind.sdkSynchronizerNotInitialized, .debug(sourceAction))))
}
return rewindPublisher
.replaceEmpty(with: Void())

View File

@ -115,10 +115,10 @@ extension RootReducer {
case let .destination(.deeplinkFailed(url, errorDescription)):
// TODO: [#221] Handle error more properly (https://github.com/zcash/secant-ios-wallet/issues/221)
state.destinationState.alert = AlertState(
title: TextState("Failed to process deeplink."),
message: TextState("Deeplink: \(url))\nError: \(errorDescription)"),
title: TextState(L10n.Root.Destination.Alert.FailedToProcessDeeplink.title),
message: TextState(L10n.Root.Destination.Alert.FailedToProcessDeeplink.message(url, errorDescription)),
dismissButton: .default(
TextState("Ok"),
TextState(L10n.General.ok),
action: .send(.destination(.dismissAlert))
)
)

View File

@ -82,17 +82,17 @@ extension RootReducer {
// TODO: [#221] Handle error more properly (https://github.com/zcash/secant-ios-wallet/issues/221)
state.appInitializationState = .failed
state.alert = AlertState(
title: TextState("Wallet initialisation failed."),
message: TextState("App initialisation state: failed"),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.Root.Initialization.Alert.Failed.title),
message: TextState(L10n.Root.Initialization.Alert.WalletStateFailed.message(walletState)),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
case .keysMissing:
// TODO: [#221] Handle error more properly (https://github.com/zcash/secant-ios-wallet/issues/221)
state.appInitializationState = .keysMissing
state.alert = AlertState(
title: TextState("Wallet initialisation failed."),
message: TextState("App initialisation state: keysMissing."),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.Root.Initialization.Alert.Failed.title),
message: TextState(L10n.Root.Initialization.Alert.WalletStateFailed.message(walletState)),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
case .initialized, .filesMissing:
@ -123,9 +123,9 @@ extension RootReducer {
state.appInitializationState = .failed
// TODO: [#221] Handle fatal error more properly (https://github.com/zcash/secant-ios-wallet/issues/221)
state.alert = AlertState(
title: TextState("Wallet initialisation failed."),
message: TextState("Can't load seed phrase from local storage."),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.Root.Initialization.Alert.Failed.title),
message: TextState(L10n.Root.Initialization.Alert.CantLoadSeedPhrase.message),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
return .none
}
@ -151,9 +151,9 @@ extension RootReducer {
state.appInitializationState = .failed
// TODO: [#221] Handle error more properly (https://github.com/zcash/secant-ios-wallet/issues/221)
state.alert = AlertState(
title: TextState("Failed to initialize the SDK"),
message: TextState("Error: \(error.localizedDescription)"),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.Root.Initialization.Alert.SdkInitFailed.title),
message: TextState(L10n.Root.Initialization.Alert.Error.message(error.localizedDescription)),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
return .none
}
@ -163,9 +163,9 @@ extension RootReducer {
state.appInitializationState = .failed
// TODO: [#221] Handle fatal error more properly (https://github.com/zcash/secant-ios-wallet/issues/221)
state.alert = AlertState(
title: TextState("Wallet initialisation failed."),
message: TextState("Can't load seed phrase from local storage."),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.Root.Initialization.Alert.Failed.title),
message: TextState(L10n.Root.Initialization.Alert.CantLoadSeedPhrase.message),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
return .none
}
@ -210,9 +210,9 @@ extension RootReducer {
} catch {
// TODO: [#201] - merge with issue 221 (https://github.com/zcash/secant-ios-wallet/issues/221) and its Error States
state.alert = AlertState(
title: TextState("Wallet initialisation failed."),
message: TextState("Can't create new wallet. Error: \(error.localizedDescription)"),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.Root.Initialization.Alert.Failed.title),
message: TextState(L10n.Root.Initialization.Alert.CantCreateNewWallet.message(error.localizedDescription)),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
}
@ -224,24 +224,26 @@ extension RootReducer {
} catch {
// TODO: [#221] error we need to handle, issue #221 (https://github.com/zcash/secant-ios-wallet/issues/221)
state.alert = AlertState(
title: TextState("Wallet initialisation failed."),
message: TextState("Can't store information that user passed phrase backup test. Error: \(error.localizedDescription)"),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.Root.Initialization.Alert.Failed.title),
message: TextState(
L10n.Root.Initialization.Alert.CantStoreThatUserPassedPhraseBackupTest.message(error.localizedDescription)
),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
}
return .none
case .initialization(.nukeWalletRequest):
state.destinationState.alert = AlertState(
title: TextState("Wipe of the wallet"),
message: TextState("Are you sure?"),
title: TextState(L10n.Root.Initialization.Alert.Wipe.title),
message: TextState(L10n.Root.Initialization.Alert.Wipe.message),
buttons: [
.destructive(
TextState("Yes"),
TextState(L10n.General.yes),
action: .send(.initialization(.nukeWallet))
),
.cancel(
TextState("No"),
TextState(L10n.General.no),
action: .send(.destination(.dismissAlert))
)
]
@ -272,9 +274,9 @@ extension RootReducer {
case .nukeWalletFailed:
// TODO: [#221] error we need to handle, issue #221 (https://github.com/zcash/secant-ios-wallet/issues/221)
state.alert = AlertState(
title: TextState("Nuke of the wallet failed"),
title: TextState(L10n.Root.Initialization.Alert.WipeFailed.title),
message: TextState(""),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
let backDestination: EffectTask<RootReducer.Action>

View File

@ -123,7 +123,7 @@ private extension RootView {
@ViewBuilder func debugView(_ viewStore: RootViewStore) -> some View {
VStack(alignment: .leading) {
if viewStore.destinationState.previousDestination == .home {
Button("general.back") {
Button(L10n.General.back) {
viewStore.goToDestination(.home)
}
.activeButtonStyle
@ -132,42 +132,42 @@ private extension RootView {
}
List {
Section(header: Text("Navigation Stack Destinations")) {
Button("Go To Sandbox (navigation proof)") {
Section(header: Text(L10n.Root.Debug.title)) {
Button(L10n.Root.Debug.Option.gotoSandbox) {
viewStore.goToDestination(.sandbox)
}
Button("Go To Onboarding") {
Button(L10n.Root.Debug.Option.gotoOnboarding) {
viewStore.goToDestination(.onboarding)
}
Button("Go To Phrase Validation Demo") {
Button(L10n.Root.Debug.Option.gotoPhraseValidationDemo) {
viewStore.goToDestination(.phraseValidation)
}
Button("Restart the app") {
Button(L10n.Root.Debug.Option.restartApp) {
viewStore.goToDestination(.welcome)
}
Button("Test Crash Reporter") {
Button(L10n.Root.Debug.Option.testCrashReporter) {
viewStore.send(.debug(.testCrashReporter))
}
Button("Export logs") {
Button(L10n.Root.Debug.Option.exportLogs) {
viewStore.send(.exportLogs(.start))
}
.disabled(viewStore.exportLogsState.exportLogsDisabled)
Button("Rescan Blockchain") {
Button(L10n.Root.Debug.Option.rescanBlockchain) {
viewStore.send(.debug(.rescanBlockchain))
}
Button("[Be careful] Nuke Wallet") {
Button(L10n.Root.Debug.Option.nukeWallet) {
viewStore.send(.initialization(.nukeWalletRequest))
}
}
Section(header: Text("Feature flags")) {
Section(header: Text(L10n.Root.Debug.featureFlags)) {
let flags = viewStore.state.walletConfig.flags
.map { FeatureFlagWrapper(name: $0.key, isEnabled: $0.value) }
.sorted()
@ -204,7 +204,7 @@ private extension RootView {
dismiss: .debug(.cancelRescan)
)
}
.navigationBarTitle("Startup")
.navigationBarTitle(L10n.Root.Debug.navigationTitle)
}
}

View File

@ -68,9 +68,9 @@ struct ScanReducer: ReducerProtocol {
} catch {
// TODO: [#322] Handle error more properly (https://github.com/zcash/secant-ios-wallet/issues/322)
state.alert = AlertState(
title: TextState("Can't initialize the camera"),
message: TextState("Error: \(error.localizedDescription)"),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.Scan.Alert.CantInitializeCamera.title),
message: TextState(L10n.Scan.Alert.CantInitializeCamera.message(error.localizedDescription)),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
}
return .none
@ -117,9 +117,9 @@ struct ScanReducer: ReducerProtocol {
} catch {
// TODO: [#322] handle torch errors (https://github.com/zcash/secant-ios-wallet/issues/322)
state.alert = AlertState(
title: TextState("Can't initialize the camera"),
message: TextState("Error: \(error.localizedDescription)"),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.Scan.Alert.CantInitializeCamera.title),
message: TextState(L10n.Scan.Alert.CantInitializeCamera.message(error.localizedDescription)),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
}
return .none

View File

@ -38,7 +38,7 @@ struct ScanView: View {
.padding(.bottom, 10)
if let scannedValue = viewStore.scannedValue {
Text("\(scannedValue)")
Text(scannedValue)
.foregroundColor(viewStore.isValidValue ? .green : .red)
} else {
Text(L10n.Scan.scanning)

View File

@ -63,9 +63,9 @@ struct SettingsReducer: ReducerProtocol {
} catch {
// TODO: [#221] - merge with issue 221 (https://github.com/zcash/secant-ios-wallet/issues/221) and its Error States
state.alert = AlertState(
title: TextState("Can't backup wallet"),
message: TextState("Error: \(error.localizedDescription)"),
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
title: TextState(L10n.Settings.Alert.CantBackupWallet.title),
message: TextState(L10n.Settings.Alert.CantBackupWallet.message(error.localizedDescription)),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.dismissAlert))
)
return .none
}
@ -104,12 +104,9 @@ struct SettingsReducer: ReducerProtocol {
state.supportData = SupportDataGenerator.generate()
} else {
state.alert = AlertState(
title: TextState("Can't send email"),
message: TextState("""
It looks like that you don't have any email account configured on your device. Therefore it's not possible to send a support \
email.
"""),
dismissButton: .default(TextState("Ok"), action: .send(.sendSupportMailFinished))
title: TextState(L10n.Settings.Alert.CantSendEmail.title),
message: TextState(L10n.Settings.Alert.CantSendEmail.message),
dismissButton: .default(TextState(L10n.General.ok), action: .send(.sendSupportMailFinished))
)
}

View File

@ -42,7 +42,7 @@ struct WalletEventsFlowReducer: ReducerProtocol {
@Dependency(\.pasteboard) var pasteboard
@Dependency(\.sdkSynchronizer) var sdkSynchronizer
@Dependency(\.zcashSDKEnvironment) var zcashSDKEnvironment
// swiftlint:disable:next cyclomatic_complexity
func reduce(into state: inout State, action: Action) -> ComposableArchitecture.EffectTask<Action> {
switch action {
@ -104,17 +104,14 @@ struct WalletEventsFlowReducer: ReducerProtocol {
case .warnBeforeLeavingApp(let blockExplorerURL):
state.alert = AlertState(
title: TextState("You are exiting your wallet"),
message: TextState("""
While usually an acceptable risk, you will possibly exposing your behavior and interest in this transaction by going online. \
OH NOES! What will you do?
"""),
title: TextState(L10n.WalletEvent.Alert.LeavingApp.title),
message: TextState(L10n.WalletEvent.Alert.LeavingApp.message),
primaryButton: .cancel(
TextState("NEVERMIND"),
TextState(L10n.WalletEvent.Alert.LeavingApp.Button.nevermind),
action: .send(.dismissAlert)
),
secondaryButton: .default(
TextState("SEE TX ONLINE"),
TextState(L10n.WalletEvent.Alert.LeavingApp.Button.seeOnline),
action: .send(.openBlockExplorer(blockExplorerURL))
)
)

View File

@ -22,28 +22,28 @@ struct SyncStatusSnapshot: Equatable {
static func snapshotFor(state: SyncStatus) -> SyncStatusSnapshot {
switch state {
case .enhancing:
return SyncStatusSnapshot(state, "Enhancing tx")
return SyncStatusSnapshot(state, L10n.Sync.Message.enhancing)
case .fetching:
return SyncStatusSnapshot(state, "fetching UTXOs")
return SyncStatusSnapshot(state, L10n.Sync.Message.fetchingUTXO)
case .disconnected:
return SyncStatusSnapshot(state, "disconnected")
return SyncStatusSnapshot(state, L10n.Sync.Message.disconnected)
case .stopped:
return SyncStatusSnapshot(state, "Stopped")
return SyncStatusSnapshot(state, L10n.Sync.Message.stopped)
case .synced:
return SyncStatusSnapshot(state, "Up-To-Date")
return SyncStatusSnapshot(state, L10n.Sync.Message.uptodate)
case .unprepared:
return SyncStatusSnapshot(state, "Unprepared")
return SyncStatusSnapshot(state, L10n.Sync.Message.unprepared)
case .error(let err):
return SyncStatusSnapshot(state, "Error: \(err.localizedDescription)")
return SyncStatusSnapshot(state, L10n.Sync.Message.error(err.localizedDescription))
case .syncing(let progress):
return SyncStatusSnapshot(state, "\(String(format: "%0.1f", progress.progress * 100))% Synced")
return SyncStatusSnapshot(state, L10n.Sync.Message.sync(String(format: "%0.1f", progress.progress * 100)))
}
}
}

View File

@ -40,12 +40,12 @@ extension WalletEvent {
case .shielded(let zatoshi):
// TODO: [#390] implement design once shielding is supported
// https://github.com/zcash/secant-ios-wallet/issues/390
Text("shielded wallet event \(zatoshi.decimalString())")
Text(L10n.WalletEvent.Row.shielded(zatoshi.decimalString()))
.padding(.leading, 30)
case .walletImport:
// TODO: [#391] implement design once shielding is supported
// https://github.com/zcash/secant-ios-wallet/issues/391
Text("wallet import wallet event")
Text(L10n.WalletEvent.Row.import)
.padding(.leading, 30)
}
}
@ -64,11 +64,11 @@ extension WalletEvent {
case .shielded(let zatoshi):
// TODO: [#390] implement design once shielding is supported
// https://github.com/zcash/secant-ios-wallet/issues/390
Text("shielded \(zatoshi.decimalString()) detail")
Text(L10n.WalletEvent.Detail.shielded(zatoshi.decimalString()))
case .walletImport:
// TODO: [#391] implement design once shielding is supported
// https://github.com/zcash/secant-ios-wallet/issues/391
Text("wallet import wallet event")
Text(L10n.WalletEvent.Detail.import)
}
}
}

View File

@ -25,6 +25,14 @@ internal enum L10n {
internal static let ta = L10n.tr("Localizable", "addressDetails.ta", fallback: "Transparent Address")
/// Unified Address
internal static let ua = L10n.tr("Localizable", "addressDetails.ua", fallback: "Unified Address")
internal enum Error {
/// could not extract sapling receiver from UA
internal static let cantExtractSaplingAddress = L10n.tr("Localizable", "addressDetails.error.cantExtractSaplingAddress", fallback: "could not extract sapling receiver from UA")
/// could not extract transparent receiver from UA
internal static let cantExtractTransparentAddress = L10n.tr("Localizable", "addressDetails.error.cantExtractTransparentAddress", fallback: "could not extract transparent receiver from UA")
/// could not extract UA
internal static let cantExtractUnifiedAddress = L10n.tr("Localizable", "addressDetails.error.cantExtractUnifiedAddress", fallback: "could not extract UA")
}
}
internal enum Balance {
/// %@ ZEC Available
@ -52,9 +60,41 @@ internal enum L10n {
/// possible roll back
internal static let rollBack = L10n.tr("Localizable", "error.rollBack", fallback: "possible roll back")
}
internal enum ExportLogs {
internal enum Alert {
internal enum Failed {
/// Error: %@
internal static func message(_ p1: Any) -> String {
return L10n.tr("Localizable", "exportLogs.alert.failed.message", String(describing: p1), fallback: "Error: %@")
}
/// Error when exporting logs
internal static let title = L10n.tr("Localizable", "exportLogs.alert.failed.title", fallback: "Error when exporting logs")
}
}
}
internal enum Field {
internal enum Multiline {
/// char limit exceeded
internal static let charLimitExceeded = L10n.tr("Localizable", "field.multiline.charLimitExceeded", fallback: "char limit exceeded")
}
internal enum TransactionAddress {
/// To:
internal static let to = L10n.tr("Localizable", "field.transactionAddress.to", fallback: "To:")
/// Valid Zcash Address
internal static let validZcashAddress = L10n.tr("Localizable", "field.transactionAddress.validZcashAddress", fallback: "Valid Zcash Address")
}
internal enum TransactionAmount {
/// Amount:
internal static let amount = L10n.tr("Localizable", "field.transactionAmount.amount", fallback: "Amount:")
/// ZEC Amount
internal static let zecAmount = L10n.tr("Localizable", "field.transactionAmount.zecAmount", fallback: "ZEC Amount")
}
}
internal enum General {
/// Back
internal static let back = L10n.tr("Localizable", "general.back", fallback: "Back")
/// Cancel
internal static let cancel = L10n.tr("Localizable", "general.cancel", fallback: "Cancel")
/// Clear
internal static let clear = L10n.tr("Localizable", "general.clear", fallback: "Clear")
/// Close
@ -65,10 +105,20 @@ internal enum L10n {
internal static let max = L10n.tr("Localizable", "general.max", fallback: "Max")
/// Next
internal static let next = L10n.tr("Localizable", "general.next", fallback: "Next")
/// No
internal static let no = L10n.tr("Localizable", "general.no", fallback: "No")
/// Ok
internal static let ok = L10n.tr("Localizable", "general.ok", fallback: "Ok")
/// Send
internal static let send = L10n.tr("Localizable", "general.send", fallback: "Send")
/// Skip
internal static let skip = L10n.tr("Localizable", "general.skip", fallback: "Skip")
/// Success
internal static let success = L10n.tr("Localizable", "general.success", fallback: "Success")
/// Unknown
internal static let unknown = L10n.tr("Localizable", "general.unknown", fallback: "Unknown")
/// Yes
internal static let yes = L10n.tr("Localizable", "general.yes", fallback: "Yes")
}
internal enum Home {
/// Receive ZEC
@ -85,6 +135,22 @@ internal enum L10n {
internal static let description = L10n.tr("Localizable", "importWallet.description", fallback: "Enter your secret backup seed phrase.")
/// Wallet Import
internal static let title = L10n.tr("Localizable", "importWallet.title", fallback: "Wallet Import")
internal enum Alert {
internal enum Failed {
/// Error: %@
internal static func message(_ p1: Any) -> String {
return L10n.tr("Localizable", "importWallet.alert.failed.message", String(describing: p1), fallback: "Error: %@")
}
/// Failed to restore wallet
internal static let title = L10n.tr("Localizable", "importWallet.alert.failed.title", fallback: "Failed to restore wallet")
}
internal enum Success {
/// The wallet has been successfully recovered.
internal static let message = L10n.tr("Localizable", "importWallet.alert.success.message", fallback: "The wallet has been successfully recovered.")
/// Success
internal static let title = L10n.tr("Localizable", "importWallet.alert.success.title", fallback: "Success")
}
}
internal enum Birthday {
/// Do you know the wallet's creation date? This will allow a faster sync. If you don't know the wallet's birthday, don't worry!
internal static let description = L10n.tr("Localizable", "importWallet.birthday.description", fallback: "Do you know the wallet's creation date? This will allow a faster sync. If you don't know the wallet's birthday, don't worry!")
@ -97,6 +163,14 @@ internal enum L10n {
/// Restore wallet
internal static let restoreWallet = L10n.tr("Localizable", "importWallet.button.restoreWallet", fallback: "Restore wallet")
}
internal enum Seed {
/// VALID SEED PHRASE
internal static let valid = L10n.tr("Localizable", "importWallet.seed.valid", fallback: "VALID SEED PHRASE")
}
}
internal enum LocalAuthentication {
/// The Following content requires authentication.
internal static let reason = L10n.tr("Localizable", "localAuthentication.reason", fallback: "The Following content requires authentication.")
}
internal enum Nefs {
/// Not enough space on disk to do synchronisation!
@ -143,6 +217,10 @@ internal enum L10n {
internal enum ReceiveZec {
/// Your Address
internal static let yourAddress = L10n.tr("Localizable", "receiveZec.yourAddress", fallback: "Your Address")
internal enum Error {
/// could not extract UA
internal static let cantExtractUnifiedAddress = L10n.tr("Localizable", "receiveZec.error.cantExtractUnifiedAddress", fallback: "could not extract UA")
}
}
internal enum RecoveryPhraseBackupValidation {
/// Drag the words below to match your backed-up copy.
@ -182,11 +260,152 @@ internal enum L10n {
internal static let goNext = L10n.tr("Localizable", "recoveryPhraseTestPreamble.button.goNext", fallback: "By understanding and preparing")
}
}
internal enum Root {
internal enum Debug {
/// Feature flags
internal static let featureFlags = L10n.tr("Localizable", "root.debug.featureFlags", fallback: "Feature flags")
/// Startup
internal static let navigationTitle = L10n.tr("Localizable", "root.debug.navigationTitle", fallback: "Startup")
/// Debug options
internal static let title = L10n.tr("Localizable", "root.debug.title", fallback: "Debug options")
internal enum Alert {
internal enum Rewind {
internal enum CantStartSync {
/// Error: %@
internal static func message(_ p1: Any) -> String {
return L10n.tr("Localizable", "root.debug.alert.rewind.cantStartSync.message", String(describing: p1), fallback: "Error: %@")
}
/// Can't start sync process after rewind
internal static let title = L10n.tr("Localizable", "root.debug.alert.rewind.cantStartSync.title", fallback: "Can't start sync process after rewind")
}
internal enum Failed {
/// Error: %@
internal static func message(_ p1: Any) -> String {
return L10n.tr("Localizable", "root.debug.alert.rewind.failed.message", String(describing: p1), fallback: "Error: %@")
}
/// Rewind failed
internal static let title = L10n.tr("Localizable", "root.debug.alert.rewind.failed.title", fallback: "Rewind failed")
}
}
}
internal enum Dialog {
internal enum Rescan {
/// Select the rescan you want
internal static let message = L10n.tr("Localizable", "root.debug.dialog.rescan.message", fallback: "Select the rescan you want")
/// Rescan
internal static let title = L10n.tr("Localizable", "root.debug.dialog.rescan.title", fallback: "Rescan")
internal enum Option {
/// Full rescan
internal static let full = L10n.tr("Localizable", "root.debug.dialog.rescan.option.full", fallback: "Full rescan")
/// Quick rescan
internal static let quick = L10n.tr("Localizable", "root.debug.dialog.rescan.option.quick", fallback: "Quick rescan")
}
}
}
internal enum Error {
internal enum Rewind {
/// SDKSynchronizer not initilized. rewindPublisher is nil
internal static let sdkSynchronizerNotInitialized = L10n.tr("Localizable", "root.debug.error.rewind.sdkSynchronizerNotInitialized", fallback: "SDKSynchronizer not initilized. rewindPublisher is nil")
}
}
internal enum Option {
/// Export logs
internal static let exportLogs = L10n.tr("Localizable", "root.debug.option.exportLogs", fallback: "Export logs")
/// Go To Onboarding
internal static let gotoOnboarding = L10n.tr("Localizable", "root.debug.option.gotoOnboarding", fallback: "Go To Onboarding")
/// Go To Phrase Validation Demo
internal static let gotoPhraseValidationDemo = L10n.tr("Localizable", "root.debug.option.gotoPhraseValidationDemo", fallback: "Go To Phrase Validation Demo")
/// Go To Sandbox (navigation proof)
internal static let gotoSandbox = L10n.tr("Localizable", "root.debug.option.gotoSandbox", fallback: "Go To Sandbox (navigation proof)")
/// [Be careful] Nuke Wallet
internal static let nukeWallet = L10n.tr("Localizable", "root.debug.option.nukeWallet", fallback: "[Be careful] Nuke Wallet")
/// Rescan Blockchain
internal static let rescanBlockchain = L10n.tr("Localizable", "root.debug.option.rescanBlockchain", fallback: "Rescan Blockchain")
/// Restart the app
internal static let restartApp = L10n.tr("Localizable", "root.debug.option.restartApp", fallback: "Restart the app")
/// Test Crash Reporter
internal static let testCrashReporter = L10n.tr("Localizable", "root.debug.option.testCrashReporter", fallback: "Test Crash Reporter")
}
}
internal enum Destination {
internal enum Alert {
internal enum FailedToProcessDeeplink {
/// Deeplink: (%@))
/// Error: (%@)
internal static func message(_ p1: Any, _ p2: Any) -> String {
return L10n.tr("Localizable", "root.destination.alert.failedToProcessDeeplink.message", String(describing: p1), String(describing: p2), fallback: "Deeplink: (%@))\nError: (%@)")
}
/// Failed to process deeplink.
internal static let title = L10n.tr("Localizable", "root.destination.alert.failedToProcessDeeplink.title", fallback: "Failed to process deeplink.")
}
}
}
internal enum Initialization {
internal enum Alert {
internal enum CantCreateNewWallet {
/// Can't create new wallet. Error: %@
internal static func message(_ p1: Any) -> String {
return L10n.tr("Localizable", "root.initialization.alert.cantCreateNewWallet.message", String(describing: p1), fallback: "Can't create new wallet. Error: %@")
}
}
internal enum CantLoadSeedPhrase {
/// Can't load seed phrase from local storage.
internal static let message = L10n.tr("Localizable", "root.initialization.alert.cantLoadSeedPhrase.message", fallback: "Can't load seed phrase from local storage.")
}
internal enum CantStoreThatUserPassedPhraseBackupTest {
/// Can't store information that user passed phrase backup test. Error: %@
internal static func message(_ p1: Any) -> String {
return L10n.tr("Localizable", "root.initialization.alert.cantStoreThatUserPassedPhraseBackupTest.message", String(describing: p1), fallback: "Can't store information that user passed phrase backup test. Error: %@")
}
}
internal enum Error {
/// Error: %@
internal static func message(_ p1: Any) -> String {
return L10n.tr("Localizable", "root.initialization.alert.error.message", String(describing: p1), fallback: "Error: %@")
}
}
internal enum Failed {
/// Wallet initialisation failed.
internal static let title = L10n.tr("Localizable", "root.initialization.alert.failed.title", fallback: "Wallet initialisation failed.")
}
internal enum SdkInitFailed {
/// Failed to initialize the SDK
internal static let title = L10n.tr("Localizable", "root.initialization.alert.sdkInitFailed.title", fallback: "Failed to initialize the SDK")
}
internal enum WalletStateFailed {
/// App initialisation state: %@.
internal static func message(_ p1: Any) -> String {
return L10n.tr("Localizable", "root.initialization.alert.walletStateFailed.message", String(describing: p1), fallback: "App initialisation state: %@.")
}
}
internal enum Wipe {
/// Are you sure?
internal static let message = L10n.tr("Localizable", "root.initialization.alert.wipe.message", fallback: "Are you sure?")
/// Wipe of the wallet
internal static let title = L10n.tr("Localizable", "root.initialization.alert.wipe.title", fallback: "Wipe of the wallet")
}
internal enum WipeFailed {
/// Nuke of the wallet failed
internal static let title = L10n.tr("Localizable", "root.initialization.alert.wipeFailed.title", fallback: "Nuke of the wallet failed")
}
}
}
}
internal enum Scan {
/// We will validate any Zcash URI and take you to the appropriate action.
internal static let info = L10n.tr("Localizable", "scan.info", fallback: "We will validate any Zcash URI and take you to the appropriate action.")
/// Scanning...
internal static let scanning = L10n.tr("Localizable", "scan.scanning", fallback: "Scanning...")
internal enum Alert {
internal enum CantInitializeCamera {
/// Error: %@
internal static func message(_ p1: Any) -> String {
return L10n.tr("Localizable", "scan.alert.cantInitializeCamera.message", String(describing: p1), fallback: "Error: %@")
}
/// Can't initialize the camera
internal static let title = L10n.tr("Localizable", "scan.alert.cantInitializeCamera.title", fallback: "Can't initialize the camera")
}
}
}
internal enum Send {
/// address: %@
@ -229,6 +448,88 @@ internal enum L10n {
internal static let feedback = L10n.tr("Localizable", "settings.feedback", fallback: "Send us feedback!")
/// Settings
internal static let title = L10n.tr("Localizable", "settings.title", fallback: "Settings")
internal enum Alert {
internal enum CantBackupWallet {
/// Error: %@
internal static func message(_ p1: Any) -> String {
return L10n.tr("Localizable", "settings.alert.cantBackupWallet.message", String(describing: p1), fallback: "Error: %@")
}
/// Can't backup wallet
internal static let title = L10n.tr("Localizable", "settings.alert.cantBackupWallet.title", fallback: "Can't backup wallet")
}
internal enum CantSendEmail {
/// It looks like that you don't have any email account configured on your device. Therefore it's not possible to send a support email.
internal static let message = L10n.tr("Localizable", "settings.alert.cantSendEmail.message", fallback: "It looks like that you don't have any email account configured on your device. Therefore it's not possible to send a support email.")
/// Can't send email
internal static let title = L10n.tr("Localizable", "settings.alert.cantSendEmail.title", fallback: "Can't send email")
}
}
}
internal enum SupportData {
internal enum AppVersionItem {
/// App identifier
internal static let bundleIdentifier = L10n.tr("Localizable", "supportData.appVersionItem.bundleIdentifier", fallback: "App identifier")
/// App version
internal static let version = L10n.tr("Localizable", "supportData.appVersionItem.version", fallback: "App version")
}
internal enum DeviceModelItem {
/// Device
internal static let device = L10n.tr("Localizable", "supportData.deviceModelItem.device", fallback: "Device")
}
internal enum FreeDiskSpaceItem {
/// Usable storage
internal static let freeDiskSpace = L10n.tr("Localizable", "supportData.freeDiskSpaceItem.freeDiskSpace", fallback: "Usable storage")
}
internal enum LocaleItem {
/// Currency decimal separator
internal static let decimalSeparator = L10n.tr("Localizable", "supportData.localeItem.decimalSeparator", fallback: "Currency decimal separator")
/// Currency grouping separator
internal static let groupingSeparator = L10n.tr("Localizable", "supportData.localeItem.groupingSeparator", fallback: "Currency grouping separator")
/// Locale
internal static let locale = L10n.tr("Localizable", "supportData.localeItem.locale", fallback: "Locale")
}
internal enum PermissionItem {
/// Camera access
internal static let camera = L10n.tr("Localizable", "supportData.permissionItem.camera", fallback: "Camera access")
/// FaceID available
internal static let faceID = L10n.tr("Localizable", "supportData.permissionItem.faceID", fallback: "FaceID available")
/// Permissions
internal static let permissions = L10n.tr("Localizable", "supportData.permissionItem.permissions", fallback: "Permissions")
/// TouchID available
internal static let touchID = L10n.tr("Localizable", "supportData.permissionItem.touchID", fallback: "TouchID available")
}
internal enum SystemVersionItem {
/// iOS version
internal static let version = L10n.tr("Localizable", "supportData.systemVersionItem.version", fallback: "iOS version")
}
internal enum TimeItem {
/// Current time
internal static let time = L10n.tr("Localizable", "supportData.timeItem.time", fallback: "Current time")
}
}
internal enum Sync {
internal enum Message {
/// disconnected
internal static let disconnected = L10n.tr("Localizable", "sync.message.disconnected", fallback: "disconnected")
/// Enhancing tx
internal static let enhancing = L10n.tr("Localizable", "sync.message.enhancing", fallback: "Enhancing tx")
/// Error: %@
internal static func error(_ p1: Any) -> String {
return L10n.tr("Localizable", "sync.message.error", String(describing: p1), fallback: "Error: %@")
}
/// fetching UTXOs
internal static let fetchingUTXO = L10n.tr("Localizable", "sync.message.fetchingUTXO", fallback: "fetching UTXOs")
/// Stopped
internal static let stopped = L10n.tr("Localizable", "sync.message.stopped", fallback: "Stopped")
/// %@ Synced
internal static func sync(_ p1: Any) -> String {
return L10n.tr("Localizable", "sync.message.sync", String(describing: p1), fallback: "%@ Synced")
}
/// Unprepared
internal static let unprepared = L10n.tr("Localizable", "sync.message.unprepared", fallback: "Unprepared")
/// Up-To-Date
internal static let uptodate = L10n.tr("Localizable", "sync.message.uptodate", fallback: "Up-To-Date")
}
}
internal enum Transaction {
/// Confirmed
@ -308,6 +609,38 @@ internal enum L10n {
internal static let phraseAgain = L10n.tr("Localizable", "validationSuccess.button.phraseAgain", fallback: "Show me my phrase again")
}
}
internal enum WalletEvent {
internal enum Alert {
internal enum LeavingApp {
/// While usually an acceptable risk, you will possibly exposing your behavior and interest in this transaction by going online. OH NOES! What will you do?
internal static let message = L10n.tr("Localizable", "walletEvent.alert.leavingApp.message", fallback: "While usually an acceptable risk, you will possibly exposing your behavior and interest in this transaction by going online. OH NOES! What will you do?")
/// You are exiting your wallet
internal static let title = L10n.tr("Localizable", "walletEvent.alert.leavingApp.title", fallback: "You are exiting your wallet")
internal enum Button {
/// NEVERMIND
internal static let nevermind = L10n.tr("Localizable", "walletEvent.alert.leavingApp.button.nevermind", fallback: "NEVERMIND")
/// SEE TX ONLINE
internal static let seeOnline = L10n.tr("Localizable", "walletEvent.alert.leavingApp.button.seeOnline", fallback: "SEE TX ONLINE")
}
}
}
internal enum Detail {
/// wallet import wallet event
internal static let `import` = L10n.tr("Localizable", "walletEvent.detail.import", fallback: "wallet import wallet event")
/// shielded %@ detail
internal static func shielded(_ p1: Any) -> String {
return L10n.tr("Localizable", "walletEvent.detail.shielded", String(describing: p1), fallback: "shielded %@ detail")
}
}
internal enum Row {
/// wallet import wallet event
internal static let `import` = L10n.tr("Localizable", "walletEvent.row.import", fallback: "wallet import wallet event")
/// shielded wallet event %@
internal static func shielded(_ p1: Any) -> String {
return L10n.tr("Localizable", "walletEvent.row.shielded", String(describing: p1), fallback: "shielded wallet event %@")
}
}
}
internal enum WelcomeScreen {
/// Just Loading, one sec
internal static let subtitle = L10n.tr("Localizable", "welcomeScreen.subtitle", fallback: "Just Loading, one sec")

View File

@ -55,6 +55,11 @@
"importWallet.button.importPrivateKey" = "Import a private or viewing key";
"importWallet.birthday.description" = "Do you know the wallet's creation date? This will allow a faster sync. If you don't know the wallet's birthday, don't worry!";
"importWallet.birthday.placeholder" = "Enter birthday height";
"importWallet.seed.valid" = "VALID SEED PHRASE";
"importWallet.alert.success.title" = "Success";
"importWallet.alert.success.message" = "The wallet has been successfully recovered.";
"importWallet.alert.failed.title" = "Failed to restore wallet";
"importWallet.alert.failed.message" = "Error: %@";
// MARK: - Home Screen
"home.sendZec" = "Send ZEC";
@ -64,11 +69,15 @@
// MARK: - Receive ZEC (Formerly Profile Screen)
"receiveZec.yourAddress" = "Your Address";
"receiveZec.error.cantExtractUnifiedAddress" = "could not extract UA";
// MARK: - Address Details
"addressDetails.ua" = "Unified Address";
"addressDetails.sa" = "Sapling Address";
"addressDetails.ta" = "Transparent Address";
"addressDetails.error.cantExtractUnifiedAddress" = "could not extract UA";
"addressDetails.error.cantExtractTransparentAddress" = "could not extract transparent receiver from UA";
"addressDetails.error.cantExtractSaplingAddress" = "could not extract sapling receiver from UA";
// MARK: - Balance Breakdown
"balanceBreakdown.blockId" = "Block: %@";
@ -80,6 +89,8 @@
// MARK: - Scan
"scan.info" = "We will validate any Zcash URI and take you to the appropriate action.";
"scan.scanning" = "Scanning...";
"scan.alert.cantInitializeCamera.title" = "Can't initialize the camera";
"scan.alert.cantInitializeCamera.message" = "Error: %@";
// MARK: - Send
"send.title" = "Send Zcash";
@ -99,6 +110,20 @@
"settings.exportLogs" = "Export & share logs";
"settings.feedback" = "Send us feedback!";
"settings.title" = "Settings";
"settings.alert.cantBackupWallet.title" = "Can't backup wallet";
"settings.alert.cantBackupWallet.message" = "Error: %@";
"settings.alert.cantSendEmail.title" = "Can't send email";
"settings.alert.cantSendEmail.message" = "It looks like that you don't have any email account configured on your device. Therefore it's not possible to send a support email.";
// MARK: - Sync message
"sync.message.enhancing" = "Enhancing tx";
"sync.message.fetchingUTXO" = "fetching UTXOs";
"sync.message.disconnected" = "disconnected";
"sync.message.stopped" = "Stopped";
"sync.message.uptodate" = "Up-To-Date";
"sync.message.unprepared" = "Unprepared";
"sync.message.error" = "Error: %@";
"sync.message.sync" = "%@ Synced";
// MARK: - Transactions
"transactions.title" = "Transactions";
@ -134,7 +159,90 @@
"general.clear" = "Clear";
"general.close" = "Close";
"general.max" = "Max";
"general.ok" = "Ok";
"general.yes" = "Yes";
"general.no" = "No";
"general.cancel" = "Cancel";
"general.success" = "Success";
"general.unknown" = "Unknown";
"balance" = "%@ ZEC";
"balance.available" = "%@ ZEC Available";
"qrCodeFor" = "QR Code for %@";
"general.dateNotAvailable" = "date not available";
// MARK: - Wallet event
"walletEvent.row.shielded" = "shielded wallet event %@";
"walletEvent.row.import" = "wallet import wallet event";
"walletEvent.detail.shielded" = "shielded %@ detail";
"walletEvent.detail.import" = "wallet import wallet event";
"walletEvent.alert.leavingApp.title" = "You are exiting your wallet";
"walletEvent.alert.leavingApp.message" = "While usually an acceptable risk, you will possibly exposing your behavior and interest in this transaction by going online. OH NOES! What will you do?";
"walletEvent.alert.leavingApp.button.nevermind" = "NEVERMIND";
"walletEvent.alert.leavingApp.button.seeOnline" = "SEE TX ONLINE";
// MARK: - Local authentication
"localAuthentication.reason" = "The Following content requires authentication.";
// MARK: - Support Data
"supportData.timeItem.time" = "Current time";
"supportData.appVersionItem.bundleIdentifier" = "App identifier";
"supportData.appVersionItem.version" = "App version";
"supportData.systemVersionItem.version" = "iOS version";
"supportData.deviceModelItem.device" = "Device";
"supportData.localeItem.locale" = "Locale";
"supportData.localeItem.groupingSeparator" = "Currency grouping separator";
"supportData.localeItem.decimalSeparator" = "Currency decimal separator";
"supportData.freeDiskSpaceItem.freeDiskSpace" = "Usable storage";
"supportData.permissionItem.permissions" = "Permissions";
"supportData.permissionItem.camera" = "Camera access";
"supportData.permissionItem.faceID" = "FaceID available";
"supportData.permissionItem.touchID" = "TouchID available";
// MARK: - Root
"root.initialization.alert.failed.title" = "Wallet initialisation failed.";
"root.initialization.alert.error.message" = "Error: %@";
"root.initialization.alert.sdkInitFailed.title" = "Failed to initialize the SDK";
"root.initialization.alert.walletStateFailed.message" = "App initialisation state: %@.";
"root.initialization.alert.cantLoadSeedPhrase.message" = "Can't load seed phrase from local storage.";
"root.initialization.alert.cantCreateNewWallet.message" = "Can't create new wallet. Error: %@";
"root.initialization.alert.cantStoreThatUserPassedPhraseBackupTest.message" = "Can't store information that user passed phrase backup test. Error: %@";
"root.initialization.alert.wipe.title" = "Wipe of the wallet";
"root.initialization.alert.wipe.message" = "Are you sure?";
"root.initialization.alert.wipeFailed.title" = "Nuke of the wallet failed";
"root.destination.alert.failedToProcessDeeplink.title" = "Failed to process deeplink.";
"root.destination.alert.failedToProcessDeeplink.message" = "Deeplink: \(%@))\nError: \(%@)";
"root.debug.title" = "Debug options";
"root.debug.navigationTitle" = "Startup";
"root.debug.option.gotoSandbox" = "Go To Sandbox (navigation proof)";
"root.debug.option.gotoOnboarding" = "Go To Onboarding";
"root.debug.option.gotoPhraseValidationDemo" = "Go To Phrase Validation Demo";
"root.debug.option.restartApp" = "Restart the app";
"root.debug.option.testCrashReporter" = "Test Crash Reporter";
"root.debug.option.rescanBlockchain" = "Rescan Blockchain";
"root.debug.option.nukeWallet" = "[Be careful] Nuke Wallet";
"root.debug.option.exportLogs" = "Export logs";
"root.debug.featureFlags" = "Feature flags";
"root.debug.dialog.rescan.title" = "Rescan";
"root.debug.dialog.rescan.message" = "Select the rescan you want";
"root.debug.dialog.rescan.option.quick" = "Quick rescan";
"root.debug.dialog.rescan.option.full" = "Full rescan";
"root.debug.alert.rewind.failed.title" = "Rewind failed";
"root.debug.alert.rewind.failed.message" = "Error: %@";
"root.debug.alert.rewind.cantStartSync.title" = "Can't start sync process after rewind";
"root.debug.alert.rewind.cantStartSync.message" = "Error: %@";
"root.debug.error.rewind.sdkSynchronizerNotInitialized" = "SDKSynchronizer not initilized. rewindPublisher is nil";
// MARK: - Export logs
"exportLogs.alert.failed.title" = "Error when exporting logs";
"exportLogs.alert.failed.message" = "Error: %@";
// MARK: - Text Fields
"field.multiline.charLimitExceeded" = "char limit exceeded";
"field.transactionAddress.validZcashAddress" = "Valid Zcash Address";
"field.transactionAddress.to" = "To:";
"field.transactionAmount.zecAmount" = "ZEC Amount";
"field.transactionAmount.amount" = "Amount:";

View File

@ -36,7 +36,7 @@ struct MultiLineTextFieldReducer: ReducerProtocol {
charLimit > 0
? isValid
? "\(textLength)/\(charLimit)"
: "char limit exceeded \(textLength)/\(charLimit)"
: "\(L10n.Field.Multiline.charLimitExceeded) \(textLength)/\(charLimit)"
: ""
}
}

View File

@ -15,8 +15,8 @@ struct TransactionAddressTextField: View {
WithViewStore(store) { viewStore in
VStack {
SingleLineTextField(
placeholderText: "Valid Zcash Address",
title: "To:",
placeholderText: L10n.Field.TransactionAddress.validZcashAddress,
title: L10n.Field.TransactionAddress.to,
store: store.scope(
state: \.textFieldState,
action: TransactionAddressTextFieldReducer.Action.textField

View File

@ -14,8 +14,8 @@ struct TransactionAmountTextField: View {
var body: some View {
VStack {
SingleLineTextField(
placeholderText: "ZEC Amount",
title: "Amount:",
placeholderText: L10n.Field.TransactionAmount.zecAmount,
title: L10n.Field.TransactionAmount.amount,
store: store.scope(
state: \.textFieldState,
action: TransactionAmountTextFieldReducer.Action.textField