mistral_translator 0.1.0 → 0.2.1

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/README.md +189 -121
  4. data/README_TESTING.md +33 -0
  5. data/SECURITY.md +157 -0
  6. data/docs/.nojekyll +2 -0
  7. data/docs/404.html +30 -0
  8. data/docs/README.md +153 -0
  9. data/docs/advanced-usage/batch-processing.md +158 -0
  10. data/docs/advanced-usage/error-handling.md +106 -0
  11. data/docs/advanced-usage/monitoring.md +133 -0
  12. data/docs/advanced-usage/summarization.md +86 -0
  13. data/docs/advanced-usage/translations.md +141 -0
  14. data/docs/api-reference/callbacks.md +231 -0
  15. data/docs/api-reference/configuration.md +74 -0
  16. data/docs/api-reference/errors.md +673 -0
  17. data/docs/api-reference/methods.md +539 -0
  18. data/docs/getting-started.md +179 -0
  19. data/docs/index.html +27 -0
  20. data/docs/installation.md +142 -0
  21. data/docs/migration-0.1.0-to-0.2.0.md +61 -0
  22. data/docs/rails-integration/adapters.md +84 -0
  23. data/docs/rails-integration/controllers.md +107 -0
  24. data/docs/rails-integration/jobs.md +97 -0
  25. data/docs/rails-integration/setup.md +339 -0
  26. data/examples/basic_usage.rb +129 -102
  27. data/examples/batch-job.rb +511 -0
  28. data/examples/monitoring-setup.rb +499 -0
  29. data/examples/rails-model.rb +399 -0
  30. data/lib/mistral_translator/adapters.rb +261 -0
  31. data/lib/mistral_translator/client.rb +103 -100
  32. data/lib/mistral_translator/client_helpers.rb +161 -0
  33. data/lib/mistral_translator/configuration.rb +171 -1
  34. data/lib/mistral_translator/errors.rb +16 -0
  35. data/lib/mistral_translator/helpers.rb +292 -0
  36. data/lib/mistral_translator/helpers_extensions.rb +150 -0
  37. data/lib/mistral_translator/levenshtein_helpers.rb +40 -0
  38. data/lib/mistral_translator/logger.rb +28 -4
  39. data/lib/mistral_translator/prompt_builder.rb +93 -41
  40. data/lib/mistral_translator/prompt_helpers.rb +83 -0
  41. data/lib/mistral_translator/prompt_metadata_helpers.rb +42 -0
  42. data/lib/mistral_translator/response_parser.rb +194 -23
  43. data/lib/mistral_translator/security.rb +72 -0
  44. data/lib/mistral_translator/summarizer.rb +41 -2
  45. data/lib/mistral_translator/translator.rb +174 -98
  46. data/lib/mistral_translator/translator_helpers.rb +268 -0
  47. data/lib/mistral_translator/version.rb +1 -1
  48. data/lib/mistral_translator.rb +51 -25
  49. metadata +39 -3
