Merge pull request #3811 from stuartbreckenridge/localize_strings

Internationalize NetNewsWire
This commit is contained in:
Brent Simmons
2023-05-27 12:54:30 -07:00
committed by GitHub
168 changed files with 5756 additions and 966 deletions

View File

@@ -26,6 +26,7 @@ dependencies.append(contentsOf: [
let package = Package(
name: "Account",
defaultLocalization: "en",
platforms: [.macOS(SupportedPlatform.MacOSVersion.v11), .iOS(SupportedPlatform.IOSVersion.v14)],
products: [
.library(

View File

@@ -32,21 +32,34 @@ public enum AccountError: LocalizedError {
}
return false
}
public var errorTitle: String {
switch self {
case .createErrorNotFound:
return NSLocalizedString("error.title.feed-not-found", bundle: Bundle.module, comment: "Unable to Add Feed")
case .createErrorAlreadySubscribed:
return NSLocalizedString("error.title.already-subscribed", bundle: Bundle.module, comment: "Already Subscribed")
case .opmlImportInProgress:
return NSLocalizedString("error.title.ompl-import-in-progress", bundle: Bundle.module, comment: "OPML Import in Progress")
case .wrappedError(_, _):
return NSLocalizedString("error.title.error", bundle: Bundle.module, comment: "Error")
}
}
public var errorDescription: String? {
switch self {
case .createErrorNotFound:
return NSLocalizedString("The feed couldnt be found and cant be added.", comment: "Not found")
return NSLocalizedString("error.message.feed-not-found", bundle: Bundle.module, comment: "Cant add a feed because no feed was found.")
case .createErrorAlreadySubscribed:
return NSLocalizedString("You are already subscribed to this feed and cant add it again.", comment: "Already subscribed")
return NSLocalizedString("error.message.feed-already-subscribed", bundle: Bundle.module, comment: "You are already subscribed to this feed and cant add it again.")
case .opmlImportInProgress:
return NSLocalizedString("An OPML import for this account is already running.", comment: "Import running")
return NSLocalizedString("error.message.opml-import-in-progress", bundle: Bundle.module, comment: "An OPML import for this account is already running.")
case .wrappedError(let error, let account):
switch error {
case TransportError.httpError(let status):
if isCredentialsError(status: status) {
let localizedText = NSLocalizedString("Your “%@” credentials are invalid or expired.", comment: "Invalid or expired")
return NSString.localizedStringWithFormat(localizedText as NSString, account.nameForDisplay) as String
let localizedText = NSLocalizedString("error.message.credentials-expired.%@", bundle: Bundle.module, comment: "Your ”%@” credentials have expired.")
return String(format: localizedText, account.nameForDisplay)
} else {
return unknownError(error, account)
}

View File

@@ -0,0 +1,16 @@
/*
Localizable.strings
Created by Stuart Breckenridge on 11/03/2023.
*/
"error.title.feed-not-found" = "Unable to Add Feed";
"error.title.already-subscribed" = "Already Subscribed";
"error.title.ompl-import-in-progress" = "OPML Import in Progress";
"error.title.error" = "Error";
"error.message.feed-not-found" = "Cant add a feed because no feed was found.";
"error.message.already-subscribed" = "You are already subscribed to this feed and cant add it again.";
"error.message.opml-import-in-progress" = "An OPML import for this account is already running.";

View File

@@ -0,0 +1,16 @@
/*
Localizable.strings
Created by Stuart Breckenridge on 11/03/2023.
*/
"error.title.feed-not-found" = "Unable to Add Feed";
"error.title.already-subscribed" = "Already Subscribed";
"error.title.ompl-import-in-progress" = "OPML Import in Progress";
"error.title.error" = "Error";
"error.message.feed-not-found" = "Cant add a feed because no feed was found.";
"error.message.already-subscribed" = "You are already subscribed to this feed and cant add it again.";
"error.message.opml-import-in-progress" = "An OPML import for this account is already running.";

View File

@@ -179,7 +179,7 @@ struct AppAssets {
}()
static var privacyPolicyLink: NSAttributedString = {
return NSAttributedString(linkText: NSLocalizedString("Privacy Policy", comment: "Privacy Policy"), linkURL: URL(string: "https://netnewswire.com/privacypolicy")!)
return NSAttributedString(linkText: NSLocalizedString("label.text.privacy-policy", comment: "Privacy Policy"), linkURL: URL(string: "https://netnewswire.com/privacypolicy")!)
}()
static var readClosedImage: RSImage = {

View File

@@ -353,13 +353,13 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
if let decodingError = error as? DecodingError {
switch decodingError {
case .typeMismatch(let type, _):
let localizedError = NSLocalizedString("This theme cannot be used because the the type—“%@”—is mismatched in the Info.plist", comment: "Type mismatch")
let localizedError = NSLocalizedString("alert.error.theme-type-mismatch.%@", comment: "This theme cannot be used because the the type—“%@”—is mismatched in the Info.plist")
informativeText = NSString.localizedStringWithFormat(localizedError as NSString, type as! CVarArg) as String
case .valueNotFound(let value, _):
let localizedError = NSLocalizedString("This theme cannot be used because the the value—“%@”—is not found in the Info.plist.", comment: "Decoding value missing")
let localizedError = NSLocalizedString("alert.error.theme-value-missing.%@", comment: "This theme cannot be used because the the value—“%@”—is not found in the Info.plist.")
informativeText = NSString.localizedStringWithFormat(localizedError as NSString, value as! CVarArg) as String
case .keyNotFound(let codingKey, _):
let localizedError = NSLocalizedString("This theme cannot be used because the the key—“%@”—is not found in the Info.plist.", comment: "Decoding key missing")
let localizedError = NSLocalizedString("alert.error.theme-key-not-found.%@", comment: "This theme cannot be used because the the key—“%@”—is not found in the Info.plist.")
informativeText = NSString.localizedStringWithFormat(localizedError as NSString, codingKey.stringValue) as String
case .dataCorrupted(let context):
guard let underlyingError = context.underlyingError as NSError?,
@@ -367,7 +367,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
informativeText = error.localizedDescription
break
}
let localizedError = NSLocalizedString("This theme cannot be used because of data corruption in the Info.plist: %@.", comment: "Decoding key missing")
let localizedError = NSLocalizedString("alert.error.theme-data-corruption.%@", comment: "This theme cannot be used because of data corruption in the Info.plist: %@.")
informativeText = NSString.localizedStringWithFormat(localizedError as NSString, debugDescription) as String
default:
@@ -380,10 +380,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
DispatchQueue.main.async {
let alert = NSAlert()
alert.alertStyle = .warning
alert.messageText = NSLocalizedString("Theme Error", comment: "Theme error")
alert.messageText = NSLocalizedString("alert.title.theme-error", comment: "Theme error")
alert.informativeText = informativeText
alert.addButton(withTitle: NSLocalizedString("OK", comment: "OK"))
alert.addButton(withTitle: NSLocalizedString("button.title.ok", comment: "OK"))
alert.buttons[0].keyEquivalent = "\r"
_ = alert.runModal()
@@ -608,8 +608,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
@MainActor @IBAction func showKeyboardShortcutsWindow(_ sender: Any?) {
if keyboardShortcutsWindowController == nil {
keyboardShortcutsWindowController = WebViewWindowController(title: NSLocalizedString("Keyboard Shortcuts", comment: "window title"))
keyboardShortcutsWindowController = WebViewWindowController(title: NSLocalizedString("window.title.keyboard-shortcuts", comment: "Keyboard Shortcuts"))
let htmlFile = Bundle(for: type(of: self)).path(forResource: "KeyboardShortcuts", ofType: "html")!
keyboardShortcutsWindowController?.displayContents(of: htmlFile)
@@ -775,11 +775,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
@IBAction func debugClearImageCaches(_ sender: Any?) {
let alert = NSAlert()
alert.alertStyle = .warning
alert.messageText = NSLocalizedString("Are you sure you want to clear the image caches? This will restart NetNewsWire to begin reloading the remote images.",
comment: "Clear and restart confirmation message.")
alert.addButton(withTitle: NSLocalizedString("Clear & Restart", comment: "Clear & Restart"))
alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "Cancel"))
alert.messageText = NSLocalizedString("alert.message.clear-image-cache-confirmation",
comment: "Are you sure you want to clear the image caches? This will restart NetNewsWire to begin reloading the remote images.")
alert.addButton(withTitle: NSLocalizedString("button.title.clear-and-restart", comment: "Clear & Restart"))
alert.addButton(withTitle: NSLocalizedString("button.title.cancel", comment: "Cancel"))
let userChoice = alert.runModal()
if userChoice == .alertFirstButtonReturn {
CacheCleaner.purge()
@@ -872,7 +872,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
let alert = NSAlert()
alert.alertStyle = .informational
let localizedMessageText = NSLocalizedString("Install theme “%@” by %@?", comment: "Theme message text")
let localizedMessageText = NSLocalizedString("alert.title.install-theme.%@.%@", comment: "Install theme “%@” by %@? — the order of the variables is theme name, author name")
alert.messageText = NSString.localizedStringWithFormat(localizedMessageText as NSString, theme.name, theme.creatorName) as String
var attrs = [NSAttributedString.Key : Any]()
@@ -884,7 +884,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
attrs[.paragraphStyle] = titleParagraphStyle
let websiteText = NSMutableAttributedString()
websiteText.append(NSAttributedString(string: NSLocalizedString("Authors website:", comment: "Author's Website"), attributes: attrs))
websiteText.append(NSAttributedString(string: NSLocalizedString("alert.title.authors-website", comment: "Author's website:"), attributes: attrs))
websiteText.append(NSAttributedString(string: "\n"))
@@ -899,10 +899,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
textView.drawsBackground = false
textView.textStorage?.setAttributedString(websiteText)
alert.accessoryView = textView
alert.addButton(withTitle: NSLocalizedString("Install Theme", comment: "Install Theme"))
alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "Cancel Install Theme"))
alert.addButton(withTitle: NSLocalizedString("button.title.install-theme", comment: "Install Theme"))
alert.addButton(withTitle: NSLocalizedString("button.title.cancel", comment: "Cancel Install Theme"))
func importTheme() {
do {
try ArticleThemesManager.shared.importTheme(filename: filename)
@@ -920,12 +920,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
let alert = NSAlert()
alert.alertStyle = .warning
let localizedMessageText = NSLocalizedString("The theme “%@” already exists. Overwrite it?", comment: "Overwrite theme")
let localizedMessageText = NSLocalizedString("alert.message.duplicate-theme.%@", comment: "The theme “%@” already exists. Overwrite it?")
alert.messageText = NSString.localizedStringWithFormat(localizedMessageText as NSString, theme.name) as String
alert.addButton(withTitle: NSLocalizedString("Overwrite", comment: "Overwrite"))
alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "Cancel Install Theme"))
alert.addButton(withTitle: NSLocalizedString("button.title.overwrite", comment: "Overwrite"))
alert.addButton(withTitle: NSLocalizedString("button.title.cancel", comment: "Cancel Install Theme"))
alert.beginSheetModal(for: window) { result in
if result == NSApplication.ModalResponse.alertFirstButtonReturn {
importTheme()
@@ -946,12 +946,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
let alert = NSAlert()
alert.alertStyle = .informational
alert.messageText = NSLocalizedString("Theme installed", comment: "Theme installed")
let localizedInformativeText = NSLocalizedString("The theme “%@” has been installed.", comment: "Theme installed")
alert.messageText = NSLocalizedString("alert.title.theme-installed", comment: "Theme installed")
let localizedInformativeText = NSLocalizedString("alert.message.theme-installed.%@", comment: "The theme “%@” has been installed.")
alert.informativeText = NSString.localizedStringWithFormat(localizedInformativeText as NSString, themeName) as String
alert.addButton(withTitle: NSLocalizedString("OK", comment: "OK"))
alert.addButton(withTitle: NSLocalizedString("button.title.ok", comment: "OK"))
alert.beginSheetModal(for: window)
}
@@ -975,9 +975,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations,
DispatchQueue.main.async {
let alert = NSAlert()
alert.alertStyle = .warning
alert.messageText = NSLocalizedString("Twitter Integration Removed", comment: "Twitter Integration Removed")
alert.informativeText = NSLocalizedString("Twitter has ended free access to the parts of the Twitter API that we need.\n\nSince Twitter does not provide RSS feeds, weve had to use the Twitter API. Without free access to that API, we cant read feeds from Twitter.\n\nWeve left your Twitter feeds intact. If you have any starred items from those feeds, they will remain as long as you dont delete those feeds.\n\nYou can still read whatever you have already downloaded. However, those feeds will no longer update.", comment: "Twitter deprecation informative text.")
alert.addButton(withTitle: NSLocalizedString("OK", comment: "OK"))
alert.messageText = NSLocalizedString("alert.title.twitter-integration-removed", comment: "Twitter Integration Removed")
alert.informativeText = NSLocalizedString("alert.message.twitter-integration-removed", comment: "Twitter deprecation informative text.")
alert.addButton(withTitle: NSLocalizedString("button.title.ok", comment: "OK"))
alert.buttons[0].keyEquivalent = "\r"
alert.runModal()
}

View File

@@ -36,7 +36,7 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView horizontalHuggingPriority="1000" verticalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="Ut3-yd-q6G">
<rect key="frame" x="54" y="16" width="399" height="329"/>
<rect key="frame" x="54" y="16" width="400" height="306"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="pR2-Bf-7Fd">
<rect key="frame" x="6" y="267" width="105" height="16"/>
@@ -109,7 +109,7 @@
</connections>
</button>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="Tdg-6Y-gvW">
<rect key="frame" x="0.0" y="181" width="399" height="5"/>
<rect key="frame" x="0.0" y="197" width="400" height="5"/>
</box>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Wsb-Lr-8Q7">
<rect key="frame" x="53" y="154" width="58" height="16"/>
@@ -163,7 +163,7 @@
</textFieldCell>
</textField>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="hQy-ng-ijd">
<rect key="frame" x="0.0" y="34" width="399" height="5"/>
<rect key="frame" x="0.0" y="38" width="400" height="5"/>
</box>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ucw-vG-yLt">
<rect key="frame" x="16" y="7" width="95" height="16"/>
@@ -527,16 +527,16 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="7UM-iq-OLB" customClass="PreferencesTableViewBackgroundView" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="20" y="44" width="180" height="217"/>
<rect key="frame" x="20" y="44" width="180" height="215"/>
<subviews>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="PaF-du-r3c">
<rect key="frame" x="1" y="1" width="178" height="215"/>
<rect key="frame" x="1" y="1" width="178" height="213"/>
<clipView key="contentView" id="cil-Gq-akO">
<rect key="frame" x="0.0" y="0.0" width="178" height="215"/>
<rect key="frame" x="0.0" y="0.0" width="178" height="213"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" tableStyle="fullWidth" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" viewBased="YES" id="aTp-KR-y6b">
<rect key="frame" x="0.0" y="0.0" width="178" height="215"/>
<rect key="frame" x="0.0" y="0.0" width="178" height="213"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@@ -643,7 +643,7 @@
<rect key="frame" x="83" y="20" width="117" height="24"/>
</customView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Y7D-xQ-wep">
<rect key="frame" x="208" y="20" width="222" height="241"/>
<rect key="frame" x="208" y="20" width="222" height="239"/>
</customView>
</subviews>
<constraints>
@@ -698,16 +698,16 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="pjs-G4-byk" customClass="PreferencesTableViewBackgroundView" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="20" y="44" width="180" height="217"/>
<rect key="frame" x="20" y="44" width="180" height="215"/>
<subviews>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="29T-r2-ckC">
<rect key="frame" x="1" y="1" width="178" height="215"/>
<rect key="frame" x="1" y="1" width="178" height="213"/>
<clipView key="contentView" id="dXw-GY-TP8">
<rect key="frame" x="0.0" y="0.0" width="178" height="215"/>
<rect key="frame" x="0.0" y="0.0" width="178" height="213"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" tableStyle="fullWidth" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" viewBased="YES" id="dfn-Vn-oDp">
<rect key="frame" x="0.0" y="0.0" width="178" height="215"/>
<rect key="frame" x="0.0" y="0.0" width="178" height="213"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@@ -810,7 +810,7 @@
<rect key="frame" x="83" y="20" width="117" height="24"/>
</customView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="N1N-pE-gBL">
<rect key="frame" x="208" y="20" width="222" height="241"/>
<rect key="frame" x="208" y="20" width="222" height="239"/>
</customView>
</subviews>
<constraints>

View File

@@ -69,8 +69,8 @@ extension Browser {
let openInBackgroundPref = AppDefaults.shared.openInBrowserInBackground
return openInBackgroundPref ?
NSLocalizedString("Open in Browser in Foreground", comment: "Open in Browser in Foreground menu item title") :
NSLocalizedString("Open in Browser in Background", comment: "Open in Browser in Background menu item title")
NSLocalizedString("button.title.open-in-foreground", comment: "Open in Browser in Foreground") :
NSLocalizedString("button.title.open-in-background", comment: "Open in Browser in Background")
}
}
@@ -95,11 +95,11 @@ extension Browser {
if urlStrings.count > 20 {
let alert = NSAlert()
let messageFormat = NSLocalizedString("Are you sure you want to open %ld articles in your browser?", comment: "Open in Browser confirmation alert message format")
let messageFormat = NSLocalizedString("alert.title.open-articles-in-browser.%ld", comment: "Are you sure you want to open %ld articles in your browser?")
alert.messageText = String.localizedStringWithFormat(messageFormat, urlStrings.count)
let confirmButtonTitleFormat = NSLocalizedString("Open %ld Articles", comment: "Open URLs in Browser confirm button format")
let confirmButtonTitleFormat = NSLocalizedString("button.title.open-articles.%ld", comment: "Open %ld Articles")
alert.addButton(withTitle: String.localizedStringWithFormat(confirmButtonTitleFormat, urlStrings.count))
alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "Cancel button"))
alert.addButton(withTitle: NSLocalizedString("button.title.cancel", comment: "Cancel button"))
if let window {
alert.beginSheetModal(for: window) { response in

View File

@@ -27,7 +27,7 @@ import AppKit
updateSmartFeed()
}
}
var windowTitle: String = NSLocalizedString("Smart Feed Inspector", comment: "Smart Feed Inspector window title")
var windowTitle: String = NSLocalizedString("window.title.smart-feed-inspector", comment: "Smart Feed Inspector")
func canInspect(_ objects: [Any]) -> Bool {
@@ -63,7 +63,7 @@ private extension BuiltinSmartFeedInspectorViewController {
func updateUI() {
nameTextField?.stringValue = smartFeed?.nameForDisplay ?? ""
windowTitle = smartFeed?.nameForDisplay ?? NSLocalizedString("Smart Feed Inspector", comment: "Smart Feed Inspector window title")
windowTitle = smartFeed?.nameForDisplay ?? NSLocalizedString("window.title.smart-feed-inspector", comment: "Smart Feed Inspector")
smartFeedImageView?.image = smartFeed?.smallIcon?.image
}
}

View File

@@ -32,7 +32,7 @@ import RSCore
updateFolder()
}
}
var windowTitle: String = NSLocalizedString("Folder Inspector", comment: "Folder Inspector window title")
var windowTitle: String = NSLocalizedString("window.title.folder-inspector", comment: "Folder Inspector")
func canInspect(_ objects: [Any]) -> Bool {
@@ -102,7 +102,7 @@ private extension FolderInspectorViewController {
if nameTextField.stringValue != name {
nameTextField.stringValue = name
}
windowTitle = folder?.nameForDisplay ?? NSLocalizedString("Folder Inspector", comment: "Folder Inspector window title")
windowTitle = folder?.nameForDisplay ?? NSLocalizedString("window.title.folder-inspector", comment: "Folder Inspector")
}
func renameFolderIfNecessary() {

View File

@@ -19,7 +19,7 @@ import AppKit
updateTextFields()
}
}
var windowTitle: String = NSLocalizedString("Inspector", comment: "Inspector window title")
var windowTitle: String = NSLocalizedString("window.title.inspector", comment: "Inspector")
func canInspect(_ objects: [Any]) -> Bool {

View File

@@ -39,7 +39,7 @@ import UserNotifications
updateFeed()
}
}
var windowTitle: String = NSLocalizedString("Feed Inspector", comment: "Feed Inspector window title")
var windowTitle: String = NSLocalizedString("window.title.feed-inspector", comment: "Feed Inspector")
func canInspect(_ objects: [Any]) -> Bool {
return objects.count == 1 && objects.first is WebFeed
@@ -138,7 +138,7 @@ private extension WebFeedInspectorViewController {
updateFeedURL()
updateNotifyAboutNewArticles()
updateIsReaderViewAlwaysOn()
windowTitle = feed?.nameForDisplay ?? NSLocalizedString("Feed Inspector", comment: "Feed Inspector window title")
windowTitle = feed?.nameForDisplay ?? NSLocalizedString("window.title.feed-inspector", comment: "Feed Inspector")
view.needsLayout = true
if let webfeed = feed {
webfeed.isFeedProvider ? (isReaderViewAlwaysOnCheckBox?.isEnabled = false) : (isReaderViewAlwaysOnCheckBox?.isEnabled = true)
@@ -172,7 +172,7 @@ private extension WebFeedInspectorViewController {
}
func updateNotifyAboutNewArticles() {
isNotifyAboutNewArticlesCheckBox?.title = feed?.notificationDisplayName ?? NSLocalizedString("Show notifications for new articles", comment: "Show notifications for new articles")
isNotifyAboutNewArticlesCheckBox?.title = feed?.notificationDisplayName ?? NSLocalizedString("checkbox.title.show-new-article-notifications", comment: "Show notifications for new articles")
isNotifyAboutNewArticlesCheckBox?.state = (feed?.isNotifyAboutNewArticles ?? false) ? .on : .off
}
@@ -194,10 +194,10 @@ private extension WebFeedInspectorViewController {
func showNotificationsDeniedError() {
let updateAlert = NSAlert()
updateAlert.alertStyle = .informational
updateAlert.messageText = NSLocalizedString("Enable Notifications", comment: "Notifications")
updateAlert.informativeText = NSLocalizedString("To enable notifications, open Notifications in System Preferences, then find NetNewsWire in the list.", comment: "To enable notifications, open Notifications in System Preferences, then find NetNewsWire in the list.")
updateAlert.addButton(withTitle: NSLocalizedString("Open System Preferences", comment: "Open System Preferences"))
updateAlert.addButton(withTitle: NSLocalizedString("Close", comment: "Close"))
updateAlert.messageText = NSLocalizedString("alert.title.enable-notifications", comment: "Enable Notifications")
updateAlert.informativeText = NSLocalizedString("alert.message.enable-notifications-in-system-settings", comment: "To enable notifications, open Notifications in System Settings, then find NetNewsWire in the list.")
updateAlert.addButton(withTitle: NSLocalizedString("button.title.open-system-settings", comment: "Open System Settings"))
updateAlert.addButton(withTitle: NSLocalizedString("button.title.close", comment: "Close"))
let modalResponse = updateAlert.runModal()
if modalResponse == .alertFirstButtonReturn {
NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.notifications")!)

View File

@@ -20,17 +20,17 @@ struct AboutNetNewsWireView: View {
.resizable()
.frame(width: 75, height: 75)
Text("NetNewsWire")
Text(verbatim: "NetNewsWire")
.font(.headline)
Text("\(Bundle.main.versionNumber) (\(Bundle.main.buildNumber))")
.foregroundColor(.secondary)
.font(.callout)
Text("By Brent Simmons and the NetNewsWire team.")
Text("label.text.netnewswire-byline", comment: "By Brent Simmons and the NetNewsWire team.")
.font(.subheadline)
Text("[netnewswire.com](https://netnewswire.com)")
Text("label.markdown.netnewswire-website", comment: "Markdown formatted link to netnewswire.com")
.font(.callout)
Spacer()

View File

@@ -136,17 +136,17 @@ private extension AddFeedController {
func showAlreadySubscribedError(_ urlString: String) {
let alert = NSAlert()
alert.alertStyle = .informational
alert.messageText = NSLocalizedString("Already subscribed", comment: "Feed finder")
alert.informativeText = NSLocalizedString("Cant add this feed because youve already subscribed to it.", comment: "Feed finder")
alert.messageText = AccountError.createErrorAlreadySubscribed.errorTitle
alert.informativeText = AccountError.createErrorAlreadySubscribed.localizedDescription
alert.beginSheetModal(for: hostWindow)
}
func showInitialDownloadError(_ error: Error) {
let alert = NSAlert()
alert.alertStyle = .informational
alert.messageText = NSLocalizedString("Download Error", comment: "Feed finder")
alert.messageText = NSLocalizedString("alert.title.download-error", comment: "Download Error")
let formatString = NSLocalizedString("Cant add this feed because of a download error: “%@", comment: "Feed finder")
let formatString = NSLocalizedString("alert.message.download-error.%@", comment: "Cant add this feed because of a download error: “%@”")
let errorText = NSString.localizedStringWithFormat(formatString as NSString, error.localizedDescription)
alert.informativeText = errorText as String
alert.beginSheetModal(for: hostWindow)
@@ -155,15 +155,15 @@ private extension AddFeedController {
func showNoFeedsErrorMessage() {
let alert = NSAlert()
alert.alertStyle = .informational
alert.messageText = NSLocalizedString("Feed not found", comment: "Feed finder")
alert.informativeText = NSLocalizedString("Cant add a feed because no feed was found.", comment: "Feed finder")
alert.messageText = AccountError.createErrorNotFound.errorTitle
alert.informativeText = AccountError.createErrorNotFound.localizedDescription
alert.beginSheetModal(for: hostWindow)
}
// MARK: Progress
func beginShowingProgress() {
runIndeterminateProgressWithMessage(NSLocalizedString("Finding feed", comment:"Feed finder"))
runIndeterminateProgressWithMessage(NSLocalizedString("label.text.finding-feed", comment:"Finding feed..."))
}
func endShowingProgress() {

View File

@@ -148,7 +148,7 @@ private extension AddRedditFeedWindowController {
animateShowHideFields(collapsed: false) {
self.accountLabel.isHidden = false
self.accountPopupButton.isHidden = false
self.typeDescriptionLabel.stringValue = NSLocalizedString("Your personal Reddit frontpage", comment: "Home")
self.typeDescriptionLabel.stringValue = NSLocalizedString("label.text.reddit-front-page", comment: "Your personal Reddit frontpage")
self.subredditTextField.isHidden = true
self.addButton.isEnabled = true
}
@@ -157,7 +157,7 @@ private extension AddRedditFeedWindowController {
accountLabel.isHidden = true
accountPopupButton.isHidden = true
typeDescriptionLabel.stringValue = NSLocalizedString("The best posts on Reddit for you", comment: "Popular")
typeDescriptionLabel.stringValue = NSLocalizedString("label.text.reddit-best-posts", comment: "The best posts on Reddit for you")
subredditTextField.isHidden = true
addButton.isEnabled = true
animateShowHideFields(collapsed: true)
@@ -166,7 +166,7 @@ private extension AddRedditFeedWindowController {
accountLabel.isHidden = true
accountPopupButton.isHidden = true
typeDescriptionLabel.stringValue = NSLocalizedString("The most active posts", comment: "All")
typeDescriptionLabel.stringValue = NSLocalizedString("label.text.reddit-active-posts", comment: "The most active posts")
subredditTextField.isHidden = true
addButton.isEnabled = true
animateShowHideFields(collapsed: true)
@@ -178,12 +178,13 @@ private extension AddRedditFeedWindowController {
self.accountPopupButton.isHidden = true
if !self.subredditTextField.stringValue.isEmpty {
self.typeDescriptionLabel.stringValue = NSLocalizedString("Posts from r/\(self.subredditTextField.stringValue)", comment: "Subreddit")
let subreddit = NSLocalizedString("label.text.posts-from-subreddit.%@", comment: "Posts from r/%@")
self.typeDescriptionLabel.stringValue = String(format: subreddit, self.subredditTextField.stringValue)
} else {
self.typeDescriptionLabel.stringValue = ""
}
self.subredditTextField.placeholderString = NSLocalizedString("Subreddit", comment: "Search Term")
self.subredditTextField.placeholderString = NSLocalizedString("label.text.subreddit", comment: "Subreddit")
self.subredditTextField.isHidden = false
self.addButton.isEnabled = !self.subredditTextField.stringValue.isEmpty
}

View File

@@ -45,13 +45,13 @@ enum ArticleExtractorButtonState {
override func accessibilityLabel() -> String? {
switch buttonState {
case .error:
return NSLocalizedString("Error - Reader View", comment: "Error - Reader View")
return NSLocalizedString("label.text.error-reader-view", comment: "Error - Reader View")
case .animated:
return NSLocalizedString("Processing - Reader View", comment: "Processing - Reader View")
return NSLocalizedString("label.text.processing-reader-view", comment: "Processing - Reader View")
case .on:
return NSLocalizedString("Selected - Reader View", comment: "Selected - Reader View")
return NSLocalizedString("label.text.selected-reader-view", comment: "Selected - Reader View")
case .off:
return NSLocalizedString("Reader View", comment: "Reader View")
return NSLocalizedString("label.text.reader-view", comment: "Reader View")
}
}

View File

@@ -15,7 +15,7 @@ import RSCore
weak var keyboardDelegate: KeyboardDelegate?
override func accessibilityLabel() -> String? {
return NSLocalizedString("Article", comment: "Article")
return NSLocalizedString("label.text.article", comment: "Article")
}
// MARK: - NSResponder

View File

@@ -207,7 +207,7 @@ enum TimelineSourceMode {
let canCopyArticleURL = canCopyArticleURL()
if let item = item as? NSMenuItem {
let format = NSLocalizedString("Copy Article URL", comment: "Copy Article URL");
let format = NSLocalizedString("button.title.copy-article-url", comment: "Copy Article URL");
item.title = String.localizedStringWithFormat(format, selectedArticles?.count ?? 0)
}
@@ -290,7 +290,7 @@ enum TimelineSourceMode {
let sidebarIsShowing = !splitViewItem.isCollapsed
if let menuItem = item as? NSMenuItem {
let title = sidebarIsShowing ? NSLocalizedString("Hide Sidebar", comment: "Menu item") : NSLocalizedString("Show Sidebar", comment: "Menu item")
let title = sidebarIsShowing ? NSLocalizedString("button.title.hide-sidebar", comment: "Hide Sidebar") : NSLocalizedString("button.title.show-sidebar", comment: "Show Sidebar")
menuItem.title = title
}
@@ -581,7 +581,7 @@ enum TimelineSourceMode {
let menu = NSMenu()
let alwaysUseReaderViewItem = NSMenuItem()
alwaysUseReaderViewItem.title = NSLocalizedString("Always Use Reader View", comment: "Always Use Reader View")
alwaysUseReaderViewItem.title = NSLocalizedString("button.title.always-use-reader-view", comment: "Always Use Reader View")
alwaysUseReaderViewItem.target = self
alwaysUseReaderViewItem.action = #selector(alwaysUseReaderView)
alwaysUseReaderViewItem.state = {
@@ -852,57 +852,57 @@ extension MainWindowController: NSToolbarDelegate {
switch itemIdentifier {
case .sidebarToggle:
let title = NSLocalizedString("Toggle Sidebar", comment: "Toggle Sidebar")
let title = NSLocalizedString("button.title.toggle-sidebar", comment: "Toggle Sidebar")
return buildToolbarButton(.toggleSidebar, title, AppAssets.sidebarToggleImage, "toggleTheSidebar:")
case .refresh:
let title = NSLocalizedString("Refresh", comment: "Refresh")
let title = NSLocalizedString("button.title.refresh", comment: "Refresh")
return buildToolbarButton(.refresh, title, AppAssets.refreshImage, "refreshAll:")
case .newSidebarItemMenu:
let toolbarItem = NSMenuToolbarItem(itemIdentifier: .newSidebarItemMenu)
toolbarItem.image = AppAssets.addNewSidebarItemImage
let description = NSLocalizedString("Add Item", comment: "Add Item")
let description = NSLocalizedString("button.title.add-item", comment: "Add Item")
toolbarItem.toolTip = description
toolbarItem.label = description
toolbarItem.menu = buildNewSidebarItemMenu()
return toolbarItem
case .markAllAsRead:
let title = NSLocalizedString("Mark All as Read", comment: "Mark All as Read")
let title = NSLocalizedString("button.title.mark-all-as-read.titlecase", comment: "Mark All as Read")
return buildToolbarButton(.markAllAsRead, title, AppAssets.markAllAsReadImage, "markAllAsRead:")
case .markAboveAsRead:
let title = NSLocalizedString("Mark Above as Read", comment: "Mark Above as Read")
let title = NSLocalizedString("button.title.mark-above-as-read.titlecase", comment: "Mark Above as Read")
return buildToolbarButton(.markAboveAsRead, title, AppAssets.markAboveAsReadImage, "markAboveAsRead:")
case .markBelowAsRead:
let title = NSLocalizedString("Mark Below as Read", comment: "Mark Below as Read")
let title = NSLocalizedString("button.title.mark-below-as-read.titlecase", comment: "Mark Below as Read")
return buildToolbarButton(.markBelowAsRead, title, AppAssets.markBelowAsReadImage, "markBelowAsRead:")
case .toggleReadArticlesFilter:
let title = NSLocalizedString("Read Articles Filter", comment: "Read Articles Filter")
let title = NSLocalizedString("button.title.read-articles-filter", comment: "Read Articles Filter")
return buildToolbarButton(.toggleReadArticlesFilter, title, AppAssets.filterInactive, "toggleReadArticlesFilter:")
case .timelineTrackingSeparator:
return NSTrackingSeparatorToolbarItem(identifier: .timelineTrackingSeparator, splitView: splitViewController!.splitView, dividerIndex: 1)
case .markRead:
let title = NSLocalizedString("Mark Read", comment: "Mark Read")
let title = NSLocalizedString("button.title.mark-read", comment: "Mark Read")
return buildToolbarButton(.markRead, title, AppAssets.readClosedImage, "toggleRead:")
case .markStar:
let title = NSLocalizedString("Star", comment: "Star")
let title = NSLocalizedString("button.title.mark-star", comment: "Star")
return buildToolbarButton(.markStar, title, AppAssets.starOpenImage, "toggleStarred:")
case .nextUnread:
let title = NSLocalizedString("Next Unread", comment: "Next Unread")
let title = NSLocalizedString("button.title.next-read", comment: "Next Unread")
return buildToolbarButton(.nextUnread, title, AppAssets.nextUnreadImage, "nextUnread:")
case .readerView:
let toolbarItem = RSToolbarItem(itemIdentifier: .readerView)
toolbarItem.autovalidates = true
let description = NSLocalizedString("Reader View", comment: "Reader View")
let description = NSLocalizedString("button.title.reader-view", comment: "Reader View")
toolbarItem.toolTip = description
toolbarItem.label = description
let button = ArticleExtractorButton()
@@ -914,7 +914,7 @@ extension MainWindowController: NSToolbarDelegate {
return toolbarItem
case .share:
let title = NSLocalizedString("Share", comment: "Share")
let title = NSLocalizedString("button.title.share", comment: "Share")
let image = AppAssets.shareImage
if #available(macOS 13.0, *) {
// `item.view` is required for properly positioning the sharing picker.
@@ -929,25 +929,25 @@ extension MainWindowController: NSToolbarDelegate {
}
case .openInBrowser:
let title = NSLocalizedString("Open in Browser", comment: "Open in Browser")
let title = NSLocalizedString("button.title.open-in-browser", comment: "Open in Browser")
return buildToolbarButton(.openInBrowser, title, AppAssets.openInBrowserImage, "openArticleInBrowser:")
case .articleThemeMenu:
articleThemeMenuToolbarItem.image = AppAssets.articleTheme
let description = NSLocalizedString("Article Theme", comment: "Article Theme")
let description = NSLocalizedString("button.title.article-theme", comment: "Article Theme")
articleThemeMenuToolbarItem.toolTip = description
articleThemeMenuToolbarItem.label = description
return articleThemeMenuToolbarItem
case .search:
let toolbarItem = NSSearchToolbarItem(itemIdentifier: .search)
let description = NSLocalizedString("Search", comment: "Search")
let description = NSLocalizedString("button.title.search", comment: "Search")
toolbarItem.toolTip = description
toolbarItem.label = description
return toolbarItem
case .cleanUp:
let title = NSLocalizedString("Clean Up", comment: "Clean Up")
let title = NSLocalizedString("button.title.clean-up", comment: "Clean Up")
return buildToolbarButton(.cleanUp, title, AppAssets.cleanUpImage, "cleanUp:")
default:
@@ -1162,7 +1162,7 @@ private extension MainWindowController {
result = false
}
let commandName = markingRead ? NSLocalizedString("Mark as Read", comment: "Command") : NSLocalizedString("Mark as Unread", comment: "Command")
let commandName = markingRead ? NSLocalizedString("button.title.mark-as-read", comment: "Mark as Read") : NSLocalizedString("button.title.mark-as-unread", comment: "Mark as Unread")
if let toolbarItem = item as? NSToolbarItem {
toolbarItem.toolTip = commandName
@@ -1249,7 +1249,7 @@ private extension MainWindowController {
result = false
}
let commandName = starring ? NSLocalizedString("Mark as Starred", comment: "Command") : NSLocalizedString("Mark as Unstarred", comment: "Command")
let commandName = starring ? NSLocalizedString("button.title.mark-as-starred", comment: "Mark as Starred") : NSLocalizedString("button.title.mark-as-unstarred", comment: "Mark as Unstarred")
if let toolbarItem = item as? NSToolbarItem {
toolbarItem.toolTip = commandName
@@ -1270,15 +1270,15 @@ private extension MainWindowController {
func validateToggleReadFeeds(_ item: NSValidatedUserInterfaceItem) -> Bool {
guard let menuItem = item as? NSMenuItem else { return false }
let showCommand = NSLocalizedString("Show Read Feeds", comment: "Command")
let hideCommand = NSLocalizedString("Hide Read Feeds", comment: "Command")
let showCommand = NSLocalizedString("button.title.show-read-feeds", comment: "Show Read Feeds")
let hideCommand = NSLocalizedString("button.title.hide-read-feeds", comment: "Hide Read Feeds")
menuItem.title = sidebarViewController?.isReadFiltered ?? false ? showCommand : hideCommand
return true
}
func validateToggleReadArticles(_ item: NSValidatedUserInterfaceItem) -> Bool {
let showCommand = NSLocalizedString("Show Read Articles", comment: "Command")
let hideCommand = NSLocalizedString("Hide Read Articles", comment: "Command")
let showCommand = NSLocalizedString("button.title.show-read-articles", comment: "Show Read Articles")
let hideCommand = NSLocalizedString("button.title.hide-read-articles", comment: "Hide Read Articles")
guard let isReadFiltered = timelineContainerViewController?.isReadFiltered else {
(item as? NSMenuItem)?.title = hideCommand
@@ -1330,14 +1330,14 @@ private extension MainWindowController {
func updateWindowTitle() {
guard timelineSourceMode != .search else {
let localizedLabel = NSLocalizedString("Search: %@", comment: "Search")
let localizedLabel = NSLocalizedString("window.title.search.%@", comment: "Search: %@")
window?.title = NSString.localizedStringWithFormat(localizedLabel as NSString, searchString ?? "") as String
window?.subtitle = ""
return
}
func setSubtitle(_ count: Int) {
let localizedLabel = NSLocalizedString("%d unread", comment: "Unread")
let localizedLabel = NSLocalizedString("window.subtitle.unread-count.%d", comment: "%d unread")
let formattedLabel = NSString.localizedStringWithFormat(localizedLabel as NSString, count)
window?.subtitle = formattedLabel as String
}
@@ -1349,7 +1349,7 @@ private extension MainWindowController {
}
guard selectedObjects.count == 1 else {
window?.title = NSLocalizedString("Multiple", comment: "Multiple")
window?.title = NSLocalizedString("window.title.multiple", comment: "Multiple")
let unreadCount = selectedObjects.reduce(0, { result, selectedObject in
if let unreadCountProvider = selectedObject as? UnreadCountProvider {
return result + unreadCountProvider.unreadCount
@@ -1443,17 +1443,17 @@ private extension MainWindowController {
let menu = NSMenu()
let newWebFeedItem = NSMenuItem()
newWebFeedItem.title = NSLocalizedString("New Web Feed", comment: "New Web Feed")
newWebFeedItem.title = NSLocalizedString("button.title.new-web-feed", comment: "New Web Feed...")
newWebFeedItem.action = Selector(("showAddWebFeedWindow:"))
menu.addItem(newWebFeedItem)
let newRedditFeedItem = NSMenuItem()
newRedditFeedItem.title = NSLocalizedString("New Reddit Feed", comment: "New Reddit Feed")
newRedditFeedItem.title = NSLocalizedString("button.title.new-reddit-feed", comment: "New Reddit Feed...")
newRedditFeedItem.action = Selector(("showAddRedditFeedWindow:"))
menu.addItem(newRedditFeedItem)
let newFolderFeedItem = NSMenuItem()
newFolderFeedItem.title = NSLocalizedString("New Folder", comment: "New Folder")
newFolderFeedItem.title = NSLocalizedString("button.title.open-new-folder", comment: "New Folder...")
newFolderFeedItem.action = Selector(("showAddFolderWindow:"))
menu.addItem(newFolderFeedItem)

View File

@@ -73,7 +73,7 @@ private extension NNW3ImportController {
panel.allowsOtherFileTypes = false
panel.accessoryView = accessoryViewController.view
panel.isAccessoryViewDisclosed = true
panel.title = NSLocalizedString("Choose a Subscriptions.plist file:", comment: "NNW3 Import")
panel.title = NSLocalizedString("panel.title.select-opml-file", comment: "Choose a Subscriptions.plist file:")
panel.beginSheetModal(for: window) { modalResult in
guard modalResult == .OK, let subscriptionsPlistURL = panel.url else {

View File

@@ -77,10 +77,10 @@ import Account
let panel = NSSavePanel()
panel.allowedFileTypes = ["opml"]
panel.allowsOtherFileTypes = false
panel.prompt = NSLocalizedString("Export OPML", comment: "Export OPML")
panel.title = NSLocalizedString("Export OPML", comment: "Export OPML")
panel.nameFieldLabel = NSLocalizedString("Export to:", comment: "Export OPML")
panel.message = NSLocalizedString("Choose a location for the exported OPML file.", comment: "Export OPML")
panel.prompt = NSLocalizedString("panel.prompt.export-opml", comment: "Export OPML")
panel.title = NSLocalizedString("panel.title.export-opml", comment: "Export OPML")
panel.nameFieldLabel = NSLocalizedString("panel.textfield.export-opml-destination", comment: "Export to:")
panel.message = NSLocalizedString("panel.message.export-opml", comment: "Choose a location for the exported OPML file.")
panel.isExtensionHidden = false
let accountName = account.nameForDisplay.replacingOccurrences(of: " ", with: "").trimmingCharacters(in: .whitespaces)

View File

@@ -17,12 +17,12 @@ import AppKit
}
func sharingService(_ sharingService: NSSharingService, willShareItems items: [Any]) {
sharingService.subject = items
let selectedItemTitles = items
.compactMap { item in
let writer = item as? ArticlePasteboardWriter
return writer?.article.title
}
.joined(separator: ", ")
sharingService.subject = ListFormatter().string(from: selectedItemTitles)
}
func sharingService(_ sharingService: NSSharingService, sourceWindowForShareItems items: [Any], sharingContentScope: UnsafeMutablePointer<NSSharingService.SharingContentScope>) -> NSWindow? {

View File

@@ -112,7 +112,7 @@ import RSTree
override func accessibilityLabel() -> String? {
if unreadCount > 0 {
let unreadLabel = NSLocalizedString("unread", comment: "Unread label for accessibility")
let unreadLabel = NSLocalizedString("label.text.unread", comment: "unread")
return "\(name) \(unreadCount) \(unreadLabel)"
} else {
return name

View File

@@ -35,7 +35,7 @@ protocol RenameWindowControllerDelegate {
newTitleTextField.stringValue = originalTitle!
let prompt = NSLocalizedString("Rename %@ to:", comment: "Rename sheet")
let prompt = NSLocalizedString("textfield.prompt.rename-to.%@", comment: "Rename %@ to:")
let localizedPrompt = NSString.localizedStringWithFormat(prompt as NSString, originalTitle!)
renamePrompt.stringValue = localizedPrompt as String

View File

@@ -19,22 +19,22 @@ import Account
if nodes.count == 1 {
if let folder = nodes.first?.representedObject as? Folder {
alert.messageText = NSLocalizedString("Delete Folder", comment: "Delete Folder")
let localizedInformativeText = NSLocalizedString("Are you sure you want to delete the “%@” folder?", comment: "Folder delete text")
alert.messageText = NSLocalizedString("alert.title.delete-folder", comment: "Delete Folder")
let localizedInformativeText = NSLocalizedString("alert.message.delete-folder.%@", comment: "Are you sure you want to delete the “%@” folder?")
alert.informativeText = NSString.localizedStringWithFormat(localizedInformativeText as NSString, folder.nameForDisplay) as String
} else if let feed = nodes.first?.representedObject as? Feed {
alert.messageText = NSLocalizedString("Delete Feed", comment: "Delete Feed")
let localizedInformativeText = NSLocalizedString("Are you sure you want to delete the “%@” feed?", comment: "Feed delete text")
alert.messageText = NSLocalizedString("alert.title.delete-feed", comment: "Delete Feed")
let localizedInformativeText = NSLocalizedString("alert.message.delete-feed.%@", comment: "Are you sure you want to delete the “%@” feed?")
alert.informativeText = NSString.localizedStringWithFormat(localizedInformativeText as NSString, feed.nameForDisplay) as String
}
} else {
alert.messageText = NSLocalizedString("Delete Items", comment: "Delete Items")
let localizedInformativeText = NSLocalizedString("Are you sure you want to delete the %d selected items?", comment: "Items delete text")
alert.messageText = NSLocalizedString("alert.title.delete-items", comment: "Delete Items")
let localizedInformativeText = NSLocalizedString("alert.message.delete-items.%d", comment: "Are you sure you want to delete the %d selected items?")
alert.informativeText = NSString.localizedStringWithFormat(localizedInformativeText as NSString, nodes.count) as String
}
alert.addButton(withTitle: NSLocalizedString("Delete", comment: "Delete Account"))
alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "Cancel Delete Account"))
alert.addButton(withTitle: NSLocalizedString("button.title.delete", comment: "Delete Account"))
alert.addButton(withTitle: NSLocalizedString("button.title.cancel", comment: "Cancel Delete Account"))
return alert
}

View File

@@ -206,10 +206,10 @@ extension SidebarViewController {
func showNotificationsNotEnabledAlert() {
DispatchQueue.main.async {
let alert = NSAlert()
alert.messageText = NSLocalizedString("Notifications are not enabled", comment: "Notifications are not enabled.")
alert.informativeText = NSLocalizedString("You can enable NetNewsWire notifications in System Preferences.", comment: "Notifications are not enabled.")
alert.addButton(withTitle: NSLocalizedString("Open System Preferences", comment: "Open System Preferences"))
alert.addButton(withTitle: NSLocalizedString("Dismiss", comment: "Dismiss"))
alert.messageText = NSLocalizedString("alert.title.notifications-not-enabled", comment: "Notifications are not enabled.")
alert.informativeText = NSLocalizedString("alert.message.enable-notifications-in-settings", comment: "You can enable NetNewsWire notifications in System Settings.")
alert.addButton(withTitle: NSLocalizedString("button.title.open-settings", comment: "Open Settings"))
alert.addButton(withTitle: NSLocalizedString("button.title.dismiss", comment: "Dismiss"))
let userChoice = alert.runModal()
if userChoice == .alertFirstButtonReturn {
let config = NSWorkspace.OpenConfiguration()
@@ -258,8 +258,8 @@ private extension SidebarViewController {
let menu = NSMenu(title: "")
menu.addItem(withTitle: NSLocalizedString("New Feed", comment: "Command"), action: #selector(AppDelegate.showAddWebFeedWindow(_:)), keyEquivalent: "")
menu.addItem(withTitle: NSLocalizedString("New Folder", comment: "Command"), action: #selector(AppDelegate.showAddFolderWindow(_:)), keyEquivalent: "")
menu.addItem(withTitle: NSLocalizedString("button.title.new-feed", comment: "New Feed"), action: #selector(AppDelegate.showAddWebFeedWindow(_:)), keyEquivalent: "")
menu.addItem(withTitle: NSLocalizedString("button.title.new-folder", comment: "New Folder"), action: #selector(AppDelegate.showAddFolderWindow(_:)), keyEquivalent: "")
return menu
}
@@ -270,7 +270,7 @@ private extension SidebarViewController {
if webFeed.unreadCount > 0 {
menu.addItem(markAllReadMenuItem([webFeed]))
let catchUpMenuItem = NSMenuItem(title: NSLocalizedString("Mark as Read Older Than", comment: "Command Submenu"), action: nil, keyEquivalent: "")
let catchUpMenuItem = NSMenuItem(title: NSLocalizedString("button.title.mark-as-read-older-than", comment: "Mark as Read Older Than"), action: nil, keyEquivalent: "")
let catchUpSubMenu = catchUpSubMenu([webFeed])
menu.addItem(catchUpMenuItem)
@@ -280,16 +280,16 @@ private extension SidebarViewController {
}
if let homePageURL = webFeed.homePageURL, let _ = URL(string: homePageURL) {
let item = menuItem(NSLocalizedString("Open Home Page", comment: "Command"), #selector(openHomePageFromContextualMenu(_:)), homePageURL.decodedURLString ?? homePageURL)
let item = menuItem(NSLocalizedString("button.title.open-home-page", comment: "Open Home Page"), #selector(openHomePageFromContextualMenu(_:)), homePageURL.decodedURLString ?? homePageURL)
menu.addItem(item)
menu.addItem(NSMenuItem.separator())
}
let copyFeedURLItem = menuItem(NSLocalizedString("Copy Feed URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), webFeed.url.decodedURLString ?? webFeed.url)
let copyFeedURLItem = menuItem(NSLocalizedString("button.title.copy-feed-url", comment: "Copy Feed URL"), #selector(copyURLFromContextualMenu(_:)), webFeed.url.decodedURLString ?? webFeed.url)
menu.addItem(copyFeedURLItem)
if let homePageURL = webFeed.homePageURL {
let item = menuItem(NSLocalizedString("Copy Home Page URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), homePageURL.decodedURLString ?? homePageURL)
let item = menuItem(NSLocalizedString("button.title.copy-home-page-url", comment: "Copy Home Page URL"), #selector(copyURLFromContextualMenu(_:)), homePageURL.decodedURLString ?? homePageURL)
menu.addItem(item)
}
menu.addItem(NSMenuItem.separator())
@@ -306,7 +306,7 @@ private extension SidebarViewController {
if !webFeed.isFeedProvider {
let articleExtractorText = NSLocalizedString("Always Use Reader View", comment: "Always Use Reader View")
let articleExtractorText = NSLocalizedString("button.title.always-use-reader-view", comment: "Always Use Reader View")
let articleExtractorMenuItem = menuItem(articleExtractorText, #selector(toggleArticleExtractorFromContextMenu(_:)), webFeed)
if webFeed.isArticleExtractorAlwaysOn == nil || webFeed.isArticleExtractorAlwaysOn! == false {
@@ -332,7 +332,7 @@ private extension SidebarViewController {
if folder.unreadCount > 0 {
menu.addItem(markAllReadMenuItem([folder]))
let catchUpMenuItem = NSMenuItem(title: NSLocalizedString("Mark as Read Older Than", comment: "Command Submenu"), action: nil, keyEquivalent: "")
let catchUpMenuItem = NSMenuItem(title: NSLocalizedString("button.title.mark-as-read-older-than", comment: "Mark as Read Older Than"), action: nil, keyEquivalent: "")
let catchUpSubMenu = catchUpSubMenu([folder])
menu.addItem(catchUpMenuItem)
@@ -360,7 +360,7 @@ private extension SidebarViewController {
}
}
let catchUpMenuItem = NSMenuItem(title: NSLocalizedString("Mark as Read Older Than", comment: "Command Submenu"), action: nil, keyEquivalent: "")
let catchUpMenuItem = NSMenuItem(title: NSLocalizedString("button.title.mark-as-read-older-than", comment: "Mark as Read Older Than"), action: nil, keyEquivalent: "")
let catchUpSubMenu = catchUpSubMenu([smartFeed])
menu.addItem(catchUpMenuItem)
menu.setSubmenu(catchUpSubMenu, for: catchUpMenuItem)
@@ -374,7 +374,7 @@ private extension SidebarViewController {
if anyObjectInArrayHasNonZeroUnreadCount(objects) {
menu.addItem(markAllReadMenuItem(objects))
let catchUpMenuItem = NSMenuItem(title: NSLocalizedString("Mark as Read Older Than", comment: "Command Submenu"), action: nil, keyEquivalent: "")
let catchUpMenuItem = NSMenuItem(title: NSLocalizedString("button.title.mark-as-read-older-than", comment: "Mark as Read Older Than"), action: nil, keyEquivalent: "")
let catchUpSubMenu = catchUpSubMenu(objects)
menu.addItem(catchUpMenuItem)
@@ -391,31 +391,31 @@ private extension SidebarViewController {
func markAllReadMenuItem(_ objects: [Any]) -> NSMenuItem {
return menuItem(NSLocalizedString("Mark All as Read", comment: "Command"), #selector(markObjectsReadFromContextualMenu(_:)), objects)
return menuItem(NSLocalizedString("button.title.mark-all-as-read.titlecase", comment: "Mark All as Read"), #selector(markObjectsReadFromContextualMenu(_:)), objects)
}
func catchUpSubMenu(_ objects: [Any]) -> NSMenu {
let menu = NSMenu(title: "Catch up to articles older than...")
let menu = NSMenu(title: NSLocalizedString("menu.title.catch-up-to-articles", comment: "Catch up to articles older than..."))
menu.addItem(menuItem(NSLocalizedString("1 day", comment: "Command"), #selector(markObjectsReadOlderThanOneDayFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("2 days", comment: "Command"), #selector(markObjectsReadOlderThanTwoDaysFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("3 days", comment: "Command"), #selector(markObjectsReadOlderThanThreeDaysFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("1 week", comment: "Command"), #selector(markObjectsReadOlderThanOneWeekFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("2 weeks", comment: "Command"), #selector(markObjectsReadOlderThanTwoWeeksFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("1 month", comment: "Command"), #selector(markObjectsReadOlderThanOneMonthFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("1 year", comment: "Command"), #selector(markObjectsReadOlderThanOneYearFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("button.title.1-day", comment: "1 day"), #selector(markObjectsReadOlderThanOneDayFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("button.title.2-days", comment: "2 days"), #selector(markObjectsReadOlderThanTwoDaysFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("button.title.3-days", comment: "3 days"), #selector(markObjectsReadOlderThanThreeDaysFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("button.title.1-week", comment: "1 week"), #selector(markObjectsReadOlderThanOneWeekFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("button.title.2-weeks", comment: "2 weeks"), #selector(markObjectsReadOlderThanTwoWeeksFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("button.title.1-month", comment: "1 month"), #selector(markObjectsReadOlderThanOneMonthFromContextualMenu(_:)), objects))
menu.addItem(menuItem(NSLocalizedString("button.title.1-year", comment: "1 year"), #selector(markObjectsReadOlderThanOneYearFromContextualMenu(_:)), objects))
return menu
}
func deleteMenuItem(_ objects: [Any]) -> NSMenuItem {
return menuItem(NSLocalizedString("Delete", comment: "Command"), #selector(deleteFromContextualMenu(_:)), objects)
return menuItem(NSLocalizedString("button.title.delete", comment: "Delete"), #selector(deleteFromContextualMenu(_:)), objects)
}
func renameMenuItem(_ object: Any) -> NSMenuItem {
return menuItem(NSLocalizedString("Rename", comment: "Command"), #selector(renameFromContextualMenu(_:)), object)
return menuItem(NSLocalizedString("button.title.rename", comment: "Rename"), #selector(renameFromContextualMenu(_:)), object)
}
func anyObjectInArrayHasNonZeroUnreadCount(_ objects: [Any]) -> Bool {

View File

@@ -11,7 +11,7 @@ import Articles
struct TimelineCellData {
private static let noText = NSLocalizedString("(No Text)", comment: "No Text")
private static let noText = NSLocalizedString("label.text.no-text", comment: "(No Text)")
let title: String
let attributedTitle: NSAttributedString

View File

@@ -14,7 +14,7 @@ import RSCore
weak var keyboardDelegate: KeyboardDelegate?
override func accessibilityLabel() -> String? {
return NSLocalizedString("Timeline", comment: "Timeline")
return NSLocalizedString("label.text.timeline", comment: "Timeline")
}
// MARK: - NSResponder

View File

@@ -227,7 +227,7 @@ private extension TimelineViewController {
return nil
}
let menu = NSMenu(title: NSLocalizedString("Share", comment: "Share menu name"))
let menu = NSMenu(title: NSLocalizedString("button.title.share", comment: "Share menu name"))
services.forEach { (service) in
service.delegate = sharingServiceDelegate
let menuItem = NSMenuItem(title: service.menuItemTitle, action: #selector(performShareServiceFromContextualMenu(_:)), keyEquivalent: "")
@@ -242,34 +242,34 @@ private extension TimelineViewController {
func markReadMenuItem(_ articles: [Article]) -> NSMenuItem {
return menuItem(NSLocalizedString("Mark as Read", comment: "Command"), #selector(markArticlesReadFromContextualMenu(_:)), articles)
return menuItem(NSLocalizedString("button.title.mark-as-read", comment: "Mark as Read"), #selector(markArticlesReadFromContextualMenu(_:)), articles)
}
func markUnreadMenuItem(_ articles: [Article]) -> NSMenuItem {
return menuItem(NSLocalizedString("Mark as Unread", comment: "Command"), #selector(markArticlesUnreadFromContextualMenu(_:)), articles)
return menuItem(NSLocalizedString("button.title.mark-as-unread", comment: "Mark as Unread"), #selector(markArticlesUnreadFromContextualMenu(_:)), articles)
}
func markStarredMenuItem(_ articles: [Article]) -> NSMenuItem {
return menuItem(NSLocalizedString("Mark as Starred", comment: "Command"), #selector(markArticlesStarredFromContextualMenu(_:)), articles)
return menuItem(NSLocalizedString("button.title.mark-as-starred", comment: "Mark as Starred"), #selector(markArticlesStarredFromContextualMenu(_:)), articles)
}
func markUnstarredMenuItem(_ articles: [Article]) -> NSMenuItem {
return menuItem(NSLocalizedString("Mark as Unstarred", comment: "Command"), #selector(markArticlesUnstarredFromContextualMenu(_:)), articles)
return menuItem(NSLocalizedString("button.title.mark-as-unstarred", comment: "Mark as Unstarred"), #selector(markArticlesUnstarredFromContextualMenu(_:)), articles)
}
func markAboveReadMenuItem(_ articles: [Article]) -> NSMenuItem {
return menuItem(NSLocalizedString("Mark Above as Read", comment: "Command"), #selector(markAboveArticlesReadFromContextualMenu(_:)), articles)
return menuItem(NSLocalizedString("button.title-mark-above-as-read.titlecase", comment: "Mark Above as Read"), #selector(markAboveArticlesReadFromContextualMenu(_:)), articles)
}
func markBelowReadMenuItem(_ articles: [Article]) -> NSMenuItem {
return menuItem(NSLocalizedString("Mark Below as Read", comment: "Command"), #selector(markBelowArticlesReadFromContextualMenu(_:)), articles)
return menuItem(NSLocalizedString("button.title-mark-below-as-read.titlecase", comment: "Mark Below as Read"), #selector(markBelowArticlesReadFromContextualMenu(_:)), articles)
}
func selectFeedInSidebarMenuItem(_ feed: WebFeed) -> NSMenuItem {
let localizedMenuText = NSLocalizedString("Select “%@” in Sidebar", comment: "Command")
let localizedMenuText = NSLocalizedString("button.title.select-in-sidebar.%@", comment: "Select “%@” in Sidebar")
let formattedMenuText = NSString.localizedStringWithFormat(localizedMenuText as NSString, feed.nameForDisplay)
return menuItem(formattedMenuText as String, #selector(selectFeedInSidebarFromContextualMenu(_:)), feed)
}
@@ -283,14 +283,14 @@ private extension TimelineViewController {
return nil
}
let localizedMenuText = NSLocalizedString("Mark All as Read in “%@", comment: "Command")
let localizedMenuText = NSLocalizedString("button.title.mark-all-as-read.%@", comment: "Mark All as Read in “%@”")
let menuText = NSString.localizedStringWithFormat(localizedMenuText as NSString, feed.nameForDisplay) as String
return menuItem(menuText, #selector(markAllInFeedAsRead(_:)), articles)
}
func openInBrowserMenuItem(_ urlStrings: [String]) -> NSMenuItem {
return menuItem(NSLocalizedString("Open in Browser", comment: "Command"), #selector(openInBrowserFromContextualMenu(_:)), urlStrings)
return menuItem(NSLocalizedString("button.title.open-in-browser", comment: "Open in Browser"), #selector(openInBrowserFromContextualMenu(_:)), urlStrings)
}
func openInBrowserReversedMenuItem(_ urlStrings: [String]) -> NSMenuItem {
@@ -301,13 +301,13 @@ private extension TimelineViewController {
}
func copyArticleURLsMenuItem(_ urlStrings: [String?]) -> NSMenuItem {
let format = NSLocalizedString("Copy Article URL", comment: "Command")
let format = NSLocalizedString("button.title.copy-article-urls.%ld", comment: "Copy Article URL or Copy Article URLs (if more than one)")
let title = String.localizedStringWithFormat(format, urlStrings.count)
return menuItem(title, #selector(copyURLFromContextualMenu(_:)), urlStrings)
}
func copyExternalURLMenuItem(_ urlString: String) -> NSMenuItem {
return menuItem(NSLocalizedString("Copy External URL", comment: "Command"), #selector(copyURLFromContextualMenu(_:)), urlString)
return menuItem(NSLocalizedString("button.title.copy-external-url", comment: "Copy External URL"), #selector(copyURLFromContextualMenu(_:)), urlString)
}

View File

@@ -20,8 +20,8 @@ import RSCore
if urlStrings.contains(nil), !AppDefaults.shared.hasSeenNotAllArticlesHaveURLsAlert {
let alert = NSAlert()
alert.messageText = NSLocalizedString("Some articles dont have links, so they weren't copied.", comment: "\"Some articles have no links\" copy alert message text")
alert.informativeText = NSLocalizedString("You won't see this message again.", comment: "You won't see this message again")
alert.messageText = NSLocalizedString("alert.message.articles-without-links", comment: "Some articles dont have links, so they weren't copied.")
alert.informativeText = NSLocalizedString("alert.informative.will-not-see-again", comment: "You won't see this message again")
if let window {
alert.beginSheetModal(for: window)

View File

@@ -13,7 +13,7 @@ enum AccountsAddCloudKitWindowControllerError: LocalizedError {
case iCloudDriveMissing
var errorDescription: String? {
return NSLocalizedString("Unable to add iCloud Account. Please make sure you have iCloud and iCloud Drive enabled in System Preferences.", comment: "Unable to add iCloud Account.")
return NSLocalizedString("error.description.cloudkit-unavailable", comment: "Unable to add iCloud Account. Please make sure you have iCloud and iCloud Drive enabled in System Settings.")
}
}

View File

@@ -23,7 +23,7 @@ import Account
override func windowDidLoad() {
super.windowDidLoad()
localAccountNameTextField.stringValue = NSLocalizedString("Create a local account on your Mac.", comment: "Account Local")
localAccountNameTextField.stringValue = NSLocalizedString("textfield.text.create-a-local-account", comment: "Create a local account on your Mac.")
}
// MARK: API

View File

@@ -34,13 +34,13 @@ import Secrets
override func windowDidLoad() {
if let account = account, let credentials = try? account.retrieveCredentials(type: .basic) {
usernameTextField.stringValue = credentials.username
actionButton.title = NSLocalizedString("Update", comment: "Update")
signInTextField.stringValue = NSLocalizedString("Update your Feedbin account credentials.", comment: "SignIn")
actionButton.title = NSLocalizedString("button.title.update", comment: "Update")
signInTextField.stringValue = NSLocalizedString("textfield.text.update-feedbin-credentials", comment: "Update your Feedbin account credentials.")
noAccountTextField.isHidden = true
createNewAccountButton.isHidden = true
} else {
actionButton.title = NSLocalizedString("Create", comment: "Add Account")
signInTextField.stringValue = NSLocalizedString("Sign in to your Feedbin account.", comment: "SignIn")
actionButton.title = NSLocalizedString("button.title.create", comment: "Create")
signInTextField.stringValue = NSLocalizedString("textfield.text.sign-in-feedbin", comment: "Sign in to your Feedbin account.")
}
enableAutofill()
@@ -66,12 +66,13 @@ import Secrets
self.errorMessageLabel.stringValue = ""
guard !usernameTextField.stringValue.isEmpty && !passwordTextField.stringValue.isEmpty else {
self.errorMessageLabel.stringValue = NSLocalizedString("Username & password required.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.userNameAndPasswordRequired.localizedDescription
return
}
guard account != nil || !AccountManager.shared.duplicateServiceAccount(type: .feedbin, username: usernameTextField.stringValue) else {
self.errorMessageLabel.stringValue = NSLocalizedString("There is already a Feedbin account with that username created.", comment: "Duplicate Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.duplicateAccount.localizedDescription
return
}
@@ -92,7 +93,8 @@ import Secrets
case .success(let validatedCredentials):
guard let validatedCredentials = validatedCredentials else {
self.errorMessageLabel.stringValue = NSLocalizedString("Invalid email/password combination.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.invalidUsernameOrPassword.localizedDescription
return
}
@@ -115,13 +117,13 @@ import Secrets
self.hostWindow?.endSheet(self.window!, returnCode: NSApplication.ModalResponse.OK)
} catch {
self.errorMessageLabel.stringValue = NSLocalizedString("Keychain error while storing credentials.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.keychainError.localizedDescription
self.logger.error("Keychain error while storing credentials: \(error.localizedDescription, privacy: .public)")
}
case .failure:
self.errorMessageLabel.stringValue = NSLocalizedString("Network error. Try again later.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.networkError.localizedDescription
}

View File

@@ -34,13 +34,13 @@ import Secrets
override func windowDidLoad() {
if let account = account, let credentials = try? account.retrieveCredentials(type: .newsBlurBasic) {
usernameTextField.stringValue = credentials.username
actionButton.title = NSLocalizedString("Update", comment: "Update")
signInTextField.stringValue = NSLocalizedString("Update your NewsBlur account credentials.", comment: "SignIn")
actionButton.title = NSLocalizedString("button.title.update", comment: "Update")
signInTextField.stringValue = NSLocalizedString("textfield.text.update-newsblur-credentials", comment: "Update your NewsBlur account credentials.")
noAccountTextField.isHidden = true
createNewAccountButton.isHidden = true
} else {
actionButton.title = NSLocalizedString("Create", comment: "Create")
signInTextField.stringValue = NSLocalizedString("Sign in to your NewsBlur account.", comment: "SignIn")
actionButton.title = NSLocalizedString("button.title.create", comment: "Create")
signInTextField.stringValue = NSLocalizedString("textfield.text.sign-in-newsblur", comment: "Sign in to your NewsBlur account.")
}
enableAutofill()
usernameTextField.becomeFirstResponder()
@@ -63,12 +63,12 @@ import Secrets
self.errorMessageLabel.stringValue = ""
guard !usernameTextField.stringValue.isEmpty else {
self.errorMessageLabel.stringValue = NSLocalizedString("Username required.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.userNameRequired.localizedDescription
return
}
guard account != nil || !AccountManager.shared.duplicateServiceAccount(type: .newsBlur, username: usernameTextField.stringValue) else {
self.errorMessageLabel.stringValue = NSLocalizedString("There is already a NewsBlur account with that username created.", comment: "Duplicate Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.duplicateAccount.localizedDescription
return
}
@@ -88,7 +88,7 @@ import Secrets
switch result {
case .success(let validatedCredentials):
guard let validatedCredentials = validatedCredentials else {
self.errorMessageLabel.stringValue = NSLocalizedString("Invalid email/password combination.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.invalidUsernameOrPassword.localizedDescription
return
}
@@ -113,14 +113,12 @@ import Secrets
self.hostWindow?.endSheet(self.window!, returnCode: NSApplication.ModalResponse.OK)
} catch {
self.errorMessageLabel.stringValue = NSLocalizedString("Keychain error while storing credentials.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.keychainError.localizedDescription
self.logger.error("Keychain error while storing credentials: \(error.localizedDescription, privacy: .public)")
}
case .failure:
self.errorMessageLabel.stringValue = NSLocalizedString("Network error. Try again later.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.networkError.localizedDescription
}
}
}

View File

@@ -66,12 +66,12 @@ protocol AccountsPreferencesAddAccountDelegate {
let alert = NSAlert()
alert.alertStyle = .warning
let deletePrompt = NSLocalizedString("Delete", comment: "Delete")
alert.messageText = "\(deletePrompt)\(acctName)”?"
alert.informativeText = NSLocalizedString("Are you sure you want to delete the account “\(acctName)”? This cannot be undone.", comment: "Delete text")
let deletePrompt = NSLocalizedString("alert.title.delete.%@", comment: "Delete “%@“")
alert.messageText = String(format: deletePrompt, acctName)
alert.informativeText = NSLocalizedString("alert.message.cannot-undo-action", comment: "Cannot undo action")
alert.addButton(withTitle: NSLocalizedString("Delete", comment: "Delete Account"))
alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "Cancel Delete Account"))
alert.addButton(withTitle: NSLocalizedString("button.title.delete", comment: "Delete Account"))
alert.addButton(withTitle: NSLocalizedString("button.title.cancel", comment: "Cancel Delete Account"))
alert.beginSheetModal(for: view.window!) { [weak self] result in
if result == NSApplication.ModalResponse.alertFirstButtonReturn {
@@ -191,13 +191,13 @@ extension AccountsPreferencesViewController: AccountsPreferencesAddAccountDelega
private func runAwaitingFeedlyLoginAlertModal(forLifetimeOf operation: OAuthAccountAuthorizationOperation) {
let alert = NSAlert()
alert.alertStyle = .informational
alert.messageText = NSLocalizedString("Waiting for access to Feedly",
alert.messageText = NSLocalizedString("alert.title.waiting-for-feedly-access",
comment: "Alert title when adding a Feedly account and waiting for authorization from the user.")
alert.informativeText = NSLocalizedString("A web browser will open the Feedly login for you to authorize access.",
comment: "Alert informative text when adding a Feedly account and waiting for authorization from the user.")
alert.informativeText = NSLocalizedString("alert.message.feedly-web-browser-information",
comment: "A web browser will open the Feedly login for you to authorize access.")
alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "Cancel"))
alert.addButton(withTitle: NSLocalizedString("button.title.cancel", comment: "Cancel"))
let attachedWindow = self.view.window!
@@ -242,9 +242,9 @@ private extension AccountsPreferencesViewController {
if tableView.selectedRow == -1 {
var helpText = ""
if sortedAccounts.count == 0 {
helpText = NSLocalizedString("Add an account by clicking the + button.", comment: "Add Account Explainer")
helpText = NSLocalizedString("label.text.add-account-explainer", comment: "Add an account by clicking the + button.")
} else {
helpText = NSLocalizedString("Select an account or add a new account by clicking the + button.", comment: "Add Account Explainer")
helpText = NSLocalizedString("label.text.select-or-add-account-explainer", comment: "Select an account or add a new account by clicking the + button.")
}
let textHostingController = NSHostingController(rootView:

View File

@@ -41,25 +41,25 @@ import Secrets
switch accountType {
case .freshRSS:
titleImageView.image = AppAssets.accountFreshRSS
titleLabel.stringValue = NSLocalizedString("Sign in to your FreshRSS account.", comment: "FreshRSS")
noAccountTextField.stringValue = NSLocalizedString("Dont have a FreshRSS instance?", comment: "No FreshRSS")
createAccountButton.title = NSLocalizedString("Find out more", comment: "No FreshRSS Button")
apiURLTextField.placeholderString = NSLocalizedString("fresh.rss.net/api/greader.php", comment: "FreshRSS API Helper")
titleLabel.stringValue = NSLocalizedString("label.text.sign-in-freshrss", comment: "Sign in to your FreshRSS account.")
noAccountTextField.stringValue = NSLocalizedString("label.text.no-fresh-rss", comment: "Dont have a FreshRSS instance?")
createAccountButton.title = NSLocalizedString("label.text.find-out-more", comment: "Find out more")
apiURLTextField.placeholderString = "fresh.rss.net/api/greader.php" // not localized.
case .inoreader:
titleImageView.image = AppAssets.accountInoreader
titleLabel.stringValue = NSLocalizedString("Sign in to your InoReader account.", comment: "InoReader")
titleLabel.stringValue = NSLocalizedString("label.text.sign-in-inoreader", comment: "Sign in to your InoReader account.")
gridView.row(at: 2).isHidden = true
noAccountTextField.stringValue = NSLocalizedString("Dont have an InoReader account?", comment: "No InoReader")
noAccountTextField.stringValue = NSLocalizedString("label.text.no-inoreader", comment: "Dont have an InoReader account?")
case .bazQux:
titleImageView.image = AppAssets.accountBazQux
titleLabel.stringValue = NSLocalizedString("Sign in to your BazQux account.", comment: "BazQux")
titleLabel.stringValue = NSLocalizedString("label.text.sign-in-bazqux", comment: "Sign in to your BazQux account.")
gridView.row(at: 2).isHidden = true
noAccountTextField.stringValue = NSLocalizedString("Dont have a BazQux account?", comment: "No BazQux")
noAccountTextField.stringValue = NSLocalizedString("label.text.no-bazqux", comment: "Dont have a BazQux account?")
case .theOldReader:
titleImageView.image = AppAssets.accountTheOldReader
titleLabel.stringValue = NSLocalizedString("Sign in to your The Old Reader account.", comment: "The Old Reader")
titleLabel.stringValue = NSLocalizedString("label.text.sign-in-old-reader", comment: "Sign in to your The Old Reader account.")
gridView.row(at: 2).isHidden = true
noAccountTextField.stringValue = NSLocalizedString("Dont have a The Old Reader account?", comment: "No OldReader")
noAccountTextField.stringValue = NSLocalizedString("label.text.no-old-reader", comment: "Dont have a The Old Reader account?")
default:
break
}
@@ -68,9 +68,9 @@ import Secrets
if let account = account, let credentials = try? account.retrieveCredentials(type: .readerBasic) {
usernameTextField.stringValue = credentials.username
apiURLTextField.stringValue = account.endpointURL?.absoluteString ?? ""
actionButton.title = NSLocalizedString("Update", comment: "Update")
actionButton.title = NSLocalizedString("button.title.update", comment: "Update")
} else {
actionButton.title = NSLocalizedString("Create", comment: "Create")
actionButton.title = NSLocalizedString("button.title.create", comment: "Create")
}
enableAutofill()
@@ -94,17 +94,17 @@ import Secrets
self.errorMessageLabel.stringValue = ""
guard !usernameTextField.stringValue.isEmpty && !passwordTextField.stringValue.isEmpty else {
self.errorMessageLabel.stringValue = NSLocalizedString("Username, password & API URL are required.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.userNameAndPasswordRequired.localizedDescription
return
}
guard let accountType = accountType, !(accountType == .freshRSS && apiURLTextField.stringValue.isEmpty) else {
self.errorMessageLabel.stringValue = NSLocalizedString("Username, password & API URL are required.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.userNamePasswordAndURLRequired.localizedDescription
return
}
guard account != nil || !AccountManager.shared.duplicateServiceAccount(type: accountType, username: usernameTextField.stringValue) else {
self.errorMessageLabel.stringValue = NSLocalizedString("There is already an account of this type with that username created.", comment: "Duplicate Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.duplicateAccount.localizedDescription
return
}
@@ -112,7 +112,7 @@ import Secrets
switch accountType {
case .freshRSS:
guard let inputURL = URL(string: apiURLTextField.stringValue) else {
self.errorMessageLabel.stringValue = NSLocalizedString("Invalid API URL.", comment: "Invalid API URL")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.invalidURL.localizedDescription
return
}
apiURL = inputURL
@@ -123,7 +123,7 @@ import Secrets
case .theOldReader:
apiURL = URL(string: ReaderAPIVariant.theOldReader.host)!
default:
self.errorMessageLabel.stringValue = NSLocalizedString("Unrecognized account type.", comment: "Bad account type")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.unrecognizedAccount.localizedDescription
return
}
@@ -143,7 +143,7 @@ import Secrets
switch result {
case .success(let validatedCredentials):
guard let validatedCredentials = validatedCredentials else {
self.errorMessageLabel.stringValue = NSLocalizedString("Invalid email/password combination.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.invalidUsernameOrPassword.localizedDescription
return
}
@@ -170,12 +170,12 @@ import Secrets
self.hostWindow?.endSheet(self.window!, returnCode: NSApplication.ModalResponse.OK)
} catch {
self.errorMessageLabel.stringValue = NSLocalizedString("Keychain error while storing credentials.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.keychainError.localizedDescription
self.logger.error("Keychain error while storing credentials: \(error.localizedDescription, privacy: .public)")
}
case .failure:
self.errorMessageLabel.stringValue = NSLocalizedString("Network error. Try again later.", comment: "Credentials Error")
self.errorMessageLabel.stringValue = LocalizedNetNewsWireError.networkError.localizedDescription
}
}

View File

@@ -43,8 +43,8 @@ struct AddAccountHelpView: View {
}
.alert(isPresented: $iCloudUnavailableError, content: {
Alert(title: Text(NSLocalizedString("Error", comment: "Error")),
message: Text(NSLocalizedString("You've already set up an iCloud account.", comment: "Error")),
Alert(title: Text(NSLocalizedString("alert.title.error", comment: "Error")),
message: Text(NSLocalizedString("alert.message.cloudkit-already-setup", comment: "You've already set up an iCloud account.")),
dismissButton: Alert.Button.cancel({
iCloudUnavailableError = false
}))

View File

@@ -20,13 +20,13 @@ enum AddAccountSections: Int, CaseIterable {
var sectionHeader: String {
switch self {
case .local:
return NSLocalizedString("Local", comment: "Local Account")
return NSLocalizedString("label.text.local", comment: "Local")
case .icloud:
return NSLocalizedString("iCloud", comment: "iCloud Account")
return NSLocalizedString("label.text.cloudkit", comment: "iCloud")
case .web:
return NSLocalizedString("Web", comment: "Web Account")
return NSLocalizedString("label.text.web", comment: "Web")
case .selfhosted:
return NSLocalizedString("Self-hosted", comment: "Self hosted Account")
return NSLocalizedString("label.text.self-hosted", comment: "Self-hosted")
case .allOrdered:
return ""
}
@@ -35,13 +35,13 @@ enum AddAccountSections: Int, CaseIterable {
var sectionFooter: String {
switch self {
case .local:
return NSLocalizedString("Local accounts do not sync feeds across devices", comment: "Local Account")
return NSLocalizedString("label.text.local-account-explainer", comment: "Local accounts do not sync your feeds across devices")
case .icloud:
return NSLocalizedString("Your iCloud account syncs your feeds across your Mac and iOS devices", comment: "iCloud Account")
return NSLocalizedString("label.text.cloudkit-explainer", comment: "Your iCloud account syncs your feeds across your Mac and iOS devices")
case .web:
return NSLocalizedString("Web accounts sync your feeds across all your devices", comment: "Web Account")
return NSLocalizedString("label.text.web-account-explainer", comment: "Web accounts sync your feeds across all your devices")
case .selfhosted:
return NSLocalizedString("Self-hosted accounts sync your feeds across all your devices", comment: "Self hosted Account")
return NSLocalizedString("label.text.self-hosted-accounts-explainer", comment: "Self-hosted accounts sync your feeds across all your devices")
case .allOrdered:
return ""
}
@@ -87,7 +87,7 @@ struct AddAccountsView: View {
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text("Choose an account type to add...")
Text("label.text.choose-account-to-add", comment: "Choose an account type to add...")
.font(.headline)
.padding()
@@ -106,20 +106,20 @@ struct AddAccountsView: View {
Button(action: {
parent?.dismiss(nil)
}, label: {
Text("Cancel")
Text("button.title.cancel")
.frame(width: 76)
})
.help("Cancel")
.help("label.text.cancel")
.keyboardShortcut(.cancelAction)
Button(action: {
addAccountDelegate?.presentSheetForAccount(selectedAccount)
parent?.dismiss(nil)
}, label: {
Text("Continue")
Text("button.title.continue", comment: "Continue")
.frame(width: 76)
})
.help("Add Account")
.help("label.text.add-account")
.keyboardShortcut(.defaultAction)
}
.padding(.top, 12)
@@ -133,7 +133,7 @@ struct AddAccountsView: View {
var localAccount: some View {
VStack(alignment: .leading) {
Text("Local")
Text("label.text.local", comment: "Local")
.font(.headline)
.padding(.horizontal)
@@ -164,7 +164,7 @@ struct AddAccountsView: View {
var icloudAccount: some View {
VStack(alignment: .leading) {
Text("iCloud")
Text("label.text.cloudkit", comment: "iCloud")
.font(.headline)
.padding(.horizontal)
.padding(.top, 8)
@@ -196,7 +196,7 @@ struct AddAccountsView: View {
@ViewBuilder
var webAccounts: some View {
VStack(alignment: .leading) {
Text("Web")
Text("label.text.web", comment: "Web")
.font(.headline)
.padding(.horizontal)
.padding(.top, 8)
@@ -234,7 +234,7 @@ struct AddAccountsView: View {
var selfhostedAccounts: some View {
VStack(alignment: .leading) {
Text("Self-hosted")
Text("label.text.self-hosted", comment: "Self-hosted")
.font(.headline)
.padding(.horizontal)
.padding(.top, 8)

View File

@@ -25,7 +25,7 @@ struct EnableExtensionPointView: View {
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text("Choose an extension to add...")
Text("label.text.choose-extension-to-add", comment: "Choose an extension to add...")
.font(.headline)
.padding()
@@ -37,7 +37,7 @@ struct EnableExtensionPointView: View {
Button(action: {
parent?.dismiss(nil)
}, label: {
Text("Cancel")
Text("button.title.cancel", comment: "Cancel")
.frame(width: 80)
})
.help("Cancel")
@@ -72,7 +72,7 @@ struct EnableExtensionPointView: View {
VStack(alignment: .leading) {
let extensionPointTypeNames = Self.feedProviderExtensionPointTypes.map { String(describing: $0) }
if extensionPointTypeNames.count > 0 {
Text("Feed Provider")
Text("label.text.feed-provider", comment: "Feed Provider")
.font(.headline)
.padding(.horizontal)
@@ -95,7 +95,7 @@ struct EnableExtensionPointView: View {
.pickerStyle(RadioGroupPickerStyle())
.offset(x: 7.5, y: 0)
Text("An extension that makes websites appear to provide RSS feeds for their content.")
Text("label.text.feed-provider-explainer", comment: "An extension that makes websites appear to provide RSS feeds for their content.")
.foregroundColor(.gray)
.font(.caption)
.padding(.horizontal)
@@ -113,7 +113,7 @@ struct EnableExtensionPointView: View {
VStack(alignment: .leading) {
let extensionPointTypeNames = Self.sendToCommandExtensionPointTypes.map { String(describing: $0) }
if extensionPointTypeNames.count > 0 {
Text("Third-Party Integration")
Text("label.text.third-party-integration", comment: "Third-Party Integration")
.font(.headline)
.padding(.horizontal)
.padding(.top, 8)
@@ -137,7 +137,7 @@ struct EnableExtensionPointView: View {
.pickerStyle(RadioGroupPickerStyle())
.offset(x: 7.5, y: 0)
Text("An extension that enables a share menu item that passes article data to a third-party application.")
Text("label.text.share-extension-explainer", comment: "An extension that enables a share menu item that passes article data to a third-party application.")
.foregroundColor(.gray)
.font(.caption)
.padding(.horizontal)

View File

@@ -64,13 +64,13 @@ protocol ExtensionPointPreferencesEnabler: AnyObject {
let alert = NSAlert()
alert.alertStyle = .warning
let prompt = NSLocalizedString("Deactivate", comment: "Deactivate")
alert.messageText = "\(prompt)\(extensionPoint.title)”?"
let prompt = NSLocalizedString("alert.title.deactivate-extension.%@", comment: "Deactivate “%@“?")
alert.messageText = String(format: prompt, extensionPoint.title)
let extensionPointTypeTitle = extensionPoint.extensionPointID.extensionPointType.title
alert.informativeText = NSLocalizedString("Are you sure you want to deactivate the \(extensionPointTypeTitle) extension “\(extensionPoint.title)”?", comment: "Deactivate text")
alert.informativeText = NSLocalizedString("alert.message.cannot-undo-action", comment: "You can't undo this action.")
alert.addButton(withTitle: NSLocalizedString("Deactivate", comment: "Deactivate Extension"))
alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "Cancel Deactivate Extension"))
alert.addButton(withTitle: NSLocalizedString("button.title.deactivate", comment: "Deactivate Extension"))
alert.addButton(withTitle: NSLocalizedString("button.title.cancel", comment: "Cancel Deactivate Extension"))
alert.beginSheetModal(for: view.window!) { [weak self] result in
if result == NSApplication.ModalResponse.alertFirstButtonReturn {
@@ -201,12 +201,12 @@ private extension ExtensionPointPreferencesViewController {
if tableView.selectedRow == -1 {
var helpText = ""
if ExtensionPointManager.shared.availableExtensionPointTypes.count == 0 {
helpText = NSLocalizedString("You've added all available extensions.", comment: "Extension Explainer")
helpText = NSLocalizedString("label.text.added-all-extensions", comment: "You've added all available extensions.")
}
else if activeExtensionPoints.count == 0 {
helpText = NSLocalizedString("Add an extension by clicking the + button.", comment: "Extension Explainer")
helpText = NSLocalizedString("label.text.add-extension", comment: "Add an extension by clicking the + button.")
} else {
helpText = NSLocalizedString("Select an extension or add a new extension by clicking the + button.", comment: "Extension Explainer")
helpText = NSLocalizedString("label.text.select-or-add-extension", comment: "Select an extension or add a new extension by clicking the + button.")
}
if let controller = children.first {
@@ -244,12 +244,12 @@ private extension ExtensionPointPreferencesViewController {
if tableView.selectedRow == -1 {
var helpText = ""
if ExtensionPointManager.shared.availableExtensionPointTypes.count == 0 {
helpText = NSLocalizedString("You've added all available extensions.", comment: "Extension Explainer")
helpText = NSLocalizedString("label.text.added-all-extensions", comment: "You've added all available extensions.")
}
else if activeExtensionPoints.count == 0 {
helpText = NSLocalizedString("Add an extension by clicking the + button.", comment: "Extension Explainer")
helpText = NSLocalizedString("label.text.add-extension", comment: "Add an extension by clicking the + button.")
} else {
helpText = NSLocalizedString("Select an extension or add a new extension by clicking the + button.", comment: "Extension Explainer")
helpText = NSLocalizedString("label.text.select-or-add-extension", comment: "Select an extension or add a new extension by clicking the + button.")
}
let textHostingController = NSHostingController(rootView: EnableExtensionPointHelpView(helpText: helpText, preferencesController: self))

View File

@@ -109,7 +109,7 @@ private extension GeneralPreferencesViewController {
let defaultBrowser = MacWebBrowser.default
let defaultBrowserFormat = NSLocalizedString("System Default (%@)", comment: "Default browser item title format")
let defaultBrowserFormat = NSLocalizedString("button.title.default-browser.%@", comment: "System Default (%@)")
let defaultBrowserTitle = String(format: defaultBrowserFormat, defaultBrowser.name!)
let item = NSMenuItem(title: defaultBrowserTitle, action: nil, keyEquivalent: "")
let icon = defaultBrowser.icon!
@@ -148,10 +148,10 @@ private extension GeneralPreferencesViewController {
func showNotificationsDeniedError() {
let updateAlert = NSAlert()
updateAlert.alertStyle = .informational
updateAlert.messageText = NSLocalizedString("Enable Notifications", comment: "Notifications")
updateAlert.informativeText = NSLocalizedString("To enable notifications, open Notifications in System Preferences, then find NetNewsWire in the list.", comment: "To enable notifications, open Notifications in System Preferences, then find NetNewsWire in the list.")
updateAlert.addButton(withTitle: NSLocalizedString("Open System Preferences", comment: "Open System Preferences"))
updateAlert.addButton(withTitle: NSLocalizedString("Close", comment: "Close"))
updateAlert.messageText = NSLocalizedString("alert.title.enable-notifications", comment: "Enable Notifications")
updateAlert.informativeText = NSLocalizedString("alert.message.enable-notifications-in-system-settings", comment: "To enable notifications, open Notifications in System Settings, then find NetNewsWire in the list.")
updateAlert.addButton(withTitle: NSLocalizedString("button.title.open-system-settings", comment: "Open System Settings"))
updateAlert.addButton(withTitle: NSLocalizedString("button.title.close", comment: "Close"))
let modalResponse = updateAlert.runModal()
if modalResponse == .alertFirstButtonReturn {
NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.notifications")!)

View File

@@ -35,13 +35,13 @@ private struct ToolbarItemIdentifier {
private let toolbarItemSpecs: [PreferencesToolbarItemSpec] = {
var specs = [PreferencesToolbarItemSpec]()
specs += [PreferencesToolbarItemSpec(identifierRawValue: ToolbarItemIdentifier.General,
name: NSLocalizedString("General", comment: "Preferences"),
name: NSLocalizedString("button.title.general", comment: "General"),
image: AppAssets.preferencesToolbarGeneralImage)]
specs += [PreferencesToolbarItemSpec(identifierRawValue: ToolbarItemIdentifier.Accounts,
name: NSLocalizedString("Accounts", comment: "Preferences"),
name: NSLocalizedString("button.title.accounts", comment: "Account"),
image: AppAssets.preferencesToolbarAccountsImage)]
specs += [PreferencesToolbarItemSpec(identifierRawValue: ToolbarItemIdentifier.Extensions,
name: NSLocalizedString("Extensions", comment: "Preferences"),
name: NSLocalizedString("button.title.extensions", comment: "Extensions"),
image: AppAssets.preferencesToolbarExtensionsImage)]
// Omit the Advanced Preferences for now because the Software Update related functionality is
@@ -50,7 +50,7 @@ private struct ToolbarItemIdentifier {
// of the content in this tab.
#if !MAC_APP_STORE
specs += [PreferencesToolbarItemSpec(identifierRawValue: ToolbarItemIdentifier.Advanced,
name: NSLocalizedString("Advanced", comment: "Preferences"),
name: NSLocalizedString("button.title.advanced", comment: "Advanced"),
image: AppAssets.preferencesToolbarAdvancedImage)]
#endif
return specs

View File

@@ -0,0 +1,12 @@
/* Bundle name */
"CFBundleName" = "NetNewsWire";
/* (No Comment) */
"NetNewsWire Theme" = "NetNewsWire Theme";
/* Privacy - AppleEvents Sending Usage Description */
"NSAppleEventsUsageDescription" = "NetNewsWire communicates with other apps on your Mac when you choose to share an article.";
/* Copyright (human-readable) */
"NSHumanReadableCopyright" = "Copyright © 2002-2022 Brent Simmons. All rights reserved.";

View File

@@ -0,0 +1,702 @@
/* No comment provided by engineer. */
"%@ (%@)" = "%1$@ (%2$@)";
/* On My iPad */
"account.name.ipad" = "On My iPad";
/* On My iPhone */
"account.name.iphone" = "On My iPhone";
/* On My Mac */
"account.name.mac" = "On My Mac";
/* See articles in “%@” */
"activity.title.see-article-in.folder.%@" = "See articles in “%@”";
/* See first unread article */
"activity.title.see-first-unread-article" = "See first unread article";
/* Unable to add iCloud Account. Please make sure you have iCloud and iCloud Drive enabled in System Settings. */
"alert.error.cloudkit-missing" = "Unable to add iCloud Account. Please make sure you have iCloud and iCloud Drive enabled in System Settings.";
/* There is already an account of that type with that username created. */
"alert.error.duplicate-account-username" = "There is already an account of that type with that username created.";
/* Invalid API URL. */
"alert.error.invalid-api-url" = "Invalid API URL.";
/* Error message: The user provided an invalid username or password. */
"alert.error.invalid-username-or-password" = "A username or password is required.";
/* Error message: Unable to save due a Keychain error. */
"alert.error.keychain-error" = "Unable to save account credentials due to a Keychain error.";
/* Network error. Please try later. */
"alert.error.network-error" = "A network error has occurred. Please try later.";
/* This theme cannot be used because of data corruption in the Info.plist: %@. */
"alert.error.theme-data-corruption.%@" = "This theme cannot be used because of data corruption in the Info.plist: %@.";
/* Error message: This theme shares the same name as a provided theme and cannot be imported. */
"alert.error.theme-duplicate-of-provided" = "This theme shares the same name as a provided theme and cannot be imported.";
/* This theme cannot be used because the the key—“%@”—is not found in the Info.plist. */
"alert.error.theme-key-not-found.%@" = "This theme cannot be used because the the key—“%@”—is not found in the Info.plist.";
/* This theme cannot be used because the the type—“%@”—is mismatched in the Info.plist */
"alert.error.theme-type-mismatch.%@" = "This theme cannot be used because the the type—“%@”—is mismatched in the Info.plist";
/* This theme cannot be used because the the value—“%@”—is not found in the Info.plist. */
"alert.error.theme-value-missing.%@" = "This theme cannot be used because the the value—“%@”—is not found in the Info.plist.";
/* The account type in invalid. */
"alert.error.unrecognized-account" = "The account type is not recognised.";
/* Error message: The user must provide a username and password. */
"alert.error.username-and-password-required" = "A username and password are required.";
/* The user must provide a username, password, and URL. */
"alert.error.username-password-url-required" = "A username, password, and API URL are required.";
/* Username required. */
"alert.error.username-required" = "A username is required.";
/* You won't see this message again */
"alert.informative.will-not-see-again" = "You won't see this message again";
/* Some articles dont have links, so they weren't copied. */
"alert.message.articles-without-links" = "Some articles dont have links, so they weren't copied.";
/* Cannot undo action
You can't undo this action. */
"alert.message.cannot-undo-action" = "You can't undo this action.";
/* Are you sure you want to clear the image caches? This will restart NetNewsWire to begin reloading the remote images. */
"alert.message.clear-image-cache-confirmation" = "Are you sure you want to clear the image caches? This will restart NetNewsWire to begin reloading the remote images.";
/* You've already set up an iCloud account. */
"alert.message.cloudkit-already-setup" = "You've already set up an iCloud account.";
/* Are you sure you want to delete the “%@” feed? */
"alert.message.delete-feed.%@" = "Are you sure you want to delete the “%@” feed?";
/* Are you sure you want to delete the “%@” folder? */
"alert.message.delete-folder.%@" = "Are you sure you want to delete the “%@” folder?";
/* Are you sure you want to delete the %d selected items? */
"alert.message.delete-items.%d" = "Are you sure you want to delete the %d selected items?";
/* Cant add this feed because of a download error: “%@” */
"alert.message.download-error.%@" = "Cant add this feed because of a download error: “%@”";
/* The theme “%@” already exists. Overwrite it? */
"alert.message.duplicate-theme.%@" = "The theme “%@” already exists. Overwrite it?";
/* You can enable NetNewsWire notifications in System Settings. */
"alert.message.enable-notifications-in-settings" = "You can enable NetNewsWire notifications in System Settings.";
/* To enable notifications, open Notifications in System Settings, then find NetNewsWire in the list. */
"alert.message.enable-notifications-in-system-settings" = "To enable notifications, open Notifications in System Settings, then find NetNewsWire in the list.";
/* A web browser will open the Feedly login for you to authorize access. */
"alert.message.feedly-web-browser-information" = "A web browser will open the Feedly login for you to authorise access.";
/* The theme “%@” has been installed. */
"alert.message.theme-installed.%@" = "The theme “%@” has been installed.";
/* Twitter Deprecation Message */
"alert.message.twitter-deprecation-message" = "On February 1, 2023, Twitter announced the end of free access to the Twitter API, effective February 9.\n\nSince Twitter does not provide RSS feeds, weve had to use the Twitter API. Without free access to that API, we cant read feeds from Twitter.\n\nWeve left your Twitter feeds intact. If you have any starred items from those feeds, they will remain as long as you dont delete those feeds.\n\nYou can still read whatever you have already downloaded. However, those feeds will no longer update.";
/* Author's website: */
"alert.title.authors-website" = "Author's website:";
/* Deactivate “%@“? */
"alert.title.deactivate-extension.%@" = "Deactivate “%@“?";
/* Delete Feed */
"alert.title.delete-feed" = "Delete Feed";
/* Delete Folder */
"alert.title.delete-folder" = "Delete Folder";
/* Delete Items */
"alert.title.delete-items" = "Delete Items";
/* Delete “%@“ */
"alert.title.delete.%@" = "Delete “%@“";
/* Download Error */
"alert.title.download-error" = "Download Error";
/* Enable Notifications */
"alert.title.enable-notifications" = "Enable Notifications";
/* Error */
"alert.title.error" = "Error";
/* Install theme “%@” by %@? — the order of the variables is theme name, author name */
"alert.title.install-theme.%@.%@" = "Install theme “%@” by %@?";
/* Notifications are not enabled. */
"alert.title.notifications-not-enabled" = "Notifications are not enabled.";
/* Are you sure you want to open %ld articles in your browser? */
"alert.title.open-articles-in-browser.%ld" = "Are you sure you want to open %ld articles in your browser?";
/* Theme error */
"alert.title.theme-error" = "Theme error";
/* Theme installed */
"alert.title.theme-installed" = "Theme installed";
/* Twitter Integration Removed */
"alert.title.twitter-integration-removed" = "Twitter Integration Removed";
/* Alert title when adding a Feedly account and waiting for authorization from the user. */
"alert.title.waiting-for-feedly-access" = "Waiting for Feedly access...";
/* Mark Above as Read */
"button.title-mark-above-as-read.titlecase" = "Mark Above as Read";
/* Mark Below as Read */
"button.title-mark-below-as-read.titlecase" = "Mark Below as Read";
/* 1 day */
"button.title.1-day" = "1 day";
/* 1 month */
"button.title.1-month" = "1 month";
/* 1 week */
"button.title.1-week" = "1 week";
/* 1 year */
"button.title.1-year" = "1 year";
/* 2 days */
"button.title.2-days" = "2 days";
/* Every 2 Hours */
"button.title.2-hours" = "Every 2 Hours";
/* 2 weeks */
"button.title.2-weeks" = "2 weeks";
/* 3 days */
"button.title.3-days" = "3 days";
/* Every 4 Hours */
"button.title.4-hours" = "Every 4 Hours";
/* Every 8 Hours */
"button.title.8-hours" = "Every 8 Hours";
/* Every 10 Minutes */
"button.title.10-minutes" = "Every 10 Minutes";
/* Every 30 Minutes */
"button.title.30-minutes" = "Every 30 Minutes";
/* Account */
"button.title.accounts" = "Account";
/* Add Item */
"button.title.add-item" = "Add Item";
/* Advanced */
"button.title.advanced" = "Advanced";
/* Always Use Reader View */
"button.title.always-use-reader-view" = "Always User Reader View";
/* Article Theme */
"button.title.article-theme" = "Article Theme";
/* Cancel
Cancel button
Cancel Deactivate Extension
Cancel Delete Account
Cancel Install Theme */
"button.title.cancel" = "Cancel";
/* Clean Up */
"button.title.clean-up" = "Clean Up";
/* Clear & Restart */
"button.title.clear-and-restart" = "Clear & Restart";
/* Close */
"button.title.close" = "Close";
/* Continue */
"button.title.continue" = "Continue";
/* Copy Article URL */
"button.title.copy-article-url" = "Copy Article URL";
/* Copy External URL */
"button.title.copy-external-url" = "Copy External URL";
/* Copy Feed URL */
"button.title.copy-feed-url" = "Copy Feed URL";
/* Copy Home Page URL */
"button.title.copy-home-page-url" = "Copy Home Page URL";
/* Create */
"button.title.create" = "Create";
/* Deactivate Extension */
"button.title.deactivate" = "Deactivate";
/* System Default (%@) */
"button.title.default-browser.%@" = "System Default (%@)";
/* Delete
Delete Account */
"button.title.delete" = "Delete";
/* Delete Feed */
"button.title.delete-feed" = "Delete Feed";
/* Delete Feeds */
"button.title.delete-feeds" = "Delete Feeds";
/* Delete Feeds and Folders */
"button.title.delete-feeds-and-folders" = "Delete Feeds and Folders";
/* Delete Folder */
"button.title.delete-folder" = "Delete Folder";
/* Delete Folders */
"button.title.delete-folders" = "Delete Folders";
/* Dismiss */
"button.title.dismiss" = "Dismiss";
/* Every Hour */
"button.title.every-hour" = "Every Hour";
/* Extensions */
"button.title.extensions" = "Extensions";
/* General */
"button.title.general" = "General";
/* Hide Read Articles */
"button.title.hide-read-articles" = "Hide Read Articles";
/* Hide Read Feeds */
"button.title.hide-read-feeds" = "Hide Read Feeds";
/* Hide Sidebar */
"button.title.hide-sidebar" = "Hide Sidebar";
/* Install Theme */
"button.title.install-theme" = "Install Theme";
/* Manually */
"button.title.manually" = "Manually";
/* Mark Above as Read */
"button.title.mark-above-as-read.titlecase" = "Mark Above as Read";
/* Mark All as Read in “%@” */
"button.title.mark-all-as-read.%@" = "Mark All as Read in “%@”";
/* Mark All as Read */
"button.title.mark-all-as-read.titlecase" = "Mark All as Read";
/* Mark as Read */
"button.title.mark-as-read" = "Mark as Read";
/* Mark as Read Older Than */
"button.title.mark-as-read-older-than" = "Mark as Read Older Than";
/* Mark as Starred */
"button.title.mark-as-starred" = "Mark as Starred";
/* Mark as Unread */
"button.title.mark-as-unread" = "Mark as Unread";
/* Mark as Unstarred */
"button.title.mark-as-unstarred" = "Mask as Unstarred";
/* Mark Below as Read */
"button.title.mark-below-as-read.titlecase" = "Mark Below as Read";
/* Mark Read */
"button.title.mark-read" = "Mark Read";
/* Star */
"button.title.mark-star" = "Mark Star";
/* Mark Starred */
"button.title.mark-starred" = "Mark Starred";
/* Mark Unread */
"button.title.mark-unread" = "Mark Unread";
/* Mark Unstarred */
"button.title.mark-unstarred" = "Mark Unstarred";
/* New Feed */
"button.title.new-feed" = "New Feed";
/* New Folder
New Folder... */
"button.title.new-folder" = "New Folder";
/* New Reddit Feed... */
"button.title.new-reddit-feed" = "New Reddit Feed...";
/* New Twitter Feed... */
"button.title.new-twitter-feed" = "New Twitter Feed...";
/* New Web Feed... */
"button.title.new-web-feed" = "New Web Feed...";
/* Next Unread */
"button.title.next-read" = "Next Unread";
/* OK */
"button.title.ok" = "OK";
/* Open */
"button.title.open" = "Open";
/* Open %ld Articles */
"button.title.open-articles.%ld" = "Open %ld Articles";
/* Open Home Page */
"button.title.open-home-page" = "Open Home Page";
/* Open in Browser in Background */
"button.title.open-in-background" = "Open in Browser in Background";
/* Open in Browser */
"button.title.open-in-browser" = "Open in Browser";
/* Open in Browser in Foreground */
"button.title.open-in-foreground" = "Open in Browser in Foreground";
/* New Folder... */
"button.title.open-new-folder" = "New Folder...";
/* Open Settings */
"button.title.open-settings" = "Open Settings";
/* Open System Settings */
"button.title.open-system-settings" = "Open System Settings";
/* Overwrite */
"button.title.overwrite" = "Overwrite";
/* Read Articles Filter */
"button.title.read-articles-filter" = "Read Articles Filter";
/* Reader View */
"button.title.reader-view" = "Reader View";
/* Refresh */
"button.title.refresh" = "Refresh";
/* Rename */
"button.title.rename" = "Rename";
/* Search */
"button.title.search" = "Search";
/* Select “%@” in Sidebar */
"button.title.select-in-sidebar.%@" = "Select “%@” in Sidebar";
/* Share
Share menu name */
"button.title.share" = "Share";
/* Show Read Articles */
"button.title.show-read-articles" = "Show Read Articles";
/* Show Read Feeds */
"button.title.show-read-feeds" = "Show Read Feeds";
/* Show Sidebar */
"button.title.show-sidebar" = "Show Sidebar";
/* Toggle Sidebar */
"button.title.toggle-sidebar" = "Toggle Sidebar";
/* Update */
"button.title.update" = "Update";
/* Show notifications for new articles */
"checkbox.title.show-new-article-notifications" = "Show notifications for new articles";
/* No comment provided by engineer. */
"Continue" = "Continue";
/* Unable to add iCloud Account. Please make sure you have iCloud and iCloud Drive enabled in System Settings. */
"error.description.cloudkit-unavailable" = "Unable to add iCloud Account. Please make sure you have iCloud and iCloud Drive enabled in System Settings.";
/* Unable to create extension. */
"error.message.unable-to-create-extension" = "Unable to create extension.";
/* Markdown formatted link to netnewswire.com */
"label.markdown.netnewswire-website" = "[netnewswire.com](https://netnewswire.com)";
/* Add an account by clicking the + button. */
"label.text.add-account-explainer" = "Add an account by clicking the + button.";
/* Add an extension by clicking the + button. */
"label.text.add-extension" = "Add an extension by clicking the + button.";
/* You've added all available extensions. */
"label.text.added-all-extensions" = "You've added all available extensions.";
/* Article */
"label.text.article" = "Article";
/* Choose an account type to add... */
"label.text.choose-account-to-add" = "Choose an account type to add...";
/* Choose an extension to add... */
"label.text.choose-extension-to-add" = "Choose an extension to add...";
/* iCloud */
"label.text.cloudkit" = "iCloud";
/* Your iCloud account syncs your feeds across your Mac and iOS devices */
"label.text.cloudkit-explainer" = "Your iCloud account syncs your feeds across your Mac and iOS devices";
/* Error - Reader View */
"label.text.error-reader-view" = "Error - Reader View";
/* XX-Large */
"label.text.extra-extra-large" = "XX-Large";
/* X-Large */
"label.text.extra-large" = "X-Large";
/* Feed Provider */
"label.text.feed-provider" = "Feed Provider";
/* An extension that makes websites appear to provide RSS feeds for their content. */
"label.text.feed-provider-explainer" = "An extension that makes websites appear to provide RSS feeds for their content.";
/* Find out more */
"label.text.find-out-more" = "Find out more";
/* Finding feed... */
"label.text.finding-feed" = "Finding feed...";
/* Large */
"label.text.large" = "Large";
/* Link: */
"label.text.link" = "Link:";
/* Local */
"label.text.local" = "Local";
/* Local accounts do not sync your feeds across devices */
"label.text.local-account-explainer" = "Local accounts do not sync your feeds across devices";
/* This extension enables share menu functionality to send selected article text to MarsEdit. You need the MarsEdit application for this to work. */
"label.text.marsedit.explainer" = "This extension enables share menu functionality to send selected article text to MarsEdit. You need the MarsEdit application for this to work.";
/* Medium */
"label.text.medium" = "Medium";
/* This extension enables share menu functionality to send selected article text to Micro.blog. You need the Micro.blog application for this to work. */
"label.text.micro-blog-expaliner" = "This extension enables share menu functionality to send selected article text to Micro.blog. You need the Micro.blog application for this to work.";
/* By Brent Simmons and the NetNewsWire team. */
"label.text.netnewswire-byline" = "By Brent Simmons and the NetNewsWire team.";
/* Dont have a BazQux account? */
"label.text.no-bazqux" = "Dont have a BazQux account?";
/* Dont have a FreshRSS instance? */
"label.text.no-fresh-rss" = "Dont have a FreshRSS instance?";
/* Dont have an InoReader account? */
"label.text.no-inoreader" = "Dont have an InoReader account?";
/* Dont have a The Old Reader account? */
"label.text.no-old-reader" = "Dont have a The Old Reader account?";
/* (No Text) */
"label.text.no-text" = "(No Text)";
/* Posts from r/%@ */
"label.text.posts-from-subreddit.%@" = "Posts from r/%@";
/* Privacy Policy */
"label.text.privacy-policy" = "Privacy Policy";
/* Processing - Reader View */
"label.text.processing-reader-view" = "Processing - Reader View";
/* Reader View */
"label.text.reader-view" = "Reader View";
/* The most active posts */
"label.text.reddit-active-posts" = "The most active posts";
/* The best posts on Reddit for you */
"label.text.reddit-best-posts" = "The best posts on Reddit for you";
/* Your personal Reddit frontpage */
"label.text.reddit-front-page" = "Your personal Reddit frontpage";
/* Select an account or add a new account by clicking the + button. */
"label.text.select-or-add-account-explainer" = "Select an account or add a new account by clicking the + button.";
/* Select an extension or add a new extension by clicking the + button. */
"label.text.select-or-add-extension" = "Select an extension or add a new extension by clicking the + button.";
/* Selected - Reader View */
"label.text.selected-reader-view" = "Selected - Reader View";
/* Self-hosted */
"label.text.self-hosted" = "Self-hosted";
/* Self-hosted accounts sync your feeds across all your devices */
"label.text.self-hosted-accounts-explainer" = "Self-hosted accounts sync your feeds across all your devices";
/* An extension that enables a share menu item that passes article data to a third-party application. */
"label.text.share-extension-explainer" = "An extension that enables a share menu item that passes article data to a third-party application.";
/* Sign in to your BazQux account. */
"label.text.sign-in-bazqux" = "Sign in to your BazQux account.";
/* Sign in to your FreshRSS account. */
"label.text.sign-in-freshrss" = "Sign in to your FreshRSS account.";
/* Sign in to your InoReader account. */
"label.text.sign-in-inoreader" = "Sign in to your InoReader account.";
/* Sign in to your The Old Reader account. */
"label.text.sign-in-old-reader" = "Sign in to your The Old Reader account.";
/* Small */
"label.text.small" = "Small";
/* Subreddit */
"label.text.subreddit" = "Subreddit";
/* Built-in */
"label.text.themes-builtin" = "Built-in Themes";
/* Third Party */
"label.text.themes-third-party" = "Other Themes";
/* Third-Party Integration */
"label.text.third-party-integration" = "Third-Party Integration";
/* Timeline */
"label.text.timeline" = "Timeline";
/* Tweets that contain %@ */
"label.text.tweets-containing.%@" = "Tweets that contain %@";
/* Tweets from everyone you follow */
"label.text.tweets-from-everyone" = "Tweets from everyone you follow";
/* Tweets from @%@ */
"label.text.tweets-from.%@" = "Tweets from @%@";
/* Tweets mentioning you */
"label.text.tweets-mentioning-you" = "Tweets mentioning you";
/* unread */
"label.text.unread" = "unread";
/* Web */
"label.text.web" = "Web";
/* Web accounts sync your feeds across all your devices */
"label.text.web-account-explainer" = "Web accounts sync your feeds across all your devices";
/* Catch up to articles older than... */
"menu.title.catch-up-to-articles" = "Catch up to articles older than...";
/* Choose a location for the exported OPML file. */
"panel.message.export-opml" = "Choose a location for the exported OPML file.";
/* Export OPML */
"panel.prompt.export-opml" = "Export OPML";
/* Export to: */
"panel.textfield.export-opml-destination" = "Export to:";
/* Export OPML */
"panel.title.export-opml" = "Export OPML";
/* Choose a Subscriptions.plist file: */
"panel.title.select-opml-file" = "Choose a Subscriptions.plist file:";
/* All Unread pseudo-feed title */
"smartfeed.title.allunread" = "All Unread";
/* Starred pseudo-feed title */
"smartfeed.title.starred" = "Starred";
/* Today pseudo-feed title */
"smartfeed.title.today" = "Today";
/* Smart Feeds group title */
"smartfeeds.title" = "Smart Feeds";
/* Search: */
"textfield.placeholder.search" = "Search:";
/* Search Term or #hashtag */
"textfield.placeholder.search-term-hashtag" = "Search Term or #hashtag";
/* @name */
"textfield.placeholder.twitter-username" = "@name";
/* Rename %@ to: */
"textfield.prompt.rename-to.%@" = "Rename %@ to:";
/* Create a local account on your Mac. */
"textfield.text.create-a-local-account" = "Create a local account on your Mac.";
/* Sign in to your Feedbin account. */
"textfield.text.sign-in-feedbin" = "Sign in to your Feedbin account.";
/* Sign in to your NewsBlur account. */
"textfield.text.sign-in-newsblur" = "Sign in to your NewsBlur account.";
/* Update your Feedbin account credentials. */
"textfield.text.update-feedbin-credentials" = "Update your Feedbin account credentials.";
/* Update your NewsBlur account credentials. */
"textfield.text.update-newsblur-credentials" = "Update your NewsBlur account credentials.";
/* %d unread */
"window.subtitle.unread-count.%d" = "%d unread";
/* Feed Inspector */
"window.title.feed-inspector" = "Feed Inspector";
/* Folder Inspector */
"window.title.folder-inspector" = "Folder Inspector";
/* Inspector */
"window.title.inspector" = "Inspector";
/* Keyboard Shortcuts */
"window.title.keyboard-shortcuts" = "Keyboard Shortcuts";
/* Multiple */
"window.title.multiple" = "Multiple";
/* Search: %@ */
"window.title.search.%@" = "Search: %@";
/* Smart Feed Inspector */
"window.title.smart-feed-inspector" = "Smart Feed Inspector";

View File

@@ -2,20 +2,20 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Copy Article URL</key>
<key>button.title.copy-article-urls.%ld</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@copy_article_url@</string>
<key>copy_article_url</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>other</key>
<string>Copy Article URLs</string>
<key>one</key>
<string>Copy Article URL</string>
<key>other</key>
<string>Copy Article URLs</string>
</dict>
</dict>
</dict>

View File

@@ -0,0 +1,695 @@
/* On My iPad */
"account.name.ipad" = "On My iPad";
/* On My iPhone */
"account.name.iphone" = "On My iPhone";
/* On My Mac */
"account.name.mac" = "On My Mac";
/* See articles in “%@” */
"activity.title.see-article-in.folder.%@" = "See articles in “%@”";
/* See first unread article */
"activity.title.see-first-unread-article" = "See first unread article";
/* Unable to add iCloud Account. Please make sure you have iCloud and iCloud Drive enabled in System Settings. */
"alert.error.cloudkit-missing" = "Unable to add iCloud Account. Please make sure you have iCloud and iCloud Drive enabled in System Settings.";
/* There is already an account of that type with that username created. */
"alert.error.duplicate-account-username" = "There is already an account of that type with that username created.";
/* Invalid API URL. */
"alert.error.invalid-api-url" = "Invalid API URL.";
/* Error message: The user provided an invalid username or password. */
"alert.error.invalid-username-or-password" = "A username or password is required.";
/* Error message: Unable to save due a Keychain error. */
"alert.error.keychain-error" = "Unable to save account credentials due to a Keychain error.";
/* Network error. Please try later. */
"alert.error.network-error" = "A network error has occurred. Please try later.";
/* This theme cannot be used because of data corruption in the Info.plist: %@. */
"alert.error.theme-data-corruption.%@" = "This theme cannot be used because of data corruption in the Info.plist: %@.";
/* Error message: This theme shares the same name as a provided theme and cannot be imported. */
"alert.error.theme-duplicate-of-provided" = "This theme shares the same name as a provided theme and cannot be imported.";
/* This theme cannot be used because the the key—“%@”—is not found in the Info.plist. */
"alert.error.theme-key-not-found.%@" = "This theme cannot be used because the the key—“%@”—is not found in the Info.plist.";
/* This theme cannot be used because the the type—“%@”—is mismatched in the Info.plist */
"alert.error.theme-type-mismatch.%@" = "This theme cannot be used because the the type—“%@”—is mismatched in the Info.plist";
/* This theme cannot be used because the the value—“%@”—is not found in the Info.plist. */
"alert.error.theme-value-missing.%@" = "This theme cannot be used because the the value—“%@”—is not found in the Info.plist.";
/* The account type in invalid. */
"alert.error.unrecognized-account" = "The account type is not recognized.";
/* Error message: The user must provide a username and password. */
"alert.error.username-and-password-required" = "A username and password are required.";
/* The user must provide a username, password, and URL. */
"alert.error.username-password-url-required" = "A username, password, and API URL are required.";
/* Username required. */
"alert.error.username-required" = "A username is required.";
/* You won't see this message again */
"alert.informative.will-not-see-again" = "You won't see this message again";
/* Some articles dont have links, so they weren't copied. */
"alert.message.articles-without-links" = "Some articles dont have links, so they weren't copied.";
/* Cannot undo action
You can't undo this action. */
"alert.message.cannot-undo-action" = "You can't undo this action.";
/* Are you sure you want to clear the image caches? This will restart NetNewsWire to begin reloading the remote images. */
"alert.message.clear-image-cache-confirmation" = "Are you sure you want to clear the image caches? This will restart NetNewsWire to begin reloading the remote images.";
/* You've already set up an iCloud account. */
"alert.message.cloudkit-already-setup" = "You've already set up an iCloud account.";
/* Are you sure you want to delete the “%@” feed? */
"alert.message.delete-feed.%@" = "Are you sure you want to delete the “%@” feed?";
/* Are you sure you want to delete the “%@” folder? */
"alert.message.delete-folder.%@" = "Are you sure you want to delete the “%@” folder?";
/* Are you sure you want to delete the %d selected items? */
"alert.message.delete-items.%d" = "Are you sure you want to delete the %d selected items?";
/* Cant add this feed because of a download error: “%@” */
"alert.message.download-error.%@" = "Cant add this feed because of a download error: “%@”";
/* The theme “%@” already exists. Overwrite it? */
"alert.message.duplicate-theme.%@" = "The theme “%@” already exists. Overwrite it?";
/* You can enable NetNewsWire notifications in System Settings. */
"alert.message.enable-notifications-in-settings" = "You can enable NetNewsWire notifications in System Settings.";
/* To enable notifications, open Notifications in System Settings, then find NetNewsWire in the list. */
"alert.message.enable-notifications-in-system-settings" = "To enable notifications, open Notifications in System Settings, then find NetNewsWire in the list.";
/* A web browser will open the Feedly login for you to authorize access. */
"alert.message.feedly-web-browser-information" = "A web browser will open the Feedly login for you to authorize access.";
/* The theme “%@” has been installed. */
"alert.message.theme-installed.%@" = "The theme “%@” has been installed.";
/* Twitter Deprecation Message */
"alert.message.twitter-deprecation-message" = "On February 1, 2023, Twitter announced the end of free access to the Twitter API, effective February 9.\n\nSince Twitter does not provide RSS feeds, weve had to use the Twitter API. Without free access to that API, we cant read feeds from Twitter.\n\nWeve left your Twitter feeds intact. If you have any starred items from those feeds, they will remain as long as you dont delete those feeds.\n\nYou can still read whatever you have already downloaded. However, those feeds will no longer update.";
/* Author's website: */
"alert.title.authors-website" = "Author's website:";
/* Deactivate “%@“? */
"alert.title.deactivate-extension.%@" = "Deactivate “%@“?";
/* Delete Feed */
"alert.title.delete-feed" = "Delete Feed";
/* Delete Folder */
"alert.title.delete-folder" = "Delete Folder";
/* Delete Items */
"alert.title.delete-items" = "Delete Items";
/* Delete “%@“ */
"alert.title.delete.%@" = "Delete “%@“";
/* Download Error */
"alert.title.download-error" = "Download Error";
/* Enable Notifications */
"alert.title.enable-notifications" = "Enable Notifications";
/* Error */
"alert.title.error" = "Error";
/* Install theme “%@” by %@? — the order of the variables is theme name, author name */
"alert.title.install-theme.%@.%@" = "Install theme “%@” by %@?";
/* Notifications are not enabled. */
"alert.title.notifications-not-enabled" = "Notifications are not enabled.";
/* Are you sure you want to open %ld articles in your browser? */
"alert.title.open-articles-in-browser.%ld" = "Are you sure you want to open %ld articles in your browser?";
/* Theme error */
"alert.title.theme-error" = "Theme error";
/* Theme installed */
"alert.title.theme-installed" = "Theme installed";
/* Twitter Integration Removed */
"alert.title.twitter-integration-removed" = "Twitter Integration Removed";
/* Alert title when adding a Feedly account and waiting for authorization from the user. */
"alert.title.waiting-for-feedly-access" = "Waiting for Feedly access...";
/* Mark Above as Read */
"button.title-mark-above-as-read.titlecase" = "Mark Above as Read";
/* Mark Below as Read */
"button.title-mark-below-as-read.titlecase" = "Mark Below as Read";
/* 1 day */
"button.title.1-day" = "1 day";
/* 1 month */
"button.title.1-month" = "1 month";
/* 1 week */
"button.title.1-week" = "1 week";
/* 1 year */
"button.title.1-year" = "1 year";
/* 2 days */
"button.title.2-days" = "2 days";
/* Every 2 Hours */
"button.title.2-hours" = "Every 2 Hours";
/* 2 weeks */
"button.title.2-weeks" = "2 weeks";
/* 3 days */
"button.title.3-days" = "3 days";
/* Every 4 Hours */
"button.title.4-hours" = "Every 4 Hours";
/* Every 8 Hours */
"button.title.8-hours" = "Every 8 Hours";
/* Every 10 Minutes */
"button.title.10-minutes" = "Every 10 Minutes";
/* Every 30 Minutes */
"button.title.30-minutes" = "Every 30 Minutes";
/* Account */
"button.title.accounts" = "Account";
/* Add Item */
"button.title.add-item" = "Add Item";
/* Advanced */
"button.title.advanced" = "Advanced";
/* Always Use Reader View */
"button.title.always-use-reader-view" = "Always User Reader View";
/* Article Theme */
"button.title.article-theme" = "Article Theme";
/* Cancel
Cancel button
Cancel Deactivate Extension
Cancel Delete Account
Cancel Install Theme */
"button.title.cancel" = "Cancel";
/* Clean Up */
"button.title.clean-up" = "Clean Up";
/* Clear & Restart */
"button.title.clear-and-restart" = "Clear & Restart";
/* Close */
"button.title.close" = "Close";
/* Continue */
"button.title.continue" = "Continue";
/* Copy Article URL */
"button.title.copy-article-url" = "Copy Article URL";
/* Copy External URL */
"button.title.copy-external-url" = "Copy External URL";
/* Copy Feed URL */
"button.title.copy-feed-url" = "Copy Feed URL";
/* Copy Home Page URL */
"button.title.copy-home-page-url" = "Copy Home Page URL";
/* Create */
"button.title.create" = "Create";
/* Deactivate Extension */
"button.title.deactivate" = "Deactivate";
/* System Default (%@) */
"button.title.default-browser.%@" = "System Default (%@)";
/* Delete
Delete Account */
"button.title.delete" = "Delete";
/* Delete Feed */
"button.title.delete-feed" = "Delete Feed";
/* Delete Feeds */
"button.title.delete-feeds" = "Delete Feeds";
/* Delete Feeds and Folders */
"button.title.delete-feeds-and-folders" = "Delete Feeds and Folders";
/* Delete Folder */
"button.title.delete-folder" = "Delete Folder";
/* Delete Folders */
"button.title.delete-folders" = "Delete Folders";
/* Dismiss */
"button.title.dismiss" = "Dismiss";
/* Every Hour */
"button.title.every-hour" = "Every Hour";
/* Extensions */
"button.title.extensions" = "Extensions";
/* General */
"button.title.general" = "General";
/* Hide Read Articles */
"button.title.hide-read-articles" = "Hide Read Articles";
/* Hide Read Feeds */
"button.title.hide-read-feeds" = "Hide Read Feeds";
/* Hide Sidebar */
"button.title.hide-sidebar" = "Hide Sidebar";
/* Install Theme */
"button.title.install-theme" = "Install Theme";
/* Manually */
"button.title.manually" = "Manually";
/* Mark Above as Read */
"button.title.mark-above-as-read.titlecase" = "Mark Above as Read";
/* Mark All as Read in “%@” */
"button.title.mark-all-as-read.%@" = "Mark All as Read in “%@”";
/* Mark All as Read */
"button.title.mark-all-as-read.titlecase" = "Mark All as Read";
/* Mark as Read */
"button.title.mark-as-read" = "Mark as Read";
/* Mark as Read Older Than */
"button.title.mark-as-read-older-than" = "Mark as Read Older Than";
/* Mark as Starred */
"button.title.mark-as-starred" = "Mark as Starred";
/* Mark as Unread */
"button.title.mark-as-unread" = "Mark as Unread";
/* Mark as Unstarred */
"button.title.mark-as-unstarred" = "Mask as Unstarred";
/* Mark Below as Read */
"button.title.mark-below-as-read.titlecase" = "Mark Below as Read";
/* Mark Read */
"button.title.mark-read" = "Mark Read";
/* Star */
"button.title.mark-star" = "Mark Star";
/* Mark Starred */
"button.title.mark-starred" = "Mark Starred";
/* Mark Unread */
"button.title.mark-unread" = "Mark Unread";
/* Mark Unstarred */
"button.title.mark-unstarred" = "Mark Unstarred";
/* New Feed */
"button.title.new-feed" = "New Feed";
/* New Folder
New Folder... */
"button.title.new-folder" = "New Folder";
/* New Reddit Feed... */
"button.title.new-reddit-feed" = "New Reddit Feed...";
/* New Twitter Feed... */
"button.title.new-twitter-feed" = "New Twitter Feed...";
/* New Web Feed... */
"button.title.new-web-feed" = "New Web Feed...";
/* Next Unread */
"button.title.next-read" = "Next Unread";
/* OK */
"button.title.ok" = "OK";
/* Open */
"button.title.open" = "Open";
/* Open %ld Articles */
"button.title.open-articles.%ld" = "Open %ld Articles";
/* Open Home Page */
"button.title.open-home-page" = "Open Home Page";
/* Open in Browser in Background */
"button.title.open-in-background" = "Open in Browser in Background";
/* Open in Browser */
"button.title.open-in-browser" = "Open in Browser";
/* Open in Browser in Foreground */
"button.title.open-in-foreground" = "Open in Browser in Foreground";
/* New Folder... */
"button.title.open-new-folder" = "New Folder...";
/* Open Settings */
"button.title.open-settings" = "Open Settings";
/* Open System Settings */
"button.title.open-system-settings" = "Open System Settings";
/* Overwrite */
"button.title.overwrite" = "Overwrite";
/* Read Articles Filter */
"button.title.read-articles-filter" = "Read Articles Filter";
/* Reader View */
"button.title.reader-view" = "Reader View";
/* Refresh */
"button.title.refresh" = "Refresh";
/* Rename */
"button.title.rename" = "Rename";
/* Search */
"button.title.search" = "Search";
/* Select “%@” in Sidebar */
"button.title.select-in-sidebar.%@" = "Select “%@” in Sidebar";
/* Share
Share menu name */
"button.title.share" = "Share";
/* Show Read Articles */
"button.title.show-read-articles" = "Show Read Articles";
/* Show Read Feeds */
"button.title.show-read-feeds" = "Show Read Feeds";
/* Show Sidebar */
"button.title.show-sidebar" = "Show Sidebar";
/* Toggle Sidebar */
"button.title.toggle-sidebar" = "Toggle Sidebar";
/* Update */
"button.title.update" = "Update";
/* Show notifications for new articles */
"checkbox.title.show-new-article-notifications" = "Show notifications for new articles";
/* Unable to add iCloud Account. Please make sure you have iCloud and iCloud Drive enabled in System Settings. */
"error.description.cloudkit-unavailable" = "Unable to add iCloud Account. Please make sure you have iCloud and iCloud Drive enabled in System Settings.";
/* Unable to create extension. */
"error.message.unable-to-create-extension" = "Unable to create extension.";
/* Markdown formatted link to netnewswire.com */
"label.markdown.netnewswire-website" = "[netnewswire.com](https://netnewswire.com)";
/* Add an account by clicking the + button. */
"label.text.add-account-explainer" = "Add an account by clicking the + button.";
/* Add an extension by clicking the + button. */
"label.text.add-extension" = "Add an extension by clicking the + button.";
/* You've added all available extensions. */
"label.text.added-all-extensions" = "You've added all available extensions.";
/* Article */
"label.text.article" = "Article";
/* Choose an account type to add... */
"label.text.choose-account-to-add" = "Choose an account type to add...";
/* Choose an extension to add... */
"label.text.choose-extension-to-add" = "Choose an extension to add...";
/* iCloud */
"label.text.cloudkit" = "iCloud";
/* Your iCloud account syncs your feeds across your Mac and iOS devices */
"label.text.cloudkit-explainer" = "Your iCloud account syncs your feeds across your Mac and iOS devices";
/* Error - Reader View */
"label.text.error-reader-view" = "Error - Reader View";
/* XX-Large */
"label.text.extra-extra-large" = "XX-Large";
/* X-Large */
"label.text.extra-large" = "X-Large";
/* Feed Provider */
"label.text.feed-provider" = "Feed Provider";
/* An extension that makes websites appear to provide RSS feeds for their content. */
"label.text.feed-provider-explainer" = "An extension that makes websites appear to provide RSS feeds for their content.";
/* Find out more */
"label.text.find-out-more" = "Find out more";
/* Finding feed... */
"label.text.finding-feed" = "Finding feed...";
/* Large */
"label.text.large" = "Large";
/* Link: */
"label.text.link" = "Link:";
/* Local */
"label.text.local" = "Local";
/* Local accounts do not sync your feeds across devices */
"label.text.local-account-explainer" = "Local accounts do not sync your feeds across devices";
/* This extension enables share menu functionality to send selected article text to MarsEdit. You need the MarsEdit application for this to work. */
"label.text.marsedit.explainer" = "This extension enables share menu functionality to send selected article text to MarsEdit. You need the MarsEdit application for this to work.";
/* Medium */
"label.text.medium" = "Medium";
/* This extension enables share menu functionality to send selected article text to Micro.blog. You need the Micro.blog application for this to work. */
"label.text.micro-blog-expaliner" = "This extension enables share menu functionality to send selected article text to Micro.blog. You need the Micro.blog application for this to work.";
/* By Brent Simmons and the NetNewsWire team. */
"label.text.netnewswire-byline" = "By Brent Simmons and the NetNewsWire team.";
/* Dont have a BazQux account? */
"label.text.no-bazqux" = "Dont have a BazQux account?";
/* Dont have a FreshRSS instance? */
"label.text.no-fresh-rss" = "Dont have a FreshRSS instance?";
/* Dont have an InoReader account? */
"label.text.no-inoreader" = "Dont have an InoReader account?";
/* Dont have a The Old Reader account? */
"label.text.no-old-reader" = "Dont have a The Old Reader account?";
/* (No Text) */
"label.text.no-text" = "(No Text)";
/* Posts from r/%@ */
"label.text.posts-from-subreddit.%@" = "Posts from r/%@";
/* Privacy Policy */
"label.text.privacy-policy" = "Privacy Policy";
/* Processing - Reader View */
"label.text.processing-reader-view" = "Processing - Reader View";
/* Reader View */
"label.text.reader-view" = "Reader View";
/* The most active posts */
"label.text.reddit-active-posts" = "The most active posts";
/* The best posts on Reddit for you */
"label.text.reddit-best-posts" = "The best posts on Reddit for you";
/* Your personal Reddit frontpage */
"label.text.reddit-front-page" = "Your personal Reddit frontpage";
/* Select an account or add a new account by clicking the + button. */
"label.text.select-or-add-account-explainer" = "Select an account or add a new account by clicking the + button.";
/* Select an extension or add a new extension by clicking the + button. */
"label.text.select-or-add-extension" = "Select an extension or add a new extension by clicking the + button.";
/* Selected - Reader View */
"label.text.selected-reader-view" = "Selected - Reader View";
/* Self-hosted */
"label.text.self-hosted" = "Self-hosted";
/* Self-hosted accounts sync your feeds across all your devices */
"label.text.self-hosted-accounts-explainer" = "Self-hosted accounts sync your feeds across all your devices";
/* An extension that enables a share menu item that passes article data to a third-party application. */
"label.text.share-extension-explainer" = "An extension that enables a share menu item that passes article data to a third-party application.";
/* Sign in to your BazQux account. */
"label.text.sign-in-bazqux" = "Sign in to your BazQux account.";
/* Sign in to your FreshRSS account. */
"label.text.sign-in-freshrss" = "Sign in to your FreshRSS account.";
/* Sign in to your InoReader account. */
"label.text.sign-in-inoreader" = "Sign in to your InoReader account.";
/* Sign in to your The Old Reader account. */
"label.text.sign-in-old-reader" = "Sign in to your The Old Reader account.";
/* Small */
"label.text.small" = "Small";
/* Subreddit */
"label.text.subreddit" = "Subreddit";
/* Built-in */
"label.text.themes-builtin" = "Built-in Themes";
/* Third Party */
"label.text.themes-third-party" = "Other Themes";
/* Third-Party Integration */
"label.text.third-party-integration" = "Third-Party Integration";
/* Timeline */
"label.text.timeline" = "Timeline";
/* Tweets that contain %@ */
"label.text.tweets-containing.%@" = "Tweets that contain %@";
/* Tweets from everyone you follow */
"label.text.tweets-from-everyone" = "Tweets from everyone you follow";
/* Tweets from @%@ */
"label.text.tweets-from.%@" = "Tweets from @%@";
/* Tweets mentioning you */
"label.text.tweets-mentioning-you" = "Tweets mentioning you";
/* unread */
"label.text.unread" = "unread";
/* Web */
"label.text.web" = "Web";
/* Web accounts sync your feeds across all your devices */
"label.text.web-account-explainer" = "Web accounts sync your feeds across all your devices";
/* Catch up to articles older than... */
"menu.title.catch-up-to-articles" = "Catch up to articles older than...";
/* Choose a location for the exported OPML file. */
"panel.message.export-opml" = "Choose a location for the exported OPML file.";
/* Export OPML */
"panel.prompt.export-opml" = "Export OPML";
/* Export to: */
"panel.textfield.export-opml-destination" = "Export to:";
/* Export OPML */
"panel.title.export-opml" = "Export OPML";
/* Choose a Subscriptions.plist file: */
"panel.title.select-opml-file" = "Choose a Subscriptions.plist file:";
/* All Unread pseudo-feed title */
"smartfeed.title.allunread" = "All Unread";
/* Starred pseudo-feed title */
"smartfeed.title.starred" = "Starred";
/* Today pseudo-feed title */
"smartfeed.title.today" = "Today";
/* Smart Feeds group title */
"smartfeeds.title" = "Smart Feeds";
/* Search: */
"textfield.placeholder.search" = "Search:";
/* Search Term or #hashtag */
"textfield.placeholder.search-term-hashtag" = "Search Term or #hashtag";
/* @name */
"textfield.placeholder.twitter-username" = "@name";
/* Rename %@ to: */
"textfield.prompt.rename-to.%@" = "Rename %@ to:";
/* Create a local account on your Mac. */
"textfield.text.create-a-local-account" = "Create a local account on your Mac.";
/* Sign in to your Feedbin account. */
"textfield.text.sign-in-feedbin" = "Sign in to your Feedbin account.";
/* Sign in to your NewsBlur account. */
"textfield.text.sign-in-newsblur" = "Sign in to your NewsBlur account.";
/* Update your Feedbin account credentials. */
"textfield.text.update-feedbin-credentials" = "Update your Feedbin account credentials.";
/* Update your NewsBlur account credentials. */
"textfield.text.update-newsblur-credentials" = "Update your NewsBlur account credentials.";
/* %d unread */
"window.subtitle.unread-count.%d" = "%d unread";
/* Feed Inspector */
"window.title.feed-inspector" = "Feed Inspector";
/* Folder Inspector */
"window.title.folder-inspector" = "Folder Inspector";
/* Inspector */
"window.title.inspector" = "Inspector";
/* Keyboard Shortcuts */
"window.title.keyboard-shortcuts" = "Keyboard Shortcuts";
/* Multiple */
"window.title.multiple" = "Multiple";
/* Search: %@ */
"window.title.search.%@" = "Search: %@";
/* Smart Feed Inspector */
"window.title.smart-feed-inspector" = "Smart Feed Inspector";

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>button.title.copy-article-urls.%ld</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>other</key>
<string>Copy Article URLs</string>
<key>one</key>
<string>Copy Article URL</string>
</dict>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,12 @@
/* Bundle display name */
"CFBundleDisplayName" = "Subscribe to Feed";
/* Bundle name */
"CFBundleName" = "Subscribe to Feed";
/* Copyright (human-readable) */
"NSHumanReadableCopyright" = "Copyright © 2019-2022 Brent Simmons. All rights reserved.";
/* Human readable description */
"NSHumanReadableDescription" = "This extension adds a Safari toolbar button for easily subscribing to the syndication feed for the current page.";

View File

@@ -0,0 +1,3 @@
/* Class = "NSTextFieldCell"; title = "Subscribe to Feed"; ObjectID = "2Ec-kd-q2K"; */
"2Ec-kd-q2K.title" = "Subscribe to Feed";

View File

@@ -0,0 +1,9 @@
/* Bundle display name */
"CFBundleDisplayName" = "NetNewsWire";
/* Bundle name */
"CFBundleName" = "NetNewsWire Share Extension MAS";
/* Copyright (human-readable) */
"NSHumanReadableCopyright" = "Copyright © 2020-2022 Ranchero Software. All rights reserved.";

View File

@@ -0,0 +1,36 @@
/* Every 2 Hours */
"button.title.2-hours" = "Every 2 Hours";
/* Every 4 Hours */
"button.title.4-hours" = "Every 4 Hours";
/* Every 8 Hours */
"button.title.8-hours" = "Every 8 Hours";
/* Every 10 Minutes */
"button.title.10-minutes" = "Every 10 Minutes";
/* Every 30 Minutes */
"button.title.30-minutes" = "Every 30 Minutes";
/* Every Hour */
"button.title.every-hour" = "Every Hour";
/* Manually */
"button.title.manually" = "Manually";
/* XX-Large */
"label.text.extra-extra-large" = "XX-Large";
/* X-Large */
"label.text.extra-large" = "X-Large";
/* Large */
"label.text.large" = "Large";
/* Medium */
"label.text.medium" = "Medium";
/* Small */
"label.text.small" = "Small";

View File

@@ -0,0 +1,27 @@
/* Class = "NSButtonCell"; title = "Send"; ObjectID = "2l4-PO-we5"; */
"2l4-PO-we5.title" = "Send";
/* Class = "NSTextFieldCell"; title = "NetNewsWire"; ObjectID = "5Ed-E1-Gf1"; */
"5Ed-E1-Gf1.title" = "NetNewsWire";
/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "6Up-t3-mwm"; */
"6Up-t3-mwm.title" = "Cancel";
/* Class = "NSTextFieldCell"; placeholderString = "Optional"; ObjectID = "27c-xz-zoJ"; */
"27c-xz-zoJ.placeholderString" = "Optional";
/* Class = "NSMenuItem"; title = "Item 3"; ObjectID = "Djb-KO-yjg"; */
"Djb-KO-yjg.title" = "Item 3";
/* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "jf0-bY-EUJ"; */
"jf0-bY-EUJ.title" = "Item 2";
/* Class = "NSTextFieldCell"; title = "Name:"; ObjectID = "Piv-xr-hYI"; */
"Piv-xr-hYI.title" = "Name:";
/* Class = "NSTextFieldCell"; title = "Folder:"; ObjectID = "qp4-R2-aO5"; */
"qp4-R2-aO5.title" = "Folder:";
/* Class = "NSMenuItem"; title = "Item 1"; ObjectID = "wvm-BK-3HS"; */
"wvm-BK-3HS.title" = "Item 1";

View File

@@ -0,0 +1,36 @@
/* Every 2 Hours */
"button.title.2-hours" = "Every 2 Hours";
/* Every 4 Hours */
"button.title.4-hours" = "Every 4 Hours";
/* Every 8 Hours */
"button.title.8-hours" = "Every 8 Hours";
/* Every 10 Minutes */
"button.title.10-minutes" = "Every 10 Minutes";
/* Every 30 Minutes */
"button.title.30-minutes" = "Every 30 Minutes";
/* Every Hour */
"button.title.every-hour" = "Every Hour";
/* Manually */
"button.title.manually" = "Manually";
/* XX-Large */
"label.text.extra-extra-large" = "XX-Large";
/* X-Large */
"label.text.extra-large" = "X-Large";
/* Large */
"label.text.large" = "Large";
/* Medium */
"label.text.medium" = "Medium";
/* Small */
"label.text.small" = "Small";

View File

@@ -0,0 +1,24 @@
/* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "Aat-NW-hPO"; */
"Aat-NW-hPO.title" = "Item 2";
/* Class = "NSMenuItem"; title = "Item 3"; ObjectID = "CVJ-R1-O8v"; */
"CVJ-R1-O8v.title" = "Item 3";
/* Class = "NSButtonCell"; title = "Add Folder"; ObjectID = "F5a-Q7-NMn"; */
"F5a-Q7-NMn.title" = "Add Folder";
/* Class = "NSTextFieldCell"; title = "Folder Name:"; ObjectID = "k8o-om-Rgh"; */
"k8o-om-Rgh.title" = "Folder Name:";
/* Class = "NSWindow"; title = "Add Folder"; ObjectID = "QvC-M9-y7g"; */
"QvC-M9-y7g.title" = "Add Folder";
/* Class = "NSMenuItem"; title = "Item 1"; ObjectID = "SDZ-cp-t7j"; */
"SDZ-cp-t7j.title" = "Item 1";
/* Class = "NSTextFieldCell"; title = "Account:"; ObjectID = "t6T-ar-V3d"; */
"t6T-ar-V3d.title" = "Account:";
/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "VXk-Yp-k6W"; */
"VXk-Yp-k6W.title" = "Cancel";

View File

@@ -0,0 +1,78 @@
/* Class = "NSMenuItem"; title = "Subreddit"; ObjectID = "0gG-oY-8yR"; */
"0gG-oY-8yR.title" = "Subreddit";
/* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "5AA-um-oEb"; */
"5AA-um-oEb.title" = "Label";
/* Class = "NSButtonCell"; title = "Add"; ObjectID = "6NK-Ql-drk"; */
"6NK-Ql-drk.title" = "Add";
/* Class = "NSTextFieldCell"; title = "Name:"; ObjectID = "8ca-Qp-BkT"; */
"8ca-Qp-BkT.title" = "Name:";
/* Class = "NSMenuItem"; title = "Popular"; ObjectID = "177-F8-Esj"; */
"177-F8-Esj.title" = "Popular";
/* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "APc-af-7Um"; */
"APc-af-7Um.title" = "Item 2";
/* Class = "NSMenuItem"; title = "Best"; ObjectID = "aub-jN-9Gq"; */
"aub-jN-9Gq.title" = "Best";
/* Class = "NSTextFieldCell"; title = "Sort:"; ObjectID = "cxl-iF-EB5"; */
"cxl-iF-EB5.title" = "Sort:";
/* Class = "NSMenuItem"; title = "All"; ObjectID = "DBZ-RV-FfV"; */
"DBZ-RV-FfV.title" = "All";
/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "Dop-HC-6Q9"; */
"Dop-HC-6Q9.title" = "Cancel";
/* Class = "NSMenuItem"; title = "Top"; ObjectID = "fuh-g6-Ro7"; */
"fuh-g6-Ro7.title" = "Top";
/* Class = "NSMenuItem"; title = "Item 3"; ObjectID = "fza-9c-2en"; */
"fza-9c-2en.title" = "Item 3";
/* Class = "NSMenuItem"; title = "Item 3"; ObjectID = "j09-9b-bGs"; */
"j09-9b-bGs.title" = "Item 3";
/* Class = "NSMenuItem"; title = "Hot"; ObjectID = "KA5-sN-dho"; */
"KA5-sN-dho.title" = "Hot";
/* Class = "NSMenuItem"; title = "New"; ObjectID = "kUE-J5-iAE"; */
"kUE-J5-iAE.title" = "New";
/* Class = "NSTextFieldCell"; title = "Folder:"; ObjectID = "Kwx-7B-CIu"; */
"Kwx-7B-CIu.title" = "Folder:";
/* Class = "NSTextFieldCell"; title = "Account:"; ObjectID = "LFf-JL-Ahl"; */
"LFf-JL-Ahl.title" = "Account:";
/* Class = "NSTextFieldCell"; placeholderString = "Optional"; ObjectID = "pLP-pL-5R5"; */
"pLP-pL-5R5.placeholderString" = "Optional";
/* Class = "NSTextFieldCell"; title = "Type:"; ObjectID = "qto-IO-a1j"; */
"qto-IO-a1j.title" = "Type:";
/* Class = "NSWindow"; title = "Add Reddit Feed"; ObjectID = "QvC-M9-y7g"; */
"QvC-M9-y7g.title" = "Add Reddit Feed";
/* Class = "NSMenuItem"; title = "Item 1"; ObjectID = "s6D-9M-HpZ"; */
"s6D-9M-HpZ.title" = "Item 1";
/* Class = "NSMenuItem"; title = "u/username"; ObjectID = "Tfk-aQ-RKg"; */
"Tfk-aQ-RKg.title" = "u/username";
/* Class = "NSMenuItem"; title = "Item 1"; ObjectID = "tLJ-zY-CcZ"; */
"tLJ-zY-CcZ.title" = "Item 1";
/* Class = "NSMenuItem"; title = "Home"; ObjectID = "uE6-1a-w5g"; */
"uE6-1a-w5g.title" = "Home";
/* Class = "NSMenuItem"; title = "Rising"; ObjectID = "XIL-2V-O3A"; */
"XIL-2V-O3A.title" = "Rising";
/* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "xTm-Qr-PIp"; */
"xTm-Qr-PIp.title" = "Item 2";

View File

@@ -0,0 +1,51 @@
/* Class = "NSMenuItem"; title = "Search"; ObjectID = "0gG-oY-8yR"; */
"0gG-oY-8yR.title" = "Search";
/* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "5AA-um-oEb"; */
"5AA-um-oEb.title" = "Label";
/* Class = "NSButtonCell"; title = "Add"; ObjectID = "6NK-Ql-drk"; */
"6NK-Ql-drk.title" = "Add";
/* Class = "NSTextFieldCell"; title = "Name:"; ObjectID = "8ca-Qp-BkT"; */
"8ca-Qp-BkT.title" = "Name:";
/* Class = "NSMenuItem"; title = "Mentions"; ObjectID = "177-F8-Esj"; */
"177-F8-Esj.title" = "Mentions";
/* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "APc-af-7Um"; */
"APc-af-7Um.title" = "Item 2";
/* Class = "NSMenuItem"; title = "Screen Name"; ObjectID = "DBZ-RV-FfV"; */
"DBZ-RV-FfV.title" = "Screen Name";
/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "Dop-HC-6Q9"; */
"Dop-HC-6Q9.title" = "Cancel";
/* Class = "NSMenuItem"; title = "Item 3"; ObjectID = "j09-9b-bGs"; */
"j09-9b-bGs.title" = "Item 3";
/* Class = "NSTextFieldCell"; title = "Folder:"; ObjectID = "Kwx-7B-CIu"; */
"Kwx-7B-CIu.title" = "Folder:";
/* Class = "NSTextFieldCell"; title = "Account:"; ObjectID = "LFf-JL-Ahl"; */
"LFf-JL-Ahl.title" = "Account:";
/* Class = "NSTextFieldCell"; placeholderString = "Optional"; ObjectID = "pLP-pL-5R5"; */
"pLP-pL-5R5.placeholderString" = "Optional";
/* Class = "NSTextFieldCell"; title = "Type:"; ObjectID = "qto-IO-a1j"; */
"qto-IO-a1j.title" = "Type:";
/* Class = "NSWindow"; title = "Add Twitter Feed"; ObjectID = "QvC-M9-y7g"; */
"QvC-M9-y7g.title" = "Add Twitter Feed";
/* Class = "NSMenuItem"; title = "@username"; ObjectID = "Tfk-aQ-RKg"; */
"Tfk-aQ-RKg.title" = "@username";
/* Class = "NSMenuItem"; title = "Item 1"; ObjectID = "tLJ-zY-CcZ"; */
"tLJ-zY-CcZ.title" = "Item 1";
/* Class = "NSMenuItem"; title = "Home Timeline"; ObjectID = "uE6-1a-w5g"; */
"uE6-1a-w5g.title" = "Home Timeline";

View File

@@ -0,0 +1,33 @@
/* Class = "NSButtonCell"; title = "Add"; ObjectID = "6NK-Ql-drk"; */
"6NK-Ql-drk.title" = "Add";
/* Class = "NSTextFieldCell"; title = "Name:"; ObjectID = "8ca-Qp-BkT"; */
"8ca-Qp-BkT.title" = "Name:";
/* Class = "NSTextFieldCell"; title = "URL:"; ObjectID = "8jE-9v-BT2"; */
"8jE-9v-BT2.title" = "URL:";
/* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "APc-af-7Um"; */
"APc-af-7Um.title" = "Item 2";
/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "Dop-HC-6Q9"; */
"Dop-HC-6Q9.title" = "Cancel";
/* Class = "NSMenuItem"; title = "Item 3"; ObjectID = "j09-9b-bGs"; */
"j09-9b-bGs.title" = "Item 3";
/* Class = "NSTextFieldCell"; title = "Folder:"; ObjectID = "Kwx-7B-CIu"; */
"Kwx-7B-CIu.title" = "Folder:";
/* Class = "NSTextFieldCell"; placeholderString = "Optional"; ObjectID = "pLP-pL-5R5"; */
"pLP-pL-5R5.placeholderString" = "Optional";
/* Class = "NSWindow"; title = "Add Web Feed"; ObjectID = "QvC-M9-y7g"; */
"QvC-M9-y7g.title" = "Add Web Feed";
/* Class = "NSMenuItem"; title = "Item 1"; ObjectID = "tLJ-zY-CcZ"; */
"tLJ-zY-CcZ.title" = "Item 1";
/* Class = "NSButtonCell"; title = "Open Feed Directory"; ObjectID = "wKl-a9-7FY"; */
"wKl-a9-7FY.title" = "Open Feed Directory";

View File

@@ -0,0 +1,378 @@
/* Class = "NSMenu"; title = "Find"; ObjectID = "1b7-l0-nxx"; */
"1b7-l0-nxx.title" = "Find";
/* Class = "NSMenuItem"; title = "Check for Updates…"; ObjectID = "1nF-7O-aKU"; */
"1nF-7O-aKU.title" = "Check for Updates…";
/* Class = "NSMenuItem"; title = "Customize Toolbar…"; ObjectID = "1UK-8n-QPP"; */
"1UK-8n-QPP.title" = "Customise Toolbar…";
/* Class = "NSMenuItem"; title = "NetNewsWire"; ObjectID = "1Xt-HY-uBw"; */
"1Xt-HY-uBw.title" = "NetNewsWire";
/* Class = "NSMenuItem"; title = "Transformations"; ObjectID = "2oI-Rn-ZJC"; */
"2oI-Rn-ZJC.title" = "Transformations";
/* Class = "NSMenu"; title = "Spelling"; ObjectID = "3IN-sU-3Bg"; */
"3IN-sU-3Bg.title" = "Spelling";
/* Class = "NSMenu"; title = "Speech"; ObjectID = "3rS-ZA-NoH"; */
"3rS-ZA-NoH.title" = "Speech";
/* Class = "NSMenuItem"; title = "Find"; ObjectID = "4EN-yA-p0u"; */
"4EN-yA-p0u.title" = "Find";
/* Class = "NSMenuItem"; title = "Open in Browser"; ObjectID = "4iQ-1v-dTa"; */
"4iQ-1v-dTa.title" = "Open in Browser";
/* Class = "NSMenuItem"; title = "Enter Full Screen"; ObjectID = "4J7-dP-txa"; */
"4J7-dP-txa.title" = "Enter Full Screen";
/* Class = "NSMenuItem"; title = "Quit NetNewsWire"; ObjectID = "4sb-4s-VLi"; */
"4sb-4s-VLi.title" = "Quit NetNewsWire";
/* Class = "NSMenuItem"; title = "About NetNewsWire"; ObjectID = "5kV-Vb-QxS"; */
"5kV-Vb-QxS.title" = "About NetNewsWire";
/* Class = "NSMenuItem"; title = "Edit"; ObjectID = "5QF-Oa-p0T"; */
"5QF-Oa-p0T.title" = "Edit";
/* Class = "NSMenuItem"; title = "Redo"; ObjectID = "6dh-zS-Vam"; */
"6dh-zS-Vam.title" = "Redo";
/* Class = "NSMenuItem"; title = "Mark Below as Read"; ObjectID = "8lZ-XI-I4y"; */
"8lZ-XI-I4y.title" = "Mark Below as Read";
/* Class = "NSMenuItem"; title = "All Unread"; ObjectID = "8ZT-ew-JNc"; */
"8ZT-ew-JNc.title" = "All Unread";
/* Class = "NSMenuItem"; title = "Substitutions"; ObjectID = "9ic-FL-obx"; */
"9ic-FL-obx.title" = "Substitutions";
/* Class = "NSMenuItem"; title = "Debug Search"; ObjectID = "9Ot-wC-s5U"; */
"9Ot-wC-s5U.title" = "Debug Search";
/* Class = "NSMenuItem"; title = "Smart Copy/Paste"; ObjectID = "9yt-4B-nSM"; */
"9yt-4B-nSM.title" = "Smart Copy/Paste";
/* Class = "NSMenuItem"; title = "Info"; ObjectID = "24r-2i-fXR"; */
"24r-2i-fXR.title" = "Info";
/* Class = "NSMenu"; title = "Article"; ObjectID = "57V-gv-vEw"; */
"57V-gv-vEw.title" = "Article";
/* Class = "NSMenuItem"; title = "Correct Spelling Automatically"; ObjectID = "78Y-hA-62v"; */
"78Y-hA-62v.title" = "Correct Spelling Automatically";
/* Class = "NSMenuItem"; title = "Window"; ObjectID = "aUF-d1-5bR"; */
"aUF-d1-5bR.title" = "Window";
/* Class = "NSMenu"; title = "Main Menu"; ObjectID = "AYu-sK-qS6"; */
"AYu-sK-qS6.title" = "Main Menu";
/* Class = "NSMenuItem"; title = "Hide Read Articles"; ObjectID = "b10-sA-Yzi"; */
"b10-sA-Yzi.title" = "Hide Read Articles";
/* Class = "NSMenu"; title = "File"; ObjectID = "bib-Uj-vzu"; */
"bib-Uj-vzu.title" = "File";
/* Class = "NSMenuItem"; title = "Preferences…"; ObjectID = "BOF-NM-1cW"; */
"BOF-NM-1cW.title" = "Preferences…";
/* Class = "NSMenuItem"; title = "Drop Conditional Get Info"; ObjectID = "btO-Tb-2qS"; */
"btO-Tb-2qS.title" = "Drop Conditional Get Info";
/* Class = "NSMenuItem"; title = "Use Selection for Find"; ObjectID = "buJ-ug-pKt"; */
"buJ-ug-pKt.title" = "Use Selection for Find";
/* Class = "NSMenu"; title = "Transformations"; ObjectID = "c8a-y6-VQd"; */
"c8a-y6-VQd.title" = "Transformations";
/* Class = "NSMenuItem"; title = "Add NetNewsWire News Feed"; ObjectID = "cmP-uH-mS8"; */
"cmP-uH-mS8.title" = "Add NetNewsWire News Feed";
/* Class = "NSMenuItem"; title = "Smart Links"; ObjectID = "cwL-P1-jid"; */
"cwL-P1-jid.title" = "Smart Links";
/* Class = "NSMenuItem"; title = "Item"; ObjectID = "CZA-zr-llF"; */
"CZA-zr-llF.title" = "Item";
/* Class = "NSMenuItem"; title = "Make Lower Case"; ObjectID = "d9M-CD-aMd"; */
"d9M-CD-aMd.title" = "Make Lower Case";
/* Class = "NSMenu"; title = "Share"; ObjectID = "Dbl-YW-bmb"; */
"Dbl-YW-bmb.title" = "Share";
/* Class = "NSMenuItem"; title = "File"; ObjectID = "dMs-cI-mzQ"; */
"dMs-cI-mzQ.title" = "File";
/* Class = "NSMenuItem"; title = "Undo"; ObjectID = "dRJ-4n-Yzg"; */
"dRJ-4n-Yzg.title" = "Undo";
/* Class = "NSMenuItem"; title = "Spelling and Grammar"; ObjectID = "Dv1-io-Yv7"; */
"Dv1-io-Yv7.title" = "Spelling and Grammar";
/* Class = "NSMenuItem"; title = "Close Window"; ObjectID = "DVo-aG-piG"; */
"DVo-aG-piG.title" = "Close Window";
/* Class = "NSMenuItem"; title = "Hide Read Feeds"; ObjectID = "E9K-zV-nLv"; */
"E9K-zV-nLv.title" = "Hide Read Feeds";
/* Class = "NSMenuItem"; title = "Open in Browser Inverted"; ObjectID = "EjD-X9-Pjf"; */
"EjD-X9-Pjf.title" = "Open in Browser Inverted";
/* Class = "NSMenuItem"; title = "Import NNW 3 Subscriptions…"; ObjectID = "ely-yi-STg"; */
"ely-yi-STg.title" = "Import NNW 3 Subscriptions…";
/* Class = "NSMenuItem"; title = "Enable Web Inspector"; ObjectID = "EwI-z4-ZA3"; */
"EwI-z4-ZA3.title" = "Enable Web Inspector";
/* Class = "NSMenu"; title = "Help"; ObjectID = "F2S-fz-NVQ"; */
"F2S-fz-NVQ.title" = "Help";
/* Class = "NSMenuItem"; title = "Mark as Read"; ObjectID = "Fc9-c7-2AY"; */
"Fc9-c7-2AY.title" = "Mark as Read";
/* Class = "NSMenu"; title = "Substitutions"; ObjectID = "FeM-D8-WVr"; */
"FeM-D8-WVr.title" = "Substitutions";
/* Class = "NSMenuItem"; title = "NetNewsWire Help"; ObjectID = "FKE-Sm-Kum"; */
"FKE-Sm-Kum.title" = "NetNewsWire Help";
/* Class = "NSMenuItem"; title = "Copy External URL"; ObjectID = "fOF-99-6Iv"; */
"fOF-99-6Iv.title" = "Copy External URL";
/* Class = "NSMenuItem"; title = "Go"; ObjectID = "FPs-q4-hLT"; */
"FPs-q4-hLT.title" = "Go";
/* Class = "NSMenuItem"; title = "Paste"; ObjectID = "gVA-U4-sdL"; */
"gVA-U4-sdL.title" = "Paste";
/* Class = "NSMenuItem"; title = "Test Crash Reporter Window"; ObjectID = "gVd-kQ-efj"; */
"gVd-kQ-efj.title" = "Test Crash Reporter Window";
/* Class = "NSMenuItem"; title = "Force Crash"; ObjectID = "gVt-cz-eoJ"; */
"gVt-cz-eoJ.title" = "Force Crash";
/* Class = "NSMenuItem"; title = "View"; ObjectID = "H8h-7b-M4v"; */
"H8h-7b-M4v.title" = "View";
/* Class = "NSMenuItem"; title = "Mark All as Read"; ObjectID = "HdN-Ks-cwh"; */
"HdN-Ks-cwh.title" = "Mark All as Read";
/* Class = "NSMenuItem"; title = "Show Spelling and Grammar"; ObjectID = "HFo-cy-zxI"; */
"HFo-cy-zxI.title" = "Show Spelling and Grammar";
/* Class = "NSMenuItem"; title = "Text Replacement"; ObjectID = "HFQ-gK-NFA"; */
"HFQ-gK-NFA.title" = "Text Replacement";
/* Class = "NSMenuItem"; title = "Smart Quotes"; ObjectID = "hQb-2v-fYv"; */
"hQb-2v-fYv.title" = "Smart Quotes";
/* Class = "NSMenu"; title = "View"; ObjectID = "HyV-fh-RgO"; */
"HyV-fh-RgO.title" = "View";
/* Class = "NSMenuItem"; title = "Check Document Now"; ObjectID = "hz2-CU-CR7"; */
"hz2-CU-CR7.title" = "Check Document Now";
/* Class = "NSMenu"; title = "Services"; ObjectID = "hz9-B4-Xy5"; */
"hz9-B4-Xy5.title" = "Services";
/* Class = "NSMenuItem"; title = "Oldest Article on Top"; ObjectID = "iii-kP-qoF"; */
"iii-kP-qoF.title" = "Oldest Article on Top";
/* Class = "NSMenuItem"; title = "Clean Up Articles"; ObjectID = "J5h-uQ-57w"; */
"J5h-uQ-57w.title" = "Clean Up Articles";
/* Class = "NSMenuItem"; title = "Share"; ObjectID = "jaf-gh-gSi"; */
"jaf-gh-gSi.title" = "Share";
/* Class = "NSMenuItem"; title = "Show All"; ObjectID = "Kd2-mp-pUS"; */
"Kd2-mp-pUS.title" = "Show All";
/* Class = "NSMenuItem"; title = "New Twitter Feed…"; ObjectID = "ki4-7l-tM6"; */
"ki4-7l-tM6.title" = "New Twitter Feed…";
/* Class = "NSMenuItem"; title = "Show Sidebar"; ObjectID = "kIP-vf-haE"; */
"kIP-vf-haE.title" = "Show Sidebar";
/* Class = "NSMenuItem"; title = "Today"; ObjectID = "L20-jv-7c9"; */
"L20-jv-7c9.title" = "Today";
/* Class = "NSMenuItem"; title = "Bring All to Front"; ObjectID = "LE2-aR-0XJ"; */
"LE2-aR-0XJ.title" = "Bring All to Front";
/* Class = "NSMenuItem"; title = "Main Window"; ObjectID = "LSZ-ci-Jb5"; */
"LSZ-ci-Jb5.title" = "Main Window";
/* Class = "NSMenuItem"; title = "Check Grammar With Spelling"; ObjectID = "mK6-2p-4JG"; */
"mK6-2p-4JG.title" = "Check Grammar With Spelling";
/* Class = "NSMenuItem"; title = "New Reddit Feed…"; ObjectID = "n6h-Bp-CIc"; */
"n6h-Bp-CIc.title" = "New Reddit Feed…";
/* Class = "NSMenuItem"; title = "Article Search…"; ObjectID = "nB2-mv-2i5"; */
"nB2-mv-2i5.title" = "Article Search…";
/* Class = "NSMenuItem"; title = "Sort Articles By"; ObjectID = "nLP-fa-KUi"; */
"nLP-fa-KUi.title" = "Sort Articles By";
/* Class = "NSMenuItem"; title = "Services"; ObjectID = "NMo-om-nkz"; */
"NMo-om-nkz.title" = "Services";
/* Class = "NSMenu"; title = "Debug"; ObjectID = "NOT-8E-ykF"; */
"NOT-8E-ykF.title" = "Debug";
/* Class = "NSMenu"; title = "Go"; ObjectID = "NQW-Ph-lw2"; */
"NQW-Ph-lw2.title" = "Go";
/* Class = "NSMenuItem"; title = "Clear Image Caches"; ObjectID = "o1k-E6-ctu"; */
"o1k-E6-ctu.title" = "Clear Image Caches";
/* Class = "NSMenu"; title = "Sort Articles By"; ObjectID = "OlJ-93-6OP"; */
"OlJ-93-6OP.title" = "Sort Articles By";
/* Class = "NSMenuItem"; title = "Hide NetNewsWire"; ObjectID = "Olw-nP-bQN"; */
"Olw-nP-bQN.title" = "Hide NetNewsWire";
/* Class = "NSMenuItem"; title = "Find Previous"; ObjectID = "OwM-mh-QMV"; */
"OwM-mh-QMV.title" = "Find Previous";
/* Class = "NSMenuItem"; title = "Minimize"; ObjectID = "OY7-WF-poV"; */
"OY7-WF-poV.title" = "Minimise";
/* Class = "NSMenuItem"; title = "Stop Speaking"; ObjectID = "Oyz-dy-DGm"; */
"Oyz-dy-DGm.title" = "Stop Speaking";
/* Class = "NSMenuItem"; title = "Mark Above as Read"; ObjectID = "p1o-EG-Uo8"; */
"p1o-EG-Uo8.title" = "Mark Above as Read";
/* Class = "NSMenuItem"; title = "Show Reader View"; ObjectID = "p5x-Xq-1fW"; */
"p5x-Xq-1fW.title" = "Show Reader View";
/* Class = "NSMenuItem"; title = "Delete"; ObjectID = "pa3-QI-u2k"; */
"pa3-QI-u2k.title" = "Delete";
/* Class = "NSMenuItem"; title = "New Window"; ObjectID = "pGg-Gc-PU2"; */
"pGg-Gc-PU2.title" = "New Window";
/* Class = "NSMenuItem"; title = "Refresh"; ObjectID = "Ppm-uh-K5n"; */
"Ppm-uh-K5n.title" = "Refresh";
/* Class = "NSMenuItem"; title = "NetNewsWire Website"; ObjectID = "q2Z-9K-GBd"; */
"q2Z-9K-GBd.title" = "Website";
/* Class = "NSMenuItem"; title = "Next Unread"; ObjectID = "q3p-nE-m2k"; */
"q3p-nE-m2k.title" = "Next Unread";
/* Class = "NSMenuItem"; title = "Find Next"; ObjectID = "q09-fT-Sye"; */
"q09-fT-Sye.title" = "Find Next";
/* Class = "NSMenuItem"; title = "Copy Article URL"; ObjectID = "qNk-By-jKp"; */
"qNk-By-jKp.title" = "Copy Article URL";
/* Class = "NSMenuItem"; title = "Zoom"; ObjectID = "R4o-n2-Eq4"; */
"R4o-n2-Eq4.title" = "Zoom";
/* Class = "NSMenuItem"; title = "Check Spelling While Typing"; ObjectID = "rbD-Rh-wIN"; */
"rbD-Rh-wIN.title" = "Check Spelling While Typing";
/* Class = "NSMenuItem"; title = "Open Application Support Folder"; ObjectID = "rg6-L6-JUr"; */
"rg6-L6-JUr.title" = "Open Application Support Folder";
/* Class = "NSMenuItem"; title = "Smart Dashes"; ObjectID = "rgM-f4-ycn"; */
"rgM-f4-ycn.title" = "Smart Dashes";
/* Class = "NSMenuItem"; title = "Import Subscriptions…"; ObjectID = "rSl-F4-qo7"; */
"rSl-F4-qo7.title" = "Import Subscriptions…";
/* Class = "NSMenuItem"; title = "Select All"; ObjectID = "Ruw-6m-B2m"; */
"Ruw-6m-B2m.title" = "Select All";
/* Class = "NSMenuItem"; title = "Jump to Selection"; ObjectID = "S0p-oC-mLd"; */
"S0p-oC-mLd.title" = "Jump to Selection";
/* Class = "NSMenuItem"; title = "Show Toolbar"; ObjectID = "snW-S8-Cw5"; */
"snW-S8-Cw5.title" = "Show Toolbar";
/* Class = "NSMenu"; title = "Window"; ObjectID = "Td7-aD-5lo"; */
"Td7-aD-5lo.title" = "Window";
/* Class = "NSMenuItem"; title = "Newest Article on Top"; ObjectID = "TNS-TV-n0U"; */
"TNS-TV-n0U.title" = "Newest Article on Top";
/* Class = "NSMenuItem"; title = "Data Detectors"; ObjectID = "tRr-pd-1PS"; */
"tRr-pd-1PS.title" = "Data Detectors";
/* Class = "NSMenuItem"; title = "Article"; ObjectID = "TzI-3g-N0v"; */
"TzI-3g-N0v.title" = "Article";
/* Class = "NSMenuItem"; title = "Capitalize"; ObjectID = "UEZ-Bs-lqG"; */
"UEZ-Bs-lqG.title" = "Capitalise";
/* Class = "NSMenuItem"; title = "Debug"; ObjectID = "UqE-mp-gtV"; */
"UqE-mp-gtV.title" = "Debug";
/* Class = "NSMenu"; title = "NetNewsWire"; ObjectID = "uQy-DD-JDr"; */
"uQy-DD-JDr.title" = "NetNewsWire";
/* Class = "NSMenuItem"; title = "Cut"; ObjectID = "uRl-iY-unG"; */
"uRl-iY-unG.title" = "Cut";
/* Class = "NSMenuItem"; title = "Hide Others"; ObjectID = "Vdr-fp-XzO"; */
"Vdr-fp-XzO.title" = "Hide Others";
/* Class = "NSMenuItem"; title = "Refresh"; ObjectID = "Veh-SV-KWy"; */
"Veh-SV-KWy.title" = "Refresh";
/* Class = "NSMenuItem"; title = "Make Upper Case"; ObjectID = "vmV-6d-7jI"; */
"vmV-6d-7jI.title" = "Make Upper Case";
/* Class = "NSMenuItem"; title = "Mark as Starred"; ObjectID = "vvo-ZM-8kl"; */
"vvo-ZM-8kl.title" = "Mark as Starred";
/* Class = "NSMenuItem"; title = "Keyboard Shortcuts"; ObjectID = "w6o-j8-cda"; */
"w6o-j8-cda.title" = "Keyboard Shortcuts";
/* Class = "NSMenu"; title = "Edit"; ObjectID = "W48-6f-4Dl"; */
"W48-6f-4Dl.title" = "Edit";
/* Class = "NSMenuItem"; title = "New Web Feed…"; ObjectID = "Was-JA-tGl"; */
"Was-JA-tGl.title" = "New Web Feed…";
/* Class = "NSMenuItem"; title = "Paste and Match Style"; ObjectID = "WeT-3V-zwk"; */
"WeT-3V-zwk.title" = "Paste and Match Style";
/* Class = "NSMenuItem"; title = "New Folder…"; ObjectID = "wkh-LX-Xp1"; */
"wkh-LX-Xp1.title" = "New Folder…";
/* Class = "NSMenuItem"; title = "Help"; ObjectID = "wpr-3q-Mcd"; */
"wpr-3q-Mcd.title" = "Help";
/* Class = "NSMenuItem"; title = "Copy"; ObjectID = "x3v-GG-iWU"; */
"x3v-GG-iWU.title" = "Copy";
/* Class = "NSMenuItem"; title = "Test Crash Log Sender"; ObjectID = "XJG-gO-OKi"; */
"XJG-gO-OKi.title" = "Test Crash Log Sender";
/* Class = "NSMenuItem"; title = "Speech"; ObjectID = "xrE-MZ-jX0"; */
"xrE-MZ-jX0.title" = "Speech";
/* Class = "NSMenuItem"; title = "Export Subscriptions…"; ObjectID = "Xy2-v8-Lj8"; */
"Xy2-v8-Lj8.title" = "Export Subscriptions…";
/* Class = "NSMenuItem"; title = "Find…"; ObjectID = "Xz5-n4-O0W"; */
"Xz5-n4-O0W.title" = "Find…";
/* Class = "NSMenuItem"; title = "Start Speaking"; ObjectID = "Ynk-f8-cLZ"; */
"Ynk-f8-cLZ.title" = "Start Speaking";
/* Class = "NSMenuItem"; title = "Show Substitutions"; ObjectID = "z6F-FW-3nz"; */
"z6F-FW-3nz.title" = "Show Substitutions";
/* Class = "NSMenuItem"; title = "Starred"; ObjectID = "ZRx-me-QXO"; */
"ZRx-me-QXO.title" = "Starred";
/* Class = "NSMenuItem"; title = "Group By Feed"; ObjectID = "Zxm-O6-NRE"; */
"Zxm-O6-NRE.title" = "Group By Feed";

View File

@@ -0,0 +1,36 @@
/* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "1F7-qu-7oN"; */
"1F7-qu-7oN.title" = "Item 2";
/* Class = "NSMenuItem"; title = "Sort"; ObjectID = "4BZ-ya-evy"; */
"4BZ-ya-evy.title" = "Sort";
/* Class = "NSMenuItem"; title = "Newest Article on Top"; ObjectID = "40c-kt-vhO"; */
"40c-kt-vhO.title" = "Newest Article on Top";
/* Class = "NSOutlineView"; ibExternalAccessibilityDescription = "Feeds"; ObjectID = "cnV-kg-Dn2"; */
"cnV-kg-Dn2.ibExternalAccessibilityDescription" = "Feeds";
/* Class = "NSTextFieldCell"; title = "HEADER CELL"; ObjectID = "dRB-0K-qxz"; */
"dRB-0K-qxz.title" = "HEADER CELL";
/* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "dVE-XG-mlU"; */
"dVE-XG-mlU.title" = "Label";
/* Class = "NSWindow"; title = "NetNewsWire"; ObjectID = "IQv-IB-iLA"; */
"IQv-IB-iLA.title" = "NetNewsWire";
/* Class = "NSMenuItem"; title = "Item 3"; ObjectID = "r9E-FO-GoU"; */
"r9E-FO-GoU.title" = "Item 3";
/* Class = "NSMenuItem"; title = "Oldest Article on Top"; ObjectID = "sOF-Ez-vIL"; */
"sOF-Ez-vIL.title" = "Oldest Article on Top";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "sXh-y7-12P"; */
"sXh-y7-12P.title" = "Text Cell";
/* Class = "NSMenuItem"; title = "Group by Feed"; ObjectID = "YSR-5C-Yjd"; */
"YSR-5C-Yjd.title" = "Group by Feed";
/* Class = "NSMenuItem"; title = "Item 1"; ObjectID = "ZDH-CV-Y2s"; */
"ZDH-CV-Y2s.title" = "Item 1";

View File

@@ -0,0 +1,120 @@
/* Class = "NSWindow"; title = "Preferences"; ObjectID = "2C0-LP-36T"; */
"2C0-LP-36T.title" = "Preferences";
/* Class = "NSMenuItem"; title = "Extra Extra Large"; ObjectID = "4Pi-2Y-XmV"; */
"4Pi-2Y-XmV.title" = "Extra Extra Large";
/* Class = "NSTextFieldCell"; title = "Download:"; ObjectID = "6bb-c0-guo"; */
"6bb-c0-guo.title" = "Download:";
/* Class = "NSMenuItem"; title = "Every 4 hours"; ObjectID = "7e2-TV-hth"; */
"7e2-TV-hth.title" = "Every 4 hours";
/* Class = "NSMenuItem"; title = "Every 8 hours"; ObjectID = "7gV-gL-Nue"; */
"7gV-gL-Nue.title" = "Every 8 hours";
/* Class = "NSButtonCell"; title = "Check for Updates"; ObjectID = "AaA-Rr-UYD"; */
"AaA-Rr-UYD.title" = "Check for Updates";
/* Class = "NSTextFieldCell"; title = "Table View Cell"; ObjectID = "CcS-BO-sdv"; */
"CcS-BO-sdv.title" = "Table View Cell";
/* Class = "NSTextFieldCell"; title = "Browser:"; ObjectID = "CgU-dE-Qtb"; */
"CgU-dE-Qtb.title" = "Browser:";
/* Class = "NSMenuItem"; title = "Large"; ObjectID = "ckZ-0Q-rNz"; */
"ckZ-0Q-rNz.title" = "Large";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "Djh-3Q-J0Q"; */
"Djh-3Q-J0Q.title" = "Text Cell";
/* Class = "NSButtonCell"; title = "Check automatically"; ObjectID = "dm8-Xy-0Ba"; */
"dm8-Xy-0Ba.title" = "Check automatically";
/* Class = "NSMenuItem"; title = "Manually only"; ObjectID = "doa-Wq-4Uq"; */
"doa-Wq-4Uq.title" = "Manually only";
/* Class = "NSTextFieldCell"; title = "Press the Shift key to do the opposite."; ObjectID = "EMq-9M-zTJ"; */
"EMq-9M-zTJ.title" = "Press the Shift key to do the opposite.";
/* Class = "NSTextFieldCell"; title = "Safari Extension:"; ObjectID = "Eth-o0-pWM"; */
"Eth-o0-pWM.title" = "Safari Extension:";
/* Class = "NSTextFieldCell"; title = "Refresh Feeds:"; ObjectID = "F7c-lm-g97"; */
"F7c-lm-g97.title" = "Refresh Feeds:";
/* Class = "NSButtonCell"; title = "Release builds"; ObjectID = "F8M-rS-und"; */
"F8M-rS-und.title" = "Release builds";
/* Class = "NSTextFieldCell"; title = "If youre not sure, choose Release builds. Test builds may have bugs, which may include crashing bugs and data loss."; ObjectID = "fOZ-zv-QTc"; */
"fOZ-zv-QTc.title" = "If youre not sure, choose Release builds. Test builds may have bugs, which may include crashing bugs and data loss.";
/* Class = "NSButtonCell"; title = "Test builds"; ObjectID = "Fuf-rU-D6M"; */
"Fuf-rU-D6M.title" = "Test builds";
/* Class = "NSTextFieldCell"; title = "Table View Cell"; ObjectID = "goO-QG-kk7"; */
"goO-QG-kk7.title" = "Table View Cell";
/* Class = "NSViewController"; title = "General"; ObjectID = "iuH-lz-18x"; */
"iuH-lz-18x.title" = "General";
/* Class = "NSMenuItem"; title = "Medium"; ObjectID = "jMV-2o-5Oh"; */
"jMV-2o-5Oh.title" = "Medium";
/* Class = "NSButtonCell"; title = "Send automatically"; ObjectID = "jnc-C5-4oI"; */
"jnc-C5-4oI.title" = "Send automatically";
/* Class = "NSTextFieldCell"; title = "Article Theme:"; ObjectID = "MQe-Za-N8J"; */
"MQe-Za-N8J.title" = "Article Theme:";
/* Class = "NSMenuItem"; title = "Every 2 hours"; ObjectID = "o1h-xo-elW"; */
"o1h-xo-elW.title" = "Every 2 hours";
/* Class = "NSMenuItem"; title = "Safari"; ObjectID = "ObP-qK-qDJ"; */
"ObP-qK-qDJ.title" = "Safari";
/* Class = "NSMenuItem"; title = "Default"; ObjectID = "Pkl-EA-Goa"; */
"Pkl-EA-Goa.title" = "Default";
/* Class = "NSTextFieldCell"; title = "Crash logs:"; ObjectID = "qcq-fU-Ks0"; */
"qcq-fU-Ks0.title" = "Crash logs:";
/* Class = "NSMenuItem"; title = "Every hour"; ObjectID = "Qjt-qr-WER"; */
"Qjt-qr-WER.title" = "Every hour";
/* Class = "NSMenuItem"; title = "Extra Large"; ObjectID = "qMe-6g-Vme"; */
"qMe-6g-Vme.title" = "Extra Large";
/* Class = "NSTextFieldCell"; title = "Privacy Policy"; ObjectID = "rJu-r1-AW4"; */
"rJu-r1-AW4.title" = "Privacy Policy";
/* Class = "NSMenuItem"; title = "Small"; ObjectID = "roB-Mu-Ht7"; */
"roB-Mu-Ht7.title" = "Small";
/* Class = "NSMenuItem"; title = "Every 30 minutes"; ObjectID = "rZU-Tg-xwo"; */
"rZU-Tg-xwo.title" = "Every 30 minutes";
/* Class = "NSButtonCell"; title = "Open feeds in default news reader"; ObjectID = "SkZ-tE-blK"; */
"SkZ-tE-blK.title" = "Open feeds in default news reader";
/* Class = "NSButtonCell"; title = "Open web pages in background in browser"; ObjectID = "t0a-LN-rCv"; */
"t0a-LN-rCv.title" = "Open web pages in background in browser";
/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "uax-iF-gzP"; */
"uax-iF-gzP.title" = "Text Cell";
/* Class = "NSButtonCell"; title = "Open feeds in NetNewsWire"; ObjectID = "uvx-O8-HvU"; */
"uvx-O8-HvU.title" = "Open feeds in NetNewsWire";
/* Class = "NSTextFieldCell"; title = "Article Text Size:"; ObjectID = "xQu-QV-91i"; */
"xQu-QV-91i.title" = "Article Text Size:";
/* Class = "NSButtonCell"; title = "Open Themes Folder"; ObjectID = "ySX-5i-SP1"; */
"ySX-5i-SP1.title" = "Open Themes Folder";
/* Class = "NSMenuItem"; title = "Every 10 minutes"; ObjectID = "zmy-xe-mVw"; */
"zmy-xe-mVw.title" = "Every 10 minutes";
/* Class = "NSTextFieldCell"; title = "App Updates:"; ObjectID = "zqG-X2-E9b"; */
"zqG-X2-E9b.title" = "App Updates:";

View File

@@ -0,0 +1,12 @@
/* Class = "NSTextFieldCell"; title = "<<Rename prompt>>"; ObjectID = "7Os-lV-Jer"; */
"7Os-lV-Jer.title" = "<<Rename prompt>>";
/* Class = "NSButtonCell"; title = "Rename"; ObjectID = "gcS-uM-zjx"; */
"gcS-uM-zjx.title" = "Rename";
/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "oe4-cJ-2V8"; */
"oe4-cJ-2V8.title" = "Cancel";
/* Class = "NSWindow"; title = "Rename"; ObjectID = "QvC-M9-y7g"; */
"QvC-M9-y7g.title" = "Rename";

View File

@@ -8,7 +8,6 @@
/* Begin PBXBuildFile section */
1701E1B52568983D009453D8 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1701E1B72568983D009453D8 /* Localizable.strings */; };
1701E1E725689D1E009453D8 /* Localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1701E1E625689D1E009453D8 /* Localized.swift */; };
17071EF026F8137400F5E71D /* ArticleTheme+Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17071EEF26F8137400F5E71D /* ArticleTheme+Notifications.swift */; };
17071EF126F8137400F5E71D /* ArticleTheme+Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17071EEF26F8137400F5E71D /* ArticleTheme+Notifications.swift */; };
1710B9132552354E00679C0D /* AddAccountHelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1710B9122552354E00679C0D /* AddAccountHelpView.swift */; };
@@ -49,7 +48,6 @@
179D280D26F73D83003B2E0A /* ArticleThemePlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179D280C26F73D83003B2E0A /* ArticleThemePlist.swift */; };
179DB1DFBCF9177104B12E0F /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; };
179DB3CE822BFCC2D774D9F4 /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; };
17D0682C2564F47E00C0B37E /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 17D0682B2564F47E00C0B37E /* Localizable.stringsdict */; };
17D643B126F8A436008D4C05 /* ArticleThemeDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D643B026F8A436008D4C05 /* ArticleThemeDownloader.swift */; };
17D643B226F8A436008D4C05 /* ArticleThemeDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D643B026F8A436008D4C05 /* ArticleThemeDownloader.swift */; };
17E0084625941887000C23F0 /* SizeCategories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17E0084525941887000C23F0 /* SizeCategories.swift */; };
@@ -783,7 +781,6 @@
84F9EAF4213660A100CF2DE4 /* testGenericScript.applescript in Sources */ = {isa = PBXBuildFile; fileRef = 84F9EAE1213660A100CF2DE4 /* testGenericScript.applescript */; };
84F9EAF5213660A100CF2DE4 /* establishMainWindowStartingState.applescript in Sources */ = {isa = PBXBuildFile; fileRef = 84F9EAE2213660A100CF2DE4 /* establishMainWindowStartingState.applescript */; };
84FF69B11FC3793300DC198E /* FaviconURLFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84FF69B01FC3793300DC198E /* FaviconURLFinder.swift */; };
B20180AB28E3B76F0059686A /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = B20180AA28E3B76F0059686A /* Localizable.stringsdict */; };
B24E9ADC245AB88400DA5718 /* NSAttributedString+NetNewsWire.swift in Sources */ = {isa = PBXBuildFile; fileRef = B24E9ABA245AB88300DA5718 /* NSAttributedString+NetNewsWire.swift */; };
B24E9ADD245AB88400DA5718 /* NSAttributedString+NetNewsWire.swift in Sources */ = {isa = PBXBuildFile; fileRef = B24E9ABA245AB88300DA5718 /* NSAttributedString+NetNewsWire.swift */; };
B24E9ADE245AB88400DA5718 /* NSAttributedString+NetNewsWire.swift in Sources */ = {isa = PBXBuildFile; fileRef = B24E9ABA245AB88300DA5718 /* NSAttributedString+NetNewsWire.swift */; };
@@ -832,9 +829,24 @@
DF59F072292085B800ACD33D /* ColorPaletteSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF59F071292085B800ACD33D /* ColorPaletteSelectorView.swift */; };
DF59F0742920DB5100ACD33D /* AccountsManagementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF59F0732920DB5100ACD33D /* AccountsManagementView.swift */; };
DF5AD10128D6922200CA3BF7 /* SmartFeedSummaryWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1768144D2564BCE000D98635 /* SmartFeedSummaryWidget.swift */; };
DF6DE50A2965907A002EC085 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE5082965907A002EC085 /* Localizable.strings */; };
DF6DE50D2965924C002EC085 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE50B2965924C002EC085 /* InfoPlist.strings */; };
DF6DE5102965924C002EC085 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE50E2965924C002EC085 /* InfoPlist.strings */; };
DF6DE5142965924C002EC085 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE5122965924C002EC085 /* InfoPlist.strings */; };
DF6DE5152965924C002EC085 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE5122965924C002EC085 /* InfoPlist.strings */; };
DF6DE5182965924C002EC085 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE5162965924C002EC085 /* InfoPlist.strings */; };
DF6DE5192965924C002EC085 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE5162965924C002EC085 /* InfoPlist.strings */; };
DF6DE51C2965924C002EC085 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE51A2965924C002EC085 /* InfoPlist.strings */; };
DF6DE51D2965924C002EC085 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE51A2965924C002EC085 /* InfoPlist.strings */; };
DF6DE5202965924D002EC085 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE51E2965924C002EC085 /* Localizable.strings */; };
DF6DE5212965924D002EC085 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE51E2965924C002EC085 /* Localizable.strings */; };
DF6DE52529659443002EC085 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE52329659443002EC085 /* InfoPlist.strings */; };
DF6DE5282965971A002EC085 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DF6DE5262965971A002EC085 /* InfoPlist.strings */; };
DF766FED29377FD9006FBBE2 /* ExtensionsManagementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF766FEC29377FD9006FBBE2 /* ExtensionsManagementView.swift */; };
DF790D6228E990A900455FC7 /* AboutData.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF790D6128E990A900455FC7 /* AboutData.swift */; };
DF84E563295122BA0045C334 /* TimelineCustomizerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF84E562295122BA0045C334 /* TimelineCustomizerView.swift */; };
DF93DB2B296A319000586C0E /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DF93DB2D296A319000586C0E /* Localizable.stringsdict */; };
DF93DB2F296A42BD00586C0E /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DF93DB31296A42BD00586C0E /* Localizable.stringsdict */; };
DFB3497A294A962D00BC81AD /* AddAccountListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFB34979294A962D00BC81AD /* AddAccountListView.swift */; };
DFB34980294B085100BC81AD /* AccountInspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFB3497F294B085100BC81AD /* AccountInspectorView.swift */; };
DFB34988294B447F00BC81AD /* InjectedNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFB34987294B447F00BC81AD /* InjectedNavigationView.swift */; };
@@ -847,6 +859,9 @@
DFB349A0294E87B700BC81AD /* LocalAddAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFB3499F294E87B700BC81AD /* LocalAddAccountView.swift */; };
DFB349A2294E90B500BC81AD /* FeedbinAddAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFB349A1294E90B500BC81AD /* FeedbinAddAccountView.swift */; };
DFB349A4294E914D00BC81AD /* AccountSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFB349A3294E914D00BC81AD /* AccountSectionHeader.swift */; };
DFB616A92965300400A359AB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DFB616A72965300400A359AB /* Localizable.strings */; };
DFB616AC2965300400A359AB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DFB616AA2965300400A359AB /* Localizable.strings */; };
DFB616AD2965300400A359AB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DFB616AA2965300400A359AB /* Localizable.strings */; };
DFBB4EAC2951BC0200639228 /* NNWThemeDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFBB4EAB2951BC0200639228 /* NNWThemeDocument.swift */; };
DFBB4EAD2951BC0200639228 /* NNWThemeDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFBB4EAB2951BC0200639228 /* NNWThemeDocument.swift */; };
DFBB4EAE2951BC0200639228 /* NNWThemeDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFBB4EAB2951BC0200639228 /* NNWThemeDocument.swift */; };
@@ -865,6 +880,7 @@
DFD406FA291FB5E400C02962 /* SettingsRows.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD406F9291FB5E400C02962 /* SettingsRows.swift */; };
DFD406FC291FB63B00C02962 /* SettingsHelpSheets.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD406FB291FB63B00C02962 /* SettingsHelpSheets.swift */; };
DFD406FF291FDC0C00C02962 /* DisplayAndBehaviorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD406FE291FDC0C00C02962 /* DisplayAndBehaviorsView.swift */; };
DFD86796295D553D0070D62D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DFD86798295D553D0070D62D /* Localizable.strings */; };
DFE522A32953DEF400376B77 /* CustomInsetGroupedRowStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFE522A22953DEF400376B77 /* CustomInsetGroupedRowStyle.swift */; };
DFFB8FC2279B75E300AC21D7 /* Account in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 51BC2F4A24D343A500E90810 /* Account */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
DFFC4E7428E95C01006B82AF /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFC4E7328E95C01006B82AF /* AboutView.swift */; };
@@ -1133,7 +1149,6 @@
/* Begin PBXFileReference section */
1701E1B62568983D009453D8 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
1701E1E625689D1E009453D8 /* Localized.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Localized.swift; sourceTree = "<group>"; };
17071EEF26F8137400F5E71D /* ArticleTheme+Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ArticleTheme+Notifications.swift"; sourceTree = "<group>"; };
1710B9122552354E00679C0D /* AddAccountHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAccountHelpView.swift; sourceTree = "<group>"; };
1710B928255246F900679C0D /* EnableExtensionPointHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnableExtensionPointHelpView.swift; sourceTree = "<group>"; };
@@ -1164,7 +1179,6 @@
178A9F9C2549449F00AB7E9D /* AddAccountsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAccountsView.swift; sourceTree = "<group>"; };
179D280C26F73D83003B2E0A /* ArticleThemePlist.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleThemePlist.swift; sourceTree = "<group>"; };
179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsNewsBlurWindowController.swift; sourceTree = "<group>"; };
17D0682B2564F47E00C0B37E /* Localizable.stringsdict */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; path = Localizable.stringsdict; sourceTree = "<group>"; };
17D643B026F8A436008D4C05 /* ArticleThemeDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleThemeDownloader.swift; sourceTree = "<group>"; };
17D7586C2679C21700B17787 /* NetNewsWire-iOS-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NetNewsWire-iOS-Bridging-Header.h"; sourceTree = "<group>"; };
17E0084525941887000C23F0 /* SizeCategories.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SizeCategories.swift; sourceTree = "<group>"; };
@@ -1537,7 +1551,6 @@
84F9EAE2213660A100CF2DE4 /* establishMainWindowStartingState.applescript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.applescript; path = establishMainWindowStartingState.applescript; sourceTree = "<group>"; };
84F9EAE4213660A100CF2DE4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
84FF69B01FC3793300DC198E /* FaviconURLFinder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FaviconURLFinder.swift; sourceTree = "<group>"; };
B20180AA28E3B76F0059686A /* Localizable.stringsdict */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.stringsdict; path = Localizable.stringsdict; sourceTree = "<group>"; };
B24E9ABA245AB88300DA5718 /* NSAttributedString+NetNewsWire.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+NetNewsWire.swift"; sourceTree = "<group>"; };
B24EFD482330FF99006C6242 /* NetNewsWire-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NetNewsWire-Bridging-Header.h"; sourceTree = "<group>"; };
B24EFD5923310109006C6242 /* WKPreferencesPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKPreferencesPrivate.h; sourceTree = "<group>"; };
@@ -1575,15 +1588,34 @@
DF28B452294FE6C600C4D8CA /* EnableExtensionPointView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnableExtensionPointView.swift; sourceTree = "<group>"; };
DF28B454294FE74A00C4D8CA /* ExtensionSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionSectionHeader.swift; sourceTree = "<group>"; };
DF28B4562950163F00C4D8CA /* EnableExtensionViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnableExtensionViewModel.swift; sourceTree = "<group>"; };
DF332714295BBBB900BFD911 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Main.strings; sourceTree = "<group>"; };
DF332716295BBBBF00BFD911 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LaunchScreenPad.strings; sourceTree = "<group>"; };
DF332718295BBBC200BFD911 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LaunchScreenPhone.strings; sourceTree = "<group>"; };
DF3630EA2936183D00326FB8 /* OPMLDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OPMLDocument.swift; sourceTree = "<group>"; };
DF3630EE293618A900326FB8 /* SettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = "<group>"; };
DF394EFF29357A180081EB6E /* NewArticleNotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewArticleNotificationsView.swift; sourceTree = "<group>"; };
DF47CDB1294803AB00FCD57E /* AddExtensionListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddExtensionListView.swift; sourceTree = "<group>"; };
DF59F071292085B800ACD33D /* ColorPaletteSelectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPaletteSelectorView.swift; sourceTree = "<group>"; };
DF59F0732920DB5100ACD33D /* AccountsManagementView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsManagementView.swift; sourceTree = "<group>"; };
DF6DE5092965907A002EC085 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
DF6DE50C2965924C002EC085 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
DF6DE50F2965924C002EC085 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
DF6DE5112965924C002EC085 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Localizable.strings"; sourceTree = "<group>"; };
DF6DE5132965924C002EC085 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
DF6DE5172965924C002EC085 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
DF6DE51B2965924C002EC085 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
DF6DE51F2965924D002EC085 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Localizable.strings"; sourceTree = "<group>"; };
DF6DE5222965937C002EC085 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
DF6DE52429659443002EC085 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
DF6DE5272965971A002EC085 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
DF766FEC29377FD9006FBBE2 /* ExtensionsManagementView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionsManagementView.swift; sourceTree = "<group>"; };
DF790D6128E990A900455FC7 /* AboutData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutData.swift; sourceTree = "<group>"; };
DF84E562295122BA0045C334 /* TimelineCustomizerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineCustomizerView.swift; sourceTree = "<group>"; };
DF93DB2C296A319000586C0E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
DF93DB2E296A324100586C0E /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "en-GB"; path = "en-GB.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
DF93DB30296A42BD00586C0E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
DF93DB33296A4A8F00586C0E /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Localizable.strings"; sourceTree = "<group>"; };
DF93DB34296A4A9300586C0E /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "en-GB"; path = "en-GB.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
DFB34979294A962D00BC81AD /* AddAccountListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAccountListView.swift; sourceTree = "<group>"; };
DFB3497F294B085100BC81AD /* AccountInspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountInspectorView.swift; sourceTree = "<group>"; };
DFB34987294B447F00BC81AD /* InjectedNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InjectedNavigationView.swift; sourceTree = "<group>"; };
@@ -1595,6 +1627,26 @@
DFB3499F294E87B700BC81AD /* LocalAddAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAddAccountView.swift; sourceTree = "<group>"; };
DFB349A1294E90B500BC81AD /* FeedbinAddAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbinAddAccountView.swift; sourceTree = "<group>"; };
DFB349A3294E914D00BC81AD /* AccountSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSectionHeader.swift; sourceTree = "<group>"; };
DFB616A82965300400A359AB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
DFB616AB2965300400A359AB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
DFB616AE29653A0600A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Main.strings"; sourceTree = "<group>"; };
DFB616AF29653A0600A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "../en-GB.lproj/MainWindow.strings"; sourceTree = "<group>"; };
DFB616B029653A0600A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "../../../en-GB.lproj/RenameSheet.strings"; sourceTree = "<group>"; };
DFB616B129653A0600A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "../en-GB.lproj/AddRedditFeedSheet.strings"; sourceTree = "<group>"; };
DFB616B229653A0600A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "../en-GB.lproj/AddTwitterFeedSheet.strings"; sourceTree = "<group>"; };
DFB616B329653A0600A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "../en-GB.lproj/AddWebFeedSheet.strings"; sourceTree = "<group>"; };
DFB616B429653A0600A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "../../en-GB.lproj/AddFolderSheet.strings"; sourceTree = "<group>"; };
DFB616B529653A0600A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "../en-GB.lproj/Preferences.strings"; sourceTree = "<group>"; };
DFB616B629653A0600A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/SafariExtensionViewController.strings"; sourceTree = "<group>"; };
DFB616B729653A0600A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/ShareViewController.strings"; sourceTree = "<group>"; };
DFB616B829653A0600A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/LaunchScreenPhone.strings"; sourceTree = "<group>"; };
DFB616B929653A0700A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/LaunchScreenPad.strings"; sourceTree = "<group>"; };
DFB616BA29653A0700A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Main.strings"; sourceTree = "<group>"; };
DFB616BB29653A0700A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Intents.strings"; sourceTree = "<group>"; };
DFB616BC29653A0700A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/MainInterface.strings"; sourceTree = "<group>"; };
DFB616BD29653A0700A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Localizable.strings"; sourceTree = "<group>"; };
DFB616BE29653A0700A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Localizable.strings"; sourceTree = "<group>"; };
DFB616BF29653A0700A359AB /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Localizable.strings"; sourceTree = "<group>"; };
DFBB4EAB2951BC0200639228 /* NNWThemeDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NNWThemeDocument.swift; sourceTree = "<group>"; };
DFBB4EAF2951BCAC00639228 /* ArticleThemeManagerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleThemeManagerView.swift; sourceTree = "<group>"; };
DFC14F0E28EA55BD00F6EE86 /* AboutWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutWindowController.swift; sourceTree = "<group>"; };
@@ -1608,6 +1660,7 @@
DFD406FB291FB63B00C02962 /* SettingsHelpSheets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsHelpSheets.swift; sourceTree = "<group>"; };
DFD406FE291FDC0C00C02962 /* DisplayAndBehaviorsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayAndBehaviorsView.swift; sourceTree = "<group>"; };
DFD6AACB27ADE80900463FAD /* NewsFax.nnwtheme */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = NewsFax.nnwtheme; sourceTree = "<group>"; };
DFD86797295D553D0070D62D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
DFE522A22953DEF400376B77 /* CustomInsetGroupedRowStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomInsetGroupedRowStyle.swift; sourceTree = "<group>"; };
DFFC4E7328E95C01006B82AF /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
FF3ABF09232599450074C542 /* ArticleSorterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleSorterTests.swift; sourceTree = "<group>"; };
@@ -1781,6 +1834,7 @@
176814792564BE3C00D98635 /* Resources */,
176813FB2564BB2D00D98635 /* Assets.xcassets */,
176813FD2564BB2D00D98635 /* Info.plist */,
DF6DE5262965971A002EC085 /* InfoPlist.strings */,
);
path = Widget;
sourceTree = "<group>";
@@ -1808,10 +1862,9 @@
176814792564BE3C00D98635 /* Resources */ = {
isa = PBXGroup;
children = (
1701E1E625689D1E009453D8 /* Localized.swift */,
1768147A2564BE5400D98635 /* widget-sample.json */,
1701E1B72568983D009453D8 /* Localizable.strings */,
17D0682B2564F47E00C0B37E /* Localizable.stringsdict */,
DF93DB31296A42BD00586C0E /* Localizable.stringsdict */,
);
path = Resources;
sourceTree = "<group>";
@@ -1823,6 +1876,8 @@
510C416024E5CDE3008226FD /* ShareViewController.swift */,
510C416224E5CDE3008226FD /* ShareViewController.xib */,
510C416524E5CDE3008226FD /* Info.plist */,
DF6DE51E2965924C002EC085 /* Localizable.strings */,
DF6DE51A2965924C002EC085 /* InfoPlist.strings */,
510C416624E5CDE3008226FD /* ShareExtension.entitlements */,
);
path = ShareExtension;
@@ -1914,6 +1969,8 @@
children = (
51314666235A7E4600387FDC /* IntentHandler.swift */,
51314665235A7E4600387FDC /* Info.plist */,
DF6DE50B2965924C002EC085 /* InfoPlist.strings */,
DFB616A72965300400A359AB /* Localizable.strings */,
51314684235A7EB900387FDC /* NetNewsWire_iOS_IntentsExtension.entitlements */,
);
path = IntentsExtension;
@@ -1929,6 +1986,8 @@
51A9A5E52380C8B20033AADF /* ShareFolderPickerFolderCell.xib */,
513C5CEA232571C2003D4054 /* MainInterface.storyboard */,
513C5CED232571C2003D4054 /* Info.plist */,
DF6DE52329659443002EC085 /* InfoPlist.strings */,
DF6DE5082965907A002EC085 /* Localizable.strings */,
515D4FCD2325909200EE1167 /* NetNewsWire_iOS_ShareExtension.entitlements */,
);
path = ShareExtension;
@@ -2210,6 +2269,7 @@
6581C73920CED60100F4AD34 /* SafariExtensionViewController.swift */,
6581C73B20CED60100F4AD34 /* SafariExtensionViewController.xib */,
6581C73E20CED60100F4AD34 /* Info.plist */,
DF6DE5162965924C002EC085 /* InfoPlist.strings */,
6581C73F20CED60100F4AD34 /* netnewswire-subscribe-to-feed.js */,
6581C74120CED60100F4AD34 /* ToolbarItemIcon.pdf */,
6581C74320CED60100F4AD34 /* Subscribe_to_Feed.entitlements */,
@@ -2652,11 +2712,13 @@
children = (
849C64671ED37A5D003D8FC0 /* Assets.xcassets */,
84C9FC8922629E8F00D921D6 /* Credits.rtf */,
B20180AA28E3B76F0059686A /* Localizable.stringsdict */,
DF93DB2D296A319000586C0E /* Localizable.stringsdict */,
84C9FC8A22629E8F00D921D6 /* NetNewsWire.sdef */,
84C9FC9022629ECB00D921D6 /* NetNewsWire.entitlements */,
51F805D32428499E0022C792 /* NetNewsWire-dev.entitlements */,
84C9FC9122629F2200D921D6 /* Info.plist */,
DF6DE5122965924C002EC085 /* InfoPlist.strings */,
DFB616AA2965300400A359AB /* Localizable.strings */,
65ED409F235DEFF00081F399 /* container-migration.plist */,
17192AE12567B3FE00AAEACA /* org.sparkle-project.Downloader.xpc */,
17192AE22567B3FE00AAEACA /* org.sparkle-project.InstallerConnection.xpc */,
@@ -2712,12 +2774,14 @@
84C9FC9A2262A1A900D921D6 /* Resources */ = {
isa = PBXGroup;
children = (
DFD86798295D553D0070D62D /* Localizable.strings */,
5103A9B324216A4200410853 /* blank.html */,
51BB7C302335ACDE008E8144 /* page.html */,
514219572353C28900E07E2C /* main_ios.js */,
17D7586C2679C21700B17787 /* NetNewsWire-iOS-Bridging-Header.h */,
84C9FC9B2262A1A900D921D6 /* Assets.xcassets */,
84C9FC9C2262A1A900D921D6 /* Info.plist */,
DF6DE50E2965924C002EC085 /* InfoPlist.strings */,
84BB0F812333426400DED65E /* NetNewsWire.entitlements */,
51F805ED24284C1C0022C792 /* NetNewsWire-dev.entitlements */,
);
@@ -2970,7 +3034,6 @@
176813EF2564BB2C00D98635 /* Sources */,
176813F02564BB2C00D98635 /* Frameworks */,
176813F12564BB2C00D98635 /* Resources */,
1701E1BF25689B44009453D8 /* SwiftGen Localization */,
17EF6A1725C4E59D002C9F81 /* Embed Frameworks */,
);
buildRules = (
@@ -3348,6 +3411,7 @@
knownRegions = (
en,
Base,
"en-GB",
);
mainGroup = 849C64571ED37A5D003D8FC0;
packageReferences = (
@@ -3388,7 +3452,8 @@
176813FC2564BB2D00D98635 /* Assets.xcassets in Resources */,
1701E1B52568983D009453D8 /* Localizable.strings in Resources */,
1768147B2564BE5400D98635 /* widget-sample.json in Resources */,
17D0682C2564F47E00C0B37E /* Localizable.stringsdict in Resources */,
DF93DB2F296A42BD00586C0E /* Localizable.stringsdict in Resources */,
DF6DE5282965971A002EC085 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3396,7 +3461,9 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DF6DE5212965924D002EC085 /* Localizable.strings in Resources */,
510C416424E5CDE3008226FD /* ShareViewController.xib in Resources */,
DF6DE51D2965924C002EC085 /* InfoPlist.strings in Resources */,
5132779F2591034D0064F1E7 /* icon.icns in Resources */,
51EFDA1B24E6D16A0085C3D6 /* SafariExt.js in Resources */,
);
@@ -3406,6 +3473,8 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DFB616A92965300400A359AB /* Localizable.strings in Resources */,
DF6DE50D2965924C002EC085 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3414,6 +3483,8 @@
buildActionMask = 2147483647;
files = (
515D4FCC2325815A00EE1167 /* SafariExt.js in Resources */,
DF6DE52529659443002EC085 /* InfoPlist.strings in Resources */,
DF6DE50A2965907A002EC085 /* Localizable.strings in Resources */,
51A9A5E62380C8B20033AADF /* ShareFolderPickerFolderCell.xib in Resources */,
51A9A5E42380C8880033AADF /* ShareFolderPickerAccountCell.xib in Resources */,
513C5CEC232571C2003D4054 /* MainInterface.storyboard in Resources */,
@@ -3432,7 +3503,9 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DF6DE5202965924D002EC085 /* Localizable.strings in Resources */,
653813502680E2DA007A082C /* ShareViewController.xib in Resources */,
DF6DE51C2965924C002EC085 /* InfoPlist.strings in Resources */,
653813512680E2DA007A082C /* icon.icns in Resources */,
653813522680E2DA007A082C /* SafariExt.js in Resources */,
);
@@ -3443,6 +3516,7 @@
buildActionMask = 2147483647;
files = (
6581C74220CED60100F4AD34 /* ToolbarItemIcon.pdf in Resources */,
DF6DE5182965924C002EC085 /* InfoPlist.strings in Resources */,
6581C73D20CED60100F4AD34 /* SafariExtensionViewController.xib in Resources */,
6581C74020CED60100F4AD34 /* netnewswire-subscribe-to-feed.js in Resources */,
);
@@ -3461,6 +3535,7 @@
5137C2E526F3F52D009EFEDB /* Sepia.nnwtheme in Resources */,
65ED4056235DEF6C0081F399 /* NetNewsWire.sdef in Resources */,
65ED4057235DEF6C0081F399 /* AccountsDetail.xib in Resources */,
DF6DE5152965924C002EC085 /* InfoPlist.strings in Resources */,
65ED4058235DEF6C0081F399 /* main.js in Resources */,
65ED40A1235DEFF00081F399 /* container-migration.plist in Resources */,
65ED4059235DEF6C0081F399 /* AccountsAddLocal.xib in Resources */,
@@ -3491,6 +3566,7 @@
65ED406B235DEF6C0081F399 /* CrashReporterWindow.xib in Resources */,
65ED406C235DEF6C0081F399 /* Credits.rtf in Resources */,
65ED406D235DEF6C0081F399 /* Inspector.storyboard in Resources */,
DFB616AD2965300400A359AB /* Localizable.strings in Resources */,
65ED406E235DEF6C0081F399 /* AddWebFeedSheet.xib in Resources */,
51077C5927A86D16000C71DB /* Hyperlegible.nnwtheme in Resources */,
51DEE81326FB9233006DAA56 /* Appanoose.nnwtheme in Resources */,
@@ -3503,6 +3579,7 @@
buildActionMask = 2147483647;
files = (
65ED4096235DEF770081F399 /* ToolbarItemIcon.pdf in Resources */,
DF6DE5192965924C002EC085 /* InfoPlist.strings in Resources */,
65ED4097235DEF770081F399 /* SafariExtensionViewController.xib in Resources */,
65ED4098235DEF770081F399 /* netnewswire-subscribe-to-feed.js in Resources */,
);
@@ -3522,10 +3599,10 @@
511D43D2231FA62C00FB1562 /* GlobalKeyboardShortcuts.plist in Resources */,
84C9FCA12262A1B300D921D6 /* Main.storyboard in Resources */,
51BB7C312335ACDE008E8144 /* page.html in Resources */,
512392C324E3451400F11704 /* TwitterAdd.storyboard in Resources */,
516A093723609A3600EAE89B /* SettingsComboTableViewCell.xib in Resources */,
51077C5A27A86D16000C71DB /* Hyperlegible.nnwtheme in Resources */,
DDF9E1D928EDF2FC000BC355 /* notificationSoundBlip.mp3 in Resources */,
DFD86796295D553D0070D62D /* Localizable.strings in Resources */,
51DEE81A26FBFF84006DAA56 /* Promenade.nnwtheme in Resources */,
1768140B2564BB8300D98635 /* NetNewsWire_iOSwidgetextension_target.xcconfig in Resources */,
5103A9B424216A4200410853 /* blank.html in Resources */,
@@ -3543,6 +3620,7 @@
514219582353C28900E07E2C /* main_ios.js in Resources */,
DFCE4F9528EF278300405869 /* Thanks.md in Resources */,
51DEE81426FB9233006DAA56 /* Appanoose.nnwtheme in Resources */,
DF6DE5102965924C002EC085 /* InfoPlist.strings in Resources */,
51E36E8C239D6765006F47A5 /* AddFeedSelectFolderTableViewCell.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -3561,6 +3639,7 @@
84C9FC7D22629E1200D921D6 /* AccountsDetail.xib in Resources */,
5137C2E426F3F52D009EFEDB /* Sepia.nnwtheme in Resources */,
517630042336215100E15FFF /* main.js in Resources */,
DFB616AC2965300400A359AB /* Localizable.strings in Resources */,
65ED40A0235DEFF00081F399 /* container-migration.plist in Resources */,
5144EA362279FC3D00D19003 /* AccountsAddLocal.xib in Resources */,
51D0214626ED617100FF2E0F /* core.css in Resources */,
@@ -3569,6 +3648,7 @@
DFCE4F9128EF26F100405869 /* About.plist in Resources */,
84C9FC8C22629E8F00D921D6 /* KeyboardShortcuts.html in Resources */,
B27EEBF9244D15F3000932E6 /* stylesheet.css in Resources */,
DF6DE5142965924C002EC085 /* InfoPlist.strings in Resources */,
5144EA3B227A379E00D19003 /* ImportOPMLSheet.xib in Resources */,
844B5B691FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist in Resources */,
DDF9E1D728EDF2FC000BC355 /* notificationSoundBlip.mp3 in Resources */,
@@ -3590,7 +3670,7 @@
51333D3B2468615D00EB5C91 /* AddRedditFeedSheet.xib in Resources */,
BDCB516724282C8A00102A80 /* AccountsNewsBlur.xib in Resources */,
5103A9982421643300410853 /* blank.html in Resources */,
B20180AB28E3B76F0059686A /* Localizable.stringsdict in Resources */,
DF93DB2B296A319000586C0E /* Localizable.stringsdict in Resources */,
515A516E243E7F950089E588 /* ExtensionPointDetail.xib in Resources */,
84BAE64921CEDAF20046DB56 /* CrashReporterWindow.xib in Resources */,
51DEE81226FB9233006DAA56 /* Appanoose.nnwtheme in Resources */,
@@ -3611,24 +3691,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
1701E1BF25689B44009453D8 /* SwiftGen Localization */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "SwiftGen Localization";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if ! command -v swiftgen &> /dev/null\nthen\n echo \"swiftgen could not be found\"\n exit\nfi\n\nswiftgen run strings -t structured-swift5 \"$PROJECT_DIR/Widget/Resources/en.lproj/Localizable.strings\" \"$PROJECT_DIR/Widget/Resources/Localizable.stringsdict\" --output \"$PROJECT_DIR/Widget/Resources/Localized.swift\";\n";
};
515D50802326D02600EE1167 /* Run Script: Verify No Build Settings */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 12;
@@ -3814,7 +3876,6 @@
1768146C2564BD8100D98635 /* WidgetDeepLinks.swift in Sources */,
1768143E2564BCC800D98635 /* TodayWidget.swift in Sources */,
1768142D2564BCA800D98635 /* TimelineProvider.swift in Sources */,
1701E1E725689D1E009453D8 /* Localized.swift in Sources */,
176814652564BD7F00D98635 /* WidgetData.swift in Sources */,
1768145E2564BD7B00D98635 /* WidgetDataDecoder.swift in Sources */,
176814132564BC8A00D98635 /* WidgetBundle.swift in Sources */,
@@ -4563,6 +4624,7 @@
isa = PBXVariantGroup;
children = (
1701E1B62568983D009453D8 /* en */,
DF93DB33296A4A8F00586C0E /* en-GB */,
);
name = Localizable.strings;
sourceTree = "<group>";
@@ -4571,6 +4633,7 @@
isa = PBXVariantGroup;
children = (
510C416324E5CDE3008226FD /* Base */,
DFB616B729653A0600A359AB /* en-GB */,
);
name = ShareViewController.xib;
sourceTree = "<group>";
@@ -4579,6 +4642,8 @@
isa = PBXVariantGroup;
children = (
511D43EE231FBDE800FB1562 /* Base */,
DF332716295BBBBF00BFD911 /* en */,
DFB616B929653A0700A359AB /* en-GB */,
);
name = LaunchScreenPad.storyboard;
sourceTree = "<group>";
@@ -4588,6 +4653,7 @@
children = (
51314706235C41FC00387FDC /* Base */,
51314714235C420900387FDC /* en */,
DFB616BB29653A0700A359AB /* en-GB */,
);
name = Intents.intentdefinition;
sourceTree = "<group>";
@@ -4596,6 +4662,7 @@
isa = PBXVariantGroup;
children = (
51333D3A2468615D00EB5C91 /* Base */,
DFB616B129653A0600A359AB /* en-GB */,
);
name = AddRedditFeedSheet.xib;
sourceTree = "<group>";
@@ -4604,14 +4671,25 @@
isa = PBXVariantGroup;
children = (
513C5CEB232571C2003D4054 /* Base */,
DFB616BC29653A0700A359AB /* en-GB */,
);
name = MainInterface.storyboard;
sourceTree = "<group>";
};
514A897F244FD63F0085E65D /* AddTwitterFeedSheet.xib */ = {
isa = PBXVariantGroup;
children = (
514A8980244FD63F0085E65D /* Base */,
DFB616B229653A0600A359AB /* en-GB */,
);
name = AddTwitterFeedSheet.xib;
sourceTree = "<group>";
};
6581C73B20CED60100F4AD34 /* SafariExtensionViewController.xib */ = {
isa = PBXVariantGroup;
children = (
6581C73C20CED60100F4AD34 /* Base */,
DFB616B629653A0600A359AB /* en-GB */,
);
name = SafariExtensionViewController.xib;
sourceTree = "<group>";
@@ -4620,6 +4698,7 @@
isa = PBXVariantGroup;
children = (
848363012262A3BC00DA1D35 /* Base */,
DFB616B329653A0600A359AB /* en-GB */,
);
name = AddWebFeedSheet.xib;
sourceTree = "<group>";
@@ -4628,6 +4707,7 @@
isa = PBXVariantGroup;
children = (
848363042262A3CC00DA1D35 /* Base */,
DFB616B429653A0600A359AB /* en-GB */,
);
name = AddFolderSheet.xib;
sourceTree = "<group>";
@@ -4636,6 +4716,7 @@
isa = PBXVariantGroup;
children = (
848363072262A3DD00DA1D35 /* Base */,
DFB616AE29653A0600A359AB /* en-GB */,
);
name = Main.storyboard;
sourceTree = "<group>";
@@ -4644,6 +4725,7 @@
isa = PBXVariantGroup;
children = (
8483630A2262A3F000DA1D35 /* Base */,
DFB616B029653A0600A359AB /* en-GB */,
);
name = RenameSheet.xib;
sourceTree = "<group>";
@@ -4652,6 +4734,7 @@
isa = PBXVariantGroup;
children = (
8483630D2262A3FE00DA1D35 /* Base */,
DFB616AF29653A0600A359AB /* en-GB */,
);
name = MainWindow.storyboard;
sourceTree = "<group>";
@@ -4660,6 +4743,7 @@
isa = PBXVariantGroup;
children = (
84C9FC8122629E4800D921D6 /* Base */,
DFB616B529653A0600A359AB /* en-GB */,
);
name = Preferences.storyboard;
sourceTree = "<group>";
@@ -4668,6 +4752,8 @@
isa = PBXVariantGroup;
children = (
84C9FCA02262A1B300D921D6 /* Base */,
DF332714295BBBB900BFD911 /* en */,
DFB616BA29653A0700A359AB /* en-GB */,
);
name = Main.storyboard;
sourceTree = "<group>";
@@ -4676,10 +4762,131 @@
isa = PBXVariantGroup;
children = (
84C9FCA32262A1B800D921D6 /* Base */,
DF332718295BBBC200BFD911 /* en */,
DFB616B829653A0600A359AB /* en-GB */,
);
name = LaunchScreenPhone.storyboard;
sourceTree = "<group>";
};
DF6DE5082965907A002EC085 /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
DF6DE5092965907A002EC085 /* en */,
DF6DE5112965924C002EC085 /* en-GB */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
DF6DE50B2965924C002EC085 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
DF6DE50C2965924C002EC085 /* en-GB */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
DF6DE50E2965924C002EC085 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
DF6DE50F2965924C002EC085 /* en-GB */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
DF6DE5122965924C002EC085 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
DF6DE5132965924C002EC085 /* en-GB */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
DF6DE5162965924C002EC085 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
DF6DE5172965924C002EC085 /* en-GB */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
DF6DE51A2965924C002EC085 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
DF6DE51B2965924C002EC085 /* en-GB */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
DF6DE51E2965924C002EC085 /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
DF6DE51F2965924D002EC085 /* en-GB */,
DF6DE5222965937C002EC085 /* en */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
DF6DE52329659443002EC085 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
DF6DE52429659443002EC085 /* en-GB */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
DF6DE5262965971A002EC085 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
DF6DE5272965971A002EC085 /* en-GB */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
DF93DB2D296A319000586C0E /* Localizable.stringsdict */ = {
isa = PBXVariantGroup;
children = (
DF93DB2C296A319000586C0E /* en */,
DF93DB2E296A324100586C0E /* en-GB */,
);
name = Localizable.stringsdict;
sourceTree = "<group>";
};
DF93DB31296A42BD00586C0E /* Localizable.stringsdict */ = {
isa = PBXVariantGroup;
children = (
DF93DB30296A42BD00586C0E /* en */,
DF93DB34296A4A9300586C0E /* en-GB */,
);
name = Localizable.stringsdict;
sourceTree = "<group>";
};
DFB616A72965300400A359AB /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
DFB616A82965300400A359AB /* en */,
DFB616BE29653A0700A359AB /* en-GB */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
DFB616AA2965300400A359AB /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
DFB616AB2965300400A359AB /* en */,
DFB616BD29653A0700A359AB /* en-GB */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
DFD86798295D553D0070D62D /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
DFD86797295D553D0070D62D /* en */,
DFB616BF29653A0700A359AB /* en-GB */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */

View File

@@ -25,31 +25,34 @@ extension AccountType {
case .onMyMac:
let defaultName: String
#if os(macOS)
defaultName = NSLocalizedString("On My Mac", comment: "Account name")
defaultName = NSLocalizedString("account.name.mac", comment: "On My Mac")
#else
if UIDevice.current.userInterfaceIdiom == .pad {
defaultName = NSLocalizedString("On My iPad", comment: "Account name")
defaultName = NSLocalizedString("account.name.ipad", comment: "On My iPad")
} else {
defaultName = NSLocalizedString("On My iPhone", comment: "Account name")
defaultName = NSLocalizedString("account.name.iphone", comment: "On My iPhone")
}
#endif
return defaultName
/* The below account names are not localized as they are product names. */
case .bazQux:
return NSLocalizedString("BazQux", comment: "Account name")
return "BazQux"
case .cloudKit:
return NSLocalizedString("iCloud", comment: "Account name")
return "iCloud"
case .feedbin:
return NSLocalizedString("Feedbin", comment: "Account name")
return "Feedbin"
case .feedly:
return NSLocalizedString("Feedly", comment: "Account name")
return "Feedly"
case .freshRSS:
return NSLocalizedString("FreshRSS", comment: "Account name")
return "FreshRSS"
case .inoreader:
return NSLocalizedString("Inoreader", comment: "Account name")
return "Inoreader"
case .newsBlur:
return NSLocalizedString("NewsBlur", comment: "Account name")
return "NewsBlur"
case .theOldReader:
return NSLocalizedString("The Old Reader", comment: "Account name")
return "The Old Reader"
}
}

View File

@@ -70,7 +70,7 @@ class ActivityManager {
guard nextUnreadActivity == nil else { return }
nextUnreadActivity = NSUserActivity(activityType: ActivityType.nextUnread.rawValue)
nextUnreadActivity!.title = NSLocalizedString("See first unread article", comment: "First Unread")
nextUnreadActivity!.title = NSLocalizedString("activity.title.see-first-unread-article", comment: "See first unread article")
#if os(iOS)
nextUnreadActivity!.suggestedInvocationPhrase = nextUnreadActivity!.title
@@ -165,7 +165,7 @@ private extension ActivityManager {
func makeSelectFeedActivity(feed: Feed) -> NSUserActivity {
let activity = NSUserActivity(activityType: ActivityType.selectFeed.rawValue)
let localizedText = NSLocalizedString("See articles in “%@", comment: "See articles in Folder")
let localizedText = NSLocalizedString("activity.title.see-article-in.folder.%@", comment: "See articles in “%@”")
let title = NSString.localizedStringWithFormat(localizedText as NSString, feed.nameForDisplay) as String
activity.title = title

View File

@@ -210,7 +210,7 @@ private extension ArticleRenderer {
d["preferred_link"] = article.preferredLink ?? ""
if let externalLink = article.externalLink, externalLink != article.preferredLink {
d["external_link_label"] = NSLocalizedString("Link:", comment: "Link")
d["external_link_label"] = NSLocalizedString("label.text.link", comment: "Link: ")
d["external_link_stripped"] = externalLink.strippingHTTPOrHTTPSScheme
d["external_link"] = externalLink
} else {

View File

@@ -35,15 +35,15 @@ enum ArticleTextSize: Int, CaseIterable, Identifiable {
func description() -> String {
switch self {
case .small:
return NSLocalizedString("Small", comment: "Small")
return NSLocalizedString("label.text.small", comment: "Small")
case .medium:
return NSLocalizedString("Medium", comment: "Medium")
return NSLocalizedString("label.text.medium", comment: "Medium")
case .large:
return NSLocalizedString("Large", comment: "Large")
return NSLocalizedString("label.text.large", comment: "Large")
case .xlarge:
return NSLocalizedString("Extra Large", comment: "X-Large")
return NSLocalizedString("label.text.extra-large", comment: "X-Large")
case .xxlarge:
return NSLocalizedString("Extra Extra Large", comment: "XX-Large")
return NSLocalizedString("label.text.extra-extra-large", comment: "XX-Large")
}
}

View File

@@ -20,6 +20,7 @@ struct ArticleTheme: Equatable {
static let defaultTheme = ArticleTheme()
static let nnwThemeSuffix = ".nnwtheme"
// Don't localize the theme names.
private static let defaultThemeName = "NetNewsWire"
private static let unknownValue = NSLocalizedString("Unknown", comment: "Unknown Value")

View File

@@ -167,8 +167,11 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging, Observable
menu.addItem(defaultMenuItem)
menu.addItem(NSMenuItem.separator())
let rancheroHeading = NSMenuItem(title: "Built-in Themes", action: nil, keyEquivalent: "")
rancheroHeading.attributedTitle = NSAttributedString(string: "Built-in Themes", attributes: [NSAttributedString.Key.foregroundColor : NSColor.secondaryLabelColor, NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 12)])
let rancheroString = NSLocalizedString("label.text.themes-builtin", comment: "Built-in Themes")
let otherString = NSLocalizedString("label.text.themes-builtin", comment: "Other Themes")
let rancheroHeading = NSMenuItem(title: rancheroString, action: nil, keyEquivalent: "")
rancheroHeading.attributedTitle = NSAttributedString(string: rancheroString, attributes: [NSAttributedString.Key.foregroundColor : NSColor.secondaryLabelColor, NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 12)])
rancheroHeading.isEnabled = false
menu.addItem(rancheroHeading)
@@ -185,8 +188,8 @@ final class ArticleThemesManager: NSObject, NSFilePresenter, Logging, Observable
menu.addItem(NSMenuItem.separator())
let thirdPartyHeading = NSMenuItem(title: "Other Themes", action: nil, keyEquivalent: "")
thirdPartyHeading.attributedTitle = NSAttributedString(string: "Other Themes", attributes: [NSAttributedString.Key.foregroundColor : NSColor.secondaryLabelColor, NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 12)])
let thirdPartyHeading = NSMenuItem(title: otherString, action: nil, keyEquivalent: "")
thirdPartyHeading.attributedTitle = NSAttributedString(string: otherString, attributes: [NSAttributedString.Key.foregroundColor : NSColor.secondaryLabelColor, NSAttributedString.Key.font: NSFont.boldSystemFont(ofSize: 12)])
thirdPartyHeading.isEnabled = false
menu.addItem(thirdPartyHeading)

View File

@@ -259,11 +259,11 @@ private extension Node {
private struct DeleteActionName {
private static let deleteFeed = NSLocalizedString("Delete Feed", comment: "command")
private static let deleteFeeds = NSLocalizedString("Delete Feeds", comment: "command")
private static let deleteFolder = NSLocalizedString("Delete Folder", comment: "command")
private static let deleteFolders = NSLocalizedString("Delete Folders", comment: "command")
private static let deleteFeedsAndFolders = NSLocalizedString("Delete Feeds and Folders", comment: "command")
private static let deleteFeed = NSLocalizedString("button.title.delete-feed", comment: "Delete Feed")
private static let deleteFeeds = NSLocalizedString("button.title.delete-feeds", comment: "Delete Feeds")
private static let deleteFolder = NSLocalizedString("button.title.delete-folder", comment: "Delete Folder")
private static let deleteFolders = NSLocalizedString("button.title.delete-folders", comment: "Delete Folders")
private static let deleteFeedsAndFolders = NSLocalizedString("button.title.delete-feeds-and-folders", comment: "Delete Feeds and Folders")
static func name(for nodes: [Node]) -> String? {

View File

@@ -111,10 +111,10 @@ private extension MarkStatusCommand {
Account.UserInfoKey.statusFlag: flag])
}
static private let markReadActionName = NSLocalizedString("Mark Read", comment: "command")
static private let markUnreadActionName = NSLocalizedString("Mark Unread", comment: "command")
static private let markStarredActionName = NSLocalizedString("Mark Starred", comment: "command")
static private let markUnstarredActionName = NSLocalizedString("Mark Unstarred", comment: "command")
static private let markReadActionName = NSLocalizedString("button.title.mark-read", comment: "Mark Read")
static private let markUnreadActionName = NSLocalizedString("button.title.mark-unread", comment: "Mark Unread")
static private let markStarredActionName = NSLocalizedString("button.title.mark-starred", comment: "Mark Starred")
static private let markUnstarredActionName = NSLocalizedString("button.title.mark-unstarred", comment: "Mark Unstarred")
static func actionName(_ statusKey: ArticleStatus.Key, _ flag: Bool) -> String {

View File

@@ -21,7 +21,7 @@ public enum ExtensionPointManagerError: LocalizedError {
public var localizedDescription: String {
switch self {
case .unableToCreate:
return NSLocalizedString("Unable to create extension.", comment: "Unable to create extension")
return NSLocalizedString("error.message.unable-to-create-extension", comment: "Unable to create extension.")
}
}
}

View File

@@ -13,7 +13,7 @@ extension RedditFeedProvider: ExtensionPoint {
static var isSinglton = false
static var isDeveloperBuildRestricted = true
static var title = NSLocalizedString("Reddit", comment: "Reddit")
static var title = "Reddit" // not localized - product name
static var image = AppAssets.extensionPointReddit
static var description: NSAttributedString = {
return RedditFeedProvider.makeAttrString("This extension enables you to subscribe to Reddit URLs as if they were RSS feeds. It only works with \(Account.defaultLocalAccountName) or iCloud accounts.")

View File

@@ -14,10 +14,10 @@ final class SendToMarsEditCommand: ExtensionPoint, SendToCommand {
static var isSinglton = true
static var isDeveloperBuildRestricted = false
static var title = NSLocalizedString("MarsEdit", comment: "MarsEdit")
static var title = "MarsEdit" // not localized
static var image = AppAssets.extensionPointMarsEdit
static var description: NSAttributedString = {
let attrString = SendToMarsEditCommand.makeAttrString("This extension enables share menu functionality to send selected article text to MarsEdit. You need the MarsEdit application for this to work.")
let attrString = SendToMarsEditCommand.makeAttrString(NSLocalizedString("label.text.marsedit.explainer", comment: "This extension enables share menu functionality to send selected article text to MarsEdit. You need the MarsEdit application for this to work."))
let range = NSRange(location: 81, length: 8)
attrString.beginEditing()
attrString.addAttribute(NSAttributedString.Key.link, value: "https://red-sweater.com/marsedit/", range: range)

View File

@@ -16,10 +16,10 @@ final class SendToMicroBlogCommand: ExtensionPoint, SendToCommand {
static var isSinglton = true
static var isDeveloperBuildRestricted = false
static var title: String = NSLocalizedString("Micro.blog", comment: "Micro.blog")
static var title: String = "Micro.blog" // not localized
static var image = AppAssets.extensionPointMicroblog
static var description: NSAttributedString = {
let attrString = SendToMicroBlogCommand.makeAttrString("This extension enables share menu functionality to send selected article text to Micro.blog. You need the Micro.blog application for this to work.")
let attrString = SendToMicroBlogCommand.makeAttrString(NSLocalizedString("label.text.micro-blog-expaliner", comment: "This extension enables share menu functionality to send selected article text to Micro.blog. You need the Micro.blog application for this to work."))
let range = NSRange(location: 81, length: 10)
attrString.beginEditing()
attrString.addAttribute(NSAttributedString.Key.link, value: "https://micro.blog", range: range)

View File

@@ -13,7 +13,7 @@ extension TwitterFeedProvider: ExtensionPoint {
static var isSinglton = false
static var isDeveloperBuildRestricted = true
static var title = NSLocalizedString("Twitter", comment: "Twitter")
static var title = "Twitter" // not localized - product name
static var image = AppAssets.extensionPointTwitter
static var description: NSAttributedString = {
return TwitterFeedProvider.makeAttrString("This extension enables you to subscribe to Twitter URLs as if they were RSS feeds. It only works with \(Account.defaultLocalAccountName) or iCloud accounts.")

View File

@@ -21,26 +21,46 @@ public enum LocalizedNetNewsWireError: LocalizedError {
case userNameAndPasswordRequired
case userNamePasswordAndURLRequired
case userNameRequired
case invalidUsernameOrPassword
case invalidURL
case keychainError
case duplicateDefaultTheme
case networkError
case unrecognizedAccount
public var errorDescription: String? {
switch self {
case .duplicateAccount:
return NSLocalizedString("There is already an account of that type with that username created.", comment: "Error message: duplicate account with same username.")
return NSLocalizedString("alert.error.duplicate-account-username", comment: "There is already an account of that type with that username created.")
case .iCloudDriveMissing:
return NSLocalizedString("Unable to add iCloud Account. Please make sure you have iCloud and iCloud Drive enabled in System Settings.", comment: "Error message: The user cannot enable the iCloud account becasue iCloud or iCloud Drive isn't enabled in Settings.")
return NSLocalizedString("alert.error.cloudkit-missing", comment: "Unable to add iCloud Account. Please make sure you have iCloud and iCloud Drive enabled in System Settings.")
case .userNameAndPasswordRequired:
return NSLocalizedString("Username and password required", comment: "Error message: The user must provide a username and password.")
return NSLocalizedString("alert.error.username-and-password-required", comment: "Error message: The user must provide a username and password.")
case .userNamePasswordAndURLRequired:
return NSLocalizedString("alert.error.username-password-url-required", comment: "The user must provide a username, password, and URL.")
case .userNameRequired:
return NSLocalizedString("alert.error.username-required", comment: "Username required.")
case .invalidUsernameOrPassword:
return NSLocalizedString("Invalid username or password", comment: "Error message: The user provided an invalid username or password.")
return NSLocalizedString("alert.error.invalid-username-or-password", comment: "Error message: The user provided an invalid username or password.")
case .invalidURL:
return NSLocalizedString("alert.error.invalid-api-url", comment: "Invalid API URL.")
case .keychainError:
return NSLocalizedString("Keychain error while storing credentials.", comment: "Error message: Unable to save due a Keychain error.")
return NSLocalizedString("alert.error.keychain-error", comment: "Error message: Unable to save due a Keychain error.")
case .duplicateDefaultTheme:
return NSLocalizedString("You cannot import a theme that shares the same name as a provided theme.", comment: "Error message: cannot import theme as this is a duplicate of a provided theme.")
return NSLocalizedString("alert.error.theme-duplicate-of-provided", comment: "Error message: This theme shares the same name as a provided theme and cannot be imported.")
case .networkError:
return NSLocalizedString("alert.error.network-error", comment: "Network error. Please try later.")
case .unrecognizedAccount:
return NSLocalizedString("alert.error.unrecognized-account", comment: "The account type in invalid.")
}
}
}

View File

@@ -22,7 +22,7 @@ struct SearchFeedDelegate: SmartFeedDelegate {
return nameForDisplayPrefix + searchString
}
let nameForDisplayPrefix = NSLocalizedString("Search: ", comment: "Search smart feed title prefix")
let nameForDisplayPrefix = NSLocalizedString("textfield.placeholder.search", comment: "Search: ")
let searchString: String
let fetchType: FetchType
var smallIcon: IconImage? = AppAssets.searchFeedImage

View File

@@ -22,7 +22,7 @@ struct SearchTimelineFeedDelegate: SmartFeedDelegate {
return nameForDisplayPrefix + searchString
}
let nameForDisplayPrefix = NSLocalizedString("Search: ", comment: "Search smart feed title prefix")
let nameForDisplayPrefix = NSLocalizedString("textfield.placeholder.search", comment: "Search: ")
let searchString: String
let fetchType: FetchType
var smallIcon: IconImage? = AppAssets.searchFeedImage

View File

@@ -17,7 +17,7 @@ final class SmartFeedsController: DisplayNameProvider, ContainerIdentifiable {
}
public static let shared = SmartFeedsController()
let nameForDisplay = NSLocalizedString("Smart Feeds", comment: "Smart Feeds group title")
let nameForDisplay = NSLocalizedString("smartfeeds.title", comment: "Smart Feeds group title")
var smartFeeds = [Feed]()
let todayFeed = SmartFeed(delegate: TodayFeedDelegate())

View File

@@ -20,7 +20,7 @@ struct StarredFeedDelegate: SmartFeedDelegate {
return FeedIdentifier.smartFeed(String(describing: StarredFeedDelegate.self))
}
let nameForDisplay = NSLocalizedString("Starred", comment: "Starred pseudo-feed title")
let nameForDisplay = NSLocalizedString("smartfeed.title.starred", comment: "Starred pseudo-feed title")
let fetchType: FetchType = .starred(nil)
var smallIcon: IconImage? {
return AppAssets.starredFeedImage

View File

@@ -18,7 +18,7 @@ struct TodayFeedDelegate: SmartFeedDelegate {
return FeedIdentifier.smartFeed(String(describing: TodayFeedDelegate.self))
}
let nameForDisplay = NSLocalizedString("Today", comment: "Today pseudo-feed title")
let nameForDisplay = NSLocalizedString("smartfeed.title.today", comment: "Today pseudo-feed title")
let fetchType = FetchType.today(nil)
var smallIcon: IconImage? {
return AppAssets.todayFeedImage

View File

@@ -30,7 +30,7 @@ final class UnreadFeed: PseudoFeed {
return FeedIdentifier.smartFeed(String(describing: UnreadFeed.self))
}
let nameForDisplay = NSLocalizedString("All Unread", comment: "All Unread pseudo-feed title")
let nameForDisplay = NSLocalizedString("smartfeed.title.allunread", comment: "All Unread pseudo-feed title")
let fetchType = FetchType.unread(nil)
var unreadCount = 0 {

View File

@@ -41,19 +41,19 @@ enum RefreshInterval: Int, CaseIterable, Identifiable {
func description() -> String {
switch self {
case .manually:
return NSLocalizedString("Manually", comment: "Manually")
return NSLocalizedString("button.title.manually", comment: "Manually")
case .every10Minutes:
return NSLocalizedString("Every 10 Minutes", comment: "Every 10 Minutes")
return NSLocalizedString("button.title.10-minutes", comment: "Every 10 Minutes")
case .every30Minutes:
return NSLocalizedString("Every 30 Minutes", comment: "Every 30 Minutes")
return NSLocalizedString("button.title.30-minutes", comment: "Every 30 Minutes")
case .everyHour:
return NSLocalizedString("Every Hour", comment: "Every Hour")
return NSLocalizedString("button.title.every-hour", comment: "Every Hour")
case .every2Hours:
return NSLocalizedString("Every 2 Hours", comment: "Every 2 Hours")
return NSLocalizedString("button.title.2-hours", comment: "Every 2 Hours")
case .every4Hours:
return NSLocalizedString("Every 4 Hours", comment: "Every 4 Hours")
return NSLocalizedString("button.title.4-hours", comment: "Every 4 Hours")
case .every8Hours:
return NSLocalizedString("Every 8 Hours", comment: "Every 8 Hours")
return NSLocalizedString("button.title.8-hours", comment: "Every 8 Hours")
}
}

View File

@@ -88,9 +88,9 @@ private extension UserNotificationManager {
}
func registerCategoriesAndActions() {
let readAction = UNNotificationAction(identifier: "MARK_AS_READ", title: NSLocalizedString("Mark as Read", comment: "Mark as Read"), options: [])
let starredAction = UNNotificationAction(identifier: "MARK_AS_STARRED", title: NSLocalizedString("Mark as Starred", comment: "Mark as Starred"), options: [])
let openAction = UNNotificationAction(identifier: "OPEN_ARTICLE", title: NSLocalizedString("Open", comment: "Open"), options: [.foreground])
let readAction = UNNotificationAction(identifier: "MARK_AS_READ", title: NSLocalizedString("button.title.mark-as-read", comment: "Mark as Read"), options: [])
let starredAction = UNNotificationAction(identifier: "MARK_AS_STARRED", title: NSLocalizedString("button.title.mark-as-starred", comment: "Mark as Starred"), options: [])
let openAction = UNNotificationAction(identifier: "OPEN_ARTICLE", title: NSLocalizedString("button.title.open", comment: "Open"), options: [.foreground])
let newArticleCategory =
UNNotificationCategory(identifier: "NEW_ARTICLE_NOTIFICATION_CATEGORY",

70
Technotes/Localization.md Normal file
View File

@@ -0,0 +1,70 @@
# Localization
NetNewsWire is an Internationalized and Localized app.
## Internationalization
`Internationalized` means that, at code-level, we don't use locale-dependent strings. Instead, in code we use a key-based approach. Generally, this takes the form of:
`UIKit` or `AppKit` — using `NSLocalizedString`:
```swift
let messageFormat = NSLocalizedString("alert.title.open-articles-in-browser.%ld", comment: "Are you sure you want to open %ld articles in your browser?")
alert.messageText = String.localizedStringWithFormat(messageFormat, urlStrings.count)
```
or, in `SwiftUI` — using the `Text` struct:
```swift
Text("alert.title.remove-account.\(viewModel.accountToDelete?.nameForDisplay ?? "")", comment: "Are you sure you want to remove “%@“?")
```
### Key Format
All keys are lower cased and follow the `dot.separated` UI element name -> `hyphen-separated` string descriptor -> `dot.separated` variable list format, e.g.:
```
alert.title.open-articles-in-browser.%ld
button.title.close
```
### Comments
Whether using `NSLocalizedString` or `Text`, a `comment` must be provided. This will generally be a reference to the string in English. However, where a key contains multiple variables, the ordering of the variables must be specified in the comment.
## Localization
All of NetNewsWire's strings in code are localized in external resources — `.strings` or `.stringsdict`. Each target has its own `Localizable.strings` (and, where necessary, `.stringsdict`) files. All Storyboards are also localized.
### Adding New Strings
If you are developing a new feature that introduces new strings to the code base, follow these general guidelines:
- Check if there is an existing string in `Localizable.strings` that meets your needs. If there is, use that.
- If there isn't:
- Add your string in code following the key and comment rules above
- Run `Export Localizations`
- Open the `en.xcloc` file and provide the new translations.
- Save the `en.xcloc` file.
- Run `Import Localizations`
- Select `en.xcloc` and Import.
### Updating Existing Translations
Update the Development Language translation first:
- Run `Export Localizations`
- Open the `en.xcloc` file and provide the new translations.
- Save the `en.xcloc` file.
- Run `Import Localizations`
- Select `en.xcloc` and Import.
Then update other lanaguages:
- Run `Export Localizations`
- Open the `en-GB.xcloc` file and provide the new translations.
- Save the `en-GB.xcloc` file.
- Run `Import Localizations`
- Select `en-GB.xcloc` and Import.

View File

@@ -1,86 +0,0 @@
// swiftlint:disable all
// Generated using SwiftGen https://github.com/SwiftGen/SwiftGen
import Foundation
// swiftlint:disable superfluous_disable_command file_length implicit_return
// MARK: - Strings
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
internal enum L10n {
/// Plural format key: "%#@localized_count@"
internal static func localizedCount(_ p1: Int) -> String {
return L10n.tr("Localizable", "LocalizedCount", p1)
}
/// Your smart feeds, summarized.
internal static let smartFeedSummaryWidgetDescription = L10n.tr("Localizable", "SmartFeedSummary_Widget_Description")
/// Your Smart Feed Summary
internal static let smartFeedSummaryWidgetTitle = L10n.tr("Localizable", "SmartFeedSummary_Widget_Title")
/// Starred
internal static let starred = L10n.tr("Localizable", "Starred")
/// A sneak peek at your starred articles.
internal static let starredWidgetDescription = L10n.tr("Localizable", "Starred_Widget_Description")
/// When you mark articles as Starred, they'll appear here.
internal static let starredWidgetNoItems = L10n.tr("Localizable", "Starred_Widget_NoItems")
/// Starred
internal static let starredWidgetNoItemsTitle = L10n.tr("Localizable", "Starred_Widget_NoItemsTitle")
/// Your Starred Articles
internal static let starredWidgetTitle = L10n.tr("Localizable", "Starred_Widget_Title")
/// Plural format key: "%#@starred_count@"
internal static func starredCount(_ p1: Int) -> String {
return L10n.tr("Localizable", "StarredCount", p1)
}
/// Today
internal static let today = L10n.tr("Localizable", "Today")
/// A sneak peek at recently published unread articles.
internal static let todayWidgetDescription = L10n.tr("Localizable", "Today_Widget_Description")
/// There are no recent unread articles left to read.
internal static let todayWidgetNoItems = L10n.tr("Localizable", "Today_Widget_NoItems")
/// Today
internal static let todayWidgetNoItemsTitle = L10n.tr("Localizable", "Today_Widget_NoItemsTitle")
/// Your Today Articles
internal static let todayWidgetTitle = L10n.tr("Localizable", "Today_Widget_Title")
/// Plural format key: "%#@today_count@"
internal static func todayCount(_ p1: Int) -> String {
return L10n.tr("Localizable", "TodayCount", p1)
}
/// Unread
internal static let unread = L10n.tr("Localizable", "Unread")
/// A sneak peek at your unread articles.
internal static let unreadWidgetDescription = L10n.tr("Localizable", "Unread_Widget_Description")
/// There are no unread articles left to read.
internal static let unreadWidgetNoItems = L10n.tr("Localizable", "Unread_Widget_NoItems")
/// Unread
internal static let unreadWidgetNoItemsTitle = L10n.tr("Localizable", "Unread_Widget_NoItemsTitle")
/// Your Unread Articles
internal static let unreadWidgetTitle = L10n.tr("Localizable", "Unread_Widget_Title")
/// Plural format key: "%#@unread_count@"
internal static func unreadCount(_ p1: Int) -> String {
return L10n.tr("Localizable", "UnreadCount", p1)
}
}
// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces
// MARK: - Implementation Details
extension L10n {
private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
let format = BundleToken.bundle.localizedString(forKey: key, value: nil, table: table)
return String(format: format, locale: Locale.current, arguments: args)
}
}
// swiftlint:disable convenience_type
private final class BundleToken {
static let bundle: Bundle = {
#if SWIFT_PACKAGE
return Bundle.module
#else
return Bundle(for: BundleToken.self)
#endif
}()
}
// swiftlint:enable convenience_type

View File

@@ -0,0 +1,51 @@
/* Starred */
"label.text.starred" = "Starred";
/* Today */
"label.text.today" = "Today";
/* Smart Feed Summary Widget */
"label.text.unread" = "Unread";
/* Your smart feeds, summarized. */
"widget.description.smart-feed-summary" = "Your smart feeds, summarised.";
/* A sneak peek at your starred articles. */
"widget.description.starred" = "A sneak peek at your starred articles.";
/* When you mark articles as Starred, they'll appear here. */
"widget.description.starred-no-items" = "When you mark articles as Starred, they'll appear here.";
/* A sneak peek at recently published unread articles. */
"widget.description.today" = "A sneak peek at recently published unread articles.";
/* There are no recent unread articles left to read. */
"widget.description.today-no-items" = "There are no recent unread articles left to read.";
/* A sneak peek at your unread articles. */
"widget.description.unread" = "A sneak peek at your unread articles.";
/* There are no unread articles left to read. */
"widget.description.unread-no-items" = "There are no unread articles left to read.";
/* Your Smart Feed Summary */
"widget.title.smart-feed-summary" = "Your Smart Feed Summary";
/* Your Starred Articles */
"widget.title.starred" = "Your Starred Articles";
/* Starred Widget */
"widget.title.starred-no-items" = "Starred";
/* Your Today Articles */
"widget.title.today" = "Your Today Articles";
/* Today Widget */
"widget.title.today-no-items" = "Today";
/* Bundle */
"widget.title.unread" = "Your Unread Articles";
/* Unread Widget */
"widget.title.unread-no-items" = "Unread";

View File

@@ -2,25 +2,7 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UnreadCount</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@unread_count@</string>
<key>unread_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>zero</key>
<string>No more unread articles</string>
<key>one</key>
<string>+ 1 more unread article</string>
<key>other</key>
<string>+ %u more unread articles</string>
</dict>
</dict>
<key>StarredCount</key>
<key>starred.count.%lld</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@starred_count@</string>
@@ -29,47 +11,49 @@
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>zero</key>
<string>No more starred articles</string>
<string>lld</string>
<key>one</key>
<string>+ 1 more starred article</string>
<key>other</key>
<string>+ %u more starred articles</string>
<string>+ %lld more starred articles</string>
<key>zero</key>
<string>No more starred articles</string>
</dict>
</dict>
<key>TodayCount</key>
<key>today.count.%lld</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@today_count@</string>
<key>today_count</key>
<key>today.count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>zero</key>
<string>No more recent articles</string>
<string>lld</string>
<key>one</key>
<string>+ 1 more recent unread article</string>
<key>other</key>
<string>+ %u more recent unread articles</string>
<string>+ %lld more recent unread articles</string>
<key>zero</key>
<string>No more recent articles</string>
</dict>
</dict>
<key>LocalizedCount</key>
<key>unread.count.%lld</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@localized_count@</string>
<key>localized_count</key>
<string>%#@unread_count@</string>
<key>unread_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>zero</key>
<string>0</string>
<string>lld</string>
<key>one</key>
<string>+ 1 more unread article</string>
<key>other</key>
<string>%u</string>
<string>+ %lld more unread articles</string>
<key>zero</key>
<string>No more unread articles</string>
</dict>
</dict>
</dict>

View File

@@ -7,31 +7,31 @@
*/
/* Bundle */
"Unread_Widget_Title" = "Your Unread Articles";
"Unread_Widget_Description" = "A sneak peek at your unread articles.";
"widget.title.unread" = "Your Unread Articles";
"widget.description.unread" = "A sneak peek at your unread articles.";
"Today_Widget_Title" = "Your Today Articles";
"Today_Widget_Description" = "A sneak peek at recently published unread articles.";
"widget.title.today" = "Your Today Articles";
"widget.description.today" = "A sneak peek at recently published unread articles.";
"Starred_Widget_Title" = "Your Starred Articles";
"Starred_Widget_Description" = "A sneak peek at your starred articles.";
"widget.title.starred" = "Your Starred Articles";
"widget.description.starred" = "A sneak peek at your starred articles.";
"SmartFeedSummary_Widget_Title" = "Your Smart Feed Summary";
"SmartFeedSummary_Widget_Description" = "Your smart feeds, summarized.";
"widget.title.smart-feed-summary" = "Your Smart Feed Summary";
"widget.description.smart-feed-summary" = "Your smart feeds, summarized.";
/* Unread Widget */
"Unread_Widget_NoItemsTitle" = "Unread";
"Unread_Widget_NoItems" = "There are no unread articles left to read.";
"widget.title.unread-no-items" = "Unread";
"widget.description.unread-no-items" = "There are no unread articles left to read.";
/* Today Widget */
"Today_Widget_NoItemsTitle" = "Today";
"Today_Widget_NoItems" = "There are no recent unread articles left to read.";
"widget.title.today-no-items" = "Today";
"widget.description.today-no-items" = "There are no recent unread articles left to read.";
/* Starred Widget */
"Starred_Widget_NoItemsTitle" = "Starred";
"Starred_Widget_NoItems" = "When you mark articles as Starred, they'll appear here.";
"widget.title.starred-no-items" = "Starred";
"widget.description.starred-no-items" = "When you mark articles as Starred, they'll appear here.";
/* Smart Feed Summary Widget */
"Unread" = "Unread";
"Today" = "Today ";
"Starred" = "Starred";
"label.text.unread" = "Unread";
"label.text.today" = "Today";
"label.text.starred" = "Starred";

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>unread.count.%lld</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@unread_count@</string>
<key>unread_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>lld</string>
<key>zero</key>
<string>No more unread articles</string>
<key>one</key>
<string>+ 1 more unread article</string>
<key>other</key>
<string>+ %lld more unread articles</string>
</dict>
</dict>
<key>starred.count.%lld</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@starred_count@</string>
<key>starred_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>lld</string>
<key>zero</key>
<string>No more starred articles</string>
<key>one</key>
<string>+ 1 more starred article</string>
<key>other</key>
<string>+ %lld more starred articles</string>
</dict>
</dict>
<key>today.count.%lld</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@today_count@</string>
<key>today.count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>lld</string>
<key>zero</key>
<string>No more recent articles</string>
<key>one</key>
<string>+ 1 more recent unread article</string>
<key>other</key>
<string>+ %lld more recent unread articles</string>
</dict>
</dict>
</dict>
</plist>

View File

@@ -11,8 +11,6 @@ import RSWeb
struct ArticleItemView: View {
var article: LatestArticle
var deepLink: URL
@State private var iconImage: Image?
@@ -30,7 +28,7 @@ struct ArticleItemView: View {
// Title and Feed Name
VStack(alignment: .leading) {
Text(article.articleTitle ?? "Untitled")
Text(verbatim: article.articleTitle ?? "Untitled")
.font(.footnote)
.bold()
.lineLimit(1)
@@ -38,12 +36,12 @@ struct ArticleItemView: View {
.padding(.top, -3)
HStack {
Text(article.feedTitle)
Text(verbatim: article.feedTitle)
.font(.caption)
.lineLimit(1)
.foregroundColor(.secondary)
Spacer()
Text(pubDate(article.pubDate))
Text(verbatim: pubDate(article.pubDate))
.font(.caption)
.lineLimit(1)
.foregroundColor(.secondary)

View File

@@ -26,7 +26,7 @@ struct SmartFeedSummaryWidgetView: View {
VStack(alignment: .leading, spacing: 2) {
HStack {
todayImage
Text(L10n.today).bold().font(.body)
Text("label.text.today", comment: "Today").bold().font(.body)
Spacer()
Text(formattedCount(entry.widgetData.currentTodayCount)).bold()
@@ -34,14 +34,14 @@ struct SmartFeedSummaryWidgetView: View {
HStack {
unreadImage
Text(L10n.unread).bold().font(.body)
Text("label.text.unread", comment: "Unread").bold().font(.body)
Spacer()
Text(formattedCount(entry.widgetData.currentUnreadCount)).bold()
}
HStack {
starredImage
Text(L10n.starred).bold().font(.body)
Text("label.text.starred", comment: "Starred").bold().font(.body)
Spacer()
Text(formattedCount(entry.widgetData.currentStarredCount)).bold()
}

View File

@@ -61,7 +61,7 @@ struct StarredWidgetView : View {
HStack {
Spacer()
if entry.widgetData.currentStarredCount - maxCount() > 0 {
Text(L10n.starredCount(entry.widgetData.currentStarredCount - maxCount()))
Text(String(format: NSLocalizedString("starred.count.%lld", comment: "Number of starred articles beyond what are currently displayed in the widget."), locale: .current, starredCount()))
.font(.caption2)
.bold()
.foregroundColor(.secondary)
@@ -97,6 +97,10 @@ struct StarredWidgetView : View {
return entry.widgetData.currentStarredCount >= 3 ? (3 - reduceAccessibilityCount) : entry.widgetData.currentStarredCount
}
func starredCount() -> Int {
entry.widgetData.currentStarredCount - maxCount()
}
var inboxZero: some View {
VStack(alignment: .center) {
Spacer()
@@ -107,11 +111,11 @@ struct StarredWidgetView : View {
.foregroundColor(.yellow)
Text(L10n.starredWidgetNoItemsTitle)
Text("widget.title.starred-no-items", comment: "Starred")
.font(.headline)
.foregroundColor(.primary)
Text(L10n.starredWidgetNoItems)
Text("widget.description.starred-no-items", comment: "When you mark articles as Starred, they'll appear here.")
.font(.caption)
.foregroundColor(.gray)
Spacer()

View File

@@ -61,10 +61,12 @@ struct TodayWidgetView : View {
HStack {
Spacer()
if entry.widgetData.currentTodayCount - maxCount() > 0 {
Text(L10n.todayCount(entry.widgetData.currentTodayCount - maxCount()))
Text(String(format: NSLocalizedString("today.count.%lld", comment: "Number of today articles beyond what are currently displayed in the widget."), locale: .current, todayCount()))
.font(.caption2)
.bold()
.foregroundColor(.secondary)
}
}
}
@@ -84,6 +86,10 @@ struct TodayWidgetView : View {
.foregroundColor(.orange)
}
func todayCount() -> Int {
entry.widgetData.currentTodayCount - maxCount()
}
func maxCount() -> Int {
var reduceAccessibilityCount: Int = 0
if SizeCategories().isSizeCategoryLarge(category: sizeCategory) {
@@ -106,11 +112,11 @@ struct TodayWidgetView : View {
.foregroundColor(.orange)
Text(L10n.todayWidgetNoItemsTitle)
Text("widget.title.today-no-items", comment: "Today")
.font(.headline)
.foregroundColor(.primary)
Text(L10n.todayWidgetNoItems)
Text("widget.description.today-no-items", comment: "There are no recent unread articles left to read.")
.font(.caption)
.foregroundColor(.gray)
Spacer()

View File

@@ -61,7 +61,7 @@ struct UnreadWidgetView : View {
HStack {
Spacer()
if entry.widgetData.currentUnreadCount - maxCount() > 0 {
Text(L10n.unreadCount(entry.widgetData.currentUnreadCount - maxCount()))
Text(String(format: NSLocalizedString("unread.count.%lld", comment: "Number of unread articles beyond what are currently displayed in the widget."), locale: .current, unreadCount()))
.font(.caption2)
.bold()
.foregroundColor(.secondary)
@@ -95,6 +95,10 @@ struct UnreadWidgetView : View {
return entry.widgetData.unreadArticles.count >= 3 ? (3 - reduceAccessibilityCount) : entry.widgetData.unreadArticles.count
}
func unreadCount() -> Int {
entry.widgetData.currentUnreadCount - maxCount()
}
var inboxZero: some View {
VStack(alignment: .center) {
Spacer()
@@ -104,11 +108,11 @@ struct UnreadWidgetView : View {
.foregroundColor(.accentColor)
.frame(width: 30)
Text(L10n.unreadWidgetNoItemsTitle)
Text("widget.title.unread-no-items", comment: "Unread")
.font(.headline)
.foregroundColor(.primary)
Text(L10n.unreadWidgetNoItems)
Text("widget.description.unread-no-items", comment: "There are no unread articles left to read.")
.font(.caption)
.foregroundColor(.gray)
Spacer()

View File

@@ -22,8 +22,8 @@ struct UnreadWidget: Widget {
.background(Color("WidgetBackground"))
})
.configurationDisplayName(L10n.unreadWidgetTitle)
.description(L10n.unreadWidgetDescription)
.configurationDisplayName(Text("widget.title.unread", comment: "Your Unread Articles"))
.description(Text("widget.description.unread", comment: "A sneak peek at your unread articles."))
.supportedFamilies([.systemMedium, .systemLarge])
}
@@ -40,8 +40,8 @@ struct TodayWidget: Widget {
.background(Color("WidgetBackground"))
})
.configurationDisplayName(L10n.todayWidgetTitle)
.description(L10n.todayWidgetDescription)
.configurationDisplayName(Text("widget.title.today", comment: "Your Today Articles"))
.description(Text("widget.description.today", comment: "A sneak peek at recently published unread articles."))
.supportedFamilies([.systemMedium, .systemLarge])
}
@@ -58,8 +58,8 @@ struct StarredWidget: Widget {
.background(Color("WidgetBackground"))
})
.configurationDisplayName(L10n.starredWidgetTitle)
.description(L10n.starredWidgetDescription)
.configurationDisplayName(Text("widget.title.starred", comment: "Your Starred Articles"))
.description(Text("widget.description.starred", comment: "A sneak peek at your starred articles."))
.supportedFamilies([.systemMedium, .systemLarge])
}
@@ -75,8 +75,8 @@ struct SmartFeedSummaryWidget: Widget {
return StaticConfiguration(kind: kind, provider: Provider(), content: { entry in
SmartFeedSummaryWidgetView(entry: entry)
})
.configurationDisplayName(L10n.smartFeedSummaryWidgetTitle)
.description(L10n.smartFeedSummaryWidgetDescription)
.configurationDisplayName(Text("widget.title.smart-feed-summary", comment: "Your Smart Feed Summary"))
.description(Text("widget.description.smart-feed-summary", comment: "Your smart feeds, summarized."))
.supportedFamilies([.accessoryRectangular])
}
}

View File

@@ -0,0 +1,6 @@
/* Bundle display name */
"CFBundleDisplayName" = "NetNewsWire Widget";
/* Bundle name */
"CFBundleName" = "NetNewsWire iOS Widget Extension";

View File

@@ -25,13 +25,13 @@ struct CloudKitAddAccountView: View {
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: { dismiss() }, label: { Text("Cancel", comment: "Button title") })
Button(action: { dismiss() }, label: { Text("button.title.cancel", comment: "Cancel") })
}
}
.alert(Text("Error", comment: "Alert title: Error"), isPresented: $accountError.1) {
Button(action: {}, label: { Text("Dismiss", comment: "Button title") })
.alert(Text("alert.title.error", comment: "Error"), isPresented: $accountError.1) {
} message: {
Text(accountError.0?.localizedDescription ?? "Unknown Error")
Text(verbatim: accountError.0?.localizedDescription ?? "Unknown Error")
}
.dismissOnExternalContextLaunch()
.dismissOnAccountAdd()
@@ -48,7 +48,7 @@ struct CloudKitAddAccountView: View {
} label: {
HStack {
Spacer()
Text("Use iCloud", comment: "Button title")
Text("button.title.use-cloudkit", comment: "Use iCloud")
Spacer()
}
}
@@ -58,9 +58,9 @@ struct CloudKitAddAccountView: View {
VStack(spacing: 4) {
if !AccountManager.shared.accounts.contains(where: { $0.type == .cloudKit }) {
// The explainer is only shown when a CloudKit account doesn't exist.
Text("NetNewsWire will use your iCloud account to sync your subscriptions across your Mac and iOS devices.", comment: "iCloud account explanatory text")
Text("label.text.cloudkit-explainer", comment: "NetNewsWire will use your iCloud account to sync your subscriptions across your Mac and iOS devices.")
}
Text("[iCloud Syncing Limitations & Solutions](https://netnewswire.com/help/iCloud)", comment: "Link which opens webpage describing iCloud syncing limitations.")
Text("link.markdown.icloud-limitations", comment: "Link which opens webpage describing iCloud syncing limitations.")
}.multilineTextAlignment(.center)
}

View File

@@ -36,21 +36,16 @@ struct FeedbinAddAccountView: View {
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: { dismiss() }, label: { Text("Cancel", comment: "Button title") })
Button(action: { dismiss() }, label: { Text("button.title.cancel", comment: "Cancel") })
.disabled(showProgressIndicator)
}
ToolbarItem(placement: .navigationBarTrailing) {
if showProgressIndicator { ProgressView() }
}
}
.alert(Text("Error", comment: "Alert title: Error"), isPresented: $accountError.1) {
Button(role: .cancel) {
//
} label: {
Text("Dismiss", comment: "Button title")
}
.alert(Text("alert.title.error", comment: "Error"), isPresented: $accountError.1) {
} message: {
Text(accountError.0?.localizedDescription ?? "Error")
Text(verbatim: accountError.0?.localizedDescription ?? "Error")
}
.navigationTitle(Text(verbatim: account?.type.localizedAccountName() ?? "Feedbin"))
.navigationBarTitleDisplayMode(.inline)
@@ -62,11 +57,11 @@ struct FeedbinAddAccountView: View {
var accountDetails: some View {
Section {
TextField("Email", text: $accountEmail, prompt: Text("Email Address", comment: "Textfield for the user to enter their account email address."))
TextField("Email", text: $accountEmail, prompt: Text("textfield.placeholder.email-address", comment: "Email Address"))
.autocorrectionDisabled()
.autocapitalization(.none)
.textContentType(.username)
SecureField("Password", text: $accountPassword, prompt: Text("Password", comment: "Textfield for the user to enter their account password."))
SecureField("Password", text: $accountPassword, prompt: Text("textfield.placeholder.password", comment: "Password"))
.textContentType(.password)
}
}
@@ -92,9 +87,9 @@ struct FeedbinAddAccountView: View {
HStack{
Spacer()
if account == nil {
Text("Add Account", comment: "Button title")
Text("button.title.add-account", comment: "Add Account")
} else {
Text("Update Credentials", comment: "Button title")
Text("button.title.update-credentials", comment: "Update Credentials")
}
Spacer()
}
@@ -105,7 +100,7 @@ struct FeedbinAddAccountView: View {
var feedbinAccountExplainer: some View {
if account == nil {
return Text("Sign in to your Feedbin account and sync your feeds across your devices. Your username and password will be encrypted and stored in Keychain.\n\nDont have a Feedbin account? [Sign Up Here](https://feedbin.com/signup)", comment: "Explanatory text describing the Feedbin account.")
return Text("label.text.feedbin-explainer", comment: "Sign in to your Feedbin account and sync your feeds across your devices. Your username and password will be encrypted and stored in Keychain.\n\nDont have a Feedbin account? [Sign Up Here](https://feedbin.com/signup)")
.multilineTextAlignment(.center)
}
return Text("").multilineTextAlignment(.center)

View File

@@ -24,7 +24,7 @@ struct LocalAddAccountView: View {
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: { dismiss() }, label: { Text("Cancel", comment: "Button title") })
Button(action: { dismiss() }, label: { Text("button.title.cancel", comment: "Cancel") })
}
}
.navigationTitle(deviceAccountName())
@@ -37,7 +37,7 @@ struct LocalAddAccountView: View {
var accountNameSection: some View {
TextField("Name",
text: $accountName,
prompt: Text("Name", comment: "Textfield placeholder for the name of the account."))
prompt: Text("textfield.placeholder.name", comment: "Name"))
.autocorrectionDisabled()
.autocapitalization(.none)
}
@@ -49,7 +49,7 @@ struct LocalAddAccountView: View {
} label: {
HStack {
Spacer()
Text("Add Account", comment: "Button title")
Text("button.title.add-account", comment: "Add Account")
Spacer()
}
}
@@ -58,7 +58,7 @@ struct LocalAddAccountView: View {
var accountFooterView: some View {
HStack {
Spacer()
Text("Local accounts do not sync your feeds across devices.", comment: "Explanatory text describing the local account.")
Text("label.text.local-account-explainer", comment: "Local accounts do not sync your feeds across devices")
.multilineTextAlignment(.center)
Spacer()
}
@@ -72,10 +72,7 @@ struct LocalAddAccountView: View {
}
private func deviceAccountName() -> Text {
if UIDevice.current.userInterfaceIdiom == .pad {
return Text("On My iPad", comment: "Account name for iPad")
}
return Text("On My iPhone", comment: "Account name for iPhone")
Text(verbatim: AccountType.onMyMac.localizedAccountName())
}
}

View File

@@ -31,7 +31,7 @@ struct NewsBlurAddAccountView: View, Logging {
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: { dismiss() }, label: { Text("Cancel", comment: "Button title") })
Button(action: { dismiss() }, label: { Text("button.title.cancel", comment: "Cancel") })
.disabled(showProgressIndicator)
}
ToolbarItem(placement: .navigationBarTrailing) {
@@ -43,14 +43,9 @@ struct NewsBlurAddAccountView: View, Logging {
.task {
retreiveCredentials()
}
.alert(Text("Error", comment: "Alert title: Error"), isPresented: $accountError.1) {
Button(role: .cancel) {
//
} label: {
Text("Dismiss", comment: "Button title")
}
.alert(Text("alert.title.error", comment: "Error"), isPresented: $accountError.1) {
} message: {
Text(accountError.0?.localizedDescription ?? "")
Text(verbatim: accountError.0?.localizedDescription ?? "")
}
.interactiveDismissDisabled(showProgressIndicator)
.dismissOnExternalContextLaunch()
@@ -70,11 +65,11 @@ struct NewsBlurAddAccountView: View, Logging {
var accountDetails: some View {
Section {
TextField("Email", text: $accountUserName, prompt: Text("Username or Email", comment: "Textfield for the user to enter their account username or email."))
TextField("Email", text: $accountUserName, prompt: Text("textfield.placeholder.username-or-email", comment: "Username or Email"))
.autocorrectionDisabled()
.autocapitalization(.none)
.textContentType(.username)
SecureField("Password", text: $accountPassword, prompt: Text("Password", comment: "Textfield for the user to enter their account password."))
SecureField("Password", text: $accountPassword, prompt: Text("textfield.placeholder.password", comment: "Password"))
.textContentType(.password)
}
}
@@ -100,9 +95,9 @@ struct NewsBlurAddAccountView: View, Logging {
HStack{
Spacer()
if account == nil {
Text("Add Account", comment: "Button title")
Text("button.title.add-account", comment: "Add Account")
} else {
Text("Update Credentials", comment: "Button title")
Text("button.title.update-credentials", comment: "Update Credentials")
}
Spacer()
}
@@ -113,7 +108,7 @@ struct NewsBlurAddAccountView: View, Logging {
var newsBlurAccountExplainer: some View {
if account == nil {
return Text("Sign in to your NewsBlur account and sync your feeds across your devices. Your username and password will be encrypted and stored in Keychain.\n\nDont have a NewsBlur account? [Sign Up Here](https://newsblur.com)", comment: "Explanatory text describing the NewsBlur account")
return Text("label.text.newsblur-explainer", comment: "Sign in to your NewsBlur account and sync your feeds across your devices. Your username and password will be encrypted and stored in Keychain.\n\nDont have a NewsBlur account? [Sign Up Here](https://newsblur.com)")
.multilineTextAlignment(.center)
}
return Text("").multilineTextAlignment(.center)

Some files were not shown because too many files have changed in this diff Show More