fastlane-plugin-translate 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +318 -0
- data/lib/fastlane/plugin/translate/actions/translate_with_deepl.rb +547 -0
- data/lib/fastlane/plugin/translate/helper/deepl_language_mapper_helper.rb +99 -0
- data/lib/fastlane/plugin/translate/helper/language_registry_helper.rb +81 -0
- data/lib/fastlane/plugin/translate/helper/translation_progress_helper.rb +78 -0
- data/lib/fastlane/plugin/translate/version.rb +7 -0
- data/lib/fastlane/plugin/translate.rb +20 -0
- metadata +204 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d4b55852f8515ef6942b0bf6819379eb2c3cb81e20ef872a924470a2e9b6d886
|
4
|
+
data.tar.gz: 7d1d3b603837c68bd8fd548dca30b171ff074e42218956b910f9446109a3fea2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 83b931afb04769b0d6bd57fe7b686a772e707d350239dbcef6d191633078d2cd205f5ebf2f0229a88aab838ef824dd078f3326b7489ed633bd6462af633d3e91
|
7
|
+
data.tar.gz: 1be7fd87de5af70a4ea87a8c05fc8900606e3fa07327c2f0694997a0f614163be7fdcec98c170ad7e4d2bee798d53b4d396838ec57fd398c603fcf7fec9f67a1
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2025 Tijs Teulings <hello@tijs.org>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,318 @@
|
|
1
|
+
# fastlane-plugin-translate
|
2
|
+
|
3
|
+
<div align="center">
|
4
|
+
<img src="fastlane-action-translate-logo.png" alt="Fastlane Translate Plugin Logo" width="200"/>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
[](https://rubygems.org/gems/fastlane-plugin-translate)
|
8
|
+
[](https://buymeacoffee.com/xocrgwybbs)
|
9
|
+
|
10
|
+
## About translate
|
11
|
+
|
12
|
+
Automatically translate iOS `Localizable.xcstrings` files using DeepL API. This plugin helps you efficiently manage app localization by translating untranslated strings while preserving your existing translations.
|
13
|
+
|
14
|
+
## Features
|
15
|
+
|
16
|
+
- 🔍 **Auto-discovery**: Automatically finds your `Localizable.xcstrings` file
|
17
|
+
- 📊 **Translation analysis**: Shows translation progress for each language
|
18
|
+
- 🎯 **Smart targeting**: Only translates untranslated strings (state: "new" with empty values)
|
19
|
+
- 💾 **Progress tracking**: Saves progress between runs to avoid re-translating
|
20
|
+
- 🎭 **Formality support**: Automatically detects and offers formality options for supported languages
|
21
|
+
- 📝 **Context extraction**: Uses comments from xcstrings as translation context
|
22
|
+
- 🔄 **Batch processing**: Efficiently handles large numbers of strings
|
23
|
+
- 🛡️ **Error recovery**: Comprehensive error handling with user choices
|
24
|
+
- 📄 **Automatic backups**: Creates timestamped backups before translation
|
25
|
+
- ✅ **Validation**: Ensures output file is valid JSON
|
26
|
+
|
27
|
+
## Getting Started
|
28
|
+
|
29
|
+
### Install from RubyGems (Recommended)
|
30
|
+
|
31
|
+
```bash
|
32
|
+
fastlane add_plugin translate
|
33
|
+
```
|
34
|
+
|
35
|
+
### Install from GitHub (Latest Development Version)
|
36
|
+
|
37
|
+
Add to your `Gemfile`:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
gem "fastlane-plugin-translate", git: "https://github.com/tijs/fastlane-plugin-translate"
|
41
|
+
```
|
42
|
+
|
43
|
+
Then run:
|
44
|
+
|
45
|
+
```bash
|
46
|
+
bundle install
|
47
|
+
```
|
48
|
+
|
49
|
+
## Setup
|
50
|
+
|
51
|
+
1. **Get a DeepL API key** from <https://www.deepl.com/pro#developer>
|
52
|
+
2. **Set your API key** as an environment variable:
|
53
|
+
|
54
|
+
```bash
|
55
|
+
export DEEPL_AUTH_KEY="your-deepl-api-key-here"
|
56
|
+
```
|
57
|
+
|
58
|
+
## Usage
|
59
|
+
|
60
|
+
### Basic Usage
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
# Automatically detect xcstrings file and show language selection
|
64
|
+
translate_with_deepl
|
65
|
+
```
|
66
|
+
|
67
|
+
### Specify Target Language
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
# Translate to German
|
71
|
+
translate_with_deepl(target_language: "de")
|
72
|
+
|
73
|
+
# Translate to French with formal style
|
74
|
+
translate_with_deepl(
|
75
|
+
target_language: "fr",
|
76
|
+
formality: "more"
|
77
|
+
)
|
78
|
+
```
|
79
|
+
|
80
|
+
### Custom Configuration
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
# Full configuration example
|
84
|
+
translate_with_deepl(
|
85
|
+
xcstrings_path: "./MyApp/Localizable.xcstrings",
|
86
|
+
target_language: "es",
|
87
|
+
formality: "prefer_more",
|
88
|
+
batch_size: 15,
|
89
|
+
free_api: true
|
90
|
+
)
|
91
|
+
```
|
92
|
+
|
93
|
+
## Supported Languages
|
94
|
+
|
95
|
+
The plugin supports all languages available in both Apple's App Store Connect and DeepL API:
|
96
|
+
|
97
|
+
### Full DeepL Support
|
98
|
+
|
99
|
+
- 🇩🇪 German (de) - *supports formality*
|
100
|
+
- 🇫🇷 French (fr) - *supports formality*
|
101
|
+
- 🇮🇹 Italian (it) - *supports formality*
|
102
|
+
- 🇪🇸 Spanish (es) - *supports formality*
|
103
|
+
- 🇳🇱 Dutch (nl) - *supports formality*
|
104
|
+
- 🇵🇱 Polish (pl) - *supports formality*
|
105
|
+
- 🇵🇹 Portuguese (pt-BR, pt-PT) - *supports formality*
|
106
|
+
- 🇯🇵 Japanese (ja) - *supports formality*
|
107
|
+
- 🇷🇺 Russian (ru) - *supports formality*
|
108
|
+
- 🇬🇧 English (en-US, en-GB)
|
109
|
+
- 🇨🇳 Chinese (zh-Hans, zh-Hant)
|
110
|
+
- 🇰🇷 Korean (ko)
|
111
|
+
- And many more...
|
112
|
+
|
113
|
+
*Languages marked with "supports formality" offer formal/informal translation options*
|
114
|
+
|
115
|
+
## Parameters
|
116
|
+
|
117
|
+
| Parameter | Description | Default | Required |
|
118
|
+
|-----------|-------------|---------|----------|
|
119
|
+
| `api_token` | DeepL API authentication key | `ENV['DEEPL_AUTH_KEY']` | Yes |
|
120
|
+
| `xcstrings_path` | Path to Localizable.xcstrings file | Auto-detected | No |
|
121
|
+
| `target_language` | Target language code (e.g., "de", "fr") | User prompted | No |
|
122
|
+
| `batch_size` | Number of strings per API call | 20 | No |
|
123
|
+
| `free_api` | Use DeepL Free API endpoint | false | No |
|
124
|
+
| `formality` | Translation formality level | Auto-detected | No |
|
125
|
+
|
126
|
+
### Formality Options
|
127
|
+
|
128
|
+
For supported languages, you can specify:
|
129
|
+
|
130
|
+
- `default` - Standard formality
|
131
|
+
- `more` - More formal language
|
132
|
+
- `less` - Less formal language
|
133
|
+
- `prefer_more` - Formal if available, otherwise default
|
134
|
+
- `prefer_less` - Informal if available, otherwise default
|
135
|
+
|
136
|
+
## Example Output
|
137
|
+
|
138
|
+
```
|
139
|
+
🔍 Found xcstrings file: ./Kilowatt/Localizable.xcstrings
|
140
|
+
✅ DeepL API key validated
|
141
|
+
💾 Backup created: ./Kilowatt/Localizable.xcstrings.backup_20241201_143022
|
142
|
+
|
143
|
+
📋 Available languages for translation:
|
144
|
+
1. German (de): 45.2% translated (127 remaining) [supports formality]
|
145
|
+
2. French (fr): 21.8% translated (220 remaining) [supports formality]
|
146
|
+
3. Spanish (es): 18.1% translated (231 remaining) [supports formality]
|
147
|
+
|
148
|
+
🎭 German supports formality options. Choose style:
|
149
|
+
→ more (formal)
|
150
|
+
|
151
|
+
🔄 Translating from EN to DE
|
152
|
+
📝 Found 127 untranslated strings
|
153
|
+
|
154
|
+
🔄 Translating batch 1/7 (20 strings)...
|
155
|
+
✅ Batch 1 completed (20 strings)
|
156
|
+
🔄 Translating batch 2/7 (20 strings)...
|
157
|
+
✅ Batch 2 completed (20 strings)
|
158
|
+
...
|
159
|
+
|
160
|
+
📝 Updating xcstrings file with 127 translations...
|
161
|
+
💾 Updated xcstrings file
|
162
|
+
✅ Updated xcstrings file is valid JSON
|
163
|
+
|
164
|
+
🎉 Translation completed!
|
165
|
+
📊 Translated 127 strings for German (de)
|
166
|
+
📄 Backup saved: ./Kilowatt/Localizable.xcstrings.backup_20241201_143022
|
167
|
+
🗑️ You can delete the backup after verifying results
|
168
|
+
```
|
169
|
+
|
170
|
+
## Error Handling
|
171
|
+
|
172
|
+
The plugin provides comprehensive error recovery:
|
173
|
+
|
174
|
+
### Rate Limiting
|
175
|
+
|
176
|
+
```
|
177
|
+
⚠️ Rate limit exceeded for batch 3/10
|
178
|
+
1. Wait 60s and retry
|
179
|
+
2. Skip this batch
|
180
|
+
3. Abort translation
|
181
|
+
```
|
182
|
+
|
183
|
+
### Translation Errors
|
184
|
+
|
185
|
+
```
|
186
|
+
❌ Translation error for batch 2/10: Network timeout
|
187
|
+
1. Skip this batch
|
188
|
+
2. Retry batch
|
189
|
+
3. Abort translation
|
190
|
+
```
|
191
|
+
|
192
|
+
### API Quota Issues
|
193
|
+
|
194
|
+
```
|
195
|
+
❌ DeepL quota exceeded. Upgrade your plan or wait for reset.
|
196
|
+
```
|
197
|
+
|
198
|
+
## Shared Values
|
199
|
+
|
200
|
+
The action sets the following shared values for use in other lanes:
|
201
|
+
|
202
|
+
- `TRANSLATE_WITH_DEEPL_TRANSLATED_COUNT` - Number of translated strings
|
203
|
+
- `TRANSLATE_WITH_DEEPL_TARGET_LANGUAGE` - Target language code
|
204
|
+
- `TRANSLATE_WITH_DEEPL_BACKUP_FILE` - Path to backup file
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
lane :translate_and_notify do
|
208
|
+
count = translate_with_deepl(target_language: "de")
|
209
|
+
|
210
|
+
slack(
|
211
|
+
message: "✅ Translated #{count} German strings!",
|
212
|
+
channel: "#localization"
|
213
|
+
)
|
214
|
+
end
|
215
|
+
```
|
216
|
+
|
217
|
+
## Progress Tracking
|
218
|
+
|
219
|
+
The plugin automatically saves translation progress:
|
220
|
+
|
221
|
+
```
|
222
|
+
📈 Found existing progress: 45 strings translated
|
223
|
+
Continue from where you left off?
|
224
|
+
1. Yes, continue
|
225
|
+
2. No, start fresh
|
226
|
+
```
|
227
|
+
|
228
|
+
Progress files are automatically cleaned up after successful completion.
|
229
|
+
|
230
|
+
## Context Support
|
231
|
+
|
232
|
+
When xcstrings files contain comments, they're used as translation context:
|
233
|
+
|
234
|
+
```json
|
235
|
+
{
|
236
|
+
"Hello World": {
|
237
|
+
"comment": "Greeting message shown on app launch",
|
238
|
+
"localizations": { ... }
|
239
|
+
}
|
240
|
+
}
|
241
|
+
```
|
242
|
+
|
243
|
+
This comment becomes context for better translation quality.
|
244
|
+
|
245
|
+
## Requirements
|
246
|
+
|
247
|
+
- Ruby >= 2.6
|
248
|
+
- Fastlane >= 2.0.0
|
249
|
+
- DeepL API account (Free or Pro)
|
250
|
+
|
251
|
+
## Development
|
252
|
+
|
253
|
+
### Setup
|
254
|
+
|
255
|
+
1. Clone the repository
|
256
|
+
2. Run `bundle install`
|
257
|
+
|
258
|
+
### Testing
|
259
|
+
|
260
|
+
#### Unit Tests (RSpec)
|
261
|
+
|
262
|
+
Run the full test suite:
|
263
|
+
|
264
|
+
```bash
|
265
|
+
bundle exec rspec
|
266
|
+
```
|
267
|
+
|
268
|
+
Run specific test files:
|
269
|
+
|
270
|
+
```bash
|
271
|
+
bundle exec rspec spec/translate_with_deepl_action_spec.rb
|
272
|
+
bundle exec rspec spec/language_registry_spec.rb
|
273
|
+
bundle exec rspec spec/deepl_language_mapper_spec.rb
|
274
|
+
```
|
275
|
+
|
276
|
+
#### Code Quality
|
277
|
+
|
278
|
+
Run RuboCop for style checking:
|
279
|
+
|
280
|
+
```bash
|
281
|
+
bundle exec rubocop
|
282
|
+
```
|
283
|
+
|
284
|
+
Auto-fix correctable issues:
|
285
|
+
|
286
|
+
```bash
|
287
|
+
bundle exec rubocop -a
|
288
|
+
```
|
289
|
+
|
290
|
+
#### Manual Testing
|
291
|
+
|
292
|
+
To test the plugin manually with a real project:
|
293
|
+
|
294
|
+
```bash
|
295
|
+
# Export your DeepL API key
|
296
|
+
export DEEPL_AUTH_KEY="your-api-key-here"
|
297
|
+
|
298
|
+
# Test the plugin
|
299
|
+
bundle exec fastlane translate_with_deepl
|
300
|
+
```
|
301
|
+
|
302
|
+
### Requirements
|
303
|
+
|
304
|
+
- Ruby >= 3.4
|
305
|
+
- Fastlane >= 2.0.0
|
306
|
+
- DeepL API account (Free or Pro) for manual testing
|
307
|
+
|
308
|
+
## Issues and Feedback
|
309
|
+
|
310
|
+
For bugs, feature requests, or questions, please [create an issue](https://github.com/yourusername/fastlane-plugin-translate/issues).
|
311
|
+
|
312
|
+
## License
|
313
|
+
|
314
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
315
|
+
|
316
|
+
## About fastlane
|
317
|
+
|
318
|
+
[fastlane](https://fastlane.tools) is the easiest way to automate beta deployments and releases for your iOS and Android apps. To get started with fastlane, check out [fastlane.tools](https://fastlane.tools).
|