better_translate 0.3.0 → 0.4.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.
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "set"
5
+ require "json"
6
+ require "time"
7
+
8
+ module BetterTranslate
9
+ class SimilarityAnalyzer
10
+ SIMILARITY_THRESHOLD = 0.75 # Abbassiamo la soglia per trovare più similarità
11
+ REPORT_FILE = "translation_similarities.json"
12
+
13
+ def initialize(yaml_files)
14
+ @yaml_files = yaml_files
15
+ @similarities = {}
16
+ end
17
+
18
+ def analyze
19
+ translations_by_language = load_translations
20
+ find_similarities(translations_by_language)
21
+ generate_report
22
+ end
23
+
24
+ private
25
+
26
+ def load_translations
27
+ translations = {}
28
+ puts "Loading YAML files..."
29
+
30
+ @yaml_files.each do |file|
31
+ lang_code = File.basename(file, ".yml")
32
+ translations[lang_code] = YAML.load_file(file)
33
+ puts " - Loaded #{lang_code}.yml"
34
+ end
35
+
36
+ translations
37
+ end
38
+
39
+ def find_similarities(translations_by_language)
40
+ translations_by_language.each do |lang, translations|
41
+ puts "\nAnalyzing #{lang} translations..."
42
+ flattened = flatten_translations(translations)
43
+ keys = flattened.keys
44
+ similar_found = 0
45
+
46
+ keys.each_with_index do |key1, i|
47
+ value1 = flattened[key1]
48
+
49
+ # Confronta solo con le chiavi successive per evitare duplicati
50
+ keys[(i + 1)..-1].each do |key2|
51
+ value2 = flattened[key2]
52
+
53
+ similarity = calculate_similarity(value1.to_s, value2.to_s)
54
+ if similarity >= SIMILARITY_THRESHOLD
55
+ record_similarity(lang, key1, key2, value1, value2, similarity)
56
+ similar_found += 1
57
+ end
58
+ end
59
+ end
60
+
61
+ puts " Found #{similar_found} similar translations"
62
+ end
63
+ end
64
+
65
+ def flatten_translations(hash, prefix = "", result = {})
66
+ hash.each do |key, value|
67
+ current_key = prefix.empty? ? key.to_s : "#{prefix}.#{key}"
68
+
69
+ if value.is_a?(Hash)
70
+ flatten_translations(value, current_key, result)
71
+ else
72
+ result[current_key] = value
73
+ end
74
+ end
75
+
76
+ result
77
+ end
78
+
79
+ def calculate_similarity(str1, str2)
80
+ # Implementazione della distanza di Levenshtein normalizzata
81
+ matrix = Array.new(str1.length + 1) { Array.new(str2.length + 1) }
82
+
83
+ (0..str1.length).each { |i| matrix[i][0] = i }
84
+ (0..str2.length).each { |j| matrix[0][j] = j }
85
+
86
+ (1..str1.length).each do |i|
87
+ (1..str2.length).each do |j|
88
+ cost = str1[i-1] == str2[j-1] ? 0 : 1
89
+ matrix[i][j] = [
90
+ matrix[i-1][j] + 1,
91
+ matrix[i][j-1] + 1,
92
+ matrix[i-1][j-1] + cost
93
+ ].min
94
+ end
95
+ end
96
+
97
+ max_length = [str1.length, str2.length].max
98
+ 1 - (matrix[str1.length][str2.length].to_f / max_length)
99
+ end
100
+
101
+ def record_similarity(lang, key1, key2, value1, value2, similarity)
102
+ @similarities[lang] ||= []
103
+ @similarities[lang] << {
104
+ key1: key1,
105
+ key2: key2,
106
+ value1: value1,
107
+ value2: value2,
108
+ similarity: similarity.round(2)
109
+ }
110
+ end
111
+
112
+ def generate_report
113
+ puts "\nGenerating reports..."
114
+ report = {
115
+ generated_at: Time.now.iso8601,
116
+ similarity_threshold: SIMILARITY_THRESHOLD,
117
+ findings: @similarities
118
+ }
119
+
120
+ File.write(REPORT_FILE, JSON.pretty_generate(report))
121
+ puts " - Generated #{REPORT_FILE}"
122
+
123
+ summary = generate_summary(report)
124
+ File.write("translation_similarities_summary.txt", summary)
125
+ puts " - Generated translation_similarities_summary.txt"
126
+ end
127
+
128
+ def generate_summary(report)
129
+ summary = ["Translation Similarities Report", "=" * 30, ""]
130
+
131
+ report[:findings].each do |lang, similarities|
132
+ summary << "Language: #{lang}"
133
+ summary << "-" * 20
134
+
135
+ similarities.each do |sim|
136
+ summary << "Similar translations found:"
137
+ summary << " Key 1: #{sim[:key1]}"
138
+ summary << " Value 1: #{sim[:value1]}"
139
+ summary << " Key 2: #{sim[:key2]}"
140
+ summary << " Value 2: #{sim[:value2]}"
141
+ summary << " Similarity: #{(sim[:similarity] * 100).round(1)}%"
142
+ summary << ""
143
+ end
144
+
145
+ summary << ""
146
+ end
147
+
148
+ summary.join("\n")
149
+ end
150
+ end
151
+ end
@@ -2,65 +2,75 @@ module BetterTranslate
2
2
  class Translator
