Skip to content

Commit

Permalink
Add ArgumentParser (#16)
Browse files Browse the repository at this point in the history
* Add ArgumentParser dependency

* Rename SwiftPolyglotCore struct

* Add RuntimeError

* Rename SwiftPolyglot struct, add ParsableCommand adoption and add RuntimeError usage

* Parse arguments and flag using ArgumentParser and adjust SwiftPolyglotCore initializer's parameters

* Update README

* Rename property

* Format

* Fix command name in help's message
  • Loading branch information
pereBohigas authored May 12, 2024
1 parent 818d73f commit 59968c2
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 76 deletions.
14 changes: 14 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"pins" : [
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser.git",
"state" : {
"revision" : "46989693916f56d1186bd59ac15124caef896560",
"version" : "1.3.1"
}
}
],
"version" : 2
}
8 changes: 7 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ let package = Package(
products: [
.executable(name: "swiftpolyglot", targets: ["SwiftPolyglot"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMajor(from: "1.3.1")),
],
targets: [
.executableTarget(
name: "SwiftPolyglot",
dependencies: ["SwiftPolyglotCore"]
dependencies: [
"SwiftPolyglotCore",
.product(name: "ArgumentParser", package: "swift-argument-parser")
]
),
.target(name: "SwiftPolyglotCore"),
.testTarget(
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ $ swift build -c release

```
$ cd ../path/to/your/project
$ swift run --package-path ../path/to/SwiftPolyglot swiftpolyglot "en,es,de"
$ swift run --package-path ../path/to/SwiftPolyglot swiftpolyglot en es de
```

## Arguments

You must specify at least one language code, they must be within quotation marks, and they must be separated by commas. If you are not providing a translation for your language of origin, you do not need to specify that language. Otherwise, you will get errors due to missing translations.
You must specify at least one language code, and they must be separated by spaces. If you are not providing a translation for your language of origin, you do not need to specify that language. Otherwise, you will get errors due to missing translations.

By default, SwiftPolyglot will not throw an error at the end of the script if there are translations missing. However, you can enable error throwing by adding the argument `--errorOnMissing`
By default, SwiftPolyglot will not throw an error at the end of the script if there are translations missing. However, you can enable error throwing by adding the flag `--error-on-missing`

## Integrating with GitHub Actions

Expand All @@ -60,6 +60,6 @@ jobs:
- name: validate translations
run: |
swift build --package-path ../SwiftPolyglot --configuration release
swift run --package-path ../SwiftPolyglot swiftpolyglot "es,fr,de,it" --errorOnMissing
swift run --package-path ../SwiftPolyglot swiftpolyglot es fr de it --error-on-missing
```

15 changes: 15 additions & 0 deletions Sources/SwiftPolyglot/RuntimeError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
enum RuntimeError: Error {
case coreError(description: String)
case fileListingNotPossible
}

extension RuntimeError: CustomStringConvertible {
var description: String {
switch self {
case let .coreError(description):
return description
case .fileListingNotPossible:
return "It was not possible to list all files to be checked"
}
}
}
36 changes: 36 additions & 0 deletions Sources/SwiftPolyglot/SwiftPolyglot.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import ArgumentParser
import Foundation
import SwiftPolyglotCore

@main
struct SwiftPolyglot: ParsableCommand {
static let configuration: CommandConfiguration = .init(commandName: "swiftpolyglot")

@Flag(help: "Log errors instead of warnings for missing translations.")
private var errorOnMissing = false

@Argument(help: "Specify the language(s) to be checked.")
private var languages: [String]

func run() throws {
guard
let enumerator = FileManager.default.enumerator(atPath: FileManager.default.currentDirectoryPath),
let filePaths = enumerator.allObjects as? [String]
else {
throw RuntimeError.fileListingNotPossible
}

let swiftPolyglotCore: SwiftPolyglotCore = .init(
filePaths: filePaths,
languageCodes: languages,
logsErrorOnMissingTranslation: errorOnMissing,
isRunningInAGitHubAction: ProcessInfo.processInfo.environment["GITHUB_ACTIONS"] == "true"
)

do {
try swiftPolyglotCore.run()
} catch {
throw RuntimeError.coreError(description: error.localizedDescription)
}
}
}
22 changes: 0 additions & 22 deletions Sources/SwiftPolyglot/main.swift

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,39 +1,29 @@
import Foundation

public struct SwiftPolyglot {
private static let errorOnMissingArgument = "--errorOnMissing"

private let arguments: [String]
public struct SwiftPolyglotCore {
private let filePaths: [String]
private let languageCodes: [String]
private let runningOnAGitHubAction: Bool

private var logErrorOnMissing: Bool {
arguments.contains(Self.errorOnMissingArgument)
}

public init(arguments: [String], filePaths: [String], runningOnAGitHubAction: Bool) throws {
let languageCodes = arguments[0].split(separator: ",").map(String.init)

guard
!languageCodes.contains(Self.errorOnMissingArgument),
!languageCodes.isEmpty
else {
throw SwiftPolyglotError.noLanguageCodes
}

self.arguments = arguments
private let logsErrorOnMissingTranslation: Bool
private let isRunningInAGitHubAction: Bool

public init(
filePaths: [String],
languageCodes: [String],
logsErrorOnMissingTranslation: Bool,
isRunningInAGitHubAction: Bool
) {
self.filePaths = filePaths
self.languageCodes = languageCodes
self.runningOnAGitHubAction = runningOnAGitHubAction
self.logsErrorOnMissingTranslation = logsErrorOnMissingTranslation
self.isRunningInAGitHubAction = isRunningInAGitHubAction
}

public func run() throws {
var missingTranslations = false

try searchDirectory(for: languageCodes, missingTranslations: &missingTranslations)

if missingTranslations, logErrorOnMissing {
if missingTranslations, logsErrorOnMissingTranslation {
throw SwiftPolyglotError.missingTranslations
} else if missingTranslations {
print("Completed with missing translations.")
Expand Down Expand Up @@ -90,7 +80,7 @@ public struct SwiftPolyglot {
let jsonDict = jsonObject as? [String: Any],
let strings = jsonDict["strings"] as? [String: [String: Any]]
else {
if runningOnAGitHubAction {
if isRunningInAGitHubAction {
print("::warning file=\(fileURL.path)::Could not process file at path: \(fileURL.path)")
} else {
print("Could not process file at path: \(fileURL.path)")
Expand Down Expand Up @@ -170,8 +160,8 @@ public struct SwiftPolyglot {
}

private func logWarning(file: String, message: String) {
if runningOnAGitHubAction {
if logErrorOnMissing {
if isRunningInAGitHubAction {
if logsErrorOnMissingTranslation {
print("::error file=\(file)::\(message)")
} else {
print("::warning file=\(file)::\(message)")
Expand Down
11 changes: 4 additions & 7 deletions Sources/SwiftPolyglotCore/SwiftPolyglotError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@ import Foundation

enum SwiftPolyglotError: Error {
case missingTranslations
case noLanguageCodes
case unsupportedVariation(variation: String)
}

extension SwiftPolyglotError: LocalizedError {
public var errorDescription: String? {
switch self {
case .missingTranslations:
return "Error: One or more translations are missing."
case .noLanguageCodes:
return "Usage: swiftpolyglot <comma-separated language codes> [--errorOnMissing]"
case let .unsupportedVariation(variation):
return "Variation type '\(variation)' is not supported. Please create an issue in GitHub"
case .missingTranslations:
return "Error: One or more translations are missing."
case let .unsupportedVariation(variation):
return "Variation type '\(variation)' is not supported. Please create an issue in GitHub"
}
}
}
36 changes: 20 additions & 16 deletions Tests/SwiftPolyglotCoreTests/SwiftPolyglotCoreTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ final class SwiftPolyglotCoreTests: XCTestCase {
return
}

let swiftPolyglot: SwiftPolyglot = try .init(
arguments: ["ca,de,en,es"],
let swiftPolyglotCore: SwiftPolyglotCore = .init(
filePaths: [stringCatalogFilePath],
runningOnAGitHubAction: false
languageCodes: ["ca", "de", "en", "es"],
logsErrorOnMissingTranslation: false,
isRunningInAGitHubAction: false
)

XCTAssertNoThrow(try swiftPolyglot.run())
XCTAssertNoThrow(try swiftPolyglotCore.run())
}

func testStringCatalogVariationsFullyTranslated() throws {
Expand All @@ -35,13 +36,14 @@ final class SwiftPolyglotCoreTests: XCTestCase {
return
}

let swiftPolyglot: SwiftPolyglot = try .init(
arguments: ["ca,de,en,es"],
let swiftPolyglotCore: SwiftPolyglotCore = .init(
filePaths: [stringCatalogFilePath],
runningOnAGitHubAction: false
languageCodes: ["ca", "de", "en", "es"],
logsErrorOnMissingTranslation: false,
isRunningInAGitHubAction: false
)

XCTAssertNoThrow(try swiftPolyglot.run())
XCTAssertNoThrow(try swiftPolyglotCore.run())
}

func testStringCatalogWithMissingTranslations() throws {
Expand All @@ -56,13 +58,14 @@ final class SwiftPolyglotCoreTests: XCTestCase {
return
}

let swiftPolyglot: SwiftPolyglot = try .init(
arguments: ["ca,de,en,es", "--errorOnMissing"],
let swiftPolyglotCore: SwiftPolyglotCore = .init(
filePaths: [stringCatalogFilePath],
runningOnAGitHubAction: false
languageCodes: ["ca", "de", "en", "es"],
logsErrorOnMissingTranslation: true,
isRunningInAGitHubAction: false
)

XCTAssertThrowsError(try swiftPolyglot.run())
XCTAssertThrowsError(try swiftPolyglotCore.run())
}

func testStringCatalogWithMissingVariations() throws {
Expand All @@ -77,12 +80,13 @@ final class SwiftPolyglotCoreTests: XCTestCase {
return
}

let swiftPolyglot: SwiftPolyglot = try .init(
arguments: ["de,en", "--errorOnMissing"],
let swiftPolyglotCore: SwiftPolyglotCore = .init(
filePaths: [stringCatalogFilePath],
runningOnAGitHubAction: false
languageCodes: ["de, en"],
logsErrorOnMissingTranslation: true,
isRunningInAGitHubAction: false
)

XCTAssertThrowsError(try swiftPolyglot.run())
XCTAssertThrowsError(try swiftPolyglotCore.run())
}
}

0 comments on commit 59968c2

Please sign in to comment.