diff --git a/ios/engine/KMEI/KeymanEngine/Classes/KeyboardMenuView.swift b/ios/engine/KMEI/KeymanEngine/Classes/KeyboardMenuView.swift index f5089a472b..94238dba5b 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/KeyboardMenuView.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/KeyboardMenuView.swift @@ -45,7 +45,8 @@ class KeyboardMenuView: UIView, UITableViewDelegate, UITableViewDataSource, UIGe titleCloseButton = closeButtonTitle } else { let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String ?? "Keyman" - titleCloseButton = "Close \(appName)" + let format = NSLocalizedString("keyboard-menu-exit", bundle: engineBundle, comment: "") + titleCloseButton = String.localizedStringWithFormat(format, appName) } if let keyboardList = keyboardList { diff --git a/ios/engine/KMEI/KeymanEngine/Classes/KeymanWebViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/KeymanWebViewController.swift index 070fc6138a..55326c6ab5 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/KeymanWebViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/KeymanWebViewController.swift @@ -10,7 +10,7 @@ import UIKit import WebKit import AudioToolbox -private let keyboardChangeHelpText = "Tap here to change keyboard" +private let keyboardChangeHelpText = NSLocalizedString("keyboard-help-change", bundle: engineBundle, comment: "") private let subKeyColor = Colors.popupKey private let subKeyColorHighlighted = Colors.popupKeyHighlighted diff --git a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardSwitcherViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardSwitcherViewController.swift index 1f5526fe71..5dd0d103cf 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardSwitcherViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardSwitcherViewController.swift @@ -19,7 +19,7 @@ class KeyboardSwitcherViewController: UITableViewController, UIAlertViewDelegate override func viewDidLoad() { super.viewDidLoad() - title = "Keyboards" + title = NSLocalizedString("menu-picker-title", bundle: engineBundle, comment: "") self.accessoryType = .none diff --git a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/LanguageLMDetailViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/LanguageLMDetailViewController.swift index c5cea614e1..6c03696a45 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/LanguageLMDetailViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/LanguageLMDetailViewController.swift @@ -125,14 +125,15 @@ class LanguageLMDetailViewController: UITableViewController, UIAlertViewDelegate } else { isUpdate = true } - - let alertController = UIAlertController(title: "\(language.name): \(lexicalModel.name)", - message: "Would you like to download this dictionary?", + + let format = NSLocalizedString("menu-lexical-model-install-title", bundle: engineBundle, comment: "") + let alertController = UIAlertController(title: String.localizedStringWithFormat(format, language.name, lexicalModel.name), + message: NSLocalizedString("menu-lexical-model-install-message", bundle: engineBundle, comment: ""), preferredStyle: UIAlertController.Style.alert) - alertController.addAction(UIAlertAction(title: "Cancel", + alertController.addAction(UIAlertAction(title: NSLocalizedString("command-cancel", bundle: engineBundle, comment: ""), style: UIAlertAction.Style.cancel, handler: nil)) - alertController.addAction(UIAlertAction(title: "Download", + alertController.addAction(UIAlertAction(title: NSLocalizedString("command-install", bundle: engineBundle, comment: ""), style: UIAlertAction.Style.default, handler: {_ in self.downloadHandler(lexicalModelIndex)} )) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/LexicalModelInfoViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/LexicalModelInfoViewController.swift index 9b542ee982..86c5774c74 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/LexicalModelInfoViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/LexicalModelInfoViewController.swift @@ -24,18 +24,18 @@ class LexicalModelInfoViewController: UITableViewController, UIAlertViewDelegate infoArray = [[String: String]]() infoArray.append([ - "title": "Dictionary version", + "title": NSLocalizedString("info-label-version-lexical-model", bundle: engineBundle, comment: ""), "subtitle": lexicalModelVersion ]) if !isCustomLexicalModel { infoArray.append([ - "title": "Help link", + "title": NSLocalizedString("info-command-help", bundle: engineBundle, comment: ""), "subtitle": "" ]) } infoArray.append([ - "title": "Uninstall dictionary", + "title": NSLocalizedString("command-uninstall-lexical-model", bundle: engineBundle, comment: ""), "subtitle": "" ]) } @@ -112,12 +112,13 @@ class LexicalModelInfoViewController: UITableViewController, UIAlertViewDelegate } private func showDeleteLexicalModel() { - let alertController = UIAlertController(title: title ?? "", message: "Would you like to delete this dictionary?", + let helpText = NSLocalizedString("command-uninstall-lexical-model-confirm", bundle: engineBundle, comment: "") + let alertController = UIAlertController(title: title ?? "", message: helpText, preferredStyle: UIAlertController.Style.alert) - alertController.addAction(UIAlertAction(title: "Cancel", + alertController.addAction(UIAlertAction(title: NSLocalizedString("command-cancel", bundle: engineBundle, comment: ""), style: UIAlertAction.Style.cancel, handler: nil)) - alertController.addAction(UIAlertAction(title: "Delete", + alertController.addAction(UIAlertAction(title: NSLocalizedString("command-uninstall", bundle: engineBundle, comment: ""), style: UIAlertAction.Style.default, handler: deleteHandler)) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/LexicalModelPickerViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/LexicalModelPickerViewController.swift index 66841a5b5d..a57fa75609 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/LexicalModelPickerViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/LexicalModelPickerViewController.swift @@ -33,8 +33,9 @@ class LexicalModelPickerViewController: UITableViewController, UIAlertViewDelega override func viewDidLoad() { super.viewDidLoad() - - title = "\(language.name) Dictionaries" + + let format = NSLocalizedString("menu-lexical-model-title", bundle: engineBundle, comment: "") + title = String.localizedStringWithFormat(format, language.name) if Manager.shared.canAddNewLexicalModels { let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(self.addClicked)) @@ -203,12 +204,12 @@ class LexicalModelPickerViewController: UITableViewController, UIAlertViewDelega item.isEnabled = true } - let title: String = "Dictionary Download Error" + let title: String = NSLocalizedString("notification-download-failure-lexical-model", bundle: engineBundle, comment: "") navigationController?.setToolbarHidden(true, animated: true) let alertController = UIAlertController(title: title, message: notification.error.localizedDescription, preferredStyle: UIAlertController.Style.alert) - alertController.addAction(UIAlertAction(title: "OK", + alertController.addAction(UIAlertAction(title: NSLocalizedString("command-ok", bundle: engineBundle, comment: ""), style: UIAlertAction.Style.cancel, handler: { _ in self.navigationController?.popToRootViewController(animated: true) @@ -276,7 +277,7 @@ class LexicalModelPickerViewController: UITableViewController, UIAlertViewDelega private func setIsDoneButtonEnabled(_ value: Bool) { _isDoneButtonEnabled = value if _isDoneButtonEnabled { - let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, + let doneButton = UIBarButtonItem(title: NSLocalizedString("command-done", bundle: engineBundle, comment: ""), style: .plain, target: self, action: #selector(self.doneClicked)) navigationItem.leftBarButtonItem = doneButton } else { @@ -325,13 +326,13 @@ class LexicalModelPickerViewController: UITableViewController, UIAlertViewDelega } func noModelsAvailable(cause: String = "nil") { - let msg = "No dictionaries available" - let logMsg = "No lexical models available for language \(language.id) (\(cause))" + let msg = NSLocalizedString("menu-lexical-model-none-message", bundle: engineBundle, comment: "") + let logMsg = "No lexical models available for language \(language.id): (\(cause))" log.info(logMsg) let alertController = UIAlertController(title: title, message: msg, preferredStyle: UIAlertController.Style.alert) - alertController.addAction(UIAlertAction(title: "OK", + alertController.addAction(UIAlertAction(title: NSLocalizedString("command-ok", bundle: engineBundle, comment: ""), style: UIAlertAction.Style.default, handler: { _ in self.navigationController?.popViewController(animated: true) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/ResourceInfoViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/ResourceInfoViewController.swift index fe30761380..a36cd52e4a 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/ResourceInfoViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/ResourceInfoViewController.swift @@ -48,22 +48,20 @@ class ResourceInfoViewController: UIViewController, UIAlertViewDelegate, UITable override func viewDidLoad() { super.viewDidLoad() - let bundle = Bundle(for: Manager.self) - infoArray = [[String: String]]() infoArray.append([ - "title": NSLocalizedString("Keyboard version", bundle: bundle, comment: "As seen on the keyboard's information page"), + "title": NSLocalizedString("info-label-version-keyboard", bundle: engineBundle, comment: ""), "subtitle": resource.version ]) if !isCustomKeyboard { infoArray.append([ - "title": NSLocalizedString("Help link", bundle: bundle, comment: "Links to the help page of the keyboard"), + "title": NSLocalizedString("info-command-help", bundle: engineBundle, comment: ""), "subtitle": "" ]) } infoArray.append([ - "title": NSLocalizedString("Uninstall keyboard", bundle: bundle, comment: "Removes the keyboard from the application"), + "title": NSLocalizedString("command-uninstall-keyboard", bundle: engineBundle, comment: ""), "subtitle": "" ]) @@ -197,12 +195,13 @@ class ResourceInfoViewController: UIViewController, UIAlertViewDelegate, UITable } private func showDeleteKeyboard() { - let alertController = UIAlertController(title: title ?? "", message: "Would you like to delete this keyboard?", + let uninstallHelp = NSLocalizedString("command-uninstall-keyboard-confirm", bundle: engineBundle, comment: "") + let alertController = UIAlertController(title: title ?? "", message: uninstallHelp, preferredStyle: UIAlertController.Style.alert) - alertController.addAction(UIAlertAction(title: "Cancel", + alertController.addAction(UIAlertAction(title: NSLocalizedString("command-cancel", bundle: engineBundle, comment: ""), style: UIAlertAction.Style.cancel, handler: nil)) - alertController.addAction(UIAlertAction(title: "Delete", + alertController.addAction(UIAlertAction(title: NSLocalizedString("command-uninstall", bundle: engineBundle, comment: ""), style: UIAlertAction.Style.default, handler: deleteHandler)) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Settings/InstalledLanguagesViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/Settings/InstalledLanguagesViewController.swift index 5e5f3c4b26..dff455c2c1 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Settings/InstalledLanguagesViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Settings/InstalledLanguagesViewController.swift @@ -360,9 +360,13 @@ public class InstalledLanguagesViewController: UITableViewController, UIAlertVie private func batchUpdateCompleted(results: BatchUpdateCompletedNotification) { if let toolbar = navigationController?.toolbar as? ResourceDownloadStatusToolbar { if results.failures.count == 0 { - toolbar.displayStatus("\(results.successes.count) update(s) successfully downloaded!", withIndicator: false, duration: 3.0) + let formatString = NSLocalizedString("notification-update-success", bundle: engineBundle, comment: "") + toolbar.displayStatus(String.localizedStringWithFormat(formatString, results.successes.count), withIndicator: false, duration: 3.0) } else { - toolbar.displayStatus("Updates complete: \(results.successes.count) successful, \(results.failures.count) failed", withIndicator: false, duration: 3.0) + // Needs to be a short string on iPhones. + // Possible TODO: condition on "is an iPad", provide more info on iPads? + let formatString = NSLocalizedString("notification-update-failed", bundle: engineBundle, comment: "") + toolbar.displayStatus(String.localizedStringWithFormat(formatString, results.failures.count), withIndicator: false, duration: 3.0) } } diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Settings/LanguageSettingsViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/Settings/LanguageSettingsViewController.swift index 90c3988c96..fa4eceaa45 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Settings/LanguageSettingsViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Settings/LanguageSettingsViewController.swift @@ -35,7 +35,8 @@ class LanguageSettingsViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() - title = "\(language.name) Settings" + let titleFormat = NSLocalizedString("menu-langsettings-title", bundle: engineBundle, comment: "") + title = String.localizedStringWithFormat(titleFormat, language.name) log.info("viewDidLoad: LanguageSettingsViewController title: \(title ?? "")") if Manager.shared.canAddNewKeyboards { @@ -191,9 +192,11 @@ class LanguageSettingsViewController: UITableViewController { var title: String switch (section) { case 0: - title = "Keyboards" + // We do NOT use a general-use "keyboards" entry because different languages have different + // pluralization rules, and it's a major assumption to assume which is preferred for general use. + title = NSLocalizedString("menu-langsettings-section-keyboards", bundle: engineBundle, comment: "") case 1: - title = "Language settings" + title = NSLocalizedString("menu-langsettings-section-settings", bundle: engineBundle, comment: "") default: title = "unknown header" } @@ -233,30 +236,21 @@ class LanguageSettingsViewController: UITableViewController { cell.accessoryType = .none switch indexPath.row { case 0: - cell.textLabel?.text = "Enable predictions" + cell.textLabel?.text = NSLocalizedString("menu-langsettings-toggle-predict", bundle: engineBundle, comment: "") case 1: doCorrectionsLabel = cell.textLabel - cell.textLabel?.text = "Enable corrections" + cell.textLabel?.text = NSLocalizedString("menu-langsettings-toggle-correct", bundle: engineBundle, comment: "") cell.textLabel?.isEnabled = !(doCorrectionsSwitch?.isHidden ?? false) case 2: - cell.textLabel?.text = "Dictionaries" + cell.textLabel?.text = NSLocalizedString("menu-langsettings-label-lexical-models", bundle: engineBundle, comment: "") cell.accessoryType = .disclosureIndicator - if let modelCt = language.lexicalModels?.count { - switch modelCt { - case 0: - cell.detailTextLabel?.text = "no dictionaries installed" - case 1: - cell.detailTextLabel?.text = "\(language.lexicalModels![0].name)" - default: - cell.detailTextLabel?.text = "\(modelCt) dictionaries installed" - } + let modelCt = language.lexicalModels?.count ?? 0 + if modelCt != 1 { + let formatString = NSLocalizedString("menu-langsettings-lexical-model-count", bundle: engineBundle, comment: "") + cell.detailTextLabel?.text = String.localizedStringWithFormat(formatString, modelCt) } else { - cell.detailTextLabel?.text = "no dictionaries installed" + cell.detailTextLabel?.text = "\(language.lexicalModels![0].name)" } - case 3: // future - cell.textLabel?.text = "Manage dictionary" - cell.accessoryType = .disclosureIndicator - cell.isUserInteractionEnabled = false default: cell.textLabel?.text = "error" diff --git a/ios/engine/KMEI/KeymanEngine/en.lproj/Localizable.strings b/ios/engine/KMEI/KeymanEngine/en.lproj/Localizable.strings index 13680b6687..7794866580 100644 Binary files a/ios/engine/KMEI/KeymanEngine/en.lproj/Localizable.strings and b/ios/engine/KMEI/KeymanEngine/en.lproj/Localizable.strings differ diff --git a/ios/engine/KMEI/KeymanEngine/en.lproj/Localizable.stringsdict b/ios/engine/KMEI/KeymanEngine/en.lproj/Localizable.stringsdict index 6fcaab931c..17aa9c21d2 100644 --- a/ios/engine/KMEI/KeymanEngine/en.lproj/Localizable.stringsdict +++ b/ios/engine/KMEI/KeymanEngine/en.lproj/Localizable.stringsdict @@ -2,6 +2,56 @@ + menu-langsettings-lexical-model-count + + NSStringLocalizedFormatKey + %#@count@ + count + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + u + zero + No dictionaries installed + one + %u dictionary installed + other + %u dictionaries installed + + + notification-update-failed + + NSStringLocalizedFormatKey + %#@count@ + count + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + u + one + %u update failed + other + %u updates failed + + + notification-update-success + + NSStringLocalizedFormatKey + %#@count@ + count + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + u + one + %u update successful + other + %u updates successful + + settings-keyboards-installed-count NSStringLocalizedFormatKey