SEO
There are quite a few SEO related things you need to keep in mind when developing a multi-language site. This page will give you a quick overview of the most important ones.
Alternate Links
Alternate links are a way to tell search engines that a page exists in multiple languages, and where to find them. This is done by adding a link tag to the head of your page.
You should add a link tag for each language your site is available in, including the one the page is currently in.
<head>
<link rel="alternate" href="/en" hreflang="en" />
<link rel="alternate" href="/de" hreflang="de" />
</head>
If you have a “default language” that you want to use when the user’s language is not available, you should add a link tag with the hreflang
attribute set to x-default
. This tells search engines that this is the default language.
<head>
<link rel="alternate" href="/en" hreflang="en" />
<link rel="alternate" href="/de" hreflang="de" />
<!--Use the english site as the default-->
<link rel="alternate" href="/en"; hreflang="x-default" />
</head>
Locale Switchers
It is recommended that you use a
tags for your locale switchers. This is because search engines and the SvelteKit prerenderer will follow these links, and index the pages they lead to. They also work if JavaScript is disabled.
But, we need to make sure to tell the search engines that these links just lead to the same page in a different language, not separate pages. We do this by adding an hreflang
attribute.
<a href="/de" hreflang="de">Deutsch</a>
The Lang Attribute
Browsers determine the page’s language by looking at the lang
attribute on the html
tag. We need to make sure that this attribute is set to the correct language, both during server rendering, and when switching languages on the client.
On the Server
SvelteKit offers a relatively simple way to set the lang
attribute during server rendering. We can set it in a hook.
In the app template, let’s add a placeholder string in the lang
attribute.
src/app.html
<!DOCTYPE html>
<html lang="%lang%">
<!-- ... -->
</html>
Then in the server handle
hook, we can replace it with the correct language.
src/hooks.server.js
export const handle = async ({ event, resolve }) => {
//Determine the locale from the URL.
//Implementing this is up to you, depending on your routing solution.
const locale = getLocale(event);
const response = await resolve(event, {
//Replace the placeholder %lang% with the current locale.
transformPageChunk({ html }) {
html = html.replace("%lang%", locale);
return html;
},
});
return response;
};
On the client
T18S does not do a full page reload when switching languages, so we need to make sure that the lang
attribute gets set correctly when switching languages on the client.
In the root layout. Check that we are in the browser, and then reactively set the lang
attribute base on the $locale
store exported by T18S.
src/routes/+layout.svelte
<script>
import { locale } from "$t18s";
import { browser } from "$app/environment";
$: if(browser) document.documentElement.lang = $locale;
</script>
<slot />
This may become built in behavior in the future, depending on feedback. Old code probably won't break, so you can add this now without worrying about it.
Text Direction
It’s important to set the dir
attribute on the html
tag to the correct value. This can be done in the same way as the lang
attribute.
You can get the current locale’s direction using the built in Intl
API.
src/routes/+layout.svelte
const dir = new Intl.Locale(get(locale)).textInfo.direction;
You then do the same thing as with the lang
attribute.