Browse Source

Merge pull request #2794 from open-webui/dev

fix
Timothy Jaeryang Baek 11 months ago
parent
commit
8a94d8a226

+ 1 - 1
README.md

@@ -21,7 +21,7 @@ Open WebUI is an extensible, feature-rich, and user-friendly self-hosted WebUI d
 
 - 🤝 **Ollama/OpenAI API Integration**: Effortlessly integrate OpenAI-compatible APIs for versatile conversations alongside Ollama models. Customize the OpenAI API URL to link with **LMStudio, GroqCloud, Mistral, OpenRouter, and more**.
 
-- 🧩 **Pipelines, Open WebUI Plugin Support**: Seamlessly integrate custom logic and Python libraries into Open WebUI using [Pipelines Plugin Framework](https://github.com/open-webui/pipelines). Launch your Pipelines instance, set the OpenAI URL to the Pipelines URL, and explore endless possibilities. [Examples](https://github.com/open-webui/pipelines/examples) include **Function Calling**, User **Rate Limiting** to control access, **Usage Monitoring** with tools like Langfuse, **Live Translation with LibreTranslate** for multilingual support, **Toxic Message Filtering** and much more.
+- 🧩 **Pipelines, Open WebUI Plugin Support**: Seamlessly integrate custom logic and Python libraries into Open WebUI using [Pipelines Plugin Framework](https://github.com/open-webui/pipelines). Launch your Pipelines instance, set the OpenAI URL to the Pipelines URL, and explore endless possibilities. [Examples](https://github.com/open-webui/pipelines/tree/main/examples) include **Function Calling**, User **Rate Limiting** to control access, **Usage Monitoring** with tools like Langfuse, **Live Translation with LibreTranslate** for multilingual support, **Toxic Message Filtering** and much more.
 
 - 📱 **Responsive Design**: Enjoy a seamless experience across Desktop PC, Laptop, and Mobile devices.
 

+ 19 - 0
src/lib/components/icons/Keyboard.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	export let className = 'size-4';
+	export let strokeWidth = '2';
+</script>
+
+<svg
+	aria-hidden="true"
+	xmlns="http://www.w3.org/2000/svg"
+	fill="currentColor"
+	viewBox="0 0 24 24"
+	stroke-width={strokeWidth}
+	class={className}
+>
+	<path
+		fill-rule="evenodd"
+		d="M2 7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V7Zm5.01 1H5v2.01h2.01V8Zm3 0H8v2.01h2.01V8Zm3 0H11v2.01h2.01V8Zm3 0H14v2.01h2.01V8Zm3 0H17v2.01h2.01V8Zm-12 3H5v2.01h2.01V11Zm3 0H8v2.01h2.01V11Zm3 0H11v2.01h2.01V11Zm3 0H14v2.01h2.01V11Zm3 0H17v2.01h2.01V11Zm-12 3H5v2.01h2.01V14ZM8 14l-.001 2 8.011.01V14H8Zm11.01 0H17v2.01h2.01V14Z"
+		clip-rule="evenodd"
+	/>
+</svg>

+ 19 - 0
src/lib/components/icons/Lifebuoy.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	export let className = 'w-4 h-4';
+	export let strokeWidth = '2';
+</script>
+
+<svg
+	xmlns="http://www.w3.org/2000/svg"
+	fill="none"
+	viewBox="0 0 24 24"
+	stroke-width={strokeWidth}
+	stroke="currentColor"
+	class={className}
+>
+	<path
+		stroke-linecap="round"
+		stroke-linejoin="round"
+		d="M16.712 4.33a9.027 9.027 0 0 1 1.652 1.306c.51.51.944 1.064 1.306 1.652M16.712 4.33l-3.448 4.138m3.448-4.138a9.014 9.014 0 0 0-9.424 0M19.67 7.288l-4.138 3.448m4.138-3.448a9.014 9.014 0 0 1 0 9.424m-4.138-5.976a3.736 3.736 0 0 0-.88-1.388 3.737 3.737 0 0 0-1.388-.88m2.268 2.268a3.765 3.765 0 0 1 0 2.528m-2.268-4.796a3.765 3.765 0 0 0-2.528 0m4.796 4.796c-.181.506-.475.982-.88 1.388a3.736 3.736 0 0 1-1.388.88m2.268-2.268 4.138 3.448m0 0a9.027 9.027 0 0 1-1.306 1.652c-.51.51-1.064.944-1.652 1.306m0 0-3.448-4.138m3.448 4.138a9.014 9.014 0 0 1-9.424 0m5.976-4.138a3.765 3.765 0 0 1-2.528 0m0 0a3.736 3.736 0 0 1-1.388-.88 3.737 3.737 0 0 1-.88-1.388m2.268 2.268L7.288 19.67m0 0a9.024 9.024 0 0 1-1.652-1.306 9.027 9.027 0 0 1-1.306-1.652m0 0 4.138-3.448M4.33 16.712a9.014 9.014 0 0 1 0-9.424m4.138 5.976a3.765 3.765 0 0 1 0-2.528m0 0c.181-.506.475-.982.88-1.388a3.736 3.736 0 0 1 1.388-.88m-2.268 2.268L4.33 7.288m6.406 1.18L7.288 4.33m0 0a9.024 9.024 0 0 0-1.652 1.306A9.025 9.025 0 0 0 4.33 7.288"
+	/>
+</svg>

+ 19 - 0
src/lib/components/icons/QuestionMarkCircle.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	export let className = 'w-4 h-4';
+	export let strokeWidth = '2';
+</script>
+
+<svg
+	xmlns="http://www.w3.org/2000/svg"
+	fill="none"
+	viewBox="0 0 24 24"
+	stroke-width={strokeWidth}
+	stroke="currentColor"
+	class={className}
+>
+	<path
+		stroke-linecap="round"
+		stroke-linejoin="round"
+		d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 5.25h.008v.008H12v-.008Z"
+	/>
+</svg>

+ 40 - 0
src/lib/components/layout/Help.svelte

@@ -0,0 +1,40 @@
+<script lang="ts">
+	import { onMount, tick, getContext } from 'svelte';
+
+	const i18n = getContext('i18n');
+
+	import ShortcutsModal from '../chat/ShortcutsModal.svelte';
+	import Tooltip from '../common/Tooltip.svelte';
+	import HelpMenu from './Help/HelpMenu.svelte';
+
+	let showShortcuts = false;
+</script>
+
+<div class=" hidden lg:flex fixed bottom-0 right-0 px-2 py-2 z-10">
+	<button
+		id="show-shortcuts-button"
+		class="hidden"
+		on:click={() => {
+			showShortcuts = !showShortcuts;
+		}}
+	/>
+
+	<HelpMenu
+		showDocsHandler={() => {
+			showShortcuts = !showShortcuts;
+		}}
+		showShortcutsHandler={() => {
+			showShortcuts = !showShortcuts;
+		}}
+	>
+		<Tooltip content={$i18n.t('Help')} placement="left">
+			<button
+				class="text-gray-600 dark:text-gray-300 bg-gray-300/20 size-5 flex items-center justify-center text-[0.7rem] rounded-full"
+			>
+				?
+			</button>
+		</Tooltip>
+	</HelpMenu>
+</div>
+
+<ShortcutsModal bind:show={showShortcuts} />

+ 60 - 0
src/lib/components/layout/Help/HelpMenu.svelte

@@ -0,0 +1,60 @@
+<script lang="ts">
+	import { DropdownMenu } from 'bits-ui';
+	import { getContext } from 'svelte';
+
+	import { showSettings } from '$lib/stores';
+	import { flyAndScale } from '$lib/utils/transitions';
+
+	import Dropdown from '$lib/components/common/Dropdown.svelte';
+	import QuestionMarkCircle from '$lib/components/icons/QuestionMarkCircle.svelte';
+	import Lifebuoy from '$lib/components/icons/Lifebuoy.svelte';
+	import Keyboard from '$lib/components/icons/Keyboard.svelte';
+	const i18n = getContext('i18n');
+
+	export let showDocsHandler: Function;
+	export let showShortcutsHandler: Function;
+
+	export let onClose: Function = () => {};
+</script>
+
+<Dropdown
+	on:change={(e) => {
+		if (e.detail === false) {
+			onClose();
+		}
+	}}
+>
+	<slot />
+
+	<div slot="content">
+		<DropdownMenu.Content
+			class="w-full max-w-[200px] rounded-xl px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg"
+			sideOffset={4}
+			side="top"
+			align="end"
+			transition={flyAndScale}
+		>
+			<DropdownMenu.Item
+				class="flex gap-2 items-center px-3 py-2 text-sm  cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
+				id="chat-share-button"
+				on:click={() => {
+					window.open('https://docs.openwebui.com', '_blank');
+				}}
+			>
+				<QuestionMarkCircle className="size-5" />
+				<div class="flex items-center">{$i18n.t('Documentation')}</div>
+			</DropdownMenu.Item>
+
+			<DropdownMenu.Item
+				class="flex gap-2 items-center px-3 py-2 text-sm  cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
+				id="chat-share-button"
+				on:click={() => {
+					showShortcutsHandler();
+				}}
+			>
+				<Keyboard className="size-5" />
+				<div class="flex items-center">{$i18n.t('Keyboard shortcuts')}</div>
+			</DropdownMenu.Item>
+		</DropdownMenu.Content>
+	</div>
+</Dropdown>

+ 11 - 11
src/lib/i18n/locales/tr-TR/translation.json

@@ -3,7 +3,7 @@
 	"(Beta)": "(Beta)",
 	"(e.g. `sh webui.sh --api`)": "(örn. `sh webui.sh --api`)",
 	"(latest)": "(en son)",
-	"{{ models }}": "{{ modeller }}",
+	"{{ models }}": "{{ models }}",
 	"{{ owner }}: You cannot delete a base model": "{{ owner }}: Temel modeli silemezsiniz",
 	"{{modelName}} is thinking...": "{{modelName}} düşünüyor...",
 	"{{user}}'s Chats": "{{user}} Sohbetleri",
@@ -37,7 +37,7 @@
 	"All Users": "Tüm Kullanıcılar",
 	"Allow": "İzin ver",
 	"Allow Chat Deletion": "Sohbet Silmeye İzin Ver",
-	"Allow non-local voices": "",
+	"Allow non-local voices": "Yerel olmayan seslere izin verin",
 	"alphanumeric characters and hyphens": "alfanumerik karakterler ve tireler",
 	"Already have an account?": "Zaten bir hesabınız mı var?",
 	"an assistant": "bir asistan",
@@ -68,7 +68,7 @@
 	"Base Model (From)": "Temel Model ('den)",
 	"before": "önce",
 	"Being lazy": "Tembelleşiyor",
-	"Brave Search API Key": "Cesur Arama API Anahtarı",
+	"Brave Search API Key": "Brave Search API Anahtarı",
 	"Bypass SSL verification for Websites": "Web Siteleri için SSL doğrulamasını atlayın",
 	"Cancel": "İptal",
 	"Capabilities": "Yetenekler",
@@ -170,7 +170,7 @@
 	"Edit Doc": "Belgeyi Düzenle",
 	"Edit User": "Kullanıcıyı Düzenle",
 	"Email": "E-posta",
-	"Embedding Batch Size": "",
+	"Embedding Batch Size": "Gömme Yığın Boyutu",
 	"Embedding Model": "Gömme Modeli",
 	"Embedding Model Engine": "Gömme Modeli Motoru",
 	"Embedding model set to \"{{embedding_model}}\"": "Gömme modeli \"{{embedding_model}}\" olarak ayarlandı",
@@ -187,7 +187,7 @@
 	"Enter Chunk Size": "Chunk Boyutunu Girin",
 	"Enter Github Raw URL": "Github Raw URL'sini girin",
 	"Enter Google PSE API Key": "Google PSE API Anahtarını Girin",
-	"Enter Google PSE Engine Id": "Google PSE Motor Kimliğini Girin",
+	"Enter Google PSE Engine Id": "Google PSE Engine Id'sini Girin",
 	"Enter Image Size (e.g. 512x512)": "Görüntü Boyutunu Girin (örn. 512x512)",
 	"Enter language codes": "Dil kodlarını girin",
 	"Enter model tag (e.g. {{modelTag}})": "Model etiketini girin (örn. {{modelTag}})",
@@ -206,9 +206,9 @@
 	"Enter Your Role": "Rolünüzü Girin",
 	"Error": "Hata",
 	"Experimental": "Deneysel",
-	"Export": "Ihracat",
+	"Export": "Dışa Aktar",
 	"Export All Chats (All Users)": "Tüm Sohbetleri Dışa Aktar (Tüm Kullanıcılar)",
-	"Export chat (.json)": "",
+	"Export chat (.json)": "Sohbeti dışa aktar (.json)",
 	"Export Chats": "Sohbetleri Dışa Aktar",
 	"Export Documents Mapping": "Belge Eşlemesini Dışa Aktar",
 	"Export Models": "Modelleri Dışa Aktar",
@@ -232,7 +232,7 @@
 	"Generation Info": "Üretim Bilgisi",
 	"Good Response": "İyi Yanıt",
 	"Google PSE API Key": "Google PSE API Anahtarı",
-	"Google PSE Engine Id": "Google PSE Motor Kimliği",
+	"Google PSE Engine Id": "Google PSE Engine Id",
 	"h:mm a": "h:mm a",
 	"has no conversations.": "hiç konuşması yok.",
 	"Hello, {{name}}": "Merhaba, {{name}}",
@@ -292,7 +292,7 @@
 	"Model '{{modelTag}}' is already in queue for downloading.": "'{{modelTag}}' zaten indirme sırasında.",
 	"Model {{modelId}} not found": "{{modelId}} bulunamadı",
 	"Model {{modelName}} is not vision capable": "Model {{modelName}} görüntü yeteneğine sahip değil",
-	"Model {{name}} is now {{status}}": "{{name}} modeli artık {{status}} oldu",
+	"Model {{name}} is now {{status}}": "{{name}} modeli artık {{status}}",
 	"Model filesystem path detected. Model shortname is required for update, cannot continue.": "Model dosya sistemi yolu algılandı. Güncelleme için model kısa adı gerekli, devam edilemiyor.",
 	"Model ID": "Model ID",
 	"Model not selected": "Model seçilmedi",
@@ -347,8 +347,8 @@
 	"pending": "beklemede",
 	"Permission denied when accessing microphone: {{error}}": "Mikrofona erişim izni reddedildi: {{error}}",
 	"Personalization": "Kişiselleştirme",
-	"Pipelines": "Boru hattı",
-	"Pipelines Valves": "Boru Hatları Vanaları",
+	"Pipelines": "Pipelinelar",
+	"Pipelines Valves": "Pipeline Valvleri",
 	"Plain text (.txt)": "Düz metin (.txt)",
 	"Playground": "Oyun Alanı",
 	"Positive attitude": "Olumlu yaklaşım",

+ 3 - 17
src/routes/(app)/+layout.svelte

@@ -36,6 +36,7 @@
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import { getBanners } from '$lib/apis/configs';
 	import { getUserSettings } from '$lib/apis/users';
+	import Help from '$lib/components/layout/Help.svelte';
 
 	const i18n = getContext('i18n');
 
@@ -160,7 +161,7 @@
 				if (isCtrlPressed && event.key === '/') {
 					event.preventDefault();
 					console.log('showShortcuts');
-					showShortcutsButtonElement.click();
+					document.getElementById('show-shortcuts-button')?.click();
 				}
 			});
 
@@ -175,22 +176,7 @@
 	});
 </script>
 
-<div class=" hidden lg:flex fixed bottom-0 right-0 px-2 py-2 z-10">
-	<Tooltip content={$i18n.t('Help')} placement="left">
-		<button
-			id="show-shortcuts-button"
-			bind:this={showShortcutsButtonElement}
-			class="text-gray-600 dark:text-gray-300 bg-gray-300/20 size-5 flex items-center justify-center text-[0.7rem] rounded-full"
-			on:click={() => {
-				showShortcuts = !showShortcuts;
-			}}
-		>
-			?
-		</button>
-	</Tooltip>
-</div>
-
-<ShortcutsModal bind:show={showShortcuts} />
+<Help />
 <SettingsModal bind:show={$showSettings} />
 <ChangelogModal bind:show={$showChangelog} />