diff --git a/apple/Omnivore.xcodeproj/project.pbxproj b/apple/Omnivore.xcodeproj/project.pbxproj index 0722253ee..8e89bd618 100644 --- a/apple/Omnivore.xcodeproj/project.pbxproj +++ b/apple/Omnivore.xcodeproj/project.pbxproj @@ -195,6 +195,7 @@ 046C5CD426A3F89A00AC5349 /* icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = icon.icns; sourceTree = ""; }; 046C5CDB26A3F89A00AC5349 /* ShareExtensionMac.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = ShareExtensionMac.plist; sourceTree = ""; }; 046C5CDC26A3F89A00AC5349 /* ShareExtensionMac.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareExtensionMac.entitlements; sourceTree = ""; }; + 047AA41F297A17FB00F0BEBF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = ""; }; 047AD6F52724CF8A004FD5CF /* SafariExtension (iOS).entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "SafariExtension (iOS).entitlements"; sourceTree = ""; }; 047AD6F62724E513004FD5CF /* SafariExtension (iOS)Release.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "SafariExtension (iOS)Release.entitlements"; sourceTree = ""; }; 0480E70B26D8A07A006CAE2F /* Omnivore-Mac.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = "Omnivore-Mac.xctestplan"; sourceTree = ""; }; @@ -834,6 +835,7 @@ knownRegions = ( Base, en, + "zh-Hans", ); mainGroup = 2EE5B57B588CF4ADBA39A106; packageReferences = ( @@ -1192,6 +1194,7 @@ children = ( 082449FB9F5F3730EE0D8D3F /* Base */, A25B2B310A2800932EECD5FD /* en */, + 047AA41F297A17FB00F0BEBF /* zh-Hans */, ); name = LaunchScreen.storyboard; sourceTree = ""; diff --git a/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift b/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift index 07073c409..c20993172 100644 --- a/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift +++ b/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift @@ -154,7 +154,7 @@ public struct ShareExtensionView: View { .padding(.trailing, 8) VStack { - Text("Labels") + Text(LocalText.labelsGeneric) .font(.appSubheadline) .foregroundColor(Color.appGrayTextContrast) .frame(maxWidth: .infinity, alignment: .leading) @@ -281,7 +281,7 @@ public struct ShareExtensionView: View { extensionContext?.completeRequest(returningItems: [], completionHandler: nil) }, label: { - Label("Read Later", systemImage: "text.book.closed.fill") + Label(LocalText.readLaterGeneric, systemImage: "text.book.closed.fill") .padding(16) .frame(maxWidth: .infinity, maxHeight: .infinity) } @@ -298,7 +298,7 @@ public struct ShareExtensionView: View { Button( action: {}, label: { - Button("Dismiss", role: .cancel, action: {}) + Button(LocalText.dismissButton, role: .cancel, action: {}) } ) Button(action: { @@ -346,7 +346,7 @@ public struct ShareExtensionView: View { case .editingTitle: return "Edit Title" case .editingLabels: - return "Labels" + return LocalText.labelsGeneric case .viewingHighlight: return "Highlight" default: @@ -378,7 +378,7 @@ public struct ShareExtensionView: View { } viewState = .mainView } - }, label: { Text("Cancel") }) + }, label: { Text(LocalText.cancelGeneric) }) .frame(maxWidth: .infinity, alignment: .leading) .opacity(viewState == .viewingHighlight ? 0.0 : 1.0) // Don't show viewState when viewing the highlight @@ -399,7 +399,7 @@ public struct ShareExtensionView: View { } } } - }, label: { Text("Done").bold() }) + }, label: { Text(LocalText.doneGeneric).bold() }) .frame(maxWidth: .infinity, alignment: .trailing) } .padding(8) @@ -546,7 +546,7 @@ struct ApplyLabelsListView: View { }, header: { - Text("Labels") + Text(LocalText.labelsGeneric) .font(.appFootnote) .foregroundColor(.appGrayText) } @@ -559,7 +559,7 @@ struct ApplyLabelsListView: View { label: { HStack { Image(systemName: "plus.circle.fill").foregroundColor(.green) - Text("Create a new Label").foregroundColor(.appGrayTextContrast) + Text(LocalText.createLabelMessage).foregroundColor(.appGrayTextContrast) Spacer() } } diff --git a/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/ExpandedPlayer.swift b/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/ExpandedPlayer.swift index 1a8e7fa09..1fde8a399 100644 --- a/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/ExpandedPlayer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/ExpandedPlayer.swift @@ -88,7 +88,7 @@ Button(action: { showVoiceSheet = true }, label: { Label("Change Voice", systemImage: "person.wave.2") }) Button(action: { viewArticle() }, label: { Label("View Article", systemImage: "book") }) Button(action: { audioController.stop() }, label: { Label("Stop", systemImage: "xmark.circle") }) - Button(action: { dismiss() }, label: { Label("Dismiss", systemImage: "arrow.down.to.line") }) + Button(action: { dismiss() }, label: { Label(LocalText.dismissButton, systemImage: "arrow.down.to.line") }) } label: { ZStack { Circle() @@ -348,7 +348,7 @@ .tint(.appGrayTextContrast) .alert("There was an error playing back your audio.", isPresented: $audioController.playbackError) { - Button("Dismiss", role: .none) {} + Button(LocalText.dismissButton, role: .none) {} } } else { EmptyView() diff --git a/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/MiniPlayer.swift b/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/MiniPlayer.swift index 9eb1082eb..a41eb61df 100644 --- a/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/MiniPlayer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/AudioPlayer/MiniPlayer.swift @@ -170,7 +170,7 @@ } }.alert("There was an error playing back your audio.", isPresented: $audioController.playbackError) { - Button("Dismiss", role: .none) {} + Button(LocalText.dismissButton, role: .none) {} } } } diff --git a/apple/OmnivoreKit/Sources/App/Views/Highlights/HighlightsListCard.swift b/apple/OmnivoreKit/Sources/App/Views/Highlights/HighlightsListCard.swift index fc1dfefca..189f1066a 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Highlights/HighlightsListCard.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Highlights/HighlightsListCard.swift @@ -38,7 +38,7 @@ struct HighlightsListCard: View { action: { onSetLabels(highlightParams.highlightID) }, - label: { Label("Labels", systemImage: "tag") } + label: { Label(LocalText.labelsGeneric, systemImage: "tag") } ) Button( action: onDeleteHighlight, diff --git a/apple/OmnivoreKit/Sources/App/Views/Highlights/HighlightsListView.swift b/apple/OmnivoreKit/Sources/App/Views/Highlights/HighlightsListView.swift index e732f7536..b0e5b8577 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Highlights/HighlightsListView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Highlights/HighlightsListView.swift @@ -84,7 +84,7 @@ struct HighlightsListView: View { var dismissButton: some View { Button( action: { presentationMode.wrappedValue.dismiss() }, - label: { Text("Done").foregroundColor(.appGrayTextContrast) } + label: { Text(LocalText.doneGeneric).foregroundColor(.appGrayTextContrast) } ) } diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift index 81d30a8e4..100e1eed5 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift @@ -419,7 +419,7 @@ import Views } self.itemToRemove = nil } - Button("Cancel", role: .cancel) { self.itemToRemove = nil } + Button(LocalText.cancelGeneric, role: .cancel) { self.itemToRemove = nil } } } } @@ -507,7 +507,7 @@ import Views } self.itemToRemove = nil } - Button("Cancel", role: .cancel) { self.itemToRemove = nil } + Button(LocalText.cancelGeneric, role: .cancel) { self.itemToRemove = nil } } } } @@ -559,3 +559,42 @@ struct LinkDestination: View { } } } + +// TODO: move everything below this to another file +extension LinkedItemFilter { + var displayName: String { + switch self { + case .inbox: + return LocalText.inboxGeneric + case .readlater: + return LocalText.readLaterGeneric + case .newsletters: + return LocalText.newslettersGeneric + case .recommended: + return "Recommended" + case .all: + return LocalText.allGeneric + case .archived: + return LocalText.archivedGeneric + case .hasHighlights: + return LocalText.highlightedGeneric + case .files: + return LocalText.filesGeneric + } + } +} + +public extension LinkedItemSort { + var displayName: String { + switch self { + case .newest: + return LocalText.newestGeneric + case .oldest: + return LocalText.oldestGeneric + case .recentlyRead: + return LocalText.recentlyReadGeneric + case .recentlyPublished: + return LocalText.recentlyPublishedGeneric + } + } +} diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewMac.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewMac.swift index 60d1c6098..5731ddde1 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewMac.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewMac.swift @@ -96,10 +96,10 @@ import Views placement: .toolbar ) { if viewModel.searchTerm.isEmpty { - Text("Inbox").searchCompletion("in:inbox ") - Text("All").searchCompletion("in:all ") - Text("Archived").searchCompletion("in:archive ") - Text("Files").searchCompletion("type:file ") + Text(LocalText.inboxGeneric).searchCompletion("in:inbox ") + Text(LocalText.allGeneric).searchCompletion("in:all ") + Text(LocalText.archivedGeneric).searchCompletion("in:archive ") + Text(LocalText.filesGeneric).searchCompletion("type:file ") } } .onChange(of: viewModel.searchTerm) { _ in @@ -137,7 +137,7 @@ import Views } } } - Button("Cancel", role: .cancel) { self.itemToRemove = nil } + Button(LocalText.cancelGeneric, role: .cancel) { self.itemToRemove = nil } } .sheet(item: $viewModel.itemUnderLabelEdit) { item in ApplyLabelsView(mode: .item(item), onSave: nil) diff --git a/apple/OmnivoreKit/Sources/App/Views/Labels/ApplyLabelsView.swift b/apple/OmnivoreKit/Sources/App/Views/Labels/ApplyLabelsView.swift index 84793a0fe..840933f9e 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Labels/ApplyLabelsView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Labels/ApplyLabelsView.swift @@ -47,7 +47,7 @@ struct ApplyLabelsView: View { label: { HStack { Image(systemName: "plus.circle.fill").foregroundColor(.green) - Text("Create a new Label").foregroundColor(.appGrayTextContrast) + Text(LocalText.createLabelMessage).foregroundColor(.appGrayTextContrast) Spacer() } } @@ -124,7 +124,7 @@ struct ApplyLabelsView: View { var cancelButton: some View { Button( action: { presentationMode.wrappedValue.dismiss() }, - label: { Text("Cancel").foregroundColor(.appGrayTextContrast) } + label: { Text(LocalText.cancelGeneric).foregroundColor(.appGrayTextContrast) } ) } diff --git a/apple/OmnivoreKit/Sources/App/Views/Labels/FilterByLabelsView.swift b/apple/OmnivoreKit/Sources/App/Views/Labels/FilterByLabelsView.swift index 3d2311041..3cd6d2d7f 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Labels/FilterByLabelsView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Labels/FilterByLabelsView.swift @@ -54,7 +54,7 @@ struct FilterByLabelsView: View { ToolbarItem(placement: .navigationBarLeading) { Button( action: { presentationMode.wrappedValue.dismiss() }, - label: { Text("Cancel").foregroundColor(.appGrayTextContrast) } + label: { Text(LocalText.cancelGeneric).foregroundColor(.appGrayTextContrast) } ) } ToolbarItem(placement: .navigationBarTrailing) { @@ -63,7 +63,7 @@ struct FilterByLabelsView: View { onSave?(viewModel.selectedLabels, viewModel.negatedLabels) presentationMode.wrappedValue.dismiss() }, - label: { Text("Done").foregroundColor(.appGrayTextContrast) } + label: { Text(LocalText.doneGeneric).foregroundColor(.appGrayTextContrast) } ) } } diff --git a/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsView.swift b/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsView.swift index 26b127f4c..c145391f1 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsView.swift @@ -10,8 +10,6 @@ struct LabelsView: View { @State private var showDeleteConfirmation = false @State private var labelToRemove: LinkedItemLabel? - let footerText = "Use labels to create curated collections of links." - var body: some View { Group { #if os(iOS) @@ -37,7 +35,7 @@ struct LabelsView: View { } self.labelToRemove = nil } - Button("Cancel", role: .cancel) { self.labelToRemove = nil } + Button(LocalText.cancelGeneric, role: .cancel) { self.labelToRemove = nil } } .sheet(isPresented: $viewModel.showCreateLabelModal) { CreateLabelView(viewModel: viewModel) @@ -47,13 +45,13 @@ struct LabelsView: View { private var innerBody: some View { Group { - Section(footer: Text(footerText)) { + Section(footer: Text(LocalText.labelsPurposeDescription)) { Button( action: { viewModel.showCreateLabelModal = true }, label: { HStack { Image(systemName: "plus.circle.fill").foregroundColor(.green) - Text("Create a new Label").foregroundColor(.appGrayTextContrast) + Text(LocalText.createLabelMessage).foregroundColor(.appGrayTextContrast) Spacer() } } @@ -62,7 +60,7 @@ struct LabelsView: View { } if !viewModel.labels.isEmpty { - Section(header: Text("Labels")) { + Section(header: Text(LocalText.labelsGeneric)) { ForEach(viewModel.labels, id: \.id) { label in HStack { TextChip(feedItemLabel: label) @@ -79,7 +77,7 @@ struct LabelsView: View { } } } - .navigationTitle("Labels") + .navigationTitle(LocalText.labelsGeneric) } } @@ -169,7 +167,7 @@ struct CreateLabelView: View { var cancelCreateLabelButton: some View { Button( action: { viewModel.showCreateLabelModal = false }, - label: { Text("Cancel").foregroundColor(.appGrayTextContrast) } + label: { Text(LocalText.cancelGeneric).foregroundColor(.appGrayTextContrast) } ) } diff --git a/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift b/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift index ea5576b93..5eeafbe4c 100644 --- a/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift @@ -184,7 +184,7 @@ struct LinkItemDetailView: View { Button("Remove Link", role: .destructive) { viewModel.handleDeleteAction(dataService: dataService) } - Button("Cancel", role: .cancel, action: {}) + Button(LocalText.cancelGeneric, role: .cancel, action: {}) } .sheet(isPresented: $showTitleEdit) { if let item = viewModel.item { diff --git a/apple/OmnivoreKit/Sources/App/Views/LinkedItemMetadataEditView.swift b/apple/OmnivoreKit/Sources/App/Views/LinkedItemMetadataEditView.swift index 821b8cf67..4af279429 100644 --- a/apple/OmnivoreKit/Sources/App/Views/LinkedItemMetadataEditView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/LinkedItemMetadataEditView.swift @@ -104,7 +104,7 @@ struct LinkedItemMetadataEditView: View { ToolbarItem(placement: .barLeading) { Button( action: { presentationMode.wrappedValue.dismiss() }, - label: { Text("Cancel").foregroundColor(.appGrayTextContrast) } + label: { Text(LocalText.cancelGeneric).foregroundColor(.appGrayTextContrast) } ) } } @@ -125,7 +125,7 @@ struct LinkedItemMetadataEditView: View { Button( action: { presentationMode.wrappedValue.dismiss() }, - label: { Text("Cancel").foregroundColor(.appGrayTextContrast) } + label: { Text(LocalText.cancelGeneric).foregroundColor(.appGrayTextContrast) } ) } } diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/NewsletterEmailsView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/NewsletterEmailsView.swift index a1b5c6932..ffd878a3a 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/NewsletterEmailsView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/NewsletterEmailsView.swift @@ -37,7 +37,6 @@ import Views struct NewsletterEmailsView: View { @EnvironmentObject var dataService: DataService @StateObject var viewModel = NewsletterEmailsViewModel() - let footerText = "Add PDFs to your library, or subscribe to newsletters using an Omnivore email address." var body: some View { Group { @@ -57,7 +56,7 @@ struct NewsletterEmailsView: View { private var innerBody: some View { Group { - Section(footer: Text(footerText)) { + Section(footer: Text(LocalText.newslettersDescription)) { Button( action: { Task { await viewModel.createEmail(dataService: dataService) } @@ -65,7 +64,7 @@ struct NewsletterEmailsView: View { label: { HStack { Image(systemName: "plus.circle.fill").foregroundColor(.green) - Text("Create a new email address") + Text(LocalText.createNewEmailMessage) Spacer() } } @@ -96,6 +95,6 @@ struct NewsletterEmailsView: View { } } } - .navigationTitle("Emails") + .navigationTitle(LocalText.emailsGeneric) } } diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift index b36aa81bc..57620e2fe 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift @@ -79,19 +79,19 @@ struct ProfileView: View { private var accountSection: some View { Section { NavigationLink(destination: LabelsView()) { - Text("Labels") + Text(LocalText.labelsGeneric) } NavigationLink(destination: NewsletterEmailsView()) { - Text("Emails") + Text(LocalText.emailsGeneric) } NavigationLink(destination: SubscriptionsView()) { - Text("Subscriptions") + Text(LocalText.subscriptionsGeneric) } NavigationLink(destination: GroupsView()) { - Text("Clubs") + Text(LocalText.clubsGeneric) } } } @@ -110,10 +110,10 @@ struct ProfileView: View { #if os(iOS) Section { NavigationLink(destination: PushNotificationSettingsView()) { - Text("Push Notifications") + Text(LocalText.pushNotificationsGeneric) } NavigationLink(destination: TextToSpeechView()) { - Text("Text to Speech") + Text(LocalText.textToSpeechGeneric) } } #endif @@ -122,19 +122,19 @@ struct ProfileView: View { NavigationLink( destination: BasicWebAppView.privacyPolicyWebView(baseURL: dataService.appEnvironment.webAppBaseURL) ) { - Text("Privacy Policy") + Text(LocalText.privacyPolicyGeneric) } NavigationLink( destination: BasicWebAppView.termsConditionsWebView(baseURL: dataService.appEnvironment.webAppBaseURL) ) { - Text("Terms and Conditions") + Text(LocalText.termsAndConditionsGeneric) } #if os(iOS) Button( action: { DataService.showIntercomMessenger?() }, - label: { Text("Feedback") } + label: { Text(LocalText.feedbackGeneric) } ) #endif } @@ -143,10 +143,10 @@ struct ProfileView: View { NavigationLink( destination: ManageAccountView() ) { - Text("Manage Account") + Text(LocalText.manageAccountGeneric) } - Text("Logout") + Text(LocalText.logoutGeneric) .onTapGesture { showLogoutConfirmation = true } diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/PushNotificationSettingsView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/PushNotificationSettingsView.swift index 8cbd83784..afd361772 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/PushNotificationSettingsView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/PushNotificationSettingsView.swift @@ -91,6 +91,6 @@ struct PushNotificationSettingsView: View { } } } - .navigationTitle("Push Notifications") + .navigationTitle(LocalText.pushNotificationsGeneric) } } diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupsView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupsView.swift index f6703e15a..0df891584 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupsView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupsView.swift @@ -104,7 +104,7 @@ struct CreateRecommendationGroupView: View { .navigationBarItems(leading: Button(action: { viewModel.showCreateSheet = false - }, label: { Text("Cancel") }), + }, label: { Text(LocalText.cancelGeneric) }), trailing: nextButton) } } @@ -132,7 +132,7 @@ struct GroupsView: View { } } .task { await viewModel.loadGroups(dataService: dataService) } - .navigationTitle("Clubs") + .navigationTitle(LocalText.clubsGeneric) } private var innerBody: some View { diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/Subscriptions.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/Subscriptions.swift index 9fa414f79..28faec9e0 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/Subscriptions.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/Subscriptions.swift @@ -115,7 +115,7 @@ struct SubscriptionsView: View { viewModel.subscriptionNameToCancel = nil } } - .navigationTitle("Subscriptions") + .navigationTitle(LocalText.subscriptionsGeneric) } } diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/TextToSpeechView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/TextToSpeechView.swift index 5a27786c4..3aad4e53c 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/TextToSpeechView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/TextToSpeechView.swift @@ -18,7 +18,7 @@ } innerBody } - }.navigationTitle("Text to Speech") + }.navigationTitle(LocalText.textToSpeechGeneric) } private var innerBody: some View { diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/RecommendToView.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/RecommendToView.swift index 6236ee7ce..80ecc315a 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/RecommendToView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/RecommendToView.swift @@ -211,7 +211,7 @@ struct RecommendToView: View { .navigationViewStyle(.stack) .navigationBarItems(leading: Button(action: { dismiss() - }, label: { Text("Cancel") }), + }, label: { Text(LocalText.cancelGeneric) }), trailing: nextButton) .task { await viewModel.loadGroups(dataService: dataService) diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift index fea5ddbc9..649a20a9b 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift @@ -292,7 +292,7 @@ struct WebReaderContainerView: View { presentationMode.wrappedValue.dismiss() #endif } - Button("Cancel", role: .cancel, action: {}) + Button(LocalText.cancelGeneric, role: .cancel, action: {}) } .sheet(isPresented: $showLabelsModal) { ApplyLabelsView(mode: .item(item), onSave: { _ in showLabelsModal = false }) diff --git a/apple/OmnivoreKit/Sources/App/Views/WelcomeView.swift b/apple/OmnivoreKit/Sources/App/Views/WelcomeView.swift index ab9362812..bc366d2be 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WelcomeView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WelcomeView.swift @@ -72,7 +72,7 @@ struct WelcomeView: View { Text("By signing up, you agree to Omnivore’s\n") + Text("Terms of Service").underline() + Text(" and ") - + Text("Privacy Policy").underline() + + Text(LocalText.privacyPolicyGeneric).underline() } .font(.appSubheadline) .confirmationDialog("", isPresented: $showTermsLinks, titleVisibility: .hidden) { @@ -247,7 +247,7 @@ struct WelcomeView: View { Button("View Details") { openURL(URL(string: "https://support.apple.com/en-us/HT210426")!) } - Button("Dismiss") { self.authenticator.showAppleRevokeTokenAlert = false } + Button(LocalText.dismissButton) { self.authenticator.showAppleRevokeTokenAlert = false } } } } diff --git a/apple/OmnivoreKit/Sources/Models/LinkedItemFilter.swift b/apple/OmnivoreKit/Sources/Models/LinkedItemFilter.swift index 7a3bbc261..f066432a5 100644 --- a/apple/OmnivoreKit/Sources/Models/LinkedItemFilter.swift +++ b/apple/OmnivoreKit/Sources/Models/LinkedItemFilter.swift @@ -12,27 +12,6 @@ public enum LinkedItemFilter: String, CaseIterable { } public extension LinkedItemFilter { - var displayName: String { - switch self { - case .inbox: - return "Inbox" - case .readlater: - return "Read Later" - case .newsletters: - return "Newsletters" - case .recommended: - return "Recommended" - case .all: - return "All" - case .archived: - return "Archived" - case .hasHighlights: - return "Highlighted" - case .files: - return "Files" - } - } - var queryString: String { switch self { case .inbox: diff --git a/apple/OmnivoreKit/Sources/Models/LinkedItemSort.swift b/apple/OmnivoreKit/Sources/Models/LinkedItemSort.swift index 7e060955b..706e6833e 100644 --- a/apple/OmnivoreKit/Sources/Models/LinkedItemSort.swift +++ b/apple/OmnivoreKit/Sources/Models/LinkedItemSort.swift @@ -8,19 +8,6 @@ public enum LinkedItemSort: String, CaseIterable { } public extension LinkedItemSort { - var displayName: String { - switch self { - case .newest: - return "Newest" - case .oldest: - return "Oldest" - case .recentlyRead: - return "Recently Read" - case .recentlyPublished: - return "Recently Published" - } - } - var queryString: String { switch self { case .newest: diff --git a/apple/OmnivoreKit/Sources/Views/Article/HighlightAnnotationSheet.swift b/apple/OmnivoreKit/Sources/Views/Article/HighlightAnnotationSheet.swift index c461327be..d82246b50 100644 --- a/apple/OmnivoreKit/Sources/Views/Article/HighlightAnnotationSheet.swift +++ b/apple/OmnivoreKit/Sources/Views/Article/HighlightAnnotationSheet.swift @@ -26,7 +26,7 @@ public struct HighlightAnnotationSheet: View { public var body: some View { VStack { HStack { - Button("Cancel", action: onCancel) + Button(LocalText.cancelGeneric, action: onCancel) Spacer() Label("Note", systemImage: "note.text") Spacer() diff --git a/apple/OmnivoreKit/Sources/Views/Article/OmnivoreWebView.swift b/apple/OmnivoreKit/Sources/Views/Article/OmnivoreWebView.swift index b0a0b1002..9ed8d876b 100644 --- a/apple/OmnivoreKit/Sources/Views/Article/OmnivoreWebView.swift +++ b/apple/OmnivoreKit/Sources/Views/Article/OmnivoreWebView.swift @@ -208,7 +208,7 @@ public final class OmnivoreWebView: WKWebView { // on iOS16 we use menuBuilder to create these items currentMenu = .defaultMenu let annotate = UIMenuItem(title: "Annotate", action: #selector(annotateSelection)) - let labels = UIMenuItem(title: "Labels", action: #selector(setLabels)) + let labels = UIMenuItem(title: LocalText.labelsGeneric, action: #selector(setLabels)) let remove = UIMenuItem(title: "Remove", action: #selector(removeSelection)) // let share = UIMenuItem(title: "Share", action: #selector(shareSelection)) @@ -309,7 +309,7 @@ public final class OmnivoreWebView: WKWebView { let annotate = UICommand(title: "Note", action: #selector(annotateSelection)) let highlight = UICommand(title: "Highlight", action: #selector(highlightSelection)) let remove = UICommand(title: "Remove", action: #selector(removeSelection)) - let setLabels = UICommand(title: "Labels", action: #selector(setLabels)) + let setLabels = UICommand(title: LocalText.labelsGeneric, action: #selector(setLabels)) let omnivore = UIMenu(title: "", options: .displayInline, diff --git a/apple/OmnivoreKit/Sources/Views/CommunityModal.swift b/apple/OmnivoreKit/Sources/Views/CommunityModal.swift index 71f904ad4..9198a93c7 100644 --- a/apple/OmnivoreKit/Sources/Views/CommunityModal.swift +++ b/apple/OmnivoreKit/Sources/Views/CommunityModal.swift @@ -115,7 +115,7 @@ public struct CommunityModal: View { Button(action: { dismiss() - }, label: { Text("Dismiss") }) + }, label: { Text(LocalText.dismissButton) }) .buttonStyle(PlainButtonStyle()) .padding(.bottom, 16) .frame(alignment: .bottom) diff --git a/apple/OmnivoreKit/Sources/Views/FeaturePrimer.swift b/apple/OmnivoreKit/Sources/Views/FeaturePrimer.swift index c5575f4c1..fe91e170c 100644 --- a/apple/OmnivoreKit/Sources/Views/FeaturePrimer.swift +++ b/apple/OmnivoreKit/Sources/Views/FeaturePrimer.swift @@ -45,7 +45,7 @@ public struct FeaturePrimer: View { Button(action: { dismiss() - }, label: { Text("Dismiss") }) + }, label: { Text(LocalText.dismissButton) }) .buttonStyle(PlainButtonStyle()) }.padding() } diff --git a/apple/OmnivoreKit/Sources/Views/FontSizeAdjustmentPopoverView.swift b/apple/OmnivoreKit/Sources/Views/FontSizeAdjustmentPopoverView.swift index 94ddb23cd..e690cac9c 100644 --- a/apple/OmnivoreKit/Sources/Views/FontSizeAdjustmentPopoverView.swift +++ b/apple/OmnivoreKit/Sources/Views/FontSizeAdjustmentPopoverView.swift @@ -201,7 +201,7 @@ public enum WebFont: String, CaseIterable { // ToolbarItem(placement: .barTrailing) { // Button( // action: dismissAction, -// label: { Text("Done").foregroundColor(.appGrayTextContrast).padding() } +// label: { Text(LocalText.doneGeneric).foregroundColor(.appGrayTextContrast).padding() } // ) // } // } diff --git a/apple/OmnivoreKit/Sources/Views/LocalText.swift b/apple/OmnivoreKit/Sources/Views/LocalText.swift index 9b9b3b17f..daed0b979 100644 --- a/apple/OmnivoreKit/Sources/Views/LocalText.swift +++ b/apple/OmnivoreKit/Sources/Views/LocalText.swift @@ -1,23 +1,47 @@ import Foundation public enum LocalText { - static func localText(key: String, comment: String? = nil) -> String { + public static func localText(key: String, comment: String? = nil) -> String { NSLocalizedString(key, bundle: .module, comment: comment ?? "no comment provided by developer") } - static let signInScreenHeadline = localText(key: "signInScreenHeadline") - static let googleAuthButton = localText(key: "googleAuthButton") - static let registrationViewSignInHeadline = localText(key: "registrationViewSignInHeadline") - static let registrationViewSignUpHeadline = localText(key: "registrationViewSignUpHeadline") - public static let registrationViewHeadline = localText(key: "registrationViewHeadline") + public static let googleAuthButton = localText(key: "googleAuthButton") public static let networkError = localText(key: "error.network") + public static let registrationViewSignUpHeadline = localText(key: "registrationViewSignUpHeadline") public static let genericError = localText(key: "error.generic") - static let invalidCredsLoginError = localText(key: "loginError.invalidCreds") + public static let invalidCredsLoginError = localText(key: "loginError.invalidCreds") public static let saveArticleSavedState = localText(key: "saveArticleSavedState") public static let saveArticleProcessingState = localText(key: "saveArticleProcessingState") public static let extensionAppUnauthorized = localText(key: "extensionAppUnauthorized") - static let dismissButton = localText(key: "dismissButton") - static let usernameValidationErrorInvalid = localText(key: "username.validation.error.invalidPattern") - static let usernameValidationErrorTooShort = localText(key: "username.validation.error.tooshort") - static let usernameValidationErrorTooLong = localText(key: "username.validation.error.toolong") + public static let dismissButton = localText(key: "dismissButton") + + public static let labelsGeneric = localText(key: "labels.generic") + public static let emailsGeneric = localText(key: "emails.generic") + public static let subscriptionsGeneric = localText(key: "subscriptions.generic") + public static let textToSpeechGeneric = localText(key: "textToSpeech.generic") + public static let privacyPolicyGeneric = localText(key: "privacy.policy.generic") + public static let termsAndConditionsGeneric = localText(key: "termsAndConditions.generic") + public static let feedbackGeneric = localText(key: "feedback.generic") + public static let manageAccountGeneric = localText(key: "manageAccount.generic") + public static let logoutGeneric = localText(key: "logout.generic") + public static let doneGeneric = localText(key: "done.generic") + public static let cancelGeneric = localText(key: "cancel.generic") + public static let inboxGeneric = localText(key: "inbox.generic") + public static let readLaterGeneric = localText(key: "readLater.generic") + public static let newslettersGeneric = localText(key: "newsletters.generic") + public static let allGeneric = localText(key: "all.generic") + public static let archivedGeneric = localText(key: "archived.generic") + public static let highlightedGeneric = localText(key: "highlighted.generic") + public static let filesGeneric = localText(key: "files.generic") + public static let newestGeneric = localText(key: "newest.generic") + public static let oldestGeneric = localText(key: "oldest.generic") + public static let recentlyReadGeneric = localText(key: "recentlyRead.generic") + public static let recentlyPublishedGeneric = localText(key: "recentlyPublished.generic") + public static let createLabelMessage = localText(key: "create.label.message") + public static let createNewEmailMessage = localText(key: "create.new.email.message") + public static let newslettersDescription = localText(key: "newsletters.description") + public static let labelsPurposeDescription = localText(key: "labels.purpose.description") + public static let noCurrentSubscriptionsMessage = localText(key: "no.current.subscriptions.message") + public static let clubsGeneric = localText(key: "clubs.generic") + public static let pushNotificationsGeneric = localText(key: "pushNotifications.generic") } diff --git a/apple/OmnivoreKit/Sources/Views/Resources/en.lproj/Localizable.strings b/apple/OmnivoreKit/Sources/Views/Resources/en.lproj/Localizable.strings index 3c8569321..37a7901c1 100644 --- a/apple/OmnivoreKit/Sources/Views/Resources/en.lproj/Localizable.strings +++ b/apple/OmnivoreKit/Sources/Views/Resources/en.lproj/Localizable.strings @@ -1,16 +1,39 @@ -"signInScreenHeadline" = "Save and share the best of the web."; "googleAuthButton" = "Continue with Google"; -"registrationViewSignInHeadline" = "Login"; "registrationViewSignUpHeadline" = "Sign Up"; -"registrationViewHeadline" = "Welcome"; -"username.validation.error.invalidPattern" = "Username can only contain letters, numbers, and underscores in the middle."; -"username.validation.error.tooshort" = "Username should contain at least three characters."; -"username.validation.error.toolong" = "Username cannot be longer than fifteen characters."; "error.network" = "We are having trouble connecting to the internet."; "error.generic" = "Something went wrong, please try again."; "extensionAppUnauthorized" = "Please login to Omnivore from the app before saving your first link."; "loginError.invalidCreds" = "The login credentials provided are invalid."; -"saveArticleSavingState" = "Saving..."; "saveArticleSavedState" = "Saved to Omnivore"; "saveArticleProcessingState" = "Saved to Omnivore"; "dismissButton" = "Dismiss"; + +"labels.generic" = "Labels"; +"emails.generic" = "Emails"; +"subscriptions.generic" = "Text to Speech"; +"textToSpeech.generic" = "Subscriptions"; +"privacy.policy.generic" = "Privacy Policy"; +"termsAndConditions.generic" = "Terms and Conditions"; +"feedback.generic" = "Feedback"; +"manageAccount.generic" = "Manage Account"; +"logout.generic" = "Logout"; +"done.generic" = "Done"; +"cancel.generic" = "Cancel"; +"inbox.generic" = "Inbox"; +"readLater.generic" = "Read Later"; +"newsletters.generic" = "Newsletters"; +"all.generic" = "All"; +"archived.generic" = "Archived"; +"highlighted.generic" = "Highlighted"; +"files.generic" = "Files"; +"newest.generic" = "Newest"; +"oldest.generic" = "Oldest"; +"recentlyRead.generic" = "Recently Read"; +"recentlyPublished.generic" = "Recently Published"; +"create.label.message" = "Create a new Label"; +"create.new.email.message" = "Create a new email address"; +"newsletters.description" = "Add PDFs to your library, or subscribe to newsletters using an Omnivore email address."; +"labels.purpose.description" = "Use labels to create curated collections of links."; +"no.current.subscriptions.message" = "You have no current Subscriptions."; +"clubs.generic" = "Clubs"; +"pushNotifications.generic" = "Push Notifications"; diff --git a/apple/OmnivoreKit/Sources/Views/Resources/es.lproj/Localizable.strings b/apple/OmnivoreKit/Sources/Views/Resources/es.lproj/Localizable.strings index 77cfe3fef..211e0e6ca 100644 --- a/apple/OmnivoreKit/Sources/Views/Resources/es.lproj/Localizable.strings +++ b/apple/OmnivoreKit/Sources/Views/Resources/es.lproj/Localizable.strings @@ -1,2 +1 @@ -"signInScreenHeadline" = "Empiece a guardar y compartir sus ideas."; "googleSignInButton" = "Continuar con Google"; diff --git a/apple/OmnivoreKit/Sources/Views/Resources/zh-Hans.lproj/Localizable.strings b/apple/OmnivoreKit/Sources/Views/Resources/zh-Hans.lproj/Localizable.strings new file mode 100644 index 000000000..5cce13d03 --- /dev/null +++ b/apple/OmnivoreKit/Sources/Views/Resources/zh-Hans.lproj/Localizable.strings @@ -0,0 +1,39 @@ +"googleAuthButton" = "Continue with Google"; +"registrationViewSignUpHeadline" = "Sign Up"; +"error.network" = "We are having trouble connecting to the internet."; +"error.generic" = "Something went wrong, please try again."; +"extensionAppUnauthorized" = "Please login to Omnivore from the app before saving your first link."; +"loginError.invalidCreds" = "The login credentials provided are invalid."; +"saveArticleSavedState" = "Saved to Omnivore"; +"saveArticleProcessingState" = "Saved to Omnivore"; +"dismissButton" = "Dismiss"; + +"labels.generic" = "标签"; +"emails.generic" = "电子邮件"; +"subscriptions.generic" = "订阅"; +"textToSpeech.generic" = "文本转语音"; +"privacy.policy.generic" = "隐私策略"; +"termsAndConditions.generic" = "条款与条件"; +"feedback.generic" = "反馈"; +"manageAccount.generic" = "管理帐户"; +"logout.generic" = "退出登陆"; +"done.generic" = "完成"; +"cancel.generic" = "取消"; +"inbox.generic" = "收集箱"; +"readLater.generic" = "稍后阅读"; +"newsletters.generic" = "新闻稿件"; +"all.generic" = "全部"; +"archived.generic" = "存档"; +"highlighted.generic" = "高亮"; +"files.generic" = "文件"; +"newest.generic" = "最新"; +"oldest.generic" = "最早"; +"recentlyRead.generic" = "最近阅读"; +"recentlyPublished.generic" = "最近发布"; +"create.label.message" = "创建新标签"; +"create.new.email.message" = "创建新的电子邮件地址"; +"newsletters.description" = "将 PDF 添加到您的资料库,或使用 Omnivore 电子邮件地址订阅新闻稿件。"; +"labels.purpose.description" = "使用标签创建精选的链接集合。"; +"no.current.subscriptions.message" = "您当前没有任何订阅。"; +"clubs.generic" = "读书俱乐部"; +"pushNotifications.generic" = "推送通知"; diff --git a/apple/OmnivoreKit/Sources/Views/SearchBar.swift b/apple/OmnivoreKit/Sources/Views/SearchBar.swift index be32bc3d1..e66fc9587 100644 --- a/apple/OmnivoreKit/Sources/Views/SearchBar.swift +++ b/apple/OmnivoreKit/Sources/Views/SearchBar.swift @@ -51,7 +51,7 @@ public struct SearchBar: View { self.isFocused = false }, label: { - Text("Cancel") + Text(LocalText.cancelGeneric) } ) .padding(.trailing, 10) diff --git a/apple/OmnivoreKit/Sources/Views/TextChip.swift b/apple/OmnivoreKit/Sources/Views/TextChip.swift index eeac92cda..b8a540af9 100644 --- a/apple/OmnivoreKit/Sources/Views/TextChip.swift +++ b/apple/OmnivoreKit/Sources/Views/TextChip.swift @@ -106,7 +106,7 @@ public struct TextChip: View { public struct TextChipButton: View { public static func makeAddLabelButton(onTap: @escaping () -> Void) -> TextChipButton { - TextChipButton(title: "Labels", color: .systemGray6, actionType: .show, negated: false, onTap: onTap) + TextChipButton(title: LocalText.labelsGeneric, color: .systemGray6, actionType: .show, negated: false, onTap: onTap) } public static func makeMenuButton(title: String) -> TextChipButton { diff --git a/apple/Resources/zh-Hans.lproj/LaunchScreen.strings b/apple/Resources/zh-Hans.lproj/LaunchScreen.strings index 0ca6e5830..8b1378917 100644 --- a/apple/Resources/zh-Hans.lproj/LaunchScreen.strings +++ b/apple/Resources/zh-Hans.lproj/LaunchScreen.strings @@ -1,53 +1 @@ -"Labels" = "标签" -"Emails" = "电子邮件" - -"Subscriptions" = "订阅" - -"Text to Speech" = "文本转语音" - -"Privacy Policy" = "隐私策略" - -"Terms and Conditions" = "条款与条件" - -"Feedback" = "反馈" - -"Manage Account" = "管理帐户" - -"Logout" = "退出登陆" - -"Done" = "完成" - -"Cancel" = "取消" - -"Inbox" = "收集箱" - -"Read Later" = "稍后阅读" - -"Newsletters" = "新闻稿件" - -"All" = "全部" - -"Archived" = "存档" - -"Highlighted" = "高亮" - -"Files" = "文件" - -"Newest" = "最新" - -"Oldest" = "最早" - -"Recently Read" = "最近阅读" - -"Recently Published" = "最近发布" - -"Create a new Label" = "创建新标签" - -"Create a new email address" = "创建新的电子邮件地址" - -"Add PDFs to your library, or subscribe to newsletters using an Omnivore email address." = "将 PDF 添加到您的资料库,或使用 Omnivore 电子邮件地址订阅新闻稿件。" - -"Use labels to create curated collections of links." = "使用标签创建精选的链接集合。" - -"You have no current Subscriptions." = "您当前没有任何订阅。"