Localization and RTL
ApexGantt's localization covers three independent concerns: the date and month labels in the timeline header (driven by a dayjs locale), the UI strings in the toolbar and context menu (driven by locale.messages), and the layout direction for RTL languages (driven by locale.direction).
Date locale
Pass a dayjs-compatible locale object to locale.dateLocale to localize every date, month, and weekday string in the timeline header:
import ApexGantt from 'apexgantt'
import localeFr from 'dayjs/locale/fr'
const gantt = new ApexGantt(document.getElementById('chart'), {
series: tasks,
locale: {
dateLocale: localeFr,
},
})
Install dayjs in your project if it is not already present — ApexGantt uses it internally but does not re-export locale files:
npm install dayjs
Then import any locale from dayjs/locale/*. Popular examples:
| Locale | Import path |
|---|---|
| French | dayjs/locale/fr |
| German | dayjs/locale/de |
| Spanish | dayjs/locale/es |
| Japanese | dayjs/locale/ja |
| Arabic | dayjs/locale/ar |
| Hebrew | dayjs/locale/he |
| Chinese (simplified) | dayjs/locale/zh-cn |
| Portuguese | dayjs/locale/pt |
RTL layout
Set locale.direction to 'rtl' to mirror the entire chart: the timeline flows right-to-left, the task list moves to the right side, and the dir="rtl" attribute is applied to the container element.
import ApexGantt from 'apexgantt'
import localeAr from 'dayjs/locale/ar'
const gantt = new ApexGantt(el, {
series: tasks,
locale: {
direction: 'rtl',
dateLocale: localeAr,
},
})
'auto' defers to the document or element's inherited dir attribute. The default is 'ltr'.
Switching direction at runtime requires a update() call:
gantt.update({ locale: { direction: 'rtl' } })
Overriding UI strings
locale.messages accepts a partial GanttMessages object. Any key you supply replaces the English default; unset keys keep their defaults.
const gantt = new ApexGantt(el, {
series: tasks,
locale: {
messages: {
addTask: 'Neue Aufgabe',
deleteSelected: 'Ausgewählte löschen',
undo: 'Rückgängig (Strg+Z)',
redo: 'Wiederholen (Strg+Y)',
exportAsSvg: 'Als SVG exportieren',
editTask: 'Aufgabe bearbeiten',
addChildTask: 'Unteraufgabe hinzufügen',
addSiblingTask: 'Geschwisteraufgabe hinzufügen',
indent: 'Einrücken',
outdent: 'Ausrücken',
deleteTask: 'Aufgabe löschen',
deleteTaskWithChildren: 'Löschen (mit Unteraufgaben)',
},
},
})
Full GanttMessages reference
| Key | Default | Context |
|---|---|---|
addTask | 'Add task' | Toolbar button |
deleteSelected | 'Delete selected' | Toolbar button |
undo | 'Undo (Ctrl+Z)' | Toolbar button |
redo | 'Redo (Ctrl+Y)' | Toolbar button |
exportAsSvg | 'Export as SVG' | Toolbar button (SVG format) |
exportAsPng | 'Export as PNG' | Toolbar button (PNG format) |
exportAsPdf | 'Export as PDF' | Toolbar button (PDF format) |
quickFilterPlaceholder | 'Search tasks…' | Quick-filter search box |
filterButton | 'Filter' | Filter builder toolbar button |
filterHeading | 'Filter tasks' | Filter builder popover heading |
filterMatchLabel | 'Match' | Filter builder match-mode label |
filterMatchAll | 'All' | Filter builder match-all (AND) option |
filterMatchAny | 'Any' | Filter builder match-any (OR) option |
filterAddCondition | '+ Add condition' | Filter builder add-condition button |
filterApply | 'Apply' | Filter builder apply button |
filterClear | 'Clear' | Filter builder clear button |
filterRemoveCondition | 'Remove condition' | Filter builder remove-condition aria-label |
filterNoConditions | 'No conditions yet.' | Filter builder empty state |
filterOperatorLabel | (operator) => string | Human-readable label for a filter operator |
groupNone | '(None)' | Group header label for an empty group value |
groupCountLabel | (count) => '(' + count + ')' | Group header member-count label |
exportFailedNoChart | 'Export failed: Chart not found. Please refresh and try again.' | Export failure alert |
exportFailedGeneric | 'Export failed. Please check the console for details.' | Export failure alert |
editTask | 'Edit task' | Context menu |
addChildTask | 'Add child task' | Context menu |
addSiblingTask | 'Add sibling task' | Context menu |
indent | 'Indent' | Context menu |
outdent | 'Outdent' | Context menu |
deleteTask | 'Delete task' | Context menu (leaf) |
deleteTaskWithChildren | 'Delete (with children)' | Context menu (parent) |
formTaskName | 'Task Name' | Edit form label |
formStartDate | 'Start Date' | Edit form label |
formEndDate | 'End Date' | Edit form label |
formProgress | 'Progress (%)' | Edit form label |
formSubmit | 'Update' | Edit form button |
editTaskTitle | (name) => 'Edit Task: ' + name | Edit dialog title |
validationStartRequired | 'Start date is required' | Validation |
validationEndRequired | 'End date is required' | Validation |
validationEndAfterStart | 'End date must be after start date' | Validation |
validationNameRequired | 'Task name is required' | Validation |
validationProgressRequired | 'Progress is required' | Validation |
validationProgressRange | 'Progress must be between 0 and 100' | Validation |
addTaskRowLabel | '+ Add task' | Inline add-task row |
baselineLabel | 'Baseline:' | Baseline tooltip |
startLabel | 'Start:' | Baseline tooltip |
endLabel | 'End:' | Baseline tooltip |
summaryAriaLabel | (ctx) => string | Summary-bar aria-label builder |
barAriaLabel | (ctx) => string | Task-bar aria-label builder |
barAriaValueText | (ctx) => string | Task-bar aria-valuetext builder |
progressAriaLabel | (name) => name + ' progress' | Progress-handle aria-label builder |
The full English defaults are exported as DEFAULT_GANTT_MESSAGES, so you can spread them as a base and override selectively:
import ApexGantt, { DEFAULT_GANTT_MESSAGES } from 'apexgantt'
const gantt = new ApexGantt(el, {
series: tasks,
locale: {
messages: { ...DEFAULT_GANTT_MESSAGES, addTask: 'Neue Aufgabe' },
},
})
Changing locale at runtime
update() merges locale settings shallowly:
gantt.update({
locale: {
direction: 'rtl',
dateLocale: localeAr,
messages: {
addTask: 'إضافة مهمة',
deleteSelected: 'حذف المحدد',
},
},
})
React example
import { useEffect, useState } from 'react'
import { ApexGanttChart } from 'react-apexgantt'
import type { GanttUserOptions } from 'react-apexgantt'
export default function LocalizedGantt() {
const [locale, setLocale] = useState<GanttUserOptions['locale']>({
direction: 'ltr',
})
const switchToArabic = async () => {
const localeAr = (await import('dayjs/locale/ar')).default
setLocale({ direction: 'rtl', dateLocale: localeAr })
}
return (
<div>
<button onClick={switchToArabic}>Switch to Arabic (RTL)</button>
<ApexGanttChart
tasks={tasks}
options={{ locale }}
height="500px"
/>
</div>
)
}
Vue example
<template>
<div>
<button @click="switchToArabic">Switch to Arabic (RTL)</button>
<ApexGanttChart :tasks="tasks" :options="ganttOptions" height="500px" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { GanttUserOptions } from 'vue-apexgantt'
const ganttOptions = ref<Partial<GanttUserOptions>>({
locale: { direction: 'ltr' },
})
const switchToArabic = async () => {
const localeAr = (await import('dayjs/locale/ar')).default
ganttOptions.value = {
locale: {
direction: 'rtl',
dateLocale: localeAr,
},
}
}
</script>