🌐 Added some missing translations

This commit is contained in:
Mawoka
2023-04-19 18:37:46 +02:00
parent a0b02ec9c3
commit b079f72c23
26 changed files with 221 additions and 93 deletions
+7 -7
View File
@@ -132,7 +132,7 @@
{#if selected_question + 1 === quiz_data.questions.length && ((timer_res === '0' && question_results !== null) || quiz_data?.questions?.[selected_question]?.type === QuizQuestionType.SLIDE)}
{#if JSON.stringify(final_results) === JSON.stringify([null])}
<button on:click={get_final_results} class="admin-button"
>Get final results
>{$t('admin_page.get_final_results')}
</button>
{/if}
{:else if timer_res === '0' || selected_question === -1}
@@ -142,7 +142,7 @@
set_question_number(selected_question + 1);
}}
class="admin-button"
>Next Question ({selected_question + 2})
>{$t('admin_page.next_question', { question: selected_question + 2 })}
</button>
{/if}
{#if question_results === null && selected_question !== -1}
@@ -152,11 +152,11 @@
set_question_number(selected_question + 1);
}}
class="admin-button"
>Next Question ({selected_question + 2})
>{$t('admin_page.next_question', { question: selected_question + 2 })}
</button>
{:else}
<button on:click={get_question_results} class="admin-button"
>Show results
>{$t('admin_page.show_results')}
</button>
{/if}
{/if}
@@ -167,11 +167,11 @@
set_question_number(selected_question + 1);
}}
class="admin-button"
>Next Question ({selected_question + 2})
>{$t('admin_page.next_question', { question: selected_question + 2 })}
</button>
{:else}
<button on:click={show_solutions} class="admin-button"
>Stop time and show solutions
>{$t('admin_page.stop_time_and_solutions')}
</button>
{/if}
{:else}
@@ -262,7 +262,7 @@
</div>
{:else}
<div class="flex justify-center">
<p class="text-2xl">Enter your answer into the input field!</p>
<p class="text-2xl">{$t('admin_page.enter_answer_into_field')}</p>
</div>
{/if}
{/if}
+5 -2
View File
@@ -11,6 +11,9 @@
import SettingsCard from '$lib/editor/settings-card.svelte';
import QuizCard from '$lib/editor/card.svelte';
import Spinner from './Spinner.svelte';
import { getLocalization } from '$lib/i18n';
const { t } = getLocalization();
let schemaInvalid = false;
let yupErrorMessage = '';
@@ -152,10 +155,10 @@
</p>
{/if}
<button
class="pr-2 align-middle bg-purple-400 pl-2 ml-auto whitespace-nowrap disabled:opacity-60 rounded-br-lg"
class="pr-2 align-middle bg-[#B07156] pl-2 ml-auto whitespace-nowrap disabled:opacity-60 rounded-br-lg"
disabled={schemaInvalid}
>
<span>Save</span>
<span>{$t('words.save')}</span>
<svg
class="w-6 h-6 inline-block"
fill="none"
@@ -80,7 +80,7 @@
type="text"
class="border-b-2 border-dotted w-5/6 text-center rounded-lg bg-transparent"
style="background-color: {answer.color ?? 'transparent'}"
placeholder="Empty..."
placeholder={$t('editor.empty')}
/>
<button
type="button"
@@ -141,7 +141,7 @@
type="text"
class="border-b-2 border-dotted w-5/6 text-center rounded-lg bg-transparent"
style="background-color: {answer.color ?? 'transparent'}"
placeholder="Empty..."
placeholder={$t('editor.empty')}
/>
<input
class="rounded-lg p-1 border-black border"
@@ -74,7 +74,7 @@
bind:value={answer.answer}
type="text"
class="border-b-2 border-dotted w-5/6 text-center rounded-lg bg-transparent"
placeholder="Empty..."
placeholder={$t('editor.empty')}
/>
<button
type="button"
@@ -79,7 +79,7 @@
type="text"
class="border-b-2 border-dotted w-5/6 text-center rounded-lg"
style="background-color: {answer.color ?? 'transparent'}"
placeholder="Empty..."
placeholder={$t('editor.empty')}
/>
<input
class="rounded-lg p-1 border-black border"
+6
View File
@@ -42,9 +42,15 @@
.toString()
.slice(0, 3);
}
};
const set_unique = () => {
unique = {};
};
$: correctTimeInput(data.questions[selected_question].time);
$: {
selected_question;
set_unique();
}
/*
if (typeof data.questions[selected_question].type !== QuizQuestionType) {
console.log(data.questions[selected_question].type !== QuizQuestionType.ABCD || data.questions[selected_question].type !== QuizQuestionType.RANGE)
+1 -1
View File
@@ -180,7 +180,7 @@
</div>
</div>
<div class="flex justify-center pt-10">
<h3>Background-Image</h3>
<h3>{$t('editor.bg_image')}</h3>
</div>
<div class="w-full flex justify-center -mt-8">
{#if data.background_image}
+14 -10
View File
@@ -9,6 +9,8 @@
import { reach } from 'yup';
import { ABCDQuestionSchema, dataSchema } from '../yupSchemas';
import { createTippy } from 'svelte-tippy';
import { getLocalization } from '$lib/i18n';
const { t } = getLocalization();
export let data: EditorData;
export let selected_question = -1;
@@ -78,7 +80,7 @@
{#if data.title}
{@html data.title}
{:else}
<i>No title...</i>
<i>{$t('editor.no_title')}</i>
{/if}
</p>
</div>
@@ -121,7 +123,7 @@
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span>Public</span>
<span>{$t('words.public')}</span>
{:else}
<svg
class="w-5 h-5 inline-block"
@@ -137,7 +139,7 @@
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"
/>
</svg>
<span>Private</span>
<span>{$t('words.private')}</span>
{/if}
</button>
</div>
@@ -190,7 +192,7 @@
class:dark:text-black={index === selected_question}
>
{#if question.question === ''}
<span class="italic text-gray-500">No title...</span>
<span class="italic text-gray-500">{$t('editor.no_title')}</span>
{:else}
{@html question.question}
{/if}
@@ -222,10 +224,11 @@
'answer'
).isValidSync(answer.answer)}
use:tippy={{
content: answer.answer === '' ? 'Empty...' : answer.answer
content:
answer.answer === '' ? $t('editor.empty') : answer.answer
}}
>{#if answer.answer === ''}
<i>Empty...</i>
<i>{$t('editor.empty')}</i>
{:else}
{answer.answer}
{/if}</span
@@ -252,10 +255,11 @@
'answer'
).isValidSync(answer.answer)}
use:tippy={{
content: answer.answer === '' ? 'Empty...' : answer.answer
content:
answer.answer === '' ? $t('editor.empty') : answer.answer
}}
>{#if answer.answer === ''}
<i>Empty...</i>
<i>{$t('editor.empty')}</i>
{:else}
{answer.answer}
{/if}</span
@@ -280,7 +284,7 @@
data.questions = [...data.questions, { ...empty_question }];
}}
>
<span class="w-full text-center">Question</span>
<span class="w-full text-center">{$t('words.question')}</span>
<svg
class="w-5/6 m-auto"
fill="none"
@@ -303,7 +307,7 @@
data.questions = [...data.questions, { ...empy_slide }];
}}
>
<span class="w-full text-center">Slide</span>
<span class="w-full text-center">{$t('words.slide')}</span>
<svg
class="w-5/6 m-auto"
fill="none"
@@ -7,7 +7,9 @@
import { ElementTypes } from '$lib/quiz_types';
import { onMount } from 'svelte';
import { fade } from 'svelte/transition';
import { getLocalization } from '$lib/i18n';
const { t } = getLocalization();
export let selected_element;
const keybinding_list = {
t: ElementTypes.Text,
@@ -40,22 +42,22 @@
shortcut: string;
}> = [
{
name: 'Headline',
description: 'A bold text for headlines',
name: $t('editor.slide.headline'),
description: $t('editor.slide.headline_description'),
type: ElementTypes.Headline,
icon: undefined,
shortcut: 'h'
},
{
name: 'Text',
description: 'Smaller longer text',
name: $t('editor.slide.text'),
description: $t('editor.slide.text_description'),
type: ElementTypes.Text,
icon: undefined,
shortcut: 't'
},
{
name: 'Rectangle',
description: 'Just a rectangle',
name: $t('editor.slide.rectangle'),
description: $t('editor.slide.rectangle_description'),
type: ElementTypes.Rectangle,
icon: undefined,
shortcut: 'r'
+11 -3
View File
@@ -48,7 +48,8 @@
"community_driven_content": "ClassQuiz hängt von der Community ab, die ClassQuiz mit Spenden, Feature-Requests, Übersetzungen und mehr versorgt! Du kannst auch ein Teil der ClassQuiz-Community werden!",
"download_quizzes_content": "Quiz können als einzige Datei heruntergeladen werden und jederzeit importiert werden, sodass du auch einfach auf eine andere Instanz von ClassQuiz umziehen kannst!",
"community_driven": "Von der Community betrieben",
"download_quizzes": "Quiz herunterladen"
"download_quizzes": "Quiz herunterladen",
"how_does_classquiz_work": "Wie funktioniert ClassQuiz überhaupt?"
},
"overview_page": {
"created_at": "Erstellt am",
@@ -161,7 +162,8 @@
"score": "Punkte",
"results": "Ergebnisse",
"note": "Notiz",
"player_plural": "Spieler"
"player_plural": "Spieler",
"slide": "Folie"
},
"editor": {
"time_in_seconds": "Zeit in Sekunden",
@@ -170,7 +172,10 @@
"add_new_question": "Neue Frage hinzufügen",
"delete_question": "Frage löschen",
"delete_answer": "Antwort löschen",
"not_all_links_imgur_links": "Nicht alle Links sind Imgur-Links!"
"not_all_links_imgur_links": "Nicht alle Links sind Imgur-Links!",
"no_title": "Kein Titel...",
"empty": "Leer...",
"bg_image": "Hintergrundbild"
},
"import": {
"need_help": "",
@@ -279,5 +284,8 @@
"time_taken": "benötigte Zeit",
"player_name": "Spielername",
"correct_answer_plural": "{{count}} richtige Antworten"
},
"navbar": {
"donate": "Spenden"
}
}
+67 -7
View File
@@ -48,7 +48,8 @@
"download_quizzes": "Download Quizzes",
"download_quizzes_content": "Quizzes can be downloaded as one file and imported at any time. This also lets you move your quizzes to other ClassQuiz instances.",
"community_driven": "Community-driven",
"community_driven_content": "ClassQuiz depends on its community for funding, testing ideas, feature requests, translations and more! You can also be a part of the ClassQuiz-community!"
"community_driven_content": "ClassQuiz depends on its community for funding, testing ideas, feature requests, translations and more! You can also be a part of the ClassQuiz-community!",
"how_does_classquiz_work": "How does ClassQuiz even work?"
},
"overview_page": {
"created_at": "Created at",
@@ -161,7 +162,13 @@
"results": "Results",
"note": "Note",
"player_plural": "Players",
"score": "Score"
"score": "Score",
"slide": "Slide",
"name": "Name",
"point": "Point",
"point_plural": "Points",
"back": "Back",
"finish": "Finish"
},
"editor": {
"time_in_seconds": "Time in seconds",
@@ -170,7 +177,18 @@
"add_new_question": "Add new question",
"delete_question": "Delete question",
"delete_answer": "Delete answer",
"not_all_links_imgur_links": "Not all links are Imgur-links!"
"not_all_links_imgur_links": "Not all links are Imgur-links!",
"no_title": "No title...",
"empty": "Empty...",
"bg_image": "Background image",
"slide": {
"headline": "Headline",
"headline_description": "A bold text for headlines",
"text": "Text",
"text_description": "Smaller longer text",
"rectangle": "Rectangle",
"rectangle_description": "Just a rectangle"
}
},
"import_page": {
"need_help": "Need help?",
@@ -194,7 +212,11 @@
"start_by_showing_first_question": "Start by showing the first question.",
"no_answers": "No answers!",
"stop_time": "Stop time",
"save_results": "Save results"
"save_results": "Save results",
"next_question": "Next Question ({{question}})",
"show_results": "Show results",
"stop_time_and_solutions": "Stop time and show solutions",
"enter_answer_into_field": "Enter your answer into the input field!"
},
"password_reset_page": {
"reset_password": "Reset password"
@@ -207,7 +229,9 @@
"last_seen": "Last seen",
"check_location": "Check location",
"delete_this_session": "Delete this session",
"this_session?": "This session?"
"this_session?": "This session?",
"change_avatar": "Change avatar",
"security_settings": "Security-Settings"
},
"explore_page": {
"made_by": "Made by",
@@ -222,7 +246,12 @@
"1st_place": "1st Place",
"2nd_place": "2nd Place",
"3rd place": "3rd Place",
"with_out_of": "with {{correct_questions}} out of {{total_question_count}}"
"with_out_of": "with {{correct_questions}} out of {{total_question_count}}",
"final_result_rank": "{{place}}: {{username}} with {{points}} points",
"your_score": "Your score: {{score}}",
"join_description": "Join at {{url}} and enter {{pin}}.",
"join_by_entering_code": "Join by entering the following code",
"points_added": "Points added"
},
"editor_page": {
"add_an_answer": "Add an answer",
@@ -257,7 +286,8 @@
"clothe_color": "Clothing color",
"clothe_graphic_type": "Graphic",
"thats_you": "That's You!",
"start_over": "Start over"
"start_over": "Start over",
"go_back": "Go back"
},
"results_page": {
"no_results_so_far": "No results saved so far...",
@@ -272,5 +302,35 @@
"correct_answer": "{{count}} correct answer",
"correct_answer_plural": "{{count}} correct answers",
"time_taken": "Time taken"
},
"navbar": {
"donate": "Donate"
},
"security_settings": {
"backup_code": "Backup-Code",
"get_backup_code": "Get Backup-Code",
"activate_2fa": "Activate Two Factor Authentication",
"2fa_activated": "Two Factor authentication is activated",
"2fa_deactivated": "Two Factor authentication is deactivated",
"webauthn": "Webauthn",
"webauthn_available": "Webauthn is available",
"webauthn_unavailable": "Webauthn is not available",
"add_security_key": "Add Security-Key",
"totp": "Totp",
"totp_available": "Totp is available",
"totp_unavailable": "Totp is not available",
"disable_totp": "Disable Totp",
"enable_totp": "Enable Totp",
"backup_codes": {
"your_backup_code": "Your Backup-Code",
"save_somewhere_save": "Save this somewhere safe!",
"download_code": "Download code"
},
"totp_setup": {
"scan_to_set_up": "Scan this QR-code to set up the code",
"enter_as_secret_if_no_see_code": "Enter this as the secret if you can't scan the QR-code",
"totp_setup": "Totp-Setup",
"do_not_forget_backup_code": "Do not forget to save your recovery-code!"
}
}
}
+2 -2
View File
@@ -109,7 +109,7 @@
<ul id="menu-items" class="lg:flex w-full flex-col lg:flex-row" class:hidden={openMenu}>
<li class="py-2 lg:hidden">
<BrownButton href="https://mawoka.eu/donate" target="_blank"
>Donate <span class="">❤️</span></BrownButton
>{$t('navbar.donate')} <span class="">❤️</span></BrownButton
>
</li>
{#if $signedIn}
@@ -183,7 +183,7 @@
>
<div class="whitespace-nowrap hidden lg:block">
<BrownButton href="https://mawoka.eu/donate" target="_blank"
>Donate <span class="">❤️</span></BrownButton
>{$t('navbar.donate')} <span class="">❤️</span></BrownButton
>
</div>
{#if darkMode}
@@ -5,6 +5,9 @@
-->
<script lang="ts">
import { onMount } from 'svelte';
import { getLocalization } from '$lib/i18n';
const { t } = getLocalization();
export let data;
export let username;
@@ -53,8 +56,11 @@
style="font-size: {player_count_or_five - i / 2}rem"
class="text-center"
>
{i + 1}
: {player} with {data[player]} points
{$t('play_page.final_result_rank', {
place: i + 1,
username: player,
points: data[player]
})}
</p>
{/if}
{/each}
@@ -62,7 +68,7 @@
{#if data[username]}
<div class="fixed bottom-0 left-0 flex justify-center w-full mb-6">
<div class="mx-auto p-2 border-[#B07156] border-4 rounded">
<p>Your score: <b>{data[username]}</b></p>
<p>{$t('play_page.your_score', { score: data[username] })}</p>
</div>
</div>
{/if}
@@ -43,7 +43,10 @@
<div class="grid grid-cols-3 mt-12">
<div class="flex justify-center">
<p class="m-auto text-2xl">
Join at <b>{window.location.host}/play</b> and enter <b>{game_pin}</b>.
{$t('play_page.join_description', {
url: `${window.location.host}/play`,
pin: game_pin
})}
</p>
</div>
<img
@@ -54,7 +57,7 @@
{#if cqc_code}
<div class="m-auto">
<div class="flex-col flex justify-center">
<p class="mx-auto">Join by entering the following code</p>
<p class="mx-auto">{$t('play_page.join_by_entering_code')}</p>
<div class="flex flex-row gap-2 mx-auto">
{#each cqc_code as c}
<div class="flex flex-col">
+7 -3
View File
@@ -7,6 +7,8 @@
import { flip } from 'svelte/animate';
import { fly } from 'svelte/transition';
import { onMount } from 'svelte';
import { getLocalization } from '$lib/i18n';
const { t } = getLocalization();
export let data;
@@ -91,11 +93,13 @@
<div>
<table class="table-auto text-xl">
<tr>
<th class="p-2 border-r border-r-black border-b-2 border-b-black">Name</th>
<th class="p-2 border-b-2 border-b-black">Points</th>
<th class="p-2 border-r border-r-black border-b-2 border-b-black"
>{$t('words.name')}</th
>
<th class="p-2 border-b-2 border-b-black">{$t('words.point', { count: 2 })}</th>
{#if show_new_score_clicked}
<th in:fly={{ x: 300 }} class="p-2 border-b-2 border-b-black"
>Points added
>{$t('play_page.points_added')}
</th>
{/if}
</tr>
+1 -1
View File
@@ -208,7 +208,7 @@
</div>
</section>
<section>
<h2 class="text-center text-5xl mb-6">How does ClassQuiz even work?</h2>
<h2 class="text-center text-5xl mb-6">{$t('index_page.how_does_classquiz_work')}</h2>
<div class="flex justify-center w-full">
<h3 class="text-center text-3xl rounded-t-lg bg-opacity-40 bg-white py-2 px-6">
@@ -170,7 +170,9 @@
alt="Profile image of {user.username}"
/>
<div class="m-2 flex justify-center">
<BrownButton href="/account/settings/avatar">Change avatar</BrownButton>
<BrownButton href="/account/settings/avatar"
>{$t('settings_page.change_avatar')}</BrownButton
>
</div>
</div>
<div class="grid grid-rows-2 col-start-2 col-end-7">
@@ -184,7 +186,7 @@
<div class="p-4 flex justify-center">
<div class="m-auto">
<BrownButton href="/account/settings/security"
>Security-Settings
>{$t('settings_page.security_settings')}
</BrownButton>
</div>
</div>
@@ -219,7 +221,7 @@
</div>
</form>
<div>
<button on:click={add_api_key}>Add API-Key</button>
<button on:click={add_api_key}>{$t('settings_page.security_settings')}</button>
{#await api_keys}
<Spinner />
{:then keys}
@@ -231,7 +233,7 @@
delete_api_key(key.key);
}}
class="admin-button"
>Delete
>{$t('words.delete')}
</button>
</div>
{/each}
@@ -94,7 +94,7 @@
on:click={() => {
index = index - 1;
}}
disabled={index < 1}>Back</BrownButton
disabled={index < 1}>{$t('words.back')}</BrownButton
>
</div>
<div class="mx-auto">
@@ -103,7 +103,7 @@
</h2>
</div>
<div class="ml-auto">
<BrownButton disabled={index < 11}>Finish</BrownButton>
<BrownButton disabled={index < 11}>{$t('words.finish')}</BrownButton>
</div>
</div>
<div class="grid grid-cols-4">
@@ -167,11 +167,11 @@
<Spinner my_20={false} />
{/if}
</BrownButton>
<BrownButton href="/account/settings">Go back</BrownButton>
<BrownButton href="/account/settings">{$t('avatar_settings.go_back')}</BrownButton>
<BrownButton
on:click={() => {
finished = false;
}}>Close</BrownButton
}}>{$t('words.close')}</BrownButton
>
</div>
</div>
@@ -10,6 +10,9 @@
import TotpSetup from './totp_setup.svelte';
import BackupCodes from './backup_codes.svelte';
import BrownButton from '$lib/components/buttons/brown.svelte';
import { getLocalization } from '$lib/i18n';
const { t } = getLocalization();
let user_data: object | undefined;
let security_keys: Array<{ id: number }> | undefined;
@@ -101,15 +104,17 @@
<div class="grid grid-rows-2 h-screen">
<div class="grid grid-cols-2 h-full border-b-2 border-black">
<div class="h-full w-full border-r-2 border-black">
<h2 class="text-center text-2xl">Backup-Code</h2>
<h2 class="text-center text-2xl">{$t('security_settings.backup_code')}</h2>
<div class="flex h-full w-full justify-center">
<div class="m-auto">
<BrownButton on:click={get_backup_code}>Get Backup-Codes</BrownButton>
<BrownButton on:click={get_backup_code}
>{$t('security_settings.get_backup_code')}</BrownButton
>
</div>
</div>
</div>
<div class="h-full w-full">
<h2 class="text-center text-2xl">Activate 2 Factor</h2>
<h2 class="text-center text-2xl">{$t('security_settings.activate_2fa')}</h2>
<div class="flex h-full w-full justify-center flex-col">
<div class="m-auto">
{#if user_data.require_password}
@@ -130,7 +135,7 @@
/>
</button>
<span class="text-sm font-medium text-gray-700 dark:text-white"
>Two Factor authentication is activated</span
>{$t('security_settings.2fa_activated')}</span
>
</div>
{:else}
@@ -151,7 +156,7 @@
/>
</button>
<span class="text-sm font-medium text-gray-700 dark:text-white"
>Two Factor authentication is deactivated</span
>{$t('security_settings.2fa_deactivated')}</span
>
</div>
{/if}
@@ -161,17 +166,19 @@
</div>
<div class="grid grid-cols-2 h-full">
<div class="h-full w-full flex flex-col border-r-2 border-black">
<h2 class="text-center text-2xl">Webauthn</h2>
<h2 class="text-center text-2xl">{$t('security_settings.webauthn')}</h2>
<div class="flex justify-center">
{#if security_keys.length > 0}
<p>Webauthn is available</p>
<p>{$t('security_settings.webauthn_available')}</p>
{:else}
<p>Webauthn is not available</p>
<p>{$t('security_settings.webauthn_unavailable')}</p>
{/if}
</div>
<div class="flex justify-center">
<div class="m-auto">
<BrownButton on:click={add_security_key}>Add Security-Key</BrownButton>
<BrownButton on:click={add_security_key}
>{$t('security_settings.add_security_key')}</BrownButton
>
</div>
</div>
<div class="flex justify-center">
@@ -190,21 +197,25 @@
</div>
</div>
<div class="h-full w-full flex flex-col">
<h2 class="text-center text-2xl">Totp</h2>
<h2 class="text-center text-2xl">{$t('security_settings.totp')}</h2>
<div class="flex justify-center">
{#if totp_activated}
<p>Totp is available</p>
<p>{$t('security_settings.totp_available')}</p>
{:else}
<p>Totp is not available</p>
<p>{$t('security_settings.totp_unavailable')}</p>
{/if}
</div>
<div class="flex justify-center">
<div class="m-auto">
{#if totp_activated}
<BrownButton on:click={disable_totp}>Disable Totp</BrownButton>
<BrownButton on:click={disable_totp}
>{$t('security_settings.disable_totp')}</BrownButton
>
{:else}
<BrownButton on:click={enable_totp}>Enable Totp</BrownButton>
<BrownButton on:click={enable_totp}
>{$t('security_settings.enable_totp')}</BrownButton
>
{/if}
</div>
</div>
@@ -4,6 +4,9 @@
- file, You can obtain one at https://mozilla.org/MPL/2.0/.
-->
<script lang="ts">
import { getLocalization } from '$lib/i18n';
const { t } = getLocalization();
export let backup_code;
let already_downloaded = false;
@@ -30,12 +33,12 @@
on:click={() => {
backup_code = undefined;
}}
>Close
>{$t('words.close')}
</button>
<div
class="bg-white dark:bg-gray-700 rounded-b-lg rounded-tr-lg w-full h-full flex flex-col"
>
<h2 class="text-3xl m-auto">Your Backup-Code</h2>
<h2 class="text-3xl m-auto">{$t('security_settings.backup_codes.your_backup_code')}</h2>
<p
class="select-all font-mono text-xl m-auto"
on:click={() => {
@@ -44,13 +47,14 @@
>
{backup_code}
</p>
<p class="m-auto">Save this somewhere safe!</p>
<p class="m-auto">{$t('security_settings.backup_codes.save_somewhere_save')}</p>
<button
on:click={() => {
download_code(true);
}}
class="m-auto p-2 bg-[#B07156] rounded-lg">Download code</button
>
class="m-auto p-2 bg-[#B07156] rounded-lg"
>{$t('security_settings.backup_codes.download_code')}
</button>
</div>
</div>
</div>
@@ -6,6 +6,9 @@
<script lang="ts">
import QRCode from 'qrcode';
import Spinner from '$lib/Spinner.svelte';
import { getLocalization } from '$lib/i18n';
const { t } = getLocalization();
export let totp_data: { url: string; secret: string } | undefined;
@@ -21,23 +24,25 @@
on:click={() => {
totp_data = undefined;
}}
>Close
>{$t('words.close')}
</button>
<div class="bg-white dark:bg-gray-700 rounded-b-lg rounded-tr-lg w-full h-full">
<div class="grid grid-cols-3 w-full h-full">
<div class="flex flex-col justify-center w-full h-5/6">
<span class="m-auto" />
<div class="h-5/6 flex">
<p class="my-auto ml-auto">Scan this to set up the code</p>
<p class="my-auto ml-auto">
{$t('security_settings.totp_setup.scan_to_set_up')}
</p>
</div>
<div class="flex">
<p class="my-auto ml-auto">
Enter this as the secret if you can't scan the code
{$t('security_settings.totp_setup.enter_as_secret_if_no_see_code')}
</p>
</div>
</div>
<div class="flex flex-col justify-start w-full h-5/6">
<h2 class="text-2xl m-auto">Totp-Setup</h2>
<h2 class="text-2xl m-auto">{$t('security_settings.totp_setup.totp_setup')}</h2>
{#await get_image_url()}
<Spinner my_20={false} />
{:then data}
@@ -52,7 +57,9 @@
<p class="m-auto select-all font-mono">{totp_data.secret}</p>
</div>
<div class="flex justify-center h-5/6 w-full">
<p class="m-auto text-3xl p-4">Do not forget to save your recovery-code!</p>
<p class="m-auto text-3xl p-4">
{$t('security_settings.totp_setup.do_not_forget_backup_code')}
</p>
</div>
</div>
</div>
@@ -5,6 +5,9 @@
-->
<script lang="ts">
import type { Question } from '$lib/quiz_types';
import { getLocalization } from '$lib/i18n';
const { t } = getLocalization();
export let questions: Question[];
export let answers: {
@@ -41,10 +44,12 @@
<div class="w-full">
<div class="flex justify-center w-full">
<p class="text-3xl w-5/6 text-center">
The quiz with the title '<strong>{title}</strong>' was played on
<strong>{new Date(timestamp).toLocaleString()}</strong>
with <strong>{usernames.length}</strong> players. The players achieved an average score
of <strong>{get_average_final_score()}</strong>.
{$t('results_page.general_overview.sentence', {
title,
date: new Date(timestamp).toLocaleString(),
player_count: usernames.length,
average_score: get_average_final_score()
})}
</p>
</div>
</div>
@@ -25,7 +25,7 @@
<th class="border-r dark:border-gray-500 p-1 mx-auto border-gray-300"
>{$t('result_page.player_name')}
</th>
<th class="p-1 mx-auto">Player Score</th>
<th class="p-1 mx-auto">{$t('result_page.player_score')}</th>
{#if Object.keys(custom_field).length !== 0}
<th class="border-l dark:border-gray-500 p-1 mx-auto border-gray-300"
>{$t('result_page.custom_field')}
@@ -40,7 +40,7 @@
<div class="grid grid-cols-6 h-full">
<div class="pl-2">
{#if data.user.username === undefined}
<h2 class="text-4xl text-center p-4">User not found</h2>
<h2 class="text-4xl text-center p-4">{$t('public_user_page.user_not_found')}</h2>
{:else}
<div class="flex justify-center">
<img src={`/api/v1/users/avatar/${data.user.id}`} alt="profile" />
@@ -49,7 +49,9 @@
@{data.user.username}
</h2>
<p class="italic text-center">
Joined on {new Date(data.user.created_at).toLocaleDateString()}
{$t('public_user_page.joined_on', {
date: new Date(data.user.created_at).toLocaleDateString()
})}
</p>
{/if}
</div>
@@ -57,7 +59,7 @@
class="col-start-2 col-end-7 border-l border-black h-full p-4 overflow-y-scroll flex flex-col gap-4"
>
{#if data.quizzes.length === 0}
<p class="text-center text-4xl">No original quizzes found...</p>
<p class="text-center text-4xl">{$t('public_user_page.no_original_quizzes')}</p>
{:else}
{#each data.quizzes as quiz}
<div
@@ -71,7 +71,8 @@
<p>{@html quiz.description}</p>
</div>
<p class="text-center">
Made by <a href="/user/{quiz.user_id.id}" class="underline">@{quiz.user_id.username}</a>
{$t('view_quiz_page.made_by')}
<a href="/user/{quiz.user_id.id}" class="underline">@{quiz.user_id.username}</a>
</p>
{#if quiz.cover_image}
<div class="flex justify-center align-middle items-center">
@@ -95,7 +96,7 @@
href="https://create.kahoot.it/details/{quiz.kahoot_id}"
target="_blank"
>
View on <i>Kahoot!</i>
{$t('view_quiz_page.view_on_kahoot')}
</GrayButton>
</div>
{/if}