Merge pull request #1683 from omnivore-app/feature/launch-screen-language-support

Use Recently Added Chinese Strings
This commit is contained in:
Jackson Harper 2023-01-20 12:31:18 +08:00 committed by GitHub
commit 0b30092f7c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 210 additions and 172 deletions

View file

@ -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>";

View file

@ -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()
}
}

View file

@ -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()

View file

@ -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) {}
}
}
}

View file

@ -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,

View file

@ -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) }
)
}

View file

@ -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
}
}
}

View file

@ -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)

View file

@ -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) }
)
}

View file

@ -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) }
)
}
}

View file

@ -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) }
)
}

View file

@ -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 {

View file

@ -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) }
)
}
}

View file

@ -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)
}
}

View file

@ -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
}

View file

@ -91,6 +91,6 @@ struct PushNotificationSettingsView: View {
}
}
}
.navigationTitle("Push Notifications")
.navigationTitle(LocalText.pushNotificationsGeneric)
}
}

View file

@ -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 {

View file

@ -115,7 +115,7 @@ struct SubscriptionsView: View {
viewModel.subscriptionNameToCancel = nil
}
}
.navigationTitle("Subscriptions")
.navigationTitle(LocalText.subscriptionsGeneric)
}
}

View file

@ -18,7 +18,7 @@
}
innerBody
}
}.navigationTitle("Text to Speech")
}.navigationTitle(LocalText.textToSpeechGeneric)
}
private var innerBody: some View {

View file

@ -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)

View file

@ -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 })

View file

@ -72,7 +72,7 @@ struct WelcomeView: View {
Text("By signing up, you agree to Omnivores\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 }
}
}
}

View file

@ -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:

View file

@ -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:

View file

@ -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()

View file

@ -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,

View file

@ -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)

View file

@ -45,7 +45,7 @@ public struct FeaturePrimer: View {
Button(action: {
dismiss()
}, label: { Text("Dismiss") })
}, label: { Text(LocalText.dismissButton) })
.buttonStyle(PlainButtonStyle())
}.padding()
}

View file

@ -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() }
// )
// }
// }

View file

@ -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")
}

View file

@ -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";

View file

@ -1,2 +1 @@
"signInScreenHeadline" = "Empiece a guardar y compartir sus ideas.";
"googleSignInButton" = "Continuar con Google";

View file

@ -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" = "推送通知";

View file

@ -51,7 +51,7 @@ public struct SearchBar: View {
self.isFocused = false
},
label: {
Text("Cancel")
Text(LocalText.cancelGeneric)
}
)
.padding(.trailing, 10)

View file

@ -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 {

View file

@ -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." = "您当前没有任何订阅。"