From ca8dd6388e7cb472af483390e63550d2cfe13b90 Mon Sep 17 00:00:00 2001 From: Nick Kosarev Date: Fri, 21 Jun 2024 14:11:09 +0200 Subject: [PATCH] fix: take locale on hook, use custom dictionary --- src/app.d.ts | 4 +- src/hooks.server.ts | 36 ++++++- src/lib/components/Header.svelte | 15 +-- src/lib/components/Locale.svelte | 29 +++--- src/lib/translations/en.ts | 20 ++++ src/lib/translations/en/about.json | 3 - src/lib/translations/en/character.json | 3 - src/lib/translations/en/error.json | 6 -- src/lib/translations/en/header.json | 7 -- src/lib/translations/en/home.json | 3 - src/lib/translations/index.ts | 95 +++---------------- src/lib/translations/lang.json | 4 - src/lib/translations/ru.ts | 20 ++++ src/lib/translations/ru/about.json | 3 - src/lib/translations/ru/character.json | 3 - src/lib/translations/ru/error.json | 6 -- src/lib/translations/ru/header.json | 7 -- src/lib/translations/ru/home.json | 3 - src/routes/(website)/+error.svelte | 15 --- src/routes/(website)/+layout.server.ts | 26 ----- src/routes/(website)/+layout.ts | 13 --- src/routes/+error.svelte | 16 ++++ .../{(game)/play => }/+layout.server.ts | 5 + .../{ => [lang]}/(game)/play/+layout.svelte | 0 .../{ => [lang]}/(game)/play/+page.svelte | 0 .../(game)/play/GameChunkInfo.svelte | 0 .../(game)/play/GameCommand.svelte | 0 .../(game)/play/GameEventCard.svelte | 0 .../(game)/play/GameEventTimer.svelte | 0 .../(game)/play/GameEvents.svelte | 0 .../(game)/play/GameHeader.svelte | 0 .../(game)/play/GameInterface.svelte | 0 .../{ => [lang]}/(game)/play/GameItem.svelte | 0 .../(game)/play/GameLoader.svelte | 0 .../(game)/play/GameLocation.svelte | 0 .../(game)/play/GamePlayerCard.svelte | 0 .../(game)/play/GamePlayersGroup.svelte | 0 .../(game)/play/GamePollProgress.svelte | 0 .../(game)/play/GameQuestConditions.svelte | 0 .../(game)/play/GameQuestTask.svelte | 0 .../(game)/play/GameQuestTaskProgress.svelte | 0 .../(game)/play/GameRouteInfo.svelte | 0 .../(game)/play/GameRouteItem.svelte | 0 .../(game)/play/GameTopPlayerCard.svelte | 0 .../(game)/play/GameTopPlayers.svelte | 0 .../(game)/play/GameTradeOffer.svelte | 0 .../{ => [lang]}/(game)/play/GameUnit.svelte | 0 .../(game)/play/GameWagonInfo.svelte | 0 .../(game)/play/GameWarehouseInfo.svelte | 0 .../(game)/play/__tests__/GameEvents.spec.ts | 0 .../{ => [lang]}/(website)/+layout.svelte | 0 .../{ => [lang]}/(website)/+page.server.ts | 0 .../{ => [lang]}/(website)/+page.svelte | 0 .../{ => [lang]}/(website)/about/+page.svelte | 0 .../(website)/auth/profile/+server.ts | 0 .../(website)/auth/sign-in/+page.svelte | 0 .../(website)/auth/sign-in/+server.ts | 0 .../(website)/character/+page.server.ts | 0 .../(website)/character/+page.svelte | 0 .../character/[slug]/+page.server.ts | 0 .../(website)/character/[slug]/+page.svelte | 0 .../{ => [lang]}/(website)/p/+page.server.ts | 0 .../(website)/p/[slug]/+page.server.ts | 0 .../(website)/p/[slug]/+page.svelte | 0 64 files changed, 134 insertions(+), 208 deletions(-) create mode 100644 src/lib/translations/en.ts delete mode 100644 src/lib/translations/en/about.json delete mode 100644 src/lib/translations/en/character.json delete mode 100644 src/lib/translations/en/error.json delete mode 100644 src/lib/translations/en/header.json delete mode 100644 src/lib/translations/en/home.json delete mode 100644 src/lib/translations/lang.json create mode 100644 src/lib/translations/ru.ts delete mode 100644 src/lib/translations/ru/about.json delete mode 100644 src/lib/translations/ru/character.json delete mode 100644 src/lib/translations/ru/error.json delete mode 100644 src/lib/translations/ru/header.json delete mode 100644 src/lib/translations/ru/home.json delete mode 100644 src/routes/(website)/+error.svelte delete mode 100644 src/routes/(website)/+layout.server.ts delete mode 100644 src/routes/(website)/+layout.ts create mode 100644 src/routes/+error.svelte rename src/routes/{(game)/play => }/+layout.server.ts (58%) rename src/routes/{ => [lang]}/(game)/play/+layout.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/+page.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameChunkInfo.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameCommand.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameEventCard.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameEventTimer.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameEvents.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameHeader.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameInterface.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameItem.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameLoader.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameLocation.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GamePlayerCard.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GamePlayersGroup.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GamePollProgress.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameQuestConditions.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameQuestTask.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameQuestTaskProgress.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameRouteInfo.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameRouteItem.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameTopPlayerCard.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameTopPlayers.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameTradeOffer.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameUnit.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameWagonInfo.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/GameWarehouseInfo.svelte (100%) rename src/routes/{ => [lang]}/(game)/play/__tests__/GameEvents.spec.ts (100%) rename src/routes/{ => [lang]}/(website)/+layout.svelte (100%) rename src/routes/{ => [lang]}/(website)/+page.server.ts (100%) rename src/routes/{ => [lang]}/(website)/+page.svelte (100%) rename src/routes/{ => [lang]}/(website)/about/+page.svelte (100%) rename src/routes/{ => [lang]}/(website)/auth/profile/+server.ts (100%) rename src/routes/{ => [lang]}/(website)/auth/sign-in/+page.svelte (100%) rename src/routes/{ => [lang]}/(website)/auth/sign-in/+server.ts (100%) rename src/routes/{ => [lang]}/(website)/character/+page.server.ts (100%) rename src/routes/{ => [lang]}/(website)/character/+page.svelte (100%) rename src/routes/{ => [lang]}/(website)/character/[slug]/+page.server.ts (100%) rename src/routes/{ => [lang]}/(website)/character/[slug]/+page.svelte (100%) rename src/routes/{ => [lang]}/(website)/p/+page.server.ts (100%) rename src/routes/{ => [lang]}/(website)/p/[slug]/+page.server.ts (100%) rename src/routes/{ => [lang]}/(website)/p/[slug]/+page.svelte (100%) diff --git a/src/app.d.ts b/src/app.d.ts index 0954c50b..e7d13739 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -1,11 +1,11 @@ /// -import type { IProfile } from '$lib/types' +import type { IProfile, Locale } from '$lib/types' declare global { namespace App { interface Locals { profile: null | IProfile - lang: string + locale: Locale } // interface Error {} diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 0234a434..b574d030 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,10 +1,18 @@ -import { type Handle, error } from '@sveltejs/kit' +import { type Handle, type RequestEvent, error, redirect } from '@sveltejs/kit' import jwt from 'jsonwebtoken' import { env as privateEnv } from '$env/dynamic/private' import { env as publicEnv } from '$env/dynamic/public' import type { IProfile } from '$lib/types' +import { type Locale, defaultLocale, supportedLocales } from '$lib/translations' export const handle: Handle = async ({ event, resolve }) => { + handleJWT(event) + handleLang(event) + + return resolve(event) +} + +function handleJWT(event: RequestEvent) { const cookieKey = publicEnv.PUBLIC_COOKIE_KEY const jwtSecret = privateEnv.PRIVATE_JWT_SECRET_KEY @@ -12,7 +20,7 @@ export const handle: Handle = async ({ event, resolve }) => { const token = event.cookies.get(cookieKey) if (!token) { event.locals.profile = null - return resolve(event) + return } try { @@ -35,6 +43,28 @@ export const handle: Handle = async ({ event, resolve }) => { } } } +} - return resolve(event) +function handleLang(event: RequestEvent) { + const { pathname, search } = new URL(event.request.url) + + const pathLang = pathname.match(/[^/]+(?=\/|$)/) + const pathnameWithoutLang = pathLang ? pathname.replace(`/${pathLang}`, '') : pathname + const matchedLang = pathLang ? pathLang[0].toLowerCase() : null + + // First time on website? Let's find locale + if (!matchedLang) { + const browserLocale = `${`${event.request.headers.get('accept-language')}`.match(/[a-z]+(?=[\-_,;])/i)}`.toLowerCase() + const locale = supportedLocales.find((locale) => locale === browserLocale) ? browserLocale : defaultLocale + + event.locals.locale = locale as Locale + redirect(301, `/${locale}${pathnameWithoutLang}${search}`) + } + + // We don't have this locale? + if (!supportedLocales.find((locale) => locale === matchedLang)) { + redirect(301, `/${defaultLocale}${pathnameWithoutLang}${search}`) + } + + event.locals.locale = matchedLang as Locale } diff --git a/src/lib/components/Header.svelte b/src/lib/components/Header.svelte index 15faffcc..59d7d741 100644 --- a/src/lib/components/Header.svelte +++ b/src/lib/components/Header.svelte @@ -1,9 +1,11 @@ -
@@ -20,19 +22,20 @@ + +
-
diff --git a/src/lib/components/Locale.svelte b/src/lib/components/Locale.svelte index b4ee212b..efa1e6b7 100644 --- a/src/lib/components/Locale.svelte +++ b/src/lib/components/Locale.svelte @@ -1,19 +1,24 @@ -
- -
+ + + diff --git a/src/lib/translations/en.ts b/src/lib/translations/en.ts new file mode 100644 index 00000000..3116e7b5 --- /dev/null +++ b/src/lib/translations/en.ts @@ -0,0 +1,20 @@ +export type Dictionary = typeof en + +export const en = { + about: undefined, + character: undefined, + error: { + 404: 'Page not found.', + 500: 'Server internal error.', + title: 'Oh, dear...', + default: 'Here we go... Or is that a feature?', + }, + header: { + menu: { + home: 'Home', + about: 'About', + characters: 'Characters', + }, + }, + home: undefined, +} diff --git a/src/lib/translations/en/about.json b/src/lib/translations/en/about.json deleted file mode 100644 index 0db3279e..00000000 --- a/src/lib/translations/en/about.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} diff --git a/src/lib/translations/en/character.json b/src/lib/translations/en/character.json deleted file mode 100644 index 0db3279e..00000000 --- a/src/lib/translations/en/character.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} diff --git a/src/lib/translations/en/error.json b/src/lib/translations/en/error.json deleted file mode 100644 index 6f6f4752..00000000 --- a/src/lib/translations/en/error.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "404": "Page not found.", - "500": "Server internal error.", - "title": "Oh, dear...", - "default": "Here we go... Or is that a feature?" -} diff --git a/src/lib/translations/en/header.json b/src/lib/translations/en/header.json deleted file mode 100644 index bb3e7f2a..00000000 --- a/src/lib/translations/en/header.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "menu": { - "home": "Home", - "about": "About", - "character": "Character" - } -} diff --git a/src/lib/translations/en/home.json b/src/lib/translations/en/home.json deleted file mode 100644 index 0db3279e..00000000 --- a/src/lib/translations/en/home.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} diff --git a/src/lib/translations/index.ts b/src/lib/translations/index.ts index db391b3a..b406bca7 100644 --- a/src/lib/translations/index.ts +++ b/src/lib/translations/index.ts @@ -1,88 +1,17 @@ -import I18n from 'sveltekit-i18n' -import type { Config } from 'sveltekit-i18n' -import lang from './lang.json' -import { dev } from '$app/environment' +import { ru } from '$lib/translations/ru' +import { type Dictionary, en } from '$lib/translations/en' + +export type Locale = 'en' | 'ru' export const defaultLocale = 'en' -export const config: Config = { - log: { - level: dev ? 'warn' : 'error', - }, - translations: { - en: { lang }, - ru: { lang }, - }, - loaders: [ - { - locale: 'en', - key: 'header', - loader: async () => (await import('./en/header.json')).default, - }, - { - locale: 'en', - key: 'error', - loader: async () => (await import('./en/error.json')).default, - }, - { - locale: 'en', - key: 'home', - routes: ['/'], - loader: async () => (await import('./en/home.json')).default, - }, - { - locale: 'en', - key: 'about', - routes: ['/about'], - loader: async () => (await import('./en/about.json')).default, - }, - { - locale: 'en', - key: 'character', - routes: ['/character'], - loader: async () => (await import('./en/character.json')).default, - }, - { - locale: 'ru', - key: 'header', - loader: async () => (await import('./ru/header.json')).default, - }, - { - locale: 'ru', - key: 'error', - loader: async () => (await import('./ru/error.json')).default, - }, - { - locale: 'ru', - key: 'home', - routes: ['/'], - loader: async () => (await import('./ru/home.json')).default, - }, - { - locale: 'ru', - key: 'about', - routes: ['/about'], - loader: async () => (await import('./ru/about.json')).default, - }, - { - locale: 'ru', - key: 'character', - routes: ['/character'], - loader: async () => (await import('./ru/character.json')).default, - }, - ], -} +export const supportedLocales = ['en', 'ru'] as Locale[] -export const { - t, - locale, - locales, - loading, - addTranslations, - loadTranslations, - translations, - setRoute, - setLocale, -} = new I18n(config) +const translations = { + en, + ru, +} -loading.subscribe(($loading) => $loading && console.log('Loading translations...')) +export function dictionary(locale: Locale): Dictionary { + return translations[locale] +} diff --git a/src/lib/translations/lang.json b/src/lib/translations/lang.json deleted file mode 100644 index c15ba482..00000000 --- a/src/lib/translations/lang.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "en": "English", - "ru": "Русский" -} diff --git a/src/lib/translations/ru.ts b/src/lib/translations/ru.ts new file mode 100644 index 00000000..9865e610 --- /dev/null +++ b/src/lib/translations/ru.ts @@ -0,0 +1,20 @@ +import type { Dictionary } from '$lib/translations/en' + +export const ru = { + about: undefined, + character: undefined, + error: { + 404: 'Страница не найдена.', + 500: 'Произошла ошибка на сервере.', + title: 'О, Боже...', + default: 'Ну вот... Или это фича?', + }, + header: { + menu: { + home: 'Главная', + about: 'Об игре', + characters: 'Персонажи', + }, + }, + home: undefined, +} satisfies Dictionary diff --git a/src/lib/translations/ru/about.json b/src/lib/translations/ru/about.json deleted file mode 100644 index 0db3279e..00000000 --- a/src/lib/translations/ru/about.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} diff --git a/src/lib/translations/ru/character.json b/src/lib/translations/ru/character.json deleted file mode 100644 index 0db3279e..00000000 --- a/src/lib/translations/ru/character.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} diff --git a/src/lib/translations/ru/error.json b/src/lib/translations/ru/error.json deleted file mode 100644 index df668cc8..00000000 --- a/src/lib/translations/ru/error.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "404": "Страница не найдена.", - "500": "Произошла ошибка на сервере.", - "title": "О, Боже...", - "default": "Ну вот... Или это фича?" -} diff --git a/src/lib/translations/ru/header.json b/src/lib/translations/ru/header.json deleted file mode 100644 index 431174a3..00000000 --- a/src/lib/translations/ru/header.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "menu": { - "home": "Главная", - "about": "Об игре", - "character": "Персонажи" - } -} diff --git a/src/lib/translations/ru/home.json b/src/lib/translations/ru/home.json deleted file mode 100644 index 0db3279e..00000000 --- a/src/lib/translations/ru/home.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} diff --git a/src/routes/(website)/+error.svelte b/src/routes/(website)/+error.svelte deleted file mode 100644 index e0e75489..00000000 --- a/src/routes/(website)/+error.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - -

