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.
Files changed (44) 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/README.md +262 -2
  6. data/RELEASE_NOTES_v1.0.0.md +240 -0
  7. data/Steepfile +2 -2
  8. data/docs/implementation/00-overview.md +1 -1
  9. data/docs/implementation/04-provider_architecture.md +5 -5
  10. data/lib/better_translate/analyzer/code_scanner.rb +151 -0
  11. data/lib/better_translate/analyzer/key_scanner.rb +109 -0
  12. data/lib/better_translate/analyzer/orphan_detector.rb +88 -0
  13. data/lib/better_translate/analyzer/reporter.rb +155 -0
  14. data/lib/better_translate/cache.rb +2 -1
  15. data/lib/better_translate/cli.rb +81 -2
  16. data/lib/better_translate/configuration.rb +48 -2
  17. data/lib/better_translate/errors.rb +9 -0
  18. data/lib/better_translate/json_handler.rb +227 -0
  19. data/lib/better_translate/providers/anthropic_provider.rb +4 -3
  20. data/lib/better_translate/providers/chatgpt_provider.rb +2 -1
  21. data/lib/better_translate/providers/gemini_provider.rb +5 -4
  22. data/lib/better_translate/railtie.rb +2 -1
  23. data/lib/better_translate/rate_limiter.rb +4 -1
  24. data/lib/better_translate/strategies/batch_strategy.rb +1 -1
  25. data/lib/better_translate/strategies/deep_strategy.rb +1 -1
  26. data/lib/better_translate/translator.rb +204 -19
  27. data/lib/better_translate/utils/hash_flattener.rb +2 -2
  28. data/lib/better_translate/variable_extractor.rb +7 -7
  29. data/lib/better_translate/version.rb +1 -1
  30. data/lib/better_translate/yaml_handler.rb +59 -0
  31. data/lib/better_translate.rb +5 -0
  32. data/lib/generators/better_translate/analyze/analyze_generator.rb +2 -1
  33. data/lib/generators/better_translate/install/install_generator.rb +4 -3
  34. data/lib/generators/better_translate/install/templates/initializer.rb.tt +39 -7
  35. data/lib/generators/better_translate/translate/translate_generator.rb +2 -1
  36. data/regenerate_vcr.rb +47 -0
  37. data/sig/better_translate/configuration.rbs +13 -2
  38. data/sig/better_translate/errors.rbs +4 -0
  39. data/sig/better_translate/providers/base_http_provider.rbs +1 -1
  40. data/sig/better_translate/translator.rbs +12 -1
  41. data/sig/better_translate/variable_extractor.rbs +1 -1
  42. data/sig/better_translate/yaml_handler.rbs +6 -0
  43. data/sig/better_translate.rbs +2 -1
  44. metadata +9 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a19ffdafe02b71cad6e1d93eba868299d8551adc3e7952450c709c3f71d1292
4
- data.tar.gz: 7c5d7dde1f0b120124d13f75c31637b2a304845955a2974fc7f0c2f58eec8e76
3
+ metadata.gz: 80868b0f529d5c8310efabe07a402bd89d015e6bced86a3c0e2689e288d702f6
4
+ data.tar.gz: fdaede4b54e2c956d3f2cc936f221a83703a2001e1d647fec3abe2283d11e157
5
5
  SHA512:
6
- metadata.gz: a0c9c62cc2a35a0663d79af39c8e4a87cd86106b906b185c805f4ff9cba2bdfa82c1eaf8c366b5e91e70fe0c5ea87d5da852e03c32ae2a3959ae32ef2318d62a
7
- data.tar.gz: 6fb2cac27269257f878d3055027213dc2bef5d75332132f559493064a4c83f1360903080571a3fd1e71c7c6feec73cf41ff619d8ecc8da180246779b5e893e59
6
+ metadata.gz: 90a863900c1e132d7be3bf96a80a66cfad9580e38d7c634fd0e8dcea891be5768ff4cd548eadae6a74dde15a18c4f839a047e8e0653e6642272e518e6859ebac
7
+ data.tar.gz: 3ffb3062a2919d7296fe0ad95f28f29d5352ea3c126f12d09c89229378194a6386c4da65a7d419e7868d34d2297353a2561364600b1b5fe09d30ee9a24244408
data/.rubocop.yml CHANGED
@@ -1,8 +1,36 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ inherit_mode:
4
+ merge:
5
+ - Exclude
6
+
7
+ plugins:
8
+ - rubocop-rake
9
+ - rubocop-rspec
10
+
1
11
  AllCops:
