More localization. More context menus.

This commit is contained in:
Selim Mustafaev 2020-12-09 00:14:54 +03:00
parent ada84bbe31
commit 84a994cb7f
14 changed files with 304 additions and 56 deletions

View File

@ -146,6 +146,7 @@
7A3F07AA24360DC800E59687 /* Dated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dated.swift; sourceTree = "<group>"; };
7A3F07AC2436350B00E59687 /* SearchController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchController.swift; sourceTree = "<group>"; };
7A43F9F7246C8A6200BA5B49 /* JWT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = "<group>"; };
7A52AB292580112E002CD910 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
7A530B7924001D3300CBFE6E /* CheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckController.swift; sourceTree = "<group>"; };
7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleCell.swift; sourceTree = "<group>"; };
7A530B7F2401803A00CBFE6E /* Vehicle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vehicle.swift; sourceTree = "<group>"; };
@ -658,6 +659,7 @@
children = (
7A61FF8A2575A2CD00D905D5 /* Base */,
7A61FF8D2575A2F900D905D5 /* ru */,
7A52AB292580112E002CD910 /* en */,
);
name = Localizable.strings;
sourceTree = "<group>";
@ -805,7 +807,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 58;
CURRENT_PROJECT_VERSION = 59;
DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
@ -828,7 +830,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 58;
CURRENT_PROJECT_VERSION = 59;
DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;

View File

@ -14,35 +14,35 @@
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>2</integer>
<integer>6</integer>
</dict>
<key>DifferenceKit (Playground) 2.xcscheme</key>
<dict>
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>3</integer>
<integer>7</integer>
</dict>
<key>DifferenceKit (Playground).xcscheme</key>
<dict>
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>1</integer>
<integer>3</integer>
</dict>
<key>Eureka (Playground) 1.xcscheme</key>
<dict>
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>5</integer>
<integer>2</integer>
</dict>
<key>Eureka (Playground) 2.xcscheme</key>
<dict>
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>6</integer>
<integer>4</integer>
</dict>
<key>Eureka (Playground) 3.xcscheme</key>
<dict>
@ -70,7 +70,7 @@
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>4</integer>
<integer>1</integer>
</dict>
<key>GettingStarted (Playground) 1.xcscheme</key>
<dict>
@ -112,7 +112,7 @@
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>13</integer>
<integer>12</integer>
</dict>
<key>Rx (Playground) 1.xcscheme</key>
<dict>
@ -133,7 +133,7 @@
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>7</integer>
<integer>5</integer>
</dict>
<key>SwiftDate (Playground) 1.xcscheme</key>
<dict>
@ -147,7 +147,7 @@
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>12</integer>
<integer>13</integer>
</dict>
<key>SwiftDate (Playground) 3.xcscheme</key>
<dict>

View File

