refactor: 🌐 Internationalize every string

This commit is contained in:
Jesse Wierzbinski 2024-12-07 22:17:22 +01:00
parent 8c3ddc2a28
commit 2ceee4827f
No known key found for this signature in database
41 changed files with 932 additions and 428 deletions

View file

@ -11,15 +11,15 @@
</template>
<script setup lang="ts">
import { useTitle } from "@vueuse/core";
import { Loader } from "lucide-vue-next";
import Note from "~/components/notes/note.vue";
import * as m from "~/paraglide/messages.js";
definePageMeta({
layout: "app",
breadcrumbs: [
{
text: "Note",
text: m.chunky_awake_mallard_grow(),
},
],
});
@ -57,7 +57,9 @@ watch(
useSeoMeta({
title: computed(() =>
note.value ? note.value.account.display_name : "Loading",
note.value
? note.value.account.display_name
: m.steep_sour_warthog_aim(),
),
description: computed(() => (note.value ? note.value.content : undefined)),
ogImage: computed(() =>

View file

@ -9,9 +9,9 @@
</TimelineScroller>
<Card v-else class="shadow-none bg-transparent border-none p-4">
<CardHeader class="text-center gap-y-4">
<CardTitle class="text-">Account not found.</CardTitle>
<CardTitle>{{ m.empty_awful_lark_dart() }}</CardTitle>
<CardDescription>
Check for typos or try again later.
{{ m.clean_even_mayfly_tap() }}
</CardDescription>
</CardHeader>
</Card>
@ -23,6 +23,7 @@ import { Loader } from "lucide-vue-next";
import AccountProfile from "~/components/profiles/profile.vue";
import AccountTimeline from "~/components/timelines/account.vue";
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
import * as m from "~/paraglide/messages.js";
const route = useRoute();
const username = (route.params.username as string).startsWith("@")
@ -33,7 +34,7 @@ definePageMeta({
layout: "app",
breadcrumbs: [
{
text: "Profile",
text: m.tough_nice_ox_drum(),
},
],
});
@ -43,10 +44,10 @@ const accountId = computed(() => account.value?.id ?? undefined);
useSeoMeta({
title: computed(() =>
account.value ? account.value.display_name : "Loading",
account.value ? account.value.display_name : m.steep_sour_warthog_aim(),
),
ogTitle: computed(() =>
account.value ? account.value.display_name : "Loading",
account.value ? account.value.display_name : m.steep_sour_warthog_aim(),
),
ogImage: computed(() => (account.value ? account.value.avatar : undefined)),
ogType: "profile",

View file

@ -9,19 +9,20 @@
<script setup lang="ts">
import Global from "~/components/timelines/global.vue";
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
import * as m from "~/paraglide/messages.js";
useHead({
title: "Global",
title: m.real_tame_moose_greet(),
});
definePageMeta({
layout: "app",
breadcrumbs: [
{
text: "Timelines",
text: m.steep_aqua_fox_harbor(),
},
{
text: "Global",
text: m.real_tame_moose_greet(),
href: "/global",
},
],

View file

@ -9,6 +9,7 @@
<script setup lang="ts">
import Home from "~/components/timelines/home.vue";
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
import * as m from "~/paraglide/messages.js";
useHead({
title: "Home",
@ -18,10 +19,10 @@ definePageMeta({
layout: "app",
breadcrumbs: [
{
text: "Timelines",
text: m.steep_aqua_fox_harbor(),
},
{
text: "Home",
text: m.bland_chunky_sparrow_propel(),
href: "/home",
},
],

View file

@ -12,24 +12,27 @@
import Home from "~/components/timelines/home.vue";
import Public from "~/components/timelines/public.vue";
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
import * as m from "~/paraglide/messages.js";
useHead({
title: identity.value ? "Home" : "Public",
title: identity.value
? m.bland_chunky_sparrow_propel()
: m.lost_trick_dog_grace(),
});
definePageMeta({
layout: "app",
breadcrumbs: [
{
text: "Timelines",
text: m.steep_aqua_fox_harbor(),
},
identity.value
? {
text: "Home",
text: m.bland_chunky_sparrow_propel(),
href: "/home",
}
: {
text: "Public",
text: m.lost_trick_dog_grace(),
href: "/public",
},
],

View file

@ -10,19 +10,20 @@
<script lang="ts" setup>
import Local from "~/components/timelines/local.vue";
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
import * as m from "~/paraglide/messages.js";
useHead({
title: "Local",
title: m.crazy_game_parrot_pave(),
});
definePageMeta({
layout: "app",
breadcrumbs: [
{
text: "Timelines",
text: m.steep_aqua_fox_harbor(),
},
{
text: "Local",
text: m.crazy_game_parrot_pave(),
href: "/local",
},
],

View file

@ -22,16 +22,17 @@
<script lang="ts" setup>
import Notifications from "~/components/timelines/notifications.vue";
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
import * as m from "~/paraglide/messages.js";
useHead({
title: "Notifications",
title: m.that_patchy_mare_snip(),
});
definePageMeta({
layout: "app",
breadcrumbs: [
{
text: "Notifications",
text: m.that_patchy_mare_snip(),
href: "/notifications",
},
],

View file

@ -4,10 +4,11 @@ import { AlertCircle, Loader } from "lucide-vue-next";
import UserAuthForm from "~/components/oauth/login.vue";
import { Alert, AlertDescription, AlertTitle } from "~/components/ui/alert";
import { Button } from "~/components/ui/button";
import * as m from "~/paraglide/messages.js";
import { NuxtLink } from "#components";
useHead({
title: "Sign In",
title: m.fuzzy_sea_moth_absorb(),
});
const host = new URL(useBaseUrl().value).host;
@ -18,7 +19,7 @@ const { error, error_description } = useUrlSearchParams();
<template>
<div class="container relative flex h-svh flex-col items-center justify-center md:flex-row lg:max-w-none lg:px-0">
<Button :as="NuxtLink" href="/register" variant="link" class="absolute right-4 top-4 md:right-8 md:top-8">
Register
{{ m.noble_cute_ocelot_aim() }}
</Button>
<div class="relative hidden h-full flex-col bg-muted p-10 text-white dark:border-r lg:flex grow bg-center bg-no-repeat bg-cover"
:style="{
@ -55,10 +56,11 @@ const { error, error_description } = useUrlSearchParams();
</Alert>
<div class="flex flex-col space-y-2 text-center">
<h1 class="text-2xl font-semibold tracking-tight">
Log in to your account.
{{ m.novel_fine_stork_snap() }}
</h1>
<p class="text-sm text-muted-foreground">
Enter your credentials for <code>{{ host }}</code>.
<p class="text-sm text-muted-foreground" v-html="m.smug_main_whale_snip({
host,
})">
</p>
</div>
<UserAuthForm v-if="instance" :instance="instance" />

View file

@ -4,8 +4,8 @@
}">
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Here's your code</CardTitle>
<CardDescription>You have signed in successfully.<br />Paste the following code into your app:
<CardTitle>{{ m.aware_awful_crow_spur() }}</CardTitle>
<CardDescription>{{ m.mushy_soft_lizard_propel() }}<br />{{ m.short_arable_leopard_zap() }}
</CardDescription>
</CardHeader>
<CardContent class="grid">
@ -23,9 +23,10 @@ import {
CardHeader,
CardTitle,
} from "~/components/ui/card";
import * as m from "~/paraglide/messages.js";
useHead({
title: "Authorization Code",
title: m.spare_aqua_warthog_mend(),
});
const { code } = useUrlSearchParams();

View file

@ -5,7 +5,9 @@
<Card class="w-full max-w-md" as="form" method="POST" :action="url.pathname.replace('/oauth/consent', '/oauth/authorize')">
<input type="hidden" v-for="([key, value]) in url.searchParams" :key="key" :name="key" :value="value" />
<CardHeader>
<CardTitle as="h1" class="text-2xl break-words">Authorize &ldquo;{{ application }}&rdquo;?</CardTitle>
<CardTitle as="h1" class="text-2xl break-words">{{ m.fresh_broad_cockroach_radiate({
application: application ?? "",
}) }}</CardTitle>
</CardHeader>
<CardContent>
<Card>
@ -23,16 +25,17 @@
</li>
</ul>
<div class="flex-col flex gap-y-1 text-sm">
<p>You are signing in to <b>{{ application }}</b> with your
account.</p>
<p>This allows <b>{{ application }}</b> to perform the above
account
actions.</p>
<p v-html="m.gross_antsy_kangaroo_succeed({
application: application ?? '',
})"></p>
<p v-html="m.hour_close_giraffe_mop({
application: application ?? '',
})"></p>
</div>
</CardContent>
<CardFooter class="grid gap-2">
<Button variant="default" type="submit">Authorize</Button>
<Button :as="NuxtLink" href="/" variant="secondary">Cancel</Button>
<Button variant="default" type="submit">{{ m.last_spare_polecat_reside() }}</Button>
<Button :as="NuxtLink" href="/" variant="secondary">{{ m.soft_bold_ant_attend() }}</Button>
</CardFooter>
</Card>
</div>
@ -42,10 +45,11 @@
import { Check } from "lucide-vue-next";
import { Button } from "~/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import * as m from "~/paraglide/messages.js";
import { NuxtLink } from "#components";
useHead({
title: "Authorization",
title: m.lower_factual_frog_evoke(),
});
const url = useRequestURL();
@ -62,20 +66,20 @@ const scope = params.scope ? decodeURIComponent(params.scope as string) : "";
const validUrlParameters = application && redirectUri && clientId && scope;
const oauthScopeText: Record<string, string> = {
"rw:accounts": "$VERB your account information",
"rw:blocks": "$VERB your block list",
"rw:bookmarks": "$VERB your bookmarks",
"rw:favourites": "$VERB your favourites",
"rw:filters": "$VERB your filters",
"rw:follows": "$VERB your follows",
"rw:lists": "$VERB your lists",
"rw:mutes": "$VERB your mutes",
"rw:notifications": "$VERB your notifications",
"r:search": "Perform searches",
"rw:statuses": "$VERB your statuses",
"w:conversations": "Edit your conversations",
"w:media": "Upload media",
"w:reports": "Report users",
"rw:accounts": m.awake_ago_capybara_kick(),
"rw:blocks": m.teary_zesty_racoon_transform(),
"rw:bookmarks": m.whole_flaky_nuthatch_rush(),
"rw:favourites": m.still_spicy_lionfish_quell(),
"rw:filters": m.away_mean_dolphin_empower(),
"rw:follows": m.sleek_empty_penguin_radiate(),
"rw:lists": m.every_silly_racoon_lift(),
"rw:mutes": m.top_careful_scallop_clip(),
"rw:notifications": m.this_short_bulldog_walk(),
"r:search": m.fresh_odd_rook_forgive(),
"rw:statuses": m.witty_whole_capybara_pull(),
"w:conversations": m.agent_warm_javelina_blink(),
"w:media": m.dirty_red_jellyfish_ascend(),
"w:reports": m.crisp_vivid_seahorse_tend(),
};
const scopes = scope.split(" ");
@ -103,7 +107,7 @@ const getScopeText = (fullScopes: string[]) => {
) {
if (oauthScopeText[possibleScope]?.includes("$VERB")) {
scopeTexts.push([
"Read and write",
m.teary_such_jay_fade(),
oauthScopeText[possibleScope]?.replace("$VERB", "") ?? "",
]);
} else {
@ -119,7 +123,7 @@ const getScopeText = (fullScopes: string[]) => {
) {
if (oauthScopeText[possibleScope]?.includes("$VERB")) {
scopeTexts.push([
"Read",
m.smug_safe_warthog_dare(),
oauthScopeText[possibleScope]?.replace("$VERB", "") ?? "",
]);
} else {
@ -134,7 +138,7 @@ const getScopeText = (fullScopes: string[]) => {
) {
if (oauthScopeText[possibleScope]?.includes("$VERB")) {
scopeTexts.push([
"Write",
m.loose_large_blackbird_peek(),
oauthScopeText[possibleScope]?.replace("$VERB", "") ?? "",
]);
} else {

View file

@ -4,14 +4,14 @@
}">
<Card v-if="params.success" class="w-full max-w-md">
<CardHeader>
<CardTitle>Success</CardTitle>
<CardTitle>{{ m.late_mean_capybara_fade() }}</CardTitle>
<CardDescription>
Your password has been reset. You can now log in with your new password.
{{ m.brave_acidic_lobster_fetch() }}
</CardDescription>
</CardHeader>
<CardFooter class="grid">
<Button :as="NuxtLink" href="/" variant="default">
Back to front page
{{ m.every_tangy_koala_persist() }}
</Button>
</CardFooter>
</Card>
@ -20,9 +20,9 @@
<CardHeader>
<Alert v-if="params.login_reset" variant="default" class="mb-4">
<AlertCircle class="size-4" />
<AlertTitle>Info</AlertTitle>
<AlertTitle>{{ m.east_loud_lobster_explore() }}</AlertTitle>
<AlertDescription>
Your password has been reset by an administrator. Please change it here.
{{ m.good_plane_gazelle_glow() }}
</AlertDescription>
</Alert>
<Alert v-if="params.error" variant="destructive" class="mb-4">
@ -32,9 +32,9 @@
{{ params.error_description }}
</AlertDescription>
</Alert>
<CardTitle as="h1">Reset your password</CardTitle>
<CardTitle as="h1">{{ m.tired_green_sloth_evoke() }}</CardTitle>
<CardDescription>
Enter your new password below. Make sure to put it in a password manager.
{{ m.solid_slow_platypus_talk() }}
</CardDescription>
</CardHeader>
<CardContent class="grid gap-6">
@ -48,7 +48,7 @@
<FormField v-slot="{ componentField }" name="password">
<FormItem>
<FormLabel>
New password
{{ m.true_male_gadfly_stab() }}
</FormLabel>
<FormControl>
<Input placeholder="hunter2" type="password" auto-capitalize="none" auto-correct="off"
@ -60,7 +60,7 @@
<FormField v-slot="{ componentField }" name="password-confirm">
<FormItem>
<FormLabel>
Confirm password
{{ m.awful_cozy_jannes_rise() }}
</FormLabel>
<FormControl>
<Input placeholder="hunter2" type="password" auto-capitalize="none" auto-correct="off"
@ -71,7 +71,7 @@
</FormField>
</CardContent>
<CardFooter class="grid gap-2">
<Button variant="default" type="submit">Reset</Button>
<Button variant="default" type="submit">{{ m.noisy_round_skate_yell() }}</Button>
</CardFooter>
</form>
</Card>
@ -100,10 +100,11 @@ import {
FormMessage,
} from "~/components/ui/form";
import { Input } from "~/components/ui/input";
import * as m from "~/paraglide/messages.js";
import { NuxtLink } from "#components";
useHead({
title: "Reset Password",
title: m.arable_arable_herring_lead(),
});
identity.value = null;
@ -115,18 +116,26 @@ const formSchema = toTypedSchema(
password: z
.string()
.min(3, {
message: "Must be at least 3 characters long",
message: m.smart_bold_macaw_aid({
count: 3,
}),
})
.max(100, {
message: "Must be at most 100 characters long",
message: m.dry_smug_goldfish_promise({
count: 100,
}),
}),
"password-confirm": z
.string()
.min(3, {
message: "Must be at least 3 characters long",
message: m.smart_bold_macaw_aid({
count: 3,
}),
})
.max(100, {
message: "Must be at most 100 characters long",
message: m.dry_smug_goldfish_promise({
count: 100,
}),
}),
})
.superRefine((data, ctx) => {
@ -134,7 +143,7 @@ const formSchema = toTypedSchema(
ctx.addIssue({
path: [...ctx.path, "password-confirm"],
code: "custom",
message: "Passwords do not match",
message: m.candid_fancy_leopard_prosper(),
});
}
return {};

View file

@ -15,6 +15,7 @@
<script lang="ts" setup>
import SelectPreference from "~/components/preferences/select.vue";
import SwitchPreference from "~/components/preferences/switch.vue";
import * as m from "~/paraglide/messages.js";
import {
type BooleanSetting,
type EnumSetting,
@ -25,14 +26,14 @@ import {
} from "~/settings.ts";
useHead({
title: "Preferences",
title: m.broad_whole_herring_reside(),
});
definePageMeta({
layout: "app",
breadcrumbs: [
{
text: "Preferences",
text: m.broad_whole_herring_reside(),
},
],
requiresAuth: true,

View file

@ -2,7 +2,7 @@
<div class="md:px-8 px-4 py-2 max-w-7xl mx-auto w-full space-y-6">
<div :class="cn('grid gap-2', profileEditor?.dirty && 'grid-cols-[1fr,auto]')">
<h1 class="scroll-m-20 text-3xl font-extrabold tracking-tight lg:text-4xl capitalize">
Account
{{ m.tasty_late_termite_sew() }}
</h1>
<Button class="ml-auto" v-if="profileEditor?.dirty" @click="profileEditor.submitForm">Save</Button>
</div>
@ -17,16 +17,17 @@ import { cn } from "@/lib/utils";
// biome-ignore lint/style/useImportType: <explanation>
import ProfileEditor from "~/components/preferences/profile/editor.vue";
import { Button } from "~/components/ui/button";
import * as m from "~/paraglide/messages.js";
useHead({
title: "Account Preferences",
title: m.actual_mean_cow_dare(),
});
definePageMeta({
layout: "app",
breadcrumbs: [
{
text: "Preferences",
text: m.broad_whole_herring_reside(),
},
],
requiresAuth: true,

View file

@ -1,7 +1,7 @@
<template>
<div class="md:px-8 px-4 py-2 max-w-7xl mx-auto w-full space-y-6">
<h1 class="scroll-m-20 text-3xl font-extrabold tracking-tight lg:text-4xl capitalize">
Emojis
{{ m.suave_smart_mantis_climb() }}
</h1>
<div v-if="emojis.length > 0" class="max-w-sm w-full relative">
<Input v-model="search" placeholder="Search" class="pl-8" />
@ -11,9 +11,9 @@
:name="name" />
<Card v-else class="shadow-none bg-transparent border-none p-4">
<CardHeader class="text-center gap-y-4">
<CardTitle class="text-">No emojis found.</CardTitle>
<CardTitle>{{ m.actual_steep_llama_rest() }}</CardTitle>
<CardDescription>
Ask your administrator to add some emojis.
{{ m.lucky_suave_myna_adore() }}
</CardDescription>
</CardHeader>
</Card>
@ -24,17 +24,24 @@
import type { Emoji } from "@versia/client/types";
import { Search } from "lucide-vue-next";
import Category from "~/components/preferences/emojis/category.vue";
import {
Card,
CardDescription,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import { Input } from "~/components/ui/input";
import * as m from "~/paraglide/messages.js";
useHead({
title: "Emoji Preferences",
title: m.mild_many_dolphin_mend(),
});
definePageMeta({
layout: "app",
breadcrumbs: [
{
text: "Preferences",
text: m.broad_whole_herring_reside(),
},
],
requiresAuth: true,
@ -56,11 +63,11 @@ const categories = computed(() => {
const categories = new Map<string, Emoji[]>();
for (const emoji of emojis.value) {
if (!emoji.category) {
if (!categories.has("Uncategorized")) {
categories.set("Uncategorized", []);
if (!categories.has(m.lucky_ago_rat_pinch())) {
categories.set(m.lucky_ago_rat_pinch(), []);
}
categories.get("Uncategorized")?.push(emoji);
categories.get(m.lucky_ago_rat_pinch())?.push(emoji);
continue;
}

View file

@ -5,11 +5,13 @@
</template>
<script lang="ts" setup>
import * as m from "~/paraglide/messages.js";
definePageMeta({
layout: "app",
breadcrumbs: [
{
text: "Preferences",
text: m.broad_whole_herring_reside(),
},
],
requiresAuth: true,

View file

@ -9,6 +9,7 @@
<script setup lang="ts">
import Public from "~/components/timelines/public.vue";
import TimelineScroller from "~/components/timelines/timeline-scroller.vue";
import * as m from "~/paraglide/messages.js";
useHead({
title: "Public",
@ -18,10 +19,10 @@ definePageMeta({
layout: "app",
breadcrumbs: [
{
text: "Timelines",
text: m.steep_aqua_fox_harbor(),
},
{
text: "Public",
text: m.lost_trick_dog_grace(),
href: "/public",
},
],

View file

@ -6,18 +6,18 @@
<CardHeader>
<Alert v-if="errors.error" variant="destructive" class="mb-4">
<AlertCircle class="size-4" />
<AlertTitle>Error</AlertTitle>
<AlertTitle>{{ m.vexed_each_falcon_enjoy() }}</AlertTitle>
<AlertDescription>
{{ errors.error }}
</AlertDescription>
</Alert>
<CardTitle as="h1" class="text-2xl break-words">Create an account</CardTitle>
<CardTitle as="h1" class="text-2xl break-words">{{ m.wide_topical_vole_walk() }}</CardTitle>
</CardHeader>
<CardContent v-if="instance && tos" class="grid gap-6">
<FormField v-slot="{ componentField }" name="username">
<FormItem>
<FormLabel>
Username
{{ m.keen_clean_nils_slurp() }}
</FormLabel>
<FormControl>
<Input placeholder="petergriffin" type="text" auto-capitalize="none"
@ -30,7 +30,7 @@
<FormField v-slot="{ componentField }" name="email">
<FormItem>
<FormLabel>
Email address
{{ m.top_inclusive_wallaby_hack() }}
</FormLabel>
<FormControl>
<Input placeholder="peter.griffin@fox.com" type="email" auto-capitalize="none"
@ -43,7 +43,7 @@
<FormField v-slot="{ componentField }" name="password">
<FormItem>
<FormLabel>
Password
{{ m.livid_bright_wallaby_quiz() }}
</FormLabel>
<FormControl>
<Input placeholder="hunter2" type="password" auto-capitalize="none" auto-complete="password"
@ -55,7 +55,7 @@
<FormField v-slot="{ componentField }" name="password-confirm">
<FormItem>
<FormLabel>
Confirm password
{{ m.awful_cozy_jannes_rise() }}
</FormLabel>
<FormControl>
<Input placeholder="hunter2" type="password" auto-capitalize="none" auto-complete="password"
@ -72,8 +72,8 @@
</FormControl>
<FormLabel>
<Dialog>
I agree to the <DialogTrigger :as-child="true"><Button variant="link"
class="px-0 underline">Terms of Service</Button>.</DialogTrigger>
{{ m.plane_quick_chipmunk_rush() }} <DialogTrigger :as-child="true"><Button variant="link"
class="px-0 underline">{{ m.glad_last_crow_dine() }}</Button>.</DialogTrigger>
<DialogContent class="!max-h-[90vh] overflow-auto">
<DialogHeader>
<DialogTitle>{{ instance.title }}
@ -88,11 +88,11 @@
</FormItem>
</FormField>
<div class="flex-col flex gap-y-1 text-sm text-muted-foreground">
<p>Passwords are never stored in plain text.</p>
<p>{{ m.happy_house_dragonfly_clap() }}</p>
</div>
</CardContent>
<CardFooter v-if="instance && tos" class="grid gap-2">
<Button variant="default" type="submit">Register</Button>
<Button variant="default" type="submit">{{ m.early_last_ocelot_praise() }}</Button>
</CardFooter>
<div v-else class="p-4 flex items-center justify-center h-48">
<Loader class="size-8 animate-spin" />
@ -100,14 +100,14 @@
</Card>
<Card v-else class="w-full max-w-md">
<CardHeader>
<CardTitle>Sorry :c</CardTitle>
<CardTitle>{{ m.wide_away_cat_taste() }}</CardTitle>
<CardDescription>
Registrations are disabled on this instance.
{{ m.safe_candid_horse_jump() }}
</CardDescription>
</CardHeader>
<CardFooter class="grid">
<Button :as="NuxtLink" href="/" variant="default">
Back to front page
{{ m.every_tangy_koala_persist() }}}
</Button>
</CardFooter>
</Card>
@ -117,7 +117,7 @@
<script setup lang="ts">
import { toTypedSchema } from "@vee-validate/zod";
import { Client, type ResponseError } from "@versia/client";
import { AlertCircle, Check, Loader } from "lucide-vue-next";
import { AlertCircle, Loader } from "lucide-vue-next";
import { useForm } from "vee-validate";
import { z } from "zod";
import { Button } from "~/components/ui/button";
@ -126,10 +126,11 @@ import { Checkbox } from "~/components/ui/checkbox";
import { Dialog, DialogContent, DialogHeader } from "~/components/ui/dialog";
import { FormItem } from "~/components/ui/form";
import { Input } from "~/components/ui/input";
import * as m from "~/paraglide/messages.js";
import { NuxtLink } from "#components";
useHead({
title: "Register",
title: m.early_last_ocelot_praise(),
});
const schema = toTypedSchema(
@ -141,13 +142,10 @@ const schema = toTypedSchema(
username: z
.string()
.min(3)
.regex(
/^[a-z0-9_]+$/,
"Must be lowercase letters, numbers, or underscores",
),
.regex(/^[a-z0-9_-]+$/, m.sea_maroon_peacock_yell()),
reason: z.string().optional(),
tos: z.boolean().refine((value) => value, {
message: "You must agree to the Terms of Service",
message: m.civil_loose_coyote_jump(),
}),
})
.superRefine((data, ctx) => {
@ -155,7 +153,7 @@ const schema = toTypedSchema(
ctx.addIssue({
path: [...ctx.path, "password-confirm"],
code: "custom",
message: "Passwords do not match",
message: m.candid_fancy_leopard_prosper(),
});
}
return {};

View file

@ -4,14 +4,14 @@
}">
<Card class="w-full max-w-md">
<CardHeader>
<CardTitle>Success</CardTitle>
<CardTitle>{{ m.late_mean_capybara_fade() }}</CardTitle>
<CardDescription>
You've successfully registered. You can now log in with your new account.
{{ m.left_maroon_myna_drip() }}
</CardDescription>
</CardHeader>
<CardFooter class="grid">
<Button :as="NuxtLink" href="/" variant="default">
Back to front page
{{ m.every_tangy_koala_persist() }}
</Button>
</CardFooter>
</Card>
@ -21,6 +21,7 @@
<script setup lang="ts">
import { Button } from "~/components/ui/button";
import { Card, CardFooter, CardHeader, CardTitle } from "~/components/ui/card";
import * as m from "~/paraglide/messages.js";
import { NuxtLink } from "#components";
useHead({