Class: PublicationTranslationWorker
- Inherits:
-
Object
- Object
- PublicationTranslationWorker
- Includes:
- Sidekiq::Job, Sidekiq::Status::Worker
- Defined in:
- app/workers/publication_translation_worker.rb
Overview
Translates a publication's PDF into another language via DeepLClient and
stages the result as a GeneratedPdf (kind +translated+) for human review in
the PDF studio. On import
(GeneratedPdfImporter, mode :new with locales) the translated PDF becomes a
sibling publication Item, gets a RelatedPublication translation link back to
the source, and — because import routes through Publication::Saver — the
full extraction/vision/embedding pipeline fires for the translated document
for free (Sunny can then search it in the target language).
Enqueued by Sunny's +pdf_translate+ tool and the CRM publication +translate+
action:
Design: doc/tasks/202607201903_PDF_TRANSLATION_POWERHOUSE.md.
Constant Summary collapse
- ALLOWED_SOURCE_RECORDS =
Only these classes may be linked as the review context — never constantize
an arbitrary Sidekiq arg. %w[AssistantConversation Item].freeze
Instance Method Summary collapse
Instance Method Details
#perform(publication_id, lang_out, options = {}) ⇒ Object
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 |
# File 'app/workers/publication_translation_worker.rb', line 36 def perform(publication_id, lang_out, = {}) publication = Item.publications.find_by(id: publication_id) return Rails.logger.info("[PublicationTranslationWorker] Publication #{publication_id} not found, skipping") unless publication return Rails.logger.info("[PublicationTranslationWorker] Publication #{publication_id} is discontinued, skipping") if publication.is_discontinued? literature = publication.literature return Rails.logger.info("[PublicationTranslationWorker] Publication #{publication_id} has no literature, skipping") unless literature&. conversation = source_record() begin lang_out = DeepLClient.canonical_document_locale(lang_out) result = translate_document(literature, lang_out, lang_in: deepl_source_lang_in(publication)) rescue DeepLClient::UnsupportedLanguage => e # A retry cannot make an unsupported target valid. Timeouts deliberately # escape this rescue: DeepL keeps processing remotely, and Sidekiq resumes # the stored document on its next attempt. ErrorReporting.warning(e, source: :background, publication_id:, sku: publication.sku, lang_out:) store error_message: failure_reason(e) notify_conversation(conversation, (publication, lang_out, e)) return end # Phase 2 (opt-in): translate text baked INTO the images. Non-fatal — a # failure here keeps the text-layer translation rather than losing the doc. image_report = nil if ['translate_images'].to_b bytes, image_report = translate_image_text(result.bytes, lang_out:) result = DeepLClient::Result.new(bytes:, meta: result.) end base = publication.publication_base_name.presence || publication.sku # The catalog metadata (name/slug derive from the base name) is translated # too — a French variant files under a French name, not the English name # with a locale suffix. Non-fatal: falls back to the source base name. translated_base = Publication::MetadataTranslator.call(base, lang_out:, lang_in: source_lang_in(publication)) title = translated_base.presence || "#{base} (#{lang_out.to_s.upcase})" staged = GeneratedPdfGenerator.stage( bytes: result.bytes, layout: translation_layout(result., publication, image_report:, translated_base:), kind: 'translated', title:, instructions: ['instructions'], created_by_id: ['created_by_id'], source_publication_id: publication.id, source_record: conversation, filename: "#{(translated_base.presence || base).to_s.parameterize}-#{lang_out.downcase}.pdf" ) raise staged.error.presence || 'staging failed' unless staged.success? # The job monitor redirects here on completion (jobs#show reads redirect_to). store redirect_to: "#{CRM_URL}/pdf_studio/#{staged.generated_pdf.id}", info_message: "Translation staged for review — #{publication.sku} → #{lang_out}" notify_conversation(conversation, (publication, lang_out, staged.generated_pdf, result.)) Rails.logger.info("[PublicationTranslationWorker] Publication #{publication_id} translated to #{lang_out}: staged GeneratedPdf #{staged.generated_pdf.id}") end |