3
3
  class << self
4
4
  def work
5
- puts "Avvio della traduzione dei file..."
5
+ message = "Starting file translation..."
6
+ BetterTranslate::Utils.logger(message: message)
6
7
 
7
8
  translations = read_yml_source
8
9
 
9
- # Rimuove le chiavi da escludere (global_exclusions) dalla struttura letta
10
+ # Removes the keys to exclude (global_exclusions) from the read structure
10
11
  global_filtered_translations = remove_exclusions(
11
12
  translations, BetterTranslate.configuration.global_exclusions
12
13
  )
13
14
 
14
- BetterTranslate.configuration.target_languages.each do |target_lang|
15
+ start_time = Time.now
16
+ threads = BetterTranslate.configuration.target_languages.map do |target_lang|
17
+ Thread.new do
15
18
 
16
- # Fase 2: Applica il filtro specifico per la lingua target
19
+ # Phase 2: Apply the target language specific filter
17
20
  lang_exclusions = BetterTranslate.configuration.exclusions_per_language[target_lang[:short_name]] || []
18
21
  filtered_translations = remove_exclusions(
19
22
  global_filtered_translations, lang_exclusions
20
23
  )
21
24
 
22
- puts "Inizio traduzione da #{BetterTranslate.configuration.source_language} a #{target_lang[:short_name]}"
25
+ message = "Starting translation from #{BetterTranslate.configuration.source_language} to #{target_lang[:short_name]}"
26
+ BetterTranslate::Utils.logger(message: message)
23
27
  service = BetterTranslate::Service.new
24
28
  translated_data = translate_with_progress(filtered_translations, service, target_lang[:short_name], target_lang[:name])
25
29
  BetterTranslate::Writer.write_translations(translated_data, target_lang[:short_name])
26
- puts "Traduzione completata da #{BetterTranslate.configuration.source_language} a #{target_lang[:short_name]}"
30
+ end_time = Time.now
31
+ duration = end_time - start_time
32
+ BetterTranslate::Utils.track_metric("translation_duration", duration)
33
+
34
+ message = "Translation completed from #{BetterTranslate.configuration.source_language} to #{target_lang[:short_name]} in #{duration.round(2)} seconds"
35
+ BetterTranslate::Utils.logger(message: message)
36
+ end
27
37
  end
28
38
  end
29
39
 
30
40
  private
31
41
 
32
- # Legge il file YAML in base al percorso fornito.
42
+ # Reads the YAML file based on the provided path.
33
43
  #
34
- # @param file_path [String] percorso del file YAML da leggere
35
- # @return [Hash] struttura dati contenente le traduzioni
36
- # @raise [StandardError] se il file non esiste
44
+ # @param file_path [String] path of the YAML file to read
45
+ # @return [Hash] data structure containing the translations
46
+ # @raise [StandardError] if the file does not exist
37
47
  def read_yml_source
38
48
  file_path = BetterTranslate.configuration.input_file
39
49
  unless File.exist?(file_path)
40
- raise "File non trovato: #{file_path}"
50
+ raise "File not found: #{file_path}"
41
51
  end
42
52
 
43
53
  YAML.load_file(file_path)
44
54
  end
45
55
 
46
- # Rimuove le chiavi globali da escludere dalla struttura dati,
47
- # calcolando i percorsi a partire dal contenuto della lingua di partenza.
56
+ # Removes the global keys to exclude from the data structure,
57
+ # calculating paths starting from the source language content.
48
58
  #
49
- # Ad esempio, se il file YAML è:
59
+ # For example, if the YAML file is:
50
60
  # { "en" => { "sample" => { "valid" => "valid", "excluded" => "Excluded" } } }
