Let's assume that we want to create a navigation of this type:
default language (en-US): routes not localized http://127.0.0.1:4173/
other languages (it-IT): localized routes http://127.0.0.1:4173/it-IT/
In routes root level add [...lang] directory to catch all routes:
src/routes/
│
└───[...lang]/
index.tsx
layout.tsx
Now let's handle it. Update plugin.ts in the root of the src/routes directory:
src/routes/plugin.ts
import type { RequestHandler } from '@builder.io/qwik-city';
import { setSpeakContext, validateLocale } from 'qwik-speak';
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
*/
export const onRequest: RequestHandler = ({ params, locale }) => {
let lang: string | undefined = undefined;
if (params.lang && validateLocale(params.lang)) {
// Check supported locales
lang = config.supportedLocales.find(value => value.lang === params.lang)?.lang;
} else {
lang = config.defaultLocale.lang;
}
// Set Speak context (optional: set the configuration on the server)
setSpeakContext(config);
// Set Qwik locale
locale(lang);
};
If you want to handle errors or redirects due to the locale, use layouts or pages. For example you could add in src/routes/layout.tsx:
export const onRequest: RequestHandler = ({ locale, error, redirect }) => {
// E.g. 404 error page
if (!locale()) throw error(404, 'Page not found for requested locale');
// E.g. Redirect
// if (!locale()) {
// const getPath = localizePath();
// throw redirect(302, getPath('/page', 'en-US')); // Let the server know the language to use
// }
};
Usage
Add index.tsx with some translation, providing optional default values for each translation: key@@[default value]:
i18n/en-US/app.json
i18n/it-IT/app.json
translations skipped due to dynamic keys: 1
extracted keys: 9
app asset for each language, initialized with the default values we provided.
translations skipped due to dynamic keys is runtime.${key}. During configuration, we provided in runtimeAssets a runtime file, which we can now create and populate with dynamic keys:
i18n/[lang]/runtime.json
{
"runtime": {
"dynamic": "I'm a dynamic value"
}
}
We can translate the it-IT files and start the app:
npm start
Production
Build the production app in preview mode:
npm run preview
and inspect the qwik-speak-inline.log file in root folder to see warnings for missing values or dynamic keys.
Domain-based routing
Prefix always
If you want to use different domains in production, update speak-config.ts with the domains supported by each locale, and set the prefix usage strategy: