better_translate 0.5.0 → 1.0.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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/.env.example +14 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +8 -0
  5. data/.yardopts +10 -0
  6. data/CHANGELOG.md +125 -114
  7. data/CLAUDE.md +385 -0
  8. data/README.md +629 -244
  9. data/Rakefile +7 -1
  10. data/Steepfile +29 -0
  11. data/docs/implementation/00-overview.md +220 -0
  12. data/docs/implementation/01-setup_dependencies.md +668 -0
  13. data/docs/implementation/02-error_handling.md +65 -0
  14. data/docs/implementation/03-core_components.md +457 -0
  15. data/docs/implementation/03.5-variable_preservation.md +509 -0
  16. data/docs/implementation/04-provider_architecture.md +571 -0
  17. data/docs/implementation/05-translation_logic.md +1065 -0
  18. data/docs/implementation/06-main_module_api.md +122 -0
  19. data/docs/implementation/07-direct_translation_helpers.md +582 -0
  20. data/docs/implementation/08-rails_integration.md +323 -0
  21. data/docs/implementation/09-testing_suite.md +228 -0
  22. data/docs/implementation/10-documentation_examples.md +150 -0
  23. data/docs/implementation/11-quality_security.md +65 -0
  24. data/docs/implementation/12-cli_standalone.md +698 -0
  25. data/exe/better_translate +9 -0
  26. data/lib/better_translate/cache.rb +125 -0
  27. data/lib/better_translate/cli.rb +304 -0
  28. data/lib/better_translate/configuration.rb +201 -0
  29. data/lib/better_translate/direct_translator.rb +131 -0
  30. data/lib/better_translate/errors.rb +101 -0
  31. data/lib/better_translate/progress_tracker.rb +157 -0
  32. data/lib/better_translate/provider_factory.rb +45 -0
  33. data/lib/better_translate/providers/anthropic_provider.rb +154 -0
  34. data/lib/better_translate/providers/base_http_provider.rb +239 -0
  35. data/lib/better_translate/providers/chatgpt_provider.rb +138 -44
  36. data/lib/better_translate/providers/gemini_provider.rb +123 -61
  37. data/lib/better_translate/railtie.rb +18 -0
  38. data/lib/better_translate/rate_limiter.rb +90 -0
  39. data/lib/better_translate/strategies/base_strategy.rb +58 -0
  40. data/lib/better_translate/strategies/batch_strategy.rb +56 -0
  41. data/lib/better_translate/strategies/deep_strategy.rb +45 -0
  42. data/lib/better_translate/strategies/strategy_selector.rb +43 -0
  43. data/lib/better_translate/translator.rb +115 -284
  44. data/lib/better_translate/utils/hash_flattener.rb +104 -0
  45. data/lib/better_translate/validator.rb +105 -0
  46. data/lib/better_translate/variable_extractor.rb +259 -0
  47. data/lib/better_translate/version.rb +2 -9
  48. data/lib/better_translate/yaml_handler.rb +168 -0
  49. data/lib/better_translate.rb +97 -73
  50. data/lib/generators/better_translate/analyze/USAGE +12 -0
  51. data/lib/generators/better_translate/analyze/analyze_generator.rb +94 -0
  52. data/lib/generators/better_translate/install/USAGE +13 -0
  53. data/lib/generators/better_translate/install/install_generator.rb +71 -0
  54. data/lib/generators/better_translate/install/templates/README +20 -0
  55. data/lib/generators/better_translate/install/templates/initializer.rb.tt +47 -0
  56. data/lib/generators/better_translate/translate/USAGE +13 -0
  57. data/lib/generators/better_translate/translate/translate_generator.rb +114 -0
  58. data/lib/tasks/better_translate.rake +136 -0
  59. data/sig/better_translate/cache.rbs +28 -0
  60. data/sig/better_translate/cli.rbs +24 -0
  61. data/sig/better_translate/configuration.rbs +78 -0
  62. data/sig/better_translate/direct_translator.rbs +18 -0
  63. data/sig/better_translate/errors.rbs +46 -0
  64. data/sig/better_translate/progress_tracker.rbs +29 -0
  65. data/sig/better_translate/provider_factory.rbs +8 -0
  66. data/sig/better_translate/providers/anthropic_provider.rbs +27 -0
  67. data/sig/better_translate/providers/base_http_provider.rbs +44 -0
  68. data/sig/better_translate/providers/chatgpt_provider.rbs +25 -0
  69. data/sig/better_translate/providers/gemini_provider.rbs +22 -0
  70. data/sig/better_translate/railtie.rbs +7 -0
  71. data/sig/better_translate/rate_limiter.rbs +20 -0
  72. data/sig/better_translate/strategies/base_strategy.rbs +19 -0
  73. data/sig/better_translate/strategies/batch_strategy.rbs +13 -0
  74. data/sig/better_translate/strategies/deep_strategy.rbs +11 -0
  75. data/sig/better_translate/strategies/strategy_selector.rbs +10 -0
  76. data/sig/better_translate/translator.rbs +24 -0
  77. data/sig/better_translate/utils/hash_flattener.rbs +14 -0
  78. data/sig/better_translate/validator.rbs +14 -0
  79. data/sig/better_translate/variable_extractor.rbs +40 -0
  80. data/sig/better_translate/version.rbs +4 -0
  81. data/sig/better_translate/yaml_handler.rbs +29 -0
  82. data/sig/better_translate.rbs +32 -2
  83. data/sig/faraday.rbs +22 -0
  84. data/sig/generators/better_translate/analyze/analyze_generator.rbs +18 -0
  85. data/sig/generators/better_translate/install/install_generator.rbs +14 -0
  86. data/sig/generators/better_translate/translate/translate_generator.rbs +10 -0
  87. data/sig/optparse.rbs +9 -0
  88. data/sig/psych.rbs +5 -0
  89. data/sig/rails.rbs +34 -0
  90. metadata +89 -203
  91. data/lib/better_translate/helper.rb +0 -83
  92. data/lib/better_translate/providers/base_provider.rb +0 -102
  93. data/lib/better_translate/service.rb +0 -144
  94. data/lib/better_translate/similarity_analyzer.rb +0 -218
  95. data/lib/better_translate/utils.rb +0 -55
  96. data/lib/better_translate/writer.rb +0 -75
  97. data/lib/generators/better_translate/analyze_generator.rb +0 -57
  98. data/lib/generators/better_translate/install_generator.rb +0 -14
  99. data/lib/generators/better_translate/templates/better_translate.rb +0 -56
  100. data/lib/generators/better_translate/translate_generator.rb +0 -84
