К содержимому

Локаль в URL

По умолчанию локаль хранится в куки, а URL не меняется. С routing: true каждая локаль, кроме локали по умолчанию, получает собственный префикс пути.

Префикс #

Пишется точно так же, как сама локаль: locales: ['en-US', 'de-DE'] даёт /en-US/some/url. Нужен /de/ — назовите локаль de, второго отображения поддерживать не придётся.

Три детали для подключения #

handle из раздела Setup не меняется: он уже читает префикс URL, когда routing включён. reroute идёт в отдельный, универсальный src/hooks.ts (не hooks.server.ts) — он убирает префикс до того, как SvelteKit сопоставляет маршруты, так что каталог [locale] в src/routes не нужен.

src/lib/i18n.ts
export const { t, handle, reroute, localizeHref, localizedEntries } = createDialect({
	// …messages as in Setup
	locales: ['en-US', 'de-DE'],
	defaultLocale: 'de-DE',
	routing: true
});
src/hooks.ts — universal, not hooks.server.ts
import type { Reroute } from '@sveltejs/kit/hooks';
import { reroute as dialect } from '#lib/i18n.js';

export const reroute: Reroute = dialect;

Примечание

reroute только выбирает маршрут для запроса, а сам URL сохраняет префикс. Поэтому event.url, url в load-функции и page.url показывают /de-DE/about — ровно то, что в адресной строке. Чтобы сравнить с маршрутом, используйте route.id (/about): локали в нём не бывает. Особенно это касается проверок доступа в хуках: /de-DE/admin рендерит тот же маршрут, что и /admin, и guard по event.url.pathname его пропустит.

Развёртывание в поддиректории #

Задайте paths.base как обычно: svelte-dialect/kit подхватит его сам, и префикс локали будет искаться после базового пути, а не вместо него.

vite.config.ts — svelte-dialect/kit reads it, nothing to pass to createDialect
sveltekit({ paths: { base: '/docs' } });

Ссылки #

Для внутренних ссылок используйте localizeHref — обычный href потеряет локаль при переходе. Он подставляет текущую локаль, а локаль по умолчанию всегда получает путь без префикса. Это обычная навигация в пределах одной локали, полной перезагрузки страницы не требует.

<a href={localizeHref('/about')}>About</a>

Переключение локали #

setLocale сам знает, включён ли routing: если да, переключение ведёт на ту же страницу под новым префиксом — намеренно полный переход, чтобы отданный документ, URL и рантайм не разошлись.

Попробуйте #

Эта же страница на каждой локали:

Пререндер префиксных адресов #

Статическая сборка рендерит только то, до чего может дойти краулер, а со страниц локали по умолчанию нет ссылок на /ru/.... localizedEntries умножает пути входа на локали для prerender.entries — рабочий пример смотрите в собственном vite.config.ts демо.

vite.config.ts
import { localizedEntries } from 'svelte-dialect/entries';

localizedEntries(['/', '/about'], { locales: ['en', 'ru'], defaultLocale: 'en' });
// → ['/', '/ru', '/about', '/ru/about']

Что означает URL #

Префикс важнее куки и Accept-Language: URL — это явный запрос конкретной версии страницы. У локали по умолчанию ровно один адрес — /de-DE/some/url, когда de-DE является локалью по умолчанию, отвечает 308 на /some/url. При detectOnBarePath: true заход документа на /about, чья куки или Accept-Language говорят ru, отвечает 307 на /ru/about — по умолчанию выключено. Без этой опции путь без префикса сохраняет свой адрес и показывает локаль, которую выбрали куки или Accept-Language (на статическом сайте — язык браузера), а локаль по умолчанию — только если ни один из них не называет предложенную вами.