mirror of
https://github.com/LogicLabs-OU/OpenArchiver.git
synced 2026-04-06 00:31:57 +02:00
* System settings setup * Multi-language support * feat: Add internationalization (i18n) support to frontend This commit introduces internationalization (i18n) to the frontend using the `sveltekit-i18n` library, allowing the user interface to be translated into multiple languages. Key changes: - Added translation files for 10 languages (en, de, es, fr, etc.). - Replaced hardcoded text strings throughout the frontend components and pages with translation keys. - Added a language selector to the system settings page, allowing administrators to set the default application language. - Updated the backend settings API to store and expose the new language configuration. * Adding greek translation * feat(backend): Implement i18n for API responses This commit introduces internationalization (i18n) to the backend API using the `i18next` library. Hardcoded error and response messages in the API controllers have been replaced with translation keys, which are processed by the new i18next middleware. This allows for API responses to be translated into different languages. The following dependencies were added: - `i18next` - `i18next-fs-backend` - `i18next-http-middleware` * Formatting code * Translation revamp for frontend and backend, adding systems docs * Docs site title --------- Co-authored-by: Wayne <5291640+ringoinca@users.noreply.github.com>
68 lines
1.8 KiB
Svelte
68 lines
1.8 KiB
Svelte
<script lang="ts">
|
|
import PostalMime, { type Email } from 'postal-mime';
|
|
import type { Buffer } from 'buffer';
|
|
import { t } from '$lib/translations';
|
|
|
|
let {
|
|
raw,
|
|
rawHtml,
|
|
}: { raw?: Buffer | { type: 'Buffer'; data: number[] } | undefined; rawHtml?: string } =
|
|
$props();
|
|
|
|
let parsedEmail: Email | null = $state(null);
|
|
let isLoading = $state(true);
|
|
|
|
// By adding a <base> tag, all relative and absolute links in the HTML document
|
|
// will open in a new tab by default.
|
|
let emailHtml = $derived(() => {
|
|
if (parsedEmail && parsedEmail.html) {
|
|
return `<base target="_blank" />${parsedEmail.html}`;
|
|
} else if (parsedEmail && parsedEmail.text) {
|
|
return `<base target="_blank" />${parsedEmail.text}`;
|
|
} else if (rawHtml) {
|
|
return `<base target="_blank" />${rawHtml}`;
|
|
}
|
|
return null;
|
|
});
|
|
|
|
$effect(() => {
|
|
async function parseEmail() {
|
|
if (raw) {
|
|
try {
|
|
let buffer: Uint8Array;
|
|
if ('type' in raw && raw.type === 'Buffer') {
|
|
buffer = new Uint8Array(raw.data);
|
|
} else {
|
|
buffer = new Uint8Array(raw as Buffer);
|
|
}
|
|
const parsed = await new PostalMime().parse(buffer);
|
|
parsedEmail = parsed;
|
|
} catch (error) {
|
|
console.error('Failed to parse email:', error);
|
|
} finally {
|
|
isLoading = false;
|
|
}
|
|
} else {
|
|
isLoading = false;
|
|
}
|
|
}
|
|
parseEmail();
|
|
});
|
|
</script>
|
|
|
|
<div class="mt-2 rounded-md border bg-white p-4">
|
|
{#if isLoading}
|
|
<p>{$t('components.email_preview.loading')}</p>
|
|
{:else if emailHtml}
|
|
<iframe
|
|
title={$t('archive.email_preview')}
|
|
srcdoc={emailHtml()}
|
|
class="h-[600px] w-full border-none"
|
|
></iframe>
|
|
{:else if raw}
|
|
<p>{$t('components.email_preview.render_error')}</p>
|
|
{:else}
|
|
<p class="text-gray-500">{$t('components.email_preview.not_available')}</p>
|
|
{/if}
|
|
</div>
|