51
- # e global_exclusions = ["sample.excluded"],
52
- # il risultato sarà:
61
+ # and global_exclusions = ["sample.excluded"],
62
+ # the result will be:
53
63
  # { "en" => { "sample" => { "valid" => "valid" } } }
54
64
  #
55
- # @param data [Hash, Array, Object] La struttura dati da filtrare.
56
- # @param global_exclusions [Array<String>] Lista dei percorsi (in dot notation) da escludere globalmente.
57
- # @param current_path [Array] Il percorso corrente (usato in maniera ricorsiva, default: []).
58
- # @return [Hash, Array, Object] La struttura dati filtrata.
65
+ # @param data [Hash, Array, Object] The data structure to filter.
66
+ # @param global_exclusions [Array<String>] List of paths (in dot notation) to exclude globally.
67
+ # @param current_path [Array] The current path (used recursively, default: []).
68
+ # @return [Hash, Array, Object] The filtered data structure.
59
69
  def remove_exclusions(data, exclusion_list, current_path = [])
60
70
  if data.is_a?(Hash)
61
71
  data.each_with_object({}) do |(key, value), result|
62
- # Se siamo al livello top-level e la chiave corrisponde alla lingua di partenza,
63
- # resettare il percorso (così da escludere "en" dal percorso finale)
72
+ # If we are at the top-level and the key matches the source language,
73
+ # reset the path (to exclude "en" from the final path)
64
74
  new_path = if current_path.empty? && key == BetterTranslate.configuration.source_language
65
75
  []
66
76
  else
@@ -81,14 +91,14 @@ module BetterTranslate
81
91
  end
82
92
  end
83
93
 
84
- # Metodo ricorsivo che percorre la struttura, traducendo ogni stringa e aggiornando il progresso.
94
+ # Recursive method that traverses the structure, translating each string and updating progress.
85
95
  #
86
- # @param data [Hash, Array, String] La struttura dati da tradurre.
87
- # @param provider [Object] Il provider che risponde al metodo translate.
88
- # @param target_lang_code [String] Codice della lingua target (es. "en").
89
- # @param target_lang_name [String] Nome della lingua target (es. "English").
90
- # @param progress [Hash] Un hash con le chiavi :count e :total per monitorare il progresso.
91
- # @return [Hash, Array, String] La struttura tradotta.
96
+ # @param data [Hash, Array, String] The data structure to translate.
97
+ # @param provider [Object] The provider that responds to the translate method.
98
+ # @param target_lang_code [String] Target language code (e.g. "en").
99
+ # @param target_lang_name [String] Target language name (e.g. "English").
100
+ # @param progress [Hash] A hash with :count and :total keys to monitor progress.
101
+ # @return [Hash, Array, String] The translated structure.
92
102
  def deep_translate_with_progress(data, service, target_lang_code, target_lang_name, progress)
93
103
  if data.is_a?(Hash)
94
104
  data.each_with_object({}) do |(key, value), result|
@@ -106,20 +116,90 @@ module BetterTranslate
106
116
  end
107
117
  end
108
118
 
109
- # Metodo principale per tradurre l'intera struttura dati, con monitoraggio del progresso.
119
+ # Main method to translate the entire data structure, with progress monitoring.
110
120
  #
111
- # @param data [Hash, Array, String] la struttura dati da tradurre
112
- # @param provider [Object] il provider da usare per tradurre (deve implementare translate)
113
- # @param target_lang_code [String] codice della lingua target
114
- # @param target_lang_name [String] nome della lingua target
115
- # @return la struttura tradotta
121
+ # @param data [Hash, Array, String] the data structure to translate
122
+ # @param provider [Object] the provider to use for translation (must implement translate)
123
+ # @param target_lang_code [String] target language code
124
+ # @param target_lang_name [String] target language name
125
+ # @return the translated structure
116
126
  def translate_with_progress(data, service, target_lang_code, target_lang_name)
117
127
  total = count_strings(data)
118
128
  progress = ProgressBar.create(total: total, format: '%a %B %p%% %t')
