B2B-88: add starter kit structure and elements
This commit is contained in:
98
lib/i18n/i18n.server.ts
Normal file
98
lib/i18n/i18n.server.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import 'server-only';
|
||||
|
||||
import { cache } from 'react';
|
||||
|
||||
import { cookies, headers } from 'next/headers';
|
||||
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
initializeServerI18n,
|
||||
parseAcceptLanguageHeader,
|
||||
} from '@kit/i18n/server';
|
||||
|
||||
import featuresFlagConfig from '~/config/feature-flags.config';
|
||||
import {
|
||||
I18N_COOKIE_NAME,
|
||||
getI18nSettings,
|
||||
languages,
|
||||
} from '~/lib/i18n/i18n.settings';
|
||||
|
||||
import { i18nResolver } from './i18n.resolver';
|
||||
|
||||
/**
|
||||
* @name priority
|
||||
* @description The language priority setting from the feature flag configuration.
|
||||
*/
|
||||
const priority = featuresFlagConfig.languagePriority;
|
||||
|
||||
/**
|
||||
* @name createI18nServerInstance
|
||||
* @description Creates an instance of the i18n server.
|
||||
* It uses the language from the cookie if it exists, otherwise it uses the language from the accept-language header.
|
||||
* If neither is available, it will default to the provided environment variable.
|
||||
*
|
||||
* Initialize the i18n instance for every RSC server request (eg. each page/layout)
|
||||
*/
|
||||
async function createInstance() {
|
||||
const cookieStore = await cookies();
|
||||
const langCookieValue = cookieStore.get(I18N_COOKIE_NAME)?.value;
|
||||
|
||||
let selectedLanguage: string | undefined = undefined;
|
||||
|
||||
// if the cookie is set, use the language from the cookie
|
||||
if (langCookieValue) {
|
||||
selectedLanguage = getLanguageOrFallback(langCookieValue);
|
||||
}
|
||||
|
||||
// if not, check if the language priority is set to user and
|
||||
// use the user's preferred language
|
||||
if (!selectedLanguage && priority === 'user') {
|
||||
const userPreferredLanguage = await getPreferredLanguageFromBrowser();
|
||||
|
||||
selectedLanguage = getLanguageOrFallback(userPreferredLanguage);
|
||||
}
|
||||
|
||||
const settings = getI18nSettings(selectedLanguage);
|
||||
|
||||
return initializeServerI18n(settings, i18nResolver);
|
||||
}
|
||||
|
||||
export const createI18nServerInstance = cache(createInstance);
|
||||
|
||||
/**
|
||||
* @name getPreferredLanguageFromBrowser
|
||||
* Get the user's preferred language from the accept-language header.
|
||||
*/
|
||||
async function getPreferredLanguageFromBrowser() {
|
||||
const headersStore = await headers();
|
||||
const acceptLanguage = headersStore.get('accept-language');
|
||||
|
||||
// no accept-language header, return
|
||||
if (!acceptLanguage) {
|
||||
return;
|
||||
}
|
||||
|
||||
return parseAcceptLanguageHeader(acceptLanguage, languages)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @name getLanguageOrFallback
|
||||
* Get the language or fallback to the default language.
|
||||
* @param selectedLanguage
|
||||
*/
|
||||
function getLanguageOrFallback(selectedLanguage: string | undefined) {
|
||||
const language = z
|
||||
.enum(languages as [string, ...string[]])
|
||||
.safeParse(selectedLanguage);
|
||||
|
||||
if (language.success) {
|
||||
return language.data;
|
||||
}
|
||||
|
||||
console.warn(
|
||||
`The language passed is invalid. Defaulted back to "${languages[0]}"`,
|
||||
);
|
||||
|
||||
return languages[0];
|
||||
}
|
||||
Reference in New Issue
Block a user