mistral_translator 0.3.0 → 0.3.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e52138d192d693042abbc570da3a9ed1f7f56acaed881c46a59df100dc476a0
4
- data.tar.gz: 74a169d74c5248dc7ec1cab84c5892018eeacf3ba398bfb0b0a3c41a98d87ae9
3
+ metadata.gz: 242809c8a55ea79c9c436a2fc7b17d7a6deda5372090eaaa43b9a0863e1ba552
4
+ data.tar.gz: b6f86bc08b253f5ea4097e9fa1f3e901e41886067155c2fc595202694ce18acb
5
5
  SHA512:
6
- metadata.gz: 3f324d7cb87b75c340d1875fc6189c13c39dfe26c1878ff187c30c04674b88549c813be6f73c644b2b01a5f28ed5e88da55351c86b37800d9648835113f58b3e
7
- data.tar.gz: 0d9ac452969b457ed81cd34295e564d869c3e8f254e0807a8d473af8c99fbcb10f0d2ea5bc5abea518a0f7bd59d978428dac8e5c25864c63a4fa61d0dfb1617a
6
+ metadata.gz: 6183a2226ee0985e5229c2cb203fed6cfb71ced4c2a0cdb28fba16115f5b6fdf28b860baba50db8f3461e64792267558f3413481e715c54f2f1b5bf0747d3647
7
+ data.tar.gz: a71be86ea71b15e50af048cbba672e5fdecd41e6d3cd1e1313d534d11d2af7747ac593cf36791ad805f9b6db4ff6d6d88853a8b166a046cc45747a66e879bf0c
data/.env.example ADDED
@@ -0,0 +1,3 @@
1
+ # Copy to .env (ignored by git) to run bin/check_api without typing the key.
2
+ # Use a key dedicated to these checks, from a workspace with generation enabled.
3
+ MISTRAL_TEST_API_KEY=
data/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.2] - 2026-10-28
4
+
5
+ ### Fixed
6
+
7
+ - Rich text adapters send the stored ActionText HTML (`to_html`) instead of the rendered one (`to_s`), which wrapped every translation in an extra `<div class="trix-content">` and inlined the rendered attachments. `ActionText::Content` values are now recognised too, not only `ActionText::RichText`.
8
+ - `RecordTranslationService` passes `preserve_html: true` for rich text fields.
9
+ - `RecordTranslationService#translate_to_all_locales` returns `false` when a translation fails. It returned `true`, so failures went unnoticed; successful translations are still saved.
10
+ - `RecordTranslationService`, `Translator` and `Summarizer` stop retrying after a few `RateLimitError`s and raise, instead of retrying forever on top of the client's own backoff.
11
+ - `translate_to_multiple` passes `preserve_html` to each translation; the option was ignored.
12
+ - `translate_with_mistral` raised `ArgumentError` on every call. `from:` is now the source locale and `to:` the target locales, through a new `target_locales:` option of `RecordTranslationService`.
13
+ - A glossary given as a string no longer raises `NoMethodError` in `PromptBuilder`.
14
+ - `BasicRateLimiter` no longer sleeps while holding its lock, which blocked every other thread.
15
+ - HTTP error messages no longer end with a stray brace.
16
+
17
+ ### Changed
18
+
19
+ - CI token restricted to read access, and development dependencies updated (addressable, json, uri).
20
+
21
+ ### Removed
22
+
23
+ - Unused helpers `log_prompt_debug` and `build_html_validation_instruction`.
24
+
25
+ ## [0.3.1] - 2026-10-27
26
+
27
+ ### Fixed
28
+
29
+ - Default model is now `mistral-small-latest`. Mistral retired the `mistral-small` name, so every call without an explicit `config.model` failed with a 404. The alias follows the current Mistral Small version; set `config.model` to pin one.
30
+
31
+ ### Added
32
+
33
+ - `bin/check_api`: checks the API key and the default model, then runs the examples against the real API when the plan allows generation. The key is read from `MISTRAL_TEST_API_KEY`, `.env`, or a hidden prompt, and never printed.
34
+ - Weekly workflow running `bin/check_api`, which opens an issue on failure.
35
+
36
+ ### Changed
37
+
38
+ - CI: a single workflow, RuboCop plus the test suite on Ruby 3.2, 3.3, 3.4 and 4.0.
39
+ - The test suite no longer prints part of the API key, and no longer deletes VCR cassettes after each run.
40
+
3
41
  ## [0.3.0] - 2025-12-09