@ -115,7 +115,7 @@ class FiltersController: FormViewController {
row.value = self.filter.addedBy?.description ?? AddedBy.anyone.description
}
form +++ Section("Time range")
form +++ Section(NSLocalizedString("Time range", comment: ""))
<<< DateInlineRow("FromDate") { row in
row.title = NSLocalizedString("From", comment: "")
row.noValueDisplayText = NSLocalizedString("Beginning", comment: "")

View File

@ -61,7 +61,7 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
override func viewDidLoad() {
super.viewDidLoad()
self.title = self.vehicle?.getNumber() ?? "Events"
self.title = self.vehicle?.getNumber() ?? NSLocalizedString("Events", comment: "")
#if targetEnvironment(macCatalyst)
self.map.showsZoomControls = true
@ -127,13 +127,27 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
// MARK: - UITableViewDelegate
func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ in
let edit = UIAction(title: NSLocalizedString("Edit", comment: ""), image: UIImage(systemName: "pencil")) { action in
self.editEvent(index: indexPath.row)
}
let delete = UIAction(title: NSLocalizedString("Delete", comment: ""), image: UIImage(systemName: "trash"), attributes: .destructive) { action in
self.deleteEvent(index: indexPath.row)
}
return UIMenu(title: NSLocalizedString("Actions", comment: ""), children: [edit, delete])
}
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let delete = UIContextualAction(style: .destructive, title: "Delete") { action, view, completion in
let delete = UIContextualAction(style: .destructive, title: NSLocalizedString("Delete", comment: "")) { action, view, completion in
self.deleteEvent(index: indexPath.row, completion: completion)
}
delete.image = UIImage(systemName: "trash")
let edit = UIContextualAction(style: .normal, title: "Edit") { action, view, completion in
let edit = UIContextualAction(style: .normal, title: NSLocalizedString("Edit", comment: "")) { action, view, completion in
self.editEvent(index: indexPath.row)
completion(true)
}
@ -147,7 +161,7 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
// MARK: - Event actions
func deleteEvent(index: Int, completion: @escaping (Bool) -> Void) {
func deleteEvent(index: Int, completion: ((Bool) -> Void)? = nil) {
guard let vehicle = self.vehicle else {
HUD.flash(.labeledError(title: nil, subtitle: "Unknown vehicle"))
return
@ -157,9 +171,9 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
if let eventId = event.id {
HUD.show(.progress)
Api.remove(event: eventId).observeOn(MainScheduler.instance).subscribe(onSuccess: { vehicle in
completion(self.update(vehicle: vehicle))
completion?(self.update(vehicle: vehicle))
}, onError: { error in
completion(false)
completion?(false)
HUD.show(error: error)
print(error)
}).disposed(by: self.bag)
@ -177,7 +191,7 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
let event = vehicle.events[index]
let sb = UIStoryboard(name: "Main", bundle: nil)
let controller = sb.instantiateViewController(identifier: "LocationEditController") as LocationEditController
controller.title = "Edit event"
controller.title = NSLocalizedString("Edit event", comment: "")
controller.date = Date(timeIntervalSince1970: event.date)
controller.placemark = Placemark(latitude: event.latitude, longitude: event.longitude, address: event.address)
controller.onDone = { newEvent in
@ -204,7 +218,7 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
let sb = UIStoryboard(name: "Main", bundle: nil)
let controller = sb.instantiateViewController(identifier: "LocationEditController") as LocationEditController
controller.title = "Add new event"
controller.title = NSLocalizedString("Add new event", comment: "")
controller.onDone = { newEvent in
self.navigationController?.popViewController(animated: true, completion: {
HUD.show(.progress)

View File

@ -21,7 +21,7 @@ class GlobalEventsController: UIViewController {
Api.events(with: self.filter)
.observeOn(MainScheduler.init())
.subscribe(onSuccess: { events in
self.title = "Events found: \(events.count)"
self.title = String.localizedStringWithFormat(NSLocalizedString("events found", comment: ""), events.count)
let pins = events.map(EventPin.init(event:))
self.map.removeAnnotations(self.map.annotations)
self.map.addAnnotations(pins)

View File

@ -22,7 +22,7 @@ class LocationEditController: FormViewController {
form +++ Section("")
<<< DateTimeInlineRow(){
$0.title = "Date and time"
$0.title = NSLocalizedString("Date and time", comment: "")
$0.value = self.date
}.onChange { row in
if let newDate = row.value {
@ -31,7 +31,7 @@ class LocationEditController: FormViewController {
}
<<< LocationRow() { row in
row.title = "Location"
row.title = NSLocalizedString("Location", comment: "")
row.value = self.placemark
}.onChange { row in
if let newPlacemark = row.value {

View File

@ -11,7 +11,7 @@ enum OsagoCheckSource: Equatable, CustomStringConvertible {
var description: String {
switch self {
case .plateNumber(let number):
return "Plate number (\(number))"
return NSLocalizedString("plate number", comment: "Check by") + " (\(number))"
case .vin(let number):
return "VIN (\(number))"
}
@ -26,21 +26,21 @@ class OsagoAddController: FormViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.title = "OSAGO check"
self.title = NSLocalizedString("OSAGO check", comment: "")
form +++ Section("Check parameters")
form +++ Section(NSLocalizedString("Check parameters", comment: ""))
<<< DateTimeInlineRow("date") { row in
row.title = "Check date"
row.title = NSLocalizedString("Check date", comment: "")
row.value = Date()
}
<<< PickerInlineRow<OsagoCheckSource>("SourcePicker") { row in
row.title = "Check by"
row.title = NSLocalizedString("Check by", comment: "")
row.value = self.checkSources.first
row.options = self.checkSources
}
form +++ Section()
<<< ButtonRow() { $0.title = "Check" }.onCellSelection { _, _ in
<<< ButtonRow() { $0.title = NSLocalizedString("Check", comment: "verb") }.onCellSelection { _, _ in
// HUD.show(.progress)
// Api.checkOsago(number: "Н133РО161", vin: nil, date: Date(), token: "")
// .observeOn(MainScheduler.instance)

View File

@ -12,7 +12,7 @@ class OsagoController: FormViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.title = "OSAGO contracts"
self.title = NSLocalizedString("OSAGO contracts", comment: "")
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(checkNewDate(_:)))
self.tableView.rowHeight = UITableView.automaticDimension

View File

@ -225,6 +225,45 @@ class RecordsController: UIViewController, UITableViewDelegate {
// MARK: - UITableViewDelegate
func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
let record = self.recordsDataSource.item(at: indexPath)
return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ in
let check = UIAction(title: NSLocalizedString("Check", comment: ""), image: UIImage(systemName: "eye")) { action in
if let number = record.number {
self.check(number: number, event: record.event)
}
}
let delete = UIAction(title: NSLocalizedString("Delete", comment: ""), image: UIImage(systemName: "trash"), attributes: .destructive) { action in
self.delete(record: record)
}
let share = UIAction(title: NSLocalizedString("Share", comment: ""), image: UIImage(systemName: "square.and.arrow.up")) { action in
self.share(record: record)
}
let showText = UIAction(title: NSLocalizedString("Show recognized text", comment: ""), image: UIImage(systemName: "textformat")) { action in
self.showAlert(title: NSLocalizedString("Recognized text", comment: ""), message: record.rawText)
}
let showMap = UIAction(title: NSLocalizedString("Show on map", comment: ""), image: UIImage(systemName: "mappin.and.ellipse")) { action in
self.showOnMap(record)
}
let edit = UIAction(title: NSLocalizedString("Edit plate number", comment: ""), image: UIImage(systemName: "pencil")) { action in
self.edit(record: record)
}
var actions = [edit, showText, showMap, share, delete]
if record.number != nil {
actions.insert(check, at: 0)
}
return UIMenu(title: NSLocalizedString("Actions", comment: ""), children: actions)
}
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
guard let cell = tableView.cellForRow(at: indexPath) else { return nil }
@ -247,15 +286,7 @@ class RecordsController: UIViewController, UITableViewDelegate {
action.image = UIImage(systemName: "ellipsis" /*"square.and.arrow.up"*/)
let delete = UIContextualAction(style: .destructive, title: NSLocalizedString("Delete", comment: "")) { action, view, completion in
do {
if let realm = record.realm {
try realm.write {
realm.delete(record)
}
}
} catch {
print(error)
}
self.delete(record: record)
completion(true)
}
delete.image = UIImage(systemName: "trash")
@ -270,14 +301,7 @@ class RecordsController: UIViewController, UITableViewDelegate {
let sheet = UIAlertController(title: NSLocalizedString("More actions", comment: ""), message: nil, preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel) { _ in sheet.dismiss(animated: true, completion: nil) }
let share = UIAlertAction(title: NSLocalizedString("Share", comment: ""), style: .default) { _ in
do {
let url = try FileManager.default.url(for: record.path, in: "recordings")
let controller = UIActivityViewController(activityItems: [url], applicationActivities: nil)
self.present(controller, animated: true)
} catch {
print("Error sharing audio record: \(error.localizedDescription)")
HUD.show(error: error)
}
self.share(record: record)
}
let showText = UIAlertAction(title: NSLocalizedString("Show recognized text", comment: ""), style: .default) { action in
self.showAlert(title: NSLocalizedString("Recognized text", comment: ""), message: record.rawText)
@ -286,10 +310,7 @@ class RecordsController: UIViewController, UITableViewDelegate {
self.edit(record: record)
}
let showOnMap = UIAlertAction(title: NSLocalizedString("Show on map", comment: ""), style: .default) { action in
let controller = ShowEventController()
controller.event = record.event
controller.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(controller, animated: true)
self.showOnMap(record)
}
sheet.addAction(editNumber)
@ -332,4 +353,34 @@ class RecordsController: UIViewController, UITableViewDelegate {
}
self.present(alert, animated: true)
}
func delete(record: AudioRecord) {
do {
if let realm = record.realm {
try realm.write {
realm.delete(record)
}
}
} catch {
print(error)
}
}
func share(record: AudioRecord) {
do {
let url = try FileManager.default.url(for: record.path, in: "recordings")
let controller = UIActivityViewController(activityItems: [url], applicationActivities: nil)
self.present(controller, animated: true)
} catch {
print("Error sharing audio record: \(error.localizedDescription)")
HUD.show(error: error)
}
}
func showOnMap(_ record: AudioRecord) {
let controller = ShowEventController()
controller.event = record.event
controller.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(controller, animated: true)
}
}

View File

@ -46,7 +46,7 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
}
form +++ Section()
<<< LabelRow(NSLocalizedString("Model", comment: "")).cellUpdate { cell, _ in cell.imageView?.kf.setImage(with: URL(string: self.vehicle?.brand?.logo ?? ""), placeholder: self.logoPlaceholder) }
<<< LabelRow("Model").cellUpdate { cell, _ in cell.imageView?.kf.setImage(with: URL(string: self.vehicle?.brand?.logo ?? ""), placeholder: self.logoPlaceholder) }
form +++ Section(NSLocalizedString("General", comment: ""))
<<< LabelRow("Year") { $0.title = NSLocalizedString("Year", comment: "") }

View File

@ -0,0 +1,7 @@
/*
Localizable.strings
AutoCat
Created by Selim Mustafaev on 01.12.2020.
Copyright © 2020 Selim Mustafaev. All rights reserved.
*/

View File

@ -0,0 +1,72 @@
<?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>events found</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>one</key>
<string>%u event found</string>
<key>two</key>
<string>%u events found</string>
<key>few</key>
<string>%u events found</string>
<key>many</key>
<string>%u events found</string>
<key>other</key>
<string>%u events found</string>
</dict>
</dict>
<key>owners count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>one</key>
<string>%u owner</string>
<key>two</key>
<string>%u owners</string>
<key>few</key>
<string>%u owners</string>
<key>many</key>
<string>%u owners</string>
<key>other</key>
<string>%u owners</string>
</dict>
</dict>
<key>vehicles found</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>one</key>
<string>%u vehicle found</string>
<key>two</key>
<string>%u vehicles found</string>
<key>few</key>
<string>%u vehicles found</string>
<key>many</key>
<string>%u vehicles found</string>
<key>other</key>
<string>%u vehicles found</string>
</dict>
</dict>
</dict>
</plist>

View File

@ -7,6 +7,9 @@
/* No comment provided by engineer. */
"Add new audio record" = "Добавить новую голосовую запись";
/* No comment provided by engineer. */
"Add new event" = "Добавить новое событие";
/* No comment provided by engineer. */
"Add new plate number via audio recording" = "Добавить новый гос. номер с помощью голосовой записи";
@ -23,13 +26,13 @@
"Anyone but me" = "Кем угодно кроме меня";
/* No comment provided by engineer. */
"As link" = "Как ссылку";
"As link" = "В виде ссылки";
/* No comment provided by engineer. */
"As one image" = "Как одну картинку";
"As one image" = "В виде одной картинки";
/* No comment provided by engineer. */
"As text and photos" = "Как текст и фотографии";
"As text and photos" = "В виде текста и фотографий";
/* No comment provided by engineer. */
"AutoCat Account" = "Аккаунт в АвтоКот";
@ -52,9 +55,18 @@
/* No comment provided by engineer. */
"Category" = "Категория";
/* No comment provided by engineer. */
/* verb */
"Check" = "Проверить";
/* No comment provided by engineer. */
"Check by" = "Проверить по";
/* No comment provided by engineer. */
"Check date" = "Дата проверки";
/* No comment provided by engineer. */
"Check parameters" = "Параметры проверки";
/* No comment provided by engineer. */
"Clear all filters" = "Очистить все фильтры";
@ -70,6 +82,9 @@
/* No comment provided by engineer. */
"Copy to pasteboard" = "Копировать в буфер обмена";
/* No comment provided by engineer. */
"Date and time" = "Дата и время";
/* No comment provided by engineer. */
"Default region" = "Регион по умолчанию";
@ -82,6 +97,12 @@
/* No comment provided by engineer. */
"Driver region" = "Регион прописки владельца ТС";
/* No comment provided by engineer. */
"Edit" = "Редактировать";
/* No comment provided by engineer. */
"Edit event" = "Редактировать событие";
/* No comment provided by engineer. */
"Edit plate number" = "Редактировать гос. номер";
@ -130,6 +151,9 @@
/* Owner type */
"legal" = "Юр. лицо";
/* No comment provided by engineer. */
"Location" = "Координаты";
/* No comment provided by engineer. */
"Log In" = "Войти";
@ -160,9 +184,15 @@
/* No comment provided by engineer. */
"OSAGO" = "ОСАГО";
/* No comment provided by engineer. */
"OSAGO check" = "Проверка ОСАГО";
/* No comment provided by engineer. */
"OSAGO contract status" = "Статус договора ОСАГО";
/* No comment provided by engineer. */
"OSAGO contracts" = "Полисы ОСАГО";
/* No comment provided by engineer. */
"Owner" = "Владелец";
@ -175,6 +205,9 @@
/* No comment provided by engineer. */
"Photos" = "Фотографии";
/* Check by */
"plate number" = "гос. номеру";
/* No comment provided by engineer. */
"Plate number" = "Гос. номер";
@ -241,6 +274,9 @@
/* No comment provided by engineer. */
"STS" = "СТС";
/* No comment provided by engineer. */
"Time range" = "Временной промежуток";
/* No comment provided by engineer. */
"To" = "По";

View File

@ -0,0 +1,66 @@
<?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>events found</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>few</key>
<string>Найдено %u события</string>
<key>many</key>
<string>Найдено %u событий</string>
<key>one</key>
<string>Найдено %u событие</string>
<key>other</key>
<string>Найдено %u событий</string>
</dict>
</dict>
<key>owners count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>few</key>
<string>%u владельца</string>
<key>many</key>
<string>%u владельцев</string>
<key>one</key>
<string>%u владелец</string>
<key>other</key>
<string>%u владельцев</string>
</dict>
</dict>
<key>vehicles found</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@VARIABLE@</string>
<key>VARIABLE</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>u</string>
<key>few</key>
<string>Найдены %u ТС</string>
<key>many</key>
<string>Найдено %u ТС</string>
<key>one</key>
<string>Найдено %u ТС</string>
<key>other</key>
<string>Найдено %u ТС</string>
</dict>
</dict>
</dict>
</plist>