---
product: "AG Charts"
title: "RTL Layout"
description: "Vue Charts supports right-to-left (RTL) layouts for languages such as Arabic, Persian, and Hebrew."
framework: vue
version: "14.2.0"
related:
    - title: "Background"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/vue/background/"
    - title: "Colours"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/vue/colours/"
    - title: "Fills & Borders"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/vue/fills-borders/"
    - title: "Layout"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/vue/layout/"
    - title: "Overlays"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/vue/overlays/"
    - title: "Text"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/vue/text/"
    - title: "Themes"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/vue/themes/"
    - title: "Background Image"
      url: "https://www.ag-grid.com/charts/archive/14.2.0/vue/background-image/"
llms: "https://www.ag-grid.com/charts/archive/14.2.0/llms.txt"
---

# RTL Layout

AG Charts supports right-to-left (RTL) text direction for languages such as Arabic, Persian, and Hebrew.

> **Note**
>
> The RTL option handles text within the data elements and controls the visual direction of the chart.  
> To change the language of chart UI elements see [Localisation](https://www.ag-grid.com/charts/archive/14.2.0/vue/localisation/).

## Enabling RTL

Set `enableRtl: true` to enable right-to-left layout for the chart.

```js
{
    enableRtl: true,
}
```

AG Charts can also detect RTL automatically from the `dir="rtl"` attribute set on the chart container or any of its ancestor elements. When the `dir` attribute is present, `enableRtl` does not need to be set explicitly.

## Example: RTL and Localisation

Use the language dropdown to switch between English (LTR), Arabic, Persian, and Hebrew.

#### RTL Locale Switcher

```ts
import { createApp, defineComponent, ref } from "vue";
import { AgCharts } from "ag-charts-vue3";
import type { AgChartOptions } from "ag-charts-types";
import {
  BarSeriesModule,
  CategoryAxisModule,
  ContextMenuModule,
  LegendModule,
  LocaleModule,
  ModuleRegistry,
  NumberAxisModule,
  ZoomModule,
} from "ag-charts-enterprise";
import {
  AG_CHARTS_LOCALE_AR_EG,
  AG_CHARTS_LOCALE_EN_US,
  AG_CHARTS_LOCALE_FA_IR,
  AG_CHARTS_LOCALE_HE_IL,
} from "ag-charts-locale";
import clone from "clone";

type Language = "en" | "ar" | "fa" | "he";

const LANGUAGES = {
  en: {
    localeText: AG_CHARTS_LOCALE_EN_US,
    enableRtl: false,
    title: "Monthly Sales Growth and Net Profit Overview",
    subtitle: "Change in Sales and Net Profit by Month for the Year 2024",
    footnote: "Source: Regional Sales Department — Internal Report",
    yAxisTitle: "Amount in US Dollars ($)",
    seriesNames: ["Sales Growth", "Net Profit"],
    zoomControls: "Zoom Controls",
    legendControls: "Legend Controls",
    data: [
      { month: "January", growth: 45, profit: 40 },
      { month: "February", growth: -60, profit: 15 },
      { month: "March", growth: 25, profit: -20 },
      { month: "April", growth: 80, profit: 65 },
      { month: "May", growth: -35, profit: -30 },
      { month: "June", growth: 50, profit: 55 },
    ],
  },
  ar: {
    localeText: AG_CHARTS_LOCALE_AR_EG,
    enableRtl: true,
    title: "نظرة عامة على نمو Sales المبيعات وصافي الربح الشهري",
    subtitle: "التغير في بيانات Profit المبيعات وصافي الربح شهريًا لعام 2024",
    footnote: "المصدر: قسم المبيعات الإقليمي — Sales Department تقرير داخلي",
    yAxisTitle: "المبلغ Amount بالدولار الأمريكي",
    seriesNames: ["نمو المبيعات", "صافي الربح"],
    zoomControls: "عناصر التكبير",
    legendControls: "عناصر وسيلة الإيضاح",
    data: [
      { month: "يناير", growth: 45, profit: 40 },
      { month: "فبراير", growth: -60, profit: 15 },
      { month: "مارس", growth: 25, profit: -20 },
      { month: "أبريل", growth: 80, profit: 65 },
      { month: "مايو", growth: -35, profit: -30 },
      { month: "يونيو", growth: 50, profit: 55 },
    ],
  },
  fa: {
    localeText: AG_CHARTS_LOCALE_FA_IR,
    enableRtl: true,
    title: "نمای کلی رشد Sales فروش و سود خالص ماهانه",
    subtitle:
      "تغییر داده‌های Profit فروش و سود خالص به تفکیک ماه برای سال 2024",
    footnote: "منبع: بخش فروش منطقه‌ای — Sales Department گزارش داخلی",
    yAxisTitle: "مبلغ Amount به دلار آمریکا",
    seriesNames: ["رشد فروش", "سود خالص"],
    zoomControls: "کنترل‌های بزرگ‌نمایی",
    legendControls: "کنترل‌های راهنما",
    data: [
      { month: "ژانوِیه", growth: 45, profit: 40 },
      { month: "فوریه", growth: -60, profit: 15 },
      { month: "مارس", growth: 25, profit: -20 },
      { month: "آوریل", growth: 80, profit: 65 },
      { month: "مه", growth: -35, profit: -30 },
      { month: "ژوئن", growth: 50, profit: 55 },
    ],
  },
  he: {
    localeText: AG_CHARTS_LOCALE_HE_IL,
    enableRtl: true,
    title: "סקירת צמיחת Sales מכירות ורווח נקי חודשי",
    subtitle: "השינוי בנתוני Profit מכירות ורווח נקי לפי חודש לשנת 2024",
    footnote: "מקור: מחלקת מכירות אזורית — Sales Department דוח פנימי",
    yAxisTitle: "הסכום Amount בשקלים חדשים",
    seriesNames: ["צמיחת מכירות", "רווח נקי"],
    zoomControls: "פקדי זום",
    legendControls: "פקדי מקרא",
    data: [
      { month: "ינואר", growth: 45, profit: 40 },
      { month: "פברואר", growth: -60, profit: 15 },
      { month: "מרץ", growth: 25, profit: -20 },
      { month: "אפריל", growth: 80, profit: 65 },
      { month: "מאי", growth: -35, profit: -30 },
      { month: "יוני", growth: 50, profit: 55 },
    ],
  },
};

// A renderer's HTML is inserted as supplied, so it wraps its own numbers to keep them left-to-right.
const LTR_EMBEDDING = "‪";

const POP_DIRECTIONAL_FORMATTING = "‬";

function profitTooltip({ datum, yName }) {
  const value = `${LTR_EMBEDDING}${datum.profit}${POP_DIRECTIONAL_FORMATTING}`;
  return `<div class="profit-tooltip">${yName} ${value}</div>`;
}

ModuleRegistry.registerModules([
  BarSeriesModule,
  CategoryAxisModule,
  ContextMenuModule,
  LegendModule,
  LocaleModule,
  NumberAxisModule,
  ZoomModule,
]);

const ChartExample = defineComponent({
  template: `
    <div class="example-controls">
      <div class="controls-row">
        <label for="locale">Language</label>
        <select id="locale" v-on:change="updateLanguage($event.target.value)">
          <option value="en">English</option>
          <option value="ar">العربية (Arabic)</option>
          <option value="fa">فارسی (Persian)</option>
          <option value="he">עברית (Hebrew)</option>
        </select>
      </div>
    </div>
    <ag-charts
      :options="options"
    />
  `,
  components: {
    "ag-charts": AgCharts,
  },
  setup(props) {
    const options = ref<AgCartesianChartOptions>({
      enableRtl: false,
      locale: {
        localeText: AG_CHARTS_LOCALE_EN_US,
      },
      title: { text: LANGUAGES.en.title, wrapping: "never", maxWidth: 300 },
      subtitle: {
        text: LANGUAGES.en.subtitle,
        wrapping: "always",
        maxWidth: 300,
      },
      footnote: { text: LANGUAGES.en.footnote },
      data: LANGUAGES.en.data,
      tooltip: { mode: "single" },
      series: [
        {
          type: "bar",
          xKey: "month",
          yKey: "growth",
          yName: LANGUAGES.en.seriesNames[0],
          label: { enabled: true, placement: "outside-end" },
        },
        {
          type: "bar",
          xKey: "month",
          yKey: "profit",
          yName: LANGUAGES.en.seriesNames[1],
          label: { enabled: true, placement: "outside-end" },
          tooltip: { renderer: profitTooltip },
        },
      ],
      axes: {
        x: { type: "category" },
        y: {
          type: "number",
          title: { text: LANGUAGES.en.yAxisTitle },
        },
      },
      zoom: { enabled: true },
      contextMenu: {
        items: [
          "download",
          "separator",
          {
            showOn: "series-area",
            label: LANGUAGES.en.zoomControls,
            items: ["zoom-to-cursor", "pan-to-cursor", "reset-zoom"],
          },
          {
            showOn: "legend-item",
            label: LANGUAGES.en.legendControls,
            items: ["toggle-series-visibility", "toggle-other-series"],
          },
        ],
      },
    });

    const updateLanguage = (lang) => {
      const optionsCopy = clone(options.value);

      const config = LANGUAGES[lang];
      optionsCopy.enableRtl = config.enableRtl;
      optionsCopy.locale = { localeText: config.localeText };
      optionsCopy.title = {
        text: config.title,
        wrapping: "never",
        maxWidth: 300,
      };
      optionsCopy.subtitle = {
        text: config.subtitle,
        wrapping: "always",
        maxWidth: 300,
      };
      optionsCopy.footnote = { text: config.footnote };
      optionsCopy.data = config.data;
      optionsCopy.series = [
        {
          type: "bar",
          xKey: "month",
          yKey: "growth",
          yName: config.seriesNames[0],
          label: { enabled: true, placement: "outside-end" },
        },
        {
          type: "bar",
          xKey: "month",
          yKey: "profit",
          yName: config.seriesNames[1],
          label: { enabled: true, placement: "outside-end" },
          tooltip: { renderer: profitTooltip },
        },
      ];
      optionsCopy.axes = {
        x: { type: "category" },
        y: {
          type: "number",
          title: { text: config.yAxisTitle },
        },
      };
      optionsCopy.contextMenu = {
        items: [
          "download",
          "separator",
          {
            showOn: "series-area",
            label: config.zoomControls,
            items: ["zoom-to-cursor", "pan-to-cursor", "reset-zoom"],
          },
          {
            showOn: "legend-item",
            label: config.legendControls,
            items: ["toggle-series-visibility", "toggle-other-series"],
          },
        ],
      };

      options.value = optionsCopy;
    };

    return {
      options,
      updateLanguage,
    };
  },
});

createApp(ChartExample).mount("#app");
```

[Live example: RTL Locale Switcher](https://www.ag-grid.com/charts/archive/14.2.0/vue3/rtl/examples/rtl-locale-switcher/)

In this example:

- The `enableRtl` option is used to enable right-to-left layout.
- The `localeText` option is used for localisation.
- All bidirectional text is rendered correctly.
- The RTL text in the title and subtitle wrap and truncate on the left.
- The legend layout is mirrored as is the series order in the chart.
- The tooltip and context menu layout are mirrored.
- Both series have negative values in some months, and those values keep their sign on the left, rendering as `-30` rather than `30-`. This applies to the sign, the decimal and group separators, and any unit attached to the value, such as `-12.5kg`.
- The "Sales Growth" series uses the default tooltip which correctly displays the negative values.
- The "Net Profit" series uses a custom `renderer`. As the returned HTML is inserted exactly as supplied, the numbers are wrapped with `U+202A` and `U+202C` to ensure the negative sign renders in the correct position.

## Axis Layout

The axis positions and directions are not changed in RTL mode. If required, users should manually set [Axis Placement](https://www.ag-grid.com/charts/archive/14.2.0/vue/axes-position/) and `reverse` options explicitly.

## API Reference

#### Chart

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| enableRtl | boolean |  | Set to `true` to render the chart in right-to-left mode. If not specified, the chart will detect the `dir` attribute on the container or its ancestors. |
