mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Merge pull request #1683 from omnivore-app/feature/launch-screen-language-support
Use Recently Added Chinese Strings
This commit is contained in:
commit
0b30092f7c
36 changed files with 210 additions and 172 deletions
|
|
@ -195,6 +195,7 @@
|
|||
046C5CD426A3F89A00AC5349 /* icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = icon.icns; sourceTree = "<group>"; };
|
||||
046C5CDB26A3F89A00AC5349 /* ShareExtensionMac.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = ShareExtensionMac.plist; sourceTree = "<group>"; };
|
||||
046C5CDC26A3F89A00AC5349 /* ShareExtensionMac.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareExtensionMac.entitlements; sourceTree = "<group>"; };
|
||||
047AA41F297A17FB00F0BEBF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = "<group>"; };
|
||||
047AD6F52724CF8A004FD5CF /* SafariExtension (iOS).entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "SafariExtension (iOS).entitlements"; sourceTree = "<group>"; };
|
||||
047AD6F62724E513004FD5CF /* SafariExtension (iOS)Release.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "SafariExtension (iOS)Release.entitlements"; sourceTree = "<group>"; };
|
||||
0480E70B26D8A07A006CAE2F /* Omnivore-Mac.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = "Omnivore-Mac.xctestplan"; sourceTree = "<group>"; };
|
||||
|
|
@ -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 = "<group>";
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,6 +91,6 @@ struct PushNotificationSettingsView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Push Notifications")
|
||||
.navigationTitle(LocalText.pushNotificationsGeneric)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ struct SubscriptionsView: View {
|
|||
viewModel.subscriptionNameToCancel = nil
|
||||
}
|
||||
}
|
||||
.navigationTitle("Subscriptions")
|
||||
.navigationTitle(LocalText.subscriptionsGeneric)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
}
|
||||
innerBody
|
||||
}
|
||||
}.navigationTitle("Text to Speech")
|
||||
}.navigationTitle(LocalText.textToSpeechGeneric)
|
||||
}
|
||||
|
||||
private var innerBody: some View {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 })
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public struct FeaturePrimer: View {
|
|||
|
||||
Button(action: {
|
||||
dismiss()
|
||||
}, label: { Text("Dismiss") })
|
||||
}, label: { Text(LocalText.dismissButton) })
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
}.padding()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -1,2 +1 @@
|
|||
"signInScreenHeadline" = "Empiece a guardar y compartir sus ideas.";
|
||||
"googleSignInButton" = "Continuar con Google";
|
||||
|
|
|
|||
|
|
@ -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" = "推送通知";
|
||||
|
|
@ -51,7 +51,7 @@ public struct SearchBar: View {
|
|||
self.isFocused = false
|
||||
},
|
||||
label: {
|
||||
Text("Cancel")
|
||||
Text(LocalText.cancelGeneric)
|
||||
}
|
||||
)
|
||||
.padding(.trailing, 10)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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." = "您当前没有任何订阅。"
|
||||
|
|
|
|||
Loading…
Reference in a new issue