Writing An I18nProvider
An i18nProvider should be an object with three required methods and one optional method:
// in src/i18nProvider.ts
export const i18nProvider = {
    // required
    translate: (key, options) => string,
    changeLocale: locale => Promise<void>,
    getLocale: () => string,
    // optional
    getLocales: () => [{ locale: string, name: string }],
}
Basic Implementation
Here is the simplest possible implementation for an i18nProvider with English and French messages:
import lodashGet from 'lodash/get';
const englishMessages = {
    ra: {
        notification: {
            http_error: 'Network error. Please retry',
        },
        action: {
            save: 'Save',
            delete: 'Delete',
        },
    },
};
const frenchMessages = {
    ra: {
        notification: {
            http_error: 'Erreur réseau, veuillez réessayer',
        },
        action: {
            save: 'Enregistrer',
            delete: 'Supprimer',
        },
    },
};
let messages = englishMessages;
let locale = 'en';
const i18nProvider = {
    translate: key => lodashGet(messages, key),
    changeLocale: newLocale => {
        messages = (newLocale === 'fr') ? frenchMessages : englishMessages;
        locale = newLocale;
        return Promise.resolve();
    },
    getLocale: () => locale
};
This works, but it is too limited: react-admin expects that i18nProviders support string interpolation for translation, and asynchronous message loading for locale change.
Leveraging Polyglot
That’s why react-admin bundles an i18nProvider factory called ra-i18n-polyglot. This factory relies on polyglot.js, which uses JSON files for translations. It only expects one argument: a function returning a list of messages based on a locale passed as an argument.
So the previous provider can be written as:
import polyglotI18nProvider from 'ra-i18n-polyglot';
const englishMessages = {
    ra: {
        notification: {
            http_error: 'Network error. Please retry',
        },
        action: {
            save: 'Save',
            delete: 'Delete',
        },
    },
};
const frenchMessages = {
    ra: {
        notification: {
            http_error: 'Erreur réseau, veuillez réessayer',
        },
        action: {
            save: 'Enregistrer',
            delete: 'Supprimer',
        },
    },
};
const i18nProvider = polyglotI18nProvider(locale => 
    locale === 'fr' ? frenchMessages : englishMessages,
    'en' // Default locale
);
The default (English) messages are available in the ra-language-english package source.
Check the Setting Up Translation for detailed instructions on how to build an i18nProvider this way.