2
12
  TargetRubyVersion: 3.0
13
+ NewCops: enable
3
14
 
4
15
  Style/StringLiterals:
5
16
  EnforcedStyle: double_quotes
6
17
 
7
18
  Style/StringLiteralsInInterpolation:
8
19
  EnforcedStyle: double_quotes
20
+
21
+ Metrics/BlockLength:
22
+ Exclude:
23
+ - 'spec/**/*_spec.rb'
24
+ - 'Rakefile'
25
+ - '*.gemspec'
26
+
27
+ # RSpec-specific configurations
28
+ RSpec/MultipleExpectations:
29
+ Max: 5
30
+
31
+ RSpec/ExampleLength:
32
+ Max: 15
33
+
34
+ RSpec/DescribeClass:
35
+ Exclude:
36
+ - 'spec/integration/**/*'
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,291 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2025-10-22 20:47:42 UTC using RuboCop version 1.81.6.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # This cop supports safe autocorrection (--autocorrect).
11
+ # Configuration parameters: Severity.
12
+ Gemspec/RequireMFA:
13
+ Exclude:
14
+ - 'better_translate.gemspec'
15
+
16
+ # Offense count: 4
17
+ # This cop supports safe autocorrection (--autocorrect).
18
+ Lint/AmbiguousOperatorPrecedence:
19
+ Exclude:
20
+ - 'lib/better_translate/analyzer/reporter.rb'
21
+
22
+ # Offense count: 1
23
+ Lint/FloatComparison:
24
+ Exclude:
25
+ - 'spec/better_translate/providers/chatgpt_provider_spec.rb'
26
+
27
+ # Offense count: 8
28
+ # This cop supports unsafe autocorrection (--autocorrect-all).
29
+ Lint/NonAtomicFileOperation:
30
+ Exclude:
31
+ - 'lib/better_translate/json_handler.rb'
32
+ - 'lib/better_translate/yaml_handler.rb'
33
+ - 'spec/better_translate/analyzer/key_scanner_spec.rb'
34
+ - 'spec/better_translate/analyzer/reporter_spec.rb'
35
+
36
+ # Offense count: 22
37
+ # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
38
+ Metrics/AbcSize:
39
+ Max: 116
40
+
41
+ # Offense count: 7
42
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
43
+ # AllowedMethods: refine
44
+ Metrics/BlockLength:
45
+ Max: 99
46
+
47
+ # Offense count: 3
48
+ # Configuration parameters: CountComments, CountAsOne.
49
+ Metrics/ClassLength:
50
+ Max: 246
51
+
52
+ # Offense count: 12
53
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
54
+ Metrics/CyclomaticComplexity:
55
+ Max: 24
56
+
57
+ # Offense count: 41
58
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
59
+ Metrics/MethodLength:
60
+ Max: 61
61
+
62
+ # Offense count: 1
63
+ # Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
64
+ Metrics/ParameterLists:
65
+ Max: 6
66
+
67
+ # Offense count: 9
68
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
69
+ Metrics/PerceivedComplexity:
70
+ Max: 25
71
+
72
+ # Offense count: 2
73
+ Naming/AccessorMethodName:
74
+ Exclude:
75
+ - 'lib/better_translate/json_handler.rb'
76
+ - 'lib/better_translate/yaml_handler.rb'
77
+
78
+ # Offense count: 6
79
+ # Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
80
+ # AllowedMethods: call
81
+ # WaywardPredicates: nonzero?
82
+ Naming/PredicateMethod:
83
+ Exclude:
84
+ - 'lib/better_translate/configuration.rb'
85
+ - 'lib/better_translate/validator.rb'
86
+ - 'lib/better_translate/variable_extractor.rb'
87
+
88
+ # Offense count: 30
89
+ RSpec/AnyInstance:
90
+ Exclude:
91
+ - 'spec/better_translate/cli_spec.rb'
92
+ - 'spec/better_translate/direct_translator_spec.rb'
93
+ - 'spec/better_translate/multiple_files_spec.rb'
94
+ - 'spec/better_translate/rake_tasks_spec.rb'
95
+ - 'spec/better_translate/translator_spec.rb'
96
+ - 'spec/better_translate_spec.rb'
97
+ - 'spec/generators/translate_generator_spec.rb'
98
+
99
+ # Offense count: 1
100
+ # This cop supports safe autocorrection (--autocorrect).
101
+ # Configuration parameters: EnforcedStyle.
102
+ # SupportedStyles: be, be_nil
103
+ RSpec/BeNil:
104
+ Exclude:
105
+ - 'spec/better_translate_spec.rb'
106
+
107
+ # Offense count: 6
108
+ RSpec/BeforeAfterAll:
109
+ Exclude:
110
+ - '**/spec/spec_helper.rb'
111
+ - '**/spec/rails_helper.rb'
112
+ - '**/spec/support/**/*.rb'
113
+ - 'spec/generators/analyze_generator_spec.rb'
114
+ - 'spec/generators/install_generator_spec.rb'
115
+ - 'spec/generators/translate_generator_spec.rb'
116
+
117
+ # Offense count: 13
118
+ # Configuration parameters: Prefixes, AllowedPatterns.
119
+ # Prefixes: when, with, without
120
+ RSpec/ContextWording:
121
+ Exclude:
122
+ - 'spec/better_translate/analyzer/reporter_spec.rb'
123
+ - 'spec/better_translate/configuration_spec.rb'
124
+ - 'spec/better_translate/strategies/batch_strategy_spec.rb'
125
+ - 'spec/better_translate/strategies/deep_strategy_spec.rb'
126
+ - 'spec/better_translate/strategies/strategy_selector_spec.rb'
127
+
128
+ # Offense count: 2
129
+ # Configuration parameters: IgnoredMetadata.
130
+ RSpec/DescribeClass:
131
+ Exclude:
132
+ - 'spec/integration/**/*'
133
+ - 'spec/better_translate/multiple_files_spec.rb'
134
+ - 'spec/better_translate/rake_tasks_spec.rb'
135
+
136
+ # Offense count: 1
137
+ # This cop supports unsafe autocorrection (--autocorrect-all).
138
+ # Configuration parameters: SkipBlocks, EnforcedStyle, OnlyStaticConstants.
139
+ # SupportedStyles: described_class, explicit
140
+ RSpec/DescribedClass:
141
+ Exclude:
142
+ - 'spec/better_translate/cli_spec.rb'
143
+
144
+ # Offense count: 18
145
+ # Configuration parameters: Max, CountAsOne.
146
+ RSpec/ExampleLength:
147
+ Exclude:
148
+ - 'spec/better_translate/configuration_spec.rb'
149
+ - 'spec/better_translate/direct_translator_spec.rb'
150
+ - 'spec/better_translate/providers/base_http_provider_spec.rb'
151
+ - 'spec/better_translate/strategies/batch_strategy_spec.rb'
152
+ - 'spec/better_translate/strategies/deep_strategy_spec.rb'
153
+ - 'spec/better_translate/translator_spec.rb'
154
+ - 'spec/integration/analyzer_integration_spec.rb'
155
+
156
+ # Offense count: 11
157
+ # This cop supports safe autocorrection (--autocorrect).
158
+ RSpec/LeadingSubject:
159
+ Exclude:
160
+ - 'spec/better_translate/direct_translator_spec.rb'
161
+ - 'spec/better_translate/json_handler_spec.rb'
162
+ - 'spec/better_translate/providers/anthropic_provider_spec.rb'
163
+ - 'spec/better_translate/providers/base_http_provider_spec.rb'
164
+ - 'spec/better_translate/providers/chatgpt_provider_spec.rb'
165
+ - 'spec/better_translate/providers/gemini_provider_spec.rb'
166
+ - 'spec/better_translate/strategies/base_strategy_spec.rb'
167
+ - 'spec/better_translate/yaml_handler_spec.rb'
168
+ - 'spec/integration/anthropic_integration_spec.rb'
169
+ - 'spec/integration/chatgpt_integration_spec.rb'
170
+ - 'spec/integration/gemini_integration_spec.rb'
171
+
172
+ # Offense count: 32
173
+ # Configuration parameters: EnforcedStyle.
174
+ # SupportedStyles: have_received, receive
175
+ RSpec/MessageSpies:
176
+ Exclude:
177
+ - 'spec/better_translate/strategies/batch_strategy_spec.rb'
178
+ - 'spec/better_translate/strategies/deep_strategy_spec.rb'
179
+
180
+ # Offense count: 1
181
+ RSpec/MultipleDescribes:
182
+ Exclude:
183
+ - 'spec/better_translate/errors_spec.rb'
184
+
185
+ # Offense count: 9
186
+ # Configuration parameters: Max.
187
+ RSpec/MultipleExpectations:
188
+ Exclude:
189
+ - 'spec/better_translate/configuration_spec.rb'
190
+ - 'spec/better_translate/providers/anthropic_provider_spec.rb'
191
+ - 'spec/better_translate/providers/chatgpt_provider_spec.rb'
192
+ - 'spec/better_translate/strategies/batch_strategy_spec.rb'
193
+ - 'spec/better_translate/strategies/deep_strategy_spec.rb'
194
+ - 'spec/better_translate_spec.rb'
195
+ - 'spec/integration/analyzer_integration_spec.rb'
196
+
197
+ # Offense count: 22
198
+ # Configuration parameters: AllowSubject.
199
+ RSpec/MultipleMemoizedHelpers:
200
+ Max: 6
201
+
202
+ # Offense count: 16
203
+ # This cop supports unsafe autocorrection (--autocorrect-all).
204
+ RSpec/ReceiveMessages:
205
+ Exclude:
206
+ - 'spec/better_translate/providers/base_http_provider_spec.rb'
207
+
208
+ # Offense count: 2
209
+ RSpec/RepeatedExample:
210
+ Exclude:
211
+ - 'spec/generators/analyze_generator_spec.rb'
212
+
213
+ # Offense count: 4
214
+ # Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata.
215
+ RSpec/SpecFilePathFormat:
216
+ Exclude:
217
+ - '**/spec/routing/**/*'
218
+ - 'spec/better_translate/providers/chatgpt_provider_spec.rb'
219
+ - 'spec/generators/analyze_generator_spec.rb'
220
+ - 'spec/generators/install_generator_spec.rb'
221
+ - 'spec/generators/translate_generator_spec.rb'
222
+
223
+ # Offense count: 17
224
+ RSpec/StubbedMock:
225
+ Exclude:
226
+ - 'spec/better_translate/strategies/batch_strategy_spec.rb'
227
+ - 'spec/better_translate/strategies/deep_strategy_spec.rb'
228
+
229
+ # Offense count: 4
230
+ RSpec/SubjectStub:
231
+ Exclude:
232
+ - 'spec/better_translate/providers/base_http_provider_spec.rb'
233
+
234
+ # Offense count: 33
235
+ # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
236
+ RSpec/VerifiedDoubles:
237
+ Exclude:
238
+ - 'spec/better_translate/providers/anthropic_provider_spec.rb'
239
+ - 'spec/better_translate/providers/base_http_provider_spec.rb'
240
+ - 'spec/better_translate/providers/chatgpt_provider_spec.rb'
241
+ - 'spec/better_translate/providers/gemini_provider_spec.rb'
242
+
243
+ # Offense count: 1
244
+ # This cop supports safe autocorrection (--autocorrect).
245
+ # Configuration parameters: EnforcedStyle.
246
+ # SupportedStyles: trailing_conditional, ternary
247
+ Style/EmptyStringInsideInterpolation:
248
+ Exclude:
249
+ - 'lib/generators/better_translate/analyze/analyze_generator.rb'
250
+
251
+ # Offense count: 14
252
+ # This cop supports safe autocorrection (--autocorrect).
253
+ # Configuration parameters: AllowedVars, DefaultToNil.
254
+ Style/FetchEnvVar:
255
+ Exclude:
256
+ - 'lib/better_translate/cli.rb'
257
+ - 'lib/generators/better_translate/translate/translate_generator.rb'
258
+ - 'lib/tasks/better_translate.rake'
259
+ - 'regenerate_vcr.rb'
260
+
261
+ # Offense count: 5
262
+ # This cop supports safe autocorrection (--autocorrect).
263
+ # Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns.
264
+ # SupportedStyles: annotated, template, unannotated
265
+ Style/FormatStringToken:
266
+ Exclude:
267
+ - 'lib/better_translate/progress_tracker.rb'
268
+
269
+ # Offense count: 2
270
+ # This cop supports unsafe autocorrection (--autocorrect-all).
271
+ Style/HashExcept:
272
+ Exclude:
273
+ - 'lib/better_translate/json_handler.rb'
274
+ - 'lib/better_translate/yaml_handler.rb'
275
+
276
+ # Offense count: 9
277
+ # This cop supports safe autocorrection (--autocorrect).
278
+ Style/IfUnlessModifier:
279
+ Exclude:
280
+ - 'lib/better_translate/configuration.rb'
281
+ - 'lib/better_translate/providers/anthropic_provider.rb'
282
+ - 'lib/better_translate/providers/chatgpt_provider.rb'
283
+ - 'lib/better_translate/providers/gemini_provider.rb'
284
+ - 'lib/better_translate/translator.rb'
285
+
286
+ # Offense count: 4
287
+ # This cop supports safe autocorrection (--autocorrect).
288
+ # Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
289
+ # URISchemes: http, https
290
+ Layout/LineLength:
291
+ Max: 181
data/CHANGELOG.md CHANGED
@@ -5,6 +5,94 @@ All notable changes to BetterTranslate will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.1.0] - 2025-10-22
9
+
10
+ ### Added
11
+
12
+ #### Enhanced Configuration
13
+ - **Provider-Specific Options**: Fine-tune AI provider behavior
14
+ - `model`: Specify which AI model to use (e.g., "gpt-5-nano", "gemini-2.0-flash-exp")
15
+ - `temperature`: Control creativity/randomness (0.0-2.0, default: 0.3)
16
+ - `max_tokens`: Limit response length (default: 2000)
17
+ - Configurable via CLI, configuration file, or programmatically
18
+
19
+ #### Automatic Backups
20
+ - **Backup System**: Automatic backup creation before overwriting translation files
21
+ - `create_backup`: Enable/disable automatic backups (default: true)
22
+ - `max_backups`: Keep up to N backup files with rotation (default: 3)
23
+ - Backup format: `.bak`, `.bak.1`, `.bak.2`, etc.
24
+ - Automatic cleanup of old backups beyond `max_backups`
25
+ - Works with both YAML and JSON files
26
+
27
+ #### JSON File Support
28
+ - **JSON Handler**: Complete support for JSON translation files
29
+ - Read and write JSON locale files
30
+ - Automatic format detection based on file extension (.json vs .yml)
31
+ - Same feature set as YAML (incremental mode, backups, exclusions)
32
+ - Pretty-printed output with proper indentation
33
+ - Compatible with modern JavaScript frameworks (React, Vue, etc.)
34
+
35
+ #### Parallel Translation
36
+ - **Concurrent Processing**: Translate multiple languages simultaneously
37
+ - `max_concurrent_requests`: Control concurrency level (default: 3)
38
+ - Thread-based parallel execution for improved performance
39
+ - Automatic fallback to sequential processing when `max_concurrent_requests = 1`
40
+ - Thread-safe error handling
41
+ - Significant time savings for projects with many target languages
42
+
43
+ #### Multiple Files Support
44
+ - **Batch Translation**: Translate multiple files in a single run
45
+ - `input_files`: Accept array of file paths or glob patterns
46
+ - Glob pattern support: `config/locales/**/*.en.yml`
47
+ - Preserves directory structure in output
48
+ - Smart filename handling: `common.en.yml` → `common.it.yml`
49
+ - Works with both YAML and JSON files
50
+ - Backward compatible with single `input_file` attribute
51
+
52
+ ### Examples
53
+
54
+ #### Provider-Specific Options
55
+ ```ruby
56
+ config.model = "gpt-5-nano" # Use specific model
57
+ config.temperature = 0.7 # More creative translations
58
+ config.max_tokens = 1500 # Limit response length
59
+ ```
60
+
61
+ #### Automatic Backups
62
+ ```ruby
63
+ config.create_backup = true # Enable backups (default)
64
+ config.max_backups = 5 # Keep up to 5 backup versions
65
+ ```
66
+
67
+ #### JSON Support
68
+ ```ruby
69
+ config.input_file = "config/locales/en.json"
70
+ config.output_folder = "config/locales"
71
+ # Automatically detects JSON format and uses JsonHandler
72
+ ```
73
+
74
+ #### Parallel Translation
75
+ ```ruby
76
+ config.target_languages = [
77
+ { short_name: "it", name: "Italian" },
78
+ { short_name: "fr", name: "French" },
79
+ { short_name: "es", name: "Spanish" }
80
+ ]
81
+ config.max_concurrent_requests = 3 # Translate 3 languages at once
82
+ ```
83
+
84
+ #### Multiple Files
85
+ ```ruby
86
+ # Array of specific files
87
+ config.input_files = [
88
+ "config/locales/common.en.yml",
89
+ "config/locales/errors.en.yml"
90
+ ]
91
+
92
+ # Or use glob patterns
93
+ config.input_files = "config/locales/**/*.en.yml"
94
+ ```
95
+
8
96
  ## [1.0.0] - 2025-10-22
9
97
 
10
98
  ### Complete Rewrite 🎉