119
- deep_translate_with_progress(data, service, target_lang_code, target_lang_name, progress)
129
+
130
+ start_time = Time.now
131
+ result = if total > 50 # Usa il batch processing per dataset grandi
132
+ batch_translate_with_progress(data, service, target_lang_code, target_lang_name, progress)
133
+ else
134
+ deep_translate_with_progress(data, service, target_lang_code, target_lang_name, progress)
135
+ end
136
+
137
+ duration = Time.now - start_time
138
+ BetterTranslate::Utils.track_metric("translation_method_duration", {
139
+ method: total > 50 ? 'batch' : 'deep',
140
+ duration: duration,
141
+ total_strings: total
142
+ })
143
+
144
+ result
145
+ end
146
+
147
+ def batch_translate_with_progress(data, service, target_lang_code, target_lang_name, progress)
148
+ texts = extract_translatable_texts(data)
149
+ translations = {}
150
+
151
+ texts.each_slice(10).each_with_index do |batch, index|
152
+ batch_start = Time.now
153
+
154
+ batch_translations = batch.map do |text|
155
+ translated = service.translate(text, target_lang_code, target_lang_name)
156
+ progress.increment
157
+ [text, translated]
158
+ end.to_h
159
+
160
+ translations.merge!(batch_translations)
161
+
162
+ batch_duration = Time.now - batch_start
163
+ BetterTranslate::Utils.track_metric("batch_translation_duration", {
164
+ batch_number: index + 1,
165
+ size: batch.size,
166
+ duration: batch_duration
167
+ })
168
+ end
169
+
170
+ replace_translations(data, translations)
171
+ end
172
+
173
+ def extract_translatable_texts(data)
174
+ texts = Set.new
175
+ traverse_structure(data) do |value|
176
+ texts.add(value) if value.is_a?(String) && !value.strip.empty?
177
+ end
178
+ texts.to_a
179
+ end
180
+
181
+ def replace_translations(data, translations)
182
+ traverse_structure(data) do |value|
183
+ if value.is_a?(String) && !value.strip.empty? && translations.key?(value)
184
+ translations[value]
185
+ else
186
+ value
187
+ end
188
+ end
189
+ end
190
+
191
+ def traverse_structure(data, &block)
192
+ case data
193
+ when Hash
194
+ data.transform_values { |v| traverse_structure(v, &block) }
195
+ when Array
196
+ data.map { |v| traverse_structure(v, &block) }
197
+ else
198
+ yield data
199
+ end
120
200
  end
121
201
 
122
- # Conta ricorsivamente il numero di stringhe traducibili nella struttura dati.
202
+ # Recursively counts the number of translatable strings in the data structure.
123
203
  def count_strings(data)
124
204
  if data.is_a?(Hash)
125
205
  data.values.sum { |v| count_strings(v) }
@@ -4,21 +4,21 @@
4
4
  #
5
5
  # = BetterSeeder::Utils
6
6
  #
7
- # Questo modulo fornisce metodi di utilità per la gestione dei seed. In particolare,
8
- # consente di trasformare i nomi delle classi in formato snake_case con il suffisso "_structure.rb",
9
- # gestire i messaggi di log e configurare il livello del logger per ActiveRecord.
7
+ # This module provides utility methods for seed management. In particular,
8
+ # allows transforming class names into snake_case format with the "_structure.rb" suffix,
9
+ # manage log messages and configure the logger level for ActiveRecord.
10
10
 
11
11
  module BetterTranslate
12
12
  class Utils
13
13
  class << self
14
14
  ##
15
- # Registra un messaggio usando il logger di Rails se disponibile, altrimenti lo stampa su standard output.
15
+ # Logs a message using the Rails logger if available, otherwise prints it to standard output.
16
16
  #
17
17
  # ==== Parametri
18
- # * +message+ - Il messaggio da loggare (può essere una stringa o nil).
18
+ # * +message+ - The message to log (can be a string or nil).
19
19
  #
20
20
  # ==== Ritorno
21
- # Non ritorna un valore significativo.
21
+ # Does not return a significant value.
22
22
  #
23
23
  def logger(message: nil)
24
24
  if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
@@ -27,6 +27,23 @@ module BetterTranslate
27
27
  puts message
28
28
  end
29
29
  end
30
+
31
+ def track_metric(name, value)
32
+ @metrics ||= {}
33
+ @metrics[name] ||= []
34
+ @metrics[name] << { value: value, timestamp: Time.now }
35
+
36
+ # Mantieni solo le ultime 1000 metriche per tipo
37
+ @metrics[name] = @metrics[name].last(1000) if @metrics[name].size > 1000
38
+ end
39
+
40
+ def get_metrics
41
+ @metrics || {}
42
+ end
43
+
44
+ def clear_metrics
45
+ @metrics = {}
46
+ end
30
47
  end
31
48
  end
32
49
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BetterTranslate
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -1,19 +1,19 @@
1
1
  module BetterTranslate
