# I18n

<Callout type="info">
  This is the documentation for the latest version of Next Admin. If you are using an older version (`<5.0.0`), please refer to the [documentation](https://next-admin.js.org/v4/docs/i18n)
</Callout>

Next Admin supports i18n with the `translations` prop of the `NextAdmin` component.

The following keys are accepted:

<OptionsTable
  options={[
    {
      name: "list.header.add.label",
      description: 'The "Add" button in the list header',
      defaultValue: '"Add"',
    },
    {
      name: "list.header.search.placeholder",
      description: "The placeholder used in the search input",
      defaultValue: '"Search"',
    },
    {
      name: "list.footer.indicator.showing",
      description: (
        <>
          The "Showing from" text in the list indicator, e.g:{" "}
          <u>Showing from</u> 1 to 10 of 25
        </>
      ),
      defaultValue: '"Showing from"',
    },
    {
      name: "list.footer.indicator.to",
      description: (
        <>
          The "to" text in the list indicator, e.g: Showing from 1 <u>to</u> 10
          of 25
        </>
      ),
      defaultValue: '"to"',
    },
    {
      name: "list.footer.indicator.of",
      description: (
        <>
          The "of" text in the list indicator, e.g: Showing from 1 to 10{" "}
          <u>of</u> 25
        </>
      ),
      defaultValue: '"of"',
    },
    {
      name: "list.row.actions.delete.label",
      description:
        "The text in the delete button displayed at the end of each row",
      defaultValue: '"Delete"',
    },
    {
      name: "list.row.actions.delete.alert",
      description:
        "The text in the native alert when the delete action is called in the list",
      defaultValue: '"Are you sure you want to delete {{count}} element(s)?"',
    },
    {
      name: "list.row.actions.delete.success",
      description:
        "The text appearing after a successful deletion from the list",
      defaultValue: '"Deleted successfully"',
    },
    {
      name: "list.row.actions.delete.error",
      description:
        "The text appearing after an error during the deletion from the list",
      defaultValue: '"An error occured while deleting"',
    },
    {
      name: "list.empty.label",
      description: "The text displayed when there is no row in the list",
      defaultValue: '"No {{resource}} found"',
    },
    {
      name: "list.empty.caption",
      description: "The caption displayed when there is no row in the list",
      defaultValue: '"Get started by creating a new {{resource}}"',
    },
    {
      name: "form.create.succeed",
      description: "The text displayed after a successful creation",
      defaultValue: '"Created successfully"',
    },
    {
      name: "form.update.succeed",
      description: "The text displayed after a successful update",
      defaultValue: '"Updated successfully"',
    },
    {
      name: "form.delete.succeed",
      description: "The text displayed after a successful deletion",
      defaultValue: '"Deleted successfully"',
    },
    {
      name: "form.validation.error",
      description: "The text displayed when a form validation error occurs",
      defaultValue: '"Validation error"',
    },
    {
      name: "form.button.save.label",
      description: "The text displayed in the form submit button",
      defaultValue: '"Submit"',
    },
    {
      name: "form.button.delete.label",
      description: "The text displayed in the form delete button",
      defaultValue: '"Delete"',
    },
    {
      name: "form.delete.alert",
      description:
        "The text displayed on the alert when the delete button is clicked",
      defaultValue: '"Are you sure you want to delete this?"',
    },
    {
      name: "form.widgets.file_upload.label",
      description: "The text displayed in file upload widget to select a file",
      defaultValue: '"Choose a file"',
    },
    {
      name: "form.widgets.file_upload.drag_and_drop",
      description:
        "The text displayed in file upload widget to indicate a drag & drop is possible",
      defaultValue: '"or drag and drop"',
    },
    {
      name: "form.widgets.file_upload.delete",
      description:
        "The text displayed in file upload widget to delete the current file",
      defaultValue: '"Delete"',
    },
    {
      name: "form.widgets.multiselect.select",
      description:
        "The text displayed in the multiselect widget in list display mode to toggle the select dialog",
      defaultValue: '"Select items"',
    },
    {
      name: "form.widgets.scalar_array.add",
      description:
        "The text displayed in the scalar array field's button to add new items to the array",
      defaultValue: '"Add new item"',
    },
    {
      name: "actions.label",
      description:
        "The text displayed in the dropdown button for the actions list",
      defaultValue: '"Action"',
    },
    {
      name: "actions.edit.label",
      description:
        "The text displayed for the default edit action in the actions dropdown",
      defaultValue: '"Edit"',
    },
    {
      name: "actions.create.label",
      description:
        "The text displayed for the default create action in the actions dropdown",
      defaultValue: '"Create"',
    },
    {
      name: "actions.delete.label",
      description:
        "The text displayed for the default delete action in the actions dropdown",
      defaultValue: '"Delete"',
    },
    {
      name: "selector.loading",
      description:
        "The text displayed in the selector widget while loading the options",
      defaultValue: '"Loading..."',
    },
    {
      name: "user.logout",
      description: "The text displayed in the logout button",
      defaultValue: '"Logout"',
    },
    {
      name: "model",
      description: (
        <>
          Object to custom model and fields names (
          <a href="#translate-model-name-and-fields">more details</a>).
        </>
      ),
      defaultValue: "{}",
    },
    {
      name: "search.advanced.title",
      description: "Title for the advanced search modal",
      defaultValue: '"Advanced search"',
    },
    {
      name: "search.advanced.add",
      description:
        "Label of the trigger button to add a filter for the advanced search",
      defaultValue: '"Add filter"',
    },
    {
      name: "search.advanced.clear",
      description:
        "Label of the button to clear the filters for the advanced search",
      defaultValue: '"Clear"',
    },
    {
      name: "search.advanced.cancel",
      description: "Label of the button to close the advanced search modal",
      defaultValue: '"Cancel"',
    },
    {
      name: "search.advanced.save",
      description:
        "Label of the button to save the filters for the advanced search",
      defaultValue: '"Save"',
    },
    {
      name: "search.advanced.and_or_group",
      description:
        "Label of the option to add an AND or OR group to the advanced search",
      defaultValue: '"AND / OR group"',
    },
    {
      name: "search.advanced.conditions.equals",
      description:
        "Label of the advanced search condition for a field that is equals to a value",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.not",
      description:
        "Label of the advanced search condition for a field that is not equal to a value",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.in",
      description:
        "Label of the advanced search condition for a field that is in a set of values",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.notIn",
      description:
        "Label of the advanced search condition for a field that is not in a set of values",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.lt",
      description:
        "Label of the advanced search condition for a field that less than a number value",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.lte",
      description:
        "Label of the advanced search condition for a field that is less than or equal to a number value",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.gt",
      description:
        "Label of the advanced search condition for a field that is greater than a number value",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.gte",
      description:
        "Label of the advanced search condition for a field that is greater than or equal to a number value",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.contains",
      description:
        "Label of the advanced search condition for a field that contains a value",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.search",
      description:
        "Label of the advanced search condition for a field that has a search value",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.startsWith",
      description:
        "Label of the advanced search condition for a field that starts with a value",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.endsWidth",
      description:
        "Label of the advanced search condition for a field that ends with a value",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.null",
      description:
        "Label of the advanced search condition for a field that is null",
      defaultValue: '"Equals"',
    },
    {
      name: "search.advanced.conditions.null",
      description:
        "Label of the advanced search condition for a field that is not null",
      defaultValue: '"Equals"',
    },
  ]}
/>

### Translate model name and fields

There are two ways to translate these default keys, provide a function named `getMessages` inside the options or provide `translations` props to `NextAdmin` component.

<Callout type="info">
  Using `getMessages` allows you to provide an object with a multiple level
  structure to translate the keys, while the `translations` props only allow you
  to provide a flat object (`form.widgets.file_upload.delete` ex.)
</Callout>

You can also pass your own set of translations. For example you can set a custom action name as a translation key, which will then be translated by the lib.

```js
actions: [
  {
    title: "actions.user.email",
    action: async (...args) => {
      "use server";
      const { submitEmail } = await import("./actions/nextadmin");
      await submitEmail(...args);
    },
    successMessage: "actions.user.email.success",
    errorMessage: "actions.user.email.error",
  },
],
```

Here, the `actions.user.email` key will be translated by the lib, and the value will be used as the action title, as well as the success and error messages after the action's execution.

Currently, you can only translate the following:

- action title, success and error message
- field validation error message

Check out the example app for more details on its usage.

### Translate model name and fields

By using the `model` key in the translations object, you can translate the model name and fields.

```json
{
  "model": {
    "User": {
      // Keep the case sensitive name of the model
      "name": "User",
      "plural": "Users",
      "fields": {
        "email": "Email",
        "password": "Password"
      }
    }
  }
}
```

<Callout type="info">
  If you only use one language for your admin, you should prefer to use the
  `alias` system ([more details](https://next-admin.js.org/docs/api/model-configuration)) to customize
  field names.
</Callout>
