API Reference
useModernI18n Hook
useModernI18n is a React Hook provided by the plugin for accessing internationalization functionality in components.
Return Value
interface UseModernI18nReturn {
/** Current language code */
language: string;
/** Function to change language */
changeLanguage: (newLang: string) => Promise<void>;
/** i18next instance (for advanced usage) */
i18nInstance: I18nInstance;
/** Supported language list */
supportedLanguages: string[];
/** Check if language is supported */
isLanguageSupported: (lang: string) => boolean;
/** Indicates if translation resources for current language are ready to use */
isResourcesReady: boolean;
}
Usage Example
import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
function LanguageSwitcher() {
const { language, changeLanguage, supportedLanguages, isLanguageSupported } =
useModernI18n();
return (
<div>
<p>Current language: {language}</p>
<div>
{supportedLanguages.map(lang => (
<button
key={lang}
onClick={() => changeLanguage(lang)}
disabled={lang === language}
>
{lang}
</button>
))}
</div>
<button
onClick={() => {
if (isLanguageSupported('ja')) {
changeLanguage('ja');
}
}}
>
Switch to Japanese
</button>
</div>
);
}
changeLanguage Method
The changeLanguage method is used to switch languages. It will:
- Update the language of the i18next instance
- Update browser cache (Cookie/LocalStorage)
- Update URL path (if
localePathRedirect is enabled)
const { changeLanguage } = useModernI18n();
// Switch language
await changeLanguage('zh');
Info
changeLanguage is an async function that returns a Promise.
Language Support Check
isLanguageSupported is used to check if a language is in the supported language list:
const { isLanguageSupported, changeLanguage } = useModernI18n();
function handleLanguageChange(lang: string) {
if (isLanguageSupported(lang)) {
changeLanguage(lang);
} else {
console.warn(`Language ${lang} is not supported`);
}
}
Resource Loading State
isResourcesReady indicates whether the translation resources for the current language are loaded and ready to use. This is particularly useful when using SDK backend to load resources dynamically.
import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
function MyComponent() {
const { isResourcesReady } = useModernI18n();
if (!isResourcesReady) {
return <div>Loading translation resources...</div>;
}
return <div>Translation resources are ready</div>;
}
When to use:
- Display a loading state while resources are being loaded
- Prevent rendering content that depends on translations before resources are ready
- Handle resource loading errors gracefully
Info
isResourcesReady automatically checks:
- If i18n instance is initialized
- If any resources for the current language are currently loading (SDK backend only)
- If all required namespaces for the current language are loaded in the store
I18nLink Component
The I18nLink component is used to create links with language prefixes.
Props
interface I18nLinkProps {
/** Target path (no need to include language prefix) */
to: string;
/** Child elements */
children: React.ReactNode;
/** Other Link component props (such as replace, state, etc.) */
[key: string]: any;
}
Usage Example
import { I18nLink } from '@modern-js/plugin-i18n/runtime';
function Navigation() {
return (
<nav>
<I18nLink to="/">Home</I18nLink>
<I18nLink to="/about">About</I18nLink>
<I18nLink to="/contact" replace>
Contact
</I18nLink>
</nav>
);
}
Runtime Plugin API
In the onBeforeRender hook of Runtime plugins, you can modify the language using the context.changeLanguage method. This is useful for scenarios where you need to dynamically set the language based on request information (such as user preferences, geographic location, etc.).
context.changeLanguage
In the onBeforeRender hook, the i18n plugin adds a changeLanguage method to the context for use by other Runtime plugins.
Type Definition:
interface TInternalRuntimeContext {
i18nInstance?: I18nInstance;
changeLanguage?: (lang: string) => Promise<void>;
}
Usage Example
import type { RuntimePlugin } from '@modern-js/runtime';
const myRuntimePlugin = (): RuntimePlugin => ({
name: 'my-runtime-plugin',
setup: api => {
api.onBeforeRender(async context => {
// Check if changeLanguage method exists (ensure i18n plugin is loaded)
if (context.changeLanguage) {
// Determine language based on some condition
const userLang = getUserLanguageFromRequest(context);
// Change language
await context.changeLanguage(userLang);
}
});
},
});
function getUserLanguageFromRequest(context: any): string {
// Get user language from request headers, cookies, or other sources
const acceptLanguage = context.ssrContext?.req?.headers['accept-language'];
// Parse and return appropriate language code
return parseAcceptLanguage(acceptLanguage) || 'zh';
}
export default myRuntimePlugin;
Notes
-
Execution Order: Ensure the i18n plugin is registered before other plugins that use changeLanguage, so that context.changeLanguage is available.
-
Async Operation: changeLanguage is an async method and requires using await to wait for completion.
-
Error Handling: If an invalid language code is passed, an error will be thrown. It's recommended to add error handling:
api.onBeforeRender(async context => {
if (context.changeLanguage) {
try {
await context.changeLanguage('zh');
} catch (error) {
console.error('Failed to change language:', error);
}
}
});
- Language Validation: It's recommended to verify that the language is in the supported language list before calling
changeLanguage:
api.onBeforeRender(async context => {
if (context.changeLanguage && context.i18nInstance) {
const supportedLngs = context.i18nInstance.options?.supportedLngs || [];
const targetLang = 'zh';
if (supportedLngs.includes(targetLang)) {
await context.changeLanguage(targetLang);
}
}
});
Info
The changeLanguage method will:
- Update the language of the i18n instance
- Cache the language selection in the browser environment (Cookie/LocalStorage)
- Trigger callbacks related to language switching
However, it will not automatically update the URL path. If you need to update the URL, you need to coordinate with the routing plugin or handle it manually.
Integration with react-i18next
The plugin is fully compatible with react-i18next and can use the useTranslation Hook and other react-i18next features.
useTranslation Hook
import { useTranslation } from 'react-i18next';
function MyComponent() {
const { t, i18n } = useTranslation();
return (
<div>
<h1>{t('welcome')}</h1>
<p>{t('description', { name: 'Modern.js' })}</p>
</div>
);
}
Accessing i18next Instance
You can get the i18next instance through useModernI18n:
import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
import { useTranslation } from 'react-i18next';
function MyComponent() {
const { i18nInstance } = useModernI18n();
const { t } = useTranslation();
// Directly access i18next instance
console.log(i18nInstance.language);
console.log(i18nInstance.options);
return <div>{t('hello')}</div>;
}
Type Definitions
I18nInstance Interface
interface I18nInstance {
language: string;
isInitialized: boolean;
init: (options?: I18nInitOptions) => void | Promise<void>;
changeLanguage: (lang: string) => void | Promise<void>;
use: (plugin: any) => void;
createInstance: (options?: I18nInitOptions) => I18nInstance;
cloneInstance?: () => I18nInstance;
services?: {
languageDetector?: {
detect: (request?: any, options?: any) => string | string[] | undefined;
[key: string]: any;
};
[key: string]: any;
};
options?: {
backend?: BackendOptions;
[key: string]: any;
};
}
I18nInitOptions Interface
interface I18nInitOptions {
lng?: string;
fallbackLng?: string;
supportedLngs?: string[];
initImmediate?: boolean;
detection?: LanguageDetectorOptions;
backend?: BackendOptions;
resources?: Resources;
ns?: string | string[];
defaultNS?: string | string[];
react?: {
useSuspense?: boolean;
[key: string]: any;
};
[key: string]: any;
}
LanguageDetectorOptions Interface
interface LanguageDetectorOptions {
/** Detection order */
order?: string[];
/** Query parameter key name, default 'lng' */
lookupQuerystring?: string;
/** Cookie key name, default 'i18next' */
lookupCookie?: string;
/** LocalStorage key name, default 'i18nextLng' (browser only) */
lookupLocalStorage?: string;
/** SessionStorage key name (browser only) */
lookupSession?: string;
/** Starting index in path for language detection, default 0 */
lookupFromPathIndex?: number;
/** Cache method, can be false or string array (e.g., ['cookie', 'localStorage']) */
caches?: boolean | string[];
/** Cookie expiration time (minutes) */
cookieMinutes?: number;
/** Cookie expiration date (Date object, takes precedence over cookieMinutes) */
cookieExpirationDate?: Date;
/** Cookie domain */
cookieDomain?: string;
/** Request header key name, default 'accept-language' */
lookupHeader?: string;
}
Resources Type
type Resources = {
[lng: string]: {
[ns: string]: string | Record<string, string>;
};
};
Info
The namespace value can be a string (for simple key-value pairs) or an object (for nested translation structures).