2
2
  class Writer
3
3
  class << self
4
- # Scrive il file di traduzione per una lingua target.
5
- # Se il metodo di traduzione è :override, il file viene riscritto da zero;
6
- # se è :incremental, il file esistente viene aggiornato inserendo le nuove traduzioni nelle posizioni corrette.
4
+ # Writes the translation file for a target language.
5
+ # If the translation method is :override, the file is rewritten from scratch;
6
+ # if it's :incremental, the existing file is updated by inserting new translations in the correct positions.
7
7
  #
8
- # @param translated_data [Hash] La struttura dati tradotta (ad es. { "sample" => { "valid" => "tradotto", "new_key" => "nuova traduzione" } }).
9
- # @param target_lang_code [String] Codice della lingua target (es. "ru").
8
+ # @param translated_data [Hash] The translated data structure (e.g. { "sample" => { "valid" => "translated", "new_key" => "new translation" } }).
9
+ # @param target_lang_code [String] Target language code (e.g. "ru").
10
10
  def write_translations(translated_data, target_lang_code)
11
11
  output_folder = BetterTranslate.configuration.output_folder
12
12
  output_file = File.join(output_folder, "#{target_lang_code}.yml")
13
13
 
14
- # Riformatta la struttura per utilizzare il codice target come chiave principale.
14
+ # Reformats the structure to use the target code as the main key.
15
15
  output_content = if translated_data.is_a?(Hash) && translated_data.key?(BetterTranslate.configuration.source_language)
16
- # Sostituisce la chiave della lingua di partenza con quella target.
16
+ # Replaces the source language key with the target one.
17
17
  { target_lang_code => translated_data[BetterTranslate.configuration.source_language] }
18
18
  else
19
19
  { target_lang_code => translated_data }
@@ -23,11 +23,13 @@ module BetterTranslate
23
23
  existing_data = YAML.load_file(output_file)
24
24
  merged = deep_merge(existing_data, output_content)
25
25
  File.write(output_file, merged.to_yaml(line_width: -1))
26
- puts "File aggiornato in modalità incremental: #{output_file}"
26
+ message = "File updated in incremental mode: #{output_file}"
27
+ BetterTranslate::Utils.logger(message: message)
27
28
  else
28
29
  FileUtils.mkdir_p(output_folder) unless Dir.exist?(output_folder)
29
30
  File.write(output_file, output_content.to_yaml(line_width: -1))
30
- puts "File riscritto in modalità override: #{output_file}"
31
+ message = "File rewritten in override mode: #{output_file}"
32
+ BetterTranslate::Utils.logger(message: message)
31
33
  end
32
34
  end
33
35
 
@@ -35,12 +37,12 @@ module BetterTranslate
35
37
 
36
38
  # Metodo di deep merge: unisce in modo ricorsivo i due hash.
37
39
  # Se una chiave esiste in entrambi gli hash e i valori sono hash, li unisce ricorsivamente.
38
- # Altrimenti, se la chiave esiste già nell'hash esistente, la mantiene e non la sovrascrive.
40
+ # Otherwise, if the key already exists in the existing hash, it keeps it and doesn't overwrite it.
39
41
  # Se la chiave non esiste, la aggiunge.
40
42
  #
41
- # @param existing [Hash] hash esistente (file corrente)
42
- # @param new_data [Hash] nuovo hash con le traduzioni da unire
43
- # @return [Hash] hash unito
43
+ # @param existing [Hash] existing hash (current file)
44
+ # @param new_data [Hash] new hash with translations to merge
45
+ # @return [Hash] merged hash
44
46
  def deep_merge(existing, new_data)
45
47
  merged = existing.dup
46
48
  new_data.each do |key, value|
@@ -48,8 +50,8 @@ module BetterTranslate
48
50
  if merged[key].is_a?(Hash) && value.is_a?(Hash)
49
51
  merged[key] = deep_merge(merged[key], value)
50
52
  else
51
- # Se la chiave esiste già, non sovrascrivo il valore (modalità incrementale)
52
- # oppure potresti decidere di aggiornare comunque, a seconda delle esigenze.
53
+ # If the key already exists, don't overwrite the value (incremental mode)
54
+ # or you might decide to update anyway, depending on the requirements.
53
55
  merged[key] = merged[key]
54
56
  end
55
57
  else
@@ -7,50 +7,53 @@ require "better_translate/translator"
7
7
  require "better_translate/service"
8
8
  require "better_translate/writer"
