This is the second part of our previous article, you could find it here if you haven't seen it, yet.
Well, we have the locale
variable with a hardcoded value, now we'll add a new file at the same level of the +layout.ts
called +.layout.server.ts
, here we will write the following content:
// +layout.server.ts
import type { LayoutServerLoad } from './$types';
export const load: LayoutServerLoad = () => {
return { locale: 'en' };
};
Then, we will change the content of the file +layout.ts
to read the value that we are returning from +layout.server.ts
// +layout.ts
import type { LayoutLoad } from './$types';
import { loadLocaleAsync } from '../i18n/i18n-util.async';
import { setLocale } from '../i18n/i18n-svelte';
export const load: LayoutLoad = async (event) => {
- const locale = 'es';
+ const locale = event.data.locale;
await loadLocaleAsync(locale);
setLocale(locale);
return event.data;
};
Our app should work as always, but we are still using a hardcoded value, but the difference is that it comes from our second file.
What we want now is to read a locale
from the URL or from the browser directly, then pass it to the file +layout.server.ts
and this in turn will pass it to the +.layout.ts
.
To accomplish the mentioned above, we need to add another file called hooks.server.ts
but in this case in the src
directory: src/hooks.server.ts
We are going to do something quite similar to what we did when we created the file +layout.server.ts
, we are going to hardcode the lang
but now in the file hooks.server.ts
and within a function called handle
that we should return.
// src/hooks.server.ts
import type { Handle } from '@sveltejs/kit';
export const handle: Handle = async ({ event, resolve }) => {
event.locals.locale = 'es';
return resolve(event);
};
And in the file +layout.server.ts
we need to read the object locals
and its property locale
:
// src/routes/+layout.server.ts
export const load: LayoutServerLoad = ({ locals }) => {
return { locale: locals.locale };
};
If we change from es
to en
and vice-versa, everything should work as always.
Now to remove the hardcoded lang, we will make use of the params in the URL, one more time, go ahead to our file hooks.server.ts
// src/hooks.server.ts
import type { Handle } from '@sveltejs/kit';
export const handle: Handle = async ({ event, resolve }) => {
- event.locals.locale = 'es';
+ const lang = event.url.searchParams.get('lang');
+ event.locals.locale = lang || 'en';
return resolve(event);
};
To test it, we should modify the URL in the browser: http://localhost:5173/?lang=es, if any lang is passed, then it will show the default language, in this case english
.
Perfect, now we can pass what language we want to use by specifying it in the URL
Reading the browser language
Now, we want to do is remove the default hardcoded language set as english
and replace it with the default language from the browser, we should use the function initAcceptLanguageHeaderDetector
in the file hooks.server.ts
, so, let's do it:
// src/hooks.server.ts
const getPreferredLocale = ({ request }: RequestEvent) => {
const acceptLanguageDetector = initAcceptLanguageHeaderDetector(request);
return detectLocale(acceptLanguageDetector);
};
We must add some imports
as well:
// src/hooks.server.ts
// import type { Handle } from '@sveltejs/kit';
+ import type { Handle, RequestEvent } from '@sveltejs/kit';
+ import { detectLocale, i18n, isLocale } from './i18n/i18n-util';
+ import { initAcceptLanguageHeaderDetector } from 'typesafe-i18n/detectors';
Then, we need to update the function handle
:
// src/hooks.server.ts
export const handle: Handle = async ({ event, resolve }) => {
const lang = event.url.searchParams.get('lang');
// event.locals.locale = lang || 'en';
+ event.locals.locale = lang || getPreferredLocale(event);
return resolve(event);
}
Now in my case, I have Spanish as my default language in Chrome:Settings/Languages
If I don't pass any language in the URL, it will read this default language from the browser directly.
Cool!, We are almost done, but there is still an improvement that we could do, for example, if I pass the lang
param via the URL but it doesn't exist in my configuration, it won't read the default browser language because the param lang
in the URL was set, but it is an invalid lang
, if we leave it as it is so right now we will get a pretty 500 error:
http://localhost:5173/?lang=ed
Well to fix that we could add validation for the lang
that was provided to us:
// src/hooks.server.ts
import type { Locales } from './i18n/i18n-types';
export const handle: Handle = async ({ event, resolve }) => {
...
const locale = isLocale(lang as Locales) ? (lang as Locales) : getPreferredLocale(event);
event.locales.locale = locale;
....
}
And that's how we fixed it, we use isLocale
to validate the lang
, if it is a valid lang
, then we use it as a value of locale
if not, then we read it from the default browser lang.
In our next post, we are going to add a button or link to switch the language, that will be our third option to use this feature. See you there and happy coding!
Top comments (0)