better_translate 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +91 -21
- data/lib/better_translate/helper.rb +75 -0
- data/lib/better_translate/translator.rb +14 -9
- data/lib/better_translate/utils.rb +32 -0
- data/lib/better_translate/version.rb +1 -1
- data/lib/better_translate.rb +12 -5
- metadata +14 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1110968d8e49f85d5231775f9c05fcbca610021a33723999c75246b687f56b77
|
4
|
+
data.tar.gz: 255e51ff5e5105ebf314b703d9aa841c66eaa6b0ffb5ca1f631ea2cbe81ab6db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b971940521bce1ad359990e13fe7d17a339f9d5e62fe5ea9b565fe1ffbd51fe2c2dd24789cd02b7e838a20a3ae88de919ed529adf325b3c11d7377c6bced68e5
|
7
|
+
data.tar.gz: 1d8d785607ba4439df35ceb70b0c302ba1944bfdd74e197d2686cbe7781cfab55bfc93ed7a2affa9ef50b5fc1a459034b1d3cdf6f60420cb2df1b0252d5e3ac5
|
data/README.md
CHANGED
@@ -15,15 +15,23 @@ Configuration is centralized via an initializer (for example, in a Rails app), w
|
|
15
15
|
- **Override**: Rewrites the file from scratch.
|
16
16
|
- **Incremental**: Updates only missing or modified keys.
|
17
17
|
- **Centralized Configuration**: Configured via an initializer with settings for API keys, source language, target languages, exclusions (using dot notation), and the output folder.
|
18
|
+
- **Two-Step Exclusion Filtering**:
|
19
|
+
- **Global Exclusions**: Removes keys defined in `global_exclusions` from the entire YAML structure.
|
20
|
+
- **Language-Specific Exclusions**: Applies additional filtering using the `exclusions_per_language` map for each target language.
|
18
21
|
- **Progress Bar**: Displays translation progress using ruby-progressbar.
|
19
|
-
- **Generators**:
|
22
|
+
- **Rails Generators**:
|
23
|
+
- `rails generate better_translate:install` to generate the initializer.
|
24
|
+
- `rails generate better_translate:translate` to trigger the translation process directly from your Rails app.
|
25
|
+
- **Translation Helpers**:
|
26
|
+
- `translate_text_to_languages` for translating a single text into multiple target languages.
|
27
|
+
- `translate_texts_to_languages` for translating an array of texts into multiple target languages.
|
20
28
|
|
21
29
|
## Installation
|
22
30
|
|
23
31
|
Add the gem to your Gemfile:
|
24
32
|
|
25
33
|
```ruby
|
26
|
-
gem 'better_translate'
|
34
|
+
gem 'better_translate', '~> 0.1.0'
|
27
35
|
```
|
28
36
|
|
29
37
|
Then run:
|
@@ -76,8 +84,13 @@ BetterTranslate.configure do |config|
|
|
76
84
|
"key.child_key"
|
77
85
|
]
|
78
86
|
|
79
|
-
# Language-specific exclusions
|
87
|
+
# Language-specific exclusions: keys to exclude only for specific target languages
|
80
88
|
config.exclusions_per_language = {
|
89
|
+
"es" => [],
|
90
|
+
"it" => ["sample.valid"],
|
91
|
+
"fr" => [],
|
92
|
+
"de" => [],
|
93
|
+
"pt" => [],
|
81
94
|
"ru" => []
|
82
95
|
}
|
83
96
|
|
@@ -85,7 +98,7 @@ BetterTranslate.configure do |config|
|
|
85
98
|
config.input_file = Rails.root.join("config", "locales", "en.yml").to_s
|
86
99
|
|
87
100
|
# Translation mode: :override or :incremental
|
88
|
-
config.
|
101
|
+
config.translation_mode = :override
|
89
102
|
end
|
90
103
|
```
|
91
104
|
|
@@ -101,28 +114,89 @@ BetterTranslate.magic
|
|
101
114
|
|
102
115
|
This will execute the process that:
|
103
116
|
1. Reads the input YAML file.
|
104
|
-
2. Applies
|
105
|
-
3.
|
106
|
-
4.
|
117
|
+
2. Applies the global exclusion filtering.
|
118
|
+
3. Applies additional language-specific exclusion filtering for each target language.
|
119
|
+
4. Translates the strings from the source language into the configured target languages.
|
120
|
+
5. Writes the translated files to the output folder, either in **override** or **incremental** mode based on the configuration.
|
107
121
|
|
108
122
|
### Using Rails Generators
|
109
123
|
|
110
|
-
The gem includes
|
124
|
+
The gem includes generators to simplify tasks:
|
111
125
|
|
112
|
-
|
113
|
-
|
126
|
+
- **Generate Initializer:**
|
127
|
+
|
128
|
+
```bash
|
129
|
+
rails generate better_translate:install
|
130
|
+
```
|
131
|
+
|
132
|
+
- **Trigger Translation Process:**
|
133
|
+
|
134
|
+
```bash
|
135
|
+
rails generate better_translate:translate
|
136
|
+
```
|
137
|
+
|
138
|
+
The `better_translate:translate` generator will trigger the translation process (via `BetterTranslate.magic`) and display progress in the terminal.
|
139
|
+
|
140
|
+
### Translation Helpers
|
141
|
+
|
142
|
+
BetterTranslate provides helper methods to simplify translation tasks.
|
143
|
+
|
144
|
+
#### Single Text Translation
|
145
|
+
|
146
|
+
The `translate_text_to_languages` helper allows you to translate a single text into multiple target languages in one call.
|
147
|
+
|
148
|
+
**Example Usage:**
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
text = "Hello world!"
|
152
|
+
target_languages = [
|
153
|
+
{ short_name: "it", name: "Italian" },
|
154
|
+
{ short_name: "fr", name: "French" }
|
155
|
+
]
|
156
|
+
|
157
|
+
translated = BetterTranslate::TranslationHelper.translate_text_to_languages(
|
158
|
+
text,
|
159
|
+
target_languages,
|
160
|
+
"en", # source language code
|
161
|
+
:chatgpt # provider: can be :chatgpt or :gemini
|
162
|
+
)
|
163
|
+
|
164
|
+
puts translated
|
165
|
+
# Expected output:
|
166
|
+
# { "it" => "Ciao mondo!", "fr" => "Bonjour le monde!" }
|
114
167
|
```
|
115
168
|
|
116
|
-
|
169
|
+
#### Multiple Texts Translation
|
117
170
|
|
118
|
-
|
171
|
+
The `translate_texts_to_languages` helper extends the functionality to translate an array of texts into multiple target languages. It returns a hash where each key is a target language code and the value is an array of translated texts.
|
119
172
|
|
120
|
-
|
173
|
+
**Example Usage:**
|
174
|
+
|
175
|
+
```ruby
|
176
|
+
texts = ["Hello world!", "How are you?"]
|
177
|
+
target_languages = [
|
178
|
+
{ short_name: "it", name: "Italian" },
|
179
|
+
{ short_name: "fr", name: "French" }
|
180
|
+
]
|
181
|
+
|
182
|
+
translated_texts = BetterTranslate::TranslationHelper.translate_texts_to_languages(
|
183
|
+
texts,
|
184
|
+
target_languages,
|
185
|
+
"en", # source language code
|
186
|
+
:chatgpt # provider: can be :chatgpt or :gemini
|
187
|
+
)
|
188
|
+
|
189
|
+
puts translated_texts
|
190
|
+
# Expected output:
|
191
|
+
# {
|
192
|
+
# "it" => ["Ciao mondo!", "Come stai?"],
|
193
|
+
# "fr" => ["Bonjour le monde!", "Comment ça va?"]
|
194
|
+
# }
|
195
|
+
```
|
121
196
|
|
122
|
-
##
|
197
|
+
## Contact & Feature Requests
|
123
198
|
|
124
|
-
|
125
|
-
- **Helper Methods**: Additional helper methods to integrate BetterTranslate as a translation system for dynamic content.
|
199
|
+
For suggestions, bug reports, or to request new features, please reach out via email at: **alessio.bussolari@pandev.it**.
|
126
200
|
|
127
201
|
## Conclusions
|
128
202
|
|
@@ -130,10 +204,6 @@ BetterTranslate aims to simplify the translation of YAML files in Ruby projects
|
|
130
204
|
|
131
205
|
For more details, please visit the [GitHub repository](https://github.com/alessiobussolari/better_translate).
|
132
206
|
|
133
|
-
## Changelog
|
134
|
-
|
135
|
-
See the [CHANGELOG](https://github.com/alessiobussolari/better_translate/blob/main/CHANGELOG.md) for a summary of changes.
|
136
|
-
|
137
207
|
## License
|
138
208
|
|
139
|
-
BetterTranslate is distributed under the MIT license. See the [LICENSE](LICENSE) file for more details.
|
209
|
+
BetterTranslate is distributed under the MIT license. See the [LICENSE](LICENSE) file for more details.
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module BetterTranslate
|
2
|
+
class Helper
|
3
|
+
class << self
|
4
|
+
# Translates a given text into multiple target languages.
|
5
|
+
#
|
6
|
+
# @param text [String] The text to be translated.
|
7
|
+
# @param target_languages [Array<Hash>] Array of target language hashes,
|
8
|
+
# e.g. [{ short_name: "it", name: "Italian" }, { short_name: "fr", name: "French" }]
|
9
|
+
# @param source_language [String] The source language code (e.g., "en").
|
10
|
+
# @param provider_name [Symbol] The provider to use (e.g., :chatgpt or :gemini).
|
11
|
+
# @return [Hash] A hash where each key is a target language code and the value is the translated text.
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
# translated = BetterTranslate::Helpers.translate_text_to_languages(
|
15
|
+
# "Hello world!",
|
16
|
+
# [{ short_name: "it", name: "Italian" }, { short_name: "fr", name: "French" }],
|
17
|
+
# "en",
|
18
|
+
# :chatgpt
|
19
|
+
# )
|
20
|
+
# # => { "it" => "Ciao mondo!", "fr" => "Bonjour le monde!" }
|
21
|
+
def translate_text_to_languages(text, target_languages, source_language, provider_name)
|
22
|
+
provider_instance = case provider_name
|
23
|
+
when :chatgpt
|
24
|
+
Providers::ChatgptProvider.new(BetterTranslate.configuration.openai_key)
|
25
|
+
when :gemini
|
26
|
+
Providers::GeminiProvider.new(BetterTranslate.configuration.google_gemini_key)
|
27
|
+
else
|
28
|
+
raise "Provider not supported: #{provider_name}"
|
29
|
+
end
|
30
|
+
|
31
|
+
result = {}
|
32
|
+
target_languages.each do |lang|
|
33
|
+
# Optionally, you could also pass the source_language if needed by your provider.
|
34
|
+
translated_text = provider_instance.translate(text, lang[:short_name], lang[:name])
|
35
|
+
result[lang[:short_name]] = translated_text
|
36
|
+
end
|
37
|
+
result
|
38
|
+
end
|
39
|
+
|
40
|
+
# Translates an array of texts into multiple target languages using the translate_text_to_languages helper.
|
41
|
+
#
|
42
|
+
# @param texts [Array<String>] An array of texts to translate.
|
43
|
+
# @param target_languages [Array<Hash>] Array of target language hashes,
|
44
|
+
# e.g. [{ short_name: "it", name: "Italian" }, { short_name: "fr", name: "French" }].
|
45
|
+
# @param source_language [String] The source language code (e.g., "en").
|
46
|
+
# @param provider_name [Symbol] The provider to use (e.g., :chatgpt or :gemini).
|
47
|
+
# @return [Hash] A hash where each key is a target language code and the value is an array of translated texts.
|
48
|
+
#
|
49
|
+
# Example:
|
50
|
+
# texts = ["Hello world!", "How are you?"]
|
51
|
+
# result = BetterTranslate::TranslationHelper.translate_texts_to_languages(
|
52
|
+
# texts,
|
53
|
+
# [{ short_name: "it", name: "Italian" }, { short_name: "fr", name: "French" }],
|
54
|
+
# "en",
|
55
|
+
# :chatgpt
|
56
|
+
# )
|
57
|
+
# # => { "it" => ["Ciao mondo!", "Come stai?"], "fr" => ["Bonjour le monde!", "Comment ça va?"] }
|
58
|
+
def translate_texts_to_languages(texts, target_languages, source_language, provider_name)
|
59
|
+
result = {}
|
60
|
+
target_languages.each do |lang|
|
61
|
+
# For each target language, translate each text and collect translations into an array.
|
62
|
+
result[lang[:short_name]] = texts.map do |text|
|
63
|
+
translation_hash = translate_text_to_languages(text, [lang], source_language, provider_name)
|
64
|
+
translation_hash[lang[:short_name]]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
result
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
__END__
|
74
|
+
|
75
|
+
translated = BetterTranslate::Helper.translate_text_to_languages("Hello world!",[{ short_name: "it", name: "Italian" }, { short_name: "fr", name: "French" }],"en",:chatgpt)
|
@@ -7,19 +7,24 @@ module BetterTranslate
|
|
7
7
|
translations = read_yml_source
|
8
8
|
|
9
9
|
# Rimuove le chiavi da escludere (global_exclusions) dalla struttura letta
|
10
|
-
|
10
|
+
global_filtered_translations = remove_exclusions(
|
11
11
|
translations, BetterTranslate.configuration.global_exclusions
|
12
12
|
)
|
13
13
|
|
14
14
|
BetterTranslate.configuration.target_languages.each do |target_lang|
|
15
|
+
|
16
|
+
# Fase 2: Applica il filtro specifico per la lingua target
|
17
|
+
lang_exclusions = BetterTranslate.configuration.exclusions_per_language[target_lang[:short_name]] || []
|
18
|
+
filtered_translations = remove_exclusions(
|
19
|
+
global_filtered_translations, lang_exclusions
|
20
|
+
)
|
21
|
+
|
15
22
|
puts "Inizio traduzione da #{BetterTranslate.configuration.source_language} a #{target_lang[:short_name]}"
|
16
23
|
service = BetterTranslate::Service.new
|
17
24
|
translated_data = translate_with_progress(filtered_translations, service, target_lang[:short_name], target_lang[:name])
|
18
25
|
BetterTranslate::Writer.write_translations(translated_data, target_lang[:short_name])
|
19
26
|
puts "Traduzione completata da #{BetterTranslate.configuration.source_language} a #{target_lang[:short_name]}"
|
20
27
|
end
|
21
|
-
|
22
|
-
"Traduzione iniziata! #{filtered_translations.inspect}"
|
23
28
|
end
|
24
29
|
|
25
30
|
private
|
@@ -38,18 +43,18 @@ module BetterTranslate
|
|
38
43
|
YAML.load_file(file_path)
|
39
44
|
end
|
40
45
|
|
41
|
-
# Rimuove le chiavi
|
46
|
+
# Rimuove le chiavi globali da escludere dalla struttura dati,
|
42
47
|
# calcolando i percorsi a partire dal contenuto della lingua di partenza.
|
43
48
|
#
|
44
49
|
# Ad esempio, se il file YAML è:
|
45
|
-
#
|
46
|
-
# e
|
50
|
+
# { "en" => { "sample" => { "valid" => "valid", "excluded" => "Excluded" } } }
|
51
|
+
# e global_exclusions = ["sample.excluded"],
|
47
52
|
# il risultato sarà:
|
48
|
-
#
|
53
|
+
# { "en" => { "sample" => { "valid" => "valid" } } }
|
49
54
|
#
|
50
55
|
# @param data [Hash, Array, Object] La struttura dati da filtrare.
|
51
|
-
# @param
|
52
|
-
# @param current_path [Array] Il percorso corrente (usato in maniera ricorsiva).
|
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: []).
|
53
58
|
# @return [Hash, Array, Object] La struttura dati filtrata.
|
54
59
|
def remove_exclusions(data, exclusion_list, current_path = [])
|
55
60
|
if data.is_a?(Hash)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/better_seeder/utils.rb
|
4
|
+
#
|
5
|
+
# = BetterSeeder::Utils
|
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.
|
10
|
+
|
11
|
+
module BetterTranslate
|
12
|
+
class Utils
|
13
|
+
class << self
|
14
|
+
##
|
15
|
+
# Registra un messaggio usando il logger di Rails se disponibile, altrimenti lo stampa su standard output.
|
16
|
+
#
|
17
|
+
# ==== Parametri
|
18
|
+
# * +message+ - Il messaggio da loggare (può essere una stringa o nil).
|
19
|
+
#
|
20
|
+
# ==== Ritorno
|
21
|
+
# Non ritorna un valore significativo.
|
22
|
+
#
|
23
|
+
def logger(message: nil)
|
24
|
+
if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
|
25
|
+
Rails.logger.info message
|
26
|
+
else
|
27
|
+
puts message
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/better_translate.rb
CHANGED
@@ -2,9 +2,11 @@
|
|
2
2
|
require "ruby-progressbar"
|
3
3
|
|
4
4
|
require "better_translate/version"
|
5
|
+
require "better_translate/utils"
|
5
6
|
require "better_translate/translator"
|
6
7
|
require "better_translate/service"
|
7
8
|
require "better_translate/writer"
|
9
|
+
require "better_translate/helper"
|
8
10
|
|
9
11
|
require 'better_translate/providers/base_provider'
|
10
12
|
require 'better_translate/providers/chatgpt_provider'
|
@@ -23,7 +25,8 @@ module BetterTranslate
|
|
23
25
|
# Metodo install per generare il file di configurazione (initializer)
|
24
26
|
def install
|
25
27
|
unless defined?(Rails) && Rails.respond_to?(:root)
|
26
|
-
|
28
|
+
message = "Il metodo install è disponibile solo in un'applicazione Rails."
|
29
|
+
BetterTranslate::Utils.logger(message: message)
|
27
30
|
return
|
28
31
|
end
|
29
32
|
|
@@ -32,19 +35,23 @@ module BetterTranslate
|
|
32
35
|
destination = File.join(Rails.root, "config", "initializers", "better_translate.rb")
|
33
36
|
|
34
37
|
if File.exist?(destination)
|
35
|
-
|
38
|
+
message = "Il file initializer esiste già: #{destination}"
|
39
|
+
BetterTranslate::Utils.logger(message: message)
|
36
40
|
else
|
37
41
|
FileUtils.mkdir_p(File.dirname(destination))
|
38
42
|
FileUtils.cp(source, destination)
|
39
|
-
|
43
|
+
message = "Il file initializer esiste già: #{destination}"
|
44
|
+
BetterTranslate::Utils.logger(message: message)
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
43
48
|
def magic
|
44
|
-
|
49
|
+
message = "Metodo magic invocato: eseguirò la traduzione dei file..."
|
50
|
+
BetterTranslate::Utils.logger(message: message)
|
45
51
|
|
46
52
|
BetterTranslate::Translator.work
|
47
|
-
|
53
|
+
message = "Metodo magic invocato: Traduzione completata con successo!"
|
54
|
+
BetterTranslate::Utils.logger(message: message)
|
48
55
|
end
|
49
56
|
|
50
57
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: better_translate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- alessio_bussolari
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-03-
|
11
|
+
date: 2025-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: yaml
|
@@ -80,15 +80,14 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '13.0'
|
83
|
-
description: "\nBetterTranslate
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
una progress bar.\n "
|
83
|
+
description: "\nBetterTranslate is a gem that allows you to translate YAML files from
|
84
|
+
a source language into one or more target languages.\nThe gem supports different
|
85
|
+
translation providers, currently ChatGPT (OpenAI) and Google Gemini, and allows
|
86
|
+
you to choose\nthe translation mode: \"override\" to regenerate all translations
|
87
|
+
or \"incremental\" to update only the missing keys.\n\nThe gem's configuration is
|
88
|
+
centralized via an initializer, where you can define API keys, target languages,
|
89
|
+
source language,\nkey exclusions, and the output folder. BetterTranslate also integrates
|
90
|
+
translation progress tracking using a progress bar.\n "
|
92
91
|
email:
|
93
92
|
- alessio.bussolari@pandev.it
|
94
93
|
executables: []
|
@@ -98,11 +97,13 @@ files:
|
|
98
97
|
- LICENSE.txt
|
99
98
|
- README.md
|
100
99
|
- lib/better_translate.rb
|
100
|
+
- lib/better_translate/helper.rb
|
101
101
|
- lib/better_translate/providers/base_provider.rb
|
102
102
|
- lib/better_translate/providers/chatgpt_provider.rb
|
103
103
|
- lib/better_translate/providers/gemini_provider.rb
|
104
104
|
- lib/better_translate/service.rb
|
105
105
|
- lib/better_translate/translator.rb
|
106
|
+
- lib/better_translate/utils.rb
|
106
107
|
- lib/better_translate/version.rb
|
107
108
|
- lib/better_translate/writer.rb
|
108
109
|
- lib/generators/better_translate/install_generator.rb
|
@@ -135,5 +136,6 @@ requirements: []
|
|
135
136
|
rubygems_version: 3.5.11
|
136
137
|
signing_key:
|
137
138
|
specification_version: 4
|
138
|
-
summary:
|
139
|
+
summary: Gem for translating YAML files into multiple languages using providers (ChatGPT
|
140
|
+
and Gemini)
|
139
141
|
test_files: []
|