Build Live Translation

Bilingual / translated caption UI.

Build a bilingual caption UI that shows source text and translation side by side.

Real-time translate_to is not currently enabled for external sessions. The public realtime gateway forwards language but does not forward translate_to, so a session.update with that field has no effect.

Layout

┌──────────────────────────────────────────┐
│ Source                                   │
│ The weather is nice today                │
│ ───────────────────────────────          │
│ Translation                              │
│ The weather is nice today                │
└──────────────────────────────────────────┘

Implementation

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);

  if (data.type === 'conversation.item.input_audio_transcription.completed') {
    const entry = document.createElement('div');
    entry.className = 'translation-entry';

    // Source text
    const source = document.createElement('div');
    source.className = 'source-text';
    source.textContent = data.text;
    entry.appendChild(source);

    // Translation (if available in the event)
    if (data.translation) {
      const translated = document.createElement('div');
      translated.className = 'translated-text';
      translated.textContent = data.translation;
      entry.appendChild(translated);
    }

    container.appendChild(entry);
    container.scrollTop = container.scrollHeight;
  }
};

CSS

.translation-entry {
  margin: 0.5em 0;
  padding: 0.5em;
  border-left: 3px solid #4f46e5;
}
.source-text {
  font-weight: 500;
}
.translated-text {
  margin-top: 0.25em;
  opacity: 0.85;
  font-style: italic;
}

Language switching

When the user switches the source language, update the session:

function switchLanguage(lang) {
  ws.send(JSON.stringify({
    type: 'session.update',
    language: lang,
  }));
}

New utterances after the switch use the new source language.