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/useI18n'; 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, { useState, useEffect, useMemo } from 'react'; import _ from 'lodash'; import useFuseSettings from '@fuse/core/FuseSettings/hooks/useFuseSettings'; import i18n from './i18n'; import I18nContext from './I18nContext'; import { LanguageType } from './I18nContext'; 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, setSettings, settingsThemeDirection]); return ( <I18nContext value={useMemo( () => ({ language: _.find(languages, { id: languageId }), languageId, langDirection: i18n.dir(languageId), languages, changeLanguage }), [languageId] )} > {children} </I18nContext> ); }
To use the I18nProvider in your components, you can import and use the useI18n
hook:
import useI18n from '@i18n/useI18n'; 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> ); }