Implementation:Langgenius Dify I18n Server
| Knowledge Sources | |
|---|---|
| Domains | Frontend, Internationalization |
| Last Updated | 2026-02-12 07:00 GMT |
Overview
Server-side i18next initialization, locale detection, translation retrieval, and resource pre-loading for Next.js server components and middleware.
Description
This module provides the server-side internationalization infrastructure for the Dify Next.js application. It exports three primary functions:
- getTranslation -- Creates or retrieves a cached i18next instance for a given locale, optionally loads a specific namespace, and returns a fixed translation function (
t) scoped to that locale and namespace along with the i18next instance itself. - getLocaleOnServer -- Detects the current user's locale through a two-step process: first checking the
localecookie, then falling back to HTTP Accept-Language header negotiation using the Negotiator library and @formatjs/intl-localematcher. The result is cached per request using a server-only context pattern. - getResources -- Pre-loads all translation JSON files for a given locale by dynamically importing every registered namespace file, converting kebab-case file names back to camelCase keys, and assembling them into a single Resource object. This function is wrapped with React's cache to avoid redundant imports within the same server request.
Internally, the module maintains a singleton i18next instance per request via serverOnlyContext. The instance is configured with react-i18next (server variant via initReactI18next) and a resources-to-backend loader that dynamically imports JSON files from i18n/{locale}/{namespace}.json.
Usage
Use getLocaleOnServer in server components and middleware to determine the user's preferred locale. Use getTranslation in server components to obtain type-safe translation functions for rendering localized content. Use getResources to pre-load all translations for a locale so they can be passed to client components for hydration.
Code Reference
Source Location
- Repository: Langgenius_Dify
- File: web/i18n-config/server.ts
- Lines: 1-94
Signature
export async function getTranslation<T extends Namespace>(
lng: Locale,
ns?: T,
): Promise<{ t: TFunction; i18n: I18nInstance }>
export const getLocaleOnServer: () => Promise<Locale>
export const getResources: (lng: Locale) => Promise<Resource>
Import
import { getTranslation, getLocaleOnServer, getResources } from '@/i18n-config/server'
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| lng (getTranslation) | Locale |
Yes | The locale to use for translations. |
| ns (getTranslation) | Namespace |
No | An optional namespace to ensure is loaded before returning the translation function. |
| lng (getResources) | Locale |
Yes | The locale for which to pre-load all translation resources. |
| (getLocaleOnServer) | -- | -- | No direct inputs; reads from cookies and HTTP headers via Next.js APIs. |
Outputs
| Name | Type | Description |
|---|---|---|
| getTranslation result | { t: TFunction; i18n: I18nInstance } |
A fixed translation function scoped to the given locale and namespace, plus the i18next instance. |
| getLocaleOnServer result | Locale |
The detected locale for the current request, cached for the duration of the request. |
| getResources result | Resource |
An object keyed by locale containing all namespace translations, e.g., { 'en-US': { common: {...}, app: {...}, ... } }.
|
Locale Detection Flow
The getLocaleOnServer function follows this priority order:
- Cookie check -- Reads the
localecookie from the request. If present, uses its value. - Accept-Language negotiation -- If no cookie is found, extracts the
Accept-Languageheader and uses the Negotiator library to determine preferred languages. - Validation -- Ensures the language array is valid (non-empty, contains only safe strings matching
/^[\w-]+$/). Falls back to the default locale ('en-US') if validation fails. - Locale matching -- Uses
@formatjs/intl-localematcher'smatchfunction to find the best match from the supported locales list. - Caching -- Stores the result in a server-only context to avoid repeated computation within the same request.
Usage Examples
Server Component with Translation
import { getTranslation, getLocaleOnServer } from '@/i18n-config/server'
export default async function Page() {
const locale = await getLocaleOnServer()
const { t } = await getTranslation(locale, 'common')
return <h1>{t('welcome')}</h1>
}
Pre-loading Resources for Client Hydration
import { getResources, getLocaleOnServer } from '@/i18n-config/server'
import { createI18nextInstance } from '@/i18n-config/client'
export default async function Layout({ children }: { children: React.ReactNode }) {
const locale = await getLocaleOnServer()
const resources = await getResources(locale)
// Pass resources to a client-side provider for hydration
return (
<I18nProvider locale={locale} resources={resources}>
{children}
</I18nProvider>
)
}
Detecting Locale in Middleware
import { getLocaleOnServer } from '@/i18n-config/server'
const locale = await getLocaleOnServer()
// locale is now 'en-US', 'ja-JP', etc. based on cookie or Accept-Language header