better_translate 1.0.0 β 1.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 +4 -4
- data/.rubocop.yml +28 -0
- data/.rubocop_todo.yml +291 -0
- data/CHANGELOG.md +88 -0
- data/README.md +262 -2
- data/RELEASE_NOTES_v1.0.0.md +240 -0
- data/Steepfile +2 -2
- data/docs/implementation/00-overview.md +1 -1
- data/docs/implementation/04-provider_architecture.md +5 -5
- data/lib/better_translate/analyzer/code_scanner.rb +151 -0
- data/lib/better_translate/analyzer/key_scanner.rb +109 -0
- data/lib/better_translate/analyzer/orphan_detector.rb +88 -0
- data/lib/better_translate/analyzer/reporter.rb +155 -0
- data/lib/better_translate/cache.rb +2 -1
- data/lib/better_translate/cli.rb +81 -2
- data/lib/better_translate/configuration.rb +48 -2
- data/lib/better_translate/errors.rb +9 -0
- data/lib/better_translate/json_handler.rb +227 -0
- data/lib/better_translate/providers/anthropic_provider.rb +4 -3
- data/lib/better_translate/providers/chatgpt_provider.rb +2 -1
- data/lib/better_translate/providers/gemini_provider.rb +5 -4
- data/lib/better_translate/railtie.rb +2 -1
- data/lib/better_translate/rate_limiter.rb +4 -1
- data/lib/better_translate/strategies/batch_strategy.rb +1 -1
- data/lib/better_translate/strategies/deep_strategy.rb +1 -1
- data/lib/better_translate/translator.rb +204 -19
- data/lib/better_translate/utils/hash_flattener.rb +2 -2
- data/lib/better_translate/variable_extractor.rb +7 -7
- data/lib/better_translate/version.rb +1 -1
- data/lib/better_translate/yaml_handler.rb +59 -0
- data/lib/better_translate.rb +5 -0
- data/lib/generators/better_translate/analyze/analyze_generator.rb +2 -1
- data/lib/generators/better_translate/install/install_generator.rb +4 -3
- data/lib/generators/better_translate/install/templates/initializer.rb.tt +39 -7
- data/lib/generators/better_translate/translate/translate_generator.rb +2 -1
- data/regenerate_vcr.rb +47 -0
- data/sig/better_translate/configuration.rbs +13 -2
- data/sig/better_translate/errors.rbs +4 -0
- data/sig/better_translate/providers/base_http_provider.rbs +1 -1
- data/sig/better_translate/translator.rbs +12 -1
- data/sig/better_translate/variable_extractor.rbs +1 -1
- data/sig/better_translate/yaml_handler.rbs +6 -0
- data/sig/better_translate.rbs +2 -1
- metadata +9 -1
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://www.ruby-lang.org/en/)
|
|
6
6
|
[](LICENSE.txt)
|
|
7
|
-
[](https://rubygems.org/gems/better_translate)
|
|
8
8
|
|
|
9
9
|
BetterTranslate automatically translates your YAML locale files using cutting-edge AI providers (ChatGPT, Google Gemini, and Anthropic Claude). It's designed for Rails applications but works with any Ruby project that uses YAML-based internationalization.
|
|
10
10
|
|
|
@@ -31,6 +31,14 @@ BetterTranslate automatically translates your YAML locale files using cutting-ed
|
|
|
31
31
|
- π« **Flexible Exclusions**: Global exclusions for all languages + language-specific exclusions for fine-grained control
|
|
32
32
|
- π¨ **Translation Context**: Provide domain-specific context for medical, legal, financial, or technical terminology
|
|
33
33
|
- π **Similarity Analysis**: Built-in Levenshtein distance analyzer to identify similar translations
|
|
34
|
+
- π **Orphan Key Analyzer**: Find unused translation keys in your codebase with comprehensive reports (text, JSON, CSV)
|
|
35
|
+
|
|
36
|
+
### New in v1.1.0 π
|
|
37
|
+
- ποΈ **Provider-Specific Options**: Fine-tune AI behavior with `model`, `temperature`, and `max_tokens`
|
|
38
|
+
- πΎ **Automatic Backups**: Configurable backup rotation before overwriting files (`.bak`, `.bak.1`, `.bak.2`)
|
|
39
|
+
- π¦ **JSON Support**: Full support for JSON locale files (React, Vue, modern JS frameworks)
|
|
40
|
+
- β‘ **Parallel Translation**: Translate multiple languages concurrently with thread-based execution
|
|
41
|
+
- π **Multiple Files**: Translate multiple files with arrays or glob patterns (`**/*.en.yml`)
|
|
34
42
|
|
|
35
43
|
### Development & Quality
|
|
36
44
|
- π§ͺ **Comprehensive Testing**: Unit tests + integration tests with VCR cassettes (18 cassettes, 260KB)
|
|
@@ -160,6 +168,11 @@ BetterTranslate.configure do |config|
|
|
|
160
168
|
config.request_timeout = 30 # seconds
|
|
161
169
|
config.max_retries = 3
|
|
162
170
|
config.retry_delay = 2.0 # seconds
|
|
171
|
+
|
|
172
|
+
# π v1.1.0: Provider-specific options
|
|
173
|
+
config.model = "gpt-5-nano" # Specify model (optional)
|
|
174
|
+
config.temperature = 0.3 # Creativity (0.0-2.0, default: 0.3)
|
|
175
|
+
config.max_tokens = 2000 # Response length limit
|
|
163
176
|
end
|
|
164
177
|
```
|
|
165
178
|
|
|
@@ -195,6 +208,90 @@ end
|
|
|
195
208
|
|
|
196
209
|
Get your API key from [Anthropic Console](https://console.anthropic.com/).
|
|
197
210
|
|
|
211
|
+
### New Features (v1.1.0)
|
|
212
|
+
|
|
213
|
+
#### Automatic Backups
|
|
214
|
+
|
|
215
|
+
Protect your translation files with automatic backup creation:
|
|
216
|
+
|
|
217
|
+
```ruby
|
|
218
|
+
config.create_backup = true # Enable backups (default: true)
|
|
219
|
+
config.max_backups = 5 # Keep up to 5 backup versions
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Backup files are created with rotation:
|
|
223
|
+
- First backup: `it.yml.bak`
|
|
224
|
+
- Second backup: `it.yml.bak.1`
|
|
225
|
+
- Third backup: `it.yml.bak.2`
|
|
226
|
+
- Older backups are automatically deleted
|
|
227
|
+
|
|
228
|
+
#### JSON File Support
|
|
229
|
+
|
|
230
|
+
Translate JSON locale files for modern JavaScript frameworks:
|
|
231
|
+
|
|
232
|
+
```ruby
|
|
233
|
+
# Automatically detects JSON format from file extension
|
|
234
|
+
config.input_file = "config/locales/en.json"
|
|
235
|
+
config.output_folder = "config/locales"
|
|
236
|
+
|
|
237
|
+
# All features work with JSON: backups, incremental mode, exclusions, etc.
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Example JSON file:
|
|
241
|
+
```json
|
|
242
|
+
{
|
|
243
|
+
"en": {
|
|
244
|
+
"common": {
|
|
245
|
+
"greeting": "Hello %{name}"
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### Parallel Translation
|
|
252
|
+
|
|
253
|
+
Translate multiple languages concurrently for faster processing:
|
|
254
|
+
|
|
255
|
+
```ruby
|
|
256
|
+
config.target_languages = [
|
|
257
|
+
{ short_name: "it", name: "Italian" },
|
|
258
|
+
{ short_name: "fr", name: "French" },
|
|
259
|
+
{ short_name: "es", name: "Spanish" },
|
|
260
|
+
{ short_name: "de", name: "German" }
|
|
261
|
+
]
|
|
262
|
+
|
|
263
|
+
config.max_concurrent_requests = 4 # Translate 4 languages at once
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Performance improvement:** With 4 languages and `max_concurrent_requests = 4`, translation time is reduced by ~75% compared to sequential processing.
|
|
267
|
+
|
|
268
|
+
#### Multiple Files Support
|
|
269
|
+
|
|
270
|
+
Translate multiple files in a single run:
|
|
271
|
+
|
|
272
|
+
```ruby
|
|
273
|
+
# Array of specific files
|
|
274
|
+
config.input_files = [
|
|
275
|
+
"config/locales/common.en.yml",
|
|
276
|
+
"config/locales/errors.en.yml",
|
|
277
|
+
"config/locales/admin.en.yml"
|
|
278
|
+
]
|
|
279
|
+
|
|
280
|
+
# Or use glob patterns (recommended)
|
|
281
|
+
config.input_files = "config/locales/**/*.en.yml"
|
|
282
|
+
|
|
283
|
+
# Or combine both approaches
|
|
284
|
+
config.input_files = [
|
|
285
|
+
"config/locales/**/*.en.yml",
|
|
286
|
+
"app/javascript/translations/*.en.json"
|
|
287
|
+
]
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Output files preserve the original structure:
|
|
291
|
+
- `common.en.yml` β `common.it.yml`
|
|
292
|
+
- `errors.en.yml` β `errors.it.yml`
|
|
293
|
+
- `admin/settings.en.yml` β `admin/settings.it.yml`
|
|
294
|
+
|
|
198
295
|
### Language Configuration
|
|
199
296
|
|
|
200
297
|
```ruby
|
|
@@ -444,6 +541,142 @@ Enable detailed logging for debugging:
|
|
|
444
541
|
config.verbose = true
|
|
445
542
|
```
|
|
446
543
|
|
|
544
|
+
## π Orphan Key Analyzer
|
|
545
|
+
|
|
546
|
+
The Orphan Key Analyzer helps you find unused translation keys in your codebase. It scans your YAML locale files and compares them against your actual code usage, generating comprehensive reports.
|
|
547
|
+
|
|
548
|
+
### CLI Usage
|
|
549
|
+
|
|
550
|
+
Find orphan keys from the command line:
|
|
551
|
+
|
|
552
|
+
```bash
|
|
553
|
+
# Basic text report (default)
|
|
554
|
+
better_translate analyze \
|
|
555
|
+
--source config/locales/en.yml \
|
|
556
|
+
--scan-path app/
|
|
557
|
+
|
|
558
|
+
# JSON format (great for CI/CD)
|
|
559
|
+
better_translate analyze \
|
|
560
|
+
--source config/locales/en.yml \
|
|
561
|
+
--scan-path app/ \
|
|
562
|
+
--format json
|
|
563
|
+
|
|
564
|
+
# CSV format (easy to share with team)
|
|
565
|
+
better_translate analyze \
|
|
566
|
+
--source config/locales/en.yml \
|
|
567
|
+
--scan-path app/ \
|
|
568
|
+
--format csv
|
|
569
|
+
|
|
570
|
+
# Save to file
|
|
571
|
+
better_translate analyze \
|
|
572
|
+
--source config/locales/en.yml \
|
|
573
|
+
--scan-path app/ \
|
|
574
|
+
--output orphan_report.txt
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### Sample Output
|
|
578
|
+
|
|
579
|
+
**Text format:**
|
|
580
|
+
```
|
|
581
|
+
============================================================
|
|
582
|
+
Orphan Keys Analysis Report
|
|
583
|
+
============================================================
|
|
584
|
+
|
|
585
|
+
Statistics:
|
|
586
|
+
Total keys: 50
|
|
587
|
+
Used keys: 45
|
|
588
|
+
Orphan keys: 5
|
|
589
|
+
Usage: 90.0%
|
|
590
|
+
|
|
591
|
+
Orphan Keys (5):
|
|
592
|
+
------------------------------------------------------------
|
|
593
|
+
|
|
594
|
+
Key: users.old_message
|
|
595
|
+
Value: This feature was removed
|
|
596
|
+
|
|
597
|
+
Key: products.deprecated_label
|
|
598
|
+
Value: Old Label
|
|
599
|
+
...
|
|
600
|
+
============================================================
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
**JSON format:**
|
|
604
|
+
```json
|
|
605
|
+
{
|
|
606
|
+
"orphans": ["users.old_message", "products.deprecated_label"],
|
|
607
|
+
"orphan_details": {
|
|
608
|
+
"users.old_message": "This feature was removed",
|
|
609
|
+
"products.deprecated_label": "Old Label"
|
|
610
|
+
},
|
|
611
|
+
"orphan_count": 5,
|
|
612
|
+
"total_keys": 50,
|
|
613
|
+
"used_keys": 45,
|
|
614
|
+
"usage_percentage": 90.0
|
|
615
|
+
}
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
### Programmatic Usage
|
|
619
|
+
|
|
620
|
+
Use the analyzer in your Ruby code:
|
|
621
|
+
|
|
622
|
+
```ruby
|
|
623
|
+
# Scan YAML file
|
|
624
|
+
key_scanner = BetterTranslate::Analyzer::KeyScanner.new("config/locales/en.yml")
|
|
625
|
+
all_keys = key_scanner.scan # Returns Hash of all keys
|
|
626
|
+
|
|
627
|
+
# Scan code for used keys
|
|
628
|
+
code_scanner = BetterTranslate::Analyzer::CodeScanner.new("app/")
|
|
629
|
+
used_keys = code_scanner.scan # Returns Set of used keys
|
|
630
|
+
|
|
631
|
+
# Detect orphans
|
|
632
|
+
detector = BetterTranslate::Analyzer::OrphanDetector.new(all_keys, used_keys)
|
|
633
|
+
orphans = detector.detect
|
|
634
|
+
|
|
635
|
+
# Get statistics
|
|
636
|
+
puts "Orphan count: #{detector.orphan_count}"
|
|
637
|
+
puts "Usage: #{detector.usage_percentage}%"
|
|
638
|
+
|
|
639
|
+
# Generate report
|
|
640
|
+
reporter = BetterTranslate::Analyzer::Reporter.new(
|
|
641
|
+
orphans: orphans,
|
|
642
|
+
orphan_details: detector.orphan_details,
|
|
643
|
+
total_keys: all_keys.size,
|
|
644
|
+
used_keys: used_keys.size,
|
|
645
|
+
usage_percentage: detector.usage_percentage,
|
|
646
|
+
format: :text
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
puts reporter.generate
|
|
650
|
+
reporter.save_to_file("orphan_report.txt")
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
### Supported Translation Patterns
|
|
654
|
+
|
|
655
|
+
The analyzer recognizes these i18n patterns:
|
|
656
|
+
|
|
657
|
+
- `t('key')` - Rails short form
|
|
658
|
+
- `t("key")` - Rails short form with double quotes
|
|
659
|
+
- `I18n.t(:key)` - Symbol syntax
|
|
660
|
+
- `I18n.t('key')` - String syntax
|
|
661
|
+
- `I18n.translate('key')` - Full method name
|
|
662
|
+
- `<%= t('key') %>` - ERB templates
|
|
663
|
+
- `I18n.t('key', param: value)` - With parameters
|
|
664
|
+
|
|
665
|
+
**Nested keys:**
|
|
666
|
+
```yaml
|
|
667
|
+
en:
|
|
668
|
+
users:
|
|
669
|
+
profile:
|
|
670
|
+
title: "Profile" # Detected as: users.profile.title
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
**Use cases:**
|
|
674
|
+
- Clean up unused translations before deployment
|
|
675
|
+
- Identify dead code after refactoring
|
|
676
|
+
- Reduce locale file size
|
|
677
|
+
- Improve translation maintenance
|
|
678
|
+
- Generate reports for translation teams
|
|
679
|
+
|
|
447
680
|
## π§ͺ Development & Testing
|
|
448
681
|
|
|
449
682
|
BetterTranslate includes comprehensive testing infrastructure with **unit tests**, **integration tests**, and a **Rails dummy app** for realistic testing.
|
|
@@ -685,7 +918,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/alessi
|
|
|
685
918
|
5. **HTTP Client**: Use Faraday for all HTTP requests (never Net::HTTP or HTTParty)
|
|
686
919
|
6. **VCR Cassettes**: Record integration tests with real API responses for CI/CD
|
|
687
920
|
|
|
688
|
-
### Workflow
|
|
921
|
+
### Development Workflow
|
|
689
922
|
|
|
690
923
|
```bash
|
|
691
924
|
# 1. Clone and setup
|
|
@@ -714,6 +947,33 @@ git push origin my-feature
|
|
|
714
947
|
# 7. Create a Pull Request
|
|
715
948
|
```
|
|
716
949
|
|
|
950
|
+
### Release Workflow
|
|
951
|
+
|
|
952
|
+
Releases are automated via GitHub Actions:
|
|
953
|
+
|
|
954
|
+
```bash
|
|
955
|
+
# 1. Update version
|
|
956
|
+
vim lib/better_translate/version.rb # VERSION = "1.0.1"
|
|
957
|
+
|
|
958
|
+
# 2. Update CHANGELOG
|
|
959
|
+
vim CHANGELOG.md
|
|
960
|
+
|
|
961
|
+
# 3. Commit and tag
|
|
962
|
+
git add -A
|
|
963
|
+
git commit -m "chore: Release v1.0.1"
|
|
964
|
+
git tag v1.0.1
|
|
965
|
+
git push origin main
|
|
966
|
+
git push origin v1.0.1
|
|
967
|
+
|
|
968
|
+
# 4. GitHub Actions automatically:
|
|
969
|
+
# β
Runs tests
|
|
970
|
+
# β
Builds gem
|
|
971
|
+
# β
Publishes to RubyGems.org
|
|
972
|
+
# β
Creates GitHub Release
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
**Setup**: See [`.github/RUBYGEMS_SETUP.md`](.github/RUBYGEMS_SETUP.md) for configuring RubyGems trusted publishing (no API keys needed!).
|
|
976
|
+
|
|
717
977
|
## π License
|
|
718
978
|
|
|
719
979
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# BetterTranslate v1.0.0 - Complete Release π
|
|
2
|
+
|
|
3
|
+
**AI-powered YAML locale file translator for Rails and Ruby projects**
|
|
4
|
+
|
|
5
|
+
This is the first complete release of BetterTranslate, featuring multi-provider AI translation support, comprehensive testing infrastructure, and production-ready features.
|
|
6
|
+
|
|
7
|
+
## π Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Install the gem
|
|
11
|
+
gem install better_translate
|
|
12
|
+
|
|
13
|
+
# Try the interactive demo
|
|
14
|
+
git clone https://github.com/alessiobussolari/better_translate.git
|
|
15
|
+
cd better_translate
|
|
16
|
+
bundle install
|
|
17
|
+
export OPENAI_API_KEY=your_key_here
|
|
18
|
+
ruby spec/dummy/demo_translation.rb
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## β¨ Key Features
|
|
22
|
+
|
|
23
|
+
### Multi-Provider AI Support
|
|
24
|
+
- **ChatGPT** (GPT-5-nano) - Fast, excellent quality
|
|
25
|
+
- **Google Gemini** (gemini-2.0-flash-exp) - Very fast, cost-effective
|
|
26
|
+
- **Anthropic Claude** (Claude 3.5) - Excellent quality (coming soon)
|
|
27
|
+
|
|
28
|
+
### Translation Features
|
|
29
|
+
- π― **Smart Strategies**: Automatic selection between deep (<50 strings) and batch (β₯50 strings) translation
|
|
30
|
+
- β‘ **Intelligent Caching**: LRU cache with optional TTL reduces API costs
|
|
31
|
+
- π **Translation Modes**: Override (replace all) or Incremental (merge with existing)
|
|
32
|
+
- π« **Flexible Exclusions**: Global + language-specific exclusion rules
|
|
33
|
+
- π¨ **Domain Context**: Provide context for medical, legal, financial, or technical terminology
|
|
34
|
+
- π **Similarity Analysis**: Built-in Levenshtein distance analyzer
|
|
35
|
+
|
|
36
|
+
### Production-Ready Quality
|
|
37
|
+
- π§ͺ **259 Tests** passing with 90%+ coverage
|
|
38
|
+
- π¬ **VCR Integration**: 18 cassettes (260KB) with real API responses
|
|
39
|
+
- ποΈ **Rails Dummy App**: Interactive demo with real translations
|
|
40
|
+
- π **Complete Documentation**: README, YARD docs, usage guides
|
|
41
|
+
- π‘οΈ **Type-Safe**: RBS signatures with Steep type checking
|
|
42
|
+
- β
**RuboCop Compliant**: Clean, consistent code style
|
|
43
|
+
|
|
44
|
+
### Rails Integration
|
|
45
|
+
```bash
|
|
46
|
+
# Generate initializer
|
|
47
|
+
rails generate better_translate:install
|
|
48
|
+
|
|
49
|
+
# Configure in config/initializers/better_translate.rb
|
|
50
|
+
BetterTranslate.configure do |config|
|
|
51
|
+
config.provider = :chatgpt
|
|
52
|
+
config.openai_key = ENV["OPENAI_API_KEY"]
|
|
53
|
+
config.source_language = "en"
|
|
54
|
+
config.target_languages = [
|
|
55
|
+
{ short_name: "it", name: "Italian" },
|
|
56
|
+
{ short_name: "fr", name: "French" }
|
|
57
|
+
]
|
|
58
|
+
config.input_file = "config/locales/en.yml"
|
|
59
|
+
config.output_folder = "config/locales"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Translate all files
|
|
63
|
+
BetterTranslate.translate_all
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## π Documentation
|
|
67
|
+
|
|
68
|
+
- **[README.md](README.md)** - Complete feature documentation
|
|
69
|
+
- **[USAGE_GUIDE.md](spec/dummy/USAGE_GUIDE.md)** - Interactive demo guide
|
|
70
|
+
- **[VCR Testing Guide](spec/integration/README.md)** - Integration testing with VCR
|
|
71
|
+
- **[CLAUDE.md](CLAUDE.md)** - Developer guide for contributors
|
|
72
|
+
- **[CHANGELOG.md](CHANGELOG.md)** - Detailed changelog
|
|
73
|
+
|
|
74
|
+
## π¬ Demo Output
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
# en.yml (input)
|
|
78
|
+
en:
|
|
79
|
+
hello: "Hello"
|
|
80
|
+
users:
|
|
81
|
+
greeting: "Hello %{name}"
|
|
82
|
+
messages:
|
|
83
|
+
success: "Operation completed successfully"
|
|
84
|
+
|
|
85
|
+
# it.yml (generated by BetterTranslate)
|
|
86
|
+
it:
|
|
87
|
+
hello: "Ciao"
|
|
88
|
+
users:
|
|
89
|
+
greeting: "Ciao %{name}" # β
Variables preserved!
|
|
90
|
+
messages:
|
|
91
|
+
success: "Operazione completata con successo"
|
|
92
|
+
|
|
93
|
+
# fr.yml (generated by BetterTranslate)
|
|
94
|
+
fr:
|
|
95
|
+
hello: "Bonjour"
|
|
96
|
+
users:
|
|
97
|
+
greeting: "Bonjour %{name}" # β
Variables preserved!
|
|
98
|
+
messages:
|
|
99
|
+
success: "OpΓ©ration rΓ©ussie"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## ποΈ Architecture Highlights
|
|
103
|
+
|
|
104
|
+
### Provider Architecture
|
|
105
|
+
```
|
|
106
|
+
BaseHttpProvider (abstract)
|
|
107
|
+
βββ ChatGPTProvider (GPT-5-nano, temp=1.0)
|
|
108
|
+
βββ GeminiProvider (gemini-2.0-flash-exp)
|
|
109
|
+
βββ AnthropicProvider (coming soon)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**BaseHttpProvider features:**
|
|
113
|
+
- Faraday-based HTTP communication
|
|
114
|
+
- Retry logic with exponential backoff (3 attempts)
|
|
115
|
+
- Rate limiting (0.5s between requests, thread-safe)
|
|
116
|
+
- Configurable timeouts (default: 30s)
|
|
117
|
+
|
|
118
|
+
### Core Components
|
|
119
|
+
- **Configuration**: Type-safe config with validation
|
|
120
|
+
- **Cache**: Thread-safe LRU cache with optional TTL
|
|
121
|
+
- **RateLimiter**: Thread-safe request throttling
|
|
122
|
+
- **Validator**: Comprehensive input validation
|
|
123
|
+
- **HashFlattener**: Nested YAML β flat structure conversion
|
|
124
|
+
- **VariableExtractor**: Preserves `%{name}` and `%<name>s` placeholders
|
|
125
|
+
- **ProgressTracker**: Real-time translation progress
|
|
126
|
+
|
|
127
|
+
### Error Hierarchy
|
|
128
|
+
```
|
|
129
|
+
BetterTranslate::Error (base)
|
|
130
|
+
βββ ConfigurationError
|
|
131
|
+
βββ ValidationError
|
|
132
|
+
βββ TranslationError
|
|
133
|
+
βββ ProviderError
|
|
134
|
+
βββ ApiError
|
|
135
|
+
βββ RateLimitError
|
|
136
|
+
βββ FileError
|
|
137
|
+
βββ YamlError
|
|
138
|
+
βββ ProviderNotFoundError
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## π§ͺ Testing Infrastructure
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
spec/
|
|
145
|
+
βββ better_translate/ # 259 unit tests
|
|
146
|
+
β βββ cache_spec.rb
|
|
147
|
+
β βββ providers/
|
|
148
|
+
β βββ ...
|
|
149
|
+
βββ integration/ # VCR integration tests
|
|
150
|
+
β βββ chatgpt_integration_spec.rb
|
|
151
|
+
β βββ gemini_integration_spec.rb
|
|
152
|
+
β βββ rails_dummy_app_spec.rb
|
|
153
|
+
βββ dummy/ # Rails dummy app
|
|
154
|
+
β βββ demo_translation.rb # π Interactive demo
|
|
155
|
+
β βββ config/locales/
|
|
156
|
+
β βββ en.yml # Source (16 keys)
|
|
157
|
+
β βββ it.yml # Generated (519 bytes)
|
|
158
|
+
β βββ fr.yml # Generated (511 bytes)
|
|
159
|
+
βββ vcr_cassettes/ # 18 cassettes (260KB)
|
|
160
|
+
βββ chatgpt/ (7)
|
|
161
|
+
βββ gemini/ (7)
|
|
162
|
+
βββ rails/ (4)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## π¦ Package Details
|
|
166
|
+
|
|
167
|
+
- **Gem Name**: `better_translate`
|
|
168
|
+
- **Version**: `1.0.0`
|
|
169
|
+
- **Size**: 83KB
|
|
170
|
+
- **Files**: 152 files
|
|
171
|
+
- **Lines of Code**: 23,654
|
|
172
|
+
- **Ruby Version**: >= 3.0.0
|
|
173
|
+
- **Dependencies**: Faraday ~> 2.0 (only runtime dependency)
|
|
174
|
+
|
|
175
|
+
## π§ Configuration Examples
|
|
176
|
+
|
|
177
|
+
### Medical Terminology
|
|
178
|
+
```ruby
|
|
179
|
+
config.translation_context = "Medical terminology for healthcare applications"
|
|
180
|
+
config.target_languages = [{ short_name: "es", name: "Spanish" }]
|
|
181
|
+
# "patient" β "paciente", "diagnosis" β "diagnΓ³stico"
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### E-commerce with Exclusions
|
|
185
|
+
```ruby
|
|
186
|
+
config.global_exclusions = ["brand_name", "sku"] # Never translate
|
|
187
|
+
config.exclusions_per_language = {
|
|
188
|
+
"de" => ["legal.terms"], # German legal terms manually translated
|
|
189
|
+
"fr" => ["marketing.slogan"] # French slogan crafted by marketing
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Incremental Mode
|
|
194
|
+
```ruby
|
|
195
|
+
config.translation_mode = :incremental
|
|
196
|
+
# Only translates missing keys, preserves manual corrections
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## π¦ Performance
|
|
200
|
+
|
|
201
|
+
**Demo Results** (16 keys, 2 languages):
|
|
202
|
+
- Italian: 16 strings in 1m 6s (~4s per string)
|
|
203
|
+
- French: 16 strings in 1m 7s (~4s per string)
|
|
204
|
+
- **Total**: 32 translations in 2m 13s
|
|
205
|
+
|
|
206
|
+
**With Caching Enabled**:
|
|
207
|
+
- Subsequent runs: < 1s (cache hits)
|
|
208
|
+
- API costs reduced by ~90%
|
|
209
|
+
|
|
210
|
+
## π€ Contributing
|
|
211
|
+
|
|
212
|
+
Contributions are welcome! Please see [CLAUDE.md](CLAUDE.md) for development guidelines.
|
|
213
|
+
|
|
214
|
+
**Development Requirements**:
|
|
215
|
+
1. TDD (Test-Driven Development) - Write tests first
|
|
216
|
+
2. YARD Documentation - Document all public methods
|
|
217
|
+
3. RuboCop Compliance - Clean code style
|
|
218
|
+
4. VCR Cassettes - Record integration tests
|
|
219
|
+
|
|
220
|
+
## π License
|
|
221
|
+
|
|
222
|
+
MIT License - See [LICENSE.txt](LICENSE.txt)
|
|
223
|
+
|
|
224
|
+
## π Acknowledgments
|
|
225
|
+
|
|
226
|
+
Built with:
|
|
227
|
+
- **Faraday** - HTTP client
|
|
228
|
+
- **VCR** - HTTP interaction recording
|
|
229
|
+
- **RSpec** - Testing framework
|
|
230
|
+
- **RuboCop** - Code linting
|
|
231
|
+
- **Steep** - Type checking
|
|
232
|
+
- **YARD** - Documentation
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
**Made with β€οΈ by [Alessio Bussolari](https://github.com/alessiobussolari)**
|
|
237
|
+
|
|
238
|
+
**Powered by Claude Code** π€
|
|
239
|
+
|
|
240
|
+
[Report Bug](https://github.com/alessiobussolari/better_translate/issues) Β· [Request Feature](https://github.com/alessiobussolari/better_translate/issues) Β· [Documentation](https://github.com/alessiobussolari/better_translate)
|
data/Steepfile
CHANGED
|
@@ -14,7 +14,7 @@ BetterTranslate is a powerful Ruby gem designed to automatically translate YAML
|
|
|
14
14
|
|
|
15
15
|
### Key Features
|
|
16
16
|
|
|
17
|
-
- **Multiple AI Providers**: ChatGPT (GPT-5-nano), Google Gemini (gemini-2.
|
|
17
|
+
- **Multiple AI Providers**: ChatGPT (GPT-5-nano), Google Gemini (gemini-2.5-flash-lite), Anthropic Claude (claude-haiku-4-5)
|
|
18
18
|
- **Smart Translation Strategies**: Automatic selection between Deep (< 50 strings) and Batch (β₯ 50 strings) processing
|
|
19
19
|
- **Intelligent Caching**: LRU cache with configurable capacity and TTL
|
|
20
20
|
- **Rails Integration**: 3 generators (install, translate, analyze)
|
|
@@ -331,10 +331,10 @@ module BetterTranslate
|
|
|
331
331
|
module Providers
|
|
332
332
|
# Google Gemini translation provider
|
|
333
333
|
#
|
|
334
|
-
# Uses gemini-2.
|
|
334
|
+
# Uses gemini-2.5-flash-lite model
|
|
335
335
|
class GeminiProvider < BaseHttpProvider
|
|
336
|
-
API_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.
|
|
337
|
-
MODEL = "gemini-2.
|
|
336
|
+
API_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent"
|
|
337
|
+
MODEL = "gemini-2.5-flash-lite"
|
|
338
338
|
|
|
339
339
|
# Translate a single text
|
|
340
340
|
#
|
|
@@ -431,10 +431,10 @@ module BetterTranslate
|
|
|
431
431
|
module Providers
|
|
432
432
|
# Anthropic Claude translation provider
|
|
433
433
|
#
|
|
434
|
-
# Uses claude-
|
|
434
|
+
# Uses claude-haiku-4-5 model
|
|
435
435
|
class AnthropicProvider < BaseHttpProvider
|
|
436
436
|
API_URL = "https://api.anthropic.com/v1/messages"
|
|
437
|
-
MODEL = "claude-
|
|
437
|
+
MODEL = "claude-haiku-4-5"
|
|
438
438
|
API_VERSION = "2023-06-01"
|
|
439
439
|
|
|
440
440
|
# Translate a single text
|