Change the way to load i18n (go throw cookie)

This commit is contained in:
Restray 2022-04-02 20:25:24 +02:00
parent 943300509b
commit a3241516cb
No known key found for this signature in database
GPG Key ID: 67C6DEF95A4DC812
11 changed files with 142 additions and 118 deletions

View File

@ -1,7 +1,8 @@
{
"i18n-ally.localesPaths": ["locales"],
"i18n-ally.localesPaths": ["static/locales"],
"i18n-ally.keystyle": "nested",
"i18n-ally.extract.ignoredByFiles": {
"src\\routes\\__layout.svelte": ["Coolify", "coolLabs logo"]
}
},
"i18n-ally.sourceLanguage": "fr"
}

View File

@ -51,9 +51,9 @@
"prisma": "3.11.1",
"svelte": "3.46.4",
"svelte-check": "2.4.6",
"svelte-i18n": "^3.3.13",
"svelte-preprocess": "4.10.4",
"svelte-select": "^4.4.7",
"sveltekit-i18n": "^2.1.2",
"tailwindcss": "3.0.23",
"ts-node": "10.7.0",
"tslib": "2.3.1",

View File

@ -46,10 +46,10 @@ specifiers:
prisma: 3.11.1
svelte: 3.46.4
svelte-check: 2.4.6
svelte-i18n: ^3.3.13
svelte-kit-cookie-session: 2.1.2
svelte-preprocess: 4.10.4
svelte-select: ^4.4.7
sveltekit-i18n: ^2.1.2
tailwindcss: 3.0.23
tailwindcss-scrollbar: ^0.1.0
ts-node: 10.7.0
@ -108,9 +108,9 @@ devDependencies:
prisma: 3.11.1
svelte: 3.46.4
svelte-check: 2.4.6_postcss@8.4.12+svelte@3.46.4
svelte-i18n: 3.3.13_svelte@3.46.4
svelte-preprocess: 4.10.4_296873641a0ad9f42fe92172d27bcedd
svelte-select: 4.4.7
sveltekit-i18n: 2.1.2_svelte@3.46.4
tailwindcss: 3.0.23_b89136460714832cdda11d1e9d57d1ff
ts-node: 10.7.0_ee885bc7281b682b6adbed6ae09ee090
tslib: 2.3.1
@ -184,55 +184,6 @@ packages:
- supports-color
dev: true
/@formatjs/ecma402-abstract/1.11.4:
resolution:
{
integrity: sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==
}
dependencies:
'@formatjs/intl-localematcher': 0.2.25
tslib: 2.3.1
dev: true
/@formatjs/fast-memoize/1.2.1:
resolution:
{
integrity: sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==
}
dependencies:
tslib: 2.3.1
dev: true
/@formatjs/icu-messageformat-parser/2.0.19:
resolution:
{
integrity: sha512-8HsLm9YLyVVIDMyBJb7wmve2wGd461cUwJ470eUog5YH5ZsF4p5lgvaJ+oGKxz1mrSMNNdDHU9v/NDsS+z+ilg==
}
dependencies:
'@formatjs/ecma402-abstract': 1.11.4
'@formatjs/icu-skeleton-parser': 1.3.6
tslib: 2.3.1
dev: true
/@formatjs/icu-skeleton-parser/1.3.6:
resolution:
{
integrity: sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==
}
dependencies:
'@formatjs/ecma402-abstract': 1.11.4
tslib: 2.3.1
dev: true
/@formatjs/intl-localematcher/0.2.25:
resolution:
{
integrity: sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==
}
dependencies:
tslib: 2.3.1
dev: true
/@humanwhocodes/config-array/0.5.0:
resolution:
{
@ -495,6 +446,26 @@ packages:
- supports-color
dev: true
/@sveltekit-i18n/base/1.1.1_svelte@3.46.4:
resolution:
{
integrity: sha512-J/sMU0OwS3dCLOuilHMBqu8vZHuuXiNV9vFJx8Nb4/b5BlR/KCZ4bCXI8wZR02GHeCOYKZxWus07CM1scxa/jw==
}
peerDependencies:
svelte: ^3.x
dependencies:
svelte: 3.46.4
optionalDependencies:
'@sveltekit-i18n/parser-default': 1.0.3
dev: true
/@sveltekit-i18n/parser-default/1.0.3:
resolution:
{
integrity: sha512-HheveklTjp3hxpYQhoHfyA6B4bQaUeSV5MQf2usIv/58UF2jY/YqhCAWj9bDBjufbuZc5pSz4BXvdX3WVT+viA==
}
dev: true
/@szmarczak/http-timer/5.0.1:
resolution:
{
@ -2254,14 +2225,6 @@ packages:
}
dev: true
/deepmerge/4.2.2:
resolution:
{
integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
}
engines: { node: '>=0.10.0' }
dev: true
/defer-to-connect/2.0.1:
resolution:
{
@ -3462,18 +3425,6 @@ packages:
integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
}
/intl-messageformat/9.12.0:
resolution:
{
integrity: sha512-5Q9j21JreB1G27/CqMYsA+pvJ19JjHyhiTSeUuvZK9BCDJGHtOLgpUUcGM+GLHiUuoVMKVeeX1smamiVHQrSKQ==
}
dependencies:
'@formatjs/ecma402-abstract': 1.11.4
'@formatjs/fast-memoize': 1.2.1
'@formatjs/icu-messageformat-parser': 2.0.19
tslib: 2.3.1
dev: true
/invariant/2.2.4:
resolution:
{
@ -5243,24 +5194,6 @@ packages:
svelte: 3.46.4
dev: true
/svelte-i18n/3.3.13_svelte@3.46.4:
resolution:
{
integrity: sha512-RQM+ys4+Y9ztH//tX22H1UL2cniLNmIR+N4xmYygV6QpQ6EyQvloZiENRew8XrVzfvJ8HaE8NU6/yurLkl7z3g==
}
engines: { node: '>= 11.15.0' }
hasBin: true
peerDependencies:
svelte: ^3.25.1
dependencies:
deepmerge: 4.2.2
estree-walker: 2.0.2
intl-messageformat: 9.12.0
sade: 1.7.4
svelte: 3.46.4
tiny-glob: 0.2.9
dev: true
/svelte-kit-cookie-session/2.1.2:
resolution:
{
@ -5338,6 +5271,19 @@ packages:
engines: { node: '>= 8' }
dev: true
/sveltekit-i18n/2.1.2_svelte@3.46.4:
resolution:
{
integrity: sha512-s5YxcbNd2EWNZaZR1A4Drt8s53E4fpUkN4XIWd3VRpw1pihZVWssqmBW1qkjQ6AB0kiu1Qwule+vt1HkbQOjrg==
}
peerDependencies:
svelte: ^3.x
dependencies:
'@sveltekit-i18n/base': 1.1.1_svelte@3.46.4
'@sveltekit-i18n/parser-default': 1.0.3
svelte: 3.46.4
dev: true
/table/6.7.2:
resolution:
{

View File

@ -6,6 +6,7 @@ import { getUserDetails, sentry } from '$lib/common';
import { version } from '$lib/common';
import cookie from 'cookie';
import { dev } from '$app/env';
import { locales } from '$lib/translations';
export const handle = handleSession(
{
@ -15,6 +16,29 @@ export const handle = handleSession(
},
async function ({ event, resolve }) {
let response;
const { url, request } = event;
const { pathname } = url;
// Get defined locales
const supportedLocales = locales.get();
let locale;
if (event.locals.cookies) {
locale = supportedLocales.find(
(l) => `${l}`.toLowerCase() === `${event.locals.cookies['lang']}`.toLowerCase()
);
}
if (!locale) {
locale = `${`${request.headers.get('accept-language')}`.match(
/[a-zA-Z]+?(?=-|_|,|;)/
)}`.toLowerCase();
// Set default locale if user preferred locale does not match
if (!supportedLocales.includes(locale)) locale = 'en';
}
try {
if (event.locals.cookies) {
if (event.locals.cookies['kit.session']) {
@ -24,7 +48,8 @@ export const handle = handleSession(
teamId,
permission,
isAdmin: permission === 'admin' || permission === 'owner',
expires: event.locals.session.data.expires
expires: event.locals.session.data.expires,
lang: locale
};
if (JSON.stringify(event.locals.session.data) !== JSON.stringify(newSession)) {
@ -34,12 +59,14 @@ export const handle = handleSession(
}
response = await resolve(event, {
ssr: !event.url.pathname.startsWith('/webhooks/success')
ssr: !event.url.pathname.startsWith('/webhooks/success'),
transformPage: ({ html }) => html.replace(/<html.*>/, `<html lang="${locale}">`)
});
} catch (error) {
console.log(error);
response = await resolve(event, {
ssr: !event.url.pathname.startsWith('/webhooks/success')
ssr: !event.url.pathname.startsWith('/webhooks/success'),
transformPage: ({ html }) => html.replace(/<html.*>/, `<html lang="${locale}">`)
});
response.headers.append(
'Set-Cookie',
@ -62,9 +89,18 @@ export const handle = handleSession(
expires: new Date('Thu, 01 Jan 1970 00:00:01 GMT')
})
);
} finally {
return response;
}
response.headers.append(
'Set-Cookie',
cookie.serialize('lang', locale, {
path: '/',
sameSite: 'strict',
maxAge: 30 * 24 * 60 * 60
})
);
return response;
}
);

4
src/lib/lang.json Normal file
View File

@ -0,0 +1,4 @@
{
"fr": "Français",
"en": "English"
}

28
src/lib/translations.ts Normal file
View File

@ -0,0 +1,28 @@
import i18n from 'sveltekit-i18n';
import lang from './lang.json';
/** @type {import('sveltekit-i18n').Config} */
const config = {
defaultLocale: 'en',
fallbackLocale: 'en',
translations: {
en: { lang },
fr: { lang }
},
loaders: [
{
locale: 'en',
key: '',
loader: async () => (await import('../../static/locales/en.json')).default
},
{
locale: 'fr',
key: '',
loader: async () => (await import('../../static/locales/fr.json')).default
}
]
};
export const { t, locale, locales, loading, loadTranslations } = new i18n(config);
loading.subscribe(($loading) => $loading && console.log('Loading translations...'));

View File

@ -12,7 +12,8 @@
</script>
<script>
import { _ } from 'svelte-i18n';
import { t } from '$lib/translations';
export let status;
export let error;
</script>
@ -21,8 +22,8 @@
<div class="pb-10 text-7xl font-bold">{status}</div>
<div class="text-3xl font-bold">Ooops you are lost! But don't be afraid!</div>
<div class="text-xl">
{$_('error.you_can_find_your_way_back')}
<a href="/" class="font-bold uppercase text-sky-400">{$_('error.here')}</a>
{$t('error.you_can_find_your_way_back')}
<a href="/" class="font-bold uppercase text-sky-400">{$t('error.here')}</a>
</div>
<div class="py-10 text-xs font-bold">
<pre

View File

@ -1,6 +1,7 @@
<script context="module" lang="ts">
import type { Load } from '@sveltejs/kit';
import { publicPaths } from '$lib/settings';
import { locale, loadTranslations } from '$lib/translations';
export const load: Load = async ({ fetch, url, session }) => {
if (!session.userId && !publicPaths.includes(url.pathname)) {
@ -15,6 +16,12 @@
const endpoint = `/teams.json`;
const res = await fetch(endpoint);
const { pathname } = url;
const defaultLocale = session.lang;
const initLocale = locale.get() || defaultLocale;
await loadTranslations(initLocale, pathname);
if (res.ok) {
return {
props: {
@ -23,6 +30,7 @@
}
};
}
return {};
};
</script>
@ -38,18 +46,8 @@
import { errorNotification } from '$lib/form';
import { asyncSleep } from '$lib/components/common';
import { del, get, post } from '$lib/api';
import { register, init, _, getLocaleFromNavigator } from 'svelte-i18n';
async function setup() {
register('en', () => import('../../static/locales/en.json'));
return await Promise.allSettled([
// TODO: add some more stuff you want to init ...
init({ initialLocale: getLocaleFromNavigator(), fallbackLocale: 'en' })
]);
}
const setupResult = setup();
import { browser } from '$app/env';
import { loading, t } from '$lib/translations';
let isUpdateAvailable = false;
@ -115,7 +113,7 @@
return window.location.reload();
} else {
await post(`/update.json`, { type: 'update', latestVersion });
toast.push(`${$_('layout.update_done')}<br><br>${$_('layout.wait_new_version_startup')}`);
toast.push(`${$t('layout.update_done')}<br><br>${$t('layout.wait_new_version_startup')}`);
let reachable = false;
let tries = 0;
do {
@ -129,7 +127,7 @@
if (reachable) break;
tries++;
} while (!reachable || tries < 120);
toast.push($_('layout.new_version'));
toast.push($t('layout.new_version'));
updateStatus.loading = false;
updateStatus.success = true;
await asyncSleep(3000);
@ -147,7 +145,7 @@
<title>Coolify</title>
</svelte:head>
{#await setupResult}
{#await loading}
Please wait...
{:then}
<SvelteToast options={{ intro: { y: -64 }, duration: 3000, pausable: true }} />
@ -336,7 +334,7 @@
{#if isUpdateAvailable}
<button
disabled={updateStatus.success === false}
title={$_('layout.update_available')}
title={$t('layout.update_available')}
on:click={update}
class="icons tooltip-right bg-gradient-to-r from-purple-500 via-pink-500 to-red-500 text-white duration-75 hover:scale-105"
>
@ -534,7 +532,7 @@
bind:value={selectedTeamId}
on:change={switchTeam}
>
<option value="" disabled selected>{$_('layout.switch_to_a_different_team')}</option>
<option value="" disabled selected>{$t('layout.switch_to_a_different_team')}</option>
{#each teams as team}
<option value={team.teamId}>{team.team.name} - {team.permission}</option>
{/each}

View File

@ -20,6 +20,8 @@
</script>
<script lang="ts">
import { t } from '$lib/translations';
export let applicationsCount: number;
export let sourcesCount: number;
export let destinationsCount: number;
@ -29,7 +31,7 @@
</script>
<div class="flex space-x-1 p-6 font-bold">
<div class="mr-4 text-2xl tracking-tight">Dashboard</div>
<div class="mr-4 text-2xl tracking-tight">{$t('index.dashboard')}</div>
</div>
<div class="mt-10 pb-12 tracking-tight sm:pb-16">

View File

@ -9,5 +9,8 @@
"error": {
"you_can_find_your_way_back": "You can find your way back",
"here": "here"
},
"index": {
"dashboard": "Dashboard"
}
}

5
static/locales/fr.json Normal file
View File

@ -0,0 +1,5 @@
{
"index": {
"dashboard": "Tableau de bord"
}
}