19 implement i18n (#29)

* init paraglide

* change export

* shared session check

* message param

* format

* check user is present

A session can exist without a user, if the user was recently deleted

* wtf

* lol bad redirect code
This commit is contained in:
Baobeld 2024-12-20 11:41:01 -05:00 committed by GitHub
parent 264f6d775d
commit 8969e2b8aa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 84 additions and 49 deletions

View file

@ -44,6 +44,7 @@ bun build
- https://svelte.dev/docs/kit/introduction
- https://zod.dev/
- https://day.js.org/
- https://inlang.com/c/svelte
### Frontend

BIN
bun.lockb

Binary file not shown.

4
messages/en.json Normal file
View file

@ -0,0 +1,4 @@
{
"$schema": "https://inlang.com/schema/inlang-message-format",
"greeting": "Hello {name}!"
}

View file

@ -38,7 +38,7 @@
"@storybook/test": "^8.4.7",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.9.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@types/bun": "^1.1.14",
"autoprefixer": "^10.4.20",
"daisyui": "^4.12.22",
@ -61,6 +61,7 @@
},
"dependencies": {
"@flaticon/flaticon-uicons": "^3.3.1",
"@inlang/paraglide-sveltekit": "^0.15.0",
"@lucia-auth/adapter-prisma": "^4.0.1",
"@pothos/core": "^4.3.0",
"@pothos/plugin-prisma": "^4.4.0",

1
project.inlang/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
cache

View file

@ -0,0 +1 @@
309efd37fde7fcb319e88bd3fa47f3ff10e868625e8bd1771591d658e463f28f

View file

@ -0,0 +1,17 @@
{
"$schema": "https://inlang.com/schema/project-settings",
"modules": [
"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@1/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-identical-pattern@1/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@1/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-without-source@1/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-valid-js-identifier@1/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@2/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@0/dist/index.js"
],
"plugin.inlang.messageFormat": {
"pathPattern": "./messages/{languageTag}.json"
},
"sourceLanguageTag": "en",
"languageTags": ["en"]
}

View file

@ -1,13 +1,15 @@
<script lang="ts">
import { messages } from '$lib/i18n';
let { title, username }: { title: string; username: string } = $props();
let greeting = $derived(`Welcome ${username}!`);
let message = $derived(messages.greeting({ name: username }));
</script>
<header class="navbar justify-between bg-base-200 px-4">
<h2 class="prose prose-xl">Hestia</h2>
<h1 class="prose prose-2xl">{title}</h1>
<p class="prose prose-lg">{greeting}</p>
<p class="prose prose-lg">{message}</p>
</header>
<style>

4
src/lib/i18n/index.ts Normal file
View file

@ -0,0 +1,4 @@
import * as runtime from '$lib/paraglide/runtime';
import { createI18n } from '@inlang/paraglide-sveltekit';
export * as messages from '$lib/paraglide/messages';
export const i18n = createI18n(runtime);

View file

@ -0,0 +1,22 @@
import { redirect, type ServerLoadEvent } from '@sveltejs/kit';
import dayjs from 'dayjs';
import { prisma } from '../prisma';
export async function validateSession(event: ServerLoadEvent) {
const sessionId = event.cookies.get('auth_session');
if (!sessionId) {
redirect(302, '/login');
}
const session = await prisma.session.findUnique({
where: { id: sessionId },
include: { user: true },
});
if (!session || !session.user) {
redirect(302, '/login');
}
const expiry = session.expiresAt;
if (dayjs(expiry).isBefore(dayjs())) {
redirect(302, '/login');
}
return session;
}

View file

@ -1,4 +1,6 @@
<script lang="ts">
import { i18n } from '$lib/i18n';
import { ParaglideJS } from '@inlang/paraglide-sveltekit';
import '../app.css';
let { children } = $props();
</script>
@ -7,8 +9,10 @@
{@render children()}
</div>
<ParaglideJS {i18n}>
<style>
.layout {
@apply h-screen w-screen bg-base-100;
}
</style>
</ParaglideJS>

View file

@ -1,18 +1,5 @@
import { prisma } from '$lib/server/prisma';
import { redirect } from '@sveltejs/kit';
import { validateSession } from '$lib/server/auth';
export async function load(event) {
const sessionId = event.cookies.get('auth_session');
if (!sessionId) {
redirect(303, '/login');
}
const user = await prisma.session.findUnique({
where: {
id: sessionId,
},
});
if (!user) {
redirect(300, '/login');
}
return {};
await validateSession(event);
}

View file

@ -1,25 +1,9 @@
import { prisma } from '$lib/server/prisma';
import { redirect } from '@sveltejs/kit';
import dayjs from 'dayjs';
import { validateSession } from '$lib/server/auth';
export async function load(event) {
const sessionId = event.cookies.get('auth_session');
if (!sessionId) {
redirect(300, '/login');
}
const session = await prisma.session.findUnique({
where: { id: sessionId },
include: { user: true },
});
if (!session) {
redirect(300, '/login');
}
const expiry = session.expiresAt;
if (dayjs(expiry).isBefore(dayjs())) {
redirect(300, '/login');
}
const { password: _, ...rest } = session.user;
const {
user: { password: _, ...rest },
} = await validateSession(event);
return {
user: rest,
};

View file

@ -1,8 +1,15 @@
import { defineConfig } from 'vitest/config';
import { paraglide } from '@inlang/paraglide-sveltekit/vite';
import { sveltekit } from '@sveltejs/kit/vite';
export default defineConfig({
plugins: [sveltekit()],
plugins: [
sveltekit(),
paraglide({
project: './project.inlang',
outdir: './src/lib/paraglide',
}),
],
test: {
include: ['src/**/*.{test,spec}.{js,ts}'],