{$t('error.title')} ({$page.status})

- -

{$t(`error.${$page.status}`, { default: $t('error.default') })}

- - diff --git a/src/routes/(website)/+layout.server.ts b/src/routes/(website)/+layout.server.ts deleted file mode 100644 index 9f4c8fc1..00000000 --- a/src/routes/(website)/+layout.server.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { LayoutServerLoad } from './$types' -import { defaultLocale, loadTranslations, locales, translations } from '$lib/translations' - -export const load = (async ({ url, cookies, request, locals }) => { - const { pathname } = url - - let locale = (cookies.get('lang') || '').toLowerCase() - - if (!locale) { - locale = `${`${request.headers.get('accept-language')}`.match(/[a-z]+(?=[\-_,;])/i)}`.toLowerCase() - } - - const supportedLocales = locales.get().map((l) => l.toLowerCase()) - - if (!supportedLocales.includes(locale)) { - locale = defaultLocale - } - - await loadTranslations(locale, pathname) - - return { - profile: locals.profile, - i18n: { locale, route: pathname }, - translations: translations.get(), - } -}) satisfies LayoutServerLoad diff --git a/src/routes/(website)/+layout.ts b/src/routes/(website)/+layout.ts deleted file mode 100644 index b54d46a9..00000000 --- a/src/routes/(website)/+layout.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { addTranslations, setLocale, setRoute } from '$lib/translations' - -export async function load({ data }) { - const { i18n, translations } = data - const { locale, route } = i18n - - addTranslations(translations) - - await setRoute(route) - await setLocale(locale) - - return i18n -} diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte new file mode 100644 index 00000000..08f9707f --- /dev/null +++ b/src/routes/+error.svelte @@ -0,0 +1,16 @@ + + +
+