4
42
 
5
43
  ### Added
data/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Ruby gem for AI-powered translation and text summarization using Mistral AI API, with advanced Rails support.
4
4
 
5
- [![Ruby](https://img.shields.io/badge/ruby-%23CC342D.svg?style=flat&logo=ruby&logoColor=white)](https://www.ruby-lang.org/)
6
- [![Gem Version](https://badge.fury.io/rb/mistral_translator.svg)](https://badge.fury.io/rb/mistral_translator)
7
- [![RSpec](https://img.shields.io/badge/tested%20with-RSpec-red.svg)](https://rspec.info/)
8
- [![RuboCop](https://img.shields.io/badge/code%20style-RuboCop-brightgreen.svg)](https://rubocop.org/)
9
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Gem Version](https://img.shields.io/gem/v/mistral_translator)](https://rubygems.org/gems/mistral_translator)
6
+ [![Downloads](https://img.shields.io/gem/dt/mistral_translator)](https://rubygems.org/gems/mistral_translator)
7
+ [![CI](https://github.com/Peyochanchan/mistral_translator/actions/workflows/ci.yml/badge.svg)](https://github.com/Peyochanchan/mistral_translator/actions/workflows/ci.yml)
8
+ [![Weekly API check](https://github.com/Peyochanchan/mistral_translator/actions/workflows/weekly-api-check.yml/badge.svg)](https://github.com/Peyochanchan/mistral_translator/actions/workflows/weekly-api-check.yml)
9
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.txt)
10
10
 
11
11
  ## Quick Start
12
12
 
@@ -159,7 +159,7 @@ MistralTranslator.configure do |config|
159
159
  config.api_key = ENV['MISTRAL_API_KEY']
160
160
 
161
161
  # Optional
162
- config.model = "mistral-small" # AI model to use
162
+ config.model = "mistral-small-latest" # AI model to use (an alias that follows the current Mistral Small)
163
163
  config.retry_delays = [1, 2, 4, 8, 16] # Retry delays in seconds
164
164
  config.enable_metrics = true # Enable performance metrics
165
165
 
@@ -233,7 +233,7 @@ The complete documentation includes:
233
233
  ## Requirements
234
234
 
235
235
  - Ruby 3.2+
236
- - Mistral AI API key
236
+ - Mistral AI API key, on a plan with API access (Mistral's free plan cannot generate text)
237
237
  - Rails 6.0+ (optional, for Rails integration features)
238
238
 
239
239
  ## Testing
@@ -247,6 +247,10 @@ bundle exec rspec spec/mistral_translator/
247
247
 
248
248
  # Run all tests with documentation format
249
249
  bundle exec rspec --format documentation
250
+
251
+ # Check the API key and default model, then run the examples against the real
252
+ # API (reads MISTRAL_TEST_API_KEY, .env or asks for the key, never prints it)
253
+ bin/check_api
250
254
  ```
251
255
 
252
256
  ### Integration Tests
@@ -11,7 +11,7 @@ Référence complète des options de configuration.
11
11
  ```ruby
12
12
  MistralTranslator.configure do |config|
13
13
  config.api_key = ENV['MISTRAL_API_KEY'] # Obligatoire
14
- config.model = "mistral-small" # Défaut
14
+ config.model = "mistral-small-latest" # Défaut
15
15
  config.api_url = "https://api.mistral.ai" # URL API
16
16
  config.default_max_tokens = 4000 # Limite tokens
17
17
  config.default_temperature = 0.3 # Créativité (0-1)
@@ -268,7 +268,7 @@ Configure la gem avec un bloc.
268
268
  ```ruby
269
269
  MistralTranslator.configure do |config|
270
270
  config.api_key = ENV['MISTRAL_API_KEY']
271
- config.model = "mistral-small"
271
+ config.model = "mistral-small-latest"
272
272
  config.retry_delays = [1, 2, 4, 8]
273
273
  config.enable_metrics = true
274
274
  end
data/docs/installation.md CHANGED
@@ -76,7 +76,7 @@ end
76
76
  ```ruby
77
77
  MistralTranslator.configure do |config|
78
78
  config.api_key = ENV['MISTRAL_API_KEY']
79
- config.model = "mistral-small" # Modèle par défaut
79
+ config.model = "mistral-small-latest" # Modèle par défaut
80
80
  config.retry_delays = [2, 4, 8, 16] # Délais retry
81
81
  config.enable_metrics = true # Suivi des stats
82
82
  config.default_max_tokens = 4000 # Limite tokens
@@ -43,24 +43,35 @@ module MistralTranslator
43
43
  value = get_field_value(field, locale)
44
44
  return false if value.nil?
45
45
 
46
- # Gestion des rich text
47
- if defined?(ActionText::RichText) && value.is_a?(ActionText::RichText)
48
- !value.to_plain_text.to_s.strip.empty?
49
- else
50
- !value.to_s.strip.empty?
51
- end
46
+ text = rich_text?(value) ? value.to_plain_text : value
47
+ !text.to_s.strip.empty?
52
48
  end
53
49
 
54
50
  def get_translatable_content(field, locale)
55
51
  value = get_field_value(field, locale)
56
52
  return nil if value.nil?
57
53
 
58
- # Gestion des rich text - préserver le HTML
59
- if defined?(ActionText::RichText) && value.is_a?(ActionText::RichText)
60
- value.body.to_s
61
- else
62
- value.to_s
63
- end
54
+ rich_text?(value) ? rich_text_html(value) : value.to_s
55
+ end
56
+
57
+ # ActionText::RichText (has_rich_text) ou ActionText::Content (son body)
58
+ def rich_text?(value)
59
+ (defined?(ActionText::RichText) && value.is_a?(ActionText::RichText)) ||
60
+ (defined?(ActionText::Content) && value.is_a?(ActionText::Content))
61
+ end
62
+
63
+ def rich_text_field?(field, locale)
64
+ rich_text?(get_field_value(field, locale))
65
+ end
66
+
67
+ private
68
+
69
+ # HTML tel que stocké, pièces jointes réduites à <action-text-attachment>.
70
+ # to_s rendrait le layout (<div class="trix-content">) et le contenu des
71
+ # pièces jointes, qui seraient alors enregistrés dans la traduction.
72
+ def rich_text_html(value)
73
+ content = value.respond_to?(:body) ? value.body : value
74
+ content&.to_html.to_s
64
75
  end
65
76
  end
66
77
 
@@ -167,16 +178,22 @@ module MistralTranslator
167
178
  # Service de traduction utilisant les adaptateurs
168
179
  module Adapters
169
180
  class RecordTranslationService
170
- def initialize(record, translatable_fields, adapter: nil, source_locale: nil)
181
+ MAX_RATE_LIMIT_RETRIES = 3
182
+
183
+ # target_locales : toutes les locales de l'adaptateur par défaut
184
+ def initialize(record, translatable_fields, adapter: nil, source_locale: nil, target_locales: nil)
171
185
  @record = record
172
186
  @translatable_fields = Array(translatable_fields)
173
187
  @adapter = adapter || Adapters::AdapterFactory.build_for(record)
174
188
  @source_locale = source_locale
189
+ @target_locales = target_locales&.map(&:to_sym)
175
190
  end
176
191
 
192
+ # Enregistre les traductions obtenues ; renvoie false si l'une a échoué.
177
193
  def translate_to_all_locales
178
194
  return false if @translatable_fields.empty?
179
195
 
196
+ @failed = false
180
197
  ActiveRecord::Base.transaction do
181
198
  @translatable_fields.each do |field|
182
199
  translate_field(field)
@@ -184,7 +201,7 @@ module MistralTranslator
184
201
  @adapter.save_record!
185
202
  end
186
203
 
187
- true
204
+ !@failed
188
205
  rescue StandardError => e
189
206
  Rails.logger.error "Translation failed: #{e.message}" if defined?(Rails)
190
207
  false
@@ -198,34 +215,57 @@ module MistralTranslator
198
215
 
199
216
  return if source_content.nil? || source_content.strip.empty?
200
217
 
218
+ options = rich_text_field?(field, source_locale) ? { preserve_html: true } : {}
201
219
  target_locales = @adapter.available_locales - [source_locale]
220
+ target_locales &= @target_locales if @target_locales
202
221
 
203
222
  target_locales.each do |target_locale|
204
- translate_to_locale(field, source_content, source_locale, target_locale)
205
- sleep(2) # Rate limiting basique
223
+ translated = translate_to_locale(field, source_content, source_locale, target_locale, options)
224
+ sleep(2) if translated # Rate limiting basique
206
225
  end
207
226
  end
208
227
 
209
- def translate_to_locale(field, content, source_locale, target_locale)
210
- translated_content = MistralTranslator.translate(
211
- content,
212
- from: source_locale.to_s,
213
- to: target_locale.to_s
214
- )
228
+ # Les adaptateurs fournis par l'application n'héritent pas forcément de BaseAdapter.
229
+ def rich_text_field?(field, locale)
230
+ @adapter.respond_to?(:rich_text_field?) && @adapter.rich_text_field?(field, locale)
231
+ end
215
232
 
216
- if translated_content && !translated_content.strip.empty?
217
- @adapter.set_field_value(field, target_locale,
218
- translated_content)
219
- end
220
- rescue MistralTranslator::RateLimitError => e
221
- Rails.logger.warn "Rate limit: #{e.message}" if defined?(Rails)
222
- sleep(2)
223
- retry
224
- rescue StandardError => e
225
- if defined?(Rails)
226
- Rails.logger.error "Translation error for #{field} #{source_locale}->#{target_locale}: #{e.message}"
233
+ def translate_to_locale(field, content, source_locale, target_locale, options)
234
+ rate_limit_retries = 0
235
+ begin
236
+ translated_content = MistralTranslator.translate(
237
+ content,
238
+ from: source_locale.to_s,
239
+ to: target_locale.to_s,
240
+ **options
241
+ )
242
+
243
+ if translated_content && !translated_content.strip.empty?
244
+ @adapter.set_field_value(field, target_locale,
245
+ translated_content)
246
+ end
247
+ true
248
+ rescue MistralTranslator::RateLimitError => e
249
+ Rails.logger.warn "Rate limit: #{e.message}" if defined?(Rails)
250
+ rate_limit_retries += 1
251
+ if rate_limit_retries <= MAX_RATE_LIMIT_RETRIES
252
+ sleep(2)
253
+ retry
254
+ end
255
+ record_failure(field, source_locale, target_locale, e)
256
+ false
257
+ rescue StandardError => e
258
+ record_failure(field, source_locale, target_locale, e)
259
+ false
227
260
  end
228
261
  end
262
+
263
+ def record_failure(field, source_locale, target_locale, error)
264
+ @failed = true
265
+ return unless defined?(Rails)
266
+
267
+ Rails.logger.error "Translation error for #{field} #{source_locale}->#{target_locale}: #{error.message}"
268
+ end
229
269
  end
230
270
  end
231
271
 
@@ -101,9 +101,9 @@ module MistralTranslator
101
101
  # Rate limit sera géré séparément
102
102
  nil
103
103
  when 400..499
104
- raise ApiError, "Client error (#{response.code})}"
104
+ raise ApiError, "Client error (#{response.code})"
105
105
  when 500..599
106
- raise ApiError, "Server error (#{response.code})}"
106
+ raise ApiError, "Server error (#{response.code})"
107
107
  end
108
108
  end
109
109
 
@@ -11,7 +11,7 @@ module MistralTranslator
11
11
  def initialize
12
12
  @api_key = nil
13
13
  @api_url = "https://api.mistral.ai"
14
- @model = "mistral-small"
14
+ @model = "mistral-small-latest"
15
15
  @default_max_tokens = nil
16
16
  @default_temperature = nil
17
17
  @retry_delays = [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
@@ -110,7 +110,8 @@ module MistralTranslator
110
110
  @metrics_mutex.synchronize do
111
111
  @metrics.merge({
112
112
  average_translation_time: if @metrics[:total_translations].positive?
113
- (@metrics[:total_duration] / @metrics[:total_translations]).round(3)
113
+ (@metrics[:total_duration] /
114
+ @metrics[:total_translations]).round(3)
114
115
  else
115
116
  0
116
117
  end,
@@ -258,10 +258,11 @@ module MistralTranslator
258
258
 
259
259
  # Module pour inclure dans les classes Rails si souhaité
260
260
  module RecordHelpers
261
- def translate_with_mistral(fields, from:, to:, **)
261
+ def translate_with_mistral(fields, from:, to:)
262
262
  adapter = MistralTranslator::Adapters::AdapterFactory.build_for(self)
263
- service = MistralTranslator::Adapters::RecordTranslationService.new(self, fields, adapter: adapter, from: from,
264
- to: to, **)
263
+ service = MistralTranslator::Adapters::RecordTranslationService.new(
264
+ self, fields, adapter: adapter, source_locale: from, target_locales: Array(to)
265
+ )
265
266
  service.translate_to_all_locales
266
267
  end
267
268
 
@@ -51,14 +51,6 @@ module MistralTranslator
51
51
  Ne traduis que le contenu textuel à l'intérieur des balises.
52
52
  HTML_INSTRUCTION
53
53
  end
54
-
55
- def build_html_validation_instruction
56
- <<~HTML_VALIDATION
57
-
58
- IMPORTANT : Vérifie que le HTML est valide et bien formé.
59
- Corrige toute erreur de structure HTML si nécessaire.
60
- HTML_VALIDATION
61
- end
62
54
  end
63
55
 
64
56
  # Helper pour les instructions de formatage
@@ -8,7 +8,7 @@ module MistralTranslator
8
8
  additions = []
9
9
 
10
10
  additions << '"has_context": true' if context && !context.to_s.strip.empty?
11
- additions << '"has_glossary": true' if glossary && !glossary.to_s.strip.empty? && glossary.any?
11
+ additions << '"has_glossary": true' if glossary_present?(glossary)
12
12
  additions << '"preserve_html": true' if preserve_html
13
13
 
14
14
  additions.any? ? ",\n #{additions.join(",\n ")}" : ""
@@ -23,20 +23,16 @@ module MistralTranslator
23
23
  additions.any? ? ",\n #{additions.join(",\n ")}" : ""
24
24
  end
25
25
 
26
+ # Le glossaire est un Hash ou une chaîne : String ne répond pas à #any?
27
+ def glossary_present?(glossary)
28
+ return glossary.any? if glossary.is_a?(Hash)
29
+
30
+ !glossary.to_s.strip.empty?
31
+ end
32
+
26
33
  def log_prompt_generation(prompt_type, source_locale, target_locale)
27
34
  message = "Generated #{prompt_type} prompt for #{source_locale} -> #{target_locale}"
28
35
  Logger.debug_if_verbose(message, sensitive: false)
29
36
  end
30
-
31
- def log_prompt_debug(_prompt)
32
- return unless ENV["MISTRAL_TRANSLATOR_DEBUG"]
33
-
34
- if defined?(Rails) && Rails.respond_to?(:logger)
35
- Rails.logger.info message
36
- elsif ENV["MISTRAL_TRANSLATOR_DEBUG"]
37
- # Log de debug seulement si mode verbose activé
38
- Logger.debug_if_verbose(message, sensitive: false)
39
- end
40
- end
41
37
  end
42
38
  end
@@ -42,30 +42,32 @@ module MistralTranslator
42
42
  @mutex = Mutex.new
43
43
  end
44
44
 
45
+ # Réserve un créneau sous verrou, puis attend hors du verrou : les autres
46
+ # threads réservent les créneaux suivants au lieu d'être bloqués.
45
47
  def wait_and_record!
46
- @mutex.synchronize do
47
- cleanup_old_requests
48
- if @requests.size >= @max_requests
49
- wait_time = calculate_wait_time
50
- sleep(wait_time) if wait_time.positive?
51
- end
52
- @requests << Time.now
48
+ wait_time = @mutex.synchronize do
49
+ now = Time.now
50
+ cleanup_old_requests(now)
51
+ slot = next_slot(now)
52
+ @requests << slot
53
+ slot - now
53
54
  end
55
+ sleep(wait_time) if wait_time.positive?
54
56
  end
55
57
 
56
58
  private
57
59
 
58
- def cleanup_old_requests
59
- cutoff_time = Time.now - @window_seconds
60
+ def cleanup_old_requests(now)
61
+ cutoff_time = now - @window_seconds
60
62
  @requests.reject! { |request_time| request_time < cutoff_time }
61
63
  end
62
64
 
63
- def calculate_wait_time
64
- return 0 if @requests.empty?
65
+ # Premier instant où la fenêtre compte moins de max_requests requêtes,
66
+ # créneaux déjà réservés compris
67
+ def next_slot(now)
68
+ return now if @requests.size < @max_requests
65
69
 
66
- oldest_request = @requests.min
67
- time_until_oldest_expires = (oldest_request + @window_seconds) - Time.now
68
- [time_until_oldest_expires, 0].max
70
+ @requests.sort[@requests.size - @max_requests] + @window_seconds
69
71
  end
70
72
  end
71
73
  end
@@ -146,10 +146,13 @@ module MistralTranslator
146
146
  log_debug("Max retries reached for #{target_locale}, giving up")
147
147
  raise e
148
148
  end
149
- rescue RateLimitError => e
149
+ rescue RateLimitError
150
+ # Le client a déjà relancé avec backoff : quelques tentatives de plus suffisent.
151
+ raise if attempt >= DEFAULT_RETRY_COUNT
152
+
150
153
  log_rate_limit_hit("summary", target_locale)
151
154
  sleep(DEFAULT_RETRY_DELAY)
152
- retry
155
+ summarize_with_retry(text, target_locale, max_words, attempt + 1)
153
156
  end
154
157
  # rubocop:enable Metrics/PerceivedComplexity
155
158
 
@@ -71,12 +71,13 @@ module MistralTranslator
71
71
  source_locale = LocaleHelper.validate_locale!(from)
72
72
  target_locales = Array(to).map { |locale| LocaleHelper.validate_locale!(locale) }
73
73
 
74
+ translation_options = { context: options[:context], glossary: options[:glossary] }
75
+ translation_options[:preserve_html] = true if options[:preserve_html]
76
+
74
77
  if options[:use_batch] && target_locales.size > 3
75
- translate_to_multiple_batch(text, source_locale, target_locales, context: options[:context],
76
- glossary: options[:glossary])
78
+ translate_to_multiple_batch(text, source_locale, target_locales, **translation_options)
77
79
  else
78
- translate_to_multiple_sequential(text, source_locale, target_locales, context: options[:context],
79
- glossary: options[:glossary])
80
+ translate_to_multiple_sequential(text, source_locale, target_locales, **translation_options)
80
81
  end
81
82
  end
82
83
 
@@ -184,9 +185,12 @@ module MistralTranslator
184
185
  translate_with_retry(text, source_locale, target_locale, attempt + 1, **options)
185
186
  end
186
187
  rescue RateLimitError
188
+ # Le client a déjà relancé avec backoff : quelques tentatives de plus suffisent.
189
+ raise if attempt >= DEFAULT_RETRY_COUNT
190
+
187
191
  log_rate_limit_hit(source_locale, target_locale)
188
192
  sleep(DEFAULT_RETRY_DELAY)
189
- retry
193
+ translate_with_retry(text, source_locale, target_locale, attempt + 1, **options)
190
194
  end
191
195
 
192
196
  # Ces méthodes sont héritées via RequestHelper
@@ -228,10 +228,14 @@ module MistralTranslator
228
228
 
229
229
  # Helper pour traductions multi-cibles
230
230
  module MultiTargetHelper
231
- def translate_to_multiple_batch(text, source_locale, target_locales, context: nil, glossary: nil)
231
+ DEFAULT_MULTI_TARGET_OPTIONS = { context: nil, glossary: nil }.freeze
232
+
233
+ # options : context, glossary, preserve_html
234
+ def translate_to_multiple_batch(text, source_locale, target_locales, **options)
235
+ options = DEFAULT_MULTI_TARGET_OPTIONS.merge(options)
232
236
  requests = target_locales.map do |target_locale|
233
237
  {
234
- prompt: build_translation_prompt(text, source_locale, target_locale, context: context, glossary: glossary),
238
+ prompt: build_translation_prompt(text, source_locale, target_locale, **options),
235
239
  from: source_locale,
236
240
  to: target_locale,
237
241
  original_text: text
@@ -252,13 +256,14 @@ module MistralTranslator
252
256
  results
253
257
  end
254
258
 
255
- def translate_to_multiple_sequential(text, source_locale, target_locales, context: nil, glossary: nil)
259
+ def translate_to_multiple_sequential(text, source_locale, target_locales, **options)
260
+ options = DEFAULT_MULTI_TARGET_OPTIONS.merge(options)
256
261
  results = {}
257
262
 
258
263
  target_locales.each_with_index do |target_locale, index|
259
264
  sleep(MistralTranslator::Translator::DEFAULT_RETRY_DELAY) if index.positive?
260
265
  results[target_locale] =
261
- translate_with_retry(text, source_locale, target_locale, context: context, glossary: glossary)
266
+ translate_with_retry(text, source_locale, target_locale, **options)
262
267
  end
263
268
 
264
269
  results
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MistralTranslator
4
- VERSION = "0.3.0"
4
+ VERSION = "0.3.2"
5
5
 
6
6
  # Informations additionnelles sur la gem
7
7
  API_VERSION = "v1"
8
- SUPPORTED_MODEL = "mistral-small"
8
+ SUPPORTED_MODEL = "mistral-small-latest"
9
9
 
10
10
  # Méthode pour obtenir des informations complètes sur la version
11
11
  def self.version_info
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mistral_translator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
- - Peyochanchan
7
+ - Pierre Cherbero
8
8
  bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
@@ -117,6 +117,7 @@ executables: []
117
117
  extensions: []
118
118
  extra_rdoc_files: []
119
119
  files:
120
+ - ".env.example"
120
121
  - ".rspec"
121
122
  - ".rubocop.yml"
122
123
  - ".ruby-version"
@@ -196,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
196
197
  - !ruby/object:Gem::Version
197
198
  version: '0'
198
199
  requirements: []
199
- rubygems_version: 3.7.1
200
+ rubygems_version: 4.0.5
200
201
  specification_version: 4
201
202
  summary: Gem to translate and summarize text with Mistral API
202
203
  test_files: []