CentercodeDitto
DittoPorygonAPI

TranslationEditorModal

Sheet for editing translations with source comparison and review workflow

Overview

TranslationEditorModal provides a side panel for editing translations of a resource. It shows source strings alongside their translations, supports AI-generated translation review, and tracks editing progress.

Key Features

  • Side-by-side source and translation comparison
  • Progress bar showing translation coverage
  • AI-generated translation indicators with review toggle
  • Stale translation warnings (source changed)
  • Bulk AI translation trigger

Examples

Basic Example

Basic translation editor with source/translation pairs.

With AI Translation

With AI translation button and loading state.

Props Reference

PropTypeDefaultDescription
openboolean-Whether the modal is open
onOpenChange(open: boolean) => void-Callback when open state changes
entityType"RESOURCE" | "BLOCK"-Type of entity being translated
entityIdstring-ID of the entity being translated
sourceLocalestring-Source language code (e.g., "en")
targetLocalestring-Target language code (e.g., "es")
targetLocaleNamestring-Display name for target language
stringsTranslationEditorString[]-Array of translatable strings
isLoadingbooleanfalseWhether translations are loading
isTranslatingbooleanfalseWhether AI translation is in progress
onSave(translations: Array<{ field, value, markReviewed }>) => void-Callback to save edited translations
onTranslateAll() => void-Callback to trigger AI translation for all strings

TranslationEditorString Type

PropTypeDefaultDescription
fieldstring-Field path (e.g., "title", "config.options[0].label")
valuestring-Source text value
sourceHashstring-Hash of source for change detection
translationstring-Existing translation value (if any)
isAIboolean-Whether translation was AI-generated
isReviewedboolean-Whether translation has been reviewed
isStaleboolean-Whether source changed since translation

Usage

import { TranslationEditorModal, type TranslationEditorString } from '@/features/translations';
import { useState } from 'react';

const [open, setOpen] = useState(false);

const strings: TranslationEditorString[] = [
  {
    field: 'title',
    value: 'Welcome Survey',
    sourceHash: 'abc123',
    translation: 'Encuesta de bienvenida',
    isAI: true,
    isReviewed: false,
  },
  {
    field: 'description',
    value: 'Please complete this survey',
    sourceHash: 'def456',
    translation: 'Por favor complete esta encuesta',
    isAI: true,
    isReviewed: true,
  },
];

<TranslationEditorModal
  open={open}
  onOpenChange={setOpen}
  entityType="RESOURCE"
  entityId="res_123"
  sourceLocale="en"
  targetLocale="es"
  targetLocaleName="Spanish"
  strings={strings}
  onSave={(translations) => {
    // Save translations to API
    console.log('Saving:', translations);
  }}
  onTranslateAll={() => {
    // Trigger AI translation for all strings
    console.log('Translating all...');
  }}
/>