Class: GroupLandingPages::AiTranslationService
- Inherits:
-
Object
- Object
- GroupLandingPages::AiTranslationService
- Includes:
- ElasticAPM::SpanHelpers
- Defined in:
- app/services/group_landing_pages/ai_translation_service.rb
Overview
Service for synchronous AI translation of group landing page fields Uses OpenRouter API with Claude for high-quality translations
Instance Attribute Summary collapse
-
#group_landing ⇒ Object
readonly
Returns the value of attribute group_landing.
-
#only_blank_fields ⇒ Object
readonly
Returns the value of attribute only_blank_fields.
-
#only_blank_languages ⇒ Object
readonly
Returns the value of attribute only_blank_languages.
-
#source_language ⇒ Object
readonly
Returns the value of attribute source_language.
-
#target_fields ⇒ Object
readonly
Returns the value of attribute target_fields.
-
#target_languages ⇒ Object
readonly
Returns the value of attribute target_languages.
Instance Method Summary collapse
- #call ⇒ Object
-
#initialize(group_landing, source_language: 'en', target_languages: [], target_fields: [], only_blank_languages: false, only_blank_fields: false) ⇒ AiTranslationService
constructor
A new instance of AiTranslationService.
Constructor Details
#initialize(group_landing, source_language: 'en', target_languages: [], target_fields: [], only_blank_languages: false, only_blank_fields: false) ⇒ AiTranslationService
Returns a new instance of AiTranslationService.
13 14 15 16 17 18 19 20 |
# File 'app/services/group_landing_pages/ai_translation_service.rb', line 13 def initialize(group_landing, source_language: 'en', target_languages: [], target_fields: [], only_blank_languages: false, only_blank_fields: false) @group_landing = group_landing @source_language = source_language @target_languages = target_languages @target_fields = target_fields @only_blank_languages = only_blank_languages @only_blank_fields = only_blank_fields end |
Instance Attribute Details
#group_landing ⇒ Object (readonly)
Returns the value of attribute group_landing.
10 11 12 |
# File 'app/services/group_landing_pages/ai_translation_service.rb', line 10 def group_landing @group_landing end |
#only_blank_fields ⇒ Object (readonly)
Returns the value of attribute only_blank_fields.
10 11 12 |
# File 'app/services/group_landing_pages/ai_translation_service.rb', line 10 def only_blank_fields @only_blank_fields end |
#only_blank_languages ⇒ Object (readonly)
Returns the value of attribute only_blank_languages.
10 11 12 |
# File 'app/services/group_landing_pages/ai_translation_service.rb', line 10 def only_blank_languages @only_blank_languages end |
#source_language ⇒ Object (readonly)
Returns the value of attribute source_language.
10 11 12 |
# File 'app/services/group_landing_pages/ai_translation_service.rb', line 10 def source_language @source_language end |
#target_fields ⇒ Object (readonly)
Returns the value of attribute target_fields.
10 11 12 |
# File 'app/services/group_landing_pages/ai_translation_service.rb', line 10 def target_fields @target_fields end |
#target_languages ⇒ Object (readonly)
Returns the value of attribute target_languages.
10 11 12 |
# File 'app/services/group_landing_pages/ai_translation_service.rb', line 10 def target_languages @target_languages end |
Instance Method Details
#call ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'app/services/group_landing_pages/ai_translation_service.rb', line 22 def call validate_inputs! # Determine actual languages and fields to translate actual_languages = determine_target_languages actual_fields = determine_target_fields return failure_result('No languages to translate') if actual_languages.blank? return failure_result('No fields to translate') if actual_fields.blank? # Filter out language-field combinations that already have content languages_needing_translation, fields_needing_translation = filter_existing_translations(actual_languages, actual_fields) if languages_needing_translation.blank? log_already_translated(actual_languages, actual_fields) return success_result({}, message: 'All translations already exist') end source_texts = extract_source_texts(fields_needing_translation) return failure_result('No source text found for translation') if source_texts.blank? # Batch translations to avoid timeout: max 6 languages per batch all_translations = {} failed_batches = [] # If more than 6 languages, batch them if languages_needing_translation.size > 6 # Batch by languages (6 at a time) languages_needing_translation.each_slice(6).with_index do |language_batch, index| BUSINESS_LOGGER.info('Processing language batch', { group_landing_id: group_landing.id, batch_index: index + 1, batch_size: language_batch.size, languages: language_batch, }) prompt = build_translation_prompt(source_texts, language_batch) batch_translations = execute_translation(prompt) if batch_translations.present? all_translations.merge!(batch_translations) BUSINESS_LOGGER.info('Language batch completed', { group_landing_id: group_landing.id, batch_index: index + 1, translated_languages: batch_translations.keys, }) end rescue StandardError => e failed_batches << "language_batch_#{index + 1}" log_batch_error(e, "language_batch_#{index + 1}", language_batch) end else # Small enough to do in one request prompt = build_translation_prompt(source_texts, languages_needing_translation) all_translations = execute_translation(prompt) end # If all batches failed, return error if all_translations.blank? error_msg = failed_batches.any? ? "All batches failed: #{failed_batches.join(', ')}" : 'No translations generated' return failure_result(error_msg) end # If some batches failed, log warning but continue if failed_batches.any? log_partial_success(failed_batches, all_translations.keys) end update_group_landing_fields(all_translations, languages_needing_translation, fields_needing_translation) # Calculate how many were skipped skipped_count = (actual_languages.size * actual_fields.size) - (languages_needing_translation.size * fields_needing_translation.size) = 'Translation completed successfully' += " (#{skipped_count} already existed)" if skipped_count > 0 += " (#{failed_batches.size} batches failed)" if failed_batches.any? success_result(all_translations, message: ) rescue StandardError => e handle_error(e) end |