feat: enhance language selection message and add translation contribution link

This commit is contained in:
Elias Schneider
2025-07-03 09:20:39 +02:00
parent 237342e876
commit be52660227
5 changed files with 93 additions and 6 deletions

View File

@@ -312,7 +312,8 @@
"reset": "Reset",
"reset_to_default": "Reset to default",
"profile_picture_has_been_reset": "Profile picture has been reset. It may take a few minutes to update.",
"select_the_language_you_want_to_use": "Select the language you want to use. Some languages may not be fully translated.",
"select_the_language_you_want_to_use": "Select the language you want to use. Please note that some text may be automatically translated and could be inaccurate.",
"contribute_to_translation": "If you find an issue you're welcome to contribute to the translation on <link href='https://crowdin.com/project/pocket-id'>Crowdin</link>.",
"personal": "Personal",
"global": "Global",
"all_users": "All Users",

View File

@@ -43,7 +43,7 @@
{description}
{#if docsLink}
<a
class="relative text-white after:absolute after:bottom-0 after:left-0 after:h-px after:w-full after:translate-y-[-1px] after:bg-white"
class="relative text-black after:absolute after:bottom-0 after:left-0 after:h-px after:w-full after:translate-y-[-1px] after:bg-white dark:text-white"
href={docsLink}
target="_blank"
>
@@ -72,7 +72,7 @@
{/if}
{/if}
{#if input?.error}
<p class="text-destructive mt-1 text-xs text-start">{input.error}</p>
<p class="text-destructive mt-1 text-start text-xs">{input.error}</p>
{/if}
</div>
</div>

View File

@@ -0,0 +1,83 @@
<!-- Component to display messages from Paraglide with support for links in the format <link href="url">text</link>. -->
<!-- This gets redundant in the future, because the library will support this natively. https://github.com/opral/inlang-sdk/issues/240 -->
<script lang="ts">
let {
m
}: {
m: string;
} = $props();
interface MessagePart {
type: 'text' | 'link';
content: string;
href?: string;
}
function parseMessage(content: string): MessagePart[] | string {
// Regex to match only <link href="url">text</link> format
const linkRegex = /<link\s+href=(['"])(.*?)\1>(.*?)<\/link>/g;
if (!linkRegex.test(content)) {
return content;
}
// Reset regex lastIndex for reuse
linkRegex.lastIndex = 0;
const parts: MessagePart[] = [];
let lastIndex = 0;
let match;
while ((match = linkRegex.exec(content)) !== null) {
// Add text before the link
if (match.index > lastIndex) {
const textContent = content.slice(lastIndex, match.index);
if (textContent) {
parts.push({ type: 'text', content: textContent });
}
}
const href = match[2];
const linkText = match[3];
parts.push({
type: 'link',
content: linkText,
href: href
});
lastIndex = match.index + match[0].length;
}
// Add remaining text after the last link
if (lastIndex < content.length) {
const remainingText = content.slice(lastIndex);
if (remainingText) {
parts.push({ type: 'text', content: remainingText });
}
}
return parts;
}
const parsedContent = parseMessage(m);
</script>
{#if typeof parsedContent === 'string'}
{parsedContent}
{:else}
{#each parsedContent as part}
{#if part.type === 'text'}
{part.content}
{:else if part.type === 'link'}
<a
class="text-black underline dark:text-white"
href={part.href}
target="_blank"
rel="noopener noreferrer"
>
{part.content}
</a>
{/if}
{/each}
{/if}

View File

@@ -13,7 +13,7 @@
<p
bind:this={ref}
data-slot="card-description"
class={cn('text-muted-foreground text-sm', className)}
class={cn('text-muted-foreground text-sm mt-1', className)}
{...restProps}
>
{@render children?.()}

View File

@@ -1,4 +1,5 @@
<script lang="ts">
import FormattedMessage from '$lib/components/formatted-message.svelte';
import * as Alert from '$lib/components/ui/alert';
import { Button } from '$lib/components/ui/button';
import * as Card from '$lib/components/ui/card';
@@ -9,7 +10,6 @@
import type { Passkey } from '$lib/types/passkey.type';
import type { UserCreate } from '$lib/types/user.type';
import { axiosErrorToast, getWebauthnErrorMessage } from '$lib/utils/error-util';
import { startRegistration } from '@simplewebauthn/browser';
import {
KeyRound,
Languages,
@@ -17,6 +17,7 @@
RectangleEllipsis,
UserCog
} from '@lucide/svelte';
import { startRegistration } from '@simplewebauthn/browser';
import { toast } from 'svelte-sonner';
import AccountForm from './account-form.svelte';
import LocalePicker from './locale-picker.svelte';
@@ -141,7 +142,7 @@
<!-- Passkey management card -->
<div>
<Card.Root>
<Card.Root class="gap-3">
<Card.Header>
<div class="flex items-center justify-between">
<div>
@@ -200,6 +201,8 @@
</Card.Title>
<Card.Description>
{m.select_the_language_you_want_to_use()}
<br />
<FormattedMessage m={m.contribute_to_translation()} />
</Card.Description>
</div>
<LocalePicker />