{t?.error.title} ({$page.status})

+

{t?.error[$page.status]}

+
+ + diff --git a/src/routes/(game)/play/+layout.server.ts b/src/routes/+layout.server.ts similarity index 58% rename from src/routes/(game)/play/+layout.server.ts rename to src/routes/+layout.server.ts index e4f6fc8d..b41e33cd 100644 --- a/src/routes/(game)/play/+layout.server.ts +++ b/src/routes/+layout.server.ts @@ -1,7 +1,12 @@ import type { LayoutServerLoad } from './$types' +import { dictionary } from '$lib/translations' export const load = (async ({ locals }) => { + const locale = locals.locale + return { profile: locals.profile, + locale, + t: dictionary(locale), } }) satisfies LayoutServerLoad diff --git a/src/routes/(game)/play/+layout.svelte b/src/routes/[lang]/(game)/play/+layout.svelte similarity index 100% rename from src/routes/(game)/play/+layout.svelte rename to src/routes/[lang]/(game)/play/+layout.svelte diff --git a/src/routes/(game)/play/+page.svelte b/src/routes/[lang]/(game)/play/+page.svelte similarity index 100% rename from src/routes/(game)/play/+page.svelte rename to src/routes/[lang]/(game)/play/+page.svelte diff --git a/src/routes/(game)/play/GameChunkInfo.svelte b/src/routes/[lang]/(game)/play/GameChunkInfo.svelte similarity index 100% rename from src/routes/(game)/play/GameChunkInfo.svelte rename to src/routes/[lang]/(game)/play/GameChunkInfo.svelte diff --git a/src/routes/(game)/play/GameCommand.svelte b/src/routes/[lang]/(game)/play/GameCommand.svelte similarity index 100% rename from src/routes/(game)/play/GameCommand.svelte rename to src/routes/[lang]/(game)/play/GameCommand.svelte diff --git a/src/routes/(game)/play/GameEventCard.svelte b/src/routes/[lang]/(game)/play/GameEventCard.svelte similarity index 100% rename from src/routes/(game)/play/GameEventCard.svelte rename to src/routes/[lang]/(game)/play/GameEventCard.svelte diff --git a/src/routes/(game)/play/GameEventTimer.svelte b/src/routes/[lang]/(game)/play/GameEventTimer.svelte similarity index 100% rename from src/routes/(game)/play/GameEventTimer.svelte rename to src/routes/[lang]/(game)/play/GameEventTimer.svelte diff --git a/src/routes/(game)/play/GameEvents.svelte b/src/routes/[lang]/(game)/play/GameEvents.svelte similarity index 100% rename from src/routes/(game)/play/GameEvents.svelte rename to src/routes/[lang]/(game)/play/GameEvents.svelte diff --git a/src/routes/(game)/play/GameHeader.svelte b/src/routes/[lang]/(game)/play/GameHeader.svelte similarity index 100% rename from src/routes/(game)/play/GameHeader.svelte rename to src/routes/[lang]/(game)/play/GameHeader.svelte diff --git a/src/routes/(game)/play/GameInterface.svelte b/src/routes/[lang]/(game)/play/GameInterface.svelte similarity index 100% rename from src/routes/(game)/play/GameInterface.svelte rename to src/routes/[lang]/(game)/play/GameInterface.svelte diff --git a/src/routes/(game)/play/GameItem.svelte b/src/routes/[lang]/(game)/play/GameItem.svelte similarity index 100% rename from src/routes/(game)/play/GameItem.svelte rename to src/routes/[lang]/(game)/play/GameItem.svelte diff --git a/src/routes/(game)/play/GameLoader.svelte b/src/routes/[lang]/(game)/play/GameLoader.svelte similarity index 100% rename from src/routes/(game)/play/GameLoader.svelte rename to src/routes/[lang]/(game)/play/GameLoader.svelte diff --git a/src/routes/(game)/play/GameLocation.svelte b/src/routes/[lang]/(game)/play/GameLocation.svelte similarity index 100% rename from src/routes/(game)/play/GameLocation.svelte rename to src/routes/[lang]/(game)/play/GameLocation.svelte diff --git a/src/routes/(game)/play/GamePlayerCard.svelte b/src/routes/[lang]/(game)/play/GamePlayerCard.svelte similarity index 100% rename from src/routes/(game)/play/GamePlayerCard.svelte rename to src/routes/[lang]/(game)/play/GamePlayerCard.svelte diff --git a/src/routes/(game)/play/GamePlayersGroup.svelte b/src/routes/[lang]/(game)/play/GamePlayersGroup.svelte similarity index 100% rename from src/routes/(game)/play/GamePlayersGroup.svelte rename to src/routes/[lang]/(game)/play/GamePlayersGroup.svelte diff --git a/src/routes/(game)/play/GamePollProgress.svelte b/src/routes/[lang]/(game)/play/GamePollProgress.svelte similarity index 100% rename from src/routes/(game)/play/GamePollProgress.svelte rename to src/routes/[lang]/(game)/play/GamePollProgress.svelte diff --git a/src/routes/(game)/play/GameQuestConditions.svelte b/src/routes/[lang]/(game)/play/GameQuestConditions.svelte similarity index 100% rename from src/routes/(game)/play/GameQuestConditions.svelte rename to src/routes/[lang]/(game)/play/GameQuestConditions.svelte diff --git a/src/routes/(game)/play/GameQuestTask.svelte b/src/routes/[lang]/(game)/play/GameQuestTask.svelte similarity index 100% rename from src/routes/(game)/play/GameQuestTask.svelte rename to src/routes/[lang]/(game)/play/GameQuestTask.svelte diff --git a/src/routes/(game)/play/GameQuestTaskProgress.svelte b/src/routes/[lang]/(game)/play/GameQuestTaskProgress.svelte similarity index 100% rename from src/routes/(game)/play/GameQuestTaskProgress.svelte rename to src/routes/[lang]/(game)/play/GameQuestTaskProgress.svelte diff --git a/src/routes/(game)/play/GameRouteInfo.svelte b/src/routes/[lang]/(game)/play/GameRouteInfo.svelte similarity index 100% rename from src/routes/(game)/play/GameRouteInfo.svelte rename to src/routes/[lang]/(game)/play/GameRouteInfo.svelte diff --git a/src/routes/(game)/play/GameRouteItem.svelte b/src/routes/[lang]/(game)/play/GameRouteItem.svelte similarity index 100% rename from src/routes/(game)/play/GameRouteItem.svelte rename to src/routes/[lang]/(game)/play/GameRouteItem.svelte diff --git a/src/routes/(game)/play/GameTopPlayerCard.svelte b/src/routes/[lang]/(game)/play/GameTopPlayerCard.svelte similarity index 100% rename from src/routes/(game)/play/GameTopPlayerCard.svelte rename to src/routes/[lang]/(game)/play/GameTopPlayerCard.svelte diff --git a/src/routes/(game)/play/GameTopPlayers.svelte b/src/routes/[lang]/(game)/play/GameTopPlayers.svelte similarity index 100% rename from src/routes/(game)/play/GameTopPlayers.svelte rename to src/routes/[lang]/(game)/play/GameTopPlayers.svelte diff --git a/src/routes/(game)/play/GameTradeOffer.svelte b/src/routes/[lang]/(game)/play/GameTradeOffer.svelte similarity index 100% rename from src/routes/(game)/play/GameTradeOffer.svelte rename to src/routes/[lang]/(game)/play/GameTradeOffer.svelte diff --git a/src/routes/(game)/play/GameUnit.svelte b/src/routes/[lang]/(game)/play/GameUnit.svelte similarity index 100% rename from src/routes/(game)/play/GameUnit.svelte rename to src/routes/[lang]/(game)/play/GameUnit.svelte diff --git a/src/routes/(game)/play/GameWagonInfo.svelte b/src/routes/[lang]/(game)/play/GameWagonInfo.svelte similarity index 100% rename from src/routes/(game)/play/GameWagonInfo.svelte rename to src/routes/[lang]/(game)/play/GameWagonInfo.svelte diff --git a/src/routes/(game)/play/GameWarehouseInfo.svelte b/src/routes/[lang]/(game)/play/GameWarehouseInfo.svelte similarity index 100% rename from src/routes/(game)/play/GameWarehouseInfo.svelte rename to src/routes/[lang]/(game)/play/GameWarehouseInfo.svelte diff --git a/src/routes/(game)/play/__tests__/GameEvents.spec.ts b/src/routes/[lang]/(game)/play/__tests__/GameEvents.spec.ts similarity index 100% rename from src/routes/(game)/play/__tests__/GameEvents.spec.ts rename to src/routes/[lang]/(game)/play/__tests__/GameEvents.spec.ts diff --git a/src/routes/(website)/+layout.svelte b/src/routes/[lang]/(website)/+layout.svelte similarity index 100% rename from src/routes/(website)/+layout.svelte rename to src/routes/[lang]/(website)/+layout.svelte diff --git a/src/routes/(website)/+page.server.ts b/src/routes/[lang]/(website)/+page.server.ts similarity index 100% rename from src/routes/(website)/+page.server.ts rename to src/routes/[lang]/(website)/+page.server.ts diff --git a/src/routes/(website)/+page.svelte b/src/routes/[lang]/(website)/+page.svelte similarity index 100% rename from src/routes/(website)/+page.svelte rename to src/routes/[lang]/(website)/+page.svelte diff --git a/src/routes/(website)/about/+page.svelte b/src/routes/[lang]/(website)/about/+page.svelte similarity index 100% rename from src/routes/(website)/about/+page.svelte rename to src/routes/[lang]/(website)/about/+page.svelte diff --git a/src/routes/(website)/auth/profile/+server.ts b/src/routes/[lang]/(website)/auth/profile/+server.ts similarity index 100% rename from src/routes/(website)/auth/profile/+server.ts rename to src/routes/[lang]/(website)/auth/profile/+server.ts diff --git a/src/routes/(website)/auth/sign-in/+page.svelte b/src/routes/[lang]/(website)/auth/sign-in/+page.svelte similarity index 100% rename from src/routes/(website)/auth/sign-in/+page.svelte rename to src/routes/[lang]/(website)/auth/sign-in/+page.svelte diff --git a/src/routes/(website)/auth/sign-in/+server.ts b/src/routes/[lang]/(website)/auth/sign-in/+server.ts similarity index 100% rename from src/routes/(website)/auth/sign-in/+server.ts rename to src/routes/[lang]/(website)/auth/sign-in/+server.ts diff --git a/src/routes/(website)/character/+page.server.ts b/src/routes/[lang]/(website)/character/+page.server.ts similarity index 100% rename from src/routes/(website)/character/+page.server.ts rename to src/routes/[lang]/(website)/character/+page.server.ts diff --git a/src/routes/(website)/character/+page.svelte b/src/routes/[lang]/(website)/character/+page.svelte similarity index 100% rename from src/routes/(website)/character/+page.svelte rename to src/routes/[lang]/(website)/character/+page.svelte diff --git a/src/routes/(website)/character/[slug]/+page.server.ts b/src/routes/[lang]/(website)/character/[slug]/+page.server.ts similarity index 100% rename from src/routes/(website)/character/[slug]/+page.server.ts rename to src/routes/[lang]/(website)/character/[slug]/+page.server.ts diff --git a/src/routes/(website)/character/[slug]/+page.svelte b/src/routes/[lang]/(website)/character/[slug]/+page.svelte similarity index 100% rename from src/routes/(website)/character/[slug]/+page.svelte rename to src/routes/[lang]/(website)/character/[slug]/+page.svelte diff --git a/src/routes/(website)/p/+page.server.ts b/src/routes/[lang]/(website)/p/+page.server.ts similarity index 100% rename from src/routes/(website)/p/+page.server.ts rename to src/routes/[lang]/(website)/p/+page.server.ts diff --git a/src/routes/(website)/p/[slug]/+page.server.ts b/src/routes/[lang]/(website)/p/[slug]/+page.server.ts similarity index 100% rename from src/routes/(website)/p/[slug]/+page.server.ts rename to src/routes/[lang]/(website)/p/[slug]/+page.server.ts diff --git a/src/routes/(website)/p/[slug]/+page.svelte b/src/routes/[lang]/(website)/p/[slug]/+page.svelte similarity index 100% rename from src/routes/(website)/p/[slug]/+page.svelte rename to src/routes/[lang]/(website)/p/[slug]/+page.svelte