9
9
  require "better_translate/helper"
10
+ require "better_translate/similarity_analyzer"
10
11
 
11
12
  require 'better_translate/providers/base_provider'
12
13
  require 'better_translate/providers/chatgpt_provider'
13
14
  require 'better_translate/providers/gemini_provider'
14
15
 
16
+ require 'ostruct'
17
+
15
18
  module BetterTranslate
16
19
  class << self
17
20
  attr_accessor :configuration
18
21
 
19
- # Metodo per configurare la gemma
22
+ # Method to configure the gem
20
23
  def configure
21
24
  self.configuration ||= OpenStruct.new
22
25
  yield(configuration) if block_given?
23
26
  end
24
27
 
25
- # Metodo install per generare il file di configurazione (initializer)
28
+ # Install method to generate the configuration file (initializer)
26
29
  def install
27
30
  unless defined?(Rails) && Rails.respond_to?(:root)
28
- message = "Il metodo install è disponibile solo in un'applicazione Rails."
31
+ message = "The install method is only available in a Rails application."
29
32
  BetterTranslate::Utils.logger(message: message)
30
33
  return
31
34
  end
32
35
 
33
- # Costruisce il percorso della cartella template all'interno della gemma
36
+ # Builds the path to the template folder inside the gem
34
37
  source = File.expand_path("../generators/better_translate/templates/better_translate.rb", __dir__)
35
38
  destination = File.join(Rails.root, "config", "initializers", "better_translate.rb")
36
39
 
37
40
  if File.exist?(destination)
38
- message = "Il file initializer esiste già: #{destination}"
41
+ message = "The initializer file already exists: #{destination}"
39
42
  BetterTranslate::Utils.logger(message: message)
40
43
  else
41
44
  FileUtils.mkdir_p(File.dirname(destination))
42
45
  FileUtils.cp(source, destination)
43
- message = "Il file initializer esiste già: #{destination}"
46
+ message = "The initializer file already exists: #{destination}"
44
47
  BetterTranslate::Utils.logger(message: message)
45
48
  end
46
49
  end
47
50
 
48
51
  def magic
49
- message = "Metodo magic invocato: eseguirò la traduzione dei file..."
52
+ message = "Magic method invoked: Translation will begin..."
50
53
  BetterTranslate::Utils.logger(message: message)
51
54
 
52
55
  BetterTranslate::Translator.work
53
- message = "Metodo magic invocato: Traduzione completata con successo!"
56
+ message = "Magic method invoked: Translation completed successfully!"
54
57
  BetterTranslate::Utils.logger(message: message)
55
58
  end
56
59
 
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module BetterTranslate
6
+ module Generators
7
+ class AnalyzeGenerator < Rails::Generators::Base
8
+ desc "Analyze translation files for similarities"
9
+
10
+ def analyze_translations
11
+ say "Starting translation similarity analysis...", :blue
12
+
13
+ # Find all YAML files in the locales directory
14
+ locale_dir = Rails.root.join("config", "locales")
15
+ yaml_files = Dir[locale_dir.join("*.yml")]
16
+
17
+ if yaml_files.empty?
18
+ say "No YAML files found in #{locale_dir}", :red
19
+ return
20
+ end
21
+
22
+ say "Found #{yaml_files.length} YAML files to analyze", :green
23
+
24
+ # Run analysis
25
+ analyzer = BetterTranslate::SimilarityAnalyzer.new(yaml_files)
26
+ analyzer.analyze
27
+
28
+ # Show results
29
+ say "\nAnalysis complete!", :green
30
+ say "Reports generated:", :green
31
+ say " * #{BetterTranslate::SimilarityAnalyzer::REPORT_FILE} (detailed JSON report)"
32
+ say " * translation_similarities_summary.txt (human-readable summary)"
33
+
34
+ # Show quick summary from the text file
35
+ if File.exist?("translation_similarities_summary.txt")
36
+ summary = File.read("translation_similarities_summary.txt")
37
+ say "\nQuick Summary:", :blue
38
+ say summary
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -4,7 +4,7 @@ module BetterTranslate
4
4
  module Generators
5
5
  class InstallGenerator < Rails::Generators::Base
6
6
  source_root File.expand_path('templates', __dir__)
7
- desc "Genera il file config/initializers/better_translate.rb con la configurazione di default"
7
+ desc "Generates the config/initializers/better_translate.rb file with default configuration"
8
8
 
9
9
  def copy_initializer
10
10
  template "better_translate.rb", "config/initializers/better_translate.rb"