Локаль в 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 не нужен.
export const { t, handle, reroute, localizeHref, localizedEntries } = createDialect({
// …messages as in Setup
locales: ['en-US', 'de-DE'],
defaultLocale: 'de-DE',
routing: true
});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 подхватит его сам, и префикс локали будет искаться после базового пути, а не вместо него.
sveltekit({ paths: { base: '/docs' } });Ссылки #
Для внутренних ссылок используйте localizeHref — обычный href потеряет локаль при переходе. Он подставляет текущую локаль, а локаль по умолчанию всегда получает путь без префикса. Это обычная навигация в пределах одной локали, полной перезагрузки страницы не требует.
<a href={localizeHref('/about')}>About</a>Переключение локали #
setLocale сам знает, включён ли routing: если да, переключение ведёт на ту же страницу под новым префиксом — намеренно полный переход, чтобы отданный документ, URL и рантайм не разошлись.
Попробуйте #
Эта же страница на каждой локали:
Пререндер префиксных адресов #
Статическая сборка рендерит только то, до чего может дойти краулер, а со страниц локали по умолчанию нет ссылок на /ru/.... localizedEntries умножает пути входа на локали для prerender.entries — рабочий пример смотрите в собственном 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 (на статическом сайте — язык браузера), а локаль по умолчанию — только если ни один из них не называет предложенную вами.