Localização de conteúdo: as notificações push de novas publicações são enviadas antes de a tradução ser salva

Resumo

Com a localização de conteúdo e a tradução por IA ativadas, a notificação push para uma nova publicação quase sempre contém o texto original do autor, mesmo quando o destinatário lê em outro idioma e uma tradução é armazenada alguns segundos depois. A notificação push é enfileirada quando a publicação é criada e procura uma tradução apenas uma vez, antes que a tarefa de tradução tenha sido concluída.

Os e-mails traduzidos foram anunciados hoje nesta resposta (#44240). Os e-mails não estão expostos a esse problema de tempo, mas as notificações push estão, portanto, uma vez que essa alteração for implantada, o e-mail e a notificação push para a mesma publicação chegarão ao mesmo membro em idiomas diferentes.

O que um membro vê

Um membro cujo idioma de interface é inglês recebe uma notificação push, no navegador e no celular, para um novo tópico escrito em francês. O corpo da notificação está em francês. Ao abrir a notificação, a publicação é exibida em inglês.

Medição

Site na versão release/2026.7 (2026.7.3) com o plugin discourse-ai incluído, idiomas suportados en, fr, de e it, tradução em gemini-3.8-flash e detecção de idioma em gemini-3.5-flash-lite.

Para 11 publicações traduzidas, a primeira tradução foi armazenada 2 a 3 segundos após a criação da publicação, e a última das três, 4 a 7 segundos depois. No caso observado, a tradução para o idioma do destinatário foi armazenada 2 segundos após a publicação, e a notificação push já havia sido enviada com o texto original.

O atraso pode ser verificado em qualquer site com:

SELECT p.id,
       p.locale AS post_locale,
       pl.locale AS translation_locale,
       ROUND(EXTRACT(EPOCH FROM (pl.created_at - p.created_at))) AS seconds_after_post
FROM posts p
JOIN post_localizations pl ON pl.post_id = p.id
WHERE p.created_at > NOW() - INTERVAL '2 days'
ORDER BY p.id, pl.created_at

Causa

  1. Em :post_created, o discourse-ai enfileira Jobs::DetectTranslatePost (plugins/discourse-ai/lib/translation/entry_point.rb). A tarefa detecta o idioma com uma chamada de modelo e, em seguida, traduz para cada outro idioma suportado, em sequência.
  2. PostJobsEnqueuer enfileira :post_alert no mesmo momento. PostAlerter.push_notification enfileira Jobs::DeliverPushNotification imediatamente. Ela é atrasada apenas quando o destinatário foi visto dentro de push_notification_time_window_mins (padrão 1) e, nesse caso, apenas pelo restante dessa janela.
  3. DeliverPushNotification#localize_content! procura TopicLocalization e PostLocalization para user.effective_locale uma única vez, quando a tarefa é executada. Não encontrando nenhuma, envia o título e o excerto originais. Nada espera ou tenta novamente.
  4. Os e-mails de notificação passam por NotificationEmailer com um atraso de email_time_window_mins (padrão 10), de modo que a tradução já existe quando o e-mail é gerado.

app/jobs/regular/deliver_push_notification.rb é idêntico em v2026.7.3 e no main em b5548f76 (2026-10-05).

Solicitação

  1. Retenha a notificação push para uma nova publicação até que sua tradução seja armazenada. Uma opção: quando a localização de conteúdo estiver ativada e a publicação ainda não tiver um idioma detectado, ou não tiver uma localização para o idioma do destinatário enquanto uma é esperada, re-enfileire DeliverPushNotification uma vez após um curto atraso e, em seguida, envie o que estiver disponível. Alguns segundos cobririam os casos medidos acima.
  2. Selecione o conteúdo com a regra compartilhada. A tarefa de push faz sua própria busca por effective_locale. A alteração de e-mail em #44240 passa por ContentLocalization.show_translated_post? e compara post_version. Usar o mesmo caminho para o push faria com que ele respeitasse automatically_translate e understood_languages, ignorasse traduções desatualizadas e permanecesse consistente com os e-mails e a visualização do tópico.
  3. Aplique o mesmo a alertas em tempo real. O payload publicado em /notification-alert/:user_id em PostAlerter.create_notification_alert contém o título e o excerto originais. O modificador post_alerter_live_notification_payload existe, mas o núcleo não localiza o payload.

Relacionado

2 curtidas