Internationalization (i18n)
Customize all UI strings in DialStack components for localization or branding.
Quick Start
import { en } from '@dialstack/sdk-js';
// Create French locale
const fr = {
...en,
common: {
...en.common,
loading: 'Chargement...',
error: 'Erreur',
noResults: 'Aucun résultat',
},
callLogs: {
...en.callLogs,
title: 'Journal des appels',
empty: 'Aucun appel trouvé',
},
};
<CallLogs locale={fr} />;
Locale Structure
Locale is the type of the built-in English locale, en. It has one section of shared strings and one per component:
| Section | Used by |
|---|---|
common | Every component (loading, errors, pagination, playback) |
callLogs | Call logs |
callHistory | Call history |
voicemails | Voicemails |
phoneNumbers | Phone numbers |
phoneNumberOrdering | PhoneNumberOrdering |
aiAgent | AIAgent |
softphone | Softphone |
dialPlan | Dial plan |
accountOnboarding | Onboarding portal steps |
onboardingPortal | Onboarding portal shell |
Sections nest further (for example callLogs.columns, callLogs.statuses). For every key and its English text, see Locale in the SDK reference or print en from @dialstack/sdk-js.
Common Strings
Shared across all components:
{
loading: 'Loading...',
error: 'Error',
noResults: 'No results',
delete: 'Delete',
call: 'Call',
cancel: 'Cancel',
confirm: 'Confirm',
previous: 'Previous',
next: 'Next',
perPage: 'Per page',
showing: 'Showing {start}-{end} of {total}',
play: 'Play',
pause: 'Pause',
}
Built-in Locales
Currently, English is the only built-in locale:
import { en } from '@dialstack/sdk-js';
Creating Custom Locales
Translating a Locale
A Locale must define every section, so start from en and replace the strings you translate. Strings you do not replace keep their English text:
import { en, type Locale } from '@dialstack/sdk-js';
const de: Locale = {
...en,
common: {
...en.common,
loading: 'Laden...',
error: 'Fehler',
noResults: 'Keine Ergebnisse',
delete: 'Löschen',
call: 'Anrufen',
cancel: 'Abbrechen',
confirm: 'Bestätigen',
previous: 'Zurück',
next: 'Weiter',
perPage: 'Pro Seite',
showing: 'Zeige {start}-{end} von {total}',
play: 'Abspielen',
pause: 'Pause',
},
callLogs: {
...en.callLogs,
title: 'Anrufliste',
loading: 'Anrufliste wird geladen...',
empty: 'Keine Anrufe gefunden',
columns: {
...en.callLogs.columns,
date: 'Datum',
direction: 'Richtung',
from: 'Von',
to: 'An',
duration: 'Dauer',
},
},
};
Extending English Locale
Override only specific strings:
import { en } from '@dialstack/sdk-js';
const customEn = {
...en,
common: {
...en.common,
noResults: 'Nothing to show',
},
callLogs: {
...en.callLogs,
title: 'Call History',
empty: 'No calls yet',
},
};
Partial Override
Override only the section you need:
import { en } from '@dialstack/sdk-js';
const brandedLocale = {
...en,
voicemails: {
...en.voicemails,
title: 'Messages',
empty: 'Your inbox is empty',
},
};
Using Locales
Per-Component
<CallLogs locale={customLocale} />
<Voicemails userId={userId} locale={customLocale} />
With Web Components
const callLogs = document.querySelector('dialstack-call-logs');
callLogs.setLocale(customLocale);
Dynamic Locale Switching
Change locale at runtime:
function Dashboard() {
const [locale, setLocale] = useState(en);
return (
<div>
<select onChange={(e) => setLocale(locales[e.target.value])}>
<option value="en">English</option>
<option value="fr">Français</option>
<option value="de">Deutsch</option>
</select>
<CallLogs locale={locale} />
<Voicemails userId={userId} locale={locale} />
</div>
);
}
Interpolation
Some strings support placeholders:
// 'showing' uses {start}, {end}, {total}
showing: 'Showing {start}-{end} of {total}';
// Result: "Showing 1-20 of 150"
Complete Example
import { useState } from 'react';
import { loadDialstackAndInitialize, en, type Locale } from '@dialstack/sdk-js';
import { DialstackComponentsProvider } from '@dialstack/sdk-react';
import { CallLogs } from '@dialstack/sdk-react/call-logs';
import { Voicemails } from '@dialstack/sdk-react/voicemails';
const es: Locale = {
...en,
common: {
...en.common,
loading: 'Cargando...',
noResults: 'Sin resultados',
delete: 'Eliminar',
call: 'Llamar',
cancel: 'Cancelar',
confirm: 'Confirmar',
previous: 'Anterior',
next: 'Siguiente',
perPage: 'Por página',
showing: 'Mostrando {start}-{end} de {total}',
play: 'Reproducir',
pause: 'Pausar',
},
voicemails: {
...en.voicemails,
title: 'Buzón de voz',
loading: 'Cargando mensajes...',
empty: 'No hay mensajes de voz',
},
callLogs: {
...en.callLogs,
title: 'Registro de llamadas',
loading: 'Cargando llamadas...',
empty: 'No hay llamadas',
},
};
const locales: Record<string, Locale> = { en, es };
const dialstack = await loadDialstackAndInitialize({
publishableKey: 'pk_live_YOUR_KEY',
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session', { method: 'POST' });
const { client_secret } = await res.json();
return client_secret;
},
});
function App({ userId }: { userId: string }) {
const [currentLocale, setCurrentLocale] = useState<string>('en');
return (
<DialstackComponentsProvider dialstack={dialstack}>
<div className="p-6">
<div className="flex justify-between items-center mb-6">
<h1 className="text-2xl font-bold">{locales[currentLocale].callLogs.title}</h1>
<select
value={currentLocale}
onChange={(e) => setCurrentLocale(e.target.value)}
className="border rounded px-3 py-2"
>
<option value="en">English</option>
<option value="es">Español</option>
</select>
</div>
<CallLogs locale={locales[currentLocale]} />
<h2 className="text-xl font-bold mt-8 mb-4">{locales[currentLocale].voicemails.title}</h2>
<Voicemails userId={userId} locale={locales[currentLocale]} />
</div>
</DialstackComponentsProvider>
);
}
TypeScript
Import the Locale type for type safety:
import { en, type Locale } from '@dialstack/sdk-js';
// TypeScript checks that every section and key is present
const myLocale: Locale = { ...en, common: { ...en.common, loading: 'Please wait…' } };
Next Steps
- Theming - Customize appearance
- Component basics - The components and their shared options