diff --git a/r2-shared-swift.xcodeproj/project.pbxproj b/r2-shared-swift.xcodeproj/project.pbxproj index 66036bfa..0ecd3a7b 100644 --- a/r2-shared-swift.xcodeproj/project.pbxproj +++ b/r2-shared-swift.xcodeproj/project.pbxproj @@ -39,6 +39,7 @@ CA2AE321221C1DCB008BD18F /* LoggerStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA2AE31E221C1DCB008BD18F /* LoggerStub.swift */; }; CA2AE322221C1DCB008BD18F /* Loggable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA2AE31F221C1DCB008BD18F /* Loggable.swift */; }; CA40C07A21FF25F80069A50E /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA40C07921FF25F80069A50E /* JSON.swift */; }; + CA50B86E22B2A1CF003AFF24 /* R2LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA50B86D22B2A1CF003AFF24 /* R2LocalizedString.swift */; }; CA9A40D1221B0AA200531EA1 /* Either.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9A40D0221B0AA200531EA1 /* Either.swift */; }; CA9E6BA12239823300ECF6E4 /* WP+Deprecated.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9E6BA02239823300ECF6E4 /* WP+Deprecated.swift */; }; CA9E6BA4223A657900ECF6E4 /* JSONEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9E6BA3223A657900ECF6E4 /* JSONEquatable.swift */; }; @@ -65,6 +66,7 @@ CACD75E42236A0F0004F20CA /* SubjectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CACD75E32236A0F0004F20CA /* SubjectTests.swift */; }; CACD75F32236B0A5004F20CA /* PublicationCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = CACD75F22236B0A5004F20CA /* PublicationCollection.swift */; }; CACD75F52236B2AF004F20CA /* PublicationCollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CACD75F42236B2AF004F20CA /* PublicationCollectionTests.swift */; }; + CAD178AD22B3A75C004E6812 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = CAD178AF22B3A75C004E6812 /* Localizable.strings */; }; CAF4EAE42237ABC700A17DA1 /* MediaOverlayNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E7D4041F4EC69100DF166D /* MediaOverlayNode.swift */; }; CAF4EAE52237ABC700A17DA1 /* MediaOverlays.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E7D4051F4EC69100DF166D /* MediaOverlays.swift */; }; CAF4EAE72237AD6000A17DA1 /* UserProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEF39DF220E3895200A560F3 /* UserProperties.swift */; }; @@ -129,6 +131,7 @@ CA2AE31E221C1DCB008BD18F /* LoggerStub.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoggerStub.swift; sourceTree = ""; }; CA2AE31F221C1DCB008BD18F /* Loggable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Loggable.swift; sourceTree = ""; }; CA40C07921FF25F80069A50E /* JSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; + CA50B86D22B2A1CF003AFF24 /* R2LocalizedString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = R2LocalizedString.swift; sourceTree = ""; }; CA6161EA21FB257700D2CFE3 /* r2-shared-swiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "r2-shared-swiftTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; CA6161EE21FB257700D2CFE3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; CA9A40D0221B0AA200531EA1 /* Either.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Either.swift; sourceTree = ""; }; @@ -154,6 +157,7 @@ CACD75E32236A0F0004F20CA /* SubjectTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubjectTests.swift; sourceTree = ""; }; CACD75F22236B0A5004F20CA /* PublicationCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicationCollection.swift; sourceTree = ""; }; CACD75F42236B2AF004F20CA /* PublicationCollectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicationCollectionTests.swift; sourceTree = ""; }; + CAD178AE22B3A75C004E6812 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; F3B1879F1FA33D4D00BB46BF /* Feed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Feed.swift; sourceTree = ""; }; F3B187A11FA33DFA00BB46BF /* Facet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Facet.swift; sourceTree = ""; }; F3B187A31FA33E1D00BB46BF /* OpdsMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpdsMetadata.swift; sourceTree = ""; }; @@ -195,6 +199,7 @@ CA9A40D0221B0AA200531EA1 /* Either.swift */, 57470F7D20ED0D1A000CDCA3 /* DownloadSession.swift */, CA9E6BA3223A657900ECF6E4 /* JSONEquatable.swift */, + CA50B86D22B2A1CF003AFF24 /* R2LocalizedString.swift */, ); path = Toolkit; sourceTree = ""; @@ -287,6 +292,14 @@ path = Logger; sourceTree = ""; }; + CA50B88922B3A6FE003AFF24 /* Resources */ = { + isa = PBXGroup; + children = ( + CAD178AF22B3A75C004E6812 /* Localizable.strings */, + ); + path = Resources; + sourceTree = ""; + }; CA6161EB21FB257700D2CFE3 /* r2-shared-swiftTests */ = { isa = PBXGroup; children = ( @@ -432,6 +445,7 @@ CA2AE31C221C1DCB008BD18F /* Logger */, 57470F7F20ED0D25000CDCA3 /* Toolkit */, F3B1879E1FA33D3700BB46BF /* OPDS */, + CA50B88922B3A6FE003AFF24 /* Resources */, ); path = "r2-shared-swift"; sourceTree = ""; @@ -549,6 +563,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + CAD178AD22B3A75C004E6812 /* Localizable.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -614,6 +629,7 @@ CA176392223AAC1A00959FEB /* UserSettings.swift in Sources */, CACD75F32236B0A5004F20CA /* PublicationCollection.swift in Sources */, CACD75DE22365780004F20CA /* WebPublication.swift in Sources */, + CA50B86E22B2A1CF003AFF24 /* R2LocalizedString.swift in Sources */, CAF4EAE42237ABC700A17DA1 /* MediaOverlayNode.swift in Sources */, CAC34F0C221C61BD002C452E /* DRM+Deprecated.swift in Sources */, CA16A8642232DA2000E66255 /* Locator.swift in Sources */, @@ -641,6 +657,17 @@ }; /* End PBXTargetDependency section */ +/* Begin PBXVariantGroup section */ + CAD178AF22B3A75C004E6812 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + CAD178AE22B3A75C004E6812 /* en */, + ); + name = Localizable.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + /* Begin XCBuildConfiguration section */ CA6161F221FB257700D2CFE3 /* Debug */ = { isa = XCBuildConfiguration; diff --git a/r2-shared-swift/Publication/Publication+JSON.swift b/r2-shared-swift/Publication/Publication+JSON.swift index 74fae51b..2b1c6e59 100644 --- a/r2-shared-swift/Publication/Publication+JSON.swift +++ b/r2-shared-swift/Publication/Publication+JSON.swift @@ -18,7 +18,7 @@ enum JSONError: LocalizedError { var errorDescription: String? { switch self { case .parsing(let type): - return "Failed to parse \(type) JSON" + return R2SharedLocalizedString("JSONError.parsing", "\(type)") } } diff --git a/r2-shared-swift/Resources/en.lproj/Localizable.strings b/r2-shared-swift/Resources/en.lproj/Localizable.strings new file mode 100644 index 00000000..2f1dcdf3 --- /dev/null +++ b/r2-shared-swift/Resources/en.lproj/Localizable.strings @@ -0,0 +1,16 @@ +/* + Localizable.strings + r2-shared-swift + + Created by Mickaël Menu on 14.06.19. + + Copyright 2019 Readium Foundation. All rights reserved. + Use of this source code is governed by a BSD-style license which is detailed + in the LICENSE file present in the project repository where this source code is maintained. +*/ + +/* Error while parsing a given JSON type */ +"R2Shared.JSONError.parsing" = "Failed to parse %@ JSON"; + +/* 404 Not found error during a network request made with DownloadSession */ +"R2Shared.DownloadSession.RequestError.notFound" = "Request failed: not found"; diff --git a/r2-shared-swift/Toolkit/DownloadSession.swift b/r2-shared-swift/Toolkit/DownloadSession.swift index 64435abb..85e61a9c 100644 --- a/r2-shared-swift/Toolkit/DownloadSession.swift +++ b/r2-shared-swift/Toolkit/DownloadSession.swift @@ -40,7 +40,7 @@ public class DownloadSession: NSObject, URLSessionDelegate, URLSessionDownloadDe var errorDescription: String? { switch self { case .notFound: - return "Request failed: not found" + return R2SharedLocalizedString("DownloadSession.RequestError.notFound") } } } diff --git a/r2-shared-swift/Toolkit/R2LocalizedString.swift b/r2-shared-swift/Toolkit/R2LocalizedString.swift new file mode 100644 index 00000000..da31b20d --- /dev/null +++ b/r2-shared-swift/Toolkit/R2LocalizedString.swift @@ -0,0 +1,31 @@ +// +// R2LocalizedString.swift +// r2-shared-swift +// +// Created by Mickaël Menu on 13.06.19. +// +// Copyright 2019 Readium Foundation. All rights reserved. +// Use of this source code is governed by a BSD-style license which is detailed +// in the LICENSE file present in the project repository where this source code is maintained. +// + +import Foundation + +/// Returns the localized string in the main bundle, or fallback on the bundle with given ID if not found. +/// Can be used to override framework localized strings in the host app. +public func R2LocalizedString(_ key: String, in bundleID: String, _ values: [CVarArg]) -> String { + let defaultValue = Bundle(identifier: bundleID)?.localizedString(forKey: key, value: nil, table: nil) + var string = Bundle.main.localizedString(forKey: key, value: defaultValue, table: nil) + if !values.isEmpty { + string = String(format: string, locale: Locale.current, arguments: values) + } + return string +} + +public func R2LocalizedString(_ key: String, in bundleID: String, _ values: CVarArg...) -> String { + return R2LocalizedString(key, in: bundleID, values) +} + +func R2SharedLocalizedString(_ key: String, _ values: CVarArg...) -> String { + return R2LocalizedString("R2Shared.\(key)", in: "org.readium.r2-shared-swift", values) +}