Let's create speak-config.ts and speak-functions.ts files in src folder:
src/speak-config.ts
importtype { SpeakConfig } from'qwik-speak';exportconstconfig:SpeakConfig= { defaultLocale: { lang:'en-US', currency:'USD', timeZone:'America/Los_Angeles' }, supportedLocales: [ { lang:'it-IT', currency:'EUR', timeZone:'Europe/Rome' }, { lang:'en-US', currency:'USD', timeZone:'America/Los_Angeles' } ],// Translations available in the whole app assets: ['app' ],// Translations with dynamic keys available in the whole app runtimeAssets: ['runtime' ]};
src/speak-functions.ts
import { server$ } from'@builder.io/qwik-city';importtype { LoadTranslationFn, Translation, TranslationFn } from'qwik-speak';/** * Translation files are lazy-loaded via dynamic import and will be split into separate chunks during build. * Assets names and keys must be valid variable names */consttranslationData=import.meta.glob<Translation>('/i18n/**/*.json');/** * Using server$, translation data is always accessed on the server */constloadTranslation$:LoadTranslationFn=server$(async (lang:string, asset:string) =>await translationData[`/i18n/${lang}/${asset}.json`]?.());exportconsttranslationFn:TranslationFn= { loadTranslation$: loadTranslation$};
loadTranslation$ is a customizable QRL function: you can load the translation files in the way you prefer
Create plugin.ts in the root of the src/routes directory:
src/routes/plugin.ts
importtype { RequestHandler } from'@builder.io/qwik-city';import { config } from'../speak-config';/** * This middleware function must only contain the logic to set the locale, * because it is invoked on every request to the server. * Avoid redirecting or throwing errors here, and prefer layouts or pages */exportconstonRequest:RequestHandler= ({ request, locale }) => {constacceptLanguage=request.headers?.get('accept-language');let lang:string|null=null;// Try to use user languageif (acceptLanguage) { lang =acceptLanguage.split(';')[0]?.split(',')[0]; }// Check supported locales lang =config.supportedLocales.find(value =>value.lang === lang)?.lang ||config.defaultLocale.lang;// Set Qwik localelocale(lang);};
We're on the server here, and you can get the language from acceptLanguage, a cookie, or a URL parameter, as you like. But is mandatory to set the Qwik locale
Set the base URL for loading the chunks in the browser in entry.ssr.tsx file:
import { isDev } from'@builder.io/qwik/build';importtype { RenderOptions } from"@builder.io/qwik/server";import { config } from'./speak-config';/** * Determine the base URL to use for loading the chunks in the browser. * The value set through Qwik 'locale()' in 'plugin.ts' is saved by Qwik in 'serverData.locale' directly. * Make sure the locale is among the 'supportedLocales' */exportfunctionextractBase({ serverData }:RenderOptions):string {if (!isDev &&serverData?.locale) {return'/build/'+serverData.locale; } else {return'/build'; }}exportdefaultfunction (opts:RenderToStreamOptions) {returnrenderToStream(<Root />, { manifest,...opts,// Determine the base URL for the client code base: extractBase,// Use container attributes to set attributes on the html tag containerAttributes: { lang:opts.serverData?.locale ||config.defaultLocale.lang,...opts.containerAttributes, }, });}