Skip to content

Commit e926340

Browse files
authored
Remove version restriction (#52)
* Add CLAUDE.md
1 parent 554248d commit e926340

File tree

3 files changed

+88
-14
lines changed

3 files changed

+88
-14
lines changed

CLAUDE.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
Swift-translate is a CLI tool and Swift Package Plugin for localizing iOS/macOS apps by translating String Catalogs (`.xcstrings` files) using OpenAI's GPT models or Google Cloud Translate.
8+
9+
## Common Development Commands
10+
11+
### Build & Test
12+
```bash
13+
swift build # Build the project
14+
swift build -c release # Build for release
15+
swift test # Run all tests
16+
swift test -v # Run tests with verbose output
17+
```
18+
19+
### Running the CLI During Development
20+
```bash
21+
# Basic text translation
22+
swift run swift-translate --verbose -k <API_KEY> --text "Hello" --lang de
23+
24+
# Translate a string catalog
25+
swift run swift-translate -k <API_KEY> path/to/catalog.xcstrings --lang de,fr,it
26+
27+
# Use Google Translate instead of OpenAI
28+
swift run swift-translate -s google -k <API_KEY> path/to/catalog.xcstrings
29+
```
30+
31+
## Architecture & Key Components
32+
33+
### Core Structure
34+
- **SwiftStringCatalog** (`Sources/SwiftStringCatalog/`) - Library for parsing/manipulating `.xcstrings` files
35+
- **SwiftTranslate** (`Sources/SwiftTranslate/`) - Main executable with CLI and translation logic
36+
- **Plugin** (`Plugin/`) - Swift Package Manager plugin support
37+
38+
### Translation Services (`Sources/SwiftTranslate/TranslationServices/`)
39+
- Protocol-based design with `TranslationService` protocol
40+
- `OpenAITranslator` - Supports GPT-4o and GPT-4.1 series models
41+
- `GoogleTranslator` - Google Cloud Translate v2 integration
42+
- Add new services by conforming to `TranslationService` protocol
43+
44+
### String Catalog Models
45+
- Private models (`_StringCatalog`, `_CatalogEntry`) for JSON parsing
46+
- Public models (`LocalizableString`, `LocalizableStringGroup`) for business logic
47+
- Supports plural variations, device variations, and string substitutions
48+
- Respects `shouldTranslate` flag in catalog entries
49+
50+
### CLI Entry Point
51+
- `Sources/SwiftTranslate/Bootstrap/SwiftTranslate.swift` - Main CLI using Swift Argument Parser
52+
- `TranslationCoordinator` orchestrates the translation workflow
53+
- Supports both text and file translation modes
54+
55+
## Key Implementation Notes
56+
57+
### String Catalog Format Support
58+
- Supports Xcode 15, 16, and 26 Beta catalog formats
59+
- Handles complex variations (plurals, devices, substitutions)
60+
- Only translates entries where `shouldTranslate` is true or nil
61+
- Preserves format specifiers like `%@`, `%d`, `%lld`
62+
63+
### Translation Workflow
64+
1. Parses catalog files into internal models
65+
2. Filters strings needing translation
66+
3. Batches requests to translation service
67+
4. Updates catalog with translations
68+
5. Writes to `.loc.xcstrings` files (or overwrites with `--overwrite`)
69+
70+
### Error Handling & Retries
71+
- Custom `SwiftTranslateError` enum for domain errors
72+
- Configurable retry logic for API failures
73+
- Timeout configuration for API requests
74+
- Validation of languages and file paths
75+
76+
### Testing
77+
- Unit tests focus on String Catalog parsing
78+
- Test resources in `Tests/Resources/`
79+
- Use `swift test` to run tests

Sources/SwiftStringCatalog/Bootstrap/StringCatalog.swift

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,8 @@ public final class StringCatalog {
99

1010
// MARK: Public
1111

12-
public enum Error: Swift.Error {
13-
case catalogVersionNotSupported(String)
14-
case substitionsNotYetSupported
15-
}
16-
1712
public let sourceLanguage: Language
18-
public let version = "1.0" // Only version 1.0 supported for now
13+
public let version: String
1914

2015
public private(set) var allKeys = [String]()
2116

@@ -36,10 +31,7 @@ public final class StringCatalog {
3631
let data = try Data(contentsOf: url)
3732
let decoder = JSONDecoder()
3833
let catalog = try decoder.decode(_StringCatalog.self, from: data)
39-
if catalog.version != version {
40-
throw Error.catalogVersionNotSupported(catalog.version)
41-
}
42-
34+
self.version = catalog.version
4335
self.allKeys = Array(catalog.strings.keys)
4436
self.sourceLanguage = catalog.sourceLanguage
4537
self.targetLanguages = {
@@ -53,9 +45,10 @@ public final class StringCatalog {
5345
try loadAllLocalizableStrings(from: catalog)
5446
}
5547

56-
public init(sourceLanguage: Language, targetLanguages: Set<Language> = []) {
48+
public init(sourceLanguage: Language, targetLanguages: Set<Language> = [], version: String = "1.0") {
5749
self.sourceLanguage = sourceLanguage
5850
self.targetLanguages = targetLanguages
51+
self.version = version
5952
}
6053

6154
// MARK: Loading
@@ -136,7 +129,8 @@ public final class StringCatalog {
136129
let entries = try buildCatalogEntries()
137130
let catalog = _StringCatalog(
138131
sourceLanguage: sourceLanguage,
139-
strings: entries
132+
strings: entries,
133+
version: version
140134
)
141135
let encoder = JSONEncoder()
142136
encoder.outputFormatting = [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes]
@@ -150,6 +144,7 @@ public final class StringCatalog {
150144
}
151145

152146
func buildCatalogEntries() throws -> [String: _CatalogEntry] {
147+
// let sortedGroups = localizableStringGroups.sorted { $0.key < $1.key }
153148
var entries = [String: _CatalogEntry]()
154149
for (key, stringGroup) in localizableStringGroups {
155150
entries[key] = try _CatalogEntry(from: stringGroup)

Sources/SwiftStringCatalog/Models/_StringCatalog.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ struct _StringCatalog: Codable {
1515

1616
// MARK: Lifecycle
1717

18-
init(sourceLanguage: Language, strings: [String: _CatalogEntry]) {
18+
init(sourceLanguage: Language, strings: [String: _CatalogEntry], version: String) {
1919
self.sourceLanguage = sourceLanguage
2020
self.strings = strings
21-
self.version = "1.0" // Only 1.0 supported
21+
self.version = version
2222
}
2323
}

0 commit comments

Comments
 (0)