Languages and right-to-left
Locales through Intl, the built-in English and Swedish strings, your own translations, rule descriptions and right-to-left layouts.
Two props make a calendar speak a language: locale formats every date and decides the
defaults that depend on the region, and strings holds every text the calendar writes itself.
locale
A BCP 47 tag, 'en-US' by default (so a server render never depends on the server's settings).
It drives:
- every date, through
Intl.DateTimeFormatand the formats: weekday and month names, the order of day and month, 12- or 24-hour times; weekStartsOn: the region's first day of the week (Intl.Locale's week info, a built-in table where a browser lacks it, else Monday);dir: right-to-left for languages written that way (Intl.Locale's text info).
Pass weekStartsOn (ISO: Monday is 1, Sunday is 7), dir or formats to choose differently.
strings
Every text the calendar writes itself, from "Today" to "Can't move it to …", is a member of
CalendarStrings. English is built in; strings takes any part of it, merged over the English,
and the functions among them (eventCount(n), moreLink(n), navigation(unit, period)) handle
plurals and word order. The texts of the interaction engines (selecting, editing, placing,
dropping, the scope dialog) are optional members whose English lives with the engine that uses
them, so a read-only calendar does not carry them. The registry's own texts read strings too:
the loading skeleton's name (loading) and the notice for a view kind the copied files cannot
render (unsupportedView(label)).
Swedish
@hapio/calendar-core/locales/sv is a complete Swedish pack, every optional member included:
'use client'
import { sv } from '@hapio/calendar-core/locales/sv'
import type { CalendarEventInput, CalendarStrings } from '@hapio/calendar-react'
import { HapioCalendar } from '@/components/hapio-calendar/hapio-calendar'
// The Swedish pack, with one string of your own over it.
const strings: Partial<CalendarStrings> = { ...sv, noEvents: 'Inga bokningar den här veckan' }
export function SwedishCalendar({ events }: { events: readonly CalendarEventInput[] }) {
return (
<HapioCalendar
events={events}
locale="sv-SE" // dates, weekday names, Monday weeks, 24-hour times
strings={strings} // every text the calendar writes, and the root's `lang` (`sv.lang`)
timeZone="Europe/Stockholm"
className="h-[36rem]"
/>
)
}Install @hapio/calendar-core (the same version as @hapio/calendar-react) to import it. Spread
it and override what you need, as above.
The calendar's root carries lang, the language of its texts: the pack's lang (sv.lang is
'sv'; the built-in English says 'en'), never locale's alone, since locale only formats the
dates. So do the parts the registry renders outside the root (the "+N more" popover, the actions
menu, the reschedule form and the scope dialog), so screen readers pronounce a Swedish calendar's
text as Swedish on an English page. A he-IL calendar without Hebrew strings says lang="en":
its dates are Hebrew, its texts English. Set lang yourself only on your own text around the
calendar.
An item that drags into calendars lives outside every calendar, so no calendar's strings reach
its description ("Press Space to pick it up, then choose a time in the calendar"): pass the
pack's text to it, <CalendarDraggable hint={sv.pickUpHint} … /> (or useExternalDraggable's
hint). See Dragging in.
Other languages
Write a CalendarStrings of your own: TypeScript lists every member and the English default of
each is in its documentation (API reference). Set its lang to the
pack's language ('he'), which the calendar's root and popups then carry. Keep the pack in a
module of its own and pass it with the matching locale, and give your draggable items its
pickUpHint as above.
Rule descriptions
describeRule(rrule, locale) from @hapio/calendar-recurrence describes a recurrence rule in
words: Swedish for a Swedish locale ("Varje vecka på måndagar och onsdagar"), English otherwise.
See Recurrence.
English and Swedish only
In 1.0 rules are described in English and Swedish. The scope dialog describes the series' rule in
the calendar's locale, so a calendar in another language (Hebrew, German, …) shows that one
sentence in English while the rest of the dialog follows your strings.
Right-to-left
'use client'
import type { CalendarEventInput } from '@hapio/calendar-react'
import { HapioCalendar } from '@/components/hapio-calendar/hapio-calendar'
export function HebrewCalendar({ events }: { events: readonly CalendarEventInput[] }) {
return (
// The root takes `dir="rtl"` from the locale; pass `dir` to override. Its `lang` is its
// text's: English (`'en'`) with the built-in strings, `'he'` with Hebrew strings that say so.
<HapioCalendar events={events} locale="he-IL" timeZone="Asia/Jerusalem" className="h-[36rem]" />
)
}In a right-to-left calendar:
- the layout mirrors: the time axis is on the right, days run from right to left, and the
registry's styles use logical properties (
ms-,ps-,start-), so nothing needs its own RTL rules; - the keys follow the screen: ← and → swap meaning in every composite (the slot cursor, the day cells, the header links, the events, a grabbed event, the view switcher), so → always moves right;
- the icons of Previous and Next point the way they go.
Text takes its own direction where it can differ from the calendar's. The registry's event time
and title each carry dir="auto", so "09:00 – 10:30" keeps its order in a right-to-left
calendar and a Latin title too long for its event is cut at its own end ("Haircut · An…", not
"…ircut · Anna"); calendar-theme still aligns both by the calendar's direction
(text-align: match-parent). The "+N more" text does the same: "+3 more" keeps its order, and in a
cell too narrow for it the word is cut, never the count. Give mixed-direction text in your own
renderEvent the same dir="auto"; see Customization.