better_translate 1.0.0.1 โ†’ 1.1.1

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +28 -0
  3. data/.rubocop_todo.yml +291 -0
  4. data/CHANGELOG.md +88 -0
  5. data/CLAUDE.md +12 -7
  6. data/CONTRIBUTING.md +432 -0
  7. data/README.md +240 -1
  8. data/Rakefile +14 -1
  9. data/SECURITY.md +160 -0
  10. data/Steepfile +0 -1
  11. data/brakeman.yml +37 -0
  12. data/codecov.yml +34 -0
  13. data/lib/better_translate/analyzer/code_scanner.rb +149 -0
  14. data/lib/better_translate/analyzer/key_scanner.rb +109 -0
  15. data/lib/better_translate/analyzer/orphan_detector.rb +91 -0
  16. data/lib/better_translate/analyzer/reporter.rb +155 -0
  17. data/lib/better_translate/cli.rb +81 -2
  18. data/lib/better_translate/configuration.rb +76 -3
  19. data/lib/better_translate/errors.rb +9 -0
  20. data/lib/better_translate/json_handler.rb +227 -0
  21. data/lib/better_translate/translator.rb +205 -23
  22. data/lib/better_translate/version.rb +1 -1
  23. data/lib/better_translate/yaml_handler.rb +59 -0
  24. data/lib/better_translate.rb +7 -0
  25. data/lib/generators/better_translate/install/install_generator.rb +2 -2
  26. data/lib/generators/better_translate/install/templates/initializer.rb.tt +22 -34
  27. data/lib/generators/better_translate/translate/translate_generator.rb +65 -46
  28. data/lib/tasks/better_translate.rake +62 -45
  29. data/sig/better_translate/analyzer/code_scanner.rbs +59 -0
  30. data/sig/better_translate/analyzer/key_scanner.rbs +40 -0
  31. data/sig/better_translate/analyzer/orphan_detector.rbs +43 -0
  32. data/sig/better_translate/analyzer/reporter.rbs +70 -0
  33. data/sig/better_translate/cli.rbs +2 -0
  34. data/sig/better_translate/configuration.rbs +6 -0
  35. data/sig/better_translate/errors.rbs +4 -0
  36. data/sig/better_translate/json_handler.rbs +65 -0
  37. data/sig/better_translate/progress_tracker.rbs +1 -1
  38. data/sig/better_translate/translator.rbs +12 -1
  39. data/sig/better_translate/yaml_handler.rbs +6 -0
  40. data/sig/better_translate.rbs +4 -0
  41. data/sig/csv.rbs +16 -0
  42. metadata +32 -3
  43. data/regenerate_vcr.rb +0 -47
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,432 @@
1
+ # Contributing to BetterTranslate
2
+
3
+ First off, thank you for considering contributing to BetterTranslate! ๐ŸŽ‰
4
+
5
+ It's people like you that make BetterTranslate such a great tool. We welcome contributions from everyone, whether you're fixing a typo or implementing a major feature.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Code of Conduct](#code-of-conduct)
10
+ - [Getting Started](#getting-started)
11
+ - [Development Workflow](#development-workflow)
12
+ - [Testing](#testing)
13
+ - [Code Style](#code-style)
14
+ - [Commit Messages](#commit-messages)
15
+ - [Pull Requests](#pull-requests)
16
+ - [Reporting Bugs](#reporting-bugs)
17
+ - [Suggesting Features](#suggesting-features)
18
+
19
+ ## Code of Conduct
20
+
21
+ This project and everyone participating in it is governed by our [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.
22
+
23
+ ## Getting Started
24
+
25
+ ### Prerequisites
26
+
27
+ - Ruby >= 3.0.0
28
+ - Bundler
29
+ - Git
30
+
31
+ ### Fork and Clone
32
+
33
+ 1. Fork the repository on GitHub
34
+ 2. Clone your fork locally:
35
+ ```bash
36
+ git clone https://github.com/YOUR_USERNAME/better_translate.git
37
+ cd better_translate
38
+ ```
39
+
40
+ 3. Add the upstream repository:
41
+ ```bash
42
+ git remote add upstream https://github.com/alessiobussolari/better_translate.git
43
+ ```
44
+
45
+ ### Install Dependencies
46
+
47
+ ```bash
48
+ bundle install
49
+ ```
50
+
51
+ ### Set Up Environment
52
+
53
+ 1. Copy the example environment file:
54
+ ```bash
55
+ cp .env.example .env
56
+ ```
57
+
58
+ 2. Add your API keys (optional, only needed for integration tests):
59
+ ```env
60
+ OPENAI_API_KEY=sk-...
61
+ GEMINI_API_KEY=...
62
+ ANTHROPIC_API_KEY=sk-ant-...
63
+ ```
64
+
65
+ ## Development Workflow
66
+
67
+ ### 1. Create a Branch
68
+
69
+ Always create a new branch for your work:
70
+
71
+ ```bash
72
+ git checkout -b feature/your-feature-name
73
+ # or
74
+ git checkout -b fix/your-bug-fix
75
+ ```
76
+
77
+ ### 2. Make Your Changes
78
+
79
+ - Write clean, readable code
80
+ - Follow the existing code style
81
+ - Add tests for new features
82
+ - Update documentation as needed
83
+
84
+ ### 3. Run Tests
85
+
86
+ Before committing, make sure all tests pass:
87
+
88
+ ```bash
89
+ # Run all tests
90
+ bundle exec rake
91
+
92
+ # Or run individual checks:
93
+ bundle exec rake spec # Tests
94
+ bundle exec rake rubocop # Linting
95
+ bundle exec rake steep # Type checking
96
+ bundle exec rake brakeman # Security scan
97
+ ```
98
+
99
+ ### 4. Commit Your Changes
100
+
101
+ ```bash
102
+ git add .
103
+ git commit -m "feat: Add awesome feature"
104
+ ```
105
+
106
+ See [Commit Messages](#commit-messages) for guidelines.
107
+
108
+ ### 5. Push and Create PR
109
+
110
+ ```bash
111
+ git push origin feature/your-feature-name
112
+ ```
113
+
114
+ Then create a Pull Request on GitHub.
115
+
116
+ ## Testing
117
+
118
+ ### Test Structure
119
+
120
+ - **Unit Tests**: `spec/better_translate/`
121
+ - Fast, no API calls
122
+ - Use WebMock for HTTP stubs
123
+
124
+ - **Integration Tests**: `spec/integration/`
125
+ - Real API interactions via VCR
126
+ - Require API keys for first run
127
+ - Subsequent runs use recorded cassettes
128
+
129
+ ### Running Tests
130
+
131
+ ```bash
132
+ # All tests
133
+ bundle exec rspec
134
+
135
+ # Only unit tests (fast)
136
+ bundle exec rspec spec/better_translate/
137
+
138
+ # Only integration tests
139
+ bundle exec rspec spec/integration/ --tag integration
140
+
141
+ # Specific file
142
+ bundle exec rspec spec/better_translate/translator_spec.rb
143
+
144
+ # Specific line
145
+ bundle exec rspec spec/better_translate/translator_spec.rb:42
146
+ ```
147
+
148
+ ### Writing Tests
149
+
150
+ **We follow Test-Driven Development (TDD)**:
151
+
152
+ 1. **RED**: Write a failing test
153
+ 2. **GREEN**: Write minimum code to pass
154
+ 3. **REFACTOR**: Clean up code
155
+
156
+ Example:
157
+
158
+ ```ruby
159
+ RSpec.describe MyNewFeature do
160
+ describe "#awesome_method" do
161
+ it "does something awesome" do
162
+ feature = MyNewFeature.new
163
+ result = feature.awesome_method
164
+
165
+ expect(result).to eq("awesome")
166
+ end
167
+ end
168
+ end
169
+ ```
170
+
171
+ ### Test Coverage
172
+
173
+ We maintain **93%+ test coverage**. New code should include tests:
174
+
175
+ ```bash
176
+ # Check coverage
177
+ bundle exec rspec
178
+ # View coverage report: open coverage/index.html
179
+ ```
180
+
181
+ ## Code Style
182
+
183
+ ### RuboCop
184
+
185
+ We use RuboCop for code style enforcement:
186
+
187
+ ```bash
188
+ # Check style
189
+ bundle exec rubocop
190
+
191
+ # Auto-fix issues
192
+ bundle exec rubocop -a
193
+ ```
194
+
195
+ ### Key Guidelines
196
+
197
+ - Use double quotes for strings
198
+ - 2 spaces for indentation (no tabs)
199
+ - Maximum line length: 120 characters
200
+ - Frozen string literals at top of files: `# frozen_string_literal: true`
201
+ - YARD documentation for public methods
202
+
203
+ ### YARD Documentation
204
+
205
+ All public methods must have YARD documentation:
206
+
207
+ ```ruby
208
+ # Translates text to target language
209
+ #
210
+ # @param text [String] The text to translate
211
+ # @param lang [String] Target language code (e.g., "it", "fr")
212
+ # @return [String] Translated text
213
+ # @raise [ValidationError] If input is invalid
214
+ #
215
+ # @example
216
+ # translate("Hello", "it") #=> "Ciao"
217
+ #
218
+ def translate(text, lang)
219
+ # ...
220
+ end
221
+ ```
222
+
223
+ ### Type Checking
224
+
225
+ We use Steep for static type checking:
226
+
227
+ ```bash
228
+ # Run type checker
229
+ bundle exec steep check
230
+
231
+ # Check specific file
232
+ bundle exec steep check lib/better_translate/translator.rb
233
+ ```
234
+
235
+ Type signatures go in `sig/` directory (RBS format).
236
+
237
+ ## Commit Messages
238
+
239
+ We follow the [Conventional Commits](https://www.conventionalcommits.org/) specification:
240
+
241
+ ### Format
242
+
243
+ ```
244
+ <type>(<scope>): <subject>
245
+
246
+ <body>
247
+
248
+ <footer>
249
+ ```
250
+
251
+ ### Types
252
+
253
+ - `feat`: New feature
254
+ - `fix`: Bug fix
255
+ - `docs`: Documentation changes
256
+ - `style`: Code style changes (formatting, no logic change)
257
+ - `refactor`: Code refactoring
258
+ - `test`: Adding or updating tests
259
+ - `chore`: Maintenance tasks
260
+
261
+ ### Examples
262
+
263
+ ```bash
264
+ # Good commits
265
+ git commit -m "feat: Add support for JSON locale files"
266
+ git commit -m "fix: Handle nil values in translations"
267
+ git commit -m "docs: Update README with new examples"
268
+ git commit -m "test: Add coverage for edge cases"
269
+
270
+ # With scope
271
+ git commit -m "feat(cli): Add --dry-run flag"
272
+ git commit -m "fix(cache): Fix TTL expiration bug"
273
+ ```
274
+
275
+ ### Multi-line Commits
276
+
277
+ For complex changes:
278
+
279
+ ```
280
+ feat: Add parallel translation support
281
+
282
+ - Implement thread-based concurrent execution
283
+ - Add max_concurrent_requests configuration
284
+ - Include progress tracking for parallel operations
285
+
286
+ Closes #42
287
+ ```
288
+
289
+ ## Pull Requests
290
+
291
+ ### Before Submitting
292
+
293
+ - [ ] Tests pass: `bundle exec rake`
294
+ - [ ] Code follows style guide
295
+ - [ ] YARD documentation added for public methods
296
+ - [ ] CHANGELOG.md updated (for notable changes)
297
+ - [ ] README.md updated (if needed)
298
+
299
+ ### PR Title
300
+
301
+ Use conventional commit format:
302
+
303
+ ```
304
+ feat: Add awesome feature
305
+ fix: Resolve critical bug
306
+ docs: Improve installation guide
307
+ ```
308
+
309
+ ### PR Description Template
310
+
311
+ ```markdown
312
+ ## Description
313
+ Brief description of changes
314
+
315
+ ## Type of Change
316
+ - [ ] Bug fix
317
+ - [ ] New feature
318
+ - [ ] Breaking change
319
+ - [ ] Documentation update
320
+
321
+ ## Testing
322
+ How has this been tested?
323
+
324
+ ## Checklist
325
+ - [ ] Tests pass locally
326
+ - [ ] Tests added for new features
327
+ - [ ] Documentation updated
328
+ - [ ] No RuboCop offenses
329
+ - [ ] No Brakeman warnings
330
+ ```
331
+
332
+ ### Review Process
333
+
334
+ 1. Automated checks run (CI/CD)
335
+ 2. Maintainer reviews code
336
+ 3. Address feedback if needed
337
+ 4. Maintainer merges PR
338
+
339
+ ## Reporting Bugs
340
+
341
+ ### Before Submitting
342
+
343
+ - Check existing issues
344
+ - Try latest version
345
+ - Gather reproduction steps
346
+
347
+ ### Bug Report Template
348
+
349
+ ```markdown
350
+ **Describe the bug**
351
+ Clear description of the bug
352
+
353
+ **To Reproduce**
354
+ Steps to reproduce:
355
+ 1. ...
356
+ 2. ...
357
+ 3. ...
358
+
359
+ **Expected behavior**
360
+ What you expected to happen
361
+
362
+ **Actual behavior**
363
+ What actually happened
364
+
365
+ **Environment**
366
+ - Ruby version: [e.g., 3.3.4]
367
+ - BetterTranslate version: [e.g., 1.1.0]
368
+ - OS: [e.g., macOS, Ubuntu]
369
+
370
+ **Additional context**
371
+ Any other relevant information
372
+ ```
373
+
374
+ ## Suggesting Features
375
+
376
+ We love feature suggestions! Open an issue with:
377
+
378
+ ```markdown
379
+ **Feature Description**
380
+ Clear description of the feature
381
+
382
+ **Use Case**
383
+ Why is this feature needed?
384
+
385
+ **Proposed Solution**
386
+ How should it work?
387
+
388
+ **Alternatives Considered**
389
+ Other approaches you've thought about
390
+
391
+ **Additional Context**
392
+ Screenshots, mockups, examples, etc.
393
+ ```
394
+
395
+ ## Development Commands
396
+
397
+ ```bash
398
+ # Run all checks
399
+ bundle exec rake
400
+
401
+ # Individual checks
402
+ bundle exec rake spec # Tests (541 examples)
403
+ bundle exec rake rubocop # Linting
404
+ bundle exec rake steep # Type checking
405
+ bundle exec rake brakeman # Security scan
406
+
407
+ # Code quality
408
+ bundle exec rubocop -a # Auto-fix style issues
409
+ bundle exec yard doc # Generate documentation
410
+ bundle exec bundler-audit # Check dependencies
411
+
412
+ # Interactive console
413
+ bin/console
414
+
415
+ # Demo app
416
+ ruby spec/dummy/demo_translation.rb
417
+ ```
418
+
419
+ ## Questions?
420
+
421
+ Feel free to:
422
+ - Open an issue
423
+ - Start a discussion
424
+ - Email: alessio.bussolari@pandev.it
425
+
426
+ ## License
427
+
428
+ By contributing, you agree that your contributions will be licensed under the MIT License.
429
+
430
+ ---
431
+
432
+ Thank you for contributing to BetterTranslate! ๐Ÿš€
data/README.md CHANGED
@@ -2,9 +2,15 @@
2
2
 
3
3
  > AI-powered YAML locale file translator for Rails and Ruby projects
4
4
 
5
+ [![CI](https://github.com/alessiobussolari/better_translate/actions/workflows/main.yml/badge.svg)](https://github.com/alessiobussolari/better_translate/actions/workflows/main.yml)
6
+ [![codecov](https://codecov.io/gh/alessiobussolari/better_translate/branch/main/graph/badge.svg)](https://codecov.io/gh/alessiobussolari/better_translate)
7
+ [![Gem Version](https://badge.fury.io/rb/better_translate.svg)](https://badge.fury.io/rb/better_translate)
8
+ [![Downloads](https://img.shields.io/gem/dt/better_translate)](https://rubygems.org/gems/better_translate)
5
9
  [![Ruby Version](https://img.shields.io/badge/ruby-%3E%3D%203.0.0-ruby.svg)](https://www.ruby-lang.org/en/)
6
10
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.txt)
7
- [![Gem Version](https://img.shields.io/badge/version-1.0.0-green.svg)](https://rubygems.org/gems/better_translate)
11
+ [![Security](https://img.shields.io/badge/security-brakeman-green)](https://brakemanscanner.org/)
12
+ [![Type Check](https://img.shields.io/badge/types-steep-blue)](https://github.com/soutaro/steep)
13
+ [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/alessiobussolari/better_translate/graphs/commit-activity)
8
14
 
9
15
  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
16
 
@@ -31,6 +37,14 @@ BetterTranslate automatically translates your YAML locale files using cutting-ed
31
37
  - ๐Ÿšซ **Flexible Exclusions**: Global exclusions for all languages + language-specific exclusions for fine-grained control
32
38
  - ๐ŸŽจ **Translation Context**: Provide domain-specific context for medical, legal, financial, or technical terminology
33
39
  - ๐Ÿ“Š **Similarity Analysis**: Built-in Levenshtein distance analyzer to identify similar translations
40
+ - ๐Ÿ” **Orphan Key Analyzer**: Find unused translation keys in your codebase with comprehensive reports (text, JSON, CSV)
41
+
42
+ ### New in v1.1.0 ๐ŸŽ‰
43
+ - ๐ŸŽ›๏ธ **Provider-Specific Options**: Fine-tune AI behavior with `model`, `temperature`, and `max_tokens`
44
+ - ๐Ÿ’พ **Automatic Backups**: Configurable backup rotation before overwriting files (`.bak`, `.bak.1`, `.bak.2`)
45
+ - ๐Ÿ“ฆ **JSON Support**: Full support for JSON locale files (React, Vue, modern JS frameworks)
46
+ - โšก **Parallel Translation**: Translate multiple languages concurrently with thread-based execution
47
+ - ๐Ÿ“ **Multiple Files**: Translate multiple files with arrays or glob patterns (`**/*.en.yml`)
34
48
 
35
49
  ### Development & Quality
36
50
  - ๐Ÿงช **Comprehensive Testing**: Unit tests + integration tests with VCR cassettes (18 cassettes, 260KB)
@@ -160,6 +174,11 @@ BetterTranslate.configure do |config|
160
174
  config.request_timeout = 30 # seconds
161
175
  config.max_retries = 3
162
176
  config.retry_delay = 2.0 # seconds
177
+
178
+ # ๐Ÿ†• v1.1.0: Provider-specific options
179
+ config.model = "gpt-5-nano" # Specify model (optional)
180
+ config.temperature = 0.3 # Creativity (0.0-2.0, default: 0.3)
181
+ config.max_tokens = 2000 # Response length limit
163
182
  end
164
183
  ```
165
184
 
@@ -195,6 +214,90 @@ end
195
214
 
196
215
  Get your API key from [Anthropic Console](https://console.anthropic.com/).
197
216
 
217
+ ### New Features (v1.1.0)
218
+
219
+ #### Automatic Backups
220
+
221
+ Protect your translation files with automatic backup creation:
222
+
223
+ ```ruby
224
+ config.create_backup = true # Enable backups (default: true)
225
+ config.max_backups = 5 # Keep up to 5 backup versions
226
+ ```
227
+
228
+ Backup files are created with rotation:
229
+ - First backup: `it.yml.bak`
230
+ - Second backup: `it.yml.bak.1`
231
+ - Third backup: `it.yml.bak.2`
232
+ - Older backups are automatically deleted
233
+
234
+ #### JSON File Support
235
+
236
+ Translate JSON locale files for modern JavaScript frameworks:
237
+
238
+ ```ruby
239
+ # Automatically detects JSON format from file extension
240
+ config.input_file = "config/locales/en.json"
241
+ config.output_folder = "config/locales"
242
+
243
+ # All features work with JSON: backups, incremental mode, exclusions, etc.
244
+ ```
245
+
246
+ Example JSON file:
247
+ ```json
248
+ {
249
+ "en": {
250
+ "common": {
251
+ "greeting": "Hello %{name}"
252
+ }
253
+ }
254
+ }
255
+ ```
256
+
257
+ #### Parallel Translation
258
+
259
+ Translate multiple languages concurrently for faster processing:
260
+
261
+ ```ruby
262
+ config.target_languages = [
263
+ { short_name: "it", name: "Italian" },
264
+ { short_name: "fr", name: "French" },
265
+ { short_name: "es", name: "Spanish" },
266
+ { short_name: "de", name: "German" }
267
+ ]
268
+
269
+ config.max_concurrent_requests = 4 # Translate 4 languages at once
270
+ ```
271
+
272
+ **Performance improvement:** With 4 languages and `max_concurrent_requests = 4`, translation time is reduced by ~75% compared to sequential processing.
273
+
274
+ #### Multiple Files Support
275
+
276
+ Translate multiple files in a single run:
277
+
278
+ ```ruby
279
+ # Array of specific files
280
+ config.input_files = [
281
+ "config/locales/common.en.yml",
282
+ "config/locales/errors.en.yml",
283
+ "config/locales/admin.en.yml"
284
+ ]
285
+
286
+ # Or use glob patterns (recommended)
287
+ config.input_files = "config/locales/**/*.en.yml"
288
+
289
+ # Or combine both approaches
290
+ config.input_files = [
291
+ "config/locales/**/*.en.yml",
292
+ "app/javascript/translations/*.en.json"
293
+ ]
294
+ ```
295
+
296
+ Output files preserve the original structure:
297
+ - `common.en.yml` โ†’ `common.it.yml`
298
+ - `errors.en.yml` โ†’ `errors.it.yml`
299
+ - `admin/settings.en.yml` โ†’ `admin/settings.it.yml`
300
+
198
301
  ### Language Configuration
199
302
 
200
303
  ```ruby
@@ -444,6 +547,142 @@ Enable detailed logging for debugging:
444
547
  config.verbose = true
445
548
  ```
446
549
 
550
+ ## ๐Ÿ” Orphan Key Analyzer
551
+
552
+ 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.
553
+
554
+ ### CLI Usage
555
+
556
+ Find orphan keys from the command line:
557
+
558
+ ```bash
559
+ # Basic text report (default)
560
+ better_translate analyze \
561
+ --source config/locales/en.yml \
562
+ --scan-path app/
563
+
564
+ # JSON format (great for CI/CD)
565
+ better_translate analyze \
566
+ --source config/locales/en.yml \
567
+ --scan-path app/ \
568
+ --format json
569
+
570
+ # CSV format (easy to share with team)
571
+ better_translate analyze \
572
+ --source config/locales/en.yml \
573
+ --scan-path app/ \
574
+ --format csv
575
+
576
+ # Save to file
577
+ better_translate analyze \
578
+ --source config/locales/en.yml \
579
+ --scan-path app/ \
580
+ --output orphan_report.txt
581
+ ```
582
+
583
+ ### Sample Output
584
+
585
+ **Text format:**
586
+ ```
587
+ ============================================================
588
+ Orphan Keys Analysis Report
589
+ ============================================================
590
+
591
+ Statistics:
592
+ Total keys: 50
593
+ Used keys: 45
594
+ Orphan keys: 5
595
+ Usage: 90.0%
596
+
597
+ Orphan Keys (5):
598
+ ------------------------------------------------------------
599
+
600
+ Key: users.old_message
601
+ Value: This feature was removed
602
+
603
+ Key: products.deprecated_label
604
+ Value: Old Label
605
+ ...
606
+ ============================================================
607
+ ```
608
+
609
+ **JSON format:**
610
+ ```json
611
+ {
612
+ "orphans": ["users.old_message", "products.deprecated_label"],
613
+ "orphan_details": {
614
+ "users.old_message": "This feature was removed",
615
+ "products.deprecated_label": "Old Label"
616
+ },
617
+ "orphan_count": 5,
618
+ "total_keys": 50,
619
+ "used_keys": 45,
620
+ "usage_percentage": 90.0
621
+ }
622
+ ```
623
+
624
+ ### Programmatic Usage
625
+
626
+ Use the analyzer in your Ruby code:
627
+
628
+ ```ruby
629
+ # Scan YAML file
630
+ key_scanner = BetterTranslate::Analyzer::KeyScanner.new("config/locales/en.yml")
631
+ all_keys = key_scanner.scan # Returns Hash of all keys
632
+
633
+ # Scan code for used keys
634
+ code_scanner = BetterTranslate::Analyzer::CodeScanner.new("app/")
635
+ used_keys = code_scanner.scan # Returns Set of used keys
636
+
637
+ # Detect orphans
638
+ detector = BetterTranslate::Analyzer::OrphanDetector.new(all_keys, used_keys)
639
+ orphans = detector.detect
640
+
641
+ # Get statistics
642
+ puts "Orphan count: #{detector.orphan_count}"
643
+ puts "Usage: #{detector.usage_percentage}%"
644
+
645
+ # Generate report
646
+ reporter = BetterTranslate::Analyzer::Reporter.new(
647
+ orphans: orphans,
648
+ orphan_details: detector.orphan_details,
649
+ total_keys: all_keys.size,
650
+ used_keys: used_keys.size,
651
+ usage_percentage: detector.usage_percentage,
652
+ format: :text
653
+ )
654
+
655
+ puts reporter.generate
656
+ reporter.save_to_file("orphan_report.txt")
657
+ ```
658
+
659
+ ### Supported Translation Patterns
660
+
661
+ The analyzer recognizes these i18n patterns:
662
+
663
+ - `t('key')` - Rails short form
664
+ - `t("key")` - Rails short form with double quotes
665
+ - `I18n.t(:key)` - Symbol syntax
666
+ - `I18n.t('key')` - String syntax
667
+ - `I18n.translate('key')` - Full method name
668
+ - `<%= t('key') %>` - ERB templates
669
+ - `I18n.t('key', param: value)` - With parameters
670
+
671
+ **Nested keys:**
672
+ ```yaml
673
+ en:
674
+ users:
675
+ profile:
676
+ title: "Profile" # Detected as: users.profile.title
677
+ ```
678
+
679
+ **Use cases:**
680
+ - Clean up unused translations before deployment
681
+ - Identify dead code after refactoring
682
+ - Reduce locale file size
683
+ - Improve translation maintenance
684
+ - Generate reports for translation teams
685
+
447
686
  ## ๐Ÿงช Development & Testing
448
687
 
449
688
  BetterTranslate includes comprehensive testing infrastructure with **unit tests**, **integration tests**, and a **Rails dummy app** for realistic testing.
data/Rakefile CHANGED
@@ -15,4 +15,17 @@ task :steep do
15
15
  sh "bundle exec steep check"
16
16
  end
17
17
 
18
- task default: %i[spec rubocop steep]
18
+ # Security scanning with Brakeman
19
+ desc "Run security scanning with Brakeman"
20
+ task :brakeman do
21
+ require "brakeman"
22
+ result = Brakeman.run(
23
+ app_path: ".",
24
+ print_report: true,
25
+ pager: false,
26
+ force_scan: true
27
+ )
28
+ exit Brakeman::Warnings_Found_Exit_Code unless result.filtered_warnings.empty?
29
+ end
30
+
31
+ task default: %i[spec rubocop steep brakeman]