add: internationalization translation to danish
This commit is contained in:
@@ -1,18 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { ThemeToggle } from '$lib/components/ui/theme-toggle';
|
||||
import { LanguageToggle } from '$lib/components/ui/language-toggle';
|
||||
import { signOut } from '@auth/sveltekit/client';
|
||||
import { languageStore } from '$lib/stores/language.svelte';
|
||||
|
||||
let { userName, userEmail }: { userName?: string | null; userEmail?: string | null } = $props();
|
||||
|
||||
const t = $derived(languageStore.t);
|
||||
</script>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold">Dashboard</h1>
|
||||
<p class="text-muted-foreground">Welcome back, {userName || userEmail}</p>
|
||||
<h1 class="text-3xl font-bold">{t.nav.dashboard}</h1>
|
||||
<p class="text-muted-foreground">{t.dashboard.welcomeBack}, {userName || userEmail}</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="flex items-center gap-1 sm:gap-2">
|
||||
<LanguageToggle />
|
||||
<ThemeToggle />
|
||||
<Button variant="outline" onclick={() => signOut({ callbackUrl: '/' })}>Sign Out</Button>
|
||||
<Button variant="outline" onclick={() => signOut({ callbackUrl: '/' })}>{t.auth.signOut}</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import ImageSelector from './ImageSelector.svelte';
|
||||
import ColorPicker from '$lib/components/ui/ColorPicker.svelte';
|
||||
import { enhance } from '$app/forms';
|
||||
import { languageStore } from '$lib/stores/language.svelte';
|
||||
|
||||
interface Props {
|
||||
onSuccess?: () => void;
|
||||
@@ -14,6 +15,8 @@
|
||||
|
||||
let { onSuccess }: Props = $props();
|
||||
|
||||
const t = $derived(languageStore.t);
|
||||
|
||||
const currencies = ['DKK', 'EUR', 'USD', 'SEK', 'NOK', 'GBP'];
|
||||
|
||||
let linkUrl = $state('');
|
||||
@@ -52,7 +55,7 @@
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Add New Item</CardTitle>
|
||||
<CardTitle>{t.form.addNewItem}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form
|
||||
@@ -68,12 +71,12 @@
|
||||
>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="space-y-2 md:col-span-2">
|
||||
<Label for="title">Item Name *</Label>
|
||||
<Label for="title">{t.form.itemName} *</Label>
|
||||
<Input id="title" name="title" required placeholder="e.g., Blue Headphones" />
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 md:col-span-2">
|
||||
<Label for="description">Description</Label>
|
||||
<Label for="description">{t.form.description}</Label>
|
||||
<Textarea
|
||||
id="description"
|
||||
name="description"
|
||||
@@ -83,7 +86,7 @@
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 md:col-span-2">
|
||||
<Label for="link">Link (URL)</Label>
|
||||
<Label for="link">{t.form.link}</Label>
|
||||
<Input
|
||||
id="link"
|
||||
name="link"
|
||||
@@ -95,7 +98,7 @@
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 md:col-span-2">
|
||||
<Label for="imageUrl">Image URL</Label>
|
||||
<Label for="imageUrl">{t.form.imageUrl}</Label>
|
||||
<Input
|
||||
id="imageUrl"
|
||||
name="imageUrl"
|
||||
@@ -108,12 +111,12 @@
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="price">Price</Label>
|
||||
<Label for="price">{t.form.price}</Label>
|
||||
<Input id="price" name="price" type="number" step="0.01" placeholder="0.00" />
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 md:col-span-2">
|
||||
<Label for="currency">Currency</Label>
|
||||
<Label for="currency">{t.form.currency}</Label>
|
||||
<select
|
||||
id="currency"
|
||||
name="currency"
|
||||
@@ -127,14 +130,14 @@
|
||||
|
||||
<div class="md:col-span-2">
|
||||
<div class="flex items-center justify-between">
|
||||
<Label for="color">Card Color (optional)</Label>
|
||||
<Label for="color">{t.form.cardColor}</Label>
|
||||
<ColorPicker bind:color={color} />
|
||||
</div>
|
||||
<input type="hidden" name="color" value={color || ''} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button type="submit" class="w-full md:w-auto">Add Item</Button>
|
||||
<Button type="submit" class="w-full md:w-auto">{t.wishlist.addItem}</Button>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import ColorPicker from '$lib/components/ui/ColorPicker.svelte';
|
||||
import { enhance } from '$app/forms';
|
||||
import type { Item } from '$lib/server/schema';
|
||||
import { languageStore } from '$lib/stores/language.svelte';
|
||||
|
||||
interface Props {
|
||||
item: Item;
|
||||
@@ -21,6 +22,8 @@
|
||||
|
||||
let { item, onSuccess, onCancel, onColorChange, currentPosition = 1, totalItems = 1, onPositionChange }: Props = $props();
|
||||
|
||||
const t = $derived(languageStore.t);
|
||||
|
||||
const currencies = ['DKK', 'EUR', 'USD', 'SEK', 'NOK', 'GBP'];
|
||||
|
||||
let linkUrl = $state(item.link || '');
|
||||
@@ -59,7 +62,7 @@
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Edit Item</CardTitle>
|
||||
<CardTitle>{t.wishlist.editItem}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form
|
||||
@@ -77,12 +80,12 @@
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="space-y-2 md:col-span-2">
|
||||
<Label for="title">Item Name *</Label>
|
||||
<Label for="title">{t.form.itemName} *</Label>
|
||||
<Input id="title" name="title" required value={item.title} placeholder="e.g., Blue Headphones" />
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 md:col-span-2">
|
||||
<Label for="description">Description</Label>
|
||||
<Label for="description">{t.form.description}</Label>
|
||||
<Textarea
|
||||
id="description"
|
||||
name="description"
|
||||
@@ -93,7 +96,7 @@
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 md:col-span-2">
|
||||
<Label for="link">Link (URL)</Label>
|
||||
<Label for="link">{t.form.link}</Label>
|
||||
<Input
|
||||
id="link"
|
||||
name="link"
|
||||
@@ -105,7 +108,7 @@
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 md:col-span-2">
|
||||
<Label for="imageUrl">Image URL</Label>
|
||||
<Label for="imageUrl">{t.form.imageUrl}</Label>
|
||||
<Input
|
||||
id="imageUrl"
|
||||
name="imageUrl"
|
||||
@@ -118,12 +121,12 @@
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="price">Price</Label>
|
||||
<Label for="price">{t.form.price}</Label>
|
||||
<Input id="price" name="price" type="number" step="0.01" value={item.price || ''} placeholder="0.00" />
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 md:col-span-2">
|
||||
<Label for="currency">Currency</Label>
|
||||
<Label for="currency">{t.form.currency}</Label>
|
||||
<select
|
||||
id="currency"
|
||||
name="currency"
|
||||
@@ -137,14 +140,14 @@
|
||||
|
||||
<div class="md:col-span-2">
|
||||
<div class="flex items-center justify-between">
|
||||
<Label for="color">Card Color (optional)</Label>
|
||||
<Label for="color">{t.form.cardColor}</Label>
|
||||
<ColorPicker bind:color={color} onchange={() => onColorChange?.(item.id, color || '')} />
|
||||
</div>
|
||||
<input type="hidden" name="color" value={color || ''} />
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 md:col-span-2">
|
||||
<Label for="position">Position in List</Label>
|
||||
<Label for="position">{t.form.position}</Label>
|
||||
<Input
|
||||
id="position"
|
||||
type="number"
|
||||
@@ -166,9 +169,9 @@
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<Button type="submit" class="flex-1 md:flex-none">Save Changes</Button>
|
||||
<Button type="submit" class="flex-1 md:flex-none">{t.form.saveChanges}</Button>
|
||||
{#if onCancel}
|
||||
<Button type="button" variant="outline" class="flex-1 md:flex-none" onclick={onCancel}>Cancel</Button>
|
||||
<Button type="button" variant="outline" class="flex-1 md:flex-none" onclick={onCancel}>{t.form.cancel}</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import type { Item } from "$lib/server/schema";
|
||||
import { enhance } from "$app/forms";
|
||||
import { flip } from "svelte/animate";
|
||||
import { languageStore } from '$lib/stores/language.svelte';
|
||||
|
||||
let {
|
||||
items = $bindable([]),
|
||||
@@ -18,6 +19,8 @@
|
||||
onStartEditing: (item: Item) => void;
|
||||
onReorder: (items: Item[]) => Promise<void>;
|
||||
} = $props();
|
||||
|
||||
const t = $derived(languageStore.t);
|
||||
</script>
|
||||
|
||||
<div class="space-y-4">
|
||||
@@ -33,7 +36,7 @@
|
||||
size="sm"
|
||||
onclick={() => onStartEditing(item)}
|
||||
>
|
||||
Edit
|
||||
{t.wishlist.edit}
|
||||
</Button>
|
||||
{#if rearranging}
|
||||
<form
|
||||
@@ -51,7 +54,7 @@
|
||||
variant="destructive"
|
||||
size="sm"
|
||||
>
|
||||
Delete
|
||||
{t.form.delete}
|
||||
</Button>
|
||||
</form>
|
||||
{/if}
|
||||
@@ -64,7 +67,7 @@
|
||||
<Card>
|
||||
<CardContent class="p-12">
|
||||
<EmptyState
|
||||
message="No items yet. Click 'Add Item' to get started!"
|
||||
message={t.wishlist.noItems + ". " + t.wishlist.addFirstItem + "!"}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { Input } from '$lib/components/ui/input';
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
import { Card, CardContent } from '$lib/components/ui/card';
|
||||
import { languageStore } from '$lib/stores/language.svelte';
|
||||
|
||||
interface Props {
|
||||
publicUrl: string;
|
||||
@@ -11,6 +12,8 @@
|
||||
|
||||
let { publicUrl, ownerUrl }: Props = $props();
|
||||
|
||||
const t = $derived(languageStore.t);
|
||||
|
||||
let copiedPublic = $state(false);
|
||||
let copiedOwner = $state(false);
|
||||
|
||||
@@ -34,22 +37,22 @@
|
||||
<Card>
|
||||
<CardContent class="space-y-4 pt-6">
|
||||
<div class="space-y-2">
|
||||
<Label>Share with friends (view only)</Label>
|
||||
<Label>{t.wishlist.shareViewOnly}</Label>
|
||||
<div class="flex gap-2">
|
||||
<Input readonly value={publicLink} class="font-mono text-sm" />
|
||||
<Button variant="outline" onclick={() => copyToClipboard(publicLink, 'public')}>
|
||||
{copiedPublic ? 'Copied!' : 'Copy'}
|
||||
{copiedPublic ? t.wishlist.copied : t.wishlist.copy}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if ownerLink}
|
||||
<div class="space-y-2">
|
||||
<Label>Your edit link (keep this private!)</Label>
|
||||
<Label>{t.wishlist.shareEditLink}</Label>
|
||||
<div class="flex gap-2">
|
||||
<Input readonly value={ownerLink} class="font-mono text-sm" />
|
||||
<Button variant="outline" onclick={() => copyToClipboard(ownerLink, 'owner')}>
|
||||
{copiedOwner ? 'Copied!' : 'Copy'}
|
||||
{copiedOwner ? t.wishlist.copied : t.wishlist.copy}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Button } from "$lib/components/ui/button";
|
||||
import { Lock, LockOpen } from "lucide-svelte";
|
||||
import { enhance } from "$app/forms";
|
||||
import { languageStore } from '$lib/stores/language.svelte';
|
||||
|
||||
let {
|
||||
rearranging = $bindable(false),
|
||||
@@ -13,9 +12,7 @@
|
||||
onToggleAddForm: () => void;
|
||||
} = $props();
|
||||
|
||||
function toggleRearranging() {
|
||||
rearranging = !rearranging;
|
||||
}
|
||||
const t = $derived(languageStore.t);
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
@@ -23,6 +20,6 @@
|
||||
onclick={onToggleAddForm}
|
||||
class="w-full md:w-auto"
|
||||
>
|
||||
{showAddForm ? "Cancel" : "+ Add Item"}
|
||||
{showAddForm ? t.form.cancel : t.wishlist.addWish}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { Pencil, Check, X } from "lucide-svelte";
|
||||
import ColorPicker from "$lib/components/ui/ColorPicker.svelte";
|
||||
import type { Wishlist } from "$lib/server/schema";
|
||||
import { languageStore } from '$lib/stores/language.svelte';
|
||||
|
||||
let {
|
||||
wishlist,
|
||||
@@ -21,6 +22,8 @@
|
||||
onEndDateUpdate: (endDate: string | null) => void;
|
||||
} = $props();
|
||||
|
||||
const t = $derived(languageStore.t);
|
||||
|
||||
let editingTitle = $state(false);
|
||||
let editingDescription = $state(false);
|
||||
let wishlistTitle = $state(wishlist.title);
|
||||
@@ -123,7 +126,7 @@
|
||||
<!-- Description -->
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<Label for="wishlist-description">Description (optional)</Label>
|
||||
<Label for="wishlist-description">{t.form.descriptionOptional}</Label>
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
@@ -159,14 +162,14 @@
|
||||
/>
|
||||
{:else}
|
||||
<div class="w-full py-2 px-3 rounded-md border border-input bg-transparent text-sm min-h-[80px]">
|
||||
{wishlistDescription || "No description"}
|
||||
{wishlistDescription || t.form.noDescription}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- End Date -->
|
||||
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 sm:gap-4">
|
||||
<Label for="wishlist-end-date">End Date (optional)</Label>
|
||||
<Label for="wishlist-end-date">{t.form.endDateOptional}</Label>
|
||||
<div class="flex items-center gap-2">
|
||||
{#if wishlistEndDate}
|
||||
<button
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import { GripVertical, ExternalLink } from "lucide-svelte";
|
||||
import { getCardStyle } from '$lib/utils/colors';
|
||||
import { Button } from "$lib/components/ui/button";
|
||||
import { languageStore } from '$lib/stores/language.svelte';
|
||||
|
||||
interface Props {
|
||||
item: Item;
|
||||
@@ -19,6 +20,8 @@
|
||||
showDragHandle = false,
|
||||
}: Props = $props();
|
||||
|
||||
const t = $derived(languageStore.t);
|
||||
|
||||
const currencySymbols: Record<string, string> = {
|
||||
DKK: "kr",
|
||||
EUR: "€",
|
||||
@@ -101,7 +104,7 @@
|
||||
class="gap-1.5"
|
||||
>
|
||||
<ExternalLink class="w-4 h-4" />
|
||||
View Product
|
||||
{t.wishlist.viewProduct}
|
||||
</Button>
|
||||
{/if}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user