dify/web/i18n-config/server.ts

63 lines
2.2 KiB
TypeScript
Raw Normal View History

import type { Locale } from '.'
import type { NamespaceCamelCase, NamespaceKebabCase } from './i18next-config'
2023-05-15 00:51:32 +00:00
import { match } from '@formatjs/intl-localematcher'
import { camelCase } from 'es-toolkit/compat'
2024-02-23 06:31:06 +00:00
import { createInstance } from 'i18next'
import resourcesToBackend from 'i18next-resources-to-backend'
import Negotiator from 'negotiator'
import { cookies, headers } from 'next/headers'
2024-02-23 06:31:06 +00:00
import { initReactI18next } from 'react-i18next/initReactI18next'
2023-05-15 00:51:32 +00:00
import { i18n } from '.'
2024-02-23 06:31:06 +00:00
// https://locize.com/blog/next-13-app-dir-i18n/
const initI18next = async (lng: Locale, ns: NamespaceKebabCase) => {
2024-02-23 06:31:06 +00:00
const i18nInstance = createInstance()
await i18nInstance
.use(initReactI18next)
.use(resourcesToBackend((language: Locale, namespace: NamespaceKebabCase) => {
return import(`../i18n/${language}/${namespace}.json`)
}))
2024-02-23 06:31:06 +00:00
.init({
lng: lng === 'zh-Hans' ? 'zh-Hans' : lng,
ns,
defaultNS: ns,
2024-02-23 06:31:06 +00:00
fallbackLng: 'en-US',
keySeparator: false,
2024-02-23 06:31:06 +00:00
})
return i18nInstance
}
export async function getTranslation(lng: Locale, ns: NamespaceKebabCase) {
const camelNs = camelCase(ns) as NamespaceCamelCase
2024-02-23 06:31:06 +00:00
const i18nextInstance = await initI18next(lng, ns)
return {
t: i18nextInstance.getFixedT(lng, camelNs),
2024-02-23 06:31:06 +00:00
i18n: i18nextInstance,
}
}
2023-05-15 00:51:32 +00:00
export const getLocaleOnServer = async (): Promise<Locale> => {
2023-05-15 00:51:32 +00:00
const locales: string[] = i18n.locales
let languages: string[] | undefined
// get locale from cookie
const localeCookie = (await cookies()).get('locale')
2023-05-15 00:51:32 +00:00
languages = localeCookie?.value ? [localeCookie.value] : []
if (!languages.length) {
// Negotiator expects plain object so we need to transform headers
const negotiatorHeaders: Record<string, string> = {};
(await headers()).forEach((value, key) => (negotiatorHeaders[key] = value))
2023-05-15 00:51:32 +00:00
// Use negotiator and intl-localematcher to get best locale
languages = new Negotiator({ headers: negotiatorHeaders }).languages()
}
2024-04-20 02:50:10 +00:00
// Validate languages
if (!Array.isArray(languages) || languages.length === 0 || !languages.every(lang => typeof lang === 'string' && /^[\w-]+$/.test(lang)))
2024-04-20 02:50:10 +00:00
languages = [i18n.defaultLocale]
2023-05-15 00:51:32 +00:00
// match locale
const matchedLocale = match(languages, locales, i18n.defaultLocale) as Locale
return matchedLocale
}