Localization
Dates, times and numbers follow the locale through Intl. The text of the interface comes from a label pack, so you ship only the languages you use. Right to left layouts mirror the whole scheduler, including the drag gestures and the arrow keys.
Two Settings
locale is a BCP 47 tag and drives every format: the day names, the month title, the hour gutter, the
time on a chip, the digits. It defaults to en-US. labels is the text the scheduler writes itself: Today, Week, All day, and what it announces to a screen
reader. The two are independent, so Vietnamese dates under English labels is a valid combination.
<script lang="ts">
import { Scheduler } from '@sv5ui/scheduler';
import { vi } from '@sv5ui/scheduler/locales';
</script>
<!-- locale formats dates, times and numbers through Intl.
labels is the text of the interface. They are independent. -->
<Scheduler bind:events locale="vi-VN" labels={vi} hour12={false} weekStartsOn={1} />Pick a Language
Thirteen packs ship with the package. Arabic switches the direction as well.
19 – 25 thg 10, 2026
<script lang="ts">
import { Scheduler } from '@sv5ui/scheduler';
import { vi } from '@sv5ui/scheduler/locales';
</script>
<!-- locale formats dates, times and numbers through Intl.
labels is the text of the interface. They are independent. -->
<Scheduler bind:events locale="vi-VN" labels={vi} hour12={false} weekStartsOn={1} />Loading Packs
Packs are named exports of @sv5ui/scheduler/locales. A static import keeps only the packs you name. The entry is a single module, so a dynamic
import defers all of them together rather than one per language; at a few hundred bytes each
that is rarely worth splitting further.
// Each pack is a named export, so the bundler keeps only what you import
import { en, vi, ja } from '@sv5ui/scheduler/locales';
const packs = { en, vi, ja };
const labels = packs[user.language] ?? en;
// Or load one when the language is picked. The entry is one module, so
// this defers all thirteen together rather than one at a time.
const { de } = await import('@sv5ui/scheduler/locales');Bundled packs
| Export | Language |
|---|---|
en | English |
vi | Tiếng Việt |
ar | العربية |
de | Deutsch |
es | Español |
fr | Français |
it | Italiano |
ja | 日本語 |
ko | 한국어 |
nl | Nederlands |
pt | Português |
ru | Русский |
zh | 中文 |
Overriding Single Strings
labels accepts any subset. Keys you leave out fall back to English, and announce merges key by key too, so changing one spoken sentence keeps the other eight. To override on top
of another language, spread the pack first.
<!-- Any subset. Missing keys fall back to English; announce merges key by key -->
<Scheduler bind:events labels={{ today: 'Now', newEvent: 'Untitled' }} />
<!-- Override on top of another pack -->
<Scheduler bind:events locale="vi-VN" labels={{ ...vi, today: 'Bây giờ' }} />
<!-- Change what a screen reader hears -->
<Scheduler
bind:events
labels={{ announce: { moved: (event, start) => `${event.title} is now at ${start}` } }}
/>Writing a Pack
A complete pack is a SchedulerLabels: thirty one keys and ten announcements. Keys that carry a count are functions, so a
language can form its plurals its own way. Type the object and a missing key is a compile
error. Every pack in the package is written this way, so any of them serves as a template.
The file lives in your app, not in the package: put it next to your other translations,
import it, and pass it to labels the same way as a bundled pack.
// src/lib/locales/sv.ts, or wherever your app keeps translations.
// Nothing registers it: you import it and pass it to labels.
import type { SchedulerLabels } from '@sv5ui/scheduler';
// A complete pack, typed so a missing key is a compile error.
export const sv: SchedulerLabels = {
today: 'Idag',
previous: 'Föregående',
next: 'Nästa',
month: 'Månad',
week: 'Vecka',
day: 'Dag',
agenda: 'Agenda',
year: 'År',
allDay: 'Heldag',
views: 'Vy',
menu: 'Visa eller dölj sidopanelen',
sidebar: 'Kalender',
actions: 'Fler åtgärder',
noEvents: 'Inga händelser',
calendars: 'Mina kalendrar',
searchEvents: 'Sök händelser',
unscheduled: 'Oplanerat',
newEvent: 'Ny händelse',
createEvent: 'Skapa händelse',
openEvent: 'Öppna detaljer',
close: 'Stäng',
deleteEvent: 'Ta bort händelse',
// Counts are functions, so a language can handle plurals its own way
more: (count) => `+${count} till`,
dayCell: (date, count) => (count === 0 ? `${date}, inga händelser` : `${date}, ${count} händelser`),
holidayDate: (date, holiday) => `${date}, ${holiday}`,
weekNumber: (week) => `V${week}`,
weekNumberLabel: (week) => `Vecka ${week}`,
eventCount: (count) => `${count} händelser`,
duration: (hours, minutes) => [hours > 0 ? `${hours} h` : '', minutes > 0 ? `${minutes} min` : ''].filter(Boolean).join(' '),
grid: (view) => `Kalender, ${view}`,
event: (event, start, end) => `${event.title}, ${start} till ${end}`,
announce: {
created: (event) => `Skapade ${event.title}`,
moved: (event, start) => `Flyttade ${event.title} till ${start}`,
resized: (event, end) => `${event.title} slutar nu ${end}`,
deleted: (event) => `Tog bort ${event.title}`,
updated: (event) => `Uppdaterade ${event.title}`,
selected: (event) => `Valde ${event.title}`,
cancelled: 'Avbrutet',
reverted: (event) => `Kunde inte spara ${event.title}, ändringen ångrades`,
conflict: (event) => `${event.title} ändrades någon annanstans`,
notEditable: (event) => `${event.title} kan inte ändras`
}
};<!-- src/routes/+page.svelte -->
<script lang="ts">
import { Scheduler } from '@sv5ui/scheduler';
import { sv } from '$lib/locales/sv';
</script>
<Scheduler bind:events locale="sv-SE" labels={sv} />Labels
| Key | English |
|---|---|
today | Today |
previous | Previous |
next | Next |
month | Month |
week | Week |
day | Day |
year | Year |
agenda | Agenda |
allDay | All day |
views | View |
menu | Toggle sidebar |
sidebar | Calendar |
actions | More actions |
noEvents | No events |
calendars | My calendars |
searchEvents | Search events |
unscheduled | Unscheduled |
newEvent | New event |
createEvent | Create event |
openEvent | Open details |
close | Close |
deleteEvent | Delete event |
more | +3 more |
dayCell | Monday, September 14, 2026, 2 events |
holidayDate | Monday, September 14, 2026, Founders day |
weekNumber | W38 |
weekNumberLabel | Week 38 |
eventCount | 3 events |
duration | 2h 30m |
grid | Calendar, Week view |
event | Standup, 9:00 AM to 9:15 AM |
Announcements
Read to screen readers through a live region after an action. The event's title is inserted as is.
| Key | English |
|---|---|
created | Created Standup |
moved | Moved Standup to 10:00 AM |
resized | Standup now ends at 9:30 AM |
deleted | Deleted Standup |
updated | Updated Standup |
selected | Selected Standup |
cancelled | Cancelled |
reverted | Could not save Standup, change reverted |
conflict | Standup was updated elsewhere |
notEditable | Standup cannot be edited |
Clocks
hour12 forces a 12 or 24 hour clock in the hour gutter, on chips, in the agenda, in the details and in
every announcement. Left unset, the locale decides: en-US reads 2:00 PM, vi-VN reads 14:00.
First Day of the Week
weekStartsOn takes 0 for Sunday through 6 for Saturday and defaults to Monday. It shapes the week view, the
month grid, the year grid and the DateNavigator, and it is the week a weekly recurrence rule counts
from when the rule sets no weekStart of its own. It is not read from the locale, because the two often disagree in practice.
Right to Left
Set dir="rtl" on the scheduler, or on any ancestor: left unset, it reads the computed direction of the page
when it mounts. The sidebar and panels dock on the other side, the arrows flip, resize edges swap,
and the left and right keys move the other way. Event titles are set to dir="auto" so a Latin title inside an Arabic calendar still truncates at its end. The same events, in Japanese
and then in Arabic; the toolbar, the weekday order and the +N counts all mirror.
2026年10月
أكتوبر ٢٠٢٦
<script lang="ts">
import { ar } from '@sv5ui/scheduler/locales';
</script>
<!-- dir flips the layout, the arrows, the resize edges and the left/right keys.
Left unset, the scheduler reads the direction of the page when it mounts. -->
<Scheduler bind:events locale="ar-EG" labels={ar} dir="rtl" />Custom View Names
The five built-in views take their switcher text from the pack. A view you register names
itself through ViewDefinition.label, so translate that string yourself. See Custom Views & Layouts.
Building Blocks Take Labels Too
Used inside the scheduler, the sidebar parts read its labels. Used on their own they read a
few keys each from a labels prop: today for DateNavigator, searchEvents for SearchBox, calendars for CalendarList, unscheduled and duration for DragSourceList. mergeLabels turns a partial set into a complete one.
<script lang="ts">
import { mergeLabels, CalendarList, SearchBox, DateNavigator } from '@sv5ui/scheduler';
import { vi } from '@sv5ui/scheduler/locales';
// The standalone parts read a few keys each; hand them a complete set
const labels = mergeLabels({ ...vi, searchEvents: 'Tìm nhanh' });
</script>
<DateNavigator {date} onSelect={(day) => (date = day)} {labels} locale="vi-VN" />
<SearchBox bind:value={search} {labels} />
<CalendarList {calendars} bind:hiddenCalendars {labels} />Props
The five settings of this page.
| Prop | Type | Default |
|---|---|---|
locale | string | 'en-US' |
labels | PartialLabels | English |
hour12 | boolean | from locale |
weekStartsOn | WeekDay | 1 |
dir | 'ltr' | 'rtl' | inherited |