diff --git a/packages/frontile/src/components/collections/calendar/calendar.gts b/packages/frontile/src/components/collections/calendar/calendar.gts index e5683f611..63790152e 100644 --- a/packages/frontile/src/components/collections/calendar/calendar.gts +++ b/packages/frontile/src/components/collections/calendar/calendar.gts @@ -37,6 +37,7 @@ import { import type { CalendarSlots, CalendarVariants } from '@frontile/theme'; import type { CalendarDay, + CalendarLabels, CalendarMode, CalendarMonthData, CalendarValue, @@ -195,8 +196,21 @@ export interface CalendarArgs { * @defaultValue 'label' */ captionLayout?: 'label' | 'dropdown'; + + /** + * Replaces any of the texts the calendar renders, e.g. to translate them. + * Anything left out keeps its English default; see `CalendarLabels`. + */ + labels?: Partial; } +const DEFAULT_LABELS: CalendarLabels = { + previousMonth: 'Previous month', + nextMonth: 'Next month', + month: 'Month', + year: 'Year' +}; + export interface CalendarSignature { Args: CalendarArgs; Blocks: { @@ -234,6 +248,10 @@ class Calendar extends Component< return this.args.captionLayout ?? 'label'; } + get labels(): CalendarLabels { + return { ...DEFAULT_LABELS, ...this.args.labels }; + } + // The autofocus below is deferred a frame; `deferredWork` holds the // test-waiter token so `settled()` does not race it, and cancels cleanly on // teardown. @@ -1097,6 +1115,7 @@ class Calendar extends Component< @months={{this.monthOptions}} @isYearGridOpen={{this.isYearGridOpen}} @onToggleYearGrid={{this.toggleYearGrid}} + @labels={{this.labels}} @classes={{this.headerClasses}} /> {{/if}} @@ -1113,6 +1132,7 @@ class Calendar extends Component< @currentYear={{this.visibleYear}} @onSelect={{this.pickYear}} @onDismiss={{this.dismissYearGrid}} + @label={{this.labels.year}} @classes={{this.yearGridClasses}} /> {{else}} diff --git a/packages/frontile/src/components/collections/calendar/calendar.md b/packages/frontile/src/components/collections/calendar/calendar.md index b0cfea531..527586197 100644 --- a/packages/frontile/src/components/collections/calendar/calendar.md +++ b/packages/frontile/src/components/collections/calendar/calendar.md @@ -405,6 +405,31 @@ import { Calendar } from 'frontile/collections'; ``` +## Labels + +`@locale` covers everything `Intl` can format, but the accessible names of the +previous/next buttons, and of the month ` @@ -141,7 +143,7 @@ export default class CalendarHeader extends Component { class={{@classes.navButton}} disabled={{if @context.canGoNext false true}} data-disabled={{if @context.canGoNext "false" "true"}} - aria-label="Next month" + aria-label={{@labels.nextMonth}} {{on "click" @context.goToNext}} > diff --git a/packages/frontile/src/components/collections/calendar/types.ts b/packages/frontile/src/components/collections/calendar/types.ts index 89884736f..e7bda2795 100644 --- a/packages/frontile/src/components/collections/calendar/types.ts +++ b/packages/frontile/src/components/collections/calendar/types.ts @@ -104,3 +104,19 @@ export interface DayCellClasses { dayContent: string; indicator: string; } + +/** + * Every text the calendar renders itself, beyond what `Intl` produces from + * `@locale`. Override any of them with `@labels`, e.g. to translate them; the + * rest keep these English defaults. + */ +export interface CalendarLabels { + /** Accessible name of the previous-month button. */ + previousMonth: string; + /** Accessible name of the next-month button. */ + nextMonth: string; + /** Accessible name of the month `