Localización de contenido: las notificaciones push de nuevas publicaciones se envían antes de guardar la traducción

Resumen

Con la localización de contenido y la traducción por IA activadas, la notificación push para una nueva publicación casi siempre contiene el texto original del autor, incluso cuando el destinatario lee en otro idioma y la traducción se guarda unos segundos después. La notificación se encola cuando se crea la publicación y busca una traducción una sola vez, antes de que la tarea de traducción haya terminado.

Hoy se anunció que los correos electrónicos traducidos estarán disponibles en esta respuesta (#44240). Los correos electrónicos no están expuestos a este problema de sincronización, pero las notificaciones push sí lo están, por lo que, una vez implementado ese cambio, el correo electrónico y la notificación push para la misma publicación llegarán al mismo miembro en idiomas diferentes.

Lo que ve un miembro

Un miembro cuya interfaz está en inglés recibe una notificación push, tanto en el navegador como en el móvil, para un nuevo tema escrito en francés. El cuerpo de la notificación está en francés. Al abrir la notificación, se muestra la publicación en inglés.

Medición

Sitio en release/2026.7 (2026.7.3) con el plugin discourse-ai incluido, localizaciones admitidas en, fr, de e it, traducción con gemini-3.8-flash y detección de idioma con gemini-3.5-flash-lite.

Para 11 publicaciones traducidas, la primera traducción se guardó entre 2 y 3 segundos después de que se creó la publicación, y la última de las tres, entre 4 y 7 segundos después. En el caso observado, la traducción al idioma del destinatario se guardó 2 segundos después de la publicación, y la notificación push ya se había enviado con el texto original.

El retraso puede leerse en cualquier sitio con:

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. En :post_created, discourse-ai encola Jobs::DetectTranslatePost (plugins/discourse-ai/lib/translation/entry_point.rb). La tarea detecta el idioma con una llamada al modelo y luego traduce a cada otra localización admitida por turnos.
  2. PostJobsEnqueuer encola :post_alert en el mismo momento. PostAlerter.push_notification encola Jobs::DeliverPushNotification inmediatamente. Solo se retrasa cuando el destinatario se vio dentro de push_notification_time_window_mins (predeterminado 1), y solo por el resto de esa ventana.
  3. DeliverPushNotification#localize_content! busca TopicLocalization y PostLocalization para user.effective_locale una sola vez, cuando se ejecuta la tarea. Al no encontrar ninguna, envía el título y el extracto originales. No hay espera ni reintentos.
  4. Los correos electrónicos de notificación pasan por NotificationEmailer con un retraso de email_time_window_mins (predeterminado 10), por lo que la traducción ya existe cuando se construye el correo.

app/jobs/regular/deliver_push_notification.rb es idéntico en v2026.7.3 y en main en b5548f76 (2026-10-05).

Solicitud

  1. Retener la notificación push para una nueva publicación hasta que se guarde su traducción. Una opción: cuando la localización de contenido esté habilitada y la publicación no tenga un idioma detectado aún, o no tenga una localización para el idioma del destinatario mientras se espera una, volver a encolar DeliverPushNotification una vez después de un breve retraso y luego enviar lo que esté disponible. Unos pocos segundos cubrirían los casos medidos anteriormente.
  2. Seleccionar el contenido con la regla compartida. La tarea de push realiza su propia búsqueda por effective_locale. El cambio de correo en #44240 pasa por ContentLocalization.show_translated_post? y compara post_version. Usar la misma ruta para push haría que respete automatically_translate y understood_languages, omita traducciones obsoletas y se mantenga consistente con los correos electrónicos y la vista del tema.
  3. Aplicar lo mismo a las alertas en vivo. La carga publicada en /notification-alert/:user_id en PostAlerter.create_notification_alert contiene el título y el extracto originales. Existe el modificador post_alerter_live_notification_payload, pero el núcleo no localiza la carga.

Relacionado

2 Me gusta