From 651176a304d3d0e9cca739a8cf4a78b3ed0f5d45 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Sun, 15 Sep 2019 00:43:29 -0700 Subject: [PATCH] First stab at Hindi localization! --- Clocker/Clocker.xcodeproj/project.pbxproj | 5 ++ Clocker/Clocker/en.lproj/Localizable.strings | 16 ++++++ Clocker/Clocker/hi.lproj/InfoPlist.strings | 10 ++++ Clocker/Clocker/hi.lproj/Localizable.strings | 38 +++++++++++++ .../Date Additions/Date+TimeAgo.swift | 4 +- .../Data Layer/TimezoneDataOperations.swift | 7 ++- Clocker/Panel/ParentPanelController.swift | 9 ++- .../About/AboutViewController.swift | 3 +- .../General/PreferencesViewController.swift | 10 ++-- .../PermissionsViewController.swift | 57 ++++++++++++------- 10 files changed, 128 insertions(+), 31 deletions(-) create mode 100644 Clocker/Clocker/hi.lproj/InfoPlist.strings create mode 100644 Clocker/Clocker/hi.lproj/Localizable.strings diff --git a/Clocker/Clocker.xcodeproj/project.pbxproj b/Clocker/Clocker.xcodeproj/project.pbxproj index eb08e5f..a39b3d2 100755 --- a/Clocker/Clocker.xcodeproj/project.pbxproj +++ b/Clocker/Clocker.xcodeproj/project.pbxproj @@ -216,6 +216,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 352AF497232E07B400D96FA7 /* hi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hi; path = hi.lproj/InfoPlist.strings; sourceTree = ""; }; + 352AF499232E07B400D96FA7 /* hi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hi; path = hi.lproj/Localizable.strings; sourceTree = ""; }; 3545C52A22612BCC00121E25 /* RateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RateTests.swift; sourceTree = ""; }; 3595FACF227F88BC0044A12A /* UserDefaults + KVOExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults + KVOExtensions.swift"; sourceTree = ""; }; 35C36EE022595EFD002FA5C6 /* StatusContainerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusContainerView.swift; sourceTree = ""; }; @@ -970,6 +972,7 @@ English, en, Base, + hi, ); mainGroup = DD4F7BF913C30F9F00825C6E; productRefGroup = DD4F7C0513C30F9F00825C6E /* Products */; @@ -1251,6 +1254,7 @@ isa = PBXVariantGroup; children = ( 9A13BAE11CA882FA007C6CBE /* en */, + 352AF497232E07B400D96FA7 /* hi */, ); name = InfoPlist.strings; path = Clocker; @@ -1260,6 +1264,7 @@ isa = PBXVariantGroup; children = ( 9A13BAEB1CA88A76007C6CBE /* en */, + 352AF499232E07B400D96FA7 /* hi */, ); name = Localizable.strings; path = Clocker; diff --git a/Clocker/Clocker/en.lproj/Localizable.strings b/Clocker/Clocker/en.lproj/Localizable.strings index 6567786..26fd763 100644 --- a/Clocker/Clocker/en.lproj/Localizable.strings +++ b/Clocker/Clocker/en.lproj/Localizable.strings @@ -20,3 +20,19 @@ "start-at-login" = "Start At Login"; "setup-steps" = "It only takes 3 steps to set up Clocker"; "Permissions-Header" = "Permissions"; +"See your next Calendar event here." = "See your next Calendar event here."; +"Click here to start." = "Click here to start."; +"Reminders Access" = "Reminders Access"; +"Calendar Access" = "Calendar Access"; +"Permissions" = "Permissions"; +"Calendar Detail" = "Upcoming events from your personal and shared calendars can be shown in the menubar and the panel."; +"Reminders Detail" = "Set reminders in the timezone of the location of your choice. Your reminders are stored in the default Reminders app."; +"Privacy Text" = "You can change this later in the Privacy section of the System Preferences."; +"Granted Button Text" = "Granted"; +"Denied Button Text" = "Denied"; +"Grant Button Text" = "Grant"; +"Start at Login" = "Start Clocker at Login"; +"Selected Timezones" = "Selected Timezones"; +"Sort by Time Difference" = "Sort by Time Difference"; +"Sort by Name" = "Sort by Name"; +"Sort by Label" = "Sort by Label"; diff --git a/Clocker/Clocker/hi.lproj/InfoPlist.strings b/Clocker/Clocker/hi.lproj/InfoPlist.strings new file mode 100644 index 0000000..0ef5caf --- /dev/null +++ b/Clocker/Clocker/hi.lproj/InfoPlist.strings @@ -0,0 +1,10 @@ +/* + InfoPlist.strings + Clocker + + Created by Abhishek Banthia on 3/27/16. + +*/ + +"CFBundleDisplayName" = "विश्व का समय"; +"CFBundleName" = "विश्व का समय"; diff --git a/Clocker/Clocker/hi.lproj/Localizable.strings b/Clocker/Clocker/hi.lproj/Localizable.strings new file mode 100644 index 0000000..7ab1579 --- /dev/null +++ b/Clocker/Clocker/hi.lproj/Localizable.strings @@ -0,0 +1,38 @@ +/* + Localizable.strings + Clocker + + Created by Abhishek Banthia on 3/27/16. + +*/ + +"Thank you for helping make Clocker even better!" = "Thank you for helping make Clocker even better!"; +"iRateMessageTitle" = "Rate %@"; +"iRateAppMessage" = "If you enjoy using %@, would you mind taking a moment to rate it? It won’t take more than a minute. Thanks for your support!"; +"iRateGameMessage" = "If you enjoy playing %@, would you mind taking a moment to rate it? It won’t take more than a minute. Thanks for your support!"; +"iRateCancelButton" = "No, Thanks"; +"iRateRateButton" = "Rate It Now"; +"iRateRemindButton" = "Remind Me Later"; +"iRateUpdateMessage" = "Update now?"; +"ClockerVersion" = "Version %@"; +"CLFeedbackAlertTitle" = "Thank you for helping make Clocker even better!"; +"app-name" = "Clocker"; +"start-at-login" = "Start At Login"; +"setup-steps" = "It only takes 3 steps to set up Clocker"; +"Permissions-Header" = "अनुमति"; +"See your next Calendar event here." = "अपना अगला कैलेंडर कार्यक्रम यहां देखें।"; +"Click here to start." = "शुरू करने के लिए यहाँ क्लिक करें।"; +"Reminders Access" = "रिमाइंडर अनुमति"; +"Calendar Access" = "कैलेंडर अनुमति"; +"Permissions" = "अनुमति"; +"Reminders Detail" = "अपनी पसंद के स्थान के समय क्षेत्र में रिमाइंडर सेट करें। आपके रिमाइंडर डिफ़ॉल्ट रिमाइंडर ऐप में संग्रहीत किए जाते हैं।"; +"Calendar Detail" = "अपने निजी और साझा कैलेंडर से आने वाली घटनाओं मेनूबार और पैनल में दिखाया जा सकता है।"; +"Privacy Text" = "आप आपकी पसंद भविष्य में सिस्टम प्रिफ्रेंसेज के प्राइवसी अनुभाग में बदल सकते हैं।"; +"Granted Button Text" = "स्वीकृत"; +"Denied Button Text" = "इनकार किया"; +"Grant Button Text" = "अनुदान"; +"Start at Login" = "लॉगिन पर शुरू करें"; +"Selected Timezones" = "चयनित स्थान"; +"Sort by Time Difference" = "समय अंतर द्वारा सॉर्ट करें"; +"Sort by Name" = "नाम द्वारा सॉर्ट करें"; +"Sort by Label" = "लेबल द्वारा सॉर्ट करें"; diff --git a/Clocker/Dependencies/Date Additions/Date+TimeAgo.swift b/Clocker/Dependencies/Date Additions/Date+TimeAgo.swift index a058bd7..733851d 100755 --- a/Clocker/Dependencies/Date Additions/Date+TimeAgo.swift +++ b/Clocker/Dependencies/Date Additions/Date+TimeAgo.swift @@ -129,7 +129,9 @@ public extension Date { return DateToolsLocalizedStrings("1 second ago") } - return DateToolsLocalizedStrings("Just now") + // Instead of returning "Just now" or the equivalent localized version; let's return an empty string + // Previously, we returned DateToolsLocalizedStrings("Just now") + return CLEmptyString } } diff --git a/Clocker/Panel/Data Layer/TimezoneDataOperations.swift b/Clocker/Panel/Data Layer/TimezoneDataOperations.swift index fed6044..0b5b3f4 100644 --- a/Clocker/Panel/Data Layer/TimezoneDataOperations.swift +++ b/Clocker/Panel/Data Layer/TimezoneDataOperations.swift @@ -8,6 +8,7 @@ class TimezoneDataOperations: NSObject { private lazy var nsCalendar: Calendar = Calendar.autoupdatingCurrent private static var gregorianCalendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian) private static var swiftyCalendar = Calendar(identifier: .gregorian) + private static let currentLocale = Locale.current.identifier init(with timezone: TimezoneData) { dataObject = timezone @@ -222,7 +223,7 @@ extension TimezoneDataOperations { let timeDifference = local.timeAgo(since: timezoneDate) - if timeDifference.contains("Just now") { + if timeDifference.isEmpty { return CLEmptyString } @@ -232,6 +233,10 @@ extension TimezoneDataOperations { let agoString = timezoneDate.timeAgo(since: local, numericDates: true) replaceAgo.append(agoString.replacingOccurrences(of: "ago", with: CLEmptyString)) + if !TimezoneDataOperations.currentLocale.contains("en") { + return replaceAgo + } + let minuteDifference = calculateTimeDifference(with: local as NSDate, timezoneDate: timezoneDate as NSDate) minuteDifference == 0 ? replaceAgo.append("ahead") : replaceAgo.append("\(minuteDifference) mins ahead") return replaceAgo.lowercased() diff --git a/Clocker/Panel/ParentPanelController.swift b/Clocker/Panel/ParentPanelController.swift index 3b84d88..09f7950 100644 --- a/Clocker/Panel/ParentPanelController.swift +++ b/Clocker/Panel/ParentPanelController.swift @@ -256,8 +256,10 @@ class ParentPanelController: NSWindowController { if eventCenter.calendarAccessGranted() { // Nice. Events will be retrieved when we open the panel } else if eventCenter.calendarAccessNotDetermined() { - nextEventLabel.stringValue = "See your next Calendar event here." - setCalendarButtonTitle(buttonTitle: "Click here to start.") + nextEventLabel.stringValue = NSLocalizedString("See your next Calendar event here.", + comment: "Next Event Label for no Calendar access") + setCalendarButtonTitle(buttonTitle: NSLocalizedString("Click here to start.", + comment: "Button Title for no Calendar access")) } else { removeUpcomingEventView() } @@ -641,7 +643,8 @@ class ParentPanelController: NSWindowController { } @IBAction func calendarButtonAction(_: NSButton) { - if calendarButton.title == "Click here to start." { + if calendarButton.title == NSLocalizedString("Click here to start.", + comment: "Button Title for no Calendar access") { showPermissionsWindow() } else { retrieveCalendarEvents() diff --git a/Clocker/Preferences/About/AboutViewController.swift b/Clocker/Preferences/About/AboutViewController.swift index c5868d4..1a6d7a0 100644 --- a/Clocker/Preferences/About/AboutViewController.swift +++ b/Clocker/Preferences/About/AboutViewController.swift @@ -26,10 +26,11 @@ class AboutViewController: ParentViewController { privateFeedback.setAccessibilityIdentifier("ClockerPrivateFeedback") + let appDisplayName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") ?? "Clocker" let shortVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") ?? "N/A" let longVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") ?? "N/A" - versionField.stringValue = "Clocker \(shortVersion) (\(longVersion))" + versionField.stringValue = "\(appDisplayName) \(shortVersion) (\(longVersion))" setup() diff --git a/Clocker/Preferences/General/PreferencesViewController.swift b/Clocker/Preferences/General/PreferencesViewController.swift index 747e36e..dd384c6 100644 --- a/Clocker/Preferences/General/PreferencesViewController.swift +++ b/Clocker/Preferences/General/PreferencesViewController.swift @@ -122,11 +122,11 @@ class PreferencesViewController: ParentViewController { } private func setupLocalizedText() { - startAtLoginLabel.stringValue = "Start Clocker at Login" - headerLabel.stringValue = "Selected Timezones" - timezoneSortButton.title = "Sort by Time Difference" - timezoneNameSortButton.title = "Sort by Name" - labelSortButton.title = "Sort by Label" + startAtLoginLabel.stringValue = NSLocalizedString("Start at Login", comment: "Start at Login") + headerLabel.stringValue = NSLocalizedString("Selected Timezones", comment: "Start at Login") + timezoneSortButton.title = NSLocalizedString("Sort by Time Difference", comment: "Start at Login") + timezoneNameSortButton.title = NSLocalizedString("Sort by Name", comment: "Start at Login") + labelSortButton.title = NSLocalizedString("Sort by Label", comment: "Start at Login") } @objc func refreshTimezoneTableView() { diff --git a/Clocker/Preferences/Permissions/PermissionsViewController.swift b/Clocker/Preferences/Permissions/PermissionsViewController.swift index aeb6bfb..3f62ce9 100644 --- a/Clocker/Preferences/Permissions/PermissionsViewController.swift +++ b/Clocker/Preferences/Permissions/PermissionsViewController.swift @@ -50,16 +50,20 @@ class PermissionsViewController: ParentViewController { } private func setupLocalizedText() { - headerLabel.stringValue = "Permissions" + headerLabel.stringValue = NSLocalizedString("Permissions", comment: "Permissions Tab Titles") - reminderHeaderLabel.stringValue = "Reminders Access" - reminderDetailLabel.stringValue = "Set reminders in the timezone of the location of your choice. Your reminders are stored in the default Reminders app. " + reminderHeaderLabel.stringValue = NSLocalizedString("Reminders Access", + comment: "Reminders Permission Title") + reminderDetailLabel.stringValue = NSLocalizedString("Reminders Detail", + comment: "Reminders Detail Text") - calendarHeaderLabel.stringValue = "Calendar Access" - calendarDetailLabel.stringValue = "Upcoming events from your personal and shared calendars can be shown in the menubar and the panel." - - privacyLabel.stringValue = "You can change this later in the Privacy section of the System Preferences." + calendarHeaderLabel.stringValue = NSLocalizedString("Calendar Access", + comment: "Calendar Permission Title") + calendarDetailLabel.stringValue = NSLocalizedString("Calendar Detail", + comment: "Calendar Detail Text") + privacyLabel.stringValue = NSLocalizedString("Privacy Text", + comment: "Text explaining options can be changed in the future through System Preferences") [calendarHeaderLabel, calendarDetailLabel, privacyLabel, reminderDetailLabel, reminderHeaderLabel, headerLabel].forEach { $0?.textColor = Themer.shared().mainTextColor() } } @@ -77,21 +81,27 @@ class PermissionsViewController: ParentViewController { } */ if EventCenter.sharedCenter().calendarAccessGranted() { - calendarButton.title = "Granted" + calendarButton.title = NSLocalizedString("Granted Button Text", + comment: "Granted Button Text") } else if EventCenter.sharedCenter().calendarAccessDenied() { - calendarButton.title = "Denied" + calendarButton.title = NSLocalizedString("Denied Button Text", + comment: "Denied Button Text") } else if EventCenter.sharedCenter().calendarAccessNotDetermined() { - calendarButton.title = "Grant" + calendarButton.title = NSLocalizedString("Grant Button Text", + comment: "Grant Button Text") } else { calendarButton.title = "Unexpected" } if EventCenter.sharedCenter().reminderAccessGranted() { - remindersButton.title = "Granted" + remindersButton.title = NSLocalizedString("Granted Button Text", + comment: "Granted Button Text") } else if EventCenter.sharedCenter().reminderAccessDenied() { - remindersButton.title = "Denied" + remindersButton.title = NSLocalizedString("Denied Button Text", + comment: "Denied Button Text") } else if EventCenter.sharedCenter().reminderAccessNotDetermined() { - remindersButton.title = "Grant" + remindersButton.title = NSLocalizedString("Grant Button Text", + comment: "Grant Button Text") } else { remindersButton.title = "Unexpected" } @@ -131,19 +141,23 @@ class PermissionsViewController: ParentViewController { self.view.window?.orderBack(nil) NSApp.activate(ignoringOtherApps: true) - self.calendarButton.title = "Granted" + self.calendarButton.title = NSLocalizedString("Granted Button Text", + comment: "Granted Button Text") // Used to update CalendarViewController's view NotificationCenter.default.post(name: .calendarAccessGranted, object: nil) } } else { - Logger.log(object: ["Reminder Access Not Granted": "YES"], for: "Reminder Access Not Granted") + Logger.log(object: ["Reminder Access Not Granted": "YES"], + for: "Reminder Access Not Granted") } }) } else if eventCenter.calendarAccessGranted() { - calendarButton.title = "Granted" + calendarButton.title = NSLocalizedString("Granted Button Text", + comment: "Granted Button Text") } else { - calendarButton.title = "Denied" + calendarButton.title = NSLocalizedString("Denied Button Text", + comment: "Denied Button Text") } } @@ -164,16 +178,19 @@ class PermissionsViewController: ParentViewController { self.view.window?.orderBack(nil) NSApp.activate(ignoringOtherApps: true) - self.remindersButton.title = "Granted" + self.remindersButton.title = NSLocalizedString("Granted Button Text", + comment: "Granted Button Text") } } else { Logger.log(object: ["Reminder Access Not Granted": "YES"], for: "Reminder Access Not Granted") } }) } else if eventCenter.reminderAccessGranted() { - remindersButton.title = "Granted" + remindersButton.title = NSLocalizedString("Granted Button Text", + comment: "Granted Button Text") } else { - remindersButton.title = "Denied" + remindersButton.title = NSLocalizedString("Denied Button Text", + comment: "Denied Button Text") } } }