Translate CW, poll options and media descriptions (#24175)
Co-authored-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
parent
44cd88adc4
commit
69057467cb
25 changed files with 603 additions and 100 deletions
|
@ -3,16 +3,24 @@
|
|||
class TranslateStatusService < BaseService
|
||||
CACHE_TTL = 1.day.freeze
|
||||
|
||||
include ERB::Util
|
||||
include FormattingHelper
|
||||
|
||||
def call(status, target_language)
|
||||
@status = status
|
||||
@content = status_content_format(@status)
|
||||
@source_texts = source_texts
|
||||
@target_language = target_language
|
||||
|
||||
raise Mastodon::NotPermittedError unless permitted?
|
||||
|
||||
Rails.cache.fetch("translations/#{@status.language}/#{@target_language}/#{content_hash}", expires_in: CACHE_TTL) { translation_backend.translate(@content, @status.language, @target_language) }
|
||||
status_translation = Rails.cache.fetch("v2:translations/#{@status.language}/#{@target_language}/#{content_hash}", expires_in: CACHE_TTL) do
|
||||
translations = translation_backend.translate(@source_texts.values, @status.language, @target_language)
|
||||
build_status_translation(translations)
|
||||
end
|
||||
|
||||
status_translation.status = @status
|
||||
|
||||
status_translation
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -22,7 +30,7 @@ class TranslateStatusService < BaseService
|
|||
end
|
||||
|
||||
def permitted?
|
||||
return false unless @status.distributable? && @status.content.present? && TranslationService.configured?
|
||||
return false unless @status.distributable? && TranslationService.configured?
|
||||
|
||||
languages[@status.language]&.include?(@target_language)
|
||||
end
|
||||
|
@ -32,6 +40,73 @@ class TranslateStatusService < BaseService
|
|||
end
|
||||
|
||||
def content_hash
|
||||
Digest::SHA256.base64digest(@content)
|
||||
Digest::SHA256.base64digest(@source_texts.transform_keys { |key| key.respond_to?(:id) ? "#{key.class}-#{key.id}" : key }.to_json)
|
||||
end
|
||||
|
||||
def source_texts
|
||||
texts = {}
|
||||
texts[:content] = wrap_emoji_shortcodes(status_content_format(@status)) if @status.content.present?
|
||||
texts[:spoiler_text] = wrap_emoji_shortcodes(html_escape(@status.spoiler_text)) if @status.spoiler_text.present?
|
||||
|
||||
@status.preloadable_poll&.loaded_options&.each do |option|
|
||||
texts[option] = wrap_emoji_shortcodes(html_escape(option.title))
|
||||
end
|
||||
|
||||
@status.media_attachments.each do |media_attachment|
|
||||
texts[media_attachment] = html_escape(media_attachment.description)
|
||||
end
|
||||
|
||||
texts
|
||||
end
|
||||
|
||||
def build_status_translation(translations)
|
||||
status_translation = Translation.new(
|
||||
detected_source_language: translations.first&.detected_source_language,
|
||||
language: @target_language,
|
||||
provider: translations.first&.provider,
|
||||
content: '',
|
||||
spoiler_text: '',
|
||||
poll_options: [],
|
||||
media_attachments: []
|
||||
)
|
||||
|
||||
@source_texts.keys.each_with_index do |source, index|
|
||||
translation = translations[index]
|
||||
|
||||
case source
|
||||
when :content
|
||||
status_translation.content = unwrap_emoji_shortcodes(translation.text).to_html
|
||||
when :spoiler_text
|
||||
status_translation.spoiler_text = unwrap_emoji_shortcodes(translation.text).content
|
||||
when Poll::Option
|
||||
status_translation.poll_options << Translation::Option.new(
|
||||
title: unwrap_emoji_shortcodes(translation.text).content
|
||||
)
|
||||
when MediaAttachment
|
||||
status_translation.media_attachments << Translation::MediaAttachment.new(
|
||||
id: source.id,
|
||||
description: html_entities.decode(translation.text)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
status_translation
|
||||
end
|
||||
|
||||
def wrap_emoji_shortcodes(text)
|
||||
EmojiFormatter.new(text, @status.emojis, { raw_shortcode: true }).to_s
|
||||
end
|
||||
|
||||
def unwrap_emoji_shortcodes(html)
|
||||
fragment = Nokogiri::HTML.fragment(html)
|
||||
fragment.css('span[translate="no"]').each do |element|
|
||||
element.remove_attribute('translate')
|
||||
element.replace(element.children) if element.attributes.empty?
|
||||
end
|
||||
fragment
|
||||
end
|
||||
|
||||
def html_entities
|
||||
HTMLEntities.new
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue