Skip to main content
Version: 4.xx.xx

i18n Provider
Check the guide
Please check the guide for more information on this topic.

Internationalization (i18n) is a process that allows software applications to be localized for different regions and languages. Refine can work with any i18n framework, but needs an i18nProvider to be created based on the chosen library.

Refine expects the i18nProvider type as follows:

import { I18nProvider } from "@refinedev/core";

const i18nProvider: I18nProvider = {
translate: (key: string, options?: any, defaultMessage?: string) => string,
changeLocale: (lang: string, options?: any) => Promise,
getLocale: () => string,
};

After creating a i18nProvider, you can pass it to the <Refine /> component:

src/App.tsx
import { Refine } from "@refinedev/core";

import i18nProvider from "./i18nProvider";

const App: React.FC = () => {
return (
<Refine
i18nProvider={i18nProvider}
/* ... */
>
{/* ... */}
</Refine>
);
};

This will allow us to put translation features to the useTranslation hook

Methods

translate

translate takes parameters and passes them to the provided i18nProvider and expects a string as a return value.

It has two function signatures with different parameters, which is known as function overloading.

function translate(key: string, options?: any, defaultMessage?: string): string;
function translate(key: string, defaultMessage?: string): string;

It means that you can use it in two different ways. The first one is to pass the key, options, and, defaultMessage as parameters. The second one is to pass the key and defaultMessage parameters. The options parameter is optional.

  • Example of the key and defaultMessage function signature
import { I18nProvider } from "@refinedev/core";
import { useTranslation } from "react-i18next";

// ...

const { t } = useTranslation();

const i18nProvider: I18nProvider = {
translate: (key: string, defaultMessage?: string) => t(key, defaultMessage),
// ...
};

// ...
import { useTranslation } from "@refinedev/core";

// ...

const { translate } = useTranslation();

// ...

translate("posts.fields.title", "Title");

// ...
  • Example of the key, options and, defaultMessage function signature
import { I18nProvider } from "@refinedev/core";
import { useTranslation } from "react-i18next";

// ...

const { t } = useTranslation();

const i18nProvider: I18nProvider = {
translate: (key: string, options?: any, defaultMessage?: string) =>
t(key, defaultMessage, options),
// ...
};

// ...
import { useTranslation } from "@refinedev/core";

// ...

const { translate } = useTranslation();

// ...

const title = translate("posts.fields.title", { ns: "resources" }, "Title");

// ...

You can use the useTranslation hook to call translate method.

changeLocale

translate takes parameters and passes them to the provided i18nProvider and expects a Promise as a return value.

changeLocale: (locale: string, options?: any) => Promise<any>;

You can use the useTranslation hook to call changeLocale method.

getLocale

getLocale expects a string as a return value. It should return the current locale from your i18nProvider.

getLocale: () => string;

You can use the useTranslation hook to call getLocale method.

Translation file

All of Refine's components supports i18n, meaning that if you want to change their text, you can create your own translation files to override Refine's default texts.

Here is the list of all translation keys that you can override:

Show translation file
/locales/en/common.json
{
"pages": {
"login": {
"title": "Sign in to your account",
"signin": "Sign in",
"signup": "Sign up",
"divider": "or",
"fields": {
"email": "Email",
"password": "Password"
},
"errors": {
"validEmail": "Invalid email address",
"requiredEmail": "Email is required",
"requiredPassword": "Password is required"
},
"buttons": {
"submit": "Login",
"forgotPassword": "Forgot password?",
"noAccount": "Don’t have an account?",
"rememberMe": "Remember me"
}
},
"forgotPassword": {
"title": "Forgot your password?",
"fields": {
"email": "Email"
},
"errors": {
"validEmail": "Invalid email address",
"requiredEmail": "Email is required"
},
"buttons": {
"submit": "Send reset instructions"
}
},
"register": {
"title": "Sign up for your account",
"fields": {
"email": "Email",
"password": "Password"
},
"errors": {
"validEmail": "Invalid email address",
"requiredEmail": "Email is required",
"requiredPassword": "Password is required"
},
"buttons": {
"submit": "Register",
"haveAccount": "Have an account?"
}
},
"updatePassword": {
"title": "Update password",
"fields": {
"password": "New Password",
"confirmPassword": "Confirm new password"
},
"errors": {
"confirmPasswordNotMatch": "Passwords do not match",
"requiredPassword": "Password required",
"requiredConfirmPassword": "Confirm password is required"
},
"buttons": {
"submit": "Update"
}
},
"error": {
"info": "You may have forgotten to add the {{action}} component to {{resource}} resource.",
"404": "Sorry, the page you visited does not exist.",
"resource404": "Are you sure you have created the {{resource}} resource.",
"backHome": "Back Home"
}
},
"actions": {
"list": "List",
"create": "Create",
"edit": "Edit",
"show": "Show"
},
"buttons": {
"create": "Create",
"save": "Save",
"logout": "Logout",
"delete": "Delete",
"edit": "Edit",
"cancel": "Cancel",
"confirm": "Are you sure?",
"filter": "Filter",
"clear": "Clear",
"refresh": "Refresh",
"show": "Show",
"undo": "Undo",
"import": "Import",
"clone": "Clone",
"notAccessTitle": "You don't have permission to access"
},
"warnWhenUnsavedChanges": "Are you sure you want to leave? You have unsaved changes.",
"notifications": {
"success": "Successful",
"error": "Error (status code: {{statusCode}})",
"undoable": "You have {{seconds}} seconds to undo",
"createSuccess": "Successfully created {{resource}}",
"createError": "There was an error creating {{resource}} (status code: {{statusCode}})",
"deleteSuccess": "Successfully deleted {{resource}}",
"deleteError": "Error when deleting {{resource}} (status code: {{statusCode}})",
"editSuccess": "Successfully edited {{resource}}",
"editError": "Error when editing {{resource}} (status code: {{statusCode}})",
"importProgress": "Importing: {{processed}}/{{total}}"
},
"loading": "Loading",
"tags": {
"clone": "Clone"
},
"dashboard": {
"title": "Dashboard"
},
"posts": {
"posts": "Posts",
"fields": {
"id": "Id",
"title": "Title",
"category": "Category",
"status": {
"title": "Status",
"published": "Published",
"draft": "Draft",
"rejected": "Rejected"
},
"content": "Content",
"createdAt": "Created At"
},
"titles": {
"create": "Create Post",
"edit": "Edit Post",
"list": "Posts",
"show": "Show Post"
}
},
"table": {
"actions": "Actions"
},
"documentTitle": {
"default": "refine",
"suffix": " | Refine",
"post": {
"list": "Posts | Refine",
"show": "#{{id}} Show Post | Refine",
"edit": "#{{id}} Edit Post | Refine",
"create": "Create new Post | Refine",
"clone": "#{{id}} Clone Post | Refine"
}
},
"autoSave": {
"success": "saved",
"error": "auto save failure",
"loading": "saving...",
"idle": "waiting for changes"
}
}

FAQ

How can I create translation files for other languages in an automated way?

You can use the following community example project as a starting point for incorporating automated translations. The project adds deepl-translate-github-action which uses DeepL, an AI translation service to translate your locales json.

Example

Run on your local
npm create refine-app@latest -- --example i18n-react