@@ -0,0 +1,673 @@
1
+ > **Navigation :** [🏠 Home](README.md) • [📖 API Reference](api-reference/methods.md) • [⚡ Advanced Usage](advanced-usage/translations.md) • [🛤️ Rails Integration](rails-integration/setup.md)
2
+
3
+ ---
4
+
5
+ # Référence des Erreurs API
6
+
7
+ ## Table des Matières
8
+
9
+ - [Hiérarchie des Erreurs](#hiérarchie-des-erreurs)
10
+ - [Erreurs de Configuration](#erreurs-de-configuration)
11
+ - [Erreurs API](#erreurs-api)
12
+ - [Erreurs de Traduction](#erreurs-de-traduction)
13
+ - [Erreurs de Sécurité](#erreurs-de-sécurité)
14
+ - [Gestion des Erreurs](#gestion-des-erreurs)
15
+ - [Bonnes Pratiques](#bonnes-pratiques)
16
+
17
+ ---
18
+
19
+ ## Hiérarchie des Erreurs
20
+
21
+ ```
22
+ StandardError
23
+ └── MistralTranslator::Error
24
+ ├── MistralTranslator::ConfigurationError
25
+ ├── MistralTranslator::ApiError
26
+ │ ├── MistralTranslator::RateLimitError
27
+ │ └── MistralTranslator::AuthenticationError
28
+ ├── MistralTranslator::InvalidResponseError
29
+ ├── MistralTranslator::EmptyTranslationError
30
+ ├── MistralTranslator::UnsupportedLanguageError
31
+ ├── MistralTranslator::SecurityError
32
+ └── MistralTranslator::RateLimitExceededError
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Erreurs de Configuration
38
+
39
+ ### `MistralTranslator::ConfigurationError`
40
+
41
+ **Description:** Erreur de configuration de la gem.
42
+
43
+ **Causes courantes:**
44
+
45
+ - Clé API manquante ou invalide
46
+ - URL d'API incorrecte
47
+ - Paramètres de configuration invalides
48
+
49
+ **Attributs:**
50
+
51
+ - `message` (String) - Message d'erreur descriptif
52
+
53
+ **Exemples:**
54
+
55
+ ```ruby
56
+ # Clé API manquante
57
+ MistralTranslator.configure do |config|
58
+ # config.api_key non définie
59
+ end
60
+
61
+ begin
62
+ MistralTranslator.translate("Hello", from: "en", to: "fr")
63
+ rescue MistralTranslator::ConfigurationError => e
64
+ puts "Configuration error: #{e.message}"
65
+ # => "API key is required. Set it with MistralTranslator.configure { |c| c.api_key = 'your_key' }"
66
+ end
67
+ ```
68
+
69
+ ```ruby
70
+ # URL d'API incorrecte
71
+ MistralTranslator.configure do |config|
72
+ config.api_key = "valid_key"
73
+ config.api_url = "http://invalid-url" # Doit être HTTPS
74
+ end
75
+ # => MistralTranslator::ConfigurationError: API URL must use HTTPS protocol
76
+ ```
77
+
78
+ **Solutions:**
79
+
80
+ - Vérifier que la clé API est définie : `ENV['MISTRAL_API_KEY']`
81
+ - Utiliser une URL HTTPS valide
82
+ - Valider les paramètres de configuration
83
+
84
+ ---
85
+
86
+ ## Erreurs API
87
+
88
+ ### `MistralTranslator::ApiError`
89
+
90
+ **Description:** Classe de base pour toutes les erreurs API.
91
+
92
+ **Attributs:**
93
+
94
+ - `message` (String) - Message d'erreur
95
+ - `response` (Net::HTTPResponse, optionnel) - Réponse HTTP brute
96
+ - `status_code` (Integer, optionnel) - Code de statut HTTP
97
+
98
+ **Exemple:**
99
+
100
+ ```ruby
101
+ begin
102
+ MistralTranslator.translate("Hello", from: "en", to: "fr")
103
+ rescue MistralTranslator::ApiError => e
104
+ puts "API Error: #{e.message}"
105
+ puts "Status: #{e.status_code}" if e.status_code
106
+ puts "Response: #{e.response.body}" if e.response
107
+ end
108
+ ```
109
+
110
+ ---
111
+
112
+ ### `MistralTranslator::AuthenticationError`
113
+
114
+ **Description:** Erreur d'authentification avec l'API Mistral.
115
+
116
+ **Hérite de:** `ApiError`
117
+
118
+ **Code HTTP:** 401
119
+
120
+ **Causes courantes:**
121
+
122
+ - Clé API invalide ou expirée
123
+ - Clé API non autorisée pour le modèle demandé
124
+ - Problème de format de la clé API
125
+
126
+ **Exemple:**
127
+
128
+ ```ruby
129
+ MistralTranslator.configure do |config|
130
+ config.api_key = "invalid_key_12345"
131
+ end
132
+
133
+ begin
134
+ MistralTranslator.translate("Hello", from: "en", to: "fr")
135
+ rescue MistralTranslator::AuthenticationError => e
136
+ puts "Authentication failed: #{e.message}"
137
+ # => "Invalid API key"
138
+
139
+ # Vérifier votre clé API
140
+ # 1. Connectez-vous à https://console.mistral.ai/
141
+ # 2. Générez une nouvelle clé API
142
+ # 3. Mettez à jour votre configuration
143
+ end
144
+ ```
145
+
146
+ **Solutions:**
147
+
148
+ - Vérifier la validité de la clé API sur la console Mistral
149
+ - Régénérer une nouvelle clé si nécessaire
150
+ - S'assurer que la clé a les permissions nécessaires
151
+
152
+ ---
153
+
154
+ ### `MistralTranslator::RateLimitError`
155
+
156
+ **Description:** Limite de taux API dépassée.
157
+
158
+ **Hérite de:** `ApiError`
159
+
160
+ **Code HTTP:** 429
161
+
162
+ **Causes courantes:**
163
+
164
+ - Trop de requêtes envoyées en peu de temps
165
+ - Quota API mensuel dépassé
166
+ - Limites par minute/heure atteintes
167
+
168
+ **Exemple:**
169
+
170
+ ```ruby
171
+ begin
172
+ # Beaucoup de traductions rapides
173
+ 100.times do |i|
174
+ MistralTranslator.translate("Text #{i}", from: "en", to: "fr")
175
+ end
176
+ rescue MistralTranslator::RateLimitError => e
177
+ puts "Rate limit exceeded: #{e.message}"
178
+
179
+ # La gem fait automatiquement des retry avec backoff exponentiel
180
+ # Mais vous pouvez aussi gérer manuellement :
181
+ puts "Waiting before retry..."
182
+ sleep(60) # Attendre 1 minute
183
+ retry
184
+ end
185
+ ```
186
+
187
+ **Gestion automatique:**
188
+ La gem inclut un système de retry automatique avec backoff exponentiel :
189
+
190
+ ```ruby
191
+ MistralTranslator.configure do |config|
192
+ config.retry_delays = [2, 4, 8, 16, 32] # Délais en secondes
193
+ end
194
+ ```
195
+
196
+ **Solutions:**
197
+
198
+ - Réduire la fréquence des requêtes
199
+ - Utiliser `translate_batch` pour les lots
200
+ - Ajouter des délais entre les requêtes
201
+ - Upgrader votre plan API si nécessaire
202
+
203
+ ---
204
+
205
+ ## Erreurs de Traduction
206
+
207
+ ### `MistralTranslator::InvalidResponseError`
208
+
209
+ **Description:** Réponse invalide ou malformée de l'API.
210
+
211
+ **Attributs:**
212
+
213
+ - `message` (String) - Description de l'erreur
214
+ - `raw_response` (String, optionnel) - Réponse brute reçue
215
+
216
+ **Causes courantes:**
217
+
218
+ - JSON invalide dans la réponse API
219
+ - Structure de réponse inattendue
220
+ - Réponse tronquée ou corrompue
221
+
222
+ **Exemple:**
223
+
224
+ ```ruby
225
+ begin
226
+ MistralTranslator.translate("Hello", from: "en", to: "fr")
227
+ rescue MistralTranslator::InvalidResponseError => e
228
+ puts "Invalid response: #{e.message}"
229
+ puts "Raw response: #{e.raw_response}" if e.raw_response
230
+
231
+ # Cela peut indiquer:
232
+ # - Un problème temporaire avec l'API
233
+ # - Une réponse inattendue du serveur
234
+ # - Un problème de parsing JSON
235
+ end
236
+ ```
237
+
238
+ **Solutions:**
239
+
240
+ - Réessayer la requête (souvent temporaire)
241
+ - Vérifier la status de l'API Mistral
242
+ - Signaler le problème si persistant
243
+
244
+ ---
245
+
246
+ ### `MistralTranslator::EmptyTranslationError`
247
+
248
+ **Description:** Traduction vide reçue de l'API.
249
+
250
+ **Causes courantes:**
251
+
252
+ - Texte source vide ou invalide
253
+ - Problème avec le prompt envoyé à l'API
254
+ - Réponse API incomplète
255
+
256
+ **Exemple:**
257
+
258
+ ```ruby
259
+ begin
260
+ MistralTranslator.translate("", from: "en", to: "fr") # Texte vide
261
+ rescue MistralTranslator::EmptyTranslationError => e
262
+ puts "Empty translation: #{e.message}"
263
+ # => "Empty translation received from API"
264
+ end
265
+
266
+ # La gem gère automatiquement les textes vides :
267
+ result = MistralTranslator.translate("", from: "en", to: "fr")
268
+ puts result # => "" (sans erreur)
269
+ ```
270
+
271
+ **Solutions:**
272
+
273
+ - Vérifier que le texte source n'est pas vide
274
+ - S'assurer que le texte contient du contenu traduisible
275
+ - Réessayer avec un texte différent
276
+
277
+ ---
278
+
279
+ ### `MistralTranslator::UnsupportedLanguageError`
280
+
281
+ **Description:** Langue non supportée par la gem.
282
+
283
+ **Attributs:**
284
+
285
+ - `language` (String) - Code de langue non supporté
286
+
287
+ **Langues supportées actuellement:**
288
+
289
+ ```ruby
290
+ MistralTranslator.supported_locales
291
+ # => ["fr", "en", "es", "pt", "de", "it", "nl", "ru", "mg", "ja", "ko", "zh", "ar"]
292
+ ```
293
+
294
+ **Exemple:**
295
+
296
+ ```ruby
297
+ begin
298
+ MistralTranslator.translate("Hello", from: "en", to: "klingon")
299
+ rescue MistralTranslator::UnsupportedLanguageError => e
300
+ puts "Unsupported language: #{e.message}"
301
+ puts "Language requested: #{e.language}"
302
+ # => "klingon"
303
+
304
+ # Obtenir des suggestions :
305
+ suggestions = MistralTranslator::Helpers.validate_locale_with_suggestions("klingon")
306
+ if suggestions[:suggestions].any?
307
+ puts "Did you mean: #{suggestions[:suggestions].join(', ')}?"
308
+ end
309
+ end
310
+ ```
311
+
312
+ **Solutions:**
313
+
314
+ - Utiliser `MistralTranslator.supported_locales` pour voir les langues disponibles
315
+ - Utiliser le helper de validation avec suggestions
316
+ - Normaliser les codes de langue (ex: "français" → "fr")
317
+
318
+ ---
319
+
320
+ ## Erreurs de Sécurité
321
+
322
+ ### `MistralTranslator::SecurityError`
323
+
324
+ **Description:** Violation de sécurité détectée.
325
+
326
+ **Causes courantes:**
327
+
328
+ - Texte dépassant la taille limite (50,000 caractères)
329
+ - Contenu potentiellement malveillant détecté
330
+ - Tentative d'injection de prompt
331
+
332
+ **Exemple:**
333
+
334
+ ```ruby
335
+ begin
336
+ huge_text = "A" * 100_000 # Texte trop grand
337
+ MistralTranslator.translate(huge_text, from: "en", to: "fr")
338
+ rescue ArgumentError => e
339
+ puts "Security limit: #{e.message}"
340
+ # => "Text too long (max 50000 chars)"
341
+ end
342
+ ```
343
+
344
+ **Solutions:**
345
+
346
+ - Diviser les textes longs en plusieurs parties
347
+ - Valider le contenu avant traduction
348
+ - Utiliser `translate_batch` pour les lots importants
349
+
350
+ ---
351
+
352
+ ### `MistralTranslator::RateLimitExceededError`
353
+
354
+ **Description:** Limite de taux personnalisée dépassée.
355
+
356
+ **Attributs:**
357
+
358
+ - `wait_time` (Integer, optionnel) - Temps d'attente suggéré
359
+ - `retry_after` (Integer, optionnel) - Timestamp de retry
360
+
361
+ **Différence avec `RateLimitError`:**
362
+
363
+ - `RateLimitError` : Limite API Mistral (HTTP 429)
364
+ - `RateLimitExceededError` : Limite locale de la gem
365
+
366
+ **Exemple:**
367
+
368
+ ```ruby
369
+ # Configuration du rate limiter local
370
+ rate_limiter = MistralTranslator::Security::BasicRateLimiter.new(
371
+ max_requests: 10,
372
+ window_seconds: 60
373
+ )
374
+
375
+ client = MistralTranslator::Client.new(rate_limiter: rate_limiter)
376
+
377
+ begin
378
+ # Trop de requêtes locales
379
+ 15.times { client.complete("Hello") }
380
+ rescue MistralTranslator::RateLimitExceededError => e
381
+ puts "Local rate limit exceeded"
382
+ sleep(e.wait_time) if e.wait_time
383
+ retry
384
+ end
385
+ ```
386
+
387
+ ---
388
+
389
+ ## Gestion des Erreurs
390
+
391
+ ### Stratégies de Récupération
392
+
393
+ #### 1. Retry avec Backoff Exponentiel
394
+
395
+ ```ruby
396
+ def safe_translate(text, from:, to:, max_retries: 3)
397
+ retries = 0
398
+
399
+ begin
400
+ MistralTranslator.translate(text, from: from, to: to)
401
+ rescue MistralTranslator::RateLimitError, MistralTranslator::ApiError => e
402
+ retries += 1
403
+ if retries <= max_retries
404
+ wait_time = 2 ** retries # 2, 4, 8 secondes
405
+ puts "Retry #{retries}/#{max_retries} in #{wait_time}s: #{e.message}"
406
+ sleep(wait_time)
407
+ retry
408
+ else
409
+ raise e
410
+ end
411
+ end
412
+ end
413
+ ```
414
+
415
+ #### 2. Fallback avec Traduction par Défaut
416
+
417
+ ```ruby
418
+ def translate_with_fallback(text, from:, to:, fallback: nil)
419
+ MistralTranslator.translate(text, from: from, to: to)
420
+ rescue MistralTranslator::Error => e
421
+ puts "Translation failed: #{e.message}"
422
+ fallback || text # Retourner le fallback ou le texte original
423
+ end
424
+ ```
425
+
426
+ #### 3. Batch avec Récupération Individuelle
427
+
428
+ ```ruby
429
+ def robust_batch_translate(texts, from:, to:)
430
+ begin
431
+ # Essayer le batch d'abord
432
+ MistralTranslator.translate_batch(texts, from: from, to: to)
433
+ rescue MistralTranslator::Error => e
434
+ puts "Batch failed: #{e.message}, falling back to individual translations"
435
+
436
+ # Fallback : traduction individuelle
437
+ results = {}
438
+ texts.each_with_index do |text, index|
439
+ begin
440
+ results[index] = MistralTranslator.translate(text, from: from, to: to)
441
+ rescue MistralTranslator::Error => e
442
+ puts "Failed to translate item #{index}: #{e.message}"
443
+ results[index] = text # Garder l'original en cas d'échec
444
+ end
445
+ end
446
+ results
447
+ end
448
+ end
449
+ ```
450
+
451
+ #### 4. Circuit Breaker Pattern
452
+
453
+ ```ruby
454
+ class TranslationCircuitBreaker
455
+ def initialize(failure_threshold: 5, reset_timeout: 60)
456
+ @failure_threshold = failure_threshold
457
+ @reset_timeout = reset_timeout
458
+ @failure_count = 0
459
+ @last_failure_time = nil
460
+ @state = :closed # :closed, :open, :half_open
461
+ end
462
+
463
+ def translate(text, from:, to:)
464
+ case @state
465
+ when :open
466
+ if Time.now - @last_failure_time > @reset_timeout
467
+ @state = :half_open
468
+ else
469
+ raise MistralTranslator::Error, "Circuit breaker is open"
470
+ end
471
+ end
472
+
473
+ begin
474
+ result = MistralTranslator.translate(text, from: from, to: to)
475
+ on_success
476
+ result
477
+ rescue MistralTranslator::Error => e
478
+ on_failure
479
+ raise e
480
+ end
481
+ end
482
+
483
+ private
484
+
485
+ def on_success
486
+ @failure_count = 0
487
+ @state = :closed
488
+ end
489
+
490
+ def on_failure
491
+ @failure_count += 1
492
+ @last_failure_time = Time.now
493
+ @state = :open if @failure_count >= @failure_threshold
494
+ end
495
+ end
496
+ ```
497
+
498
+ ### Logging et Monitoring
499
+
500
+ #### Configuration des Callbacks d'Erreur
501
+
502
+ ```ruby
503
+ MistralTranslator.configure do |config|
504
+ config.on_translation_error = lambda do |from, to, error, attempt, timestamp|
505
+ # Log structuré
506
+ Rails.logger.error({
507
+ event: "translation_error",
508
+ from_language: from,
509
+ to_language: to,
510
+ error_class: error.class.name,
511
+ error_message: error.message,
512
+ attempt_number: attempt,
513
+ timestamp: timestamp
514
+ }.to_json)
515
+
516
+ # Notification externe (Sentry, Honeybadger, etc.)
517
+ if defined?(Sentry)
518
+ Sentry.capture_exception(error, extra: {
519
+ from_language: from,
520
+ to_language: to,
521
+ attempt_number: attempt
522
+ })
523
+ end
524
+ end
525
+
526
+ config.on_rate_limit = lambda do |from, to, wait_time, attempt, timestamp|
527
+ Rails.logger.warn({
528
+ event: "rate_limit",
529
+ from_language: from,
530
+ to_language: to,
531
+ wait_time: wait_time,
532
+ attempt_number: attempt,
533
+ timestamp: timestamp
534
+ }.to_json)
535
+ end
536
+ end
537
+ ```
538
+
539
+ #### Métriques d'Erreurs
540
+
541
+ ```ruby
542
+ # Analyser le taux d'erreur
543
+ metrics = MistralTranslator.metrics
544
+ puts "Error rate: #{metrics[:error_rate]}%"
545
+ puts "Total errors: #{metrics[:errors_count]}"
546
+
547
+ # Alertes basées sur les métriques
548
+ if metrics[:error_rate] > 10.0 # Plus de 10% d'erreurs
549
+ # Envoyer une alerte
550
+ AlertService.notify("High translation error rate: #{metrics[:error_rate]}%")
551
+ end
552
+ ```
553
+
554
+ ---
555
+
556
+ ## Bonnes Pratiques
557
+
558
+ ### 1. Gestion Proactive des Erreurs
559
+
560
+ ```ruby
561
+ # ✅ Bon : Gestion spécifique des erreurs
562
+ begin
563
+ translation = MistralTranslator.translate(text, from: "fr", to: "en")
564
+ rescue MistralTranslator::UnsupportedLanguageError => e
565
+ # Gérer les langues non supportées
566
+ translation = handle_unsupported_language(text, e.language)
567
+ rescue MistralTranslator::RateLimitError => e
568
+ # Gérer les rate limits
569
+ translation = handle_rate_limit(text, e)
570
+ rescue MistralTranslator::AuthenticationError => e
571
+ # Gérer les problèmes d'auth
572
+ translation = handle_auth_error(text, e)
573
+ rescue MistralTranslator::Error => e
574
+ # Fallback général pour toutes les autres erreurs
575
+ translation = handle_general_error(text, e)
576
+ end
577
+
578
+ # ❌ Mauvais : Catch-all trop large
579
+ begin
580
+ translation = MistralTranslator.translate(text, from: "fr", to: "en")
581
+ rescue StandardError => e
582
+ # Trop générique, peut cacher d'autres problèmes
583
+ translation = text
584
+ end
585
+ ```
586
+
587
+ ### 2. Validation des Entrées
588
+
589
+ ```ruby
590
+ def safe_translate(text, from:, to:, **options)
591
+ # Validation préalable
592
+ raise ArgumentError, "Text cannot be nil" if text.nil?
593
+ raise ArgumentError, "Text too long" if text.length > 50_000
594
+
595
+ # Validation des langues avec suggestions
596
+ from_validation = MistralTranslator::Helpers.validate_locale_with_suggestions(from)
597
+ unless from_validation[:valid]
598
+ raise MistralTranslator::UnsupportedLanguageError,
599
+ "Source language '#{from}' not supported. Suggestions: #{from_validation[:suggestions].join(', ')}"
600
+ end
601
+
602
+ # Traduction sécurisée
603
+ MistralTranslator.translate(text, from: from, to: to, **options)
604
+ end
605
+ ```
606
+
607
+ ### 3. Monitoring et Alertes
608
+
609
+ ```ruby
610
+ class TranslationMonitor
611
+ def self.monitor_translation(&block)
612
+ start_time = Time.now
613
+ result = yield
614
+ duration = Time.now - start_time
615
+
616
+ # Log de performance
617
+ if duration > 30.0 # Plus de 30 secondes
618
+ Rails.logger.warn("Slow translation detected: #{duration}s")
619
+ end
620
+
621
+ result
622
+ rescue MistralTranslator::Error => e
623
+ # Log d'erreur avec contexte
624
+ Rails.logger.error({
625
+ event: "translation_failure",
626
+ error: e.class.name,
627
+ message: e.message,
628
+ duration: Time.now - start_time
629
+ }.to_json)
630
+
631
+ raise e
632
+ end
633
+ end
634
+
635
+ # Usage
636
+ translation = TranslationMonitor.monitor_translation do
637
+ MistralTranslator.translate("Hello", from: "en", to: "fr")
638
+ end
639
+ ```
640
+
641
+ ### 4. Tests des Scenarios d'Erreur
642
+
643
+ ```ruby
644
+ # Dans vos specs RSpec
645
+ describe "error handling" do
646
+ it "handles rate limit gracefully" do
647
+ allow(MistralTranslator::Client).to receive(:new).and_raise(
648
+ MistralTranslator::RateLimitError.new("Rate limit exceeded")
649
+ )
650
+
651
+ expect {
652
+ MistralTranslator.translate("Hello", from: "en", to: "fr")
653
+ }.to raise_error(MistralTranslator::RateLimitError)
654
+ end
655
+
656
+ it "provides fallback for unsupported languages" do
657
+ result = translate_with_fallback(
658
+ "Hello",
659
+ from: "klingon",
660
+ to: "fr",
661
+ fallback: "Hello"
662
+ )
663
+ expect(result).to eq("Hello")
664
+ end
665
+ end
666
+ ```
667
+
668
+ Cette approche robuste de gestion des erreurs garantit que votre application reste stable même en cas de problèmes avec l'API de traduction.
669
+
670
+ ---
671
+
672
+ **API-Reference Navigation:**
673
+ [← Methods](api-reference/methods.md) | [Errors](api-reference/errors.md) | [Callbacks](api-reference/callbacks.md) | [Configuration](api-reference/configuration.md) →