logo

FUSE

DOCS

PurchaseBack to the Dashboard

Multi Language

Fuse React uses react-i18next for to support multiple languages.

Although most people don't require multi-language capabilities for their apps, we have chosen NOT to incorporate translations into every application. To get a glimpse of how translations work in practice, try visiting the Mail app and altering the language in the Toolbar. This is the only app specifically configured with translations for demonstration purposes. If you wish to delve into the details, you can review the source code for an example of how they are used.

Usage

To use the translations, create a translation file called i18n/en.ts within the folder of the app you would like to use them with. For example, to use the translations in the Mail app, create this file inside the apps/mail folder.

const locale = {
	APP_TITLE: 'Mailbox',
	COMPOSE: 'Compose',
	FOLDERS: 'Mailboxes',
	FILTERS: 'Filters',
	LABELS: 'Labels',
	NO_MESSAGES: 'There are no messages!',
	SEARCH_PLACEHOLDER: 'Search for an e-mail or task',
	INBOX: 'Inbox',
	SENT: 'Sent',
	DRAFTS: 'Drafts',
	SPAM: 'Spam',
	TRASH: 'Trash',
	STARRED: 'Starred',
	IMPORTANT: 'Important'
};

export default locale;

And register the language file with i18next.addResourceBundle() atsrc/app/(control-panel)/apps/mailbox/i18n/index.ts

import i18n from '@i18n';
import ar from './ar';
import en from './en';
import tr from './tr';

i18n.addResourceBundle('en', 'mailboxApp', en);
i18n.addResourceBundle('tr', 'mailboxApp', tr);
i18n.addResourceBundle('ar', 'mailboxApp', ar);

And use in a component with useTranslation hook as below:

import {useTranslation} from 'react-i18next';

const {t} = useTranslation('mailApp');

return (
    <div className="p-24">
        <Button
            variant="contained"
            color="primary"
            className="w-full"
            onClick={handleOpenDialog}
        >
            {t('COMPOSE')}
        </Button>
Default Language

To change the default language of the Fuse React, you need to change lng setting in the file @i18n/i18n.ts

You can change "eng" value to "ar" to test it out.

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

/**
 * resources is an object that contains all the translations for the different languages.
 */
const resources = {
	en: {
		translation: {
			'Welcome to React': 'Welcome to React and react-i18next'
		}
	}
};

/**
 * i18n is initialized with the resources object and the language to use.
 * The keySeparator option is set to false because we do not use keys in form messages.welcome.
 * The interpolation option is set to false because we do not use interpolation in form messages.welcome.
 */
i18n.use(initReactI18next) // passes i18n down to react-i18next
	.init({
		resources,
		lng: 'en',

		keySeparator: false, // we do not use keys in form messages.welcome

		interpolation: {
			escapeValue: false // react already safes from xss
		}
	});

export default i18n;
Changing Language

You should use changeLanguage in the hook to change language dynamically:

import { useI18n } from '@i18n/I18nProvider';

const { changeLanguage } = useI18n();

const handleLanguageChange = async (newLanguageId) => {
  await changeLanguage(newLanguageId);
};

Checkout example usage atapp/theme-layouts/components/LanguageSwitcher.tsx

I18n Provider

Fuse React uses a custom I18nProvider to manage language settings and provide language-related functionality throughout the application. The I18nProvider is defined in @i18n/I18nProvider.tsx.

Key features of the I18nProvider:

  • Manages available languages
  • Provides current language and language direction
  • Offers a function to change the current language
  • Integrates with Fuse settings to update the layout direction

Here's the implementation of the I18nProvider:

'use client';

import React, { createContext, useContext, useState, useEffect, useMemo } from 'react';
import _ from 'lodash';
import useFuseSettings from '@fuse/core/FuseSettings/hooks/useFuseSettings';
import i18n from './i18n';

export type LanguageType = {
	id: string;
	title: string;
	flag: string;
};

type I18nContextType = {
	language: LanguageType;
	languageId: string;
	languages: LanguageType[];
	changeLanguage: (languageId: string) => Promise<void>;
	langDirection: 'ltr' | 'rtl';
};

const I18nContext = createContext<I18nContextType | undefined>(undefined);

type I18nProviderProps = {
	children: React.ReactNode;
};

const languages: LanguageType[] = [
	{ id: 'en', title: 'English', flag: 'US' },
	{ id: 'tr', title: 'Turkish', flag: 'TR' },
	{ id: 'ar', title: 'Arabic', flag: 'SA' }
];

export function I18nProvider(props: I18nProviderProps) {
	const { children } = props;
	const { data: settings, setSettings } = useFuseSettings();
	const settingsThemeDirection = useMemo(() => settings.direction, [settings]);
	const [languageId, setLanguageId] = useState(i18n.options.lng);

	const changeLanguage = async (languageId: string) => {
		setLanguageId(languageId);
		await i18n.changeLanguage(languageId);
	};

	useEffect(() => {
		if (languageId !== i18n.options.lng) {
			i18n.changeLanguage(languageId);
		}

		const langDirection = i18n.dir(languageId);

		if (settingsThemeDirection !== langDirection) {
			setSettings({ direction: langDirection });
		}
	}, [languageId, settingsThemeDirection]);

	return (
		<I18nContext.Provider
			value={useMemo(
				() => ({
					language: _.find(languages, { id: languageId }),
					languageId,
					langDirection: i18n.dir(languageId),
					languages,
					changeLanguage
				}),
				[languageId, languages]
			)}
		>
			{children}
		</I18nContext.Provider>
	);
}

export const useI18n = () => {
	const context = useContext(I18nContext);

	if (!context) {
		throw new Error('useI18n must be used within an I18nProvider');
	}

	return context;
};

To use the I18nProvider in your components, you can import and use the useI18n hook:

import { useI18n } from '@i18n/I18nProvider';

function MyComponent() {
  const { language, changeLanguage, langDirection } = useI18n();

  return (
    <div>
      <p>Current language: {language.title}</p>
      <p>Language direction: {langDirection}</p>
      <button onClick={() => changeLanguage('ar')}>
        Switch to Arabic
      </button>
    </div>
  );
}