diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/BarcodeScanner.podspec b/BarcodeScanner.podspec index f84e366..5acd641 100644 --- a/BarcodeScanner.podspec +++ b/BarcodeScanner.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "BarcodeScanner" s.summary = "Simple and beautiful barcode scanner." - s.version = "5.0.0" + s.version = "5.0.1" s.homepage = "https://github.com/hyperoslo/BarcodeScanner" s.license = 'MIT' s.author = { "Hyper Interaktiv AS" => "ios@hyper.no" } diff --git a/BarcodeScanner.xcodeproj/project.pbxproj b/BarcodeScanner.xcodeproj/project.pbxproj index 4b26f59..a961262 100644 --- a/BarcodeScanner.xcodeproj/project.pbxproj +++ b/BarcodeScanner.xcodeproj/project.pbxproj @@ -8,11 +8,9 @@ /* Begin PBXBuildFile section */ 2DBF9E0E1F169DEF006B5AA8 /* FocusViewType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DBF9E0D1F169DEF006B5AA8 /* FocusViewType.swift */; }; + AA8BA41623CCA895002F447D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = AA8BA40F23CCA895002F447D /* Localizable.strings */; }; + CE8C0771252FBBAF007FF4A4 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE8C0770252FBBAF007FF4A4 /* Images.xcassets */; }; D504555F1FD8714700E46826 /* UIView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D504555E1FD8714700E46826 /* UIView+Extensions.swift */; }; - D50BE3E91C9FE7A80000A34C /* flashOff@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D50BE3E51C9FE7A80000A34C /* flashOff@3x.png */; }; - D50BE3EA1C9FE7A80000A34C /* flashOn@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D50BE3E61C9FE7A80000A34C /* flashOn@3x.png */; }; - D50BE3EB1C9FE7A80000A34C /* info@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D50BE3E71C9FE7A80000A34C /* info@3x.png */; }; - D5349DF8201E42D900CD53EA /* cameraRotate@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D5349DF7201E42D900CD53EA /* cameraRotate@3x.png */; }; D55281B62016758F00FF3CDD /* HeaderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55281B52016758F00FF3CDD /* HeaderViewController.swift */; }; D55281B8201675D500FF3CDD /* MessageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55281B7201675D500FF3CDD /* MessageViewController.swift */; }; D55281BA2016770800FF3CDD /* CameraViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55281B92016770800FF3CDD /* CameraViewController.swift */; }; @@ -28,11 +26,14 @@ /* Begin PBXFileReference section */ 2DBF9E0D1F169DEF006B5AA8 /* FocusViewType.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = FocusViewType.swift; sourceTree = ""; tabWidth = 2; }; + AA8BA41023CCA895002F447D /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; + AA8BA41123CCA895002F447D /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = ""; }; + AA8BA41223CCA895002F447D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + AA8BA41323CCA895002F447D /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; }; + AA8BA41423CCA895002F447D /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; + AA8BA41523CCA895002F447D /* pl-PL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pl-PL"; path = "pl-PL.lproj/Localizable.strings"; sourceTree = ""; }; + CE8C0770252FBBAF007FF4A4 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; D504555E1FD8714700E46826 /* UIView+Extensions.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = "UIView+Extensions.swift"; sourceTree = ""; tabWidth = 2; }; - D50BE3E51C9FE7A80000A34C /* flashOff@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "flashOff@3x.png"; sourceTree = ""; }; - D50BE3E61C9FE7A80000A34C /* flashOn@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "flashOn@3x.png"; sourceTree = ""; }; - D50BE3E71C9FE7A80000A34C /* info@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "info@3x.png"; sourceTree = ""; }; - D5349DF7201E42D900CD53EA /* cameraRotate@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "cameraRotate@3x.png"; sourceTree = ""; }; D55281B52016758F00FF3CDD /* HeaderViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderViewController.swift; sourceTree = ""; }; D55281B7201675D500FF3CDD /* MessageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageViewController.swift; sourceTree = ""; }; D55281B92016770800FF3CDD /* CameraViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraViewController.swift; sourceTree = ""; }; @@ -59,13 +60,18 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + AA8BA40E23CCA895002F447D /* Localization */ = { + isa = PBXGroup; + children = ( + AA8BA40F23CCA895002F447D /* Localizable.strings */, + ); + path = Localization; + sourceTree = ""; + }; D50BE3E31C9FE7A80000A34C /* Images */ = { isa = PBXGroup; children = ( - D5349DF7201E42D900CD53EA /* cameraRotate@3x.png */, - D50BE3E51C9FE7A80000A34C /* flashOff@3x.png */, - D50BE3E61C9FE7A80000A34C /* flashOn@3x.png */, - D50BE3E71C9FE7A80000A34C /* info@3x.png */, + CE8C0770252FBBAF007FF4A4 /* Images.xcassets */, ); path = Images; sourceTree = ""; @@ -95,9 +101,9 @@ D5B2E8951C3A780C00C0327D = { isa = PBXGroup; children = ( - D50BE3E31C9FE7A80000A34C /* Images */, D5C629691C3A809D007F7B7C /* Sources */, D5C6295C1C3A800E007F7B7C /* BarcodeScanner */, + AA8BA40E23CCA895002F447D /* Localization */, D5B2E8A01C3A780C00C0327D /* Products */, ); sourceTree = ""; @@ -121,6 +127,7 @@ D5C629691C3A809D007F7B7C /* Sources */ = { isa = PBXGroup; children = ( + D50BE3E31C9FE7A80000A34C /* Images */, D5CB3785201947D000B9319D /* Helpers */, D5CB37842019477900B9319D /* DataStructures */, D55281BD20167D9F00FF3CDD /* Extensions */, @@ -200,7 +207,13 @@ developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( + English, en, + de, + ja, + tr, + fr, + "pl-PL", Base, ); mainGroup = D5B2E8951C3A780C00C0327D; @@ -218,10 +231,12 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + AA8BA41623CCA895002F447D /* Localizable.strings in Resources */, D50BE3E91C9FE7A80000A34C /* flashOff@3x.png in Resources */, D5349DF8201E42D900CD53EA /* cameraRotate@3x.png in Resources */, D50BE3EB1C9FE7A80000A34C /* info@3x.png in Resources */, D50BE3EA1C9FE7A80000A34C /* flashOn@3x.png in Resources */, + CE8C0771252FBBAF007FF4A4 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -250,6 +265,22 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXVariantGroup section */ + AA8BA40F23CCA895002F447D /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + AA8BA41023CCA895002F447D /* de */, + AA8BA41123CCA895002F447D /* ja */, + AA8BA41223CCA895002F447D /* en */, + AA8BA41323CCA895002F447D /* tr */, + AA8BA41423CCA895002F447D /* fr */, + AA8BA41523CCA895002F447D /* pl-PL */, + ); + name = Localizable.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + /* Begin XCBuildConfiguration section */ D5B2E8B11C3A780C00C0327D /* Debug */ = { isa = XCBuildConfiguration; diff --git a/Example/BarcodeScannerExample/BarcodeScannerExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example/BarcodeScannerExample/BarcodeScannerExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Example/BarcodeScannerExample/BarcodeScannerExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..637b8ab --- /dev/null +++ b/Package.swift @@ -0,0 +1,28 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "BarcodeScanner", + defaultLocalization: "en", + platforms: [.iOS(.v14)], + products: [ + // Products define the executables and libraries produced by a package, and make them visible to other packages. + .library( + name: "BarcodeScanner", + targets: ["BarcodeScanner"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "BarcodeScanner", + path: "Sources" + ), + ] +) diff --git a/Sources/Controllers/BarcodeScannerViewController.swift b/Sources/Controllers/BarcodeScannerViewController.swift index b93eb9e..0a166a0 100644 --- a/Sources/Controllers/BarcodeScannerViewController.swift +++ b/Sources/Controllers/BarcodeScannerViewController.swift @@ -4,7 +4,7 @@ import AVFoundation // MARK: - Delegates /// Delegate to handle the captured code. -public protocol BarcodeScannerCodeDelegate: class { +@objc public protocol BarcodeScannerCodeDelegate: AnyObject { func scanner( _ controller: BarcodeScannerViewController, didCaptureCode code: String, @@ -13,12 +13,12 @@ public protocol BarcodeScannerCodeDelegate: class { } /// Delegate to report errors. -public protocol BarcodeScannerErrorDelegate: class { +@objc public protocol BarcodeScannerErrorDelegate: AnyObject { func scanner(_ controller: BarcodeScannerViewController, didReceiveError error: Error) } /// Delegate to dismiss barcode scanner when the close button has been pressed. -public protocol BarcodeScannerDismissalDelegate: class { +@objc public protocol BarcodeScannerDismissalDelegate: AnyObject { func scannerDidDismiss(_ controller: BarcodeScannerViewController) } @@ -32,24 +32,28 @@ public protocol BarcodeScannerDismissalDelegate: class { - Not found error message */ open class BarcodeScannerViewController: UIViewController { - private static let footerHeight: CGFloat = 75 - public var hideFooterView = false + public static var footerHeight: CGFloat = 75 + @objc public var hideFooterView = false // MARK: - Public properties /// Delegate to handle the captured code. - public weak var codeDelegate: BarcodeScannerCodeDelegate? + @objc public weak var codeDelegate: BarcodeScannerCodeDelegate? /// Delegate to report errors. - public weak var errorDelegate: BarcodeScannerErrorDelegate? + @objc public weak var errorDelegate: BarcodeScannerErrorDelegate? /// Delegate to dismiss barcode scanner when the close button has been pressed. - public weak var dismissalDelegate: BarcodeScannerDismissalDelegate? + @objc public weak var dismissalDelegate: BarcodeScannerDismissalDelegate? /// When the flag is set to `true` controller returns a captured code /// and waits for the next reset action. - public var isOneTimeSearch = true + @objc public var isOneTimeSearch = true + /// When the flag is set to `true` the screen is flashed on barcode scan. + /// Defaults to true. + @objc public var shouldSimulateFlash = true + /// `AVCaptureMetadataOutput` metadata object types. - public var metadata = AVMetadataObject.ObjectType.barcodeScannerMetadata { + @objc public var metadata = AVMetadataObject.ObjectType.barcodeScannerMetadata { didSet { cameraViewController.metadata = metadata } @@ -198,6 +202,13 @@ open class BarcodeScannerViewController: UIViewController { - Parameter processing: Flag to set the current state to `.processing`. */ private func animateFlash(whenProcessing: Bool = false) { + guard shouldSimulateFlash else { + if whenProcessing { + self.status = Status(state: .processing) + } + return + } + let flashView = UIView(frame: view.bounds) flashView.backgroundColor = UIColor.white flashView.alpha = 1 diff --git a/Sources/Controllers/CameraViewController.swift b/Sources/Controllers/CameraViewController.swift index da907e8..f5a722d 100644 --- a/Sources/Controllers/CameraViewController.swift +++ b/Sources/Controllers/CameraViewController.swift @@ -2,7 +2,7 @@ import UIKit import AVFoundation /// Delegate to handle camera setup and video capturing. -protocol CameraViewControllerDelegate: class { +protocol CameraViewControllerDelegate: AnyObject { func cameraViewControllerDidSetupCaptureSession(_ controller: CameraViewController) func cameraViewControllerDidFailToSetupCaptureSession(_ controller: CameraViewController) func cameraViewController(_ controller: CameraViewController, didReceiveError error: Error) @@ -134,7 +134,9 @@ public final class CameraViewController: UIViewController { } torchMode = .off - captureSession.startRunning() + DispatchQueue.global(qos: .background).async { + self.captureSession.startRunning() + } focusView.isHidden = false flashButton.isHidden = captureDevice?.position == .front cameraButton.isHidden = !showsCameraButton diff --git a/Sources/Controllers/HeaderViewController.swift b/Sources/Controllers/HeaderViewController.swift index 733e73c..8eb1c9e 100644 --- a/Sources/Controllers/HeaderViewController.swift +++ b/Sources/Controllers/HeaderViewController.swift @@ -1,7 +1,7 @@ import UIKit /// Delegate to handle touch event of the close button. -protocol HeaderViewControllerDelegate: class { +protocol HeaderViewControllerDelegate: AnyObject { func headerViewControllerDidTapCloseButton(_ controller: HeaderViewController) } diff --git a/Sources/Helpers/Functions.swift b/Sources/Helpers/Functions.swift index f959382..8c70eb7 100644 --- a/Sources/Helpers/Functions.swift +++ b/Sources/Helpers/Functions.swift @@ -7,15 +7,9 @@ import AVFoundation - Returns: An image. */ func imageNamed(_ name: String) -> UIImage { - let cls = BarcodeScannerViewController.self - var bundle = Bundle(for: cls) let traitCollection = UITraitCollection(displayScale: 3) - if let resourceBundle = bundle.resourcePath.flatMap({ Bundle(path: $0 + "/BarcodeScanner.bundle") }) { - bundle = resourceBundle - } - - guard let image = UIImage(named: name, in: bundle, compatibleWith: traitCollection) else { + guard let image = UIImage(named: name, in: Bundle.module, compatibleWith: traitCollection) else { return UIImage() } @@ -28,6 +22,9 @@ func imageNamed(_ name: String) -> UIImage { - Returns: An image. */ func localizedString(_ key: String) -> String { + if let bundle = Bundle(identifier: "no.hyper.BarcodeScanner-iOS") { + return bundle.localizedString(forKey: key, value: nil, table: "Localizable") + } if let path = Bundle(for: BarcodeScannerViewController.self).resourcePath, let resourceBundle = Bundle(path: path + "/Localization.bundle") { return resourceBundle.localizedString(forKey: key, value: nil, table: "Localizable") diff --git a/Sources/Images/Images.xcassets/Contents.json b/Sources/Images/Images.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Sources/Images/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sources/Images/Images.xcassets/cameraRotate.imageset/Contents.json b/Sources/Images/Images.xcassets/cameraRotate.imageset/Contents.json new file mode 100644 index 0000000..dcae763 --- /dev/null +++ b/Sources/Images/Images.xcassets/cameraRotate.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "cameraRotate@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Images/cameraRotate@3x.png b/Sources/Images/Images.xcassets/cameraRotate.imageset/cameraRotate@3x.png similarity index 100% rename from Images/cameraRotate@3x.png rename to Sources/Images/Images.xcassets/cameraRotate.imageset/cameraRotate@3x.png diff --git a/Sources/Images/Images.xcassets/flashOff.imageset/Contents.json b/Sources/Images/Images.xcassets/flashOff.imageset/Contents.json new file mode 100644 index 0000000..d663350 --- /dev/null +++ b/Sources/Images/Images.xcassets/flashOff.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "flashOff@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Images/flashOff@3x.png b/Sources/Images/Images.xcassets/flashOff.imageset/flashOff@3x.png similarity index 100% rename from Images/flashOff@3x.png rename to Sources/Images/Images.xcassets/flashOff.imageset/flashOff@3x.png diff --git a/Sources/Images/Images.xcassets/flashOn.imageset/Contents.json b/Sources/Images/Images.xcassets/flashOn.imageset/Contents.json new file mode 100644 index 0000000..3c72d8a --- /dev/null +++ b/Sources/Images/Images.xcassets/flashOn.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "flashOn@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Images/flashOn@3x.png b/Sources/Images/Images.xcassets/flashOn.imageset/flashOn@3x.png similarity index 100% rename from Images/flashOn@3x.png rename to Sources/Images/Images.xcassets/flashOn.imageset/flashOn@3x.png diff --git a/Sources/Images/Images.xcassets/info.imageset/Contents.json b/Sources/Images/Images.xcassets/info.imageset/Contents.json new file mode 100644 index 0000000..675e54e --- /dev/null +++ b/Sources/Images/Images.xcassets/info.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "info@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Images/info@3x.png b/Sources/Images/Images.xcassets/info.imageset/info@3x.png similarity index 100% rename from Images/info@3x.png rename to Sources/Images/Images.xcassets/info.imageset/info@3x.png diff --git a/Localization/de.lproj/Localizable.strings b/Sources/Localization/de.lproj/Localizable.strings similarity index 100% rename from Localization/de.lproj/Localizable.strings rename to Sources/Localization/de.lproj/Localizable.strings diff --git a/Localization/en.lproj/Localizable.strings b/Sources/Localization/en.lproj/Localizable.strings similarity index 100% rename from Localization/en.lproj/Localizable.strings rename to Sources/Localization/en.lproj/Localizable.strings diff --git a/Localization/fr.lproj/Localizable.strings b/Sources/Localization/fr.lproj/Localizable.strings similarity index 100% rename from Localization/fr.lproj/Localizable.strings rename to Sources/Localization/fr.lproj/Localizable.strings diff --git a/Localization/ja.lproj/Localizable.strings b/Sources/Localization/ja.lproj/Localizable.strings similarity index 100% rename from Localization/ja.lproj/Localizable.strings rename to Sources/Localization/ja.lproj/Localizable.strings diff --git a/Localization/nl.lproj/Localizable.strings b/Sources/Localization/nl.lproj/Localizable.strings similarity index 100% rename from Localization/nl.lproj/Localizable.strings rename to Sources/Localization/nl.lproj/Localizable.strings diff --git a/Localization/pl-PL.lproj/Localizable.strings b/Sources/Localization/pl-PL.lproj/Localizable.strings similarity index 100% rename from Localization/pl-PL.lproj/Localizable.strings rename to Sources/Localization/pl-PL.lproj/Localizable.strings diff --git a/Localization/pt-BR.lproj/Localizable.strings b/Sources/Localization/pt-BR.lproj/Localizable.strings similarity index 100% rename from Localization/pt-BR.lproj/Localizable.strings rename to Sources/Localization/pt-BR.lproj/Localizable.strings diff --git a/Localization/ru.lproj/Localizable.strings b/Sources/Localization/ru.lproj/Localizable.strings similarity index 100% rename from Localization/ru.lproj/Localizable.strings rename to Sources/Localization/ru.lproj/Localizable.strings diff --git a/Localization/tr.lproj/Localizable.strings b/Sources/Localization/tr.lproj/Localizable.strings similarity index 100% rename from Localization/tr.lproj/Localizable.strings rename to Sources/Localization/tr.lproj/Localizable.strings diff --git a/Sources/Localization/zh-Hans.lproj/Localizable.strings b/Sources/Localization/zh-Hans.lproj/Localizable.strings new file mode 100644 index 0000000..2b3abfb --- /dev/null +++ b/Sources/Localization/zh-Hans.lproj/Localizable.strings @@ -0,0 +1,7 @@ +"SCAN_BARCODE_TITLE" = "扫描二维码"; +"BUTTON_CLOSE" = "关闭"; +"BUTTON_SETTINGS" = "设置"; +"INFO_DESCRIPTION_TEXT" = "把条形码放在窗口来扫描。搜索会自动开始。"; +"INFO_LOADING_TITLE" = "寻找产品中..."; +"NO_PRODUCT_ERROR_TITLE" = "没有找到产品。"; +"ASK_FOR_PERMISSION_TEXT" = "你需要允许在设置里,允许访问相机才能扫描条形码。";