Skip to content

Commit 848151d

Browse files
authored
Enhanced Bundle Locator (#23)
1 parent 7268f25 commit 848151d

File tree

6 files changed

+54
-15
lines changed

6 files changed

+54
-15
lines changed

Package.resolved

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
"repositoryURL": "https://github.com/apple/swift-argument-parser",
77
"state": {
88
"branch": null,
9-
"revision": "35b76bf577d3cc74820f8991894ce3bcdf024ddc",
10-
"version": "0.0.2"
9+
"revision": "e394bf350e38cb100b6bc4172834770ede1b7232",
10+
"version": "1.0.3"
1111
}
1212
}
1313
]

Package.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ let package = Package(
1212
.executable(name: "lingo", targets: ["Lingo"])
1313
],
1414
dependencies: [
15-
.package(url: "https://github.com/apple/swift-argument-parser", .upToNextMinor(from: "0.0.1")),
15+
.package(url: "https://github.com/apple/swift-argument-parser", .upToNextMinor(from: "1.0.0")),
1616
],
1717
targets: [
1818
.target(

Sources/Core/LingoCore.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@
2828
import Foundation
2929

3030
public struct LingoCore {
31-
public static func run(input: String, output: String) throws {
31+
public static func run(input: String, output: String, packageName: String?) throws {
3232
guard let fileData = FileHandler.readFiles(inputPath: input, outputPath: output) else {
3333
throw LingoError.custom("Couldn't read files. Did you type your arguments incorrectly?")
3434
}
3535

3636
let keyValues = KeyGenerator.generate(localizationFileContents: fileData.input)
3737
let generatedStructs = StructGenerator.generate(keyValues: keyValues)
38-
let swift = SwiftGenerator.generate(structs: generatedStructs, keyValues: keyValues)
38+
let swift = SwiftGenerator.generate(structs: generatedStructs, keyValues: keyValues, packageName: packageName)
3939

4040
try FileHandler.writeOutput(swift: swift, to: output)
4141
}

Sources/Core/SwiftGenerator.swift

+37-6
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@
2828
import Foundation
2929

3030
public struct SwiftGenerator {
31-
public static func generate(structs: [Struct], keyValues: [String:String]) -> String {
31+
public static func generate(structs: [Struct], keyValues: [String:String], packageName: String?) -> String {
3232
var swift = "// This file is autogenerated by Lingo from your localized strings file.\n\n"
3333
swift += "import Foundation\n\n"
3434
swift += "private class BundleLocator {\n"
3535
swift += " static let bundle: Bundle = {\n"
36-
swift += " #if SWIFT_PACKAGE\n"
37-
swift += " return Bundle.module\n"
38-
swift += " #else\n"
39-
swift += " return Bundle(for: BundleLocator.self)\n"
40-
swift += " #endif\n"
36+
swift += " #if SWIFT_PACKAGE\n"
37+
swift += " \(modulde(packageName))\n"
38+
swift += " #else\n"
39+
swift += " return Bundle(for: BundleLocator.self)\n"
40+
swift += " #endif\n"
4141
swift += " }()\n"
4242
swift += "}\n\n"
4343
swift += "public struct Lingo {\n"
@@ -65,4 +65,35 @@ public struct SwiftGenerator {
6565
swift += "\n }"
6666
return swift
6767
}
68+
69+
private static func modulde(_ packageName: String?) -> String {
70+
if let packageName = packageName {
71+
return """
72+
let bundleName = "\(packageName)_\(packageName)"
73+
let candidates = [
74+
/* Bundle should be present here when the package is linked into an App. */
75+
Bundle.main.resourceURL,
76+
/* Bundle should be present here when the package is linked into a framework. */
77+
Bundle(for: BundleLocator.self).resourceURL,
78+
/* For command-line tools. */
79+
Bundle.main.bundleURL,
80+
/* Bundle should be present here when the package is used in UI Tests. */
81+
Bundle(for: BundleLocator.self).resourceURL?.deletingLastPathComponent(),
82+
/* Bundle should be present here when running previews from a different package (this is the path to "…/Debug-iphonesimulator/"). */
83+
Bundle(for: BundleLocator.self).resourceURL?.deletingLastPathComponent().deletingLastPathComponent()
84+
]
85+
86+
for candidate in candidates {
87+
let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle")
88+
if let bundle = bundlePath.flatMap(Bundle.init(url:)) {
89+
return bundle
90+
}
91+
}
92+
93+
fatalError("unable to find bundle named \\(bundleName)")
94+
"""
95+
} else {
96+
return "return Bundle.module"
97+
}
98+
}
6899
}

Sources/Lingo/main.swift

+9-1
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,16 @@ struct Lingo: ParsableCommand {
3535
@Option(help: "path including file name to write Swift to")
3636
var output: String
3737

38+
@Option(
39+
help: ArgumentHelp(
40+
"The name of the SPM package which `Lingo.swift` will belong to.",
41+
discussion: "If you are using SwiftUI and your strings file (and Lingo.swift) belong to a Swift package, specify that Swift package's name with this option. Without it SwiftUI previews will fatal error.",
42+
valueName: "package-name")
43+
)
44+
var packageName: String?
45+
3846
func run() throws {
39-
try LingoCore.run(input: input, output: output)
47+
try LingoCore.run(input: input, output: output, packageName: packageName)
4048
}
4149
}
4250

Tests/LingoTests/LingoTests.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class LingoTests: XCTestCase {
7777
let keyValues = ["Lingo.Title": "\"Lingo\"", "Lingo.WasHisName": "\"Oh\"", "Flair.Description": "\"As in pieces of flair from Office Space the movie\"", "MONK.Title": "\"A networking lib\""]
7878

7979
let structs = StructGenerator.generate(keyValues: keyValues)
80-
let swift = SwiftGenerator.generate(structs: structs, keyValues: keyValues)
80+
let swift = SwiftGenerator.generate(structs: structs, keyValues: keyValues, packageName: nil)
8181

8282
XCTAssert(swift == LingoTests.expectedText, "Generated Swift doesn't match expected")
8383
}
@@ -110,7 +110,7 @@ class LingoTests: XCTestCase {
110110
let url = try! LingoTests.write(LingoTests.localizableStrings, toTemp: "input")
111111
measure {
112112
do {
113-
try LingoCore.run(input: url.path, output: outputURL.path)
113+
try LingoCore.run(input: url.path, output: outputURL.path, packageName: nil)
114114

115115
let expectedSwift = LingoTests.expectedText
116116
let generatedSwift = try? String(contentsOf: self.outputURL)
@@ -135,7 +135,7 @@ private extension LingoTests {
135135

136136
static var expectedText: String {
137137
return """
138-
// This file is autogenerated by Lingo from your localized strings file.\n\nimport Foundation\n\nprivate class BundleLocator {\n static let bundle: Bundle = {\n #if SWIFT_PACKAGE\n return Bundle.module\n #else\n return Bundle(for: BundleLocator.self)\n #endif\n }()\n}\n\npublic struct Lingo {\n public struct Flair {\n /// \"As in pieces of flair from Office Space the movie\"\n public static let description = NSLocalizedString(\"Flair.Description\", bundle: BundleLocator.bundle, comment: \"\")\n }\n\n public struct Lingo {\n /// \"Lingo\"\n public static let title = NSLocalizedString(\"Lingo.Title\", bundle: BundleLocator.bundle, comment: \"\")\n /// \"Oh\"\n public static let wasHisName = NSLocalizedString(\"Lingo.WasHisName\", bundle: BundleLocator.bundle, comment: \"\")\n }\n\n public struct MONK {\n /// \"A networking lib\"\n public static let title = NSLocalizedString(\"MONK.Title\", bundle: BundleLocator.bundle, comment: \"\")\n }\n}\n
138+
// This file is autogenerated by Lingo from your localized strings file.\n\nimport Foundation\n\nprivate class BundleLocator {\n static let bundle: Bundle = {\n #if SWIFT_PACKAGE\n return Bundle.module\n #else\n return Bundle(for: BundleLocator.self)\n #endif\n }()\n}\n\npublic struct Lingo {\n public struct Flair {\n /// \"As in pieces of flair from Office Space the movie\"\n public static let description = NSLocalizedString(\"Flair.Description\", bundle: BundleLocator.bundle, comment: \"\")\n }\n\n public struct Lingo {\n /// \"Lingo\"\n public static let title = NSLocalizedString(\"Lingo.Title\", bundle: BundleLocator.bundle, comment: \"\")\n /// \"Oh\"\n public static let wasHisName = NSLocalizedString(\"Lingo.WasHisName\", bundle: BundleLocator.bundle, comment: \"\")\n }\n\n public struct MONK {\n /// \"A networking lib\"\n public static let title = NSLocalizedString(\"MONK.Title\", bundle: BundleLocator.bundle, comment: \"\")\n }\n}\n
139139
"""
140140
}
141141

0 commit comments

Comments
 (0)