ソースを参照

Added more german translations + added more i18n keys

Jannik Streidl 1 年間 前
コミット
19843e39fd

+ 3 - 3
src/lib/components/admin/UserChatsModal.svelte

@@ -70,7 +70,7 @@
 								>
 									<tr>
 										<th scope="col" class="px-3 py-2"> {$i18n.t('Name')} </th>
-										<th scope="col" class="px-3 py-2 hidden md:flex"> {$i18n.t('Created At')} </th>
+										<th scope="col" class="px-3 py-2 hidden md:flex"> {$i18n.t('Created at')} </th>
 										<th scope="col" class="px-3 py-2 text-right" />
 									</tr>
 								</thead>
@@ -96,7 +96,7 @@
 
 											<td class="px-3 py-1 text-right">
 												<div class="flex justify-end w-full">
-													<Tooltip content="Delete Chat">
+													<Tooltip content={$i18n.t('Delete Chat')}>
 														<button
 															class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
 															on:click={async () => {
@@ -133,7 +133,7 @@
 						{/each} -->
 					</div>
 				{:else}
-					<div class="text-left text-sm w-full mb-8">{user.name} has no conversations.</div>
+					<div class="text-left text-sm w-full mb-8">{user.name} {$i18n.t('has no conversations.')}</div>
 				{/if}
 			</div>
 		</div>

+ 8 - 8
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -492,7 +492,7 @@
 										{/if}
 
 										{#if !readOnly}
-											<Tooltip content="Edit" placement="bottom">
+											<Tooltip content={$i18n.t('Edit')} placement="bottom">
 												<button
 													class="{isLastMessage
 														? 'visible'
@@ -519,7 +519,7 @@
 											</Tooltip>
 										{/if}
 
-										<Tooltip content="Copy" placement="bottom">
+										<Tooltip content={$i18n.t('Copy')} placement="bottom">
 											<button
 												class="{isLastMessage
 													? 'visible'
@@ -546,7 +546,7 @@
 										</Tooltip>
 
 										{#if !readOnly}
-											<Tooltip content="Good Response" placement="bottom">
+											<Tooltip content={$i18n.t('Good Response')} placement="bottom">
 												<button
 													class="{isLastMessage
 														? 'visible'
@@ -581,7 +581,7 @@
 												</button>
 											</Tooltip>
 
-											<Tooltip content="Bad Response" placement="bottom">
+											<Tooltip content={$i18n.t('Bad Response')} placement="bottom">
 												<button
 													class="{isLastMessage
 														? 'visible'
@@ -616,7 +616,7 @@
 											</Tooltip>
 										{/if}
 
-										<Tooltip content="Read Aloud" placement="bottom">
+										<Tooltip content={$i18n.t('Read Aloud')} placement="bottom">
 											<button
 												id="speak-button-{message.id}"
 												class="{isLastMessage
@@ -765,7 +765,7 @@
 										{/if}
 
 										{#if message.info}
-											<Tooltip content="Generation Info" placement="bottom">
+											<Tooltip content={$i18n.t('Generation Info')} placement="bottom">
 												<button
 													class=" {isLastMessage
 														? 'visible'
@@ -794,7 +794,7 @@
 										{/if}
 
 										{#if isLastMessage && !readOnly}
-											<Tooltip content="Continue Response" placement="bottom">
+											<Tooltip content={$i18n.t('Continue Response')} placement="bottom">
 												<button
 													type="button"
 													class="{isLastMessage
@@ -826,7 +826,7 @@
 												</button>
 											</Tooltip>
 
-											<Tooltip content="Regenerate" placement="bottom">
+											<Tooltip content={$i18n.t('Regenerate')} placement="bottom">
 												<button
 													type="button"
 													class="{isLastMessage

+ 3 - 3
src/lib/components/chat/Messages/UserMessage.svelte

@@ -266,7 +266,7 @@
 						{/if}
 
 						{#if !readOnly}
-							<Tooltip content="Edit" placement="bottom">
+							<Tooltip content={$i18n.t('Edit')} placement="bottom">
 								<button
 									class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition edit-user-message-button"
 									on:click={() => {
@@ -291,7 +291,7 @@
 							</Tooltip>
 						{/if}
 
-						<Tooltip content="Copy" placement="bottom">
+						<Tooltip content={$i18n.t('Copy')} placement="bottom">
 							<button
 								class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition"
 								on:click={() => {
@@ -316,7 +316,7 @@
 						</Tooltip>
 
 						{#if !isFirstMessage && !readOnly}
-							<Tooltip content="Delete" placement="bottom">
+							<Tooltip content={$i18n.t('Delete')} placement="bottom">
 								<button
 									class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition"
 									on:click={() => {

+ 1 - 1
src/lib/components/chat/ModelSelector.svelte

@@ -57,7 +57,7 @@
 
 			{#if selectedModelIdx === 0}
 				<div class="  self-center mr-2 disabled:text-gray-600 disabled:hover:text-gray-600">
-					<Tooltip content="Add Model">
+					<Tooltip content={$i18n.t('Add Model')}>
 						<button
 							class=" "
 							{disabled}

+ 1 - 1
src/lib/components/chat/ModelSelector/Selector.svelte

@@ -21,7 +21,7 @@
 	export let value = '';
 	export let placeholder = 'Select a model';
 	export let searchEnabled = true;
-	export let searchPlaceholder = 'Search a model';
+	export let searchPlaceholder = $i18n.t('Search a model');
 
 	export let items = [{ value: 'mango', label: 'Mango' }];
 

+ 4 - 1
src/lib/components/common/Tags.svelte

@@ -1,6 +1,9 @@
 <script lang="ts">
 	import TagInput from './Tags/TagInput.svelte';
 	import TagList from './Tags/TagList.svelte';
+	import { getContext } from 'svelte';
+
+	const i18n = getContext('i18n');
 
 	export let tags = [];
 
@@ -17,7 +20,7 @@
 	/>
 
 	<TagInput
-		label={tags.length == 0 ? 'Add Tags' : ''}
+		label={tags.length == 0 ? $i18n.t('Add Tags') : ''}
 		on:add={(e) => {
 			addTag(e.detail);
 		}}

+ 2 - 2
src/lib/components/layout/Navbar.svelte

@@ -42,7 +42,7 @@
 				<div class="flex self-center w-[1px] h-5 mx-2 bg-gray-300 dark:bg-stone-700" />
 
 				{#if !shareEnabled}
-					<Tooltip content="Settings">
+					<Tooltip content={$i18n.t('Settings')}>
 						<button
 							class="cursor-pointer p-1.5 flex dark:hover:bg-gray-700 rounded-full transition"
 							id="open-settings-button"
@@ -104,7 +104,7 @@
 						</button>
 					</Menu>
 				{/if}
-				<Tooltip content="New Chat">
+				<Tooltip content={$i18n.t('New Chat')}>
 					<button
 						id="new-chat-button"
 						class=" cursor-pointer p-1.5 flex dark:hover:bg-gray-700 rounded-full transition"

+ 8 - 5
src/lib/components/layout/Navbar/Menu.svelte

@@ -1,5 +1,6 @@
 <script lang="ts">
 	import { DropdownMenu } from 'bits-ui';
+	import { getContext } from 'svelte';
 
 	import fileSaver from 'file-saver';
 	const { saveAs } = fileSaver;
@@ -12,6 +13,8 @@
 
 	import { downloadChatAsPDF } from '$lib/apis/utils';
 
+	const i18n = getContext('i18n');
+
 	export let shareEnabled: boolean = false;
 	export let shareHandler: Function;
 	export let downloadHandler: Function;
@@ -104,7 +107,7 @@
 						d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
 					/>
 				</svg>
-				<div class="flex items-center">Settings</div>
+				<div class="flex items-center">{$i18n.t('Settings')}</div>
 			</DropdownMenu.Item>
 
 			{#if shareEnabled}
@@ -126,7 +129,7 @@
 							clip-rule="evenodd"
 						/>
 					</svg>
-					<div class="flex items-center">Share</div>
+					<div class="flex items-center">{$i18n.t('Share')}</div>
 				</DropdownMenu.Item>
 
 				<!-- <DropdownMenu.Item
@@ -154,7 +157,7 @@
 							/>
 						</svg>
 
-						<div class="flex items-center">Download</div>
+						<div class="flex items-center">{$i18n.t('Download')}</div>
 					</DropdownMenu.SubTrigger>
 					<DropdownMenu.SubContent
 						class="w-full rounded-lg px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-900 dark:text-white shadow-lg"
@@ -167,7 +170,7 @@
 								downloadTxt();
 							}}
 						>
-							<div class="flex items-center line-clamp-1">Plain text (.txt)</div>
+							<div class="flex items-center line-clamp-1">{$i18n.t('Plain text (.txt)')}</div>
 						</DropdownMenu.Item>
 
 						<DropdownMenu.Item
@@ -176,7 +179,7 @@
 								downloadPdf();
 							}}
 						>
-							<div class="flex items-center line-clamp-1">PDF document (.pdf)</div>
+							<div class="flex items-center line-clamp-1">{$i18n.t('PDF document (.pdf)')}</div>
 						</DropdownMenu.Item>
 					</DropdownMenu.SubContent>
 				</DropdownMenu.Sub>

+ 1 - 1
src/lib/components/layout/Sidebar.svelte

@@ -610,7 +610,7 @@
 										</button>
 									</ChatMenu>
 
-									<Tooltip content="Archive">
+									<Tooltip content={$i18n.t('Archive')}>
 										<button
 											aria-label="Archive"
 											class=" self-center dark:hover:text-white transition"

+ 4 - 1
src/lib/components/layout/Sidebar/ChatMenu.svelte

@@ -1,6 +1,7 @@
 <script lang="ts">
 	import { DropdownMenu } from 'bits-ui';
 	import { flyAndScale } from '$lib/utils/transitions';
+	import { getContext } from 'svelte'
 
 	import Dropdown from '$lib/components/common/Dropdown.svelte';
 	import GarbageBin from '$lib/components/icons/GarbageBin.svelte';
@@ -9,6 +10,8 @@
 	import Tags from '$lib/components/chat/Tags.svelte';
 	import Share from '$lib/components/icons/Share.svelte';
 
+	const i18n = getContext('i18n');
+
 	export let shareHandler: Function;
 	export let renameHandler: Function;
 	export let deleteHandler: Function;
@@ -27,7 +30,7 @@
 		}
 	}}
 >
-	<Tooltip content="More">
+	<Tooltip content={$i18n.t('More')}>
 		<slot />
 	</Tooltip>
 

+ 36 - 10
src/lib/i18n/locales/de-DE/translation.json

@@ -3,8 +3,6 @@
 	"(Beta)": "(Beta)",
 	"(e.g. `sh webui.sh --api`)": "(z.B. `sh webui.sh --api`)",
 	"(latest)": "(neueste)",
-	"{{modelName}} is thinking...": "{{modelName}} denkt nach...",
-	"{{webUIName}} Backend Required": "{{webUIName}}-Backend erforderlich",
 	"a user": "ein Benutzer",
 	"About": "Über",
 	"Account": "Account",
@@ -17,6 +15,8 @@
 	"Add Docs": "Dokumente hinzufügen",
 	"Add Files": "Dateien hinzufügen",
 	"Add message": "Nachricht eingeben",
+	"Add Model": "Modell hinzufügen",
+	"Add Tags": "Tags hinzufügen",
 	"add tags": "Tags hinzufügen",
 	"Adjusting these settings will apply changes universally to all users.": "Das Anpassen dieser Einstellungen wirkt sich universell auf alle Benutzer aus.",
 	"admin": "Administrator",
@@ -34,6 +34,7 @@
 	"API Base URL": "API Basis URL",
 	"API Key": "API Key",
 	"API RPM": "API RPM",
+	"Archive": "Archivieren",
 	"are allowed - Activate this command by typing": "sind erlaubt - Aktiviere diesen Befehl, indem du",
 	"Are you sure?": "Bist du sicher?",
 	"Audio": "Audio",
@@ -43,6 +44,7 @@
 	"AUTOMATIC1111 Base URL is required.": "",
 	"available!": "verfügbar!",
 	"Back": "Zurück",
+	"Bad Response": "Schlechte Antwort",
 	"Builder Mode": "Builder Modus",
 	"Cancel": "Abbrechen",
 	"Categories": "Kategorien",
@@ -71,7 +73,10 @@
 	"Connections": "Verbindungen",
 	"Content": "Inhalt",
 	"Context Length": "Context Length",
+	"Continue Response": "Antwort fortsetzen",
 	"Conversation Mode": "Konversationsmodus",
+	"Copied shared chat URL to clipboard!": "Geteilte Chat-URL in die Zwischenablage kopiert!",
+	"Copy": "Kopieren",
 	"Copy last code block": "Letzten Codeblock kopieren",
 	"Copy last response": "Letzte Antwort kopieren",
 	"Copying to clipboard was successful!": "Das Kopieren in die Zwischenablage war erfolgreich!",
@@ -95,12 +100,13 @@
 	"Default User Role": "Standardbenutzerrolle",
 	"delete": "löschen",
 	"Delete a model": "Ein Modell löschen",
+	"Delete Chat": "Chat löschen",
 	"Delete chat": "Chat löschen",
 	"Delete Chats": "Chats löschen",
-	"Deleted {{deleteModelTag}}": "{{deleteModelTag}} gelöscht",
+	"Delete User": "Benutzer löschen",
 	"Deleted {tagName}": "{tagName} gelöscht",
+	"Deleted {{deleteModelTag}}": "{{deleteModelTag}} gelöscht",
 	"Description": "Beschreibung",
-	"Notifications": "Desktop-Benachrichtigungen",
 	"Disabled": "Deaktiviert",
 	"Discover a modelfile": "Ein Modelfile entdecken",
 	"Discover a prompt": "Einen Prompt entdecken",
@@ -113,17 +119,18 @@
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "stellt keine externen Verbindungen her, und Deine Daten bleiben sicher auf Deinen lokal gehosteten Server.",
 	"Don't Allow": "Nicht erlauben",
 	"Don't have an account?": "Hast du vielleicht noch kein Konto?",
+	"Download": "Herunterladen",
 	"Download as a File": "Als Datei herunterladen",
 	"Download Database": "Datenbank herunterladen",
 	"Drop any files here to add to the conversation": "Ziehe Dateien in diesen Bereich, um sie an den Chat anzuhängen",
 	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "z.B. '30s','10m'. Gültige Zeiteinheiten sind 's', 'm', 'h'.",
+	"Edit": "Bearbeiten",
 	"Edit Doc": "Dokument bearbeiten",
 	"Edit User": "Benutzer bearbeiten",
 	"Email": "E-Mail",
 	"Enable Chat History": "Chat-Verlauf aktivieren",
 	"Enable New Sign Ups": "Neue Anmeldungen aktivieren",
 	"Enabled": "Aktiviert",
-	"Enter {{role}} message here": "Gib die {{role}} Nachricht hier ein",
 	"Enter API Key": "Gib den API-Schlüssel ein",
 	"Enter Chunk Overlap": "Gib den Chunk Overlap ein",
 	"Enter Chunk Size": "Gib die Chunk Size ein",
@@ -141,6 +148,7 @@
 	"Enter Your Email": "Gib deine E-Mail-Adresse ein",
 	"Enter Your Full Name": "Gib deinen vollständigen Namen ein",
 	"Enter Your Password": "Gib dein Passwort ein",
+	"Enter {{role}} message here": "Gib die {{role}} Nachricht hier ein",
 	"Experimental": "Experimentell",
 	"Export All Chats (All Users)": "Alle Chats exportieren (alle Benutzer)",
 	"Export Chats": "Chats exportieren",
@@ -156,6 +164,9 @@
 	"Full Screen Mode": "Vollbildmodus",
 	"General": "Allgemein",
 	"General Settings": "Allgemeine Einstellungen",
+	"Generation Info": "Generierungsinformationen",
+	"Good Response": "Gute Antwort",
+	"has no conversations.": "hat keine Unterhaltungen.",
 	"Hello, {{name}}": "Hallo, {{name}}",
 	"Hide": "Verbergen",
 	"Hide Additional Params": "Verstecke zusätzliche Parameter",
@@ -177,6 +188,7 @@
 	"Keep Alive": "Keep Alive",
 	"Keyboard shortcuts": "Tastenkürzel",
 	"Language": "Sprache",
+	"Last Active": "Zuletzt aktiv",
 	"Light": "Hell",
 	"Listening...": "Hören...",
 	"LLMs can make mistakes. Verify important information.": "LLMs können Fehler machen. Überprüfe wichtige Informationen.",
@@ -190,21 +202,22 @@
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",
 	"Mirostat Tau": "Mirostat Tau",
-	"MMMM DD, YYYY": "DD.MM.YYYY",
+	"MMMM DD, YYYY": "DD MMMM YYYY",
 	"Model '{{modelName}}' has been successfully downloaded.": "Modell '{{modelName}}' wurde erfolgreich heruntergeladen.",
 	"Model '{{modelTag}}' is already in queue for downloading.": "Modell '{{modelTag}}' befindet sich bereits in der Warteschlange zum Herunterladen.",
-	"Model {{modelId}} not found": "Modell {{modelId}} nicht gefunden",
-	"Model {{modelName}} already exists.": "Modell {{modelName}} existiert bereits.",
 	"Model Name": "Modellname",
 	"Model not selected": "Modell nicht ausgewählt",
 	"Model Tag Name": "Modell-Tag-Name",
 	"Model Whitelisting": "Modell-Whitelisting",
+	"Model {{modelId}} not found": "Modell {{modelId}} nicht gefunden",
+	"Model {{modelName}} already exists.": "Modell {{modelName}} existiert bereits.",
 	"Model(s) Whitelisted": "Modell(e) auf der Whitelist",
 	"Modelfile": "Modelfiles",
 	"Modelfile Advanced Settings": "Erweiterte Modelfileseinstellungen",
 	"Modelfile Content": "Modelfile Content",
 	"Modelfiles": "Modelfiles",
 	"Models": "Modelle",
+	"More": "Mehr",
 	"My Documents": "Meine Dokumente",
 	"My Modelfiles": "Meine Modelfiles",
 	"My Prompts": "Meine Prompts",
@@ -215,6 +228,7 @@
 	"New Password": "Neues Passwort",
 	"Not sure what to add?": "Nicht sicher, was hinzugefügt werden soll?",
 	"Not sure what to write? Switch to": "Nicht sicher, was Du schreiben sollst? Wechsel zu",
+	"Notifications": "Desktop-Benachrichtigungen",
 	"Off": "Aus",
 	"Okay, Let's Go!": "Okay, los geht's!",
 	"Ollama Base URL": "Ollama Basis URL",
@@ -235,9 +249,11 @@
 	"or": "oder",
 	"Parameters": "Parameter",
 	"Password": "Passwort",
+	"PDF document (.pdf)": "PDF-Dokument (.pdf)",
 	"PDF Extract Images (OCR)": "Text von Bildern aus PDFs extrahieren (OCR)",
 	"pending": "ausstehend",
 	"Permission denied when accessing microphone: {{error}}": "Zugriff auf das Mikrofon verweigert: {{error}}",
+	"Plain text (.txt)": "Nur Text (.txt)",
 	"Playground": "Playground",
 	"Profile": "Profil",
 	"Prompt Content": "Prompt-Inhalt",
@@ -248,8 +264,10 @@
 	"Query Params": "Query Parameter",
 	"RAG Template": "RAG-Vorlage",
 	"Raw Format": "Rohformat",
+	"Read Aloud": "Vorlesen",
 	"Record voice": "Stimme aufnehmen",
 	"Redirecting you to OpenWebUI Community": "Du wirst zur OpenWebUI-Community weitergeleitet",
+	"Regenerate": "Neu generieren",
 	"Release Notes": "Versionshinweise",
 	"Repeat Last N": "Repeat Last N",
 	"Repeat Penalty": "Repeat Penalty",
@@ -268,6 +286,7 @@
 	"Scan complete!": "Scan abgeschlossen!",
 	"Scan for documents from {{path}}": "Dokumente von {{path}} scannen",
 	"Search": "Suchen",
+	"Search a model": "Ein Modell suchen",
 	"Search Documents": "Dokumente suchen",
 	"Search Prompts": "Prompts suchen",
 	"See readme.md for instructions": "Anleitung in readme.md anzeigen",
@@ -287,6 +306,8 @@
 	"Set Voice": "Stimme festlegen",
 	"Settings": "Einstellungen",
 	"Settings saved successfully!": "Einstellungen erfolgreich gespeichert!",
+	"Share": "Teilen",
+	"Share Chat": "Chat teilen",
 	"Share to OpenWebUI Community": "Mit OpenWebUI Community teilen",
 	"short-summary": "kurze-zusammenfassung",
 	"Show": "Anzeigen",
@@ -333,6 +354,8 @@
 	"Type Hugging Face Resolve (Download) URL": "",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Ups! Es gab ein Problem bei der Verbindung mit {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Unbekannter Dateityp '{{file_type}}', wird jedoch akzeptiert und als einfacher Text behandelt.",
+	"Update and Copy Link": "Erneuern und kopieren",
+	"Update Embedding Model": "Embedding Modell aktualisieren",
 	"Update password": "Passwort aktualisieren",
 	"Upload a GGUF model": "GGUF Model hochladen",
 	"Upload files": "Dateien hochladen",
@@ -348,6 +371,7 @@
 	"variable": "Variable",
 	"variable to have them replaced with clipboard content.": "Variable, um den Inhalt der Zwischenablage beim Nutzen des Prompts zu ersetzen.",
 	"Version": "Version",
+	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Warnung: Wenn du dein Einbettungsmodell aktualisierst oder änderst, musst du alle Dokumente erneut importieren.",
 	"Web": "Web",
 	"WebUI Add-ons": "WebUI-Add-Ons",
 	"WebUI Settings": "WebUI-Einstellungen",
@@ -359,5 +383,7 @@
 	"Write a summary in 50 words that summarizes [topic or keyword].": "Schreibe eine kurze Zusammenfassung in 50 Wörtern, die [Thema oder Schlüsselwort] zusammenfasst.",
 	"You": "Du",
 	"You're a helpful assistant.": "Du bist ein hilfreicher Assistent.",
-	"You're now logged in.": "Du bist nun eingeloggt."
-}
+	"You're now logged in.": "Du bist nun eingeloggt.",
+	"{{modelName}} is thinking...": "{{modelName}} denkt nach...",
+	"{{webUIName}} Backend Required": "{{webUIName}}-Backend erforderlich"
+}

+ 2 - 2
src/routes/(app)/admin/+page.svelte

@@ -247,7 +247,7 @@
 															</button>
 														</Tooltip>
 
-														<Tooltip content="Edit User">
+														<Tooltip content={$i18n.t('Edit User')}>
 															<button
 																class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
 																on:click={async () => {
@@ -272,7 +272,7 @@
 															</button>
 														</Tooltip>
 
-														<Tooltip content="Delete User">
+														<Tooltip content={$i18n.t('Delete User')}>
 															<button
 																class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
 																on:click={async () => {

+ 1 - 1
src/routes/s/[id]/+page.svelte

@@ -145,7 +145,7 @@
 					</div>
 
 					<div class=" mt-1 text-gray-400">
-						{dayjs(chat.chat.timestamp).format('MMMM D, YYYY')}
+						{dayjs(chat.chat.timestamp).format($i18n.t('MMMM DD, YYYY'))}
 					</div>
 				</div>