More localization

This commit is contained in:
Selim Mustafaev 2020-12-07 00:27:00 +03:00
parent 577dbca22e
commit ada84bbe31
14 changed files with 461 additions and 128 deletions

View File

@ -15,6 +15,7 @@
7A0420BA25693D2C00034941 /* dkbm.js in Resources */ = {isa = PBXBuildFile; fileRef = 7A0420B925693D2C00034941 /* dkbm.js */; };
7A051611241412CA00FC55AC /* SwiftDate in Frameworks */ = {isa = PBXBuildFile; productRef = 7A051610241412CA00FC55AC /* SwiftDate */; };
7A05161A2414FF0900FC55AC /* DateSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0516192414FF0900FC55AC /* DateSection.swift */; };
7A0B96A0257D6D4B000B39AD /* MultilineLabelRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0B969F257D6D4B000B39AD /* MultilineLabelRow.swift */; };
7A1090E824A394F100B4F0B2 /* AudioRecordCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1090E724A394F100B4F0B2 /* AudioRecordCell.swift */; };
7A1090EA24A3A26300B4F0B2 /* AudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1090E924A3A26300B4F0B2 /* AudioPlayer.swift */; };
7A1090EC24A4E3E100B4F0B2 /* CellProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1090EB24A4E3E100B4F0B2 /* CellProgressView.swift */; };
@ -55,6 +56,7 @@
7A530B8B240181F500CBFE6E /* RxRealm in Frameworks */ = {isa = PBXBuildFile; productRef = 7A530B8A240181F500CBFE6E /* RxRealm */; };
7A61FF8B2575A2CD00D905D5 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7A61FF892575A2CD00D905D5 /* Localizable.strings */; };
7A61FF912575A5B300D905D5 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7A61FF8F2575A5B300D905D5 /* InfoPlist.strings */; };
7A61FFA0257D3CFC00D905D5 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 7A61FFA2257D3CFC00D905D5 /* Localizable.stringsdict */; };
7A64AE732469DFB600ABE48E /* DismissAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE6F2469DFB600ABE48E /* DismissAnimationController.swift */; };
7A64AE742469DFB600ABE48E /* MediaContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE702469DFB600ABE48E /* MediaContentView.swift */; };
7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE712469DFB600ABE48E /* MediaBrowserViewController.swift */; };
@ -112,6 +114,7 @@
7A0420B52568650C00034941 /* DkbmController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DkbmController.swift; sourceTree = "<group>"; };
7A0420B925693D2C00034941 /* dkbm.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = dkbm.js; sourceTree = "<group>"; };
7A0516192414FF0900FC55AC /* DateSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateSection.swift; sourceTree = "<group>"; };
7A0B969F257D6D4B000B39AD /* MultilineLabelRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineLabelRow.swift; sourceTree = "<group>"; };
7A1090E724A394F100B4F0B2 /* AudioRecordCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecordCell.swift; sourceTree = "<group>"; };
7A1090E924A3A26300B4F0B2 /* AudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayer.swift; sourceTree = "<group>"; };
7A1090EB24A4E3E100B4F0B2 /* CellProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellProgressView.swift; sourceTree = "<group>"; };
@ -152,6 +155,8 @@
7A61FF902575A5B300D905D5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
7A61FF932575A5B600D905D5 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = "<group>"; };
7A61FF962576C16400D905D5 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Main.strings; sourceTree = "<group>"; };
7A61FFA1257D3CFC00D905D5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
7A61FFA4257D3D0200D905D5 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
7A64AE6B2469DC6900ABE48E /* AutoCat.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AutoCat.entitlements; sourceTree = "<group>"; };
7A64AE6F2469DFB600ABE48E /* DismissAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DismissAnimationController.swift; sourceTree = "<group>"; };
7A64AE702469DFB600ABE48E /* MediaContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaContentView.swift; sourceTree = "<group>"; };
@ -242,6 +247,14 @@
path = JS;
sourceTree = "<group>";
};
7A0B969D257D6CB3000B39AD /* eureka */ = {
isa = PBXGroup;
children = (
7A0B969F257D6D4B000B39AD /* MultilineLabelRow.swift */,
);
path = eureka;
sourceTree = "<group>";
};
7A1146F423FDE7E500B424AF = {
isa = PBXGroup;
children = (
@ -279,6 +292,7 @@
7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */,
7A11470E23FDE7E600B424AF /* Info.plist */,
7A61FF892575A2CD00D905D5 /* Localizable.strings */,
7A61FFA2257D3CFC00D905D5 /* Localizable.stringsdict */,
7A61FF8F2575A5B300D905D5 /* InfoPlist.strings */,
);
path = AutoCat;
@ -404,6 +418,7 @@
7A6DD901242BF48D009DE740 /* Views */ = {
isa = PBXGroup;
children = (
7A0B969D257D6CB3000B39AD /* eureka */,
7A6DD902242BF4A5009DE740 /* PlateView.swift */,
7A6DD90B24335A6D009DE740 /* FlagLayer.swift */,
7AB67E8B2435C38700258F61 /* CustomTextField.swift */,
@ -524,6 +539,7 @@
files = (
7A0420BA25693D2C00034941 /* dkbm.js in Resources */,
7A61FF912575A5B300D905D5 /* InfoPlist.strings in Resources */,
7A61FFA0257D3CFC00D905D5 /* Localizable.stringsdict in Resources */,
7ADF6C99250F872C00F237B2 /* RoadNumbers.otf in Resources */,
7A11470D23FDE7E600B424AF /* LaunchScreen.storyboard in Resources */,
7A61FF8B2575A2CD00D905D5 /* Localizable.strings in Resources */,
@ -553,6 +569,7 @@
7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */,
7AABDE26253350C30041AFC6 /* RxSectionedDataSource.swift in Sources */,
7AB562BA249C9E9B00473D53 /* Region.swift in Sources */,
7A0B96A0257D6D4B000B39AD /* MultilineLabelRow.swift in Sources */,
7A659B5924A2B1BA0043A0F2 /* AudioRecord.swift in Sources */,
7A6DD90C24335A6D009DE740 /* FlagLayer.swift in Sources */,
7AE26A3524F31B0700625033 /* EventsController.swift in Sources */,
@ -654,6 +671,15 @@
name = InfoPlist.strings;
sourceTree = "<group>";
};
7A61FFA2257D3CFC00D905D5 /* Localizable.stringsdict */ = {
isa = PBXVariantGroup;
children = (
7A61FFA1257D3CFC00D905D5 /* en */,
7A61FFA4257D3D0200D905D5 /* ru */,
);
name = Localizable.stringsdict;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
@ -779,7 +805,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 57;
CURRENT_PROJECT_VERSION = 58;
DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
@ -802,7 +828,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 57;
CURRENT_PROJECT_VERSION = 58;
DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;

View File

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

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>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>other</key>
<string>%u owners</string>
</dict>
</dict>
</dict>
</plist>

View File

@ -9,9 +9,9 @@ enum AddedBy: String, CustomStringConvertible, CaseIterable {
var description: String {
switch self {
case .anyone: return "Anyone"
case .me: return "Me"
case .anyoneButMe: return "Anyone but me"
case .anyone: return NSLocalizedString("Anyone", comment: "Added by")
case .me: return NSLocalizedString("Me", comment: "Added by")
case .anyoneButMe: return NSLocalizedString("Anyone but me", comment: "Added by")
}
}
}
@ -28,11 +28,11 @@ class FiltersController: FormViewController {
override func viewDidLoad() {
super.viewDidLoad()
form +++ Section("Main filters") { $0.tag = "MainFilters" }
form +++ Section(NSLocalizedString("Main filters", comment: "")) { $0.tag = "MainFilters" }
<<< PushRow<String>("Brand") { row in
row.title = "Brand"
row.title = NSLocalizedString("Brand", comment: "")
row.value = self.filter.brand ?? "Any"
row.selectorTitle = "Brands"
row.selectorTitle = NSLocalizedString("Brands", comment: "")
row.optionsProvider = .lazy({ form, completion in
Api.getBrands().observeOn(MainScheduler.instance).subscribe(onSuccess: { brands in
completion(["Any"] + brands)
@ -45,7 +45,7 @@ class FiltersController: FormViewController {
.cellUpdate { $1.value = self.filter.brand ?? "Any" }
<<< PushRow<String>("Model") { row in
row.title = "Model"
row.title = NSLocalizedString("Model", comment: "")
row.value = self.filter.model ?? "Any"
row.disabled = "$Brand == 'Any'"
row.optionsProvider = .lazy({ form, completion in
@ -64,7 +64,7 @@ class FiltersController: FormViewController {
.cellUpdate { $1.value = self.filter.model ?? "Any" }
<<< PushRow<String>("Color") { row in
row.title = "Color"
row.title = NSLocalizedString("Color", comment: "")
row.value = self.filter.color ?? "Any"
row.optionsProvider = .lazy({ form, completion in
Api.getColors().observeOn(MainScheduler.instance).subscribe(onSuccess: { colors in
@ -79,7 +79,7 @@ class FiltersController: FormViewController {
form +++ Section() { $0.tag = "Regions" }
<<< LabelRow("RegionsRow") { row in
row.title = "Regions"
row.title = NSLocalizedString("Regions", comment: "")
row.value = self.filter.regions?.map(String.init).joined(separator: ",") ?? "Any"
row.cellUpdate { cell, _ in
cell.accessoryType = .disclosureIndicator
@ -99,8 +99,8 @@ class FiltersController: FormViewController {
form +++ Section() { $0.tag = "AddedByMe" }
<<< ActionSheetRow<String>("AddedByMeRow") { row in
row.title = "Added by"
row.selectorTitle = "Added by"
row.title = NSLocalizedString("Added by", comment: "")
row.selectorTitle = NSLocalizedString("Added by", comment: "")
row.options = AddedBy.allCases.map { $0.description }
row.value = self.filter.addedBy?.description ?? AddedBy.anyone.description
}
@ -117,22 +117,22 @@ class FiltersController: FormViewController {
form +++ Section("Time range")
<<< DateInlineRow("FromDate") { row in
row.title = "From"
row.noValueDisplayText = "Beginning"
row.title = NSLocalizedString("From", comment: "")
row.noValueDisplayText = NSLocalizedString("Beginning", comment: "")
row.value = self.filter.fromDate
}
.onChange { self.filter.fromDate = $0.value }
.cellUpdate(self.update(cell:row:))
<<< DateInlineRow("ToDate") { row in
row.title = "To"
row.noValueDisplayText = "Now"
row.title = NSLocalizedString("To", comment: "")
row.noValueDisplayText = NSLocalizedString("Now", comment: "")
row.value = self.filter.toDate
}
.onChange { self.filter.toDate = $0.value }
.cellUpdate(self.update(cell:row:))
form +++ Section()
<<< ButtonRow("ClearAll") { $0.title = "Clear all filters" }.onCellSelection { cell, row in
<<< ButtonRow("ClearAll") { $0.title = NSLocalizedString("Clear all filters", comment: "") }.onCellSelection { cell, row in
self.filter.clear()
for section in self.form.allSections {
// For some reason certain cells do not redraw after first reload

View File

@ -47,19 +47,19 @@ class OsagoController: FormViewController {
self.form.removeAll()
for osago in vehicle.osagoContracts.sorted(by: { $0.date < $1.date }) {
self.form +++ Section(formatter.string(from: Date(timeIntervalSince1970: osago.date)))
<<< self.row("Contract #", value: osago.number)
<<< self.row("Name", value: osago.name)
<<< self.row("Status", value: osago.status)
<<< self.row("Insurant", value: osago.insurant)
<<< self.row("Owner", value: osago.owner)
<<< self.row("Region", value: osago.usageRegion)
<<< self.row("Restrictions", value: osago.restrictions, height: 100)
<<< self.row("Plate number", value: osago.plateNumber)
<<< self.row("VIN", value: osago.vin)
<<< self.multilineRow(NSLocalizedString("Contract series and number", comment: ""), value: osago.number)
<<< self.multilineRow(NSLocalizedString("Insurance organization name", comment: ""), value: osago.name)
<<< self.multilineRow(NSLocalizedString("OSAGO contract status", comment: ""), value: osago.status)
<<< self.multilineRow(NSLocalizedString("Insurant", comment: ""), value: osago.insurant)
<<< self.multilineRow(NSLocalizedString("Owner", comment: ""), value: osago.owner)
<<< self.multilineRow(NSLocalizedString("Vehicle usage region", comment: ""), value: osago.usageRegion)
<<< self.multilineRow(NSLocalizedString("Contract restrictions", comment: ""), value: osago.restrictions)
<<< self.row(NSLocalizedString("Plate number", comment: ""), value: osago.plateNumber)
<<< self.row(NSLocalizedString("VIN", comment: ""), value: osago.vin)
}
}
func row(_ title: String, value: String?, height: CGFloat = 44) -> LabelRow {
func row(_ title: String, value: String?) -> LabelRow {
LabelRow() { row in
if let cell = row.cell, let label = cell.detailTextLabel, let titleLabel = cell.textLabel {
titleLabel.translatesAutoresizingMaskIntoConstraints = false
@ -75,7 +75,13 @@ class OsagoController: FormViewController {
label.font = UIFont.preferredFont(forTextStyle: .subheadline)
}
//row.cell.height = { height }
row.title = title
row.value = value
}
}
func multilineRow(_ title: String, value: String?) -> MultilineLabelRow {
MultilineLabelRow() { row in
row.title = title
row.value = value
}

View File

@ -10,37 +10,33 @@ class OwnersController: FormViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = UITableView.automaticDimension
self.formatter.dateStyle = .long
self.formatter.timeStyle = .none
self.title = "\(self.owners.count) owner(s)"
self.title = String.localizedStringWithFormat(NSLocalizedString("owners count", comment: ""), self.owners.count)
for (index, owner) in self.owners.enumerated() {
let section = Section(header: "", footer: owner.lastOperation)
let fromDate = Date(timeIntervalSince1970: TimeInterval(owner.from/1000))
let from = self.formatter.string(from: fromDate)
var to = NSLocalizedString("now", comment: "")
if owner.to > 0 {
let toDate = Date(timeIntervalSince1970: TimeInterval(owner.to/1000))
to = self.formatter.string(from: toDate)
}
let section = Section(header: from + " - " + to, footer: owner.lastOperation)
form +++ section
<<< LabelRow("Owner\(index)") { row in
row.title = "Owner type"
row.value = owner.ownerType
}
<<< LabelRow("From\(index)") { row in
row.title = "From"
let date = Date(timeIntervalSince1970: TimeInterval(owner.from/1000))
row.value = self.formatter.string(from: date)
}
<<< LabelRow("To\(index)") { row in
row.title = "To"
if owner.to == 0 {
row.value = "now"
} else {
let date = Date(timeIntervalSince1970: TimeInterval(owner.to/1000))
row.value = self.formatter.string(from: date)
}
row.title = NSLocalizedString("Owner type", comment: "")
row.value = NSLocalizedString(owner.ownerType, comment: "")
}
if let vehicleRegistrationRegion = owner.region {
section <<< LabelRow("VehicleRegion\(index)") { row in
row.cell.detailTextLabel?.numberOfLines = 0
row.title = "Vehicle region"
section <<< MultilineLabelRow("VehicleRegion\(index)") { row in
row.title = NSLocalizedString("Vehicle region", comment: "")
row.value = vehicleRegistrationRegion
}
}
@ -51,16 +47,15 @@ class OwnersController: FormViewController {
if let driverRegion = owner.registrationRegion {
dRegion += " (\(driverRegion))"
}
section <<< LabelRow("DriverRegion\(index)") { row in
row.cell.detailTextLabel?.numberOfLines = 0
row.title = "Driver region"
section <<< MultilineLabelRow("DriverRegion\(index)") { row in
row.title = NSLocalizedString("Driver region", comment: "")
row.value = dRegion
}
}
if let code = owner.code {
section <<< LabelRow("Code\(index)") { row in
row.title = "ZIP (or OKTMO) code"
section <<< MultilineLabelRow("Code\(index)") { row in
row.title = NSLocalizedString("ZIP (or OKTMO) code", comment: "")
row.value = code
}
}

View File

@ -65,12 +65,12 @@ class RecordsController: UIViewController, UITableViewDelegate {
activity.persistentIdentifier = activityId
activity.isEligibleForSearch = true
activity.isEligibleForPrediction = true
activity.title = "Add new audio record"
activity.title = NSLocalizedString("Add new audio record", comment: "")
activity.suggestedInvocationPhrase = "Запиши номер"
let attributes = CSSearchableItemAttributeSet()
attributes.contentType = kUTTypeItem as String
attributes.contentDescription = "Add new plate number via audio recording"
attributes.contentDescription = NSLocalizedString("Add new plate number via audio recording", comment: "")
activity.contentAttributeSet = attributes
self.userActivity = activity
@ -153,9 +153,9 @@ class RecordsController: UIViewController, UITableViewDelegate {
}
func showRecordingAlert() -> UIAlertController {
let alert = UIAlertController(title: "Recording...", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in self.recordDisposable?.dispose() }))
alert.addAction(UIAlertAction(title: "Done", style: .default, handler: { _ in self.recorder?.stopRecording() }))
let alert = UIAlertController(title: NSLocalizedString("Recording...", comment: ""), message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: { _ in self.recordDisposable?.dispose() }))
alert.addAction(UIAlertAction(title: NSLocalizedString("Done", comment: ""), style: .default, handler: { _ in self.recorder?.stopRecording() }))
self.present(alert, animated: true)
return alert
}
@ -230,7 +230,7 @@ class RecordsController: UIViewController, UITableViewDelegate {
let record = self.recordsDataSource.item(at: indexPath)
let check = UIContextualAction(style: .normal, title: "Check") { action, view, completion in
let check = UIContextualAction(style: .normal, title: NSLocalizedString("Check", comment: "")) { action, view, completion in
if let number = record.number {
self.check(number: number, event: record.event)
}
@ -239,14 +239,14 @@ class RecordsController: UIViewController, UITableViewDelegate {
check.backgroundColor = .systemGray2
check.image = UIImage(systemName: "eye")
let action = UIContextualAction(style: .normal, title: "Action") { action, view, completion in
let action = UIContextualAction(style: .normal, title: NSLocalizedString("Action", comment: "")) { action, view, completion in
self.moreActions(for: record, cell: cell)
completion(true)
}
action.backgroundColor = .systemGray2
action.image = UIImage(systemName: "ellipsis" /*"square.and.arrow.up"*/)
let delete = UIContextualAction(style: .destructive, title: "Delete") { action, view, completion in
let delete = UIContextualAction(style: .destructive, title: NSLocalizedString("Delete", comment: "")) { action, view, completion in
do {
if let realm = record.realm {
try realm.write {
@ -267,9 +267,9 @@ class RecordsController: UIViewController, UITableViewDelegate {
}
func moreActions(for record: AudioRecord, cell: UITableViewCell) {
let sheet = UIAlertController(title: "More actions", message: nil, preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: "Cancel", style: .cancel) { _ in sheet.dismiss(animated: true, completion: nil) }
let share = UIAlertAction(title: "Share", style: .default) { _ in
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)
@ -279,13 +279,13 @@ class RecordsController: UIViewController, UITableViewDelegate {
HUD.show(error: error)
}
}
let showText = UIAlertAction(title: "Show recognized text", style: .default) { action in
self.showAlert(title: "Recognized text", message: record.rawText)
let showText = UIAlertAction(title: NSLocalizedString("Show recognized text", comment: ""), style: .default) { action in
self.showAlert(title: NSLocalizedString("Recognized text", comment: ""), message: record.rawText)
}
let editNumber = UIAlertAction(title: "Edit plate number", style: .default) { action in
let editNumber = UIAlertAction(title: NSLocalizedString("Edit plate number", comment: ""), style: .default) { action in
self.edit(record: record)
}
let showOnMap = UIAlertAction(title: "Show on map", style: .default) { action in
let showOnMap = UIAlertAction(title: NSLocalizedString("Show on map", comment: ""), style: .default) { action in
let controller = ShowEventController()
controller.event = record.event
controller.hidesBottomBarWhenPushed = true
@ -311,8 +311,8 @@ class RecordsController: UIViewController, UITableViewDelegate {
}
func edit(record: AudioRecord) {
let alert = UIAlertController(title: "Edit plate number", message: nil, preferredStyle: .alert)
let done = UIAlertAction(title: "Done", style: .default) { action in
let alert = UIAlertController(title: NSLocalizedString("Edit plate number", comment: ""), message: nil, preferredStyle: .alert)
let done = UIAlertAction(title: NSLocalizedString("Done", comment: ""), style: .default) { action in
guard let tf = alert.textFields?.first else { return }
if let realm = try? Realm() {
try? realm.write {
@ -321,7 +321,7 @@ class RecordsController: UIViewController, UITableViewDelegate {
}
}
alert.addAction(done)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { action in
alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: { action in
alert.dismiss(animated: true)
}))
alert.addTextField { tf in

View File

@ -26,7 +26,7 @@ class RegionsController: UIViewController, UISearchResultsUpdating, UITableViewD
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search regions"
searchController.searchBar.placeholder = NSLocalizedString("Search regions", comment: "Search field placeholder")
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
definesPresentationContext = true

View File

@ -46,30 +46,30 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
}
form +++ Section()
<<< LabelRow("Model").cellUpdate { cell, _ in cell.imageView?.kf.setImage(with: URL(string: self.vehicle?.brand?.logo ?? ""), placeholder: self.logoPlaceholder) }
<<< LabelRow(NSLocalizedString("Model", comment: "")).cellUpdate { cell, _ in cell.imageView?.kf.setImage(with: URL(string: self.vehicle?.brand?.logo ?? ""), placeholder: self.logoPlaceholder) }
form +++ Section("General")
<<< LabelRow("Year") { $0.title = "Year" }
<<< LabelRow("Color") { $0.title = "Color" }
<<< LabelRow("Category") { $0.title = "Category" }
<<< LabelRow("STP") { $0.title = "Steering wheel position" }
<<< LabelRow("Japanese") { $0.title = "Japanese" }
form +++ Section(NSLocalizedString("General", comment: ""))
<<< LabelRow("Year") { $0.title = NSLocalizedString("Year", comment: "") }
<<< LabelRow("Color") { $0.title = NSLocalizedString("Color", comment: "") }
<<< LabelRow("Category") { $0.title = NSLocalizedString("Category", comment: "") }
<<< LabelRow("STP") { $0.title = NSLocalizedString("Steering wheel position", comment: "") }
<<< LabelRow("Japanese") { $0.title = NSLocalizedString("Japanese", comment: "") }
form +++ Section("Identifiers")
<<< LabelRow("PlateNumber") { $0.title = "Number" }
<<< LabelRow("VIN") { $0.title = "VIN" }
<<< LabelRow("STS") { $0.title = "STS" }
<<< LabelRow("PTS") { $0.title = "PTS" }
form +++ Section(NSLocalizedString("Identifiers", comment: ""))
<<< LabelRow("PlateNumber") { $0.title = NSLocalizedString("Plate number", comment: "") }
<<< LabelRow("VIN") { $0.title = NSLocalizedString("VIN", comment: "") }
<<< LabelRow("STS") { $0.title = NSLocalizedString("STS", comment: "") }
<<< LabelRow("PTS") { $0.title = NSLocalizedString("PTS", comment: "") }
form +++ Section("Engine")
<<< LabelRow("EngineNumber") { $0.title = "Number" }
<<< LabelRow("FuelType") { $0.title = "Fuel type" }
<<< LabelRow("Volume") { $0.title = "Volume (cm³)" }
<<< LabelRow("PowerHP") { $0.title = "Power (HP)" }
<<< LabelRow("PowerKw") { $0.title = "Power (kw)" }
form +++ Section(NSLocalizedString("Engine", comment: ""))
<<< LabelRow("EngineNumber") { $0.title = NSLocalizedString("Number", comment: "") }
<<< LabelRow("FuelType") { $0.title = NSLocalizedString("Fuel type", comment: "") }
<<< LabelRow("Volume") { $0.title = NSLocalizedString("Volume (cm³)", comment: "") }
<<< LabelRow("PowerHP") { $0.title = NSLocalizedString("Power (HP)", comment: "") }
<<< LabelRow("PowerKw") { $0.title = NSLocalizedString("Power (kw)", comment: "") }
form +++ Section("History")
<<< LabelRow("Events") { $0.title = "Events" }
form +++ Section(NSLocalizedString("History", comment: ""))
<<< LabelRow("Events") { $0.title = NSLocalizedString("Events", comment: "") }
.cellUpdate { cell, _ in cell.accessoryType = .disclosureIndicator }
.onCellSelection { _, _ in
let sb = UIStoryboard(name: "Main", bundle: nil)
@ -78,7 +78,7 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
self.navigationController?.pushViewController(controller, animated: true)
}
<<< LabelRow("OSAGO") { $0.title = "OSAGO" }
<<< LabelRow("OSAGO") { $0.title = NSLocalizedString("OSAGO", comment: "") }
.cellUpdate { cell, _ in cell.accessoryType = .disclosureIndicator }
.onCellSelection { _, _ in
let sb = UIStoryboard(name: "Main", bundle: nil)
@ -88,7 +88,7 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
}
<<< LabelRow("Owners") { row in
row.title = "Owners"
row.title = NSLocalizedString("Owners", comment: "")
row.disabled = "$Owners == '0'"
}
.cellUpdate { cell, _ in cell.accessoryType = .disclosureIndicator }
@ -102,7 +102,7 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
}
<<< LabelRow("Photos") { row in
row.title = "Photos"
row.title = NSLocalizedString("Photos", comment: "")
row.disabled = "$Photos == '0'"
}
.cellUpdate { cell, _ in cell.accessoryType = .disclosureIndicator }
@ -125,8 +125,8 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
self.row("Year")?.value = String(self.vehicle?.year ?? 0)
self.row("Color")?.value = self.vehicle?.color ?? "<unknown>"
self.row("Category")?.value = self.vehicle?.category ?? "<unknown>"
self.row("STP")?.value = self.stringFromBool(self.vehicle?.isRightWheel.value, yes: "Right", no: "Left")
self.row("Japanese")?.value = self.stringFromBool(self.vehicle?.isJapanese.value, yes: "Yes", no: "No")
self.row("STP")?.value = self.stringFromBool(self.vehicle?.isRightWheel.value, yes: NSLocalizedString("Right", comment: ""), no: NSLocalizedString("Left", comment: ""))
self.row("Japanese")?.value = self.stringFromBool(self.vehicle?.isJapanese.value, yes: NSLocalizedString("Yes", comment: ""), no: NSLocalizedString("No", comment: ""))
var num = self.vehicle?.getNumber() ?? "<unknown>"
if self.vehicle?.outdated ?? false, let current = self.vehicle?.currentNumber {
@ -204,11 +204,11 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
@IBAction func onShare(_ sender: UIBarButtonItem) {
guard let vehicle = self.vehicle else { return }
let sheet = UIAlertController(title: "Share report", message: nil, preferredStyle: .actionSheet)
let sheet = UIAlertController(title: NSLocalizedString("Share report", comment: ""), message: nil, preferredStyle: .actionSheet)
sheet.popoverPresentationController?.barButtonItem = self.actionBarItem
let cancel = UIAlertAction(title: "Cancel", style: .cancel) { _ in sheet.dismiss(animated: true, completion: nil) }
let shareImage = UIAlertAction(title: "As one image", style: .default) { _ in
let cancel = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel) { _ in sheet.dismiss(animated: true, completion: nil) }
let shareImage = UIAlertAction(title: NSLocalizedString("As one image", comment: ""), style: .default) { _ in
let image = vehicle.reportImage(width: self.tableView.contentSize.width)
do {
@ -228,7 +228,7 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
}
}
let shareTextAndImage = UIAlertAction(title: "As text and photos", style: .default) { _ in
let shareTextAndImage = UIAlertAction(title: NSLocalizedString("As text and photos", comment: ""), style: .default) { _ in
guard let vehicle = self.vehicle else { return }
var items: [Any] = [vehicle.reportText()]
for photo in vehicle.photos {
@ -245,7 +245,7 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
self.present(controller, animated: true)
}
let shareLink = UIAlertAction(title: "As link", style: .default) { _ in
let shareLink = UIAlertAction(title: NSLocalizedString("As link", comment: ""), style: .default) { _ in
guard let vehicle = self.vehicle else { return }
if let jwt = try? JWT<EmptyPayload>.generate(for: vehicle.getNumber()), let url = URL(string: Constants.reportLinkBaseURL + "?token=" + jwt) {
@ -285,11 +285,11 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
// MARK: - Copy
@IBAction func onCopy(_ sender: UIBarButtonItem) {
let sheet = UIAlertController(title: "Copy to pasteboard", message: nil, preferredStyle: .actionSheet)
let sheet = UIAlertController(title: NSLocalizedString("Copy to pasteboard", comment: ""), message: nil, preferredStyle: .actionSheet)
sheet.popoverPresentationController?.barButtonItem = self.copyBarItem
let cancel = UIAlertAction(title: "Cancel", style: .cancel) { _ in sheet.dismiss(animated: true, completion: nil) }
let copyPlateNumber = UIAlertAction(title: "Plate number", style: .default) { _ in UIPasteboard.general.string = self.vehicle?.getNumber() }
let copyVin = UIAlertAction(title: "VIN", style: .default) { _ in UIPasteboard.general.string = self.vehicle?.vin1 }
let cancel = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel) { _ in sheet.dismiss(animated: true, completion: nil) }
let copyPlateNumber = UIAlertAction(title: NSLocalizedString("Plate number", comment: ""), style: .default) { _ in UIPasteboard.general.string = self.vehicle?.getNumber() }
let copyVin = UIAlertAction(title: NSLocalizedString("VIN", comment: ""), style: .default) { _ in UIPasteboard.general.string = self.vehicle?.vin1 }
sheet.addAction(copyPlateNumber)
sheet.addAction(copyVin)
sheet.addAction(cancel)

View File

@ -24,7 +24,7 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search plate numbers"
searchController.searchBar.placeholder = NSLocalizedString("Search plate numbers", comment: "")
navigationItem.searchController = searchController
definesPresentationContext = true
@ -42,7 +42,7 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
.flatMap { Api.getVehicles(with: $0).catchErrorJustReturn([]) }
.observeOn(MainScheduler.instance)
.do(onNext: {
self.navigationItem.title = "\($0.count) vehicles found"
self.navigationItem.title = String.localizedStringWithFormat(NSLocalizedString("vehicles found", comment: ""), $0.count)
self.showMapButton.isEnabled = $0.count > 0
self.refreshControl.endRefreshing()
})
@ -117,7 +117,7 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let vehicle = self.datasource.item(at: indexPath)
let updateAction = UIContextualAction(style: .normal, title: "Update") { action, view, completion in
let updateAction = UIContextualAction(style: .normal, title: NSLocalizedString("Update", comment: "")) { action, view, completion in
self.update(vehicle: vehicle, at: indexPath)
completion(true)
}
@ -133,11 +133,11 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
let vehicle = self.datasource.item(at: indexPath)
return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ in
let update = UIAction(title: "Update", image: UIImage(systemName: "arrow.2.circlepath")) { action in
let update = UIAction(title: NSLocalizedString("Update", comment: ""), image: UIImage(systemName: "arrow.2.circlepath")) { action in
self.update(vehicle: vehicle, at: indexPath)
}
return UIMenu(title: "Actions", children: [update])
return UIMenu(title: NSLocalizedString("Actions", comment: ""), children: [update])
}
}

View File

@ -58,9 +58,16 @@ class VehiclePhoto: Object, Decodable {
}
}
enum OwnerType: String {
enum OwnerType: String, CustomStringConvertible {
case legal
case individual
var description: String {
switch self {
case .legal: return NSLocalizedString("legal", comment: "Owner type")
case .individual: return NSLocalizedString("individual", comment: "Owner type")
}
}
}
enum SteeringWheelPosition: CustomStringConvertible {

View File

@ -3,9 +3,9 @@ import Foundation
enum Constants {
static var baseUrl: String {
#if DEBUG
return "http://127.0.0.1:3000/"
//return "http://127.0.0.1:3000/"
//return "http://192.168.1.67:3000/"
//return "https://vps.aliencat.pro:8443/"
return "https://vps.aliencat.pro:8443/"
#else
return "https://vps.aliencat.pro:8443/"
#endif

View File

@ -0,0 +1,55 @@
import UIKit
import Eureka
final class MultilineLabelCell: Cell<String>, CellType {
private var title: UILabel!
private var value: UILabel!
required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func setup() {
super.setup()
self.title = UILabel()
self.contentView.addSubview(self.title)
self.title.translatesAutoresizingMaskIntoConstraints = false
self.title.font = UIFont.preferredFont(forTextStyle: .caption1)
self.title.leadingAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.leadingAnchor).isActive = true
self.title.trailingAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.trailingAnchor).isActive = true
self.title.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 8).isActive = true
self.value = UILabel()
self.contentView.addSubview(self.value)
self.value.translatesAutoresizingMaskIntoConstraints = false
self.value.textColor = .secondaryLabel
self.value.numberOfLines = 0
self.value.textAlignment = .right
self.value.leadingAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.leadingAnchor).isActive = true
self.value.trailingAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.trailingAnchor).isActive = true
self.value.topAnchor.constraint(equalTo: self.title.bottomAnchor, constant: 8).isActive = true
self.value.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -8).isActive = true
}
override func update() {
super.update()
self.textLabel?.text = nil
self.detailTextLabel?.text = nil
self.title.text = row.title
self.value.text = row.value
}
}
final class MultilineLabelRow: Row<MultilineLabelCell>, RowType {
required init(tag: String?) {
super.init(tag: tag)
cellProvider = CellProvider<MultilineLabelCell>()
}
}

View File

@ -1,60 +1,282 @@
/* No comment provided by engineer. */
"Action" = "Действие";
/* No comment provided by engineer. */
"Actions" = "Действия";
/* No comment provided by engineer. */
"Add new audio record" = "Добавить новую голосовую запись";
/* No comment provided by engineer. */
"Add new plate number via audio recording" = "Добавить новый гос. номер с помощью голосовой записи";
/* No comment provided by engineer. */
"Added by" = "Добавлено";
/* No comment provided by engineer. */
"Alternative order" = "Альтернативный порядок";
/* Added by */
"Anyone" = "Кем угодно";
/* Added by */
"Anyone but me" = "Кем угодно кроме меня";
/* No comment provided by engineer. */
"As link" = "Как ссылку";
/* No comment provided by engineer. */
"As one image" = "Как одну картинку";
/* No comment provided by engineer. */
"As text and photos" = "Как текст и фотографии";
/* No comment provided by engineer. */
"AutoCat Account" = "Аккаунт в АвтоКот";
/* No comment provided by engineer. */
"Beep before record" = "Звуковой сигнал перед записью";
/* No comment provided by engineer. */
"Beginning" = "Начала";
/* No comment provided by engineer. */
"Brand" = "Марка";
/* No comment provided by engineer. */
"Brands" = "Марки";
/* No comment provided by engineer. */
"Cancel" = "Отмена";
/* No comment provided by engineer. */
"Category" = "Категория";
/* No comment provided by engineer. */
"Check" = "Проверить";
/* No comment provided by engineer. */
"Clear all filters" = "Очистить все фильтры";
/* No comment provided by engineer. */
"Color" = "Цвет";
/* No comment provided by engineer. */
"Contract restrictions" = "Ограничения лиц, допущенных к управлению";
/* No comment provided by engineer. */
"Contract series and number" = "Серия и номер договора";
/* No comment provided by engineer. */
"Copy to pasteboard" = "Копировать в буфер обмена";
/* No comment provided by engineer. */
"Default region" = "Регион по умолчанию";
/* No comment provided by engineer. */
"Delete" = "Удалить";
/* No comment provided by engineer. */
"Done" = "Готово";
/* No comment provided by engineer. */
"Driver region" = "Регион прописки владельца ТС";
/* No comment provided by engineer. */
"Edit plate number" = "Редактировать гос. номер";
/* No comment provided by engineer. */
"Engine" = "Двигатель";
/* No comment provided by engineer. */
"Events" = "События";
/* No comment provided by engineer. */
"From" = "С";
/* No comment provided by engineer. */
"Fuel type" = "Вид топлива";
/* No comment provided by engineer. */
"General" = "Общее";
/* No comment provided by engineer. */
"Google" = "Аккаунт Google";
/* No comment provided by engineer. */
"History" = "История";
/* No comment provided by engineer. */
"Identifiers" = "Идентификаторы";
/* No comment provided by engineer. */
"If enabled, app will try to recognize shortened plate numbers (without region) and add default region" = "Если опция включена, приложение попытается распознавать укороченные номера (без региона) и добавлять регион по умолчанию";
/* Owner type */
"individual" = "Физ. лицо";
/* No comment provided by engineer. */
"Insurance organization name" = "Наименование страховой организации";
/* No comment provided by engineer. */
"Insurant" = "Страхователь";
/* No comment provided by engineer. */
"Japanese" = "Японское ТС";
/* No comment provided by engineer. */
"Left" = "Левый";
/* Owner type */
"legal" = "Юр. лицо";
/* No comment provided by engineer. */
"Log In" = "Войти";
/* No comment provided by engineer. */
"Main filters" = "Основные фильтры";
/* Added by */
"Me" = "Мной";
/* No comment provided by engineer. */
"Model" = "Модель";
/* No comment provided by engineer. */
"More actions" = "Больше действий";
/* No comment provided by engineer. */
"No" = "Нет";
/* No comment provided by engineer. */
"now" = "Настоящий момент";
/* No comment provided by engineer. */
"Now" = "Настоящий момент";
/* No comment provided by engineer. */
"Number" = "Номер";
/* No comment provided by engineer. */
"OSAGO" = "ОСАГО";
/* No comment provided by engineer. */
"OSAGO contract status" = "Статус договора ОСАГО";
/* No comment provided by engineer. */
"Owner" = "Владелец";
/* No comment provided by engineer. */
"Owner type" = "Тип владельца";
/* No comment provided by engineer. */
"Owners" = "Владельцы";
/* No comment provided by engineer. */
"Photos" = "Фотографии";
/* No comment provided by engineer. */
"Plate number" = "Гос. номер";
/* No comment provided by engineer. */
"Plate number recognition" = "Распознавание гос. номера";
/* No comment provided by engineer. */
"Power (HP)" = "Мощность (л.с.)";
/* No comment provided by engineer. */
"Power (kw)" = "Мощность (кВт)";
/* No comment provided by engineer. */
"Profile" = "Профиль";
/* No comment provided by engineer. */
"PTS" = "ПТС";
/* No comment provided by engineer. */
"Recognize plate numbers in alternative form. For example 'ЕВА 123 777' instead of 'Е123ВА 777'" = "Распознавать гос. номер в альтернативной форме. Например 'ЕВА 123 777' вместо 'Е123ВА 777'";
/* No comment provided by engineer. */
"Recognized text" = "Распознанный текст";
/* No comment provided by engineer. */
"Recording..." = "Запись...";
/* No comment provided by engineer. */
"Regions" = "Регионы";
/* No comment provided by engineer. */
"Remove" = "Удалить";
/* No comment provided by engineer. */
"Right" = "Правый";
/* No comment provided by engineer. */
"Search plate numbers" = "Поиск по гос. номеру";
/* Search field placeholder */
"Search regions" = "Поиск по региону";
/* No comment provided by engineer. */
"Share" = "Поделиться";
/* No comment provided by engineer. */
"Share report" = "Поделиться отчетом";
/* No comment provided by engineer. */
"Shortened numbers" = "Укороченные номера";
/* No comment provided by engineer. */
"Show on map" = "Показать на карте";
/* No comment provided by engineer. */
"Show recognized text" = "Показать распознанный текст";
/* No comment provided by engineer. */
"Sign Out" = "Выйти";
/* No comment provided by engineer. */
"Steering wheel position" = "Положение руля";
/* No comment provided by engineer. */
"STS" = "СТС";
/* No comment provided by engineer. */
"To" = "По";
/* No comment provided by engineer. */
"Today" = "Сегодня";
/* No comment provided by engineer. */
"Update" = "Обновить";
/* No comment provided by engineer. */
"Vehicle region" = "Регион регистрации ТС";
/* No comment provided by engineer. */
"Vehicle usage region" = "Транспортное средство используется в регионе";
/* No comment provided by engineer. */
"VIN" = "VIN";
/* No comment provided by engineer. */
"Volume (cm³)" = "Объем (см³)";
/* No comment provided by engineer. */
"When enabled, you will hear short sound before starting audio recording. This will only work when audio record is started via Siri" = "Если включено, вы услышите короткий звуковой сигнал перед началом записи аудио.";
/* No comment provided by engineer. */
"Year" = "Год";
/* No comment provided by engineer. */
"Yes" = "Да";
/* No comment provided by engineer. */
"Yesterday" = "Вчера";
/* No comment provided by engineer. */
"You are currently signed in with email %@. It will help to gather more data about vehicles." = "Сейчас вы залогинены с почтой %@. Это поможет собирать больше данных для отчета";
/* No comment provided by engineer. */
"ZIP (or OKTMO) code" = "Индекс (или ОКТМО)";