An embeddable translation component for Svelte 5 applications with voice input, text-to-speech, and live interpreter mode. Powered by Cohere, Groq, and ElevenLabs.
- Text Translation — Type in any language, get translations with romanized pronunciation
- Voice Input — Tap the mic to speak instead of type (Groq Whisper)
- Text-to-Speech — Hear translations spoken aloud (ElevenLabs)
- Interpreter Mode — Live voice-to-voice translation loop
pnpm add github:RSHVR/tsujiCOHERE_API_KEY=your_cohere_key
GROQ_API_KEY=your_groq_key
ELEVENLABS_API_KEY=your_elevenlabs_keyTranslation endpoint:
// src/routes/api/translate/+server.ts
import type { RequestHandler } from './$types';
import { createTranslationHandler } from 'tsuji/server';
import { env } from '$env/dynamic/private';
export const POST: RequestHandler = async ({ request }) => {
const handler = createTranslationHandler({
apiKey: env.COHERE_API_KEY || ''
});
return handler(request);
};Voice transcription endpoint (for voice input):
// src/routes/api/transcribe/+server.ts
import { env } from '$env/dynamic/private';
import type { RequestHandler } from './$types';
export const POST: RequestHandler = async ({ request }) => {
const formData = await request.formData();
const audioFile = formData.get('audio') as File;
const groqFormData = new FormData();
groqFormData.append('file', audioFile, 'audio.webm');
groqFormData.append('model', 'whisper-large-v3');
const response = await fetch('https://api.groq.com/openai/v1/audio/transcriptions', {
method: 'POST',
headers: { Authorization: `Bearer ${env.GROQ_API_KEY}` },
body: groqFormData
});
const result = await response.json();
return new Response(JSON.stringify({ text: result.text }), {
headers: { 'Content-Type': 'application/json' }
});
};Text-to-speech endpoint:
// src/routes/api/speak/+server.ts
import { env } from '$env/dynamic/private';
import type { RequestHandler } from './$types';
const VOICE_ID = '21m00Tcm4TlvDq8ikWAM'; // Rachel (multilingual)
export const POST: RequestHandler = async ({ request }) => {
const { text } = await request.json();
const response = await fetch(
`https://api.elevenlabs.io/v1/text-to-speech/${VOICE_ID}`,
{
method: 'POST',
headers: {
'xi-api-key': env.ELEVENLABS_API_KEY || '',
'Content-Type': 'application/json'
},
body: JSON.stringify({
text,
model_id: 'eleven_multilingual_v2',
voice_settings: { stability: 0.75, similarity_boost: 0.75, speed: 0.7 }
})
}
);
return new Response(response.body, {
headers: { 'Content-Type': 'audio/mpeg' }
});
};<script>
import { Tsuji } from 'tsuji';
</script>
<div class="h-screen">
<Tsuji />
</div>| Prop | Type | Default | Description |
|---|---|---|---|
apiEndpoint |
string |
'/api/translate' |
API endpoint for translation requests |
height |
string |
'100%' |
CSS height of the component |
maxWidth |
string |
'28rem' |
CSS max-width of the component |
defaultLanguage |
string |
'Japanese' |
Default target language |
defaultMode |
TranslationMode |
'standard' |
Default translation mode |
showClearButton |
boolean |
true |
Show the clear chat button |
class |
string |
'' |
Additional CSS classes |
All modes include romanized pronunciation guides.
- Standard — Natural, contextually appropriate translation
- Plain — Simple, straightforward translation
- Literal — Word-for-word translation preserving original structure
- Explanation — Translation with cultural/linguistic notes
- Formal — Formal/polite register
- Informal — Casual/colloquial register
Toggle "Interpreter Mode" on the empty state screen for live voice translation:
- Speak into your microphone
- Audio is transcribed (Groq Whisper)
- Text is translated (Cohere)
- Translation is spoken aloud (ElevenLabs)
- Loop repeats automatically
Arabic, Chinese, Czech, Dutch, French, German, Greek, Hebrew, Hindi, Indonesian, Italian, Japanese, Korean, Persian, Polish, Portuguese, Romanian, Russian, Spanish, Turkish, Ukrainian, Vietnamese
- Svelte 5
- Tailwind CSS
- API keys: Cohere, Groq, ElevenLabs
MIT