Integrating Internationalization
Modern.js provides the @modern-js/plugin-i18n plugin to support internationalization. When using Module Federation, you need to provide corresponding i18n integration solutions for different scenarios (components or applications).
Prerequisites
Before you begin, make sure you have:
- Understood Module Federation Basic Usage
- Understood Basic Usage of the Internationalization Plugin
- Created producer and consumer applications
Solution Overview
In Module Federation scenarios, producers and consumers need to share or independently manage i18n instances. Based on different use cases, we provide two solutions:
- Shared I18n Instance: Producers and consumers use the same i18n instance, and language switching will be synchronized
- Independent I18n Instance: Producers and consumers maintain their own independent i18n instances and can switch languages independently
For component scenarios, we recommend using a shared I18n instance, because components are ultimately rendered on the same React tree, and sharing an instance ensures consistency in language switching.
For detailed usage of the i18n plugin, please refer to the Internationalization Documentation.
Enabling I18n Capability
Both producers and consumers need to enable i18n capability first.
Install Dependencies
In Module Federation scenarios, you need to install both the i18n plugin and the Module Federation plugin:
i18next and react-i18next are peer dependencies and need to be installed manually.
Configure Plugins
Configure both the i18n plugin and the Module Federation plugin in modern.config.ts:
For detailed configuration options of the i18n plugin, please refer to the Configuration Documentation.
Scenario 1: Producer - Component
When the producer exports component-level modules, you can use the following two solutions to integrate i18n.
Shared I18n Instance (Recommended)
For component scenarios, producers and consumers are ultimately on the same React tree, so you only need to share the i18next and react-i18next dependencies.
Both producers and consumers need to configure shared in module-federation.config.ts to ensure that i18next and react-i18next use singleton mode.
Configure Module Federation
Using Translation
Use the useTranslation hook from react-i18next in components to perform translation:
When using a shared instance, remote components will use the consumer's i18n instance, and when the main application switches languages, the corresponding remote components will automatically update.
Independent I18n Instance
If the producer needs to maintain its own I18n instance (for example, it needs independent language resources or language switching logic), you can avoid configuring shared for i18next and react-i18next, but you need to:
- Create an independent i18n instance
- Wrap the exported component with
I18nextProvider - Export a language switching Hook for consumers to use
Create an Independent I18n Instance
Wrap Component with I18nextProvider
Export Language Switching Hook
Export a changeLanguage hook that allows consumers to switch the language of the corresponding producer:
When using an independent I18n instance, the producer maintains its own language state. Consumers need to manually call the language switching hook to synchronize language changes between the main application and the remote component. This approach is useful when the producer needs to maintain its own language resources or has independent language switching logic.
Configure Module Federation
Scenario 2: Consumer - Component
When consumers need to load remote components, they need to configure accordingly based on the solution used by the producer.
Configure Module Federation
First, configure the remote module in the consumer's module-federation.config.ts:
If the producer uses a shared I18n instance, the consumer must configure shared for i18next and react-i18next. If the producer uses an independent instance, there is no need to configure shared for these two dependencies.
Shared I18n Instance
When the producer uses a shared I18n instance, the consumer can directly load the remote component without additional configuration:
The i18n resources and i18n instance used here are from the main application. When the main application switches languages, the corresponding remote components will automatically update.
Independent I18n Instance
When the producer uses an independent I18n instance, the consumer needs to handle the language switching logic for both the main application and the remote component:
For detailed API documentation of the useModernI18n Hook, please refer to the API Reference Documentation.
When using an independent I18n instance:
- The producer and consumer maintain separate language states
- Language switching must be synchronized manually by calling both the main application's
changeLanguageand the remote component's language switching hook - This approach is recommended when the producer needs independent language resources or custom language switching logic
- For component scenarios, we generally recommend using a shared I18n instance for better consistency
Scenario 3: Producer - Application
When the producer exports application-level modules, you need to use the Bridge API to export the application. For detailed information about application-level modules, please refer to Application-Level Modules.
Producers do not support enabling path redirection (localePathRedirect). Route and language switching need to be managed uniformly in the consumer.
For detailed information about routing integration, please refer to the Routing Integration Documentation.
Export Application
First, you need to create an entry file to export the application:
Shared I18n Instance
Configure Module Federation
Configure Runtime to Use Shared Instance
Configure the use of a shared i18n instance in modern.runtime.tsx:
When using a shared instance, i18next here does not need to call init. You can directly use the default exported i18next instance initialized by the consumer.
For applications with multiple entries, defineRuntimeConfig can accept a function that receives the entryName parameter, allowing you to return different configurations for different entries:
This is useful when you need different i18n instances for different entry points.
For detailed information about the i18nInstance configuration, please refer to the Configuration Documentation.
Independent I18n Instance (Recommended)
For an independent I18n instance, no additional operations are needed. The producer will use its own i18n instance. The i18n plugin will automatically initialize the i18n instance.
Scenario 4: Consumer - Application
When consumers need to load remote applications, they need to use the Bridge API to load application-level modules.
Configure Module Federation
First, configure the remote application in the consumer's module-federation.config.ts:
If the producer uses a shared I18n instance, the consumer must configure shared for i18next and react-i18next. If the producer uses an independent instance, there is no need to configure shared for these two dependencies.
Define Component to Load Remote Application
Create a component for loading the remote application:
The export parameter in createRemoteAppComponent specifies which export to use from the remote module:
- When the producer uses
export default, you can omit this parameter - When the producer uses named exports (e.g.,
export const provider), you must specify the export name :::
Using Remote Application in Routes
Use the remote application component in route files. The basename parameter is used to specify the base path of the remote application and needs to be determined based on whether path redirection (localePathRedirect) is enabled:
When Path Redirection is Enabled
If the consumer has enabled path redirection (localePathRedirect: true), the route will include a [lang] dynamic parameter. You need to get the language information from the route parameters and pass it to basename:
When Path Redirection is Not Enabled
If the consumer has not enabled path redirection (localePathRedirect: false or not configured), the route does not include a language parameter, and basename only needs to include the route path:
:::note
Rules for calculating basename:
- When
localePathRedirectis enabled:basenameneeds to include the language prefix in the format${lang}/${routePath}(e.g.,zh/remote,en/remote) - When
localePathRedirectis not enabled:basenameonly needs to include the route path in the format${routePath}(e.g.,remote), without adding a language prefix
Shared I18n Instance
When the producer uses a shared I18n instance, the consumer needs to create a custom i18n instance and use it in the runtime configuration.
Create Custom I18n Instance
Create a custom i18n instance using the default exported instance from i18next:
Configure Runtime to Use Custom Instance
Pass the custom i18n instance into the application:
For detailed information about the i18nInstance configuration, please refer to the Configuration Documentation.
Independent I18n Instance
For an independent I18n instance, no additional operations are needed. The remote application will use its own i18n instance.
Summary
Key points for integrating i18n with Module Federation:
- Component Scenarios: It is recommended to use a shared I18n instance. Producers and consumers share
i18nextandreact-i18next, and language switching will be automatically synchronized - Application Scenarios: You can choose to share or use an independent I18n instance based on business requirements
- Configuration Points: Ensure that the
sharedconfiguration of producers and consumers is consistent, especially the singleton configuration ofi18nextandreact-i18next - Route Management: Producers do not support path redirection (
localePathRedirect). Route and language switching need to be managed uniformly in the consumer - Dependency Sharing: When using a shared instance, you must configure
i18nextandreact-i18nextas singletons in both the producer's and consumer'smodule-federation.config.ts - Name Uniqueness: The
nameparameter ofcreateModuleFederationConfigmust be unique for each application and cannot be the same for different remotes