@@ -1,218 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "yaml"
4
- require "set"
5
- require "json"
6
- require "time"
7
-
8
- module BetterTranslate
9
- # Analyzes translation YAML files to find similar content across keys.
10
- # Uses the Levenshtein distance algorithm to identify strings that are similar
11
- # but not identical, which could indicate redundant translations.
12
- #
13
- # @example
14
- # analyzer = BetterTranslate::SimilarityAnalyzer.new(["config/locales/en.yml", "config/locales/fr.yml"])
15
- # analyzer.analyze
16
- class SimilarityAnalyzer
17
- # Default threshold for considering two strings similar (75%)
18
- # @return [Float] The similarity threshold as a decimal between 0 and 1
19
- SIMILARITY_THRESHOLD = 0.75 # Abbassiamo la soglia per trovare più similarità
20
-
21
- # Default filename for the detailed JSON report
22
- # @return [String] The filename for the JSON report
23
- REPORT_FILE = "translation_similarities.json"
24
-
25
- # Initializes a new SimilarityAnalyzer with the specified YAML files.
26
- #
27
- # @param yaml_files [Array<String>] An array of paths to YAML translation files
28
- # @return [SimilarityAnalyzer] A new instance of the analyzer
29
- def initialize(yaml_files)
30
- @yaml_files = yaml_files
31
- @similarities = {}
32
- end
33
-
34
- # Performs the complete analysis process:
35
- # 1. Loads all translation files
36
- # 2. Finds similarities between translations
37
- # 3. Generates JSON and text reports
38
- #
39
- # @return [void]
40
- def analyze
41
- translations_by_language = load_translations
42
- find_similarities(translations_by_language)
43
- generate_report
44
- end
45
-
46
- private
47
-
48
- # Loads all YAML translation files specified during initialization.
49
- # Parses each file and organizes translations by language code.
50
- #
51
- # @return [Hash] A hash mapping language codes to their translation data structures
52
- def load_translations
53
- translations = {}
54
- puts "Loading YAML files..."
55
-
56
- @yaml_files.each do |file|
57
- lang_code = File.basename(file, ".yml")
58
- translations[lang_code] = YAML.load_file(file)
59
- puts " - Loaded #{lang_code}.yml"
60
- end
61
-
62
- translations
63
- end
64
-
65
- # Finds similar translations within each language file.
66
- # For each language, flattens the translation structure and compares each pair of strings
67
- # to identify similarities based on the Levenshtein distance algorithm.
68
- #
69
- # @param translations_by_language [Hash] A hash mapping language codes to their translation data
70
- # @return [void]
71
- def find_similarities(translations_by_language)
72
- translations_by_language.each do |lang, translations|
73
- puts "\nAnalyzing #{lang} translations..."
74
- flattened = flatten_translations(translations)
75
- keys = flattened.keys
76
- similar_found = 0
77
-
78
- keys.each_with_index do |key1, i|
79
- value1 = flattened[key1]
80
-
81
- # Confronta solo con le chiavi successive per evitare duplicati
82
- keys[(i + 1)..-1].each do |key2|
83
- value2 = flattened[key2]
84
-
85
- similarity = calculate_similarity(value1.to_s, value2.to_s)
86
- if similarity >= SIMILARITY_THRESHOLD
87
- record_similarity(lang, key1, key2, value1, value2, similarity)
88
- similar_found += 1
89
- end
90
- end
91
- end
92
-
93
- puts " Found #{similar_found} similar translations"
94
- end
95
- end
96
-
97
- # Flattens a nested translation hash into a single-level hash with dot-notation keys.
98
- # For example, {"en" => {"hello" => "world"}} becomes {"en.hello" => "world"}.
99
- #
100
- # @param hash [Hash] The nested hash to flatten
101
- # @param prefix [String] The current key prefix (used recursively)
102
- # @param result [Hash] The accumulator for flattened key-value pairs
103
- # @return [Hash] A flattened hash with dot-notation keys
104
- def flatten_translations(hash, prefix = "", result = {})
105
- hash.each do |key, value|
106
- current_key = prefix.empty? ? key.to_s : "#{prefix}.#{key}"
107
-
108
- if value.is_a?(Hash)
109
- flatten_translations(value, current_key, result)
110
- else
111
- result[current_key] = value
112
- end
113
- end
114
-
115
- result
116
- end
117
-
118
- # Calculates the similarity between two strings using normalized Levenshtein distance.
119
- # Returns a value between 0 (completely different) and 1 (identical).
120
- # The normalization accounts for the length of the strings.
121
- #
122
- # @param str1 [String] The first string to compare
123
- # @param str2 [String] The second string to compare
124
- # @return [Float] A similarity score between 0 and 1
125
- def calculate_similarity(str1, str2)
126
- # Implementazione della distanza di Levenshtein normalizzata
127
- matrix = Array.new(str1.length + 1) { Array.new(str2.length + 1) }
128
-
129
- (0..str1.length).each { |i| matrix[i][0] = i }
130
- (0..str2.length).each { |j| matrix[0][j] = j }
131
-
132
- (1..str1.length).each do |i|
133
- (1..str2.length).each do |j|
134
- cost = str1[i-1] == str2[j-1] ? 0 : 1
135
- matrix[i][j] = [
136
- matrix[i-1][j] + 1,
137
- matrix[i][j-1] + 1,
138
- matrix[i-1][j-1] + cost
139
- ].min
140
- end
141
- end
142
-
143
- max_length = [str1.length, str2.length].max
144
- 1 - (matrix[str1.length][str2.length].to_f / max_length)
145
- end
146
-
147
- # Records a similarity finding in the internal data structure.
148
- # Organizes findings by language and stores all relevant information about the similar strings.
149
- #
150
- # @param lang [String] The language code
151
- # @param key1 [String] The first translation key
152
- # @param key2 [String] The second translation key
153
- # @param value1 [String] The first translation value
154
- # @param value2 [String] The second translation value
155
- # @param similarity [Float] The calculated similarity score
156
- # @return [void]
157
- def record_similarity(lang, key1, key2, value1, value2, similarity)
158
- @similarities[lang] ||= []
159
- @similarities[lang] << {
160
- key1: key1,
161
- key2: key2,
162
- value1: value1,
163
- value2: value2,
164
- similarity: similarity.round(2)
165
- }
166
- end
167
-
168
- # Generates both JSON and human-readable reports of the similarity findings.
169
- # The JSON report contains detailed information about each similarity found.
170
- # The text summary provides a more readable format for quick review.
171
- #
172
- # @return [void]
173
- def generate_report
174
- puts "\nGenerating reports..."
175
- report = {
176
- generated_at: Time.now.iso8601,
177
- similarity_threshold: SIMILARITY_THRESHOLD,
178
- findings: @similarities
179
- }
180
-
181
- File.write(REPORT_FILE, JSON.pretty_generate(report))
182
- puts " - Generated #{REPORT_FILE}"
183
-
184
- summary = generate_summary(report)
185
- File.write("translation_similarities_summary.txt", summary)
186
- puts " - Generated translation_similarities_summary.txt"
187
- end
188
-
189
- # Generates a human-readable summary of the similarity findings.
190
- # Creates a formatted text report organized by language, showing each pair of similar strings
191
- # with their keys, values, and similarity percentage.
192
- #
193
- # @param report [Hash] The complete similarity report data
194
- # @return [String] A formatted text summary
195
- def generate_summary(report)
196
- summary = ["Translation Similarities Report", "=" * 30, ""]
197
-
198
- report[:findings].each do |lang, similarities|
199
- summary << "Language: #{lang}"
200
- summary << "-" * 20
201
-
202
- similarities.each do |sim|
203
- summary << "Similar translations found:"
204
- summary << " Key 1: #{sim[:key1]}"
205
- summary << " Value 1: #{sim[:value1]}"
206
- summary << " Key 2: #{sim[:key2]}"
207
- summary << " Value 2: #{sim[:value2]}"
208
- summary << " Similarity: #{(sim[:similarity] * 100).round(1)}%"
209
- summary << ""
210
- end
211
-
212
- summary << ""
213
- end
214
-
215
- summary.join("\n")
216
- end
217
- end
218
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module BetterTranslate
4
- # Utility class providing helper methods for logging and metrics tracking.
5
- # Used throughout the BetterTranslate gem to standardize logging and performance monitoring.
6
- class Utils
7
- class << self
8
-
9
- # Logs a message using the Rails logger if available, otherwise prints to standard output.
10
- # Provides a consistent logging interface across different environments.
11
- #
12
- # @param message [String, nil] The message to log
13
- # @return [void]
14
- def logger(message: nil)
15
- if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
16
- Rails.logger.info message
17
- else
18
- puts message
19
- end
20
- end
21
-
22
- # Tracks a metric with the given name and value.
23
- # Stores metrics in memory with timestamps for performance analysis.
24
- # Automatically limits each metric type to the most recent 1000 entries.
25
- #
26
- # @param name [Symbol, String] The name of the metric to track
27
- # @param value [Numeric] The value to record for this metric
28
- # @return [void]
29
- def track_metric(name, value)
30
- @metrics ||= {}
31
- @metrics[name] ||= []
32
- @metrics[name] << { value: value, timestamp: Time.now }
33
-
34
- # Mantieni solo le ultime 1000 metriche per tipo
35
- @metrics[name] = @metrics[name].last(1000) if @metrics[name].size > 1000
36
- end
37
-
38
- # Retrieves all tracked metrics.
39
- # Returns a hash where keys are metric names and values are arrays of recorded values with timestamps.
40
- #
41
- # @return [Hash] The collected metrics or an empty hash if no metrics have been tracked
42
- def get_metrics
43
- @metrics || {}
44
- end
45
-
46
- # Clears all tracked metrics.
47
- # Useful for resetting metrics between translation jobs or testing.
48
- #
49
- # @return [Hash] An empty hash representing the cleared metrics
50
- def clear_metrics
51
- @metrics = {}
52
- end
53
- end
54
- end
55
- end
@@ -1,75 +0,0 @@
1
- module BetterTranslate
2
- # Responsible for writing translated content to YAML files.
3
- # Supports both incremental and override translation methods.
4
- # Incremental mode preserves existing translations and adds new ones,
5
- # while override mode completely replaces the target file.
6
- class Writer
7
- class << self
8
- # Writes the translation file for a target language.
9
- # If the translation method is :override, the file is rewritten from scratch;
10
- # if it's :incremental, the existing file is updated by inserting new translations in the correct positions.
11
- #
12
- # @param translated_data [Hash] The translated data structure (e.g. { "sample" => { "valid" => "translated", "new_key" => "new translation" } }).
13
- # @param target_lang_code [String] Target language code (e.g. "ru").
14
- def write_translations(translated_data, target_lang_code)
15
- output_folder = BetterTranslate.configuration.output_folder
16
- output_file = File.join(output_folder, "#{target_lang_code}.yml")
17
-
18
- # Reformats the structure to use the target code as the main key.
19
- output_content = if translated_data.is_a?(Hash) && translated_data.key?(BetterTranslate.configuration.source_language)
20
- # Replaces the source language key with the target one.
21
- { target_lang_code => translated_data[BetterTranslate.configuration.source_language] }
22
- else
23
- { target_lang_code => translated_data }
24
- end
25
-
26
- if BetterTranslate.configuration.translation_method.to_sym == :incremental && File.exist?(output_file)
27
- existing_data = YAML.load_file(output_file)
28
- merged = deep_merge(existing_data, output_content)
29
- File.write(output_file, merged.to_yaml(line_width: -1))
30
- message = "File updated in incremental mode: #{output_file}"
31
- BetterTranslate::Utils.logger(message: message)
32
- else
33
- FileUtils.mkdir_p(output_folder) unless Dir.exist?(output_folder)
34
- File.write(output_file, output_content.to_yaml(line_width: -1))
35
- message = "File rewritten in override mode: #{output_file}"
36
- BetterTranslate::Utils.logger(message: message)
37
- end
38
- end
39
-
40
- private
41
-
42
- # Recursively merges two hashes while preserving existing values.
43
- # If a key exists in both hashes and the values are hashes, they are merged recursively.
44
- # If a key exists in both hashes but the values are not hashes, the existing value is preserved.
45
- # If a key only exists in the new hash, it is added to the merged result.
46
- #
47
- # @param existing [Hash] The existing hash (current file content)
48
- # @param new_data [Hash] The new hash with translations to merge
49
- # @return [Hash] The merged hash with preserved existing values
50
- # @example
51
- # existing = { "en" => { "hello" => "Hello", "nested" => { "key" => "Value" } } }
52
- # new_data = { "en" => { "hello" => "New Hello", "nested" => { "key2" => "Value2" } } }
53
- # deep_merge(existing, new_data)
54
- # # => { "en" => { "hello" => "Hello", "nested" => { "key" => "Value", "key2" => "Value2" } } }
55
- def deep_merge(existing, new_data)
56
- merged = existing.dup
57
- new_data.each do |key, value|
58
- if merged.key?(key)
59
- if merged[key].is_a?(Hash) && value.is_a?(Hash)
60
- merged[key] = deep_merge(merged[key], value)
61
- else
62
- # If the key already exists, don't overwrite the value (incremental mode)
63
- # or you might decide to update anyway, depending on the requirements.
64
- merged[key] = merged[key]
65
- end
66
- else
67
- merged[key] = value
68
- end
69
- end
70
- merged
71
- end
72
-
73
- end
74
- end
75
- end
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators"
4
-
5
- module BetterTranslate
6
- module Generators
7
- # Rails generator for analyzing translation files to find similar content.
8
- # Uses the SimilarityAnalyzer to identify potentially redundant translations
9
- # across locale files and generates both JSON and human-readable reports.
10
- #
11
- # @example
12
- # rails generate better_translate:analyze
13
- class AnalyzeGenerator < Rails::Generators::Base
14
- desc "Analyze translation files for similarities"
15
-
16
- # Main generator method that analyzes translation files for similarities.
17
- # Finds all YAML files in the config/locales directory, runs the analysis,
18
- # and displays a summary of the results.
19
- #
20
- # The analysis uses the Levenshtein distance algorithm to identify strings
21
- # that are similar but not identical, which could indicate redundant translations.
22
- #
23
- # @return [void]
24
- def analyze_translations
25
- say "Starting translation similarity analysis...", :blue
26
-
27
- # Find all YAML files in the locales directory
28
- locale_dir = Rails.root.join("config", "locales")
29
- yaml_files = Dir[locale_dir.join("*.yml")]
30
-
31
- if yaml_files.empty?
32
- say "No YAML files found in #{locale_dir}", :red
33
- return
34
- end
35
-
36
- say "Found #{yaml_files.length} YAML files to analyze", :green
37
-
38
- # Run analysis
39
- analyzer = BetterTranslate::SimilarityAnalyzer.new(yaml_files)
40
- analyzer.analyze
41
-
42
- # Show results
43
- say "\nAnalysis complete!", :green
44
- say "Reports generated:", :green
45
- say " * #{BetterTranslate::SimilarityAnalyzer::REPORT_FILE} (detailed JSON report)"
46
- say " * translation_similarities_summary.txt (human-readable summary)"
47
-
48
- # Show quick summary from the text file
49
- if File.exist?("translation_similarities_summary.txt")
50
- summary = File.read("translation_similarities_summary.txt")
51
- say "\nQuick Summary:", :blue
52
- say summary
53
- end
54
- end
55
- end
56
- end
57
- end
@@ -1,14 +0,0 @@
1
- require 'rails/generators'
2
-
3
- module BetterTranslate
4
- module Generators
5
- class InstallGenerator < Rails::Generators::Base
6
- source_root File.expand_path('templates', __dir__)
7
- desc "Generates the config/initializers/better_translate.rb file with default configuration"
8
-
9
- def copy_initializer
10
- template "better_translate.rb", "config/initializers/better_translate.rb"
11
- end
12
- end
13
- end
14
- end
@@ -1,56 +0,0 @@
1
- BetterTranslate.configure do |config|
2
- # Choose the provider to use: :chatgpt, :gemini, or any custom provider registered with BetterTranslate::Service.register_provider
3
- config.provider = :chatgpt
4
-
5
- # API key for OpenAI
6
- config.openai_key = ENV.fetch("OPENAI_API_KEY") { "YOUR_OPENAI_API_KEY" }
7
-
8
- # API key for Google Gemini
9
- config.google_gemini_key = ENV.fetch("GOOGLE_GEMINI_KEY") { "YOUR_GOOGLE_GEMINI_KEY" }
10
-
11
- # Custom provider API keys
12
- # If you've created a custom provider using 'rails generate better_translate:provider YourProvider',
13
- # add its API key here following the naming convention: config.your_provider_key
14
- #
15
- # Example for a custom DeepL provider:
16
- # config.deepl_key = ENV.fetch("DEEPL_API_KEY") { "YOUR_DEEPL_API_KEY" }
17
-
18
- # Source language (for example "en" if the source file is in English)
19
- config.source_language = "en"
20
-
21
- # List of target languages (short_name and name)
22
- config.target_languages = [
23
- # { short_name: 'es', name: 'spagnolo' },
24
- # { short_name: 'it', name: 'italiano' },
25
- # { short_name: 'fr', name: 'francese' },
26
- # { short_name: 'de', name: 'tedesco' },
27
- # { short_name: 'pt', name: 'portoghese' },
28
- { short_name: "ru", name: "russian" }
29
- ]
30
-
31
- # Global exclusions (paths in dot notation) to exclude for all languages
32
- config.global_exclusions = [
33
- "key.value"
34
- ]
35
-
36
- # Language-specific exclusions
37
- config.exclusions_per_language = {
38
- "es" => [],
39
- "it" => [],
40
- "fr" => [],
41
- "de" => [],
42
- "pt" => [],
43
- "ru" => []
44
- }
45
-
46
- # Input file path (e.g. en.yml)
47
- config.input_file = Rails.root.join("config", "locales", "en.yml").to_s
48
-
49
- # Output folder where translated files will be saved
50
- config.output_folder = Rails.root.join("config", "locales", "translated").to_s
51
-
52
- # Translation method:
53
- # - :override => regenerates all translations
54
- # - :incremental => updates only missing keys (or those that have been modified)
55
- config.translation_method = :override
56
- end
@@ -1,84 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails/generators'
4
-
5
- module BetterTranslate
6
- module Generators
7
- # Rails generator for executing translations with BetterTranslate.
8
- # This generator validates the configuration and starts the translation process.
9
- #
10
- # @example
11
- # rails generate better_translate:translate
12
- class TranslateGenerator < Rails::Generators::Base
13
- desc "Starts the translation process configured in BetterTranslate"
14
-
15
- # Main generator method that initiates the translation process.
16
- # Validates the configuration before starting and provides status messages.
17
- #
18
- # @return [void]
19
- def translate
20
- say "Starting translation with BetterTranslate...", :blue
21
-
22
- # Verifica che la configurazione sia valida
23
- if validate_configuration
24
- say "Configuration validated. Starting translation...", :green
25
- BetterTranslate.magic
26
- say "Translation completed.", :green
27
- else
28
- say "Translation aborted due to configuration issues.", :red
29
- end
30
- end
31
-
32
- private
33
-
34
- # Validates the BetterTranslate configuration.
35
- # Checks for required settings and reports any issues found.
36
- #
37
- # @return [Boolean] true if the configuration is valid, false otherwise
38
- def validate_configuration
39
- valid = true
40
-
41
- # Verifica che il file di input esista
42
- unless BetterTranslate.configuration.respond_to?(:input_file)
43
- say "Error: input_file not configured. Please check your initializer.", :red
44
- return false
45
- end
46
-
47
- input_file = BetterTranslate.configuration.input_file
48
- unless File.exist?(input_file)
49
- say "Error: Input file not found: #{input_file}", :red
50
- valid = false
51
- end
52
-
53
- # Verifica che ci siano lingue target attive
54
- if !BetterTranslate.configuration.respond_to?(:target_languages) ||
55
- BetterTranslate.configuration.target_languages.empty?
56
- say "Error: No target languages configured. Please uncomment or add target languages in your initializer.", :red
57
- valid = false
58
- end
59
-
60
- # Verifica che il provider sia configurato
61
- if !BetterTranslate.configuration.respond_to?(:provider)
62
- say "Error: No provider configured. Please set config.provider in your initializer.", :red
63
- valid = false
64
- end
65
-
66
- # Verifica che la chiave API sia configurata per il provider selezionato
67
- if BetterTranslate.configuration.respond_to?(:provider)
68
- provider = BetterTranslate.configuration.provider
69
- if provider == :chatgpt && (!BetterTranslate.configuration.respond_to?(:openai_key) ||
70
- BetterTranslate.configuration.openai_key == "YOUR_OPENAI_API_KEY")
71
- say "Error: OpenAI API key not configured. Please set config.openai_key in your initializer.", :red
72
- valid = false
73
- elsif provider == :gemini && (!BetterTranslate.configuration.respond_to?(:google_gemini_key) ||
74
- BetterTranslate.configuration.google_gemini_key == "YOUR_GOOGLE_GEMINI_KEY")
75
- say "Error: Gemini API key not configured. Please set config.google_gemini_key in your initializer.", :red
76
- valid = false
77
- end
78
- end
79
-
80
- valid
81
- end
82
- end
83
- end
84
- end