Compare commits

...
239 Commits
Author SHA1 Message Date
Timothy Jaeryang Baek ac294a74e7 Merge pull request #1277 from open-webui/dev
0.1.115
2024-03-24 18:20:08 -05:00
Timothy J. Baekandrob 4c9598918a doc: changelog
Co-Author: Fixed the upload experimental feature
Co-Authored-By: rob <64106559+kroonen@users.noreply.github.com>
2024-03-24 16:12:07 -07:00
Timothy Jaeryang Baek ffa168211e Merge pull request #1237 from lainedfles/debug_print
Migrate to python logging module with env var control.
2024-03-24 18:04:27 -05:00
Timothy Jaeryang Baek 371dfc1143 Merge branch 'dev' into debug_print 2024-03-24 18:04:03 -05:00
Timothy Jaeryang Baek a1faa307b1 Merge pull request #1272 from anuraagdjain/feat/cancel-model-download
feat: cancel model download
2024-03-24 18:00:57 -05:00
Timothy J. Baek a4c4a0370e refac: transition 2024-03-24 15:55:03 -07:00
Timothy J. Baek 3e0aa29683 refac: transition 2024-03-24 15:43:03 -07:00
Timothy J. Baek df21a92542 fix: select 2024-03-24 15:31:09 -07:00
Timothy J. Baek b218b02d93 feat: custom model selector 2024-03-24 15:28:36 -07:00
Timothy J. Baek ff8a55a861 refac: rag api 2024-03-24 00:41:41 -07:00
Timothy J. Baek 7e0ea8f77d feat: RAG text ingestion(store) api 2024-03-24 00:40:27 -07:00
Timothy J. Baek c2d6d3230b refac: reset vector db 2024-03-23 20:50:57 -07:00
Timothy J. Baek 8d108060d5 refac: styling 2024-03-23 18:08:33 -07:00
Timothy J. Baek 5cb6e9b0b4 refac: styling 2024-03-23 18:07:42 -07:00
Timothy J. Baek cea74eaf52 feat: light mode theme update 2024-03-23 18:05:36 -07:00
Timothy Jaeryang Baek adf9ccb5eb Merge pull request #1275 from open-webui/comfyui
feat: comfyui support
2024-03-23 19:01:51 -05:00
Timothy J. Baek 98624a406f feat: comfyui integration 2024-03-23 17:01:13 -07:00
Timothy J. Baek 862c96fcef feat: comfyui support 2024-03-23 15:38:59 -07:00
Timothy J. Baek cbaaacfb75 fix: styling 2024-03-23 13:36:11 -07:00
Timothy Jaeryang Baek 3e0d9ad74f Merge branch 'dev' into feat/cancel-model-download 2024-03-23 15:16:06 -05:00
Timothy J. Baek e008738f30 feat: cancel download from backend 2024-03-23 13:12:54 -07:00
Timothy J. Baek 244f34c24e refac: cancel download 2024-03-23 13:12:23 -07:00
Timothy J. Baek 642ca5a94a refac: ui 2024-03-23 12:46:06 -07:00
Timothy J. Baek 85187deb4b fix: languages order 2024-03-23 12:43:31 -07:00
Timothy Jaeryang Baek 3305ac5928 Merge pull request #1269 from pazoff/dev
added Italian, Portuguese and Japanese translations
2024-03-23 14:34:54 -05:00
Timothy Jaeryang Baek 51a4e49ae1 Merge pull request #1247 from changchiyou/enhance/zh_TW_translation
Enhance/zh tw translation
2024-03-23 14:34:28 -05:00
Timothy Jaeryang Baek 6c9f552733 Merge pull request #1271 from Axodouble/main
Added nl-NL (Dutch) Translations.
2024-03-23 14:33:54 -05:00
Anuraag Jain 7e6d499486 refac: remove conosle.log 2024-03-23 21:00:01 +02:00
Anuraag Jain d291821bf3 refac: delete button UI 2024-03-23 20:56:18 +02:00
Anuraag Jain 45311bfa15 Merge branch 'main' into feat/cancel-model-download
# Conflicts:
#	src/lib/components/chat/Settings/Models.svelte
2024-03-23 18:10:35 +02:00
changchiyou b03f4371d6 enhance: setting 2024-03-23 23:55:42 +08:00
Axodouble f662aab9e8 Finished Dutch translation. 2024-03-23 13:05:13 +01:00
Axodouble 129253d90d Added partial Dutch (Netherlands, NL) translations. 2024-03-23 12:23:05 +01:00
changchiyou 2d1b67561b enhance: routes/auth 2024-03-23 17:13:43 +08:00
changchiyou dca3dbbce6 enhance: admin 2024-03-23 17:07:35 +08:00
changchiyou e9f1a714e8 enhance: playground 2024-03-23 16:19:14 +08:00
Plamen Vatev d5b5155c20 add ja-JP (Japanese) translation 2024-03-23 07:29:07 +02:00
Plamen Vatev 6e79530e0e add Japanese translation 2024-03-23 07:27:24 +02:00
Plamen Vatev b0a2eb31ee add Portuguese translation 2024-03-23 07:00:40 +02:00
Plamen Vatev c0549498bf add Portuguese translation 2024-03-23 07:00:08 +02:00
Plamen Vatev f8a922e966 Merge branch 'open-webui:dev' into dev 2024-03-23 06:52:51 +02:00
Timothy J. Baek 5c1e3a460e fix: remove aiofiles dependency 2024-03-22 21:47:53 -07:00
Plamen Vatev bc04553a7c add Italian translation 2024-03-23 06:28:26 +02:00
Plamen Vatev c296e9061e add Italian translation 2024-03-23 06:22:53 +02:00
changchiyou e14ad508c9 enhance: e9a198d8ed 2024-03-23 10:14:47 +08:00
changchiyou e9a198d8ed enhance: routes/documents & components/documents/Settings/General.svelte 2024-03-23 10:12:11 +08:00
changchiyou cb0e858c04 enhance: routes/prompts 2024-03-23 09:44:56 +08:00
Timothy Jaeryang Baek 848d2382bc Merge pull request #1267 from Michelklingler/langfuse_dependency
Added langfuse dependency to the requierements.txt file.
2024-03-22 16:36:21 -05:00
Timothy Jaeryang Baek 106727109e Merge pull request #1258 from que-nguyen/main
Fixed Vietnamese translation for improved language quality
2024-03-22 16:20:39 -05:00
Timothy Jaeryang Baek c97051e6eb Merge pull request #1262 from pazoff/dev
Fixed spelling in Bulgarian translation
2024-03-22 16:20:11 -05:00
Michel K 4140e1b84a Added langfuse dependency to the requierements.txt file. 2024-03-22 14:01:39 -04:00
Plamen Vatev fe8a3ac2d7 Fix spelling 2024-03-22 17:49:25 +02:00
changchiyou b5111c4b34 enhance: routes/modelfiles
- `Modelfile` is a proprietary term of Ollama. `模型文件` is the Simplified Chinese translation used in their community but not common used in zh-TW community.
- `Prompt`'s better zh-TW translation is `提示詞`(refert to https://docs.aws.amazon.com/zh_tw/bedrock/latest/userguide/what-is-prompt-engineering.html ) instead of `提示`, which is easily misunderstood as a verb `建議`
2024-03-22 17:17:22 +08:00
Timothy J. Baek 92cc87d908 fix: ollama upload url 2024-03-22 00:58:38 -07:00
Timothy J. Baek 9e37d6edcc refac: gguf upload ui 2024-03-22 00:55:59 -07:00
Timothy J. Baek 77ec296ac3 chore: print removed 2024-03-22 00:11:17 -07:00
Timothy J. Baek bc80f1438c fix: ollama gguf upload 2024-03-22 00:10:55 -07:00
Timothy J. Baek af4caec4f5 refac: ollama gguf upload 2024-03-21 23:45:00 -07:00
Que Nguyen c5e9ceeb06 Merge branch 'open-webui:main' into main 2024-03-22 10:43:03 +07:00
Que Nguyen 47a04a7e3c Fixed Vietnamese translation for improved language quality 2024-03-22 10:42:38 +07:00
Timothy Jaeryang Baek c54fb92263 Merge pull request #1249 from pazoff/dev
added Bulgarian Translation
2024-03-21 16:29:25 -05:00
Timothy J. Baek f3c113cb04 fix: languages order 2024-03-21 14:29:05 -07:00
Plamen Vatev 5f26b2a9e3 added bg-BG (Bulgarian) 2024-03-21 17:43:31 +02:00
Plamen Vatev 8935dca279 added Bulgarian Translation 2024-03-21 17:14:59 +02:00
changchiyou f675a18b05 enhance: i18n's zh-TW translation for About.svelte 2024-03-21 19:38:42 +08:00
Self Denial f74f2ea765 Merge conflicts 2024-03-21 00:14:13 -06:00
Timothy Jaeryang Baek 5a90e90c0b Merge pull request #1241 from 7a6ac0/duplicate_def
fix: delete duplicate function
2024-03-20 22:01:13 -05:00
Timothy Jaeryang Baek 2fa94956f4 Merge pull request #1209 from open-webui/dev
0.1.114
2024-03-20 21:34:22 -05:00
Timothy J. Baek 8e52ba8b91 refac: auth required for litellm in dev 2024-03-20 19:33:27 -07:00
Timothy J. Baek ed0d4b5a2a chore: comment clean up 2024-03-20 19:32:25 -07:00
tabaco.wang a1412d0b55 fix: delete duplicate function 2024-03-21 10:31:25 +08:00
Timothy J. Baek 1a240e103e doc: changelog 2024-03-20 19:31:15 -07:00
Timothy J. Baek 93c90dc186 feat: litellm model filter support 2024-03-20 19:28:33 -07:00
Timothy J. Baek 8cb7127fbc doc: changelog 2024-03-20 19:01:20 -07:00
Timothy J. Baek 4b91ac352a chore: i18n alphabetically ordering 2024-03-20 18:52:24 -07:00
Timothy Jaeryang Baek 09dc3b7b67 Merge pull request #1226 from marionguyen/main
Added Vietnamese translation files
2024-03-20 20:49:27 -05:00
Timothy J. Baek bdc51b45ec Update translation.json 2024-03-20 18:49:08 -07:00
Timothy Jaeryang Baek 6313a98287 Merge branch 'dev' into main 2024-03-20 20:48:26 -05:00
Timothy Jaeryang Baek ae347bb5e7 Merge pull request #1239 from open-webui/webhook
feat: webhook
2024-03-20 20:47:46 -05:00
Timothy J. Baek fa65be2ad2 refac: post webhook 2024-03-20 18:47:13 -07:00
Timothy J. Baek 2481e48a3a feat: webhook settings frontend 2024-03-20 18:35:54 -07:00
Timothy J. Baek 2c6e2d5e8a feat: webhook backend 2024-03-20 18:35:02 -07:00
Self Denial e6dd0bfbe0 Migrate to python logging module with env var control. 2024-03-20 17:11:36 -06:00
Que Nguyen b22ed64770 Added Vietnamese translation files 2024-03-20 11:31:44 +07:00
Timothy Jaeryang Baek 16fe0ee167 Merge pull request #1151 from changchiyou/feat/custom_default_user_permissions_chat_deletion
Feat/custom default user permissions chat deletion
2024-03-19 16:23:23 -05:00
Timothy J. Baek 87344adf29 refac 2024-03-19 14:21:46 -07:00
Timothy J. Baek 349fd0c87d refac: config.json 2024-03-19 14:03:46 -07:00
Timothy Jaeryang Baek d4a11ca33f Merge pull request #1220 from justinh-rahb/fix-messsage
Fix spelling
2024-03-19 15:17:06 -05:00
Justin Hayes bd84ee0c6a Fix spelling 2024-03-19 15:06:45 -04:00
Timothy J. Baek a9e411fdb9 fix: languages 2024-03-19 11:46:48 -07:00
Timothy Jaeryang Baek de8de7e008 Merge pull request #1217 from justinh-rahb/french
French (Canada) translations added, some French (France) strings updated/changed
2024-03-19 13:45:53 -05:00
Timothy Jaeryang Baek 63edaae8d8 Merge pull request #1219 from djismgaming/spanish-translation
Spanish translation
2024-03-19 13:44:47 -05:00
Timothy Jaeryang Baek d3cf9a7535 Merge pull request #1215 from granludo/main
Added Catalan translation
2024-03-19 13:42:53 -05:00
Ismael 7c8727151e spanish translation of the webui 2024-03-19 14:12:04 -04:00
Justin Hayes c3f805b809 Fix capitalization of words 2024-03-19 12:24:12 -04:00
Justin Hayes 8508319c23 Revert "Change some fr-FR strings"
This reverts commit b21091bc01.
2024-03-19 12:07:16 -04:00
Justin Hayes b9382f7051 Update languages.json 2024-03-19 11:51:52 -04:00
Justin Hayes 53fb3d9c3e Add fr-CA translations.json 2024-03-19 11:51:36 -04:00
Justin Hayes b21091bc01 Change some fr-FR strings 2024-03-19 11:51:21 -04:00
Ludo (Marc Alier) 4de591b930 added catalan to "languages.json" added proper code "ca-ES" 2024-03-19 15:26:02 +01:00
Ludo (Marc Alier) 492d4f3403 Added Catalan translation 2024-03-19 11:27:46 +01:00
Timothy J. Baek 0b163c2c2d Update translation.json 2024-03-19 00:30:44 -07:00
Timothy Jaeryang Baek 7bb8e91edb Merge pull request #1207 from officialsahyaboutorabi/patch-4
Update languages.json
2024-03-19 02:28:53 -05:00
Timothy Jaeryang Baek 49faff497e Merge pull request #1206 from officialsahyaboutorabi/patch-3
Create translation.json
2024-03-19 02:28:14 -05:00
Timothy Jaeryang Baek 33888ffaf8 Merge pull request #1205 from adan89lion/patch-1
Enhance Traditional Chinese translation
2024-03-19 02:27:17 -05:00
officialsahyaboutorabi b10eb0dacc Update languages.json 2024-03-19 16:14:34 +11:00
officialsahyaboutorabi 7f197a70f9 Create translation.json
For Russian language.
2024-03-19 16:13:20 +11:00
Ismael 61b4ab1e63 spanish translation of the webui 2024-03-18 22:44:38 -04:00
Ismael 51342179ad feat: Add support for Spanish language option in WebUI Settings 2024-03-18 22:44:05 -04:00
Seohyun Joo f1925841e2 Enhance Traditional Chinese translation
Correct some machine translation mistakes, and convert Mainland China's regional expression to Taiwan.
2024-03-19 10:17:54 +08:00
Timothy J. Baek e86db74333 refac: stream default value 2024-03-18 18:14:05 -07:00
Timothy J. Baek c569280806 fix: styling 2024-03-18 17:46:16 -07:00
Timothy J. Baek bc5d322cbb fix: add doc modal styling 2024-03-18 17:03:08 -07:00
Timothy Jaeryang Baek d865b9fe59 Merge pull request #1199 from open-webui/dev
fix: openai proxy issue
2024-03-18 13:04:53 -05:00
Timothy J. Baek b188143f01 fix: openai proxy issue 2024-03-18 11:04:22 -07:00
Timothy Jaeryang Baek 621719c6ac Merge pull request #1187 from open-webui/dev
0.1.113
2024-03-18 13:02:46 -05:00
Timothy J. Baek ec9895a14a fix: openai proxy issue 2024-03-18 11:02:09 -07:00
Timothy J. Baek 212e051683 doc: changelog 2024-03-18 11:00:38 -07:00
Timothy J. Baek 47081011d6 doc: readme 2024-03-18 10:51:45 -07:00
Timothy J. Baek c94d72bca8 fix: sidebar menu 2024-03-18 10:49:39 -07:00
Timothy Jaeryang Baek c3dd11de16 Merge pull request #1196 from fbirlik/patch-autoscrolldisable
fix: auto scroll fails to stop with small scroll amounts
2024-03-18 11:57:34 -05:00
Timothy Jaeryang Baek 1f0dcb4fce Merge pull request #1115 from dannyl1u/feat/system-wide-theme
feat: system os light/dark mode option 🔦
2024-03-18 11:55:45 -05:00
Timothy J. Baek 1bfcd801b7 fix: multiple openai issue 2024-03-18 01:11:48 -07:00
Timothy J. Baek 19f69c821f refac: code convention 2024-03-18 00:31:43 -07:00
Timothy J. Baek 8f8a68e002 refac: unnecessary code 2024-03-18 00:30:08 -07:00
Timothy J. Baek 94c845d71f refac 2024-03-18 00:27:48 -07:00
Firat Birlik adbcb06892 fix: auto scroll fails to stop with small scroll amounts 2024-03-18 00:08:45 -05:00
Danny Liu 3c01932a78 run prettier 2024-03-17 01:00:38 -07:00
Danny Liu a57586a2b7 use IIFE in app.html to prevent FOUC 2024-03-17 00:25:33 -07:00
Danny Liu 41cb6d7a54 remove duplicate "System" in select menu 2024-03-17 00:06:59 -07:00
Danny Liu 549408d808 Add setContext import to +layout.svelte 2024-03-16 23:59:09 -07:00
Danny Liu f25a967a0b add system theme ⚙️ option to select menu 2024-03-16 23:54:18 -07:00
Danny Liu f55dae3027 fix merge conflict 2024-03-16 23:27:08 -07:00
Danny Liu db0712aefd Merge branch 'dev' into feat/system-wide-theme 2024-03-16 23:23:56 -07:00
Danny Liu f1716f45b9 add event listener in app.html to handle system theme changes 2024-03-16 23:14:38 -07:00
Danny Liu 6f3acb347d update theme handling and persist selection using Svelte store 2024-03-16 23:14:13 -07:00
Timothy J. Baek e414b9ea6d fix: typo 2024-03-16 03:28:02 -07:00
Timothy J. Baek 1e03871748 fix: openai issue 2024-03-16 03:25:20 -07:00
Timothy J. Baek f90236f521 doc: demo.gif 2024-03-16 03:22:37 -07:00
Timothy J. Baek cf82aa9268 Update README.md 2024-03-16 03:01:43 -07:00
Timothy Jaeryang Baek ddb654f293 Merge pull request #1099 from zhecho/feat/helm-labels-and-lb-class
feat(helm): adding lb class and labels for using it with Cilium CNI l…
2024-03-16 04:50:49 -05:00
Timothy J. Baek ed964260ba fix: openai urls issue 2024-03-16 02:45:24 -07:00
Timothy J. Baek a636e784bc fix: styling 2024-03-16 02:43:51 -07:00
Timothy J. Baek ffeae78b88 feat: chat menu tooltip added 2024-03-16 02:35:40 -07:00
Timothy J. Baek 79a02b85a8 refac: chat menu styling 2024-03-16 02:34:27 -07:00
Timothy Jaeryang Baek 36a5588957 Merge pull request #926 from asedmammad/feat/add-i18n
Add i18n
2024-03-16 04:30:22 -05:00
Timothy J. Baek e664c38377 refac: settings styling 2024-03-16 02:24:32 -07:00
Timothy J. Baek 264eb28455 fix: styling 2024-03-16 02:16:24 -07:00
Timothy J. Baek 06f7cba401 Update package-lock.json 2024-03-16 02:10:19 -07:00
Timothy J. Baek df55ced0c0 Merge branch 'dev' into pr/926 2024-03-16 02:08:02 -07:00
Timothy J. Baek 71def5c4cb feat: sidebar ui update 2024-03-16 01:57:26 -07:00
Timothy J. Baek d6905d6297 feat: sidebar ui update 2024-03-16 00:27:29 -07:00
Timothy J. Baek 91efd6cb63 fix: file upload encoding issue 2024-03-15 23:52:37 -07:00
Ased Mammad d6e89d074d Update Ukranian translation 2024-03-15 15:14:07 +03:30
Ased Mammad f9bc35a11c fix: Ternary expression workaround for i18n:parse 2024-03-15 12:30:49 +03:30
Ased Mammad b85385385a Update uk translation 2024-03-14 23:42:30 +03:30
Ased Mammad aeb265c789 Update persian translation + run i18n:parse 2024-03-14 23:35:09 +03:30
Jannik Streidl 1e590b79cf added uk keys 2024-03-14 20:52:52 +01:00
Jannik Streidl c0de658dac uk key dix 2024-03-14 20:32:59 +01:00
Jannik Streidl a65d042c73 title fix + new translation keys 2024-03-14 20:30:30 +01:00
Jannik Streidl e99ab95987 maybe this matches better.. im done 2024-03-14 17:29:37 +01:00
Jannik Streidl dd22f1aebc ..and the icon 2024-03-14 17:28:00 +01:00
Jannik Streidl 81fba4774b typo 2024-03-14 17:20:56 +01:00
Jannik Streidl 8a23704138 added changelog entry 2024-03-14 17:19:39 +01:00
Jannik Streidl 5d6182eb7f sorted 2024-03-14 14:43:17 +01:00
Jannik Streidl fafe42e487 more missing translation keys 2024-03-14 14:40:52 +01:00
Jannik Streidl ccc1c81256 added missing translation keys 2024-03-14 14:38:05 +01:00
Jannik Streidl dbdc602791 added simplified + traditional chinese, updates uk keys, changed standart language code format to xx-XX 2024-03-14 12:10:04 +01:00
Jannik Streidl aa3985e879 merged from main and added new translation keys 2024-03-14 09:42:37 +01:00
Jannik Streidl 2a5bc2b2ad added chinese 2024-03-14 09:29:02 +01:00
changchiyou c6e14ce327 refactor: restrict the scope of USER_PERMISSIONS_CHAT_DELETION
it can easily confuse people before becuase when people accidentally set `env.USER_PERMISSIONS_CHAT_DELETION` to `true/yes/Yes`, `USER_PERMISSIONS["chat"]["deletion"]` would become `False`, which is unexpectedly and hard to notice.
2024-03-14 00:01:46 +08:00
changchiyou 04e3b168a6 config: allow custom default user permissions - chat deletion
Allow Chat Deletion
2024-03-13 23:17:22 +08:00
Ased Mammad 1091ee5a9b fix: Typo 2024-03-11 18:54:31 +03:30
Ased Mammad 78f79ef670 Update persian translation with new dev features 2024-03-11 01:04:22 +03:30
Ased Mammad 7545a717ff Add more translation keys 2024-03-10 22:31:10 +03:30
Ased Mammad b8902072fd Merge branch 'dev' into feat/add-i18n 2024-03-10 22:02:16 +03:30
Danny Liu 27153ddb03 remove unused variable 2024-03-09 13:12:15 -08:00
Danny Liu b94dc767ff implement system wide light/dark mode option 🔦 2024-03-09 12:17:47 -08:00
Ased Mammad 6e57fda8f4 fix: Whisper French translation 2024-03-09 15:18:14 +03:30
Ased Mammad f221e39c24 Merge remote-tracking branch 'upstream/dev' into feat/add-i18n 2024-03-09 05:26:39 +03:30
Ased Mammad c7ca7d03ee Add more translations 2024-03-09 04:03:53 +03:30
Ased Mammad 90513941bc feat: add i18n:parser script to package.json 2024-03-09 03:40:32 +03:30
Ased Mammad e8ffb2c023 fix: configure i18next to not return empty strings 2024-03-09 03:33:20 +03:30
Ased Mammad 48e8b45dc9 fix: issue with nbsp in i18next-parser 2024-03-09 03:11:45 +03:30
Zhecho Zhechev 3c4cc60277 feat(helm): adding lb class and labels for using it with Cilium CNI l2 annoncements mode 2024-03-08 10:09:21 +02:00
Ased Mammad f605bd96be Update translations 2024-03-07 23:24:15 +03:30
Ased Mammad f73cae2a73 format some files with prettier 2024-03-07 22:21:00 +03:30
Ased Mammad 3fa5144cf6 fix: Add missing english translations 2024-03-07 20:39:43 +03:30
Jannik Streidl 275a8256bb second merge 2024-03-07 18:04:50 +01:00
Jannik Streidl d4c8a7dab2 merge 2024-03-07 17:58:43 +01:00
Ased Mammad 1f2d704f76 fix: Add missing translations in admin setting 2024-03-07 20:27:52 +03:30
Jannik Streidl 12c74b2cd1 select fix + uk update 2024-03-07 17:56:57 +01:00
Ased Mammad fcc6189091 fix: Update uk translations 2024-03-07 20:24:44 +03:30
Jannik Streidl 93ed5851ca spelling + changed to hardcoded text 2024-03-07 16:37:37 +01:00
Jannik Streidl d40fbcd06b added margin 2024-03-07 16:21:56 +01:00
Jannik Streidl 8c596ea2fc only show the info when language = en (makes more sense to me) 2024-03-07 16:02:14 +01:00
Jannik Streidl 0d127ffef1 merged conflicts 2024-03-07 15:47:15 +01:00
Jannik Streidl f5afb0ca52 contribution info in the settings 2024-03-07 15:41:18 +01:00
Ased Mammad f7e10e1fb6 Update translations 2024-03-07 16:35:56 +03:30
Ased Mammad 03690de773 fix: disable i18next debug 2024-03-07 16:23:17 +03:30
Ased Mammad 80e2125266 add missing types 2024-03-07 16:23:17 +03:30
Ased Mammad 7031aa14e8 Merge branch 'dev' into feat/add-i18n 2024-03-07 15:41:42 +03:30
Ased Mammad 08aa60b33e feat: auto add translation keys to json
Uses i18next-parser to automatically extract translation keys
from js and svelte files.
2024-03-07 15:21:37 +03:30
Ased Mammad f55525c680 fix: load languages in an exported function 2024-03-07 14:10:30 +03:30
Ased Mammad c724e19e62 add new persian translations 2024-03-07 13:27:09 +03:30
Ased Mammad b76eb46d86 docs: Update contributing.md 2024-03-07 13:20:00 +03:30
Ased Mammad f4a1885298 feat: Get available languages from json file 2024-03-07 13:08:37 +03:30
Ased Mammad 41378748b8 refac: Move store to i18n index 2024-03-07 13:08:37 +03:30
Jannik Streidl 6a271a1691 fix: spelling 2024-03-06 20:55:07 +01:00
Ased Mammad 213e08a8a5 feat: add French translation 2024-03-06 20:03:33 +03:30
Ased Mammad 25e0f0de42 Merge remote-tracking branch 'upstream/dev' into feat/add-i18n 2024-03-06 01:25:29 +03:30
Ased Mammad df8aeb39c6 docs: Add translations section to contributing.md 2024-03-05 18:17:52 +03:30
Jannik Streidl 2b3c8194eb fix: type 2024-03-05 15:39:57 +01:00
Jannik Streidl 71dba592bf changed some german spelling 2024-03-05 14:24:03 +01:00
Jannik Streidl 31fc9a04b6 Merge branch 'feat/add-i18n' of https://github.com/asedmammad/open-webui into feat/add-i18n 2024-03-05 14:06:47 +01:00
Jannik Streidl 53f69ace6c fixed you var + added ua translation for the new playground 2024-03-05 14:06:27 +01:00
Ased Mammad 66342140a3 fix: use translation key as fallback + more translations 2024-03-05 15:28:54 +03:30
Jannik Streidl b5b860f575 add: ukrainian translation 2024-03-05 11:52:07 +01:00
Jannik Streidl 7f9049c3a1 add: added Playground + AddFilesPlaceholder translation 2024-03-05 11:44:37 +01:00
Jannik Streidl b9f53abf37 fix: show translated user role in admin panel 2024-03-05 09:30:00 +01:00
Jannik Streidl fcb991db63 fix: darkmode for selects 2024-03-05 09:15:22 +01:00
Ased Mammad 5f5b6ec141 feat: add persian translation for new keys 2024-03-05 00:47:43 +03:30
Jannik Streidl 4d67dd977d sidebar tooltop translation 2024-03-04 14:53:34 +01:00
Ased Mammad ec8f229f5a fix: make translation key naming consistent 2024-03-04 16:48:08 +03:30
Jannik Streidl d4fd6c5a57 merged new updates 2024-03-04 11:53:09 +01:00
Jannik Streidl 7a79aab5d4 (probably) last transition vars + Theme select element bg and icon fix 2024-03-04 11:15:54 +01:00
Jannik Streidl 3fe5f00114 more translations 2024-03-04 09:53:56 +01:00
Jannik Streidl 304006aa8c typo 2024-03-03 12:22:54 +01:00
Jannik Streidl 893b738cbf german translations + new vars 2024-03-03 12:22:29 +01:00
Ased Mammad 670b65c066 fix: add missed imports 2024-03-03 13:34:26 +03:30
Ased Mammad 6d2f462090 fix: add missed translations 2024-03-03 13:31:34 +03:30
Ased Mammad da0202851f feat: add farsi translation file v1 2024-03-03 01:45:18 +03:30
Ased Mammad 45f6908154 fix: Minor fixes in english translation file 2024-03-03 01:43:49 +03:30
Ased Mammad fbed07f651 fix: Merge similar string literals 2024-03-03 01:23:41 +03:30
Ased Mammad 511b52f642 feat: Add translation file for english 2024-03-03 01:12:32 +03:30
Ased Mammad 3c471ee2ca feat: Migrate hardcoded strings to i18n calls 2024-03-03 00:56:24 +03:30
Ased Mammad 7a77f3c2c0 feat: Change translation keys to fallback strings 2024-03-02 14:47:41 +03:30
Ased Mammad fab89a76b1 feat: WIP: Initial setup for i18next 2024-03-02 14:47:37 +03:30
Anuraag Jain ae97a96379 WIP feat: cancel model download 2024-02-18 21:29:47 +02:00
123 changed files with 12650 additions and 4370 deletions
+1 -1
View File
@@ -166,7 +166,7 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.idea/
# Logs
logs
+54
View File
@@ -5,6 +5,60 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.1.115] - 2024-03-24
### Added
- **🔍 Custom Model Selector**: Easily find and select custom models with the new search filter feature.
- **🛑 Cancel Model Download**: Added the ability to cancel model downloads.
- **🎨 Image Generation ComfyUI**: Image generation now supports ComfyUI.
- **🌟 Updated Light Theme**: Updated the light theme for a fresh look.
- **🌍 Additional Language Support**: Now supporting Bulgarian, Italian, Portuguese, Japanese, and Dutch.
### Fixed
- **🔧 Fixed Broken Experimental GGUF Upload**: Resolved issues with experimental GGUF upload functionality.
### Changed
- **🔄 Vector Storage Reset Button**: Moved the reset vector storage button to document settings.
## [0.1.114] - 2024-03-20
### Added
- **🔗 Webhook Integration**: Now you can subscribe to new user sign-up events via webhook. Simply navigate to the admin panel > admin settings > webhook URL.
- **🛡️ Enhanced Model Filtering**: Alongside Ollama, OpenAI proxy model whitelisting, we've added model filtering functionality for LiteLLM proxy.
- **🌍 Expanded Language Support**: Spanish, Catalan, and Vietnamese languages are now available, with improvements made to others.
### Fixed
- **🔧 Input Field Spelling**: Resolved issue with spelling mistakes in input fields.
- **🖊️ Light Mode Styling**: Fixed styling issue with light mode in document adding.
### Changed
- **🔄 Language Sorting**: Languages are now sorted alphabetically by their code for improved organization.
## [0.1.113] - 2024-03-18
### Added
- 🌍 **Localization**: You can now change the UI language in Settings > General. We support Ukrainian, German, Farsi (Persian), Traditional and Simplified Chinese and French translations. You can help us to translate the UI into your language! More info in our [CONTRIBUTION.md](https://github.com/open-webui/open-webui/blob/main/docs/CONTRIBUTING.md#-translations-and-internationalization).
- 🎨 **System-wide Theme**: Introducing a new system-wide theme for enhanced visual experience.
### Fixed
- 🌑 **Dark Background on Select Fields**: Improved readability by adding a dark background to select fields, addressing issues on certain browsers/devices.
- **Multiple OPENAI_API_BASE_URLS Issue**: Resolved issue where multiple base URLs caused conflicts when one wasn't functioning.
- **RAG Encoding Issue**: Fixed encoding problem in RAG.
- **npm Audit Fix**: Addressed npm audit findings.
- **Reduced Scroll Threshold**: Improved auto-scroll experience by reducing the scroll threshold from 50px to 5px.
### Changed
- 🔄 **Sidebar UI Update**: Updated sidebar UI to feature a chat menu dropdown, replacing two icons for improved navigation.
## [0.1.112] - 2024-03-15
### Fixed
+3 -1
View File
@@ -11,7 +11,7 @@
[![Discord](https://img.shields.io/badge/Discord-Open_WebUI-blue?logo=discord&logoColor=white)](https://discord.gg/5rJgQTnV4s)
[![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/tjbck)
User-friendly WebUI for LLMs, supported LLM runners include Ollama and OpenAI-compatible APIs. For more information, be sure to check out our [Open WebUI Documentation](https://docs.openwebui.com/).
Open WebUI is an extensible, feature-rich, and user-friendly self-hosted WebUI designed to operate entirely offline. It supports various LLM runners, including Ollama and OpenAI-compatible APIs. For more information, be sure to check out our [Open WebUI Documentation](https://docs.openwebui.com/).
![Open WebUI Demo](./demo.gif)
@@ -79,6 +79,8 @@ User-friendly WebUI for LLMs, supported LLM runners include Ollama and OpenAI-co
- 🔒 **Backend Reverse Proxy Support**: Bolster security through direct communication between Open WebUI backend and Ollama. This key feature eliminates the need to expose Ollama over LAN. Requests made to the '/ollama/api' route from the web UI are seamlessly redirected to Ollama from the backend, enhancing overall system security.
- 🌐🌍 **Multilingual Support**: Experience Open WebUI in your preferred language with our internationalization (i18n) support. Join us in expanding our supported languages! We're actively seeking contributors!
- 🌟 **Continuous Updates**: We are committed to improving Open WebUI with regular updates and new features.
## 🔗 Also Check Out Open WebUI Community!
+8 -4
View File
@@ -1,4 +1,5 @@
import os
import logging
from fastapi import (
FastAPI,
Request,
@@ -21,7 +22,10 @@ from utils.utils import (
)
from utils.misc import calculate_sha256
from config import CACHE_DIR, UPLOAD_DIR, WHISPER_MODEL, WHISPER_MODEL_DIR
from config import SRC_LOG_LEVELS, CACHE_DIR, UPLOAD_DIR, WHISPER_MODEL, WHISPER_MODEL_DIR
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["AUDIO"])
app = FastAPI()
app.add_middleware(
@@ -38,7 +42,7 @@ def transcribe(
file: UploadFile = File(...),
user=Depends(get_current_user),
):
print(file.content_type)
log.info(f"file.content_type: {file.content_type}")
if file.content_type not in ["audio/mpeg", "audio/wav"]:
raise HTTPException(
@@ -62,7 +66,7 @@ def transcribe(
)
segments, info = model.transcribe(file_path, beam_size=5)
print(
log.info(
"Detected language '%s' with probability %f"
% (info.language, info.language_probability)
)
@@ -72,7 +76,7 @@ def transcribe(
return {"text": transcript.strip()}
except Exception as e:
print(e)
log.exception(e)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
+107 -13
View File
@@ -18,6 +18,8 @@ from utils.utils import (
get_current_user,
get_admin_user,
)
from apps.images.utils.comfyui import ImageGenerationPayload, comfyui_generate_image
from utils.misc import calculate_sha256
from typing import Optional
from pydantic import BaseModel
@@ -25,10 +27,14 @@ from pathlib import Path
import uuid
import base64
import json
import logging
from config import CACHE_DIR, AUTOMATIC1111_BASE_URL
from config import SRC_LOG_LEVELS, CACHE_DIR, AUTOMATIC1111_BASE_URL, COMFYUI_BASE_URL
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["IMAGES"])
IMAGE_CACHE_DIR = Path(CACHE_DIR).joinpath("./image/generations/")
IMAGE_CACHE_DIR.mkdir(parents=True, exist_ok=True)
@@ -49,6 +55,8 @@ app.state.MODEL = ""
app.state.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL
app.state.COMFYUI_BASE_URL = COMFYUI_BASE_URL
app.state.IMAGE_SIZE = "512x512"
app.state.IMAGE_STEPS = 50
@@ -71,32 +79,48 @@ async def update_config(form_data: ConfigUpdateForm, user=Depends(get_admin_user
return {"engine": app.state.ENGINE, "enabled": app.state.ENABLED}
class UrlUpdateForm(BaseModel):
url: str
class EngineUrlUpdateForm(BaseModel):
AUTOMATIC1111_BASE_URL: Optional[str] = None
COMFYUI_BASE_URL: Optional[str] = None
@app.get("/url")
async def get_automatic1111_url(user=Depends(get_admin_user)):
return {"AUTOMATIC1111_BASE_URL": app.state.AUTOMATIC1111_BASE_URL}
async def get_engine_url(user=Depends(get_admin_user)):
return {
"AUTOMATIC1111_BASE_URL": app.state.AUTOMATIC1111_BASE_URL,
"COMFYUI_BASE_URL": app.state.COMFYUI_BASE_URL,
}
@app.post("/url/update")
async def update_automatic1111_url(
form_data: UrlUpdateForm, user=Depends(get_admin_user)
async def update_engine_url(
form_data: EngineUrlUpdateForm, user=Depends(get_admin_user)
):
if form_data.url == "":
if form_data.AUTOMATIC1111_BASE_URL == None:
app.state.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL
else:
url = form_data.url.strip("/")
url = form_data.AUTOMATIC1111_BASE_URL.strip("/")
try:
r = requests.head(url)
app.state.AUTOMATIC1111_BASE_URL = url
except Exception as e:
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e))
if form_data.COMFYUI_BASE_URL == None:
app.state.COMFYUI_BASE_URL = COMFYUI_BASE_URL
else:
url = form_data.COMFYUI_BASE_URL.strip("/")
try:
r = requests.head(url)
app.state.COMFYUI_BASE_URL = url
except Exception as e:
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e))
return {
"AUTOMATIC1111_BASE_URL": app.state.AUTOMATIC1111_BASE_URL,
"COMFYUI_BASE_URL": app.state.COMFYUI_BASE_URL,
"status": True,
}
@@ -186,6 +210,18 @@ def get_models(user=Depends(get_current_user)):
{"id": "dall-e-2", "name": "DALL·E 2"},
{"id": "dall-e-3", "name": "DALL·E 3"},
]
elif app.state.ENGINE == "comfyui":
r = requests.get(url=f"{app.state.COMFYUI_BASE_URL}/object_info")
info = r.json()
return list(
map(
lambda model: {"id": model, "name": model},
info["CheckpointLoaderSimple"]["input"]["required"]["ckpt_name"][0],
)
)
else:
r = requests.get(
url=f"{app.state.AUTOMATIC1111_BASE_URL}/sdapi/v1/sd-models"
@@ -207,6 +243,8 @@ async def get_default_model(user=Depends(get_admin_user)):
try:
if app.state.ENGINE == "openai":
return {"model": app.state.MODEL if app.state.MODEL else "dall-e-2"}
elif app.state.ENGINE == "comfyui":
return {"model": app.state.MODEL if app.state.MODEL else ""}
else:
r = requests.get(url=f"{app.state.AUTOMATIC1111_BASE_URL}/sdapi/v1/options")
options = r.json()
@@ -221,10 +259,12 @@ class UpdateModelForm(BaseModel):
def set_model_handler(model: str):
if app.state.ENGINE == "openai":
app.state.MODEL = model
return app.state.MODEL
if app.state.ENGINE == "comfyui":
app.state.MODEL = model
return app.state.MODEL
else:
r = requests.get(url=f"{app.state.AUTOMATIC1111_BASE_URL}/sdapi/v1/options")
options = r.json()
@@ -266,6 +306,23 @@ def save_b64_image(b64_str):
with open(file_path, "wb") as f:
f.write(img_data)
return image_id
except Exception as e:
log.error(f"Error saving image: {e}")
return None
def save_url_image(url):
image_id = str(uuid.uuid4())
file_path = IMAGE_CACHE_DIR.joinpath(f"{image_id}.png")
try:
r = requests.get(url)
r.raise_for_status()
with open(file_path, "wb") as image_file:
image_file.write(r.content)
return image_id
except Exception as e:
print(f"Error saving image: {e}")
@@ -278,6 +335,8 @@ def generate_image(
user=Depends(get_current_user),
):
width, height = tuple(map(int, app.state.IMAGE_SIZE.split("x")))
r = None
try:
if app.state.ENGINE == "openai":
@@ -315,12 +374,47 @@ def generate_image(
return images
elif app.state.ENGINE == "comfyui":
data = {
"prompt": form_data.prompt,
"width": width,
"height": height,
"n": form_data.n,
}
if app.state.IMAGE_STEPS != None:
data["steps"] = app.state.IMAGE_STEPS
if form_data.negative_prompt != None:
data["negative_prompt"] = form_data.negative_prompt
data = ImageGenerationPayload(**data)
res = comfyui_generate_image(
app.state.MODEL,
data,
user.id,
app.state.COMFYUI_BASE_URL,
)
print(res)
images = []
for image in res["data"]:
image_id = save_url_image(image["url"])
images.append({"url": f"/cache/image/generations/{image_id}.png"})
file_body_path = IMAGE_CACHE_DIR.joinpath(f"{image_id}.json")
with open(file_body_path, "w") as f:
json.dump(data.model_dump(exclude_none=True), f)
print(images)
return images
else:
if form_data.model:
set_model_handler(form_data.model)
width, height = tuple(map(int, app.state.IMAGE_SIZE.split("x")))
data = {
"prompt": form_data.prompt,
"batch_size": form_data.n,
@@ -341,7 +435,7 @@ def generate_image(
res = r.json()
print(res)
log.debug(f"res: {res}")
images = []
+228
View File
@@ -0,0 +1,228 @@
import websocket # NOTE: websocket-client (https://github.com/websocket-client/websocket-client)
import uuid
import json
import urllib.request
import urllib.parse
import random
from pydantic import BaseModel
from typing import Optional
COMFYUI_DEFAULT_PROMPT = """
{
"3": {
"inputs": {
"seed": 0,
"steps": 20,
"cfg": 8,
"sampler_name": "euler",
"scheduler": "normal",
"denoise": 1,
"model": [
"4",
0
],
"positive": [
"6",
0
],
"negative": [
"7",
0
],
"latent_image": [
"5",
0
]
},
"class_type": "KSampler",
"_meta": {
"title": "KSampler"
}
},
"4": {
"inputs": {
"ckpt_name": "model.safetensors"
},
"class_type": "CheckpointLoaderSimple",
"_meta": {
"title": "Load Checkpoint"
}
},
"5": {
"inputs": {
"width": 512,
"height": 512,
"batch_size": 1
},
"class_type": "EmptyLatentImage",
"_meta": {
"title": "Empty Latent Image"
}
},
"6": {
"inputs": {
"text": "Prompt",
"clip": [
"4",
1
]
},
"class_type": "CLIPTextEncode",
"_meta": {
"title": "CLIP Text Encode (Prompt)"
}
},
"7": {
"inputs": {
"text": "Negative Prompt",
"clip": [
"4",
1
]
},
"class_type": "CLIPTextEncode",
"_meta": {
"title": "CLIP Text Encode (Prompt)"
}
},
"8": {
"inputs": {
"samples": [
"3",
0
],
"vae": [
"4",
2
]
},
"class_type": "VAEDecode",
"_meta": {
"title": "VAE Decode"
}
},
"9": {
"inputs": {
"filename_prefix": "ComfyUI",
"images": [
"8",
0
]
},
"class_type": "SaveImage",
"_meta": {
"title": "Save Image"
}
}
}
"""
def queue_prompt(prompt, client_id, base_url):
print("queue_prompt")
p = {"prompt": prompt, "client_id": client_id}
data = json.dumps(p).encode("utf-8")
req = urllib.request.Request(f"{base_url}/prompt", data=data)
return json.loads(urllib.request.urlopen(req).read())
def get_image(filename, subfolder, folder_type, base_url):
print("get_image")
data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
url_values = urllib.parse.urlencode(data)
with urllib.request.urlopen(f"{base_url}/view?{url_values}") as response:
return response.read()
def get_image_url(filename, subfolder, folder_type, base_url):
print("get_image")
data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
url_values = urllib.parse.urlencode(data)
return f"{base_url}/view?{url_values}"
def get_history(prompt_id, base_url):
print("get_history")
with urllib.request.urlopen(f"{base_url}/history/{prompt_id}") as response:
return json.loads(response.read())
def get_images(ws, prompt, client_id, base_url):
prompt_id = queue_prompt(prompt, client_id, base_url)["prompt_id"]
output_images = []
while True:
out = ws.recv()
if isinstance(out, str):
message = json.loads(out)
if message["type"] == "executing":
data = message["data"]
if data["node"] is None and data["prompt_id"] == prompt_id:
break # Execution is done
else:
continue # previews are binary data
history = get_history(prompt_id, base_url)[prompt_id]
for o in history["outputs"]:
for node_id in history["outputs"]:
node_output = history["outputs"][node_id]
if "images" in node_output:
for image in node_output["images"]:
url = get_image_url(
image["filename"], image["subfolder"], image["type"], base_url
)
output_images.append({"url": url})
return {"data": output_images}
class ImageGenerationPayload(BaseModel):
prompt: str
negative_prompt: Optional[str] = ""
steps: Optional[int] = None
seed: Optional[int] = None
width: int
height: int
n: int = 1
def comfyui_generate_image(
model: str, payload: ImageGenerationPayload, client_id, base_url
):
host = base_url.replace("http://", "").replace("https://", "")
comfyui_prompt = json.loads(COMFYUI_DEFAULT_PROMPT)
comfyui_prompt["4"]["inputs"]["ckpt_name"] = model
comfyui_prompt["5"]["inputs"]["batch_size"] = payload.n
comfyui_prompt["5"]["inputs"]["width"] = payload.width
comfyui_prompt["5"]["inputs"]["height"] = payload.height
# set the text prompt for our positive CLIPTextEncode
comfyui_prompt["6"]["inputs"]["text"] = payload.prompt
comfyui_prompt["7"]["inputs"]["text"] = payload.negative_prompt
if payload.steps:
comfyui_prompt["3"]["inputs"]["steps"] = payload.steps
comfyui_prompt["3"]["inputs"]["seed"] = (
payload.seed if payload.seed else random.randint(0, 18446744073709551614)
)
try:
ws = websocket.WebSocket()
ws.connect(f"ws://{host}/ws?clientId={client_id}")
print("WebSocket connection established.")
except Exception as e:
print(f"Failed to connect to WebSocket server: {e}")
return None
try:
images = get_images(ws, comfyui_prompt, client_id, base_url)
except Exception as e:
print(f"Error while receiving images: {e}")
images = None
ws.close()
return images
+67 -8
View File
@@ -1,10 +1,27 @@
import logging
from litellm.proxy.proxy_server import ProxyConfig, initialize
from litellm.proxy.proxy_server import app
from fastapi import FastAPI, Request, Depends, status
from fastapi import FastAPI, Request, Depends, status, Response
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.responses import StreamingResponse
import json
from utils.utils import get_http_authorization_cred, get_current_user
from config import ENV
from config import SRC_LOG_LEVELS, ENV
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["LITELLM"])
from config import (
MODEL_FILTER_ENABLED,
MODEL_FILTER_LIST,
)
proxy_config = ProxyConfig()
@@ -26,16 +43,58 @@ async def on_startup():
await startup()
app.state.MODEL_FILTER_ENABLED = MODEL_FILTER_ENABLED
app.state.MODEL_FILTER_LIST = MODEL_FILTER_LIST
@app.middleware("http")
async def auth_middleware(request: Request, call_next):
auth_header = request.headers.get("Authorization", "")
request.state.user = None
if ENV != "dev":
try:
user = get_current_user(get_http_authorization_cred(auth_header))
print(user)
except Exception as e:
return JSONResponse(status_code=400, content={"detail": str(e)})
try:
user = get_current_user(get_http_authorization_cred(auth_header))
log.debug(f"user: {user}")
request.state.user = user
except Exception as e:
return JSONResponse(status_code=400, content={"detail": str(e)})
response = await call_next(request)
return response
class ModifyModelsResponseMiddleware(BaseHTTPMiddleware):
async def dispatch(
self, request: Request, call_next: RequestResponseEndpoint
) -> Response:
response = await call_next(request)
user = request.state.user
if "/models" in request.url.path:
if isinstance(response, StreamingResponse):
# Read the content of the streaming response
body = b""
async for chunk in response.body_iterator:
body += chunk
data = json.loads(body.decode("utf-8"))
if app.state.MODEL_FILTER_ENABLED:
if user and user.role == "user":
data["data"] = list(
filter(
lambda model: model["id"]
in app.state.MODEL_FILTER_LIST,
data["data"],
)
)
# Modified Flag
data["modified"] = True
return JSONResponse(content=data)
return response
app.add_middleware(ModifyModelsResponseMiddleware)
+287 -47
View File
@@ -1,24 +1,43 @@
from fastapi import FastAPI, Request, Response, HTTPException, Depends, status
from fastapi import (
FastAPI,
Request,
Response,
HTTPException,
Depends,
status,
UploadFile,
File,
BackgroundTasks,
)
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse
from fastapi.concurrency import run_in_threadpool
from pydantic import BaseModel, ConfigDict
import os
import copy
import random
import requests
import json
import uuid
import aiohttp
import asyncio
import logging
from urllib.parse import urlparse
from typing import Optional, List, Union
from apps.web.models.users import Users
from constants import ERROR_MESSAGES
from utils.utils import decode_token, get_current_user, get_admin_user
from config import OLLAMA_BASE_URLS, MODEL_FILTER_ENABLED, MODEL_FILTER_LIST
from typing import Optional, List, Union
from config import SRC_LOG_LEVELS, OLLAMA_BASE_URLS, MODEL_FILTER_ENABLED, MODEL_FILTER_LIST, UPLOAD_DIR
from utils.misc import calculate_sha256
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["OLLAMA"])
app = FastAPI()
app.add_middleware(
@@ -69,7 +88,7 @@ class UrlUpdateForm(BaseModel):
async def update_ollama_api_url(form_data: UrlUpdateForm, user=Depends(get_admin_user)):
app.state.OLLAMA_BASE_URLS = form_data.urls
print(app.state.OLLAMA_BASE_URLS)
log.info(f"app.state.OLLAMA_BASE_URLS: {app.state.OLLAMA_BASE_URLS}")
return {"OLLAMA_BASE_URLS": app.state.OLLAMA_BASE_URLS}
@@ -90,7 +109,7 @@ async def fetch_url(url):
return await response.json()
except Exception as e:
# Handle connection error here
print(f"Connection error: {e}")
log.error(f"Connection error: {e}")
return None
@@ -98,13 +117,14 @@ def merge_models_lists(model_lists):
merged_models = {}
for idx, model_list in enumerate(model_lists):
for model in model_list:
digest = model["digest"]
if digest not in merged_models:
model["urls"] = [idx]
merged_models[digest] = model
else:
merged_models[digest]["urls"].append(idx)
if model_list is not None:
for model in model_list:
digest = model["digest"]
if digest not in merged_models:
model["urls"] = [idx]
merged_models[digest] = model
else:
merged_models[digest]["urls"].append(idx)
return list(merged_models.values())
@@ -113,14 +133,13 @@ def merge_models_lists(model_lists):
async def get_all_models():
print("get_all_models")
log.info("get_all_models()")
tasks = [fetch_url(f"{url}/api/tags") for url in app.state.OLLAMA_BASE_URLS]
responses = await asyncio.gather(*tasks)
responses = list(filter(lambda x: x is not None, responses))
models = {
"models": merge_models_lists(
map(lambda response: response["models"], responses)
map(lambda response: response["models"] if response else None, responses)
)
}
@@ -155,7 +174,7 @@ async def get_ollama_tags(
return r.json()
except Exception as e:
print(e)
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
@@ -201,7 +220,7 @@ async def get_ollama_versions(url_idx: Optional[int] = None):
return r.json()
except Exception as e:
print(e)
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
@@ -227,18 +246,33 @@ async def pull_model(
form_data: ModelNameForm, url_idx: int = 0, user=Depends(get_admin_user)
):
url = app.state.OLLAMA_BASE_URLS[url_idx]
print(url)
log.info(f"url: {url}")
r = None
def get_request():
nonlocal url
nonlocal r
request_id = str(uuid.uuid4())
try:
REQUEST_POOL.append(request_id)
def stream_content():
for chunk in r.iter_content(chunk_size=8192):
yield chunk
try:
yield json.dumps({"id": request_id, "done": False}) + "\n"
for chunk in r.iter_content(chunk_size=8192):
if request_id in REQUEST_POOL:
yield chunk
else:
print("User: canceled request")
break
finally:
if hasattr(r, "close"):
r.close()
if request_id in REQUEST_POOL:
REQUEST_POOL.remove(request_id)
r = requests.request(
method="POST",
@@ -259,8 +293,9 @@ async def pull_model(
try:
return await run_in_threadpool(get_request)
except Exception as e:
print(e)
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
@@ -299,7 +334,7 @@ async def push_model(
)
url = app.state.OLLAMA_BASE_URLS[url_idx]
print(url)
log.debug(f"url: {url}")
r = None
@@ -331,7 +366,7 @@ async def push_model(
try:
return await run_in_threadpool(get_request)
except Exception as e:
print(e)
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
@@ -359,9 +394,9 @@ class CreateModelForm(BaseModel):
async def create_model(
form_data: CreateModelForm, url_idx: int = 0, user=Depends(get_admin_user)
):
print(form_data)
log.debug(f"form_data: {form_data}")
url = app.state.OLLAMA_BASE_URLS[url_idx]
print(url)
log.info(f"url: {url}")
r = None
@@ -383,7 +418,7 @@ async def create_model(
r.raise_for_status()
print(r)
log.debug(f"r: {r}")
return StreamingResponse(
stream_content(),
@@ -396,7 +431,7 @@ async def create_model(
try:
return await run_in_threadpool(get_request)
except Exception as e:
print(e)
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
@@ -434,7 +469,7 @@ async def copy_model(
)
url = app.state.OLLAMA_BASE_URLS[url_idx]
print(url)
log.info(f"url: {url}")
try:
r = requests.request(
@@ -444,11 +479,11 @@ async def copy_model(
)
r.raise_for_status()
print(r.text)
log.debug(f"r.text: {r.text}")
return True
except Exception as e:
print(e)
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
@@ -481,7 +516,7 @@ async def delete_model(
)
url = app.state.OLLAMA_BASE_URLS[url_idx]
print(url)
log.info(f"url: {url}")
try:
r = requests.request(
@@ -491,11 +526,11 @@ async def delete_model(
)
r.raise_for_status()
print(r.text)
log.debug(f"r.text: {r.text}")
return True
except Exception as e:
print(e)
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
@@ -521,7 +556,7 @@ async def show_model_info(form_data: ModelNameForm, user=Depends(get_current_use
url_idx = random.choice(app.state.MODELS[form_data.name]["urls"])
url = app.state.OLLAMA_BASE_URLS[url_idx]
print(url)
log.info(f"url: {url}")
try:
r = requests.request(
@@ -533,7 +568,7 @@ async def show_model_info(form_data: ModelNameForm, user=Depends(get_current_use
return r.json()
except Exception as e:
print(e)
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
@@ -573,7 +608,7 @@ async def generate_embeddings(
)
url = app.state.OLLAMA_BASE_URLS[url_idx]
print(url)
log.info(f"url: {url}")
try:
r = requests.request(
@@ -585,7 +620,7 @@ async def generate_embeddings(
return r.json()
except Exception as e:
print(e)
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
@@ -633,7 +668,7 @@ async def generate_completion(
)
url = app.state.OLLAMA_BASE_URLS[url_idx]
print(url)
log.info(f"url: {url}")
r = None
@@ -654,7 +689,7 @@ async def generate_completion(
if request_id in REQUEST_POOL:
yield chunk
else:
print("User: canceled request")
log.warning("User: canceled request")
break
finally:
if hasattr(r, "close"):
@@ -709,7 +744,7 @@ class GenerateChatCompletionForm(BaseModel):
format: Optional[str] = None
options: Optional[dict] = None
template: Optional[str] = None
stream: Optional[bool] = True
stream: Optional[bool] = None
keep_alive: Optional[Union[int, str]] = None
@@ -731,11 +766,11 @@ async def generate_chat_completion(
)
url = app.state.OLLAMA_BASE_URLS[url_idx]
print(url)
log.info(f"url: {url}")
r = None
print(form_data.model_dump_json(exclude_none=True).encode())
log.debug("form_data.model_dump_json(exclude_none=True).encode(): {0} ".format(form_data.model_dump_json(exclude_none=True).encode()))
def get_request():
nonlocal form_data
@@ -754,7 +789,7 @@ async def generate_chat_completion(
if request_id in REQUEST_POOL:
yield chunk
else:
print("User: canceled request")
log.warning("User: canceled request")
break
finally:
if hasattr(r, "close"):
@@ -777,7 +812,7 @@ async def generate_chat_completion(
headers=dict(r.headers),
)
except Exception as e:
print(e)
log.exception(e)
raise e
try:
@@ -831,7 +866,7 @@ async def generate_openai_chat_completion(
)
url = app.state.OLLAMA_BASE_URLS[url_idx]
print(url)
log.info(f"url: {url}")
r = None
@@ -854,7 +889,7 @@ async def generate_openai_chat_completion(
if request_id in REQUEST_POOL:
yield chunk
else:
print("User: canceled request")
log.warning("User: canceled request")
break
finally:
if hasattr(r, "close"):
@@ -897,6 +932,211 @@ async def generate_openai_chat_completion(
)
class UrlForm(BaseModel):
url: str
class UploadBlobForm(BaseModel):
filename: str
def parse_huggingface_url(hf_url):
try:
# Parse the URL
parsed_url = urlparse(hf_url)
# Get the path and split it into components
path_components = parsed_url.path.split("/")
# Extract the desired output
user_repo = "/".join(path_components[1:3])
model_file = path_components[-1]
return model_file
except ValueError:
return None
async def download_file_stream(
ollama_url, file_url, file_path, file_name, chunk_size=1024 * 1024
):
done = False
if os.path.exists(file_path):
current_size = os.path.getsize(file_path)
else:
current_size = 0
headers = {"Range": f"bytes={current_size}-"} if current_size > 0 else {}
timeout = aiohttp.ClientTimeout(total=600) # Set the timeout
async with aiohttp.ClientSession(timeout=timeout) as session:
async with session.get(file_url, headers=headers) as response:
total_size = int(response.headers.get("content-length", 0)) + current_size
with open(file_path, "ab+") as file:
async for data in response.content.iter_chunked(chunk_size):
current_size += len(data)
file.write(data)
done = current_size == total_size
progress = round((current_size / total_size) * 100, 2)
yield f'data: {{"progress": {progress}, "completed": {current_size}, "total": {total_size}}}\n\n'
if done:
file.seek(0)
hashed = calculate_sha256(file)
file.seek(0)
url = f"{ollama_url}/api/blobs/sha256:{hashed}"
response = requests.post(url, data=file)
if response.ok:
res = {
"done": done,
"blob": f"sha256:{hashed}",
"name": file_name,
}
os.remove(file_path)
yield f"data: {json.dumps(res)}\n\n"
else:
raise "Ollama: Could not create blob, Please try again."
# def number_generator():
# for i in range(1, 101):
# yield f"data: {i}\n"
# url = "https://huggingface.co/TheBloke/stablelm-zephyr-3b-GGUF/resolve/main/stablelm-zephyr-3b.Q2_K.gguf"
@app.post("/models/download")
@app.post("/models/download/{url_idx}")
async def download_model(
form_data: UrlForm,
url_idx: Optional[int] = None,
):
if url_idx == None:
url_idx = 0
url = app.state.OLLAMA_BASE_URLS[url_idx]
file_name = parse_huggingface_url(form_data.url)
if file_name:
file_path = f"{UPLOAD_DIR}/{file_name}"
return StreamingResponse(
download_file_stream(url, form_data.url, file_path, file_name),
)
else:
return None
@app.post("/models/upload")
@app.post("/models/upload/{url_idx}")
def upload_model(file: UploadFile = File(...), url_idx: Optional[int] = None):
if url_idx == None:
url_idx = 0
ollama_url = app.state.OLLAMA_BASE_URLS[url_idx]
file_path = f"{UPLOAD_DIR}/{file.filename}"
# Save file in chunks
with open(file_path, "wb+") as f:
for chunk in file.file:
f.write(chunk)
def file_process_stream():
nonlocal ollama_url
total_size = os.path.getsize(file_path)
chunk_size = 1024 * 1024
try:
with open(file_path, "rb") as f:
total = 0
done = False
while not done:
chunk = f.read(chunk_size)
if not chunk:
done = True
continue
total += len(chunk)
progress = round((total / total_size) * 100, 2)
res = {
"progress": progress,
"total": total_size,
"completed": total,
}
yield f"data: {json.dumps(res)}\n\n"
if done:
f.seek(0)
hashed = calculate_sha256(f)
f.seek(0)
url = f"{ollama_url}/api/blobs/sha256:{hashed}"
response = requests.post(url, data=f)
if response.ok:
res = {
"done": done,
"blob": f"sha256:{hashed}",
"name": file.filename,
}
os.remove(file_path)
yield f"data: {json.dumps(res)}\n\n"
else:
raise Exception(
"Ollama: Could not create blob, Please try again."
)
except Exception as e:
res = {"error": str(e)}
yield f"data: {json.dumps(res)}\n\n"
return StreamingResponse(file_process_stream(), media_type="text/event-stream")
# async def upload_model(file: UploadFile = File(), url_idx: Optional[int] = None):
# if url_idx == None:
# url_idx = 0
# url = app.state.OLLAMA_BASE_URLS[url_idx]
# file_location = os.path.join(UPLOAD_DIR, file.filename)
# total_size = file.size
# async def file_upload_generator(file):
# print(file)
# try:
# async with aiofiles.open(file_location, "wb") as f:
# completed_size = 0
# while True:
# chunk = await file.read(1024*1024)
# if not chunk:
# break
# await f.write(chunk)
# completed_size += len(chunk)
# progress = (completed_size / total_size) * 100
# print(progress)
# yield f'data: {json.dumps({"status": "uploading", "percentage": progress, "total": total_size, "completed": completed_size, "done": False})}\n'
# except Exception as e:
# print(e)
# yield f"data: {json.dumps({'status': 'error', 'message': str(e)})}\n"
# finally:
# await file.close()
# print("done")
# yield f'data: {json.dumps({"status": "completed", "percentage": 100, "total": total_size, "completed": completed_size, "done": True})}\n'
# return StreamingResponse(
# file_upload_generator(copy.deepcopy(file)), media_type="text/event-stream"
# )
@app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
async def deprecated_proxy(path: str, request: Request, user=Depends(get_current_user)):
url = app.state.OLLAMA_BASE_URLS[0]
@@ -947,7 +1187,7 @@ async def deprecated_proxy(path: str, request: Request, user=Depends(get_current
if request_id in REQUEST_POOL:
yield chunk
else:
print("User: canceled request")
log.warning("User: canceled request")
break
finally:
if hasattr(r, "close"):
+46 -21
View File
@@ -6,6 +6,7 @@ import requests
import aiohttp
import asyncio
import json
import logging
from pydantic import BaseModel
@@ -19,6 +20,7 @@ from utils.utils import (
get_admin_user,
)
from config import (
SRC_LOG_LEVELS,
OPENAI_API_BASE_URLS,
OPENAI_API_KEYS,
CACHE_DIR,
@@ -31,6 +33,9 @@ from typing import List, Optional
import hashlib
from pathlib import Path
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["OPENAI"])
app = FastAPI()
app.add_middleware(
CORSMiddleware,
@@ -111,6 +116,7 @@ async def speech(request: Request, user=Depends(get_verified_user)):
headers["Authorization"] = f"Bearer {app.state.OPENAI_API_KEYS[idx]}"
headers["Content-Type"] = "application/json"
r = None
try:
r = requests.post(
url=f"{app.state.OPENAI_API_BASE_URLS[idx]}/audio/speech",
@@ -133,7 +139,7 @@ async def speech(request: Request, user=Depends(get_verified_user)):
return FileResponse(file_path)
except Exception as e:
print(e)
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
@@ -143,7 +149,9 @@ async def speech(request: Request, user=Depends(get_verified_user)):
except:
error_detail = f"External: {e}"
raise HTTPException(status_code=r.status_code, detail=error_detail)
raise HTTPException(
status_code=r.status_code if r else 500, detail=error_detail
)
except ValueError:
raise HTTPException(status_code=401, detail=ERROR_MESSAGES.OPENAI_NOT_FOUND)
@@ -157,7 +165,7 @@ async def fetch_url(url, key):
return await response.json()
except Exception as e:
# Handle connection error here
print(f"Connection error: {e}")
log.error(f"Connection error: {e}")
return None
@@ -165,20 +173,21 @@ def merge_models_lists(model_lists):
merged_list = []
for idx, models in enumerate(model_lists):
merged_list.extend(
[
{**model, "urlIdx": idx}
for model in models
if "api.openai.com" not in app.state.OPENAI_API_BASE_URLS[idx]
or "gpt" in model["id"]
]
)
if models is not None and "error" not in models:
merged_list.extend(
[
{**model, "urlIdx": idx}
for model in models
if "api.openai.com" not in app.state.OPENAI_API_BASE_URLS[idx]
or "gpt" in model["id"]
]
)
return merged_list
async def get_all_models():
print("get_all_models")
log.info("get_all_models()")
if len(app.state.OPENAI_API_KEYS) == 1 and app.state.OPENAI_API_KEYS[0] == "":
models = {"data": []}
@@ -187,15 +196,24 @@ async def get_all_models():
fetch_url(f"{url}/models", app.state.OPENAI_API_KEYS[idx])
for idx, url in enumerate(app.state.OPENAI_API_BASE_URLS)
]
responses = await asyncio.gather(*tasks)
responses = list(
filter(lambda x: x is not None and "error" not in x, responses)
)
models = {
"data": merge_models_lists(
list(map(lambda response: response["data"], responses))
list(
map(
lambda response: (
response["data"]
if response and "data" in response
else None
),
responses,
)
)
)
}
log.info(f"models: {models}")
app.state.MODELS = {model["id"]: model for model in models["data"]}
return models
@@ -218,6 +236,9 @@ async def get_models(url_idx: Optional[int] = None, user=Depends(get_current_use
return models
else:
url = app.state.OPENAI_API_BASE_URLS[url_idx]
r = None
try:
r = requests.request(method="GET", url=f"{url}/models")
r.raise_for_status()
@@ -230,7 +251,7 @@ async def get_models(url_idx: Optional[int] = None, user=Depends(get_current_use
return response_data
except Exception as e:
print(e)
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
@@ -264,7 +285,7 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
if body.get("model") == "gpt-4-vision-preview":
if "max_tokens" not in body:
body["max_tokens"] = 4000
print("Modified body_dict:", body)
log.debug("Modified body_dict:", body)
# Fix for ChatGPT calls failing because the num_ctx key is in body
if "num_ctx" in body:
@@ -276,7 +297,7 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
# Convert the modified body back to JSON
body = json.dumps(body)
except json.JSONDecodeError as e:
print("Error loading request body into a dictionary:", e)
log.error("Error loading request body into a dictionary:", e)
url = app.state.OPENAI_API_BASE_URLS[idx]
key = app.state.OPENAI_API_KEYS[idx]
@@ -290,6 +311,8 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
headers["Authorization"] = f"Bearer {key}"
headers["Content-Type"] = "application/json"
r = None
try:
r = requests.request(
method=request.method,
@@ -312,7 +335,7 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
response_data = r.json()
return response_data
except Exception as e:
print(e)
log.exception(e)
error_detail = "Open WebUI: Server Connection Error"
if r is not None:
try:
@@ -322,4 +345,6 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
except:
error_detail = f"External: {e}"
raise HTTPException(status_code=r.status_code, detail=error_detail)
raise HTTPException(
status_code=r.status_code if r else 500, detail=error_detail
)
+95 -44
View File
@@ -8,7 +8,7 @@ from fastapi import (
Form,
)
from fastapi.middleware.cors import CORSMiddleware
import os, shutil
import os, shutil, logging
from pathlib import Path
from typing import List
@@ -54,6 +54,7 @@ from utils.misc import (
)
from utils.utils import get_current_user, get_admin_user
from config import (
SRC_LOG_LEVELS,
UPLOAD_DIR,
DOCS_DIR,
RAG_EMBEDDING_MODEL,
@@ -66,6 +67,9 @@ from config import (
from constants import ERROR_MESSAGES
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
#
# if RAG_EMBEDDING_MODEL:
# sentence_transformer_ef = SentenceTransformer(
@@ -110,40 +114,6 @@ class CollectionNameForm(BaseModel):
class StoreWebForm(CollectionNameForm):
url: str
def store_data_in_vector_db(data, collection_name, overwrite: bool = False) -> bool:
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=app.state.CHUNK_SIZE, chunk_overlap=app.state.CHUNK_OVERLAP
)
docs = text_splitter.split_documents(data)
texts = [doc.page_content for doc in docs]
metadatas = [doc.metadata for doc in docs]
try:
if overwrite:
for collection in CHROMA_CLIENT.list_collections():
if collection_name == collection.name:
print(f"deleting existing collection {collection_name}")
CHROMA_CLIENT.delete_collection(name=collection_name)
collection = CHROMA_CLIENT.create_collection(
name=collection_name,
embedding_function=app.state.sentence_transformer_ef,
)
collection.add(
documents=texts, metadatas=metadatas, ids=[str(uuid.uuid1()) for _ in texts]
)
return True
except Exception as e:
print(e)
if e.__class__.__name__ == "UniqueConstraintError":
return True
return False
@app.get("/")
async def get_status():
return {
@@ -274,7 +244,7 @@ def query_doc_handler(
embedding_function=app.state.sentence_transformer_ef,
)
except Exception as e:
print(e)
log.exception(e)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT(e),
@@ -318,13 +288,63 @@ def store_web(form_data: StoreWebForm, user=Depends(get_current_user)):
"filename": form_data.url,
}
except Exception as e:
print(e)
log.exception(e)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT(e),
)
def store_data_in_vector_db(data, collection_name, overwrite: bool = False) -> bool:
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=app.state.CHUNK_SIZE,
chunk_overlap=app.state.CHUNK_OVERLAP,
add_start_index=True,
)
docs = text_splitter.split_documents(data)
return store_docs_in_vector_db(docs, collection_name, overwrite)
def store_text_in_vector_db(
text, metadata, collection_name, overwrite: bool = False
) -> bool:
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=app.state.CHUNK_SIZE,
chunk_overlap=app.state.CHUNK_OVERLAP,
add_start_index=True,
)
docs = text_splitter.create_documents([text], metadatas=[metadata])
return store_docs_in_vector_db(docs, collection_name, overwrite)
def store_docs_in_vector_db(docs, collection_name, overwrite: bool = False) -> bool:
texts = [doc.page_content for doc in docs]
metadatas = [doc.metadata for doc in docs]
try:
if overwrite:
for collection in CHROMA_CLIENT.list_collections():
if collection_name == collection.name:
print(f"deleting existing collection {collection_name}")
CHROMA_CLIENT.delete_collection(name=collection_name)
collection = CHROMA_CLIENT.create_collection(
name=collection_name,
embedding_function=app.state.sentence_transformer_ef,
)
collection.add(
documents=texts, metadatas=metadatas, ids=[str(uuid.uuid1()) for _ in texts]
)
return True
except Exception as e:
print(e)
if e.__class__.__name__ == "UniqueConstraintError":
return True
return False
def get_loader(filename: str, file_content_type: str, file_path: str):
file_ext = filename.split(".")[-1].lower()
known_type = True
@@ -400,9 +420,9 @@ def get_loader(filename: str, file_content_type: str, file_path: str):
elif file_ext in known_source_ext or (
file_content_type and file_content_type.find("text/") >= 0
):
loader = TextLoader(file_path)
loader = TextLoader(file_path, autodetect_encoding=True)
else:
loader = TextLoader(file_path)
loader = TextLoader(file_path, autodetect_encoding=True)
known_type = False
return loader, known_type
@@ -416,7 +436,7 @@ def store_doc(
):
# "https://www.gutenberg.org/files/1727/1727-h/1727-h.htm"
print(file.content_type)
log.info(f"file.content_type: {file.content_type}")
try:
filename = file.filename
file_path = f"{UPLOAD_DIR}/{filename}"
@@ -447,7 +467,7 @@ def store_doc(
detail=ERROR_MESSAGES.DEFAULT(),
)
except Exception as e:
print(e)
log.exception(e)
if "No pandoc was found" in str(e):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
@@ -460,6 +480,37 @@ def store_doc(
)
class TextRAGForm(BaseModel):
name: str
content: str
collection_name: Optional[str] = None
@app.post("/text")
def store_text(
form_data: TextRAGForm,
user=Depends(get_current_user),
):
collection_name = form_data.collection_name
if collection_name == None:
collection_name = calculate_sha256_string(form_data.content)
result = store_text_in_vector_db(
form_data.content,
metadata={"name": form_data.name, "created_by": user.id},
collection_name=collection_name,
)
if result:
return {"status": True, "collection_name": collection_name}
else:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=ERROR_MESSAGES.DEFAULT(),
)
@app.get("/scan")
def scan_docs_dir(user=Depends(get_admin_user)):
for path in Path(DOCS_DIR).rglob("./**/*"):
@@ -512,7 +563,7 @@ def scan_docs_dir(user=Depends(get_admin_user)):
)
except Exception as e:
print(e)
log.exception(e)
return True
@@ -533,11 +584,11 @@ def reset(user=Depends(get_admin_user)) -> bool:
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
except Exception as e:
print("Failed to delete %s. Reason: %s" % (file_path, e))
log.error("Failed to delete %s. Reason: %s" % (file_path, e))
try:
CHROMA_CLIENT.reset()
except Exception as e:
print(e)
log.exception(e)
return True
+9 -3
View File
@@ -1,7 +1,11 @@
import re
import logging
from typing import List
from config import CHROMA_CLIENT
from config import SRC_LOG_LEVELS, CHROMA_CLIENT
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["RAG"])
def query_doc(collection_name: str, query: str, k: int, embedding_function):
@@ -97,7 +101,7 @@ def rag_template(template: str, context: str, query: str):
def rag_messages(docs, messages, template, k, embedding_function):
print(docs)
log.debug(f"docs: {docs}")
last_user_message_idx = None
for i in range(len(messages) - 1, -1, -1):
@@ -137,6 +141,8 @@ def rag_messages(docs, messages, template, k, embedding_function):
k=k,
embedding_function=embedding_function,
)
elif doc["type"] == "text":
context = doc["content"]
else:
context = query_doc(
collection_name=doc["collection_name"],
@@ -145,7 +151,7 @@ def rag_messages(docs, messages, template, k, embedding_function):
embedding_function=embedding_function,
)
except Exception as e:
print(e)
log.exception(e)
context = None
relevant_contexts.append(context)
+5 -2
View File
@@ -1,13 +1,16 @@
from peewee import *
from config import DATA_DIR
from config import SRC_LOG_LEVELS, DATA_DIR
import os
import logging
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["DB"])
# Check if the file exists
if os.path.exists(f"{DATA_DIR}/ollama.db"):
# Rename the file
os.rename(f"{DATA_DIR}/ollama.db", f"{DATA_DIR}/webui.db")
print("File renamed successfully.")
log.info("File renamed successfully.")
else:
pass
+2
View File
@@ -19,6 +19,7 @@ from config import (
DEFAULT_USER_ROLE,
ENABLE_SIGNUP,
USER_PERMISSIONS,
WEBHOOK_URL,
)
app = FastAPI()
@@ -32,6 +33,7 @@ app.state.DEFAULT_MODELS = DEFAULT_MODELS
app.state.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS
app.state.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE
app.state.USER_PERMISSIONS = USER_PERMISSIONS
app.state.WEBHOOK_URL = WEBHOOK_URL
app.add_middleware(
+7 -2
View File
@@ -2,6 +2,7 @@ from pydantic import BaseModel
from typing import List, Union, Optional
import time
import uuid
import logging
from peewee import *
from apps.web.models.users import UserModel, Users
@@ -9,6 +10,10 @@ from utils.utils import verify_password
from apps.web.internal.db import DB
from config import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
# DB MODEL
####################
@@ -86,7 +91,7 @@ class AuthsTable:
def insert_new_auth(
self, email: str, password: str, name: str, role: str = "pending"
) -> Optional[UserModel]:
print("insert_new_auth")
log.info("insert_new_auth")
id = str(uuid.uuid4())
@@ -103,7 +108,7 @@ class AuthsTable:
return None
def authenticate_user(self, email: str, password: str) -> Optional[UserModel]:
print("authenticate_user", email)
log.info(f"authenticate_user: {email}")
try:
auth = Auth.get(Auth.email == email, Auth.active == True)
if auth:
-14
View File
@@ -95,20 +95,6 @@ class ChatTable:
except:
return None
def update_chat_by_id(self, id: str, chat: dict) -> Optional[ChatModel]:
try:
query = Chat.update(
chat=json.dumps(chat),
title=chat["title"] if "title" in chat else "New Chat",
timestamp=int(time.time()),
).where(Chat.id == id)
query.execute()
chat = Chat.get(Chat.id == id)
return ChatModel(**model_to_dict(chat))
except:
return None
def get_chat_lists_by_user_id(
self, user_id: str, skip: int = 0, limit: int = 50
) -> List[ChatModel]:
+7 -2
View File
@@ -3,6 +3,7 @@ from peewee import *
from playhouse.shortcuts import model_to_dict
from typing import List, Union, Optional
import time
import logging
from utils.utils import decode_token
from utils.misc import get_gravatar_url
@@ -11,6 +12,10 @@ from apps.web.internal.db import DB
import json
from config import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
# Documents DB Schema
####################
@@ -118,7 +123,7 @@ class DocumentsTable:
doc = Document.get(Document.name == form_data.name)
return DocumentModel(**model_to_dict(doc))
except Exception as e:
print(e)
log.exception(e)
return None
def update_doc_content_by_name(
@@ -138,7 +143,7 @@ class DocumentsTable:
doc = Document.get(Document.name == name)
return DocumentModel(**model_to_dict(doc))
except Exception as e:
print(e)
log.exception(e)
return None
def delete_doc_by_name(self, name: str) -> bool:
+9 -4
View File
@@ -6,9 +6,14 @@ from playhouse.shortcuts import model_to_dict
import json
import uuid
import time
import logging
from apps.web.internal.db import DB
from config import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
# Tag DB Schema
####################
@@ -173,7 +178,7 @@ class TagTable:
(ChatIdTag.tag_name == tag_name) & (ChatIdTag.user_id == user_id)
)
res = query.execute() # Remove the rows, return number of rows removed.
print(res)
log.debug(f"res: {res}")
tag_count = self.count_chat_ids_by_tag_name_and_user_id(tag_name, user_id)
if tag_count == 0:
@@ -185,7 +190,7 @@ class TagTable:
return True
except Exception as e:
print("delete_tag", e)
log.error(f"delete_tag: {e}")
return False
def delete_tag_by_tag_name_and_chat_id_and_user_id(
@@ -198,7 +203,7 @@ class TagTable:
& (ChatIdTag.user_id == user_id)
)
res = query.execute() # Remove the rows, return number of rows removed.
print(res)
log.debug(f"res: {res}")
tag_count = self.count_chat_ids_by_tag_name_and_user_id(tag_name, user_id)
if tag_count == 0:
@@ -210,7 +215,7 @@ class TagTable:
return True
except Exception as e:
print("delete_tag", e)
log.error(f"delete_tag: {e}")
return False
def delete_tags_by_chat_id_and_user_id(self, chat_id: str, user_id: str) -> bool:
+13 -1
View File
@@ -27,7 +27,8 @@ from utils.utils import (
create_token,
)
from utils.misc import parse_duration, validate_email_format
from constants import ERROR_MESSAGES
from utils.webhook import post_webhook
from constants import ERROR_MESSAGES, WEBHOOK_MESSAGES
router = APIRouter()
@@ -155,6 +156,17 @@ async def signup(request: Request, form_data: SignupForm):
)
# response.set_cookie(key='token', value=token, httponly=True)
if request.app.state.WEBHOOK_URL:
post_webhook(
request.app.state.WEBHOOK_URL,
WEBHOOK_MESSAGES.USER_SIGNUP(user.name),
{
"action": "signup",
"message": WEBHOOK_MESSAGES.USER_SIGNUP(user.name),
"user": user.model_dump_json(exclude_none=True),
},
)
return {
"token": token,
"token_type": "Bearer",
+7 -2
View File
@@ -5,6 +5,7 @@ from utils.utils import get_current_user, get_admin_user
from fastapi import APIRouter
from pydantic import BaseModel
import json
import logging
from apps.web.models.users import Users
from apps.web.models.chats import (
@@ -27,6 +28,10 @@ from apps.web.models.tags import (
from constants import ERROR_MESSAGES
from config import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
router = APIRouter()
############################
@@ -78,7 +83,7 @@ async def create_new_chat(form_data: ChatForm, user=Depends(get_current_user)):
chat = Chats.insert_new_chat(user.id, form_data)
return ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
except Exception as e:
print(e)
log.exception(e)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()
)
@@ -95,7 +100,7 @@ async def get_all_tags(user=Depends(get_current_user)):
tags = Tags.get_tags_by_user_id(user.id)
return tags
except Exception as e:
print(e)
log.exception(e)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()
)
+6 -1
View File
@@ -7,6 +7,7 @@ from fastapi import APIRouter
from pydantic import BaseModel
import time
import uuid
import logging
from apps.web.models.users import UserModel, UserUpdateForm, UserRoleUpdateForm, Users
from apps.web.models.auths import Auths
@@ -14,6 +15,10 @@ from apps.web.models.auths import Auths
from utils.utils import get_current_user, get_password_hash, get_admin_user
from constants import ERROR_MESSAGES
from config import SRC_LOG_LEVELS
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
router = APIRouter()
############################
@@ -83,7 +88,7 @@ async def update_user_by_id(
if form_data.password:
hashed = get_password_hash(form_data.password)
print(hashed)
log.debug(f"hashed: {hashed}")
Auths.update_user_password_by_id(user_id, hashed)
Auths.update_email_by_id(user_id, form_data.email.lower())
-149
View File
@@ -21,155 +21,6 @@ from constants import ERROR_MESSAGES
router = APIRouter()
class UploadBlobForm(BaseModel):
filename: str
from urllib.parse import urlparse
def parse_huggingface_url(hf_url):
try:
# Parse the URL
parsed_url = urlparse(hf_url)
# Get the path and split it into components
path_components = parsed_url.path.split("/")
# Extract the desired output
user_repo = "/".join(path_components[1:3])
model_file = path_components[-1]
return model_file
except ValueError:
return None
async def download_file_stream(url, file_path, file_name, chunk_size=1024 * 1024):
done = False
if os.path.exists(file_path):
current_size = os.path.getsize(file_path)
else:
current_size = 0
headers = {"Range": f"bytes={current_size}-"} if current_size > 0 else {}
timeout = aiohttp.ClientTimeout(total=600) # Set the timeout
async with aiohttp.ClientSession(timeout=timeout) as session:
async with session.get(url, headers=headers) as response:
total_size = int(response.headers.get("content-length", 0)) + current_size
with open(file_path, "ab+") as file:
async for data in response.content.iter_chunked(chunk_size):
current_size += len(data)
file.write(data)
done = current_size == total_size
progress = round((current_size / total_size) * 100, 2)
yield f'data: {{"progress": {progress}, "completed": {current_size}, "total": {total_size}}}\n\n'
if done:
file.seek(0)
hashed = calculate_sha256(file)
file.seek(0)
url = f"{OLLAMA_BASE_URLS[0]}/api/blobs/sha256:{hashed}"
response = requests.post(url, data=file)
if response.ok:
res = {
"done": done,
"blob": f"sha256:{hashed}",
"name": file_name,
}
os.remove(file_path)
yield f"data: {json.dumps(res)}\n\n"
else:
raise "Ollama: Could not create blob, Please try again."
@router.get("/download")
async def download(
url: str,
):
# url = "https://huggingface.co/TheBloke/stablelm-zephyr-3b-GGUF/resolve/main/stablelm-zephyr-3b.Q2_K.gguf"
file_name = parse_huggingface_url(url)
if file_name:
file_path = f"{UPLOAD_DIR}/{file_name}"
return StreamingResponse(
download_file_stream(url, file_path, file_name),
media_type="text/event-stream",
)
else:
return None
@router.post("/upload")
def upload(file: UploadFile = File(...)):
file_path = f"{UPLOAD_DIR}/{file.filename}"
# Save file in chunks
with open(file_path, "wb+") as f:
for chunk in file.file:
f.write(chunk)
def file_process_stream():
total_size = os.path.getsize(file_path)
chunk_size = 1024 * 1024
try:
with open(file_path, "rb") as f:
total = 0
done = False
while not done:
chunk = f.read(chunk_size)
if not chunk:
done = True
continue
total += len(chunk)
progress = round((total / total_size) * 100, 2)
res = {
"progress": progress,
"total": total_size,
"completed": total,
}
yield f"data: {json.dumps(res)}\n\n"
if done:
f.seek(0)
hashed = calculate_sha256(f)
f.seek(0)
url = f"{OLLAMA_BASE_URLS[0]}/blobs/sha256:{hashed}"
response = requests.post(url, data=f)
if response.ok:
res = {
"done": done,
"blob": f"sha256:{hashed}",
"name": file.filename,
}
os.remove(file_path)
yield f"data: {json.dumps(res)}\n\n"
else:
raise Exception(
"Ollama: Could not create blob, Please try again."
)
except Exception as e:
res = {"error": str(e)}
yield f"data: {json.dumps(res)}\n\n"
return StreamingResponse(file_process_stream(), media_type="text/event-stream")
@router.get("/gravatar")
async def get_gravatar(
email: str,
+47 -8
View File
@@ -1,4 +1,6 @@
import os
import sys
import logging
import chromadb
from chromadb import Settings
from base64 import b64encode
@@ -21,7 +23,7 @@ try:
load_dotenv(find_dotenv("../.env"))
except ImportError:
print("dotenv not installed, skipping...")
log.warning("dotenv not installed, skipping...")
WEBUI_NAME = "Open WebUI"
shutil.copyfile("../build/favicon.png", "./static/favicon.png")
@@ -100,6 +102,34 @@ for version in soup.find_all("h2"):
CHANGELOG = changelog_json
####################################
# LOGGING
####################################
log_levels = ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"]
GLOBAL_LOG_LEVEL = os.environ.get("GLOBAL_LOG_LEVEL", "").upper()
if GLOBAL_LOG_LEVEL in log_levels:
logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL, force=True)
else:
GLOBAL_LOG_LEVEL = "INFO"
log = logging.getLogger(__name__)
log.info(f"GLOBAL_LOG_LEVEL: {GLOBAL_LOG_LEVEL}")
log_sources = ["AUDIO", "CONFIG", "DB", "IMAGES", "LITELLM", "MAIN", "MODELS", "OLLAMA", "OPENAI", "RAG"]
SRC_LOG_LEVELS = {}
for source in log_sources:
log_env_var = source + "_LOG_LEVEL"
SRC_LOG_LEVELS[source] = os.environ.get(log_env_var, "").upper()
if SRC_LOG_LEVELS[source] not in log_levels:
SRC_LOG_LEVELS[source] = GLOBAL_LOG_LEVEL
log.info(f"{log_env_var}: {SRC_LOG_LEVELS[source]}")
log.setLevel(SRC_LOG_LEVELS["CONFIG"])
####################################
# CUSTOM_NAME
####################################
@@ -125,7 +155,7 @@ if CUSTOM_NAME:
WEBUI_NAME = data["name"]
except Exception as e:
print(e)
log.exception(e)
pass
@@ -194,9 +224,9 @@ def create_config_file(file_path):
LITELLM_CONFIG_PATH = f"{DATA_DIR}/litellm/config.yaml"
if not os.path.exists(LITELLM_CONFIG_PATH):
print("Config file doesn't exist. Creating...")
log.info("Config file doesn't exist. Creating...")
create_config_file(LITELLM_CONFIG_PATH)
print("Config file created successfully.")
log.info("Config file created successfully.")
####################################
@@ -250,8 +280,10 @@ OPENAI_API_BASE_URLS = (
OPENAI_API_BASE_URLS if OPENAI_API_BASE_URLS != "" else OPENAI_API_BASE_URL
)
OPENAI_API_BASE_URLS = [url.strip() for url in OPENAI_API_BASE_URLS.split(";")]
OPENAI_API_BASE_URLS = [
url.strip() if url != "" else "https://api.openai.com/v1"
for url in OPENAI_API_BASE_URLS.split(";")
]
####################################
# WEBUI
@@ -288,13 +320,19 @@ DEFAULT_PROMPT_SUGGESTIONS = (
DEFAULT_USER_ROLE = os.getenv("DEFAULT_USER_ROLE", "pending")
USER_PERMISSIONS = {"chat": {"deletion": True}}
USER_PERMISSIONS_CHAT_DELETION = (
os.environ.get("USER_PERMISSIONS_CHAT_DELETION", "True").lower() == "true"
)
USER_PERMISSIONS = {"chat": {"deletion": USER_PERMISSIONS_CHAT_DELETION}}
MODEL_FILTER_ENABLED = os.environ.get("MODEL_FILTER_ENABLED", False)
MODEL_FILTER_ENABLED = os.environ.get("MODEL_FILTER_ENABLED", "False").lower() == "true"
MODEL_FILTER_LIST = os.environ.get("MODEL_FILTER_LIST", "")
MODEL_FILTER_LIST = [model.strip() for model in MODEL_FILTER_LIST.split(";")]
WEBHOOK_URL = os.environ.get("WEBHOOK_URL", "")
####################################
# WEBUI_VERSION
@@ -368,3 +406,4 @@ WHISPER_MODEL_DIR = os.getenv("WHISPER_MODEL_DIR", f"{CACHE_DIR}/whisper/models"
####################################
AUTOMATIC1111_BASE_URL = os.getenv("AUTOMATIC1111_BASE_URL", "")
COMFYUI_BASE_URL = os.getenv("COMFYUI_BASE_URL", "")
+8 -1
View File
@@ -5,6 +5,13 @@ class MESSAGES(str, Enum):
DEFAULT = lambda msg="": f"{msg if msg else ''}"
class WEBHOOK_MESSAGES(str, Enum):
DEFAULT = lambda msg="": f"{msg if msg else ''}"
USER_SIGNUP = lambda username="": (
f"New user signed up: {username}" if username else "New user signed up"
)
class ERROR_MESSAGES(str, Enum):
def __str__(self) -> str:
return super().__str__()
@@ -46,7 +53,7 @@ class ERROR_MESSAGES(str, Enum):
PANDOC_NOT_INSTALLED = "Pandoc is not installed on the server. Please contact your administrator for assistance."
INCORRECT_FORMAT = (
lambda err="": f"Invalid format. Please use the correct format{err if err else ''}"
lambda err="": f"Invalid format. Please use the correct format{err}"
)
RATE_LIMIT_EXCEEDED = "API rate limit exceeded"
+1 -1
View File
@@ -1,5 +1,5 @@
{
"version": "0.0.1",
"version": 0,
"ui": {
"prompt_suggestions": [
{
+35 -3
View File
@@ -4,6 +4,7 @@ import markdown
import time
import os
import sys
import logging
import requests
from fastapi import FastAPI, Request, Depends, status
@@ -38,9 +39,15 @@ from config import (
FRONTEND_BUILD_DIR,
MODEL_FILTER_ENABLED,
MODEL_FILTER_LIST,
GLOBAL_LOG_LEVEL,
SRC_LOG_LEVELS,
WEBHOOK_URL,
)
from constants import ERROR_MESSAGES
logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL)
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MAIN"])
class SPAStaticFiles(StaticFiles):
async def get_response(self, path: str, scope):
@@ -58,6 +65,9 @@ app = FastAPI(docs_url="/docs" if ENV == "dev" else None, redoc_url=None)
app.state.MODEL_FILTER_ENABLED = MODEL_FILTER_ENABLED
app.state.MODEL_FILTER_LIST = MODEL_FILTER_LIST
app.state.WEBHOOK_URL = WEBHOOK_URL
origins = ["*"]
@@ -66,7 +76,7 @@ class RAGMiddleware(BaseHTTPMiddleware):
if request.method == "POST" and (
"/api/chat" in request.url.path or "/chat/completions" in request.url.path
):
print(request.url.path)
log.debug(f"request.url.path: {request.url.path}")
# Read the original request body
body = await request.body()
@@ -89,7 +99,7 @@ class RAGMiddleware(BaseHTTPMiddleware):
)
del data["docs"]
print(data["messages"])
log.debug(f"data['messages']: {data['messages']}")
modified_body_bytes = json.dumps(data).encode("utf-8")
@@ -178,7 +188,7 @@ class ModelFilterConfigForm(BaseModel):
@app.post("/api/config/model/filter")
async def get_model_filter_config(
async def update_model_filter_config(
form_data: ModelFilterConfigForm, user=Depends(get_admin_user)
):
@@ -197,6 +207,28 @@ async def get_model_filter_config(
}
@app.get("/api/webhook")
async def get_webhook_url(user=Depends(get_admin_user)):
return {
"url": app.state.WEBHOOK_URL,
}
class UrlForm(BaseModel):
url: str
@app.post("/api/webhook")
async def update_webhook_url(form_data: UrlForm, user=Depends(get_admin_user)):
app.state.WEBHOOK_URL = form_data.url
webui_app.state.WEBHOOK_URL = app.state.WEBHOOK_URL
return {
"url": app.state.WEBHOOK_URL,
}
@app.get("/api/version")
async def get_app_config():
+1
View File
@@ -45,3 +45,4 @@ PyJWT
pyjwt[crypto]
black
langfuse
+20
View File
@@ -0,0 +1,20 @@
import requests
def post_webhook(url: str, message: str, event_data: dict) -> bool:
try:
payload = {}
if "https://hooks.slack.com" in url:
payload["text"] = message
elif "https://discord.com/api/webhooks" in url:
payload["content"] = message
else:
payload = {**event_data}
r = requests.post(url, json=payload)
r.raise_for_status()
return True
except Exception as e:
print(e)
return False
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 MiB

After

Width:  |  Height:  |  Size: 5.0 MiB

+12
View File
@@ -50,6 +50,18 @@ We welcome pull requests. Before submitting one, please:
Help us make Open WebUI more accessible by improving documentation, writing tutorials, or creating guides on setting up and optimizing the web UI.
### 🌐 Translations and Internationalization
Help us make Open WebUI available to a wider audience. In this section, we'll guide you through the process of adding new translations to the project.
We use JSON files to store translations. You can find the existing translation files in the `src/lib/i18n/locales` directory. Each directory corresponds to a specific language, for example, `en-US` for English (US), `fr-FR` for French (France) and so on. You can refer to [ISO 639 Language Codes][http://www.lingoes.net/en/translator/langcode.htm] to find the appropriate code for a specific language.
To add a new language:
- Create a new directory in the `src/lib/i18n/locales` path with the appropriate language code as its name. For instance, if you're adding translations for Spanish (Spain), create a new directory named `es-ES`.
- Copy the American English translation file(s) (from `en-US` directory in `src/lib/i18n/locale`) to this new directory and update the string values in JSON format according to your language. Make sure to preserve the structure of the JSON object.
- Add the language code and its respective title to languages file at `src/lib/i18n/locales/languages.json`.
### 🤔 Questions & Feedback
Got questions or feedback? Join our [Discord community](https://discord.gg/5rJgQTnV4s) or open an issue. We're here to help!
+38
View File
@@ -0,0 +1,38 @@
// i18next-parser.config.ts
import { getLanguages } from './src/lib/i18n/index.ts';
const getLangCodes = async () => {
const languages = await getLanguages();
return languages.map((l) => l.code);
};
export default {
contextSeparator: '_',
createOldCatalogs: false,
defaultNamespace: 'translation',
defaultValue: '',
indentation: 2,
keepRemoved: false,
keySeparator: false,
lexers: {
svelte: ['JavascriptLexer'],
js: ['JavascriptLexer'],
ts: ['JavascriptLexer'],
default: ['JavascriptLexer']
},
lineEnding: 'auto',
locales: await getLangCodes(),
namespaceSeparator: false,
output: 'src/lib/i18n/locales/$LOCALE/$NAMESPACE.json',
pluralSeparator: '_',
input: 'src/**/*.{js,svelte}',
sort: true,
verbose: true,
failOnWarnings: false,
failOnUpdate: false,
customValueTemplate: null,
resetDefaultValueLocale: null,
i18nextOptions: null,
yamlOptions: null
};
+11 -6
View File
@@ -4,6 +4,9 @@ metadata:
name: {{ include "open-webui.name" . }}
labels:
{{- include "open-webui.labels" . | nindent 4 }}
{{- with .Values.webui.service.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.webui.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
@@ -11,14 +14,16 @@ metadata:
spec:
selector:
{{- include "open-webui.selectorLabels" . | nindent 4 }}
{{- with .Values.webui.service }}
type: {{ .type }}
type: {{ .Values.webui.service.type | default "ClusterIP" }}
ports:
- protocol: TCP
name: http
port: {{ .port }}
port: {{ .Values.webui.service.port }}
targetPort: http
{{- if .nodePort }}
nodePort: {{ .nodePort | int }}
{{- if .Values.webui.service.nodePort }}
nodePort: {{ .Values.webui.service.nodePort | int }}
{{- end }}
{{- end }}
{{- if .Values.webui.service.loadBalancerClass }}
loadBalancerClass: {{ .Values.webui.service.loadBalancerClass | quote }}
{{- end }}
+2
View File
@@ -70,3 +70,5 @@ webui:
port: 80
containerPort: 8080
nodePort: ""
labels: {}
loadBalancerClass: ""
+3116 -2945
View File
File diff suppressed because it is too large Load Diff
+8 -2
View File
@@ -1,6 +1,6 @@
{
"name": "open-webui",
"version": "0.1.112",
"version": "0.1.115",
"private": true,
"scripts": {
"dev": "vite dev --host",
@@ -13,7 +13,8 @@
"lint:types": "npm run check",
"lint:backend": "pylint backend/",
"format": "prettier --plugin-search-dir --write '**/*.{js,ts,svelte,css,md,html,json}'",
"format:backend": "yapf --recursive backend -p -i"
"format:backend": "yapf --recursive backend -p -i",
"i18n:parse": "i18next --config i18next-parser.config.ts && prettier --write 'src/lib/i18n/**/*.{js,json}'"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^2.0.0",
@@ -27,6 +28,7 @@
"eslint": "^8.56.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte": "^2.30.0",
"i18next-parser": "^8.13.0",
"postcss": "^8.4.31",
"prettier": "^2.8.0",
"prettier-plugin-svelte": "^2.10.1",
@@ -42,9 +44,13 @@
"dependencies": {
"@sveltejs/adapter-node": "^1.3.1",
"async": "^3.2.5",
"bits-ui": "^0.19.7",
"dayjs": "^1.11.10",
"file-saver": "^2.0.5",
"highlight.js": "^11.9.0",
"i18next": "^23.10.0",
"i18next-browser-languagedetector": "^7.2.0",
"i18next-resources-to-backend": "^1.2.0",
"idb": "^7.1.1",
"js-sha256": "^0.10.1",
"katex": "^0.16.9",
+28 -11
View File
@@ -8,18 +8,35 @@
<meta name="robots" content="noindex,nofollow" />
<script>
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
if (
localStorage.theme === 'light' ||
(!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: light)').matches)
) {
document.documentElement.classList.add('light');
} else if (localStorage.theme) {
localStorage.theme.split(' ').forEach((e) => {
document.documentElement.classList.add(e);
(() => {
if (
localStorage.theme === 'light' ||
(!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: light)').matches)
) {
document.documentElement.classList.add('light');
} else if (localStorage.theme && localStorage.theme !== 'system') {
localStorage.theme.split(' ').forEach((e) => {
document.documentElement.classList.add(e);
});
} else if (localStorage.theme && localStorage.theme === 'system') {
systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.classList.add(systemTheme ? 'dark' : 'light');
} else {
document.documentElement.classList.add('dark');
}
window.matchMedia('(prefers-color-scheme: dark)').addListener((e) => {
if (localStorage.theme === 'system') {
if (e.matches) {
document.documentElement.classList.add('dark');
document.documentElement.classList.remove('light');
} else {
document.documentElement.classList.add('light');
document.documentElement.classList.remove('dark');
}
}
});
} else {
document.documentElement.classList.add('dark');
}
})();
</script>
%sveltekit.head%
+5 -5
View File
@@ -139,7 +139,7 @@ export const updateOpenAIKey = async (token: string = '', key: string) => {
return res.OPENAI_API_KEY;
};
export const getAUTOMATIC1111Url = async (token: string = '') => {
export const getImageGenerationEngineUrls = async (token: string = '') => {
let error = null;
const res = await fetch(`${IMAGES_API_BASE_URL}/url`, {
@@ -168,10 +168,10 @@ export const getAUTOMATIC1111Url = async (token: string = '') => {
throw error;
}
return res.AUTOMATIC1111_BASE_URL;
return res;
};
export const updateAUTOMATIC1111Url = async (token: string = '', url: string) => {
export const updateImageGenerationEngineUrls = async (token: string = '', urls: object = {}) => {
let error = null;
const res = await fetch(`${IMAGES_API_BASE_URL}/url/update`, {
@@ -182,7 +182,7 @@ export const updateAUTOMATIC1111Url = async (token: string = '', url: string) =>
...(token && { authorization: `Bearer ${token}` })
},
body: JSON.stringify({
url: url
...urls
})
})
.then(async (res) => {
@@ -203,7 +203,7 @@ export const updateAUTOMATIC1111Url = async (token: string = '', url: string) =>
throw error;
}
return res.AUTOMATIC1111_BASE_URL;
return res;
};
export const getImageSize = async (token: string = '') => {
+57
View File
@@ -139,3 +139,60 @@ export const updateModelFilterConfig = async (
return res;
};
export const getWebhookUrl = async (token: string) => {
let error = null;
const res = await fetch(`${WEBUI_BASE_URL}/api/webhook`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.log(err);
error = err;
return null;
});
if (error) {
throw error;
}
return res.url;
};
export const updateWebhookUrl = async (token: string, url: string) => {
let error = null;
const res = await fetch(`${WEBUI_BASE_URL}/api/webhook`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
},
body: JSON.stringify({
url: url
})
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.log(err);
error = err;
return null;
});
if (error) {
throw error;
}
return res.url;
};
+68 -1
View File
@@ -271,7 +271,7 @@ export const generateChatCompletion = async (token: string = '', body: object) =
return [res, controller];
};
export const cancelChatCompletion = async (token: string = '', requestId: string) => {
export const cancelOllamaRequest = async (token: string = '', requestId: string) => {
let error = null;
const res = await fetch(`${OLLAMA_API_BASE_URL}/cancel/${requestId}`, {
@@ -390,6 +390,73 @@ export const pullModel = async (token: string, tagName: string, urlIdx: string |
return res;
};
export const downloadModel = async (
token: string,
download_url: string,
urlIdx: string | null = null
) => {
let error = null;
const res = await fetch(
`${OLLAMA_API_BASE_URL}/models/download${urlIdx !== null ? `/${urlIdx}` : ''}`,
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
},
body: JSON.stringify({
url: download_url
})
}
).catch((err) => {
console.log(err);
error = err;
if ('detail' in err) {
error = err.detail;
}
return null;
});
if (error) {
throw error;
}
return res;
};
export const uploadModel = async (token: string, file: File, urlIdx: string | null = null) => {
let error = null;
const formData = new FormData();
formData.append('file', file);
const res = await fetch(
`${OLLAMA_API_BASE_URL}/models/upload${urlIdx !== null ? `/${urlIdx}` : ''}`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${token}`
},
body: formData
}
).catch((err) => {
console.log(err);
error = err;
if ('detail' in err) {
error = err.detail;
}
return null;
});
if (error) {
throw error;
}
return res;
};
// export const pullModel = async (token: string, tagName: string) => {
// return await fetch(`${OLLAMA_API_BASE_URL}/pull`, {
// method: 'POST',
@@ -1,8 +1,13 @@
<script>
import { getContext } from 'svelte';
const i18n = getContext('i18n');
</script>
<div class=" text-center text-6xl mb-3">📄</div>
<div class="text-center dark:text-white text-2xl font-semibold z-50">Add Files</div>
<div class="text-center dark:text-white text-2xl font-semibold z-50">{$i18n.t('Add Files')}</div>
<slot
><div class=" mt-2 text-center text-sm dark:text-gray-200 w-full">
Drop any files here to add to the conversation
{$i18n.t('Drop any files here to add to the conversation')}
</div>
</slot>
+7 -4
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
import { Confetti } from 'svelte-confetti';
import { WEBUI_NAME, config } from '$lib/stores';
@@ -9,6 +9,8 @@
import Modal from './common/Modal.svelte';
const i18n = getContext('i18n');
export let show = false;
let changelog = null;
@@ -23,7 +25,8 @@
<div class="px-5 py-4 dark:text-gray-300">
<div class="flex justify-between items-start">
<div class="text-xl font-bold">
What’s New in {$WEBUI_NAME}
{$i18n.t('What’s New in')}
{$WEBUI_NAME}
<Confetti x={[-1, -0.25]} y={[0, 0.5]} />
</div>
<button
@@ -45,7 +48,7 @@
</button>
</div>
<div class="flex items-center mt-1">
<div class="text-sm dark:text-gray-200">Release Notes</div>
<div class="text-sm dark:text-gray-200">{$i18n.t('Release Notes')}</div>
<div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-700" />
<div class="text-sm dark:text-gray-200">
v{WEBUI_VERSION}
@@ -108,7 +111,7 @@
}}
class=" px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded"
>
<span class="relative">Okay, Let's Go!</span>
<span class="relative">{$i18n.t("Okay, Let's Go!")}</span>
</button>
</div>
</div>
@@ -2,11 +2,12 @@
import { toast } from 'svelte-sonner';
import dayjs from 'dayjs';
import { createEventDispatcher } from 'svelte';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
import { updateUserById } from '$lib/apis/users';
import Modal from '../common/Modal.svelte';
const i18n = getContext('i18n');
const dispatch = createEventDispatcher();
export let show = false;
@@ -42,7 +43,7 @@
<Modal size="sm" bind:show>
<div>
<div class=" flex justify-between dark:text-gray-300 px-5 py-4">
<div class=" text-lg font-medium self-center">Edit User</div>
<div class=" text-lg font-medium self-center">{$i18n.t('Edit User')}</div>
<button
class="self-center"
on:click={() => {
@@ -84,7 +85,8 @@
<div class=" self-center capitalize font-semibold">{selectedUser.name}</div>
<div class="text-xs text-gray-500">
Created at {dayjs(selectedUser.timestamp * 1000).format('MMMM DD, YYYY')}
{$i18n.t('Created at')}
{dayjs(selectedUser.timestamp * 1000).format($i18n.t('MMMM DD, YYYY'))}
</div>
</div>
</div>
@@ -93,7 +95,7 @@
<div class=" flex flex-col space-y-1.5">
<div class="flex flex-col w-full">
<div class=" mb-1 text-xs text-gray-500">Email</div>
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Email')}</div>
<div class="flex-1">
<input
@@ -108,7 +110,7 @@
</div>
<div class="flex flex-col w-full">
<div class=" mb-1 text-xs text-gray-500">Name</div>
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Name')}</div>
<div class="flex-1">
<input
@@ -122,7 +124,7 @@
</div>
<div class="flex flex-col w-full">
<div class=" mb-1 text-xs text-gray-500">New Password</div>
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('New Password')}</div>
<div class="flex-1">
<input
@@ -140,7 +142,7 @@
class=" px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded"
type="submit"
>
Save
{$i18n.t('Save')}
</button>
</div>
</form>
@@ -1,6 +1,8 @@
<script lang="ts">
import { downloadDatabase } from '$lib/apis/utils';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
const i18n = getContext('i18n');
export let saveHandler: Function;
@@ -17,10 +19,10 @@
>
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
<div>
<div class=" mb-2 text-sm font-medium">Database</div>
<div class=" mb-2 text-sm font-medium">{$i18n.t('Database')}</div>
<div class=" flex w-full justify-between">
<!-- <div class=" self-center text-xs font-medium">Allow Chat Deletion</div> -->
<!-- <div class=" self-center text-xs font-medium">{$i18n.t('Allow Chat Deletion')}</div> -->
<button
class=" flex rounded-md py-1.5 px-3 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
@@ -46,7 +48,7 @@
/>
</svg>
</div>
<div class=" self-center text-sm font-medium">Download Database</div>
<div class=" self-center text-sm font-medium">{$i18n.t('Download Database')}</div>
</button>
</div>
</div>
@@ -1,4 +1,5 @@
<script lang="ts">
import { getWebhookUrl, updateWebhookUrl } from '$lib/apis';
import {
getDefaultUserRole,
getJWTExpiresDuration,
@@ -7,13 +8,17 @@
updateDefaultUserRole,
updateJWTExpiresDuration
} from '$lib/apis/auths';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
const i18n = getContext('i18n');
export let saveHandler: Function;
let signUpEnabled = true;
let defaultUserRole = 'pending';
let JWTExpiresIn = '';
let webhookUrl = '';
const toggleSignUpEnabled = async () => {
signUpEnabled = await toggleSignUpEnabledStatus(localStorage.token);
};
@@ -26,27 +31,32 @@
JWTExpiresIn = await updateJWTExpiresDuration(localStorage.token, duration);
};
const updateWebhookUrlHandler = async () => {
webhookUrl = await updateWebhookUrl(localStorage.token, webhookUrl);
};
onMount(async () => {
signUpEnabled = await getSignUpEnabledStatus(localStorage.token);
defaultUserRole = await getDefaultUserRole(localStorage.token);
JWTExpiresIn = await getJWTExpiresDuration(localStorage.token);
webhookUrl = await getWebhookUrl(localStorage.token);
});
</script>
<form
class="flex flex-col h-full justify-between space-y-3 text-sm"
on:submit|preventDefault={() => {
// console.log('submit');
updateJWTExpiresDurationHandler(JWTExpiresIn);
updateWebhookUrlHandler();
saveHandler();
}}
>
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
<div>
<div class=" mb-2 text-sm font-medium">General Settings</div>
<div class=" mb-2 text-sm font-medium">{$i18n.t('General Settings')}</div>
<div class=" flex w-full justify-between">
<div class=" self-center text-xs font-medium">Enable New Sign Ups</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Enable New Sign Ups')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -66,7 +76,7 @@
d="M11.5 1A3.5 3.5 0 0 0 8 4.5V7H2.5A1.5 1.5 0 0 0 1 8.5v5A1.5 1.5 0 0 0 2.5 15h7a1.5 1.5 0 0 0 1.5-1.5v-5A1.5 1.5 0 0 0 9.5 7V4.5a2 2 0 1 1 4 0v1.75a.75.75 0 0 0 1.5 0V4.5A3.5 3.5 0 0 0 11.5 1Z"
/>
</svg>
<span class="ml-2 self-center">Enabled</span>
<span class="ml-2 self-center">{$i18n.t('Enabled')}</span>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -81,25 +91,25 @@
/>
</svg>
<span class="ml-2 self-center">Disabled</span>
<span class="ml-2 self-center">{$i18n.t('Disabled')}</span>
{/if}
</button>
</div>
<div class=" flex w-full justify-between">
<div class=" self-center text-xs font-medium">Default User Role</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Default User Role')}</div>
<div class="flex items-center relative">
<select
class="w-fit pr-8 rounded py-2 px-2 text-xs bg-transparent outline-none text-right"
class="dark:bg-gray-900 w-fit pr-8 rounded py-2 px-2 text-xs bg-transparent outline-none text-right"
bind:value={defaultUserRole}
placeholder="Select a theme"
on:change={(e) => {
updateDefaultUserRoleHandler(e.target.value);
}}
>
<option value="pending">Pending</option>
<option value="user">User</option>
<option value="admin">Admin</option>
<option value="pending">{$i18n.t('pending')}</option>
<option value="user">{$i18n.t('user')}</option>
<option value="admin">{$i18n.t('admin')}</option>
</select>
</div>
</div>
@@ -108,7 +118,24 @@
<div class=" w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">JWT Expiration</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Webhook URL')}</div>
</div>
<div class="flex mt-2 space-x-2">
<input
class="w-full rounded py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none border border-gray-100 dark:border-gray-600"
type="text"
placeholder={`https://example.com/webhook`}
bind:value={webhookUrl}
/>
</div>
</div>
<hr class=" dark:border-gray-700 my-3" />
<div class=" w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('JWT Expiration')}</div>
</div>
<div class="flex mt-2 space-x-2">
@@ -121,8 +148,9 @@
</div>
<div class="mt-2 text-xs text-gray-400 dark:text-gray-500">
Valid time units: <span class=" text-gray-300 font-medium"
>'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.</span
{$i18n.t('Valid time units:')}
<span class=" text-gray-300 font-medium"
>{$i18n.t("'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.")}</span
>
</div>
</div>
@@ -134,7 +162,7 @@
class=" px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded"
type="submit"
>
Save
{$i18n.t('Save')}
</button>
</div>
</form>
+15 -11
View File
@@ -2,8 +2,11 @@
import { getModelFilterConfig, updateModelFilterConfig } from '$lib/apis';
import { getSignUpEnabledStatus, toggleSignUpEnabledStatus } from '$lib/apis/auths';
import { getUserPermissions, updateUserPermissions } from '$lib/apis/users';
import { onMount, getContext } from 'svelte';
import { models } from '$lib/stores';
import { onMount } from 'svelte';
const i18n = getContext('i18n');
export let saveHandler: Function;
@@ -39,10 +42,10 @@
>
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
<div>
<div class=" mb-2 text-sm font-medium">User Permissions</div>
<div class=" mb-2 text-sm font-medium">{$i18n.t('User Permissions')}</div>
<div class=" flex w-full justify-between">
<div class=" self-center text-xs font-medium">Allow Chat Deletion</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Allow Chat Deletion')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -62,7 +65,7 @@
d="M11.5 1A3.5 3.5 0 0 0 8 4.5V7H2.5A1.5 1.5 0 0 0 1 8.5v5A1.5 1.5 0 0 0 2.5 15h7a1.5 1.5 0 0 0 1.5-1.5v-5A1.5 1.5 0 0 0 9.5 7V4.5a2 2 0 1 1 4 0v1.75a.75.75 0 0 0 1.5 0V4.5A3.5 3.5 0 0 0 11.5 1Z"
/>
</svg>
<span class="ml-2 self-center">Allow</span>
<span class="ml-2 self-center">{$i18n.t('Allow')}</span>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -77,7 +80,7 @@
/>
</svg>
<span class="ml-2 self-center">Don't Allow</span>
<span class="ml-2 self-center">{$i18n.t("Don't Allow")}</span>
{/if}
</button>
</div>
@@ -89,21 +92,21 @@
<div>
<div class="mb-2">
<div class="flex justify-between items-center text-xs">
<div class=" text-sm font-medium">Manage Models</div>
<div class=" text-sm font-medium">{$i18n.t('Manage Models')}</div>
</div>
</div>
<div class=" space-y-3">
<div>
<div class="flex justify-between items-center text-xs">
<div class=" text-xs font-medium">Model Whitelisting</div>
<div class=" text-xs font-medium">{$i18n.t('Model Whitelisting')}</div>
<button
class=" text-xs font-medium text-gray-500"
type="button"
on:click={() => {
whitelistEnabled = !whitelistEnabled;
}}>{whitelistEnabled ? 'On' : 'Off'}</button
}}>{whitelistEnabled ? $i18n.t('On') : $i18n.t('Off')}</button
>
</div>
</div>
@@ -119,7 +122,7 @@
bind:value={modelId}
placeholder="Select a model"
>
<option value="" disabled selected>Select a model</option>
<option value="" disabled selected>{$i18n.t('Select a model')}</option>
{#each $models.filter((model) => model.id) as model}
<option value={model.id} class="bg-gray-100 dark:bg-gray-700"
>{model.name}</option
@@ -174,7 +177,8 @@
<div class="flex justify-end items-center text-xs mt-1.5 text-right">
<div class=" text-xs font-medium">
{whitelistModels.length} Model(s) Whitelisted
{whitelistModels.length}
{$i18n.t('Model(s) Whitelisted')}
</div>
</div>
</div>
@@ -189,7 +193,7 @@
class=" px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded"
type="submit"
>
Save
{$i18n.t('Save')}
</button>
</div>
</form>
@@ -1,10 +1,13 @@
<script>
import { getContext } from 'svelte';
import Modal from '../common/Modal.svelte';
import Database from './Settings/Database.svelte';
import General from './Settings/General.svelte';
import Users from './Settings/Users.svelte';
const i18n = getContext('i18n');
export let show = false;
let selectedTab = 'general';
@@ -13,7 +16,7 @@
<Modal bind:show>
<div>
<div class=" flex justify-between dark:text-gray-300 px-5 py-4">
<div class=" text-lg font-medium self-center">Admin Settings</div>
<div class=" text-lg font-medium self-center">{$i18n.t('Admin Settings')}</div>
<button
class="self-center"
on:click={() => {
@@ -61,7 +64,7 @@
/>
</svg>
</div>
<div class=" self-center">General</div>
<div class=" self-center">{$i18n.t('General')}</div>
</button>
<button
@@ -85,7 +88,7 @@
/>
</svg>
</div>
<div class=" self-center">Users</div>
<div class=" self-center">{$i18n.t('Users')}</div>
</button>
<button
@@ -113,7 +116,7 @@
/>
</svg>
</div>
<div class=" self-center">Database</div>
<div class=" self-center">{$i18n.t('Database')}</div>
</button>
</div>
<div class="flex-1 md:min-h-[380px]">
+23 -15
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { toast } from 'svelte-sonner';
import { onMount, tick } from 'svelte';
import { onMount, tick, getContext } from 'svelte';
import { settings } from '$lib/stores';
import { blobToFile, calculateSHA256, findWordIndices } from '$lib/utils';
@@ -14,6 +14,8 @@
import { transcribeAudio } from '$lib/apis/audio';
import Tooltip from '../common/Tooltip.svelte';
const i18n = getContext('i18n');
export let submitPrompt: Function;
export let stopResponse: Function;
@@ -209,11 +211,11 @@
// Event triggered when an error occurs
speechRecognition.onerror = function (event) {
console.log(event);
toast.error(`Speech recognition error: ${event.error}`);
toast.error($i18n.t(`Speech recognition error: {{error}}`, { error: event.error }));
isRecording = false;
};
} else {
toast.error('SpeechRecognition API is not supported in this browser.');
toast.error($i18n.t('SpeechRecognition API is not supported in this browser.'));
}
}
}
@@ -333,12 +335,15 @@
uploadDoc(file);
} else {
toast.error(
`Unknown File Type '${file['type']}', but accepting and treating as plain text`
$i18n.t(
`Unknown File Type '{{file_type}}', but accepting and treating as plain text`,
{ file_type: file['type'] }
)
);
uploadDoc(file);
}
} else {
toast.error(`File not found.`);
toast.error($i18n.t(`File not found.`));
}
}
@@ -477,13 +482,16 @@
filesInputElement.value = '';
} else {
toast.error(
`Unknown File Type '${file['type']}', but accepting and treating as plain text`
$i18n.t(
`Unknown File Type '{{file_type}}', but accepting and treating as plain text`,
{ file_type: file['type'] }
)
);
uploadDoc(file);
filesInputElement.value = '';
}
} else {
toast.error(`File not found.`);
toast.error($i18n.t(`File not found.`));
}
}}
/>
@@ -570,7 +578,7 @@
{file.name}
</div>
<div class=" text-gray-500 text-sm">Document</div>
<div class=" text-gray-500 text-sm">{$i18n.t('Document')}</div>
</div>
</div>
{:else if file.type === 'collection'}
@@ -598,7 +606,7 @@
{file?.title ?? `#${file.name}`}
</div>
<div class=" text-gray-500 text-sm">Collection</div>
<div class=" text-gray-500 text-sm">{$i18n.t('Collection')}</div>
</div>
</div>
{/if}
@@ -632,7 +640,7 @@
<div class=" flex">
{#if fileUploadEnabled}
<div class=" self-end mb-2 ml-1">
<Tooltip content="Upload files">
<Tooltip content={$i18n.t('Upload files')}>
<button
class="bg-gray-50 hover:bg-gray-100 text-gray-800 dark:bg-gray-850 dark:text-white dark:hover:bg-gray-800 transition rounded-full p-1.5"
type="button"
@@ -664,8 +672,8 @@
placeholder={chatInputPlaceholder !== ''
? chatInputPlaceholder
: isRecording
? 'Listening...'
: 'Send a message'}
? $i18n.t('Listening...')
: $i18n.t('Send a Message')}
bind:value={prompt}
on:keypress={(e) => {
if (e.keyCode == 13 && !e.shiftKey) {
@@ -804,7 +812,7 @@
<div class="self-end mb-2 flex space-x-1 mr-1">
{#if messages.length == 0 || messages.at(-1).done == true}
<Tooltip content="Record voice">
<Tooltip content={$i18n.t('Record voice')}>
{#if speechRecognitionEnabled}
<button
id="voice-input-button"
@@ -873,7 +881,7 @@
{/if}
</Tooltip>
<Tooltip content="Send message">
<Tooltip content={$i18n.t('Send message')}>
<button
class="{prompt !== ''
? 'bg-black text-white hover:bg-gray-900 dark:bg-white dark:text-black dark:hover:bg-gray-100 '
@@ -919,7 +927,7 @@
</form>
<div class="mt-1.5 text-xs text-gray-500 text-center">
LLMs can make mistakes. Verify important information.
{$i18n.t('LLMs can make mistakes. Verify important information.')}
</div>
</div>
</div>
@@ -3,9 +3,11 @@
import { documents } from '$lib/stores';
import { removeFirstHashWord, isValidHttpUrl } from '$lib/utils';
import { tick } from 'svelte';
import { tick, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
const i18n = getContext('i18n');
export let prompt = '';
const dispatch = createEventDispatcher();
@@ -117,7 +119,7 @@
{doc?.title ?? `#${doc.name}`}
</div>
<div class=" text-xs text-gray-600 line-clamp-1">Collection</div>
<div class=" text-xs text-gray-600 line-clamp-1">{$i18n.t('Collection')}</div>
{:else}
<div class=" font-medium text-black line-clamp-1">
#{doc.name} ({doc.filename})
@@ -140,7 +142,9 @@
confirmSelectWeb(url);
} else {
toast.error(
'Oops! Looks like the URL is invalid. Please double-check and try again.'
$i18n.t(
'Oops! Looks like the URL is invalid. Please double-check and try again.'
)
);
}
}}
@@ -149,7 +153,7 @@
{prompt.split(' ')?.at(0)?.substring(1)}
</div>
<div class=" text-xs text-gray-600 line-clamp-1">Web</div>
<div class=" text-xs text-gray-600 line-clamp-1">{$i18n.t('Web')}</div>
</button>
{/if}
</div>
@@ -2,9 +2,11 @@
import { generatePrompt } from '$lib/apis/ollama';
import { models } from '$lib/stores';
import { splitStream } from '$lib/utils';
import { tick } from 'svelte';
import { tick, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
const i18n = getContext('i18n');
export let prompt = '';
export let user = null;
@@ -41,7 +43,7 @@
user = JSON.parse(JSON.stringify(model.name));
await tick();
chatInputPlaceholder = `'${model.name}' is thinking...`;
chatInputPlaceholder = $i18n.t('{{modelName}} is thinking...', { modelName: model.name });
const chatInputElement = document.getElementById('chat-textarea');
@@ -113,7 +115,9 @@
toast.error(error.error);
}
} else {
toast.error(`Uh-oh! There was an issue connecting to Ollama.`);
toast.error(
$i18n.t('Uh-oh! There was an issue connecting to {{provider}}.', { provider: 'llama' })
);
}
}
@@ -1,9 +1,11 @@
<script lang="ts">
import { prompts } from '$lib/stores';
import { findWordIndices } from '$lib/utils';
import { tick } from 'svelte';
import { tick, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
const i18n = getContext('i18n');
export let prompt = '';
let selectedCommandIdx = 0;
let filteredPromptCommands = [];
@@ -29,7 +31,7 @@
if (command.content.includes('{{CLIPBOARD}}')) {
const clipboardText = await navigator.clipboard.readText().catch((err) => {
toast.error('Failed to read clipboard contents');
toast.error($i18n.t('Failed to read clipboard contents'));
return '{{CLIPBOARD}}';
});
@@ -113,8 +115,9 @@
</div>
<div class="line-clamp-1">
Tip: Update multiple variable slots consecutively by pressing the tab key in the chat
input after each replacement.
{$i18n.t(
'Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.'
)}
</div>
</div>
</div>
+4 -2
View File
@@ -2,7 +2,7 @@
import { v4 as uuidv4 } from 'uuid';
import { chats, config, modelfiles, settings, user } from '$lib/stores';
import { tick } from 'svelte';
import { tick, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
import { getChatList, updateChatById } from '$lib/apis/chats';
@@ -13,6 +13,8 @@
import Spinner from '../common/Spinner.svelte';
import { imageGenerations } from '$lib/apis/images';
const i18n = getContext('i18n');
export let chatId = '';
export let sendPrompt: Function;
export let continueGeneration: Function;
@@ -67,7 +69,7 @@
navigator.clipboard.writeText(text).then(
function () {
console.log('Async: Copying to clipboard was successful!');
toast.success('Copying to clipboard was successful!');
toast.success($i18n.t('Copying to clipboard was successful!'));
},
function (err) {
console.error('Async: Could not copy text: ', err);
@@ -1,7 +1,9 @@
<script lang="ts">
import { WEBUI_BASE_URL } from '$lib/constants';
import { user } from '$lib/stores';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
const i18n = getContext('i18n');
export let models = [];
export let modelfiles = [];
@@ -31,7 +33,7 @@
<img
src={modelfiles[model]?.imageUrl ?? `${WEBUI_BASE_URL}/static/favicon.png`}
alt="modelfile"
class=" w-14 rounded-full border-[1px] border-gray-200 dark:border-none"
class=" size-12 rounded-full border-[1px] border-gray-200 dark:border-none"
draggable="false"
/>
{:else}
@@ -39,7 +41,7 @@
src={models.length === 1
? `${WEBUI_BASE_URL}/static/favicon.png`
: `${WEBUI_BASE_URL}/static/favicon.png`}
class=" w-14 rounded-full border-[1px] border-gray-200 dark:border-none"
class=" size-12 rounded-full border-[1px] border-gray-200 dark:border-none"
alt="logo"
draggable="false"
/>
@@ -64,9 +66,9 @@
</div>
{/if}
{:else}
<div class=" line-clamp-1">Hello, {$user.name}</div>
<div class=" line-clamp-1">{$i18n.t('Hello, {{name}}', { name: $user.name })}</div>
<div>How can I help you today?</div>
<div>{$i18n.t('How can I help you today?')}</div>
{/if}
</div>
</div>
@@ -8,7 +8,9 @@
import { fade } from 'svelte/transition';
import { createEventDispatcher } from 'svelte';
import { onMount, tick } from 'svelte';
import { onMount, tick, getContext } from 'svelte';
const i18n = getContext('i18n');
const dispatch = createEventDispatcher();
@@ -316,7 +318,7 @@
{#if message.timestamp}
<span class=" invisible group-hover:visible text-gray-400 text-xs font-medium">
{dayjs(message.timestamp * 1000).format('DD/MM/YYYY HH:mm')}
{dayjs(message.timestamp * 1000).format($i18n.t('DD/MM/YYYY HH:mm'))}
</span>
{/if}
</Name>
@@ -360,7 +362,7 @@
editMessageConfirmHandler();
}}
>
Save
{$i18n.t('Save')}
</button>
<button
@@ -369,7 +371,7 @@
cancelEditMessage();
}}
>
Cancel
{$i18n.t('Cancel')}
</button>
</div>
</div>
@@ -420,7 +422,7 @@
class=" flex justify-start space-x-1 overflow-x-auto buttons text-gray-700 dark:text-gray-500"
>
{#if siblings.length > 1}
<div class="flex self-center min-w-fit">
<div class="flex self-center min-w-fit -mt-1">
<button
class="self-center dark:hover:text-white hover:text-black transition"
on:click={() => {
@@ -1,12 +1,14 @@
<script lang="ts">
import dayjs from 'dayjs';
import { tick, createEventDispatcher } from 'svelte';
import { tick, createEventDispatcher, getContext } from 'svelte';
import Name from './Name.svelte';
import ProfileImage from './ProfileImage.svelte';
import { modelfiles, settings } from '$lib/stores';
import Tooltip from '$lib/components/common/Tooltip.svelte';
const i18n = getContext('i18n');
const dispatch = createEventDispatcher();
export let user;
@@ -65,17 +67,18 @@
{#if $modelfiles.map((modelfile) => modelfile.tagName).includes(message.user)}
{$modelfiles.find((modelfile) => modelfile.tagName === message.user)?.title}
{:else}
You <span class=" text-gray-500 text-sm font-medium">{message?.user ?? ''}</span>
{$i18n.t('You')}
<span class=" text-gray-500 text-sm font-medium">{message?.user ?? ''}</span>
{/if}
{:else if $settings.showUsername}
{user.name}
{:else}
You
{$i18n.t('You')}
{/if}
{#if message.timestamp}
<span class=" invisible group-hover:visible text-gray-400 text-xs font-medium">
{dayjs(message.timestamp * 1000).format('DD/MM/YYYY HH:mm')}
{dayjs(message.timestamp * 1000).format($i18n.t('DD/MM/YYYY HH:mm'))}
</span>
{/if}
</Name>
@@ -123,7 +126,7 @@
{file.name}
</div>
<div class=" text-gray-500 text-sm">Document</div>
<div class=" text-gray-500 text-sm">{$i18n.t('Document')}</div>
</div>
</button>
{:else if file.type === 'collection'}
@@ -152,7 +155,7 @@
{file?.title ?? `#${file.name}`}
</div>
<div class=" text-gray-500 text-sm">Collection</div>
<div class=" text-gray-500 text-sm">{$i18n.t('Collection')}</div>
</div>
</button>
{/if}
@@ -181,7 +184,7 @@
editMessageConfirmHandler();
}}
>
Save & Submit
{$i18n.t('Save & Submit')}
</button>
<button
@@ -190,7 +193,7 @@
cancelEditMessage();
}}
>
Cancel
{$i18n.t('Cancel')}
</button>
</div>
</div>
@@ -200,7 +203,7 @@
<div class=" flex justify-start space-x-1 text-gray-700 dark:text-gray-500">
{#if siblings.length > 1}
<div class="flex self-center">
<div class="flex self-center -mt-1">
<button
class="self-center dark:hover:text-white hover:text-black transition"
on:click={() => {
+25 -26
View File
@@ -1,8 +1,11 @@
<script lang="ts">
import { setDefaultModels } from '$lib/apis/configs';
import { models, showSettings, settings, user } from '$lib/stores';
import { onMount, tick } from 'svelte';
import { onMount, tick, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
import Select from '../common/Select.svelte';
const i18n = getContext('i18n');
export let selectedModels = [''];
export let disabled = false;
@@ -10,7 +13,7 @@
const saveDefaultModel = async () => {
const hasEmptyModel = selectedModels.filter((it) => it === '');
if (hasEmptyModel.length) {
toast.error('Choose a model before saving...');
toast.error($i18n.t('Choose a model before saving...'));
return;
}
settings.set({ ...$settings, models: selectedModels });
@@ -20,7 +23,7 @@
console.log('setting default models globally');
await setDefaultModels(localStorage.token, selectedModels.join(','));
}
toast.success('Default model updated');
toast.success($i18n.t('Default model updated'));
};
$: if (selectedModels.length > 0 && $models.length > 0) {
@@ -30,28 +33,24 @@
}
</script>
<div class="flex flex-col my-2">
<div class="flex flex-col my-2 w-full">
{#each selectedModels as selectedModel, selectedModelIdx}
<div class="flex">
<select
id="models"
class="outline-none bg-transparent text-lg font-semibold rounded-lg block w-full placeholder-gray-400"
bind:value={selectedModel}
{disabled}
>
<option class=" text-gray-700" value="" selected disabled>Select a model</option>
{#each $models as model}
{#if model.name === 'hr'}
<hr />
{:else}
<option value={model.id} class="text-gray-700 text-lg"
>{model.name +
`${model.size ? ` (${(model.size / 1024 ** 3).toFixed(1)}GB)` : ''}`}</option
>
{/if}
{/each}
</select>
<div class="flex w-full">
<div class="overflow-hidden w-full">
<div class="mr-2 max-w-full">
<Select
placeholder={$i18n.t('Select a model')}
items={$models
.filter((model) => model.name !== 'hr')
.map((model) => ({
value: model.id,
label:
model.name + `${model.size ? ` (${(model.size / 1024 ** 3).toFixed(1)}GB)` : ''}`
}))}
bind:value={selectedModel}
/>
</div>
</div>
{#if selectedModelIdx === 0}
<button
@@ -132,6 +131,6 @@
{/each}
</div>
<div class="text-left mt-1.5 text-xs text-gray-500">
<button on:click={saveDefaultModel}> Set as default</button>
<div class="text-left mt-1.5 ml-1 text-xs text-gray-500">
<button on:click={saveDefaultModel}> {$i18n.t('Set as default')}</button>
</div>
+13 -9
View File
@@ -4,7 +4,9 @@
import { WEBUI_VERSION } from '$lib/constants';
import { WEBUI_NAME, config, showChangelog } from '$lib/stores';
import { compareVersion } from '$lib/utils';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
const i18n = getContext('i18n');
let ollamaVersion = '';
@@ -43,7 +45,8 @@
<div>
<div class=" mb-2.5 text-sm font-medium flex space-x-2 items-center">
<div>
{$WEBUI_NAME} Version
{$WEBUI_NAME}
{$i18n.t('Version')}
</div>
</div>
<div class="flex w-full justify-between items-center">
@@ -56,10 +59,10 @@
target="_blank"
>
{updateAvailable === null
? 'Checking for updates...'
? $i18n.t('Checking for updates...')
: updateAvailable
? `(v${version.latest} available!)`
: '(latest)'}
? `(v${version.latest} ${$i18n.t('available!')})`
: $i18n.t('(latest)')}
</a>
</div>
@@ -69,7 +72,7 @@
showChangelog.set(true);
}}
>
<div>See what's new</div>
<div>{$i18n.t("See what's new")}</div>
</button>
</div>
@@ -79,7 +82,7 @@
checkForVersionUpdates();
}}
>
Check for updates
{$i18n.t('Check for updates')}
</button>
</div>
</div>
@@ -88,7 +91,7 @@
<hr class=" dark:border-gray-700" />
<div>
<div class=" mb-2.5 text-sm font-medium">Ollama Version</div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Ollama Version')}</div>
<div class="flex w-full">
<div class="flex-1 text-xs text-gray-700 dark:text-gray-200">
{ollamaVersion ?? 'N/A'}
@@ -123,7 +126,8 @@
</div>
<div class="mt-2 text-xs text-gray-400 dark:text-gray-500">
Created by <a
{$i18n.t('Created by')}
<a
class=" text-gray-500 dark:text-gray-300 font-medium"
href="https://github.com/tjbck"
target="_blank">Timothy J. Baek</a
@@ -1,6 +1,6 @@
<script lang="ts">
import { toast } from 'svelte-sonner';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
import { user } from '$lib/stores';
import { updateUserProfile } from '$lib/apis/auths';
@@ -9,6 +9,8 @@
import { getGravatarUrl } from '$lib/apis/utils';
import { copyToClipboard } from '$lib/utils';
const i18n = getContext('i18n');
export let saveHandler: Function;
let profileImageUrl = '';
@@ -38,7 +40,7 @@
</script>
<div class="flex flex-col h-full justify-between text-sm">
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-[22rem]">
<input
id="profile-image-input"
bind:this={profileImageInputElement}
@@ -101,7 +103,7 @@
}}
/>
<div class=" mb-2.5 text-sm font-medium">Profile</div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Profile')}</div>
<div class="flex space-x-5">
<div class="flex flex-col">
@@ -143,13 +145,13 @@
const url = await getGravatarUrl($user.email);
profileImageUrl = url;
}}>Use Gravatar</button
}}>{$i18n.t('Use Gravatar')}</button
>
</div>
<div class="flex-1">
<div class="flex flex-col w-full">
<div class=" mb-1 text-xs text-gray-500">Name</div>
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Name')}</div>
<div class="flex-1">
<input
@@ -170,7 +172,7 @@
<div class=" w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">JWT Token</div>
<div class=" self-center text-xs font-medium">{$i18n.t('JWT Token')}</div>
</div>
<div class="flex mt-2">
@@ -280,7 +282,7 @@
}
}}
>
Save
{$i18n.t('Save')}
</button>
</div>
</div>
@@ -1,7 +1,10 @@
<script lang="ts">
import { getContext } from 'svelte';
import { toast } from 'svelte-sonner';
import { updateUserPassword } from '$lib/apis/auths';
const i18n = getContext('i18n');
let show = false;
let currentPassword = '';
let newPassword = '';
@@ -17,7 +20,7 @@
);
if (res) {
toast.success('Successfully updated.');
toast.success($i18n.t('Successfully updated.'));
}
currentPassword = '';
@@ -40,20 +43,20 @@
}}
>
<div class="flex justify-between items-center text-sm">
<div class=" font-medium">Change Password</div>
<div class=" font-medium">{$i18n.t('Change Password')}</div>
<button
class=" text-xs font-medium text-gray-500"
type="button"
on:click={() => {
show = !show;
}}>{show ? 'Hide' : 'Show'}</button
}}>{show ? $i18n.t('Hide') : $i18n.t('Show')}</button
>
</div>
{#if show}
<div class=" py-2.5 space-y-1.5">
<div class="flex flex-col w-full">
<div class=" mb-1 text-xs text-gray-500">Current Password</div>
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Current Password')}</div>
<div class="flex-1">
<input
@@ -67,7 +70,7 @@
</div>
<div class="flex flex-col w-full">
<div class=" mb-1 text-xs text-gray-500">New Password</div>
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('New Password')}</div>
<div class="flex-1">
<input
@@ -81,7 +84,7 @@
</div>
<div class="flex flex-col w-full">
<div class=" mb-1 text-xs text-gray-500">Confirm Password</div>
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Confirm Password')}</div>
<div class="flex-1">
<input
@@ -99,7 +102,7 @@
<button
class=" px-4 py-2 text-xs bg-gray-800 hover:bg-gray-900 dark:bg-gray-700 dark:hover:bg-gray-800 text-gray-100 transition rounded-md font-medium"
>
Update password
{$i18n.t('Update password')}
</button>
</div>
{/if}
@@ -1,8 +1,10 @@
<script lang="ts">
import { createEventDispatcher, onMount } from 'svelte';
import { createEventDispatcher, onMount, getContext } from 'svelte';
import AdvancedParams from './Advanced/AdvancedParams.svelte';
const i18n = getContext('i18n');
const dispatch = createEventDispatcher();
import AdvancedParams from './Advanced/AdvancedParams.svelte';
export let saveSettings: Function;
// Advanced
@@ -55,14 +57,14 @@
<div class="flex flex-col h-full justify-between text-sm">
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
<div class=" text-sm font-medium">Parameters</div>
<div class=" text-sm font-medium">{$i18n.t('Parameters')}</div>
<AdvancedParams bind:options />
<hr class=" dark:border-gray-700" />
<div class=" py-1 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Keep Alive</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Keep Alive')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -72,9 +74,9 @@
}}
>
{#if keepAlive === null}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center">{$i18n.t('Custom')}</span>
{/if}
</button>
</div>
@@ -84,7 +86,7 @@
<input
class="w-full rounded py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none border border-gray-100 dark:border-gray-600"
type="text"
placeholder={`e.g.) "30s","10m". Valid time units are "s", "m", "h".`}
placeholder={$i18n.t("e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.")}
bind:value={keepAlive}
/>
</div>
@@ -93,7 +95,7 @@
<div>
<div class=" py-1 flex w-full justify-between">
<div class=" self-center text-sm font-medium">Request Mode</div>
<div class=" self-center text-sm font-medium">{$i18n.t('Request Mode')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -102,7 +104,7 @@
}}
>
{#if requestFormat === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center"> {$i18n.t('Default')} </span>
{:else if requestFormat === 'json'}
<!-- <svg
xmlns="http://www.w3.org/2000/svg"
@@ -114,7 +116,7 @@
d="M10 2a.75.75 0 01.75.75v1.5a.75.75 0 01-1.5 0v-1.5A.75.75 0 0110 2zM10 15a.75.75 0 01.75.75v1.5a.75.75 0 01-1.5 0v-1.5A.75.75 0 0110 15zM10 7a3 3 0 100 6 3 3 0 000-6zM15.657 5.404a.75.75 0 10-1.06-1.06l-1.061 1.06a.75.75 0 001.06 1.06l1.06-1.06zM6.464 14.596a.75.75 0 10-1.06-1.06l-1.06 1.06a.75.75 0 001.06 1.06l1.06-1.06zM18 10a.75.75 0 01-.75.75h-1.5a.75.75 0 010-1.5h1.5A.75.75 0 0118 10zM5 10a.75.75 0 01-.75.75h-1.5a.75.75 0 010-1.5h1.5A.75.75 0 015 10zM14.596 15.657a.75.75 0 001.06-1.06l-1.06-1.061a.75.75 0 10-1.06 1.06l1.06 1.06zM5.404 6.464a.75.75 0 001.06-1.06l-1.06-1.06a.75.75 0 10-1.061 1.06l1.06 1.06z"
/>
</svg> -->
<span class="ml-2 self-center"> JSON </span>
<span class="ml-2 self-center">{$i18n.t('JSON')}</span>
{/if}
</button>
</div>
@@ -147,7 +149,7 @@
dispatch('save');
}}
>
Save
{$i18n.t('Save')}
</button>
</div>
</div>
@@ -1,4 +1,8 @@
<script lang="ts">
import { getContext } from 'svelte';
const i18n = getContext('i18n');
export let options = {
// Advanced
seed: 0,
@@ -20,7 +24,7 @@
<div class=" space-y-3 text-xs">
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" w-20 text-xs font-medium self-center">Seed</div>
<div class=" w-20 text-xs font-medium self-center">{$i18n.t('Seed')}</div>
<div class=" flex-1 self-center">
<input
class="w-full rounded py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none border border-gray-100 dark:border-gray-600"
@@ -36,12 +40,12 @@
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" w-20 text-xs font-medium self-center">Stop Sequence</div>
<div class=" w-20 text-xs font-medium self-center">{$i18n.t('Stop Sequence')}</div>
<div class=" flex-1 self-center">
<input
class="w-full rounded py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none border border-gray-100 dark:border-gray-600"
type="text"
placeholder="Enter Stop Sequence"
placeholder={$i18n.t('Enter stop sequence')}
bind:value={options.stop}
autocomplete="off"
/>
@@ -51,7 +55,7 @@
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Temperature</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Temperature')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -61,9 +65,9 @@
}}
>
{#if options.temperature === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center"> {$i18n.t('Default')} </span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center"> {$i18n.t('Custom')} </span>
{/if}
</button>
</div>
@@ -97,7 +101,7 @@
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Mirostat</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Mirostat')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -107,9 +111,9 @@
}}
>
{#if options.mirostat === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{/if}
</button>
</div>
@@ -143,7 +147,7 @@
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Mirostat Eta</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Mirostat Eta')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -153,9 +157,9 @@
}}
>
{#if options.mirostat_eta === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{/if}
</button>
</div>
@@ -189,7 +193,7 @@
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Mirostat Tau</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Mirostat Tau')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -199,9 +203,9 @@
}}
>
{#if options.mirostat_tau === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center">{$i18n.t('Custom')}</span>
{/if}
</button>
</div>
@@ -235,7 +239,7 @@
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Top K</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Top K')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -245,9 +249,9 @@
}}
>
{#if options.top_k === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{/if}
</button>
</div>
@@ -281,7 +285,7 @@
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Top P</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Top P')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -291,9 +295,9 @@
}}
>
{#if options.top_p === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{/if}
</button>
</div>
@@ -327,7 +331,7 @@
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Repeat Penalty</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Repeat Penalty')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -337,9 +341,9 @@
}}
>
{#if options.repeat_penalty === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{/if}
</button>
</div>
@@ -373,7 +377,7 @@
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Repeat Last N</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Repeat Last N')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -383,9 +387,9 @@
}}
>
{#if options.repeat_last_n === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{/if}
</button>
</div>
@@ -419,7 +423,7 @@
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Tfs Z</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Tfs Z')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -429,9 +433,9 @@
}}
>
{#if options.tfs_z === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{/if}
</button>
</div>
@@ -465,7 +469,7 @@
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Context Length</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Context Length')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -475,9 +479,9 @@
}}
>
{#if options.num_ctx === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{/if}
</button>
</div>
@@ -510,7 +514,7 @@
</div>
<div class=" py-0.5 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Max Tokens</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Max Tokens')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -520,9 +524,9 @@
}}
>
{#if options.num_predict === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{/if}
</button>
</div>
+33 -25
View File
@@ -1,8 +1,10 @@
<script lang="ts">
import { createEventDispatcher, onMount } from 'svelte';
import { createEventDispatcher, onMount, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
const dispatch = createEventDispatcher();
const i18n = getContext('i18n');
export let saveSettings: Function;
// Audio
@@ -101,32 +103,36 @@
>
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
<div>
<div class=" mb-1 text-sm font-medium">STT Settings</div>
<div class=" mb-1 text-sm font-medium">{$i18n.t('STT Settings')}</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">Speech-to-Text Engine</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Speech-to-Text Engine')}</div>
<div class="flex items-center relative">
<select
class="w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
class="dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
bind:value={STTEngine}
placeholder="Select a mode"
on:change={(e) => {
if (e.target.value !== '') {
navigator.mediaDevices.getUserMedia({ audio: true }).catch(function (err) {
toast.error(`Permission denied when accessing microphone: ${err}`);
toast.error(
$i18n.t(`Permission denied when accessing microphone: {{error}}`, {
error: err
})
);
STTEngine = '';
});
}
}}
>
<option value="">Default (Web API)</option>
<option value="whisper-local">Whisper (Local)</option>
<option value="">{$i18n.t('Default (Web API)')}</option>
<option value="whisper-local">{$i18n.t('Whisper (Local)')}</option>
</select>
</div>
</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">Conversation Mode</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Conversation Mode')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -136,15 +142,17 @@
type="button"
>
{#if conversationMode === true}
<span class="ml-2 self-center">On</span>
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">Off</span>
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">Auto-send input after 3 sec.</div>
<div class=" self-center text-xs font-medium">
{$i18n.t('Auto-send input after 3 sec.')}
</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -154,22 +162,22 @@
type="button"
>
{#if speechAutoSend === true}
<span class="ml-2 self-center">On</span>
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">Off</span>
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
</div>
<div>
<div class=" mb-1 text-sm font-medium">TTS Settings</div>
<div class=" mb-1 text-sm font-medium">{$i18n.t('TTS Settings')}</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">Text-to-Speech Engine</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Text-to-Speech Engine')}</div>
<div class="flex items-center relative">
<select
class="w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
class=" dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
bind:value={TTSEngine}
placeholder="Select a mode"
on:change={(e) => {
@@ -182,14 +190,14 @@
}
}}
>
<option value="">Default (Web API)</option>
<option value="openai">Open AI</option>
<option value="">{$i18n.t('Default (Web API)')}</option>
<option value="openai">{$i18n.t('Open AI')}</option>
</select>
</div>
</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">Auto-playback response</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Auto-playback response')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -199,9 +207,9 @@
type="button"
>
{#if responseAutoPlayback === true}
<span class="ml-2 self-center">On</span>
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">Off</span>
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
@@ -211,7 +219,7 @@
{#if TTSEngine === ''}
<div>
<div class=" mb-2.5 text-sm font-medium">Set Voice</div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Voice')}</div>
<div class="flex w-full">
<div class="flex-1">
<select
@@ -219,7 +227,7 @@
bind:value={speaker}
placeholder="Select a voice"
>
<option value="" selected>Default</option>
<option value="" selected>{$i18n.t('Default')}</option>
{#each voices.filter((v) => v.localService === true) as voice}
<option value={voice.name} class="bg-gray-100 dark:bg-gray-700">{voice.name}</option
>
@@ -230,7 +238,7 @@
</div>
{:else if TTSEngine === 'openai'}
<div>
<div class=" mb-2.5 text-sm font-medium">Set Voice</div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Voice')}</div>
<div class="flex w-full">
<div class="flex-1">
<select
@@ -254,7 +262,7 @@
class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
type="submit"
>
Save
{$i18n.t('Save')}
</button>
</div>
</form>
+14 -43
View File
@@ -2,7 +2,6 @@
import fileSaver from 'file-saver';
const { saveAs } = fileSaver;
import { resetVectorDB } from '$lib/apis/rag';
import { chats, user } from '$lib/stores';
import {
@@ -13,10 +12,12 @@
getChatList
} from '$lib/apis/chats';
import { getImportOrigin, convertOpenAIChats } from '$lib/utils';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
import { goto } from '$app/navigation';
import { toast } from 'svelte-sonner';
const i18n = getContext('i18n');
export let saveSettings: Function;
// Chats
let saveChatHistory = true;
@@ -99,13 +100,13 @@
});
</script>
<div class="flex flex-col h-full justify-between space-y-3 text-sm">
<div class="flex flex-col h-full justify-between space-y-3 text-sm max-h-[22rem]">
<div class=" space-y-2">
<div
class="flex flex-col justify-between rounded-md items-center py-2 px-3.5 w-full transition"
>
<div class="flex w-full justify-between">
<div class=" self-center text-sm font-medium">Chat History</div>
<div class=" self-center text-sm font-medium">{$i18n.t('Chat History')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -129,7 +130,7 @@
/>
</svg>
<span class="ml-2 self-center"> On </span>
<span class="ml-2 self-center"> {$i18n.t('On')} </span>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -147,13 +148,13 @@
/>
</svg>
<span class="ml-2 self-center">Off</span>
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
<div class="text-xs text-left w-full font-medium mt-0.5">
This setting does not sync across browsers or devices.
{$i18n.t('This setting does not sync across browsers or devices.')}
</div>
</div>
@@ -188,7 +189,7 @@
/>
</svg>
</div>
<div class=" self-center text-sm font-medium">Import Chats</div>
<div class=" self-center text-sm font-medium">{$i18n.t('Import Chats')}</div>
</button>
<button
class=" flex rounded-md py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
@@ -210,7 +211,7 @@
/>
</svg>
</div>
<div class=" self-center text-sm font-medium">Export Chats</div>
<div class=" self-center text-sm font-medium">{$i18n.t('Export Chats')}</div>
</button>
</div>
@@ -232,7 +233,7 @@
clip-rule="evenodd"
/>
</svg>
<span>Are you sure?</span>
<span>{$i18n.t('Are you sure?')}</span>
</div>
<div class="flex space-x-1.5 items-center">
@@ -296,7 +297,7 @@
/>
</svg>
</div>
<div class=" self-center text-sm font-medium">Delete Chats</div>
<div class=" self-center text-sm font-medium">{$i18n.t('Delete Chats')}</div>
</button>
{/if}
@@ -324,39 +325,9 @@
/>
</svg>
</div>
<div class=" self-center text-sm font-medium">Export All Chats (All Users)</div>
</button>
<hr class=" dark:border-gray-700" />
<button
class=" flex rounded-md py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
on:click={() => {
const res = resetVectorDB(localStorage.token).catch((error) => {
toast.error(error);
return null;
});
if (res) {
toast.success('Success');
}
}}
>
<div class=" self-center mr-3">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M3.5 2A1.5 1.5 0 0 0 2 3.5v9A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 12.5 4H9.621a1.5 1.5 0 0 1-1.06-.44L7.439 2.44A1.5 1.5 0 0 0 6.38 2H3.5Zm6.75 7.75a.75.75 0 0 0 0-1.5h-4.5a.75.75 0 0 0 0 1.5h4.5Z"
clip-rule="evenodd"
/>
</svg>
<div class=" self-center text-sm font-medium">
{$i18n.t('Export All Chats (All Users)')}
</div>
<div class=" self-center text-sm font-medium">Reset Vector Storage</div>
</button>
{/if}
</div>
@@ -1,6 +1,6 @@
<script lang="ts">
import { models, user } from '$lib/stores';
import { createEventDispatcher, onMount } from 'svelte';
import { createEventDispatcher, onMount, getContext } from 'svelte';
const dispatch = createEventDispatcher();
import { getOllamaUrls, getOllamaVersion, updateOllamaUrls } from '$lib/apis/ollama';
@@ -12,6 +12,8 @@
} from '$lib/apis/openai';
import { toast } from 'svelte-sonner';
const i18n = getContext('i18n');
export let getModels: Function;
// External
@@ -42,7 +44,7 @@
});
if (ollamaVersion) {
toast.success('Server connection verified');
toast.success($i18n.t('Server connection verified'));
await models.set(await getModels());
}
};
@@ -63,17 +65,17 @@
dispatch('save');
}}
>
<div class=" pr-1.5 overflow-y-scroll max-h-[20.5rem] space-y-3">
<div class=" pr-1.5 overflow-y-scroll max-h-[22rem] space-y-3">
<div class=" space-y-3">
<div class="mt-2 space-y-2 pr-1.5">
<div class="flex justify-between items-center text-sm">
<div class=" font-medium">OpenAI API</div>
<div class=" font-medium">{$i18n.t('OpenAI API')}</div>
<button
class=" text-xs font-medium text-gray-500"
type="button"
on:click={() => {
showOpenAI = !showOpenAI;
}}>{showOpenAI ? 'Hide' : 'Show'}</button
}}>{showOpenAI ? $i18n.t('Hide') : $i18n.t('Show')}</button
>
</div>
@@ -84,7 +86,7 @@
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder="API Base URL"
placeholder={$i18n.t('API Base URL')}
bind:value={url}
autocomplete="off"
/>
@@ -93,7 +95,7 @@
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder="API Key"
placeholder={$i18n.t('API Key')}
bind:value={OPENAI_API_KEYS[idx]}
autocomplete="off"
/>
@@ -143,7 +145,8 @@
</div>
</div>
<div class=" mb-1 text-xs text-gray-400 dark:text-gray-500">
WebUI will make requests to <span class=" text-gray-200">'{url}/models'</span>
{$i18n.t('WebUI will make requests to')}
<span class=" text-gray-200">'{url}/models'</span>
</div>
{/each}
</div>
@@ -154,7 +157,7 @@
<hr class=" dark:border-gray-700" />
<div>
<div class=" mb-2.5 text-sm font-medium">Ollama Base URL</div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Ollama Base URL')}</div>
<div class="flex w-full gap-1.5">
<div class="flex-1 flex flex-col gap-2">
{#each OLLAMA_BASE_URLS as url, idx}
@@ -233,13 +236,13 @@
</div>
<div class="mt-2 text-xs text-gray-400 dark:text-gray-500">
Trouble accessing Ollama?
{$i18n.t('Trouble accessing Ollama?')}
<a
class=" text-gray-300 font-medium"
class=" text-gray-300 font-medium underline"
href="https://github.com/open-webui/open-webui#troubleshooting"
target="_blank"
>
Click here for help.
{$i18n.t('Click here for help.')}
</a>
</div>
</div>
@@ -250,7 +253,7 @@
class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
type="submit"
>
Save
{$i18n.t('Save')}
</button>
</div>
</form>
+97 -73
View File
@@ -1,9 +1,12 @@
<script lang="ts">
import { toast } from 'svelte-sonner';
import { createEventDispatcher, onMount } from 'svelte';
import { createEventDispatcher, onMount, getContext } from 'svelte';
import { getLanguages } from '$lib/i18n';
const dispatch = createEventDispatcher();
import { models, user } from '$lib/stores';
import { models, user, theme } from '$lib/stores';
const i18n = getContext('i18n');
import AdvancedParams from './Advanced/AdvancedParams.svelte';
@@ -12,7 +15,10 @@
// General
let themes = ['dark', 'light', 'rose-pine dark', 'rose-pine-dawn light'];
let theme = 'dark';
let selectedTheme = 'system';
let languages = [];
let lang = $i18n.language;
let notificationEnabled = false;
let system = '';
@@ -63,9 +69,11 @@
};
onMount(async () => {
selectedTheme = localStorage.theme ?? 'system';
let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
languages = await getLanguages();
theme = localStorage.theme ?? 'dark';
notificationEnabled = settings.notificationEnabled ?? false;
system = settings.system ?? '';
@@ -81,77 +89,93 @@
options = { ...options, ...settings.options };
options.stop = (settings?.options?.stop ?? []).join(',');
});
const applyTheme = (_theme: string) => {
let themeToApply = _theme;
if (_theme === 'system') {
themeToApply = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
themes
.filter((e) => e !== themeToApply)
.forEach((e) => {
e.split(' ').forEach((e) => {
document.documentElement.classList.remove(e);
});
});
themeToApply.split(' ').forEach((e) => {
document.documentElement.classList.add(e);
});
console.log(_theme);
};
const themeChangeHandler = (_theme: string) => {
theme.set(_theme);
localStorage.setItem('theme', _theme);
applyTheme(_theme);
};
</script>
<div class="flex flex-col h-full justify-between text-sm">
<div class=" pr-1.5 overflow-y-scroll max-h-[20.5rem]">
<div class=" pr-1.5 overflow-y-scroll max-h-[22rem]">
<div class="">
<div class=" mb-1 text-sm font-medium">WebUI Settings</div>
<div class=" mb-1 text-sm font-medium">{$i18n.t('WebUI Settings')}</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">Theme</div>
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Theme')}</div>
<div class="flex items-center relative">
<div class=" absolute right-16">
{#if theme === 'dark'}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M7.455 2.004a.75.75 0 01.26.77 7 7 0 009.958 7.967.75.75 0 011.067.853A8.5 8.5 0 116.647 1.921a.75.75 0 01.808.083z"
clip-rule="evenodd"
/>
</svg>
{:else if theme === 'light'}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4 self-center"
>
<path
d="M10 2a.75.75 0 01.75.75v1.5a.75.75 0 01-1.5 0v-1.5A.75.75 0 0110 2zM10 15a.75.75 0 01.75.75v1.5a.75.75 0 01-1.5 0v-1.5A.75.75 0 0110 15zM10 7a3 3 0 100 6 3 3 0 000-6zM15.657 5.404a.75.75 0 10-1.06-1.06l-1.061 1.06a.75.75 0 001.06 1.06l1.06-1.06zM6.464 14.596a.75.75 0 10-1.06-1.06l-1.06 1.06a.75.75 0 001.06 1.06l1.06-1.06zM18 10a.75.75 0 01-.75.75h-1.5a.75.75 0 010-1.5h1.5A.75.75 0 0118 10zM5 10a.75.75 0 01-.75.75h-1.5a.75.75 0 010-1.5h1.5A.75.75 0 015 10zM14.596 15.657a.75.75 0 001.06-1.06l-1.06-1.061a.75.75 0 10-1.06 1.06l1.06 1.06zM5.404 6.464a.75.75 0 001.06-1.06l-1.06-1.06a.75.75 0 10-1.061 1.06l1.06 1.06z"
/>
</svg>
{/if}
</div>
<select
class="w-fit pr-8 rounded py-2 px-2 text-xs bg-transparent outline-none text-right"
bind:value={theme}
class=" dark:bg-gray-900 w-fit pr-8 rounded py-2 px-2 text-xs bg-transparent outline-none text-right"
bind:value={selectedTheme}
placeholder="Select a theme"
on:change={(e) => {
localStorage.theme = theme;
themes
.filter((e) => e !== theme)
.forEach((e) => {
e.split(' ').forEach((e) => {
document.documentElement.classList.remove(e);
});
});
theme.split(' ').forEach((e) => {
document.documentElement.classList.add(e);
});
console.log(theme);
}}
on:change={() => themeChangeHandler(selectedTheme)}
>
<option value="dark">Dark</option>
<option value="light">Light</option>
<option value="rose-pine dark">Rosé Pine</option>
<option value="rose-pine-dawn light">Rosé Pine Dawn</option>
<option value="system">⚙️ {$i18n.t('System')}</option>
<option value="dark">🌑 {$i18n.t('Dark')}</option>
<option value="light">☀️ {$i18n.t('Light')}</option>
<option value="rose-pine dark">🪻 {$i18n.t('Rosé Pine')}</option>
<option value="rose-pine-dawn light">🌷 {$i18n.t('Rosé Pine Dawn')}</option>
</select>
</div>
</div>
<div class=" flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Language')}</div>
<div class="flex items-center relative">
<select
class=" dark:bg-gray-900 w-fit pr-8 rounded py-2 px-2 text-xs bg-transparent outline-none text-right"
bind:value={lang}
placeholder="Select a language"
on:change={(e) => {
$i18n.changeLanguage(lang);
}}
>
{#each languages as language}
<option value={language['code']}>{language['title']}</option>
{/each}
</select>
</div>
</div>
{#if $i18n.language === 'en-US'}
<div class="mb-2 text-xs text-gray-400 dark:text-gray-500">
Couldn't find your language?
<a
class=" text-gray-300 font-medium underline"
href="https://github.com/open-webui/open-webui/blob/main/docs/CONTRIBUTING.md#-translations-and-internationalization"
target="_blank"
>
Help us translate Open WebUI!
</a>
</div>
{/if}
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">Notification</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Desktop Notifications')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -161,9 +185,9 @@
type="button"
>
{#if notificationEnabled === true}
<span class="ml-2 self-center">On</span>
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">Off</span>
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
@@ -173,7 +197,7 @@
<hr class=" dark:border-gray-700 my-3" />
<div>
<div class=" my-2.5 text-sm font-medium">System Prompt</div>
<div class=" my-2.5 text-sm font-medium">{$i18n.t('System Prompt')}</div>
<textarea
bind:value={system}
class="w-full rounded-lg p-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none resize-none"
@@ -183,13 +207,13 @@
<div class="mt-2 space-y-3 pr-1.5">
<div class="flex justify-between items-center text-sm">
<div class=" font-medium">Advanced Parameters</div>
<div class=" font-medium">{$i18n.t('Advanced Parameters')}</div>
<button
class=" text-xs font-medium text-gray-500"
type="button"
on:click={() => {
showAdvanced = !showAdvanced;
}}>{showAdvanced ? 'Hide' : 'Show'}</button
}}>{showAdvanced ? $i18n.t('Hide') : $i18n.t('Show')}</button
>
</div>
@@ -199,7 +223,7 @@
<div class=" py-1 w-full justify-between">
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">Keep Alive</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Keep Alive')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -209,9 +233,9 @@
}}
>
{#if keepAlive === null}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center"> {$i18n.t('Default')} </span>
{:else}
<span class="ml-2 self-center"> Custom </span>
<span class="ml-2 self-center"> {$i18n.t('Custom')} </span>
{/if}
</button>
</div>
@@ -221,7 +245,7 @@
<input
class="w-full rounded py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none border border-gray-100 dark:border-gray-600"
type="text"
placeholder={`e.g.) "30s","10m". Valid time units are "s", "m", "h".`}
placeholder={$i18n.t("e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.")}
bind:value={keepAlive}
/>
</div>
@@ -230,7 +254,7 @@
<div>
<div class=" py-1 flex w-full justify-between">
<div class=" self-center text-sm font-medium">Request Mode</div>
<div class=" self-center text-sm font-medium">{$i18n.t('Request Mode')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -239,7 +263,7 @@
}}
>
{#if requestFormat === ''}
<span class="ml-2 self-center"> Default </span>
<span class="ml-2 self-center"> {$i18n.t('Default')} </span>
{:else if requestFormat === 'json'}
<!-- <svg
xmlns="http://www.w3.org/2000/svg"
@@ -251,7 +275,7 @@
d="M10 2a.75.75 0 01.75.75v1.5a.75.75 0 01-1.5 0v-1.5A.75.75 0 0110 2zM10 15a.75.75 0 01.75.75v1.5a.75.75 0 01-1.5 0v-1.5A.75.75 0 0110 15zM10 7a3 3 0 100 6 3 3 0 000-6zM15.657 5.404a.75.75 0 10-1.06-1.06l-1.061 1.06a.75.75 0 001.06 1.06l1.06-1.06zM6.464 14.596a.75.75 0 10-1.06-1.06l-1.06 1.06a.75.75 0 001.06 1.06l1.06-1.06zM18 10a.75.75 0 01-.75.75h-1.5a.75.75 0 010-1.5h1.5A.75.75 0 0118 10zM5 10a.75.75 0 01-.75.75h-1.5a.75.75 0 010-1.5h1.5A.75.75 0 015 10zM14.596 15.657a.75.75 0 001.06-1.06l-1.06-1.061a.75.75 0 10-1.06 1.06l1.06 1.06zM5.404 6.464a.75.75 0 001.06-1.06l-1.06-1.06a.75.75 0 10-1.061 1.06l1.06 1.06z"
/>
</svg> -->
<span class="ml-2 self-center"> JSON </span>
<span class="ml-2 self-center"> {$i18n.t('JSON')} </span>
{/if}
</button>
</div>
@@ -286,7 +310,7 @@
dispatch('save');
}}
>
Save
{$i18n.t('Save')}
</button>
</div>
</div>
+112 -45
View File
@@ -1,17 +1,17 @@
<script lang="ts">
import { toast } from 'svelte-sonner';
import { createEventDispatcher, onMount } from 'svelte';
import { createEventDispatcher, onMount, getContext } from 'svelte';
import { config, user } from '$lib/stores';
import {
getAUTOMATIC1111Url,
getImageGenerationModels,
getDefaultImageGenerationModel,
updateDefaultImageGenerationModel,
getImageSize,
getImageGenerationConfig,
updateImageGenerationConfig,
updateAUTOMATIC1111Url,
getImageGenerationEngineUrls,
updateImageGenerationEngineUrls,
updateImageSize,
getImageSteps,
updateImageSteps,
@@ -21,6 +21,8 @@
import { getBackendConfig } from '$lib/apis';
const dispatch = createEventDispatcher();
const i18n = getContext('i18n');
export let saveSettings: Function;
let loading = false;
@@ -29,6 +31,8 @@
let enableImageGeneration = false;
let AUTOMATIC1111_BASE_URL = '';
let COMFYUI_BASE_URL = '';
let OPENAI_API_KEY = '';
let selectedModel = '';
@@ -47,24 +51,47 @@
});
};
const updateAUTOMATIC1111UrlHandler = async () => {
const res = await updateAUTOMATIC1111Url(localStorage.token, AUTOMATIC1111_BASE_URL).catch(
(error) => {
const updateUrlHandler = async () => {
if (imageGenerationEngine === 'comfyui') {
const res = await updateImageGenerationEngineUrls(localStorage.token, {
COMFYUI_BASE_URL: COMFYUI_BASE_URL
}).catch((error) => {
toast.error(error);
console.log(error);
return null;
}
);
});
if (res) {
AUTOMATIC1111_BASE_URL = res;
if (res) {
COMFYUI_BASE_URL = res.COMFYUI_BASE_URL;
await getModels();
await getModels();
if (models) {
toast.success('Server connection verified');
if (models) {
toast.success($i18n.t('Server connection verified'));
}
} else {
({ COMFYUI_BASE_URL } = await getImageGenerationEngineUrls(localStorage.token));
}
} else {
AUTOMATIC1111_BASE_URL = await getAUTOMATIC1111Url(localStorage.token);
const res = await updateImageGenerationEngineUrls(localStorage.token, {
AUTOMATIC1111_BASE_URL: AUTOMATIC1111_BASE_URL
}).catch((error) => {
toast.error(error);
return null;
});
if (res) {
AUTOMATIC1111_BASE_URL = res.AUTOMATIC1111_BASE_URL;
await getModels();
if (models) {
toast.success($i18n.t('Server connection verified'));
}
} else {
({ AUTOMATIC1111_BASE_URL } = await getImageGenerationEngineUrls(localStorage.token));
}
}
};
const updateImageGeneration = async () => {
@@ -99,7 +126,11 @@
imageGenerationEngine = res.engine;
enableImageGeneration = res.enabled;
}
AUTOMATIC1111_BASE_URL = await getAUTOMATIC1111Url(localStorage.token);
const URLS = await getImageGenerationEngineUrls(localStorage.token);
AUTOMATIC1111_BASE_URL = URLS.AUTOMATIC1111_BASE_URL;
COMFYUI_BASE_URL = URLS.COMFYUI_BASE_URL;
OPENAI_API_KEY = await getOpenAIKey(localStorage.token);
imageSize = await getImageSize(localStorage.token);
@@ -136,39 +167,45 @@
loading = false;
}}
>
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-[20.5rem]">
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-[24rem]">
<div>
<div class=" mb-1 text-sm font-medium">Image Settings</div>
<div class=" mb-1 text-sm font-medium">{$i18n.t('Image Settings')}</div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">Image Generation Engine</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Image Generation Engine')}</div>
<div class="flex items-center relative">
<select
class="w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
bind:value={imageGenerationEngine}
placeholder="Select a mode"
placeholder={$i18n.t('Select a mode')}
on:change={async () => {
await updateImageGeneration();
}}
>
<option value="">Default (Automatic1111)</option>
<option value="openai">Open AI (Dall-E)</option>
<option value="">{$i18n.t('Default (Automatic1111)')}</option>
<option value="comfyui">{$i18n.t('ComfyUI')}</option>
<option value="openai">{$i18n.t('Open AI (Dall-E)')}</option>
</select>
</div>
</div>
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">Image Generation (Experimental)</div>
<div class=" self-center text-xs font-medium">
{$i18n.t('Image Generation (Experimental)')}
</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
on:click={() => {
if (imageGenerationEngine === '' && AUTOMATIC1111_BASE_URL === '') {
toast.error('AUTOMATIC1111 Base URL is required.');
toast.error($i18n.t('AUTOMATIC1111 Base URL is required.'));
enableImageGeneration = false;
} else if (imageGenerationEngine === 'comfyui' && COMFYUI_BASE_URL === '') {
toast.error($i18n.t('ComfyUI Base URL is required.'));
enableImageGeneration = false;
} else if (imageGenerationEngine === 'openai' && OPENAI_API_KEY === '') {
toast.error('OpenAI API Key is required.');
toast.error($i18n.t('OpenAI API Key is required.'));
enableImageGeneration = false;
} else {
enableImageGeneration = !enableImageGeneration;
@@ -179,9 +216,9 @@
type="button"
>
{#if enableImageGeneration === true}
<span class="ml-2 self-center">On</span>
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">Off</span>
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
@@ -190,22 +227,20 @@
<hr class=" dark:border-gray-700" />
{#if imageGenerationEngine === ''}
<div class=" mb-2.5 text-sm font-medium">AUTOMATIC1111 Base URL</div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('AUTOMATIC1111 Base URL')}</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder="Enter URL (e.g. http://127.0.0.1:7860/)"
placeholder={$i18n.t('Enter URL (e.g. http://127.0.0.1:7860/)')}
bind:value={AUTOMATIC1111_BASE_URL}
/>
</div>
<button
class="px-3 bg-gray-200 hover:bg-gray-300 dark:bg-gray-600 dark:hover:bg-gray-700 rounded-lg transition"
class="px-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-gray-100 rounded-lg transition"
type="button"
on:click={() => {
// updateOllamaAPIUrlHandler();
updateAUTOMATIC1111UrlHandler();
updateUrlHandler();
}}
>
<svg
@@ -224,22 +259,53 @@
</div>
<div class="mt-2 text-xs text-gray-400 dark:text-gray-500">
Include `--api` flag when running stable-diffusion-webui
{$i18n.t('Include `--api` flag when running stable-diffusion-webui')}
<a
class=" text-gray-300 font-medium"
href="https://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/3734"
target="_blank"
>
(e.g. `sh webui.sh --api`)
{$i18n.t('(e.g. `sh webui.sh --api`)')}
</a>
</div>
{:else if imageGenerationEngine === 'openai'}
<div class=" mb-2.5 text-sm font-medium">OpenAI API Key</div>
{:else if imageGenerationEngine === 'comfyui'}
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('ComfyUI Base URL')}</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder="Enter API Key"
placeholder={$i18n.t('Enter URL (e.g. http://127.0.0.1:7860/)')}
bind:value={COMFYUI_BASE_URL}
/>
</div>
<button
class="px-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-gray-100 rounded-lg transition"
type="button"
on:click={() => {
updateUrlHandler();
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M15.312 11.424a5.5 5.5 0 01-9.201 2.466l-.312-.311h2.433a.75.75 0 000-1.5H3.989a.75.75 0 00-.75.75v4.242a.75.75 0 001.5 0v-2.43l.31.31a7 7 0 0011.712-3.138.75.75 0 00-1.449-.39zm1.23-3.723a.75.75 0 00.219-.53V2.929a.75.75 0 00-1.5 0V5.36l-.31-.31A7 7 0 003.239 8.188a.75.75 0 101.448.389A5.5 5.5 0 0113.89 6.11l.311.31h-2.432a.75.75 0 000 1.5h4.243a.75.75 0 00.53-.219z"
clip-rule="evenodd"
/>
</svg>
</button>
</div>
{:else if imageGenerationEngine === 'openai'}
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('OpenAI API Key')}</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={$i18n.t('Enter API Key')}
bind:value={OPENAI_API_KEY}
/>
</div>
@@ -250,16 +316,17 @@
<hr class=" dark:border-gray-700" />
<div>
<div class=" mb-2.5 text-sm font-medium">Set Default Model</div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Default Model')}</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={selectedModel}
placeholder="Select a model"
placeholder={$i18n.t('Select a model')}
required
>
{#if !selectedModel}
<option value="" disabled selected>Select a model</option>
<option value="" disabled selected>{$i18n.t('Select a model')}</option>
{/if}
{#each models ?? [] as model}
<option value={model.id} class="bg-gray-100 dark:bg-gray-700">{model.name}</option>
@@ -270,12 +337,12 @@
</div>
<div>
<div class=" mb-2.5 text-sm font-medium">Set Image Size</div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Image Size')}</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder="Enter Image Size (e.g. 512x512)"
placeholder={$i18n.t('Enter Image Size (e.g. 512x512)')}
bind:value={imageSize}
/>
</div>
@@ -283,12 +350,12 @@
</div>
<div>
<div class=" mb-2.5 text-sm font-medium">Set Steps</div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Steps')}</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder="Enter Number of Steps (e.g. 50)"
placeholder={$i18n.t('Enter Number of Steps (e.g. 50)')}
bind:value={steps}
/>
</div>
@@ -305,7 +372,7 @@
type="submit"
disabled={loading}
>
Save
{$i18n.t('Save')}
{#if loading}
<div class="ml-2 self-center">
@@ -2,10 +2,12 @@
import { getBackendConfig } from '$lib/apis';
import { setDefaultPromptSuggestions } from '$lib/apis/configs';
import { config, models, user } from '$lib/stores';
import { createEventDispatcher, onMount } from 'svelte';
import { createEventDispatcher, onMount, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
const dispatch = createEventDispatcher();
const i18n = getContext('i18n');
export let saveSettings: Function;
// Addons
@@ -82,7 +84,9 @@
titleAutoGenerateModel = settings.titleAutoGenerateModel ?? '';
titleGenerationPrompt =
settings.titleGenerationPrompt ??
`Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title': {{prompt}}`;
$i18n.t(
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':"
) + ' {{prompt}}';
});
</script>
@@ -93,13 +97,13 @@
dispatch('save');
}}
>
<div class=" space-y-3 pr-1.5 overflow-y-scroll h-80">
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-[22rem]">
<div>
<div class=" mb-1 text-sm font-medium">WebUI Add-ons</div>
<div class=" mb-1 text-sm font-medium">{$i18n.t('WebUI Add-ons')}</div>
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">Title Auto-Generation</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Title Auto-Generation')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -109,9 +113,9 @@
type="button"
>
{#if titleAutoGenerate === true}
<span class="ml-2 self-center">On</span>
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">Off</span>
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
@@ -119,7 +123,9 @@
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">Response AutoCopy to Clipboard</div>
<div class=" self-center text-xs font-medium">
{$i18n.t('Response AutoCopy to Clipboard')}
</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -129,9 +135,9 @@
type="button"
>
{#if responseAutoCopy === true}
<span class="ml-2 self-center">On</span>
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">Off</span>
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
@@ -139,7 +145,7 @@
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">Full Screen Mode</div>
<div class=" self-center text-xs font-medium">{$i18n.t('Full Screen Mode')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -149,9 +155,9 @@
type="button"
>
{#if fullScreenMode === true}
<span class="ml-2 self-center">On</span>
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">Off</span>
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
@@ -160,7 +166,7 @@
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">
Display the username instead of "You" in the Chat
{$i18n.t('Display the username instead of You in the Chat')}
</div>
<button
@@ -171,9 +177,9 @@
type="button"
>
{#if showUsername === true}
<span class="ml-2 self-center">On</span>
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">Off</span>
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
@@ -183,15 +189,15 @@
<hr class=" dark:border-gray-700" />
<div>
<div class=" mb-2.5 text-sm font-medium">Set Title Auto-Generation Model</div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Title Auto-Generation Model')}</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={titleAutoGenerateModel}
placeholder="Select a model"
placeholder={$i18n.t('Select a model')}
>
<option value="" selected>Current Model</option>
<option value="" selected>{$i18n.t('Current Model')}</option>
{#each $models as model}
{#if model.size != null}
<option value={model.name} class="bg-gray-100 dark:bg-gray-700">
@@ -202,8 +208,9 @@
</select>
</div>
</div>
<div class="mt-3 mr-2">
<div class=" mb-2.5 text-sm font-medium">Title Generation Prompt</div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Title Generation Prompt')}</div>
<textarea
bind:value={titleGenerationPrompt}
class="w-full rounded-lg p-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none resize-none"
@@ -217,7 +224,9 @@
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
<div class="flex w-full justify-between mb-2">
<div class=" self-center text-sm font-semibold">Default Prompt Suggestions</div>
<div class=" self-center text-sm font-semibold">
{$i18n.t('Default Prompt Suggestions')}
</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -290,19 +299,19 @@
{#if promptSuggestions.length > 0}
<div class="text-xs text-left w-full mt-2">
Adjusting these settings will apply changes universally to all users.
{$i18n.t('Adjusting these settings will apply changes universally to all users.')}
</div>
{/if}
</div>
{/if}
</div>
<div class="flex justify-end pt-3 text-sm font-medium">
<div class="flex justify-end text-sm font-medium">
<button
class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
type="submit"
>
Save
{$i18n.t('Save')}
</button>
</div>
</form>
+212 -96
View File
@@ -5,17 +5,22 @@
import {
createModel,
deleteModel,
downloadModel,
getOllamaUrls,
getOllamaVersion,
pullModel
pullModel,
cancelOllamaRequest,
uploadModel
} from '$lib/apis/ollama';
import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
import { WEBUI_NAME, models, user } from '$lib/stores';
import { splitStream } from '$lib/utils';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
import { addLiteLLMModel, deleteLiteLLMModel, getLiteLLMModelInfo } from '$lib/apis/litellm';
import Tooltip from '$lib/components/common/Tooltip.svelte';
const i18n = getContext('i18n');
export let getModels: Function;
let showLiteLLM = false;
@@ -58,11 +63,13 @@
let pullProgress = null;
let modelUploadMode = 'file';
let modelInputFile = '';
let modelInputFile: File[] | null = null;
let modelFileUrl = '';
let modelFileContent = `TEMPLATE """{{ .System }}\nUSER: {{ .Prompt }}\nASSISTANT: """\nPARAMETER num_ctx 4096\nPARAMETER stop "</s>"\nPARAMETER stop "USER:"\nPARAMETER stop "ASSISTANT:"`;
let modelFileDigest = '';
let uploadProgress = null;
let uploadMessage = '';
let deleteModelTag = '';
@@ -134,11 +141,17 @@
const pullModelHandler = async () => {
const sanitizedModelTag = modelTag.trim();
if (modelDownloadStatus[sanitizedModelTag]) {
toast.error(`Model '${sanitizedModelTag}' is already in queue for downloading.`);
toast.error(
$i18n.t(`Model '{{modelTag}}' is already in queue for downloading.`, {
modelTag: sanitizedModelTag
})
);
return;
}
if (Object.keys(modelDownloadStatus).length === 3) {
toast.error('Maximum of 3 models can be downloaded simultaneously. Please try again later.');
toast.error(
$i18n.t('Maximum of 3 models can be downloaded simultaneously. Please try again later.')
);
return;
}
@@ -151,15 +164,17 @@
// Remove the downloaded model
delete modelDownloadStatus[modelName];
console.log(data);
modelDownloadStatus = { ...modelDownloadStatus };
if (!data.success) {
toast.error(data.error);
} else {
toast.success(`Model '${modelName}' has been successfully downloaded.`);
toast.success(
$i18n.t(`Model '{{modelName}}' has been successfully downloaded.`, { modelName })
);
const notification = new Notification($WEBUI_NAME, {
body: `Model '${modelName}' has been successfully downloaded.`,
body: $i18n.t(`Model '{{modelName}}' has been successfully downloaded.`, { modelName }),
icon: `${WEBUI_BASE_URL}/static/favicon.png`
});
@@ -174,35 +189,32 @@
const uploadModelHandler = async () => {
modelTransferring = true;
uploadProgress = 0;
let uploaded = false;
let fileResponse = null;
let name = '';
if (modelUploadMode === 'file') {
const file = modelInputFile[0];
const formData = new FormData();
formData.append('file', file);
const file = modelInputFile ? modelInputFile[0] : null;
fileResponse = await fetch(`${WEBUI_API_BASE_URL}/utils/upload`, {
method: 'POST',
headers: {
...($user && { Authorization: `Bearer ${localStorage.token}` })
},
body: formData
}).catch((error) => {
console.log(error);
return null;
});
if (file) {
uploadMessage = 'Uploading...';
fileResponse = await uploadModel(localStorage.token, file, selectedOllamaUrlIdx).catch(
(error) => {
toast.error(error);
return null;
}
);
}
} else {
fileResponse = await fetch(`${WEBUI_API_BASE_URL}/utils/download?url=${modelFileUrl}`, {
method: 'GET',
headers: {
...($user && { Authorization: `Bearer ${localStorage.token}` })
}
}).catch((error) => {
console.log(error);
uploadProgress = 0;
fileResponse = await downloadModel(
localStorage.token,
modelFileUrl,
selectedOllamaUrlIdx
).catch((error) => {
toast.error(error);
return null;
});
}
@@ -225,6 +237,9 @@
let data = JSON.parse(line.replace(/^data: /, ''));
if (data.progress) {
if (uploadMessage) {
uploadMessage = '';
}
uploadProgress = data.progress;
}
@@ -308,7 +323,11 @@
}
modelFileUrl = '';
modelInputFile = '';
if (modelUploadInputElement) {
modelUploadInputElement.value = '';
}
modelInputFile = null;
modelTransferring = false;
uploadProgress = null;
@@ -323,7 +342,7 @@
);
if (res) {
toast.success(`Deleted ${deleteModelTag}`);
toast.success($i18n.t(`Deleted {{deleteModelTag}}`, { deleteModelTag }));
}
deleteModelTag = '';
@@ -354,12 +373,24 @@
for (const line of lines) {
if (line !== '') {
let data = JSON.parse(line);
console.log(data);
if (data.error) {
throw data.error;
}
if (data.detail) {
throw data.detail;
}
if (data.id) {
modelDownloadStatus[opts.modelName] = {
...modelDownloadStatus[opts.modelName],
requestId: data.id,
reader,
done: false
};
console.log(data);
}
if (data.status) {
if (data.digest) {
let downloadProgress = 0;
@@ -369,11 +400,17 @@
downloadProgress = 100;
}
modelDownloadStatus[opts.modelName] = {
...modelDownloadStatus[opts.modelName],
pullProgress: downloadProgress,
digest: data.digest
};
} else {
toast.success(data.status);
modelDownloadStatus[opts.modelName] = {
...modelDownloadStatus[opts.modelName],
done: data.status === 'success'
};
}
}
}
@@ -386,7 +423,14 @@
opts.callback({ success: false, error, modelName: opts.modelName });
}
}
opts.callback({ success: true, modelName: opts.modelName });
console.log(modelDownloadStatus[opts.modelName]);
if (modelDownloadStatus[opts.modelName].done) {
opts.callback({ success: true, modelName: opts.modelName });
} else {
opts.callback({ success: false, error: 'Download canceled', modelName: opts.modelName });
}
}
};
@@ -410,7 +454,7 @@
}
}
} else {
toast.error(`Model ${liteLLMModelName} already exists.`);
toast.error($i18n.t(`Model {{modelName}} already exists.`, { modelName: liteLLMModelName }));
}
liteLLMModelName = '';
@@ -456,13 +500,25 @@
ollamaVersion = await getOllamaVersion(localStorage.token).catch((error) => false);
liteLLMModelInfo = await getLiteLLMModelInfo(localStorage.token);
});
const cancelModelPullHandler = async (model: string) => {
const { reader, requestId } = modelDownloadStatus[model];
if (reader) {
await reader.cancel();
await cancelOllamaRequest(localStorage.token, requestId);
delete modelDownloadStatus[model];
await deleteModel(localStorage.token, model);
toast.success(`${model} download has been canceled`);
}
};
</script>
<div class="flex flex-col h-full justify-between text-sm">
<div class=" space-y-3 pr-1.5 overflow-y-scroll h-[23rem]">
<div class=" space-y-3 pr-1.5 overflow-y-scroll h-[24rem]">
{#if ollamaVersion}
<div class="space-y-2 pr-1.5">
<div class="text-sm font-medium">Manage Ollama Models</div>
<div class="text-sm font-medium">{$i18n.t('Manage Ollama Models')}</div>
{#if OLLAMA_URLS.length > 0}
<div class="flex gap-2">
@@ -470,7 +526,7 @@
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={selectedOllamaUrlIdx}
placeholder="Select an Ollama instance"
placeholder={$i18n.t('Select an Ollama instance')}
>
{#each OLLAMA_URLS as url, idx}
<option value={idx} class="bg-gray-100 dark:bg-gray-700">{url}</option>
@@ -513,12 +569,14 @@
<div class="space-y-2">
<div>
<div class=" mb-2 text-sm font-medium">Pull a model from Ollama.com</div>
<div class=" mb-2 text-sm font-medium">{$i18n.t('Pull a model from Ollama.com')}</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder="Enter model tag (e.g. mistral:7b)"
placeholder={$i18n.t('Enter model tag (e.g. {{modelTag}})', {
modelTag: 'mistral:7b'
})}
bind:value={modelTag}
/>
</div>
@@ -573,47 +631,84 @@
</button>
</div>
<div>
<div class="mt-2 mb-1 text-xs text-gray-400 dark:text-gray-500">
To access the available model names for downloading, <a
class=" text-gray-500 dark:text-gray-300 font-medium underline"
href="https://ollama.com/library"
target="_blank">click here.</a
>
</div>
<div class="mt-2 mb-1 text-xs text-gray-400 dark:text-gray-500">
{$i18n.t('To access the available model names for downloading,')}
<a
class=" text-gray-500 dark:text-gray-300 font-medium underline"
href="https://ollama.com/library"
target="_blank">{$i18n.t('click here.')}</a
>
</div>
{#if Object.keys(modelDownloadStatus).length > 0}
{#each Object.keys(modelDownloadStatus) as model}
<div class="flex flex-col">
<div class="font-medium mb-1">{model}</div>
<div class="">
<div
class="dark:bg-gray-600 bg-gray-500 text-xs font-medium text-gray-100 text-center p-0.5 leading-none rounded-full"
style="width: {Math.max(15, modelDownloadStatus[model].pullProgress ?? 0)}%"
>
{modelDownloadStatus[model].pullProgress ?? 0}%
</div>
<div class="mt-1 text-xs dark:text-gray-500" style="font-size: 0.5rem;">
{modelDownloadStatus[model].digest}
{#if 'pullProgress' in modelDownloadStatus[model]}
<div class="flex flex-col">
<div class="font-medium mb-1">{model}</div>
<div class="">
<div class="flex flex-row justify-between space-x-4 pr-2">
<div class=" flex-1">
<div
class="dark:bg-gray-600 bg-gray-500 text-xs font-medium text-gray-100 text-center p-0.5 leading-none rounded-full"
style="width: {Math.max(
15,
modelDownloadStatus[model].pullProgress ?? 0
)}%"
>
{modelDownloadStatus[model].pullProgress ?? 0}%
</div>
</div>
<Tooltip content="Cancel">
<button
class="text-gray-800 dark:text-gray-100"
on:click={() => {
cancelModelPullHandler(model);
}}
>
<svg
class="w-4 h-4 text-gray-800 dark:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"
viewBox="0 0 24 24"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18 17.94 6M18 18 6.06 6"
/>
</svg>
</button>
</Tooltip>
</div>
{#if 'digest' in modelDownloadStatus[model]}
<div class="mt-1 text-xs dark:text-gray-500" style="font-size: 0.5rem;">
{modelDownloadStatus[model].digest}
</div>
{/if}
</div>
</div>
</div>
{/if}
{/each}
{/if}
</div>
<div>
<div class=" mb-2 text-sm font-medium">Delete a model</div>
<div class=" mb-2 text-sm font-medium">{$i18n.t('Delete a model')}</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={deleteModelTag}
placeholder="Select a model"
placeholder={$i18n.t('Select a model')}
>
{#if !deleteModelTag}
<option value="" disabled selected>Select a model</option>
<option value="" disabled selected>{$i18n.t('Select a model')}</option>
{/if}
{#each $models.filter((m) => m.size != null && (selectedOllamaUrlIdx === null ? true : (m?.urls ?? []).includes(selectedOllamaUrlIdx))) as model}
<option value={model.name} class="bg-gray-100 dark:bg-gray-700"
@@ -646,13 +741,13 @@
<div class="pt-1">
<div class="flex justify-between items-center text-xs">
<div class=" text-sm font-medium">Experimental</div>
<div class=" text-sm font-medium">{$i18n.t('Experimental')}</div>
<button
class=" text-xs font-medium text-gray-500"
type="button"
on:click={() => {
showExperimentalOllama = !showExperimentalOllama;
}}>{showExperimentalOllama ? 'Hide' : 'Show'}</button
}}>{showExperimentalOllama ? $i18n.t('Hide') : $i18n.t('Show')}</button
>
</div>
</div>
@@ -664,7 +759,7 @@
}}
>
<div class=" mb-2 flex w-full justify-between">
<div class=" text-sm font-medium">Upload a GGUF model</div>
<div class=" text-sm font-medium">{$i18n.t('Upload a GGUF model')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
@@ -678,9 +773,9 @@
type="button"
>
{#if modelUploadMode === 'file'}
<span class="ml-2 self-center">File Mode</span>
<span class="ml-2 self-center">{$i18n.t('File Mode')}</span>
{:else}
<span class="ml-2 self-center">URL Mode</span>
<span class="ml-2 self-center">{$i18n.t('URL Mode')}</span>
{/if}
</button>
</div>
@@ -704,7 +799,7 @@
<button
type="button"
class="w-full rounded-lg text-left py-2 px-4 dark:text-gray-300 dark:bg-gray-850"
class="w-full rounded-lg text-left py-2 px-4 bg-white dark:text-gray-300 dark:bg-gray-850"
on:click={() => {
modelUploadInputElement.click();
}}
@@ -712,21 +807,21 @@
{#if modelInputFile && modelInputFile.length > 0}
{modelInputFile[0].name}
{:else}
Click here to select
{$i18n.t('Click here to select')}
{/if}
</button>
</div>
{:else}
<div class="flex-1 {modelFileUrl !== '' ? 'mr-2' : ''}">
<input
class="w-full rounded-lg text-left py-2 px-4 dark:text-gray-300 dark:bg-gray-850 outline-none {modelFileUrl !==
class="w-full rounded-lg text-left py-2 px-4 bg-white dark:text-gray-300 dark:bg-gray-850 outline-none {modelFileUrl !==
''
? 'mr-2'
: ''}"
type="url"
required
bind:value={modelFileUrl}
placeholder="Type Hugging Face Resolve (Download) URL"
placeholder={$i18n.t('Type Hugging Face Resolve (Download) URL')}
/>
</div>
{/if}
@@ -734,7 +829,7 @@
{#if (modelUploadMode === 'file' && modelInputFile && modelInputFile.length > 0) || (modelUploadMode === 'url' && modelFileUrl !== '')}
<button
class="px-3 text-gray-100 bg-emerald-600 hover:bg-emerald-700 disabled:bg-gray-700 disabled:cursor-not-allowed rounded transition"
class="px-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-gray-100 rounded-lg disabled:cursor-not-allowed transition"
type="submit"
disabled={modelTransferring}
>
@@ -786,26 +881,43 @@
{#if (modelUploadMode === 'file' && modelInputFile && modelInputFile.length > 0) || (modelUploadMode === 'url' && modelFileUrl !== '')}
<div>
<div>
<div class=" my-2.5 text-sm font-medium">Modelfile Content</div>
<div class=" my-2.5 text-sm font-medium">{$i18n.t('Modelfile Content')}</div>
<textarea
bind:value={modelFileContent}
class="w-full rounded py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none resize-none"
class="w-full rounded-lg py-2 px-4 text-sm bg-gray-100 dark:text-gray-100 dark:bg-gray-850 outline-none resize-none"
rows="6"
/>
</div>
</div>
{/if}
<div class=" mt-1 text-xs text-gray-400 dark:text-gray-500">
To access the GGUF models available for downloading, <a
{$i18n.t('To access the GGUF models available for downloading,')}
<a
class=" text-gray-500 dark:text-gray-300 font-medium underline"
href="https://huggingface.co/models?search=gguf"
target="_blank">click here.</a
target="_blank">{$i18n.t('click here.')}</a
>
</div>
{#if uploadProgress !== null}
{#if uploadMessage}
<div class="mt-2">
<div class=" mb-2 text-xs">Upload Progress</div>
<div class=" mb-2 text-xs">{$i18n.t('Upload Progress')}</div>
<div class="w-full rounded-full dark:bg-gray-800">
<div
class="dark:bg-gray-600 bg-gray-500 text-xs font-medium text-gray-100 text-center p-0.5 leading-none rounded-full"
style="width: 100%"
>
{uploadMessage}
</div>
</div>
<div class="mt-1 text-xs dark:text-gray-500" style="font-size: 0.5rem;">
{modelFileDigest}
</div>
</div>
{:else if uploadProgress !== null}
<div class="mt-2">
<div class=" mb-2 text-xs">{$i18n.t('Upload Progress')}</div>
<div class="w-full rounded-full dark:bg-gray-800">
<div
@@ -832,13 +944,13 @@
<div>
<div class="mb-2">
<div class="flex justify-between items-center text-xs">
<div class=" text-sm font-medium">Manage LiteLLM Models</div>
<div class=" text-sm font-medium">{$i18n.t('Manage LiteLLM Models')}</div>
<button
class=" text-xs font-medium text-gray-500"
type="button"
on:click={() => {
showLiteLLM = !showLiteLLM;
}}>{showLiteLLM ? 'Hide' : 'Show'}</button
}}>{showLiteLLM ? $i18n.t('Hide') : $i18n.t('Show')}</button
>
</div>
</div>
@@ -846,14 +958,16 @@
{#if showLiteLLM}
<div>
<div class="flex justify-between items-center text-xs">
<div class=" text-sm font-medium">Add a model</div>
<div class=" text-sm font-medium">{$i18n.t('Add a model')}</div>
<button
class=" text-xs font-medium text-gray-500"
type="button"
on:click={() => {
showLiteLLMParams = !showLiteLLMParams;
}}
>{showLiteLLMParams ? 'Hide Additional Params' : 'Show Additional Params'}</button
>{showLiteLLMParams
? $i18n.t('Hide Additional Params')
: $i18n.t('Show Additional Params')}</button
>
</div>
</div>
@@ -863,7 +977,7 @@
<div class="flex-1 mr-2">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder="Enter LiteLLM Model (litellm_params.model)"
placeholder={$i18n.t('Enter LiteLLM Model (litellm_params.model)')}
bind:value={liteLLMModel}
autocomplete="off"
/>
@@ -890,7 +1004,7 @@
{#if showLiteLLMParams}
<div>
<div class=" mb-1.5 text-sm font-medium">Model Name</div>
<div class=" mb-1.5 text-sm font-medium">{$i18n.t('Model Name')}</div>
<div class="flex w-full">
<div class="flex-1">
<input
@@ -904,12 +1018,14 @@
</div>
<div>
<div class=" mb-1.5 text-sm font-medium">API Base URL</div>
<div class=" mb-1.5 text-sm font-medium">{$i18n.t('API Base URL')}</div>
<div class="flex w-full">
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder="Enter LiteLLM API Base URL (litellm_params.api_base)"
placeholder={$i18n.t(
'Enter LiteLLM API Base URL (litellm_params.api_base)'
)}
bind:value={liteLLMAPIBase}
autocomplete="off"
/>
@@ -918,12 +1034,12 @@
</div>
<div>
<div class=" mb-1.5 text-sm font-medium">API Key</div>
<div class=" mb-1.5 text-sm font-medium">{$i18n.t('API Key')}</div>
<div class="flex w-full">
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder="Enter LiteLLM API Key (litellm_params.api_key)"
placeholder={$i18n.t('Enter LiteLLM API Key (litellm_params.api_key)')}
bind:value={liteLLMAPIKey}
autocomplete="off"
/>
@@ -932,12 +1048,12 @@
</div>
<div>
<div class="mb-1.5 text-sm font-medium">API RPM</div>
<div class="mb-1.5 text-sm font-medium">{$i18n.t('API RPM')}</div>
<div class="flex w-full">
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder="Enter LiteLLM API RPM (litellm_params.rpm)"
placeholder={$i18n.t('Enter LiteLLM API RPM (litellm_params.rpm)')}
bind:value={liteLLMRPM}
autocomplete="off"
/>
@@ -946,12 +1062,12 @@
</div>
<div>
<div class="mb-1.5 text-sm font-medium">Max Tokens</div>
<div class="mb-1.5 text-sm font-medium">{$i18n.t('Max Tokens')}</div>
<div class="flex w-full">
<div class="flex-1">
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder="Enter Max Tokens (litellm_params.max_tokens)"
placeholder={$i18n.t('Enter Max Tokens (litellm_params.max_tokens)')}
bind:value={liteLLMMaxTokens}
type="number"
min="1"
@@ -964,27 +1080,27 @@
</div>
<div class="mb-2 text-xs text-gray-400 dark:text-gray-500">
Not sure what to add?
{$i18n.t('Not sure what to add?')}
<a
class=" text-gray-300 font-medium underline"
href="https://litellm.vercel.app/docs/proxy/configs#quick-start"
target="_blank"
>
Click here for help.
{$i18n.t('Click here for help.')}
</a>
</div>
<div>
<div class=" mb-2.5 text-sm font-medium">Delete a model</div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Delete a model')}</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<select
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
bind:value={deleteLiteLLMModelId}
placeholder="Select a model"
placeholder={$i18n.t('Select a model')}
>
{#if !deleteLiteLLMModelId}
<option value="" disabled selected>Select a model</option>
<option value="" disabled selected>{$i18n.t('Select a model')}</option>
{/if}
{#each liteLLMModelInfo as model}
<option value={model.model_info.id} class="bg-gray-100 dark:bg-gray-700"
+20 -17
View File
@@ -1,4 +1,5 @@
<script lang="ts">
import { getContext } from 'svelte';
import { toast } from 'svelte-sonner';
import { models, settings, user } from '$lib/stores';
@@ -17,6 +18,8 @@
import Connections from './Settings/Connections.svelte';
import Images from './Settings/Images.svelte';
const i18n = getContext('i18n');
export let show = false;
const saveSettings = async (updated) => {
@@ -58,7 +61,7 @@
<Modal bind:show>
<div>
<div class=" flex justify-between dark:text-gray-300 px-5 py-4">
<div class=" text-lg font-medium self-center">Settings</div>
<div class=" text-lg font-medium self-center">{$i18n.t('Settings')}</div>
<button
class="self-center"
on:click={() => {
@@ -106,7 +109,7 @@
/>
</svg>
</div>
<div class=" self-center">General</div>
<div class=" self-center">{$i18n.t('General')}</div>
</button>
{#if $user?.role === 'admin'}
@@ -131,7 +134,7 @@
/>
</svg>
</div>
<div class=" self-center">Connections</div>
<div class=" self-center">{$i18n.t('Connections')}</div>
</button>
<button
@@ -157,7 +160,7 @@
/>
</svg>
</div>
<div class=" self-center">Models</div>
<div class=" self-center">{$i18n.t('Models')}</div>
</button>
{/if}
@@ -184,7 +187,7 @@
/>
</svg>
</div>
<div class=" self-center">Interface</div>
<div class=" self-center">{$i18n.t('Interface')}</div>
</button>
<button
@@ -211,7 +214,7 @@
/>
</svg>
</div>
<div class=" self-center">Audio</div>
<div class=" self-center">{$i18n.t('Audio')}</div>
</button>
{#if $user.role === 'admin'}
@@ -238,7 +241,7 @@
/>
</svg>
</div>
<div class=" self-center">Images</div>
<div class=" self-center">{$i18n.t('Images')}</div>
</button>
{/if}
@@ -265,7 +268,7 @@
/>
</svg>
</div>
<div class=" self-center">Chats</div>
<div class=" self-center">{$i18n.t('Chats')}</div>
</button>
<button
@@ -291,7 +294,7 @@
/>
</svg>
</div>
<div class=" self-center">Account</div>
<div class=" self-center">{$i18n.t('Account')}</div>
</button>
<button
@@ -317,16 +320,16 @@
/>
</svg>
</div>
<div class=" self-center">About</div>
<div class=" self-center">{$i18n.t('About')}</div>
</button>
</div>
<div class="flex-1 md:min-h-[380px]">
<div class="flex-1 md:min-h-[25rem]">
{#if selectedTab === 'general'}
<General
{getModels}
{saveSettings}
on:save={() => {
toast.success('Settings saved successfully!');
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'models'}
@@ -335,28 +338,28 @@
<Connections
{getModels}
on:save={() => {
toast.success('Settings saved successfully!');
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'interface'}
<Interface
{saveSettings}
on:save={() => {
toast.success('Settings saved successfully!');
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'audio'}
<Audio
{saveSettings}
on:save={() => {
toast.success('Settings saved successfully!');
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'images'}
<Images
{saveSettings}
on:save={() => {
toast.success('Settings saved successfully!');
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'chats'}
@@ -364,7 +367,7 @@
{:else if selectedTab === 'account'}
<Account
saveHandler={() => {
toast.success('Settings saved successfully!');
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'about'}
@@ -1,6 +1,9 @@
<script lang="ts">
import { getContext } from 'svelte';
import Modal from '../common/Modal.svelte';
const i18n = getContext('i18n');
export let downloadChat: Function;
export let shareChat: Function;
@@ -17,11 +20,11 @@
show = false;
}}
>
Share to OpenWebUI Community
{$i18n.t('Share to OpenWebUI Community')}
</button>
<div class="flex justify-center space-x-1 mt-1.5">
<div class=" self-center text-gray-400 text-xs font-medium">or</div>
<div class=" self-center text-gray-400 text-xs font-medium">{$i18n.t('or')}</div>
<button
class=" self-center rounded-full text-xs font-medium text-gray-700 dark:text-gray-500 underline"
@@ -31,7 +34,7 @@
show = false;
}}
>
Download as a File
{$i18n.t('Download as a File')}
</button>
</div>
</div>
+12 -9
View File
@@ -1,13 +1,16 @@
<script lang="ts">
import { getContext } from 'svelte';
import Modal from '../common/Modal.svelte';
const i18n = getContext('i18n');
export let show = false;
</script>
<Modal bind:show>
<div>
<div class=" flex justify-between dark:text-gray-300 px-5 py-4">
<div class=" text-lg font-medium self-center">Keyboard shortcuts</div>
<div class=" text-lg font-medium self-center">{$i18n.t('Keyboard shortcuts')}</div>
<button
class="self-center"
on:click={() => {
@@ -32,7 +35,7 @@
<div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6">
<div class="flex flex-col space-y-3 w-full self-start">
<div class="w-full flex justify-between items-center">
<div class=" text-sm">Open new chat</div>
<div class=" text-sm">{$i18n.t('Open new chat')}</div>
<div class="flex space-x-1 text-xs">
<div
@@ -56,7 +59,7 @@
</div>
<div class="w-full flex justify-between items-center">
<div class=" text-sm">Focus chat input</div>
<div class=" text-sm">{$i18n.t('Focus chat input')}</div>
<div class="flex space-x-1 text-xs">
<div
@@ -74,7 +77,7 @@
</div>
<div class="w-full flex justify-between items-center">
<div class=" text-sm">Copy last code block</div>
<div class=" text-sm">{$i18n.t('Copy last code block')}</div>
<div class="flex space-x-1 text-xs">
<div
@@ -98,7 +101,7 @@
</div>
<div class="w-full flex justify-between items-center">
<div class=" text-sm">Copy last response</div>
<div class=" text-sm">{$i18n.t('Copy last response')}</div>
<div class="flex space-x-1 text-xs">
<div
@@ -124,7 +127,7 @@
<div class="flex flex-col space-y-3 w-full self-start">
<div class="w-full flex justify-between items-center">
<div class=" text-sm">Toggle settings</div>
<div class=" text-sm">{$i18n.t('Toggle settings')}</div>
<div class="flex space-x-1 text-xs">
<div
@@ -141,7 +144,7 @@
</div>
<div class="w-full flex justify-between items-center">
<div class=" text-sm">Toggle sidebar</div>
<div class=" text-sm">{$i18n.t('Toggle sidebar')}</div>
<div class="flex space-x-1 text-xs">
<div
@@ -165,7 +168,7 @@
</div>
<div class="w-full flex justify-between items-center">
<div class=" text-sm">Delete chat</div>
<div class=" text-sm">{$i18n.t('Delete chat')}</div>
<div class="flex space-x-1 text-xs">
<div
@@ -188,7 +191,7 @@
</div>
<div class="w-full flex justify-between items-center">
<div class=" text-sm">Show shortcuts</div>
<div class=" text-sm">{$i18n.t('Show shortcuts')}</div>
<div class="flex space-x-1 text-xs">
<div
+40
View File
@@ -0,0 +1,40 @@
<script lang="ts">
import { DropdownMenu } from 'bits-ui';
import { createEventDispatcher } from 'svelte';
import { flyAndScale } from '$lib/utils/transitions';
const dispatch = createEventDispatcher();
</script>
<DropdownMenu.Root
onOpenChange={(state) => {
dispatch('change', state);
}}
>
<DropdownMenu.Trigger>
<slot />
</DropdownMenu.Trigger>
<slot name="content">
<DropdownMenu.Content
class="w-full max-w-[130px] rounded-lg px-1 py-1.5 border border-gray-700 z-50 bg-gray-850 text-white"
sideOffset={8}
side="bottom"
align="start"
transition={flyAndScale}
>
<DropdownMenu.Item class="flex items-center px-3 py-2 text-sm font-medium">
<div class="flex items-center">Profile</div>
</DropdownMenu.Item>
<DropdownMenu.Item class="flex items-center px-3 py-2 text-sm font-medium">
<div class="flex items-center">Profile</div>
</DropdownMenu.Item>
<DropdownMenu.Item class="flex items-center px-3 py-2 text-sm font-medium">
<div class="flex items-center">Profile</div>
</DropdownMenu.Item>
</DropdownMenu.Content>
</slot>
</DropdownMenu.Root>
+17 -4
View File
@@ -2,6 +2,22 @@
export let show = false;
export let src = '';
export let alt = '';
const downloadImage = (url, filename) => {
fetch(url)
.then((response) => response.blob())
.then((blob) => {
const objectUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = objectUrl;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(objectUrl);
})
.catch((error) => console.error('Error downloading image:', error));
};
</script>
{#if show}
@@ -35,10 +51,7 @@
<button
class=" p-5"
on:click={() => {
const a = document.createElement('a');
a.href = src;
a.download = 'Image.png';
a.click();
downloadImage(src, 'Image.png');
}}
>
<svg
+4 -2
View File
@@ -2,6 +2,8 @@
import { onMount } from 'svelte';
import { fade } from 'svelte/transition';
import { flyAndScale } from '$lib/utils/transitions';
export let show = true;
export let size = 'md';
@@ -41,10 +43,10 @@
}}
>
<div
class=" modal-content m-auto rounded-2xl max-w-full {sizeToWidth(
class=" m-auto rounded-2xl max-w-full {sizeToWidth(
size
)} mx-2 bg-gray-50 dark:bg-gray-900 shadow-3xl"
in:fade={{ duration: 10 }}
in:flyAndScale
on:click={(e) => {
e.stopPropagation();
}}
+87
View File
@@ -0,0 +1,87 @@
<script lang="ts">
import { Select } from 'bits-ui';
import { flyAndScale } from '$lib/utils/transitions';
import { createEventDispatcher } from 'svelte';
import ChevronDown from '../icons/ChevronDown.svelte';
import Check from '../icons/Check.svelte';
import Search from '../icons/Search.svelte';
const dispatch = createEventDispatcher();
export let value = '';
export let placeholder = 'Select a model';
export let items = [
{ value: 'mango', label: 'Mango' },
{ value: 'watermelon', label: 'Watermelon' },
{ value: 'apple', label: 'Apple' },
{ value: 'pineapple', label: 'Pineapple' },
{ value: 'orange', label: 'Orange' }
];
let searchValue = '';
$: filteredItems = searchValue
? items.filter((item) => item.value.includes(searchValue.toLowerCase()))
: items;
</script>
<Select.Root
{items}
onOpenChange={() => {
searchValue = '';
}}
selected={items.find((item) => item.value === value)}
onSelectedChange={(selectedItem) => {
value = selectedItem.value;
}}
>
<Select.Trigger class="relative w-full" aria-label={placeholder}>
<Select.Value
class="inline-flex h-input px-0.5 w-full outline-none bg-transparent truncate text-lg font-semibold placeholder-gray-400 focus:outline-none"
{placeholder}
/>
<ChevronDown className="absolute end-2 top-1/2 -translate-y-[45%] size-3.5" strokeWidth="2.5" />
</Select.Trigger>
<Select.Content
class="w-full rounded-lg bg-white dark:bg-gray-900 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-700/50 outline-none"
transition={flyAndScale}
sideOffset={4}
>
<div class="flex items-center gap-2.5 px-5 mt-3.5 mb-3">
<Search className="size-4" strokeWidth="2.5" />
<input
bind:value={searchValue}
class="w-full text-sm bg-transparent outline-none"
placeholder="Search a model"
/>
</div>
<hr class="border-gray-100 dark:border-gray-800" />
<div class="px-3 my-2 max-h-80 overflow-y-auto">
{#each filteredItems as item}
<Select.Item
class="flex w-full font-medium line-clamp-1 select-none items-center rounded-button py-2 pl-3 pr-1.5 text-sm text-gray-700 dark:text-gray-100 outline-none transition-all duration-75 data-[highlighted]:bg-muted"
value={item.value}
label={item.label}
>
{item.label}
{#if value === item.value}
<div class="ml-auto">
<Check />
</div>
{/if}
</Select.Item>
{:else}
<span class="block px-5 py-2 text-sm text-gray-700 dark:text-gray-100">
No results found
</span>
{/each}
</div>
</Select.Content>
<Select.Input name="favoriteFruit" />
</Select.Root>
@@ -1,7 +1,9 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import { createEventDispatcher, getContext } from 'svelte';
const dispatch = createEventDispatcher();
const i18n = getContext('i18n');
let showTagInput = false;
let tagName = '';
</script>
@@ -9,12 +11,6 @@
<div class="flex space-x-1 pl-1.5">
{#if showTagInput}
<div class="flex items-center">
<input
bind:value={tagName}
class=" cursor-pointer self-center text-xs h-fit bg-transparent outline-none line-clamp-1 w-[4rem]"
placeholder="Add a tag"
/>
<button
type="button"
on:click={() => {
@@ -36,6 +32,11 @@
/>
</svg>
</button>
<input
bind:value={tagName}
class=" pl-2 cursor-pointer self-center text-xs h-fit bg-transparent outline-none line-clamp-1 w-[8rem]"
placeholder={$i18n.t('Add a tag')}
/>
</div>
<!-- TODO: Tag Suggestions -->
@@ -1,7 +1,7 @@
<script lang="ts">
import { toast } from 'svelte-sonner';
import dayjs from 'dayjs';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
import { createNewDoc, getDocs, tagDocByName, updateDocByName } from '$lib/apis/documents';
import Modal from '../common/Modal.svelte';
@@ -13,6 +13,8 @@
import { transformFileName } from '$lib/utils';
import { SUPPORTED_FILE_EXTENSIONS, SUPPORTED_FILE_TYPE } from '$lib/constants';
const i18n = getContext('i18n');
export let show = false;
export let selectedDoc;
let uploadDocInputElement: HTMLInputElement;
@@ -71,7 +73,7 @@
inputFiles = null;
uploadDocInputElement.value = '';
} else {
toast.error(`File not found.`);
toast.error($i18n.t(`File not found.`));
}
show = false;
@@ -96,7 +98,7 @@
<Modal size="sm" bind:show>
<div>
<div class=" flex justify-between dark:text-gray-300 px-5 py-4">
<div class=" text-lg font-medium self-center">Add Docs</div>
<div class=" text-lg font-medium self-center">{$i18n.t('Add Docs')}</div>
<button
class="self-center"
on:click={() => {
@@ -136,7 +138,7 @@
/>
<button
class="w-full text-sm font-medium py-3 bg-gray-850 hover:bg-gray-800 text-center rounded-xl"
class="w-full text-sm font-medium py-3 bg-gray-100 hover:bg-gray-200 dark:bg-gray-850 dark:hover:bg-gray-800 text-center rounded-xl"
type="button"
on:click={() => {
uploadDocInputElement.click();
@@ -145,14 +147,14 @@
{#if inputFiles}
{inputFiles.length > 0 ? `${inputFiles.length}` : ''} document(s) selected.
{:else}
Click here to select documents.
{$i18n.t('Click here to select documents.')}
{/if}
</button>
</div>
<div class=" flex flex-col space-y-1.5">
<div class="flex flex-col w-full">
<div class=" mb-1.5 text-xs text-gray-500">Tags</div>
<div class=" mb-1.5 text-xs text-gray-500">{$i18n.t('Tags')}</div>
<Tags {tags} addTag={addTagHandler} deleteTag={deleteTagHandler} />
</div>
@@ -163,7 +165,7 @@
class=" px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded"
type="submit"
>
Save
{$i18n.t('Save')}
</button>
</div>
</form>
@@ -1,7 +1,7 @@
<script lang="ts">
import { toast } from 'svelte-sonner';
import dayjs from 'dayjs';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
import { getDocs, tagDocByName, updateDocByName } from '$lib/apis/documents';
import Modal from '../common/Modal.svelte';
@@ -10,6 +10,8 @@
import Tags from '../common/Tags.svelte';
import { addTagById } from '$lib/apis/chats';
const i18n = getContext('i18n');
export let show = false;
export let selectedDoc;
@@ -74,7 +76,7 @@
<Modal size="sm" bind:show>
<div>
<div class=" flex justify-between dark:text-gray-300 px-5 py-4">
<div class=" text-lg font-medium self-center">Edit Doc</div>
<div class=" text-lg font-medium self-center">{$i18n.t('Edit Doc')}</div>
<button
class="self-center"
on:click={() => {
@@ -105,7 +107,7 @@
>
<div class=" flex flex-col space-y-1.5">
<div class="flex flex-col w-full">
<div class=" mb-1 text-xs text-gray-500">Name Tag</div>
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Name Tag')}</div>
<div class="flex flex-1">
<div
@@ -134,7 +136,7 @@
</div>
<div class="flex flex-col w-full">
<div class=" mb-1 text-xs text-gray-500">Title</div>
<div class=" mb-1 text-xs text-gray-500">{$i18n.t('Title')}</div>
<div class="flex-1">
<input
@@ -148,7 +150,7 @@
</div>
<div class="flex flex-col w-full">
<div class=" mb-1.5 text-xs text-gray-500">Tags</div>
<div class=" mb-1.5 text-xs text-gray-500">{$i18n.t('Tags')}</div>
<Tags {tags} addTag={addTagHandler} deleteTag={deleteTagHandler} />
</div>
@@ -159,7 +161,7 @@
class=" px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded"
type="submit"
>
Save
{$i18n.t('Save')}
</button>
</div>
</form>
@@ -5,16 +5,22 @@
updateRAGConfig,
getQuerySettings,
scanDocs,
updateQuerySettings
updateQuerySettings,
resetVectorDB
} from '$lib/apis/rag';
import { documents } from '$lib/stores';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
import { toast } from 'svelte-sonner';
const i18n = getContext('i18n');
export let saveHandler: Function;
let loading = false;
let showResetConfirm = false;
let chunkSize = 0;
let chunkOverlap = 0;
let pdfExtractImages = true;
@@ -31,7 +37,7 @@
if (res) {
await documents.set(await getDocs(localStorage.token));
toast.success('Scan complete!');
toast.success($i18n.t('Scan complete!'));
}
};
@@ -69,10 +75,12 @@
>
<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
<div>
<div class=" mb-2 text-sm font-medium">General Settings</div>
<div class=" mb-2 text-sm font-medium">{$i18n.t('General Settings')}</div>
<div class=" flex w-full justify-between">
<div class=" self-center text-xs font-medium">Scan for documents from '/data/docs'</div>
<div class=" self-center text-xs font-medium">
{$i18n.t('Scan for documents from {{path}}', { path: '/data/docs' })}
</div>
<button
class=" self-center text-xs p-1 px-3 bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 rounded flex flex-row space-x-1 items-center {loading
@@ -85,7 +93,7 @@
type="button"
disabled={loading}
>
<div class="self-center font-medium">Scan</div>
<div class="self-center font-medium">{$i18n.t('Scan')}</div>
<!-- <svg
xmlns="http://www.w3.org/2000/svg"
@@ -133,77 +141,76 @@
<hr class=" dark:border-gray-700" />
<div class=" space-y-3">
<div class=" space-y-3">
<div class=" text-sm font-medium">Chunk Params</div>
<div class=" ">
<div class=" text-sm font-medium">{$i18n.t('Chunk Params')}</div>
<div class=" flex gap-2">
<div class=" flex w-full justify-between gap-2">
<div class="self-center text-xs font-medium min-w-fit">Chunk Size</div>
<div class=" flex">
<div class=" flex w-full justify-between">
<div class="self-center text-xs font-medium min-w-fit">{$i18n.t('Chunk Size')}</div>
<div class="self-center">
<input
class=" w-full rounded py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none border border-gray-100 dark:border-gray-600"
type="number"
placeholder="Enter Chunk Size"
bind:value={chunkSize}
autocomplete="off"
min="0"
/>
</div>
</div>
<div class="flex w-full gap-2">
<div class=" self-center text-xs font-medium min-w-fit">Chunk Overlap</div>
<div class="self-center">
<input
class="w-full rounded py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none border border-gray-100 dark:border-gray-600"
type="number"
placeholder="Enter Chunk Overlap"
bind:value={chunkOverlap}
autocomplete="off"
min="0"
/>
</div>
<div class="self-center p-3">
<input
class=" w-full rounded py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none border border-gray-100 dark:border-gray-600"
type="number"
placeholder={$i18n.t('Enter Chunk Size')}
bind:value={chunkSize}
autocomplete="off"
min="0"
/>
</div>
</div>
<div>
<div class="flex justify-between items-center text-xs">
<div class=" text-xs font-medium">PDF Extract Images (OCR)</div>
<div class="flex w-full">
<div class=" self-center text-xs font-medium min-w-fit">{$i18n.t('Chunk Overlap')}</div>
<button
class=" text-xs font-medium text-gray-500"
type="button"
on:click={() => {
pdfExtractImages = !pdfExtractImages;
}}>{pdfExtractImages ? 'On' : 'Off'}</button
>
<div class="self-center p-3">
<input
class="w-full rounded py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none border border-gray-100 dark:border-gray-600"
type="number"
placeholder={$i18n.t('Enter Chunk Overlap')}
bind:value={chunkOverlap}
autocomplete="off"
min="0"
/>
</div>
</div>
</div>
<div>
<div class=" text-sm font-medium">Query Params</div>
<div class="flex justify-between items-center text-xs">
<div class=" text-xs font-medium">{$i18n.t('PDF Extract Images (OCR)')}</div>
<div class=" flex py-2">
<div class=" flex w-full justify-between gap-2">
<div class="self-center text-xs font-medium flex-1">Top K</div>
<button
class=" text-xs font-medium text-gray-500"
type="button"
on:click={() => {
pdfExtractImages = !pdfExtractImages;
}}>{pdfExtractImages ? $i18n.t('On') : $i18n.t('Off')}</button
>
</div>
</div>
</div>
<div class="self-center">
<input
class=" w-full rounded py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none border border-gray-100 dark:border-gray-600"
type="number"
placeholder="Enter Top K"
bind:value={querySettings.k}
autocomplete="off"
min="0"
/>
</div>
<div>
<div class=" text-sm font-medium">{$i18n.t('Query Params')}</div>
<div class=" flex">
<div class=" flex w-full justify-between">
<div class="self-center text-xs font-medium flex-1">{$i18n.t('Top K')}</div>
<div class="self-center p-3">
<input
class=" w-full rounded py-1.5 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none border border-gray-100 dark:border-gray-600"
type="number"
placeholder={$i18n.t('Enter Top K')}
bind:value={querySettings.k}
autocomplete="off"
min="0"
/>
</div>
</div>
<!-- <div class="flex w-full">
<!-- <div class="flex w-full">
<div class=" self-center text-xs font-medium min-w-fit">Chunk Overlap</div>
<div class="self-center p-3">
@@ -217,18 +224,111 @@
/>
</div>
</div> -->
</div>
</div>
<div>
<div class=" mb-2.5 text-sm font-medium">RAG Template</div>
<textarea
bind:value={querySettings.template}
class="w-full rounded p-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none resize-none"
rows="4"
/>
</div>
<div>
<div class=" mb-2.5 text-sm font-medium">{$i18n.t('RAG Template')}</div>
<textarea
bind:value={querySettings.template}
class="w-full rounded p-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none resize-none"
rows="4"
/>
</div>
</div>
<hr class=" dark:border-gray-700" />
{#if showResetConfirm}
<div class="flex justify-between rounded-md items-center py-2 px-3.5 w-full transition">
<div class="flex items-center space-x-3">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path d="M2 3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3Z" />
<path
fill-rule="evenodd"
d="M13 6H3v6a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V6ZM5.72 7.47a.75.75 0 0 1 1.06 0L8 8.69l1.22-1.22a.75.75 0 1 1 1.06 1.06L9.06 9.75l1.22 1.22a.75.75 0 1 1-1.06 1.06L8 10.81l-1.22 1.22a.75.75 0 0 1-1.06-1.06l1.22-1.22-1.22-1.22a.75.75 0 0 1 0-1.06Z"
clip-rule="evenodd"
/>
</svg>
<span>{$i18n.t('Are you sure?')}</span>
</div>
<div class="flex space-x-1.5 items-center">
<button
class="hover:text-white transition"
on:click={() => {
const res = resetVectorDB(localStorage.token).catch((error) => {
toast.error(error);
return null;
});
if (res) {
toast.success($i18n.t('Success'));
}
showResetConfirm = false;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
clip-rule="evenodd"
/>
</svg>
</button>
<button
class="hover:text-white transition"
on:click={() => {
showResetConfirm = false;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
</div>
{:else}
<button
class=" flex rounded-md py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
on:click={() => {
showResetConfirm = true;
}}
>
<div class=" self-center mr-3">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M3.5 2A1.5 1.5 0 0 0 2 3.5v9A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 12.5 4H9.621a1.5 1.5 0 0 1-1.06-.44L7.439 2.44A1.5 1.5 0 0 0 6.38 2H3.5Zm6.75 7.75a.75.75 0 0 0 0-1.5h-4.5a.75.75 0 0 0 0 1.5h4.5Z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class=" self-center text-sm font-medium">{$i18n.t('Reset Vector Storage')}</div>
</button>
{/if}
</div>
<div class="flex justify-end pt-3 text-sm font-medium">
@@ -236,7 +336,7 @@
class=" px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded"
type="submit"
>
Save
{$i18n.t('Save')}
</button>
</div>
</form>
@@ -1,7 +1,10 @@
<script>
import { getContext } from 'svelte';
import Modal from '../common/Modal.svelte';
import General from './Settings/General.svelte';
const i18n = getContext('i18n');
export let show = false;
let selectedTab = 'general';
@@ -10,7 +13,7 @@
<Modal bind:show>
<div>
<div class=" flex justify-between dark:text-gray-300 px-5 py-4">
<div class=" text-lg font-medium self-center">Document Settings</div>
<div class=" text-lg font-medium self-center">{$i18n.t('Document Settings')}</div>
<button
class="self-center"
on:click={() => {
@@ -58,7 +61,7 @@
/>
</svg>
</div>
<div class=" self-center">General</div>
<div class=" self-center">{$i18n.t('General')}</div>
</button>
</div>
<div class="flex-1 md:min-h-[380px]">
+15
View File
@@ -0,0 +1,15 @@
<script lang="ts">
export let className = 'w-4 h-4';
export let strokeWidth = '1.5';
</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="m4.5 12.75 6 6 9-13.5" />
</svg>
@@ -0,0 +1,15 @@
<script lang="ts">
export let className = 'w-4 h-4';
export let strokeWidth = '1.5';
</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="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
@@ -0,0 +1,19 @@
<script lang="ts">
export let className = 'w-4 h-4';
export let strokeWidth = '1.5';
</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="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
/>
</svg>
+19
View File
@@ -0,0 +1,19 @@
<script lang="ts">
export let className = 'w-4 h-4';
export let strokeWidth = '1.5';
</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.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
/>
</svg>
+19
View File
@@ -0,0 +1,19 @@
<script lang="ts">
export let className = 'w-4 h-4';
export let strokeWidth = '1.5';
</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="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"
/>
</svg>
+6 -6
View File
@@ -1,4 +1,5 @@
<script lang="ts">
import { getContext } from 'svelte';
import { toast } from 'svelte-sonner';
import fileSaver from 'file-saver';
const { saveAs } = fileSaver;
@@ -9,6 +10,8 @@
import TagInput from '../common/Tags/TagInput.svelte';
import Tags from '../common/Tags.svelte';
const i18n = getContext('i18n');
export let initNewChat: Function;
export let title: string = $WEBUI_NAME;
export let shareEnabled: boolean = false;
@@ -26,7 +29,7 @@
const chat = (await getChatById(localStorage.token, $chatId)).chat;
console.log('share', chat);
toast.success('Redirecting you to OpenWebUI Community');
toast.success($i18n.t('Redirecting you to OpenWebUI Community'));
const url = 'https://openwebui.com';
// const url = 'http://localhost:5173';
@@ -66,10 +69,7 @@
</script>
<ShareChatModal bind:show={showShareChatModal} {downloadChat} {shareChat} />
<nav
id="nav"
class=" sticky py-2.5 top-0 flex flex-row justify-center bg-white/95 dark:bg-gray-900/90 dark:text-gray-200 backdrop-blur-xl z-30"
>
<nav id="nav" class=" sticky py-2.5 top-0 flex flex-row justify-center z-30">
<div
class=" flex {$settings?.fullScreenMode ?? null
? 'max-w-full'
@@ -110,7 +110,7 @@
<Tags {tags} {deleteTag} {addTag} />
<button
class=" cursor-pointer p-1.5 flex dark:hover:bg-gray-700 rounded-lg transition border dark:border-gray-600"
class=" cursor-pointer p-1.5 flex dark:hover:bg-gray-700 rounded-lg transition"
on:click={async () => {
showShareChatModal = !showShareChatModal;
+203 -198
View File
@@ -7,7 +7,10 @@
import { goto, invalidateAll } from '$app/navigation';
import { page } from '$app/stores';
import { user, chats, settings, showSettings, chatId, tags } from '$lib/stores';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
const i18n = getContext('i18n');
import {
deleteChatById,
getChatList,
@@ -17,9 +20,10 @@
getAllChatTags
} from '$lib/apis/chats';
import { toast } from 'svelte-sonner';
import { slide } from 'svelte/transition';
import { fade, slide } from 'svelte/transition';
import { WEBUI_BASE_URL } from '$lib/constants';
import Tooltip from '../common/Tooltip.svelte';
import ChatMenu from './Sidebar/ChatMenu.svelte';
let show = false;
let navElement;
@@ -27,6 +31,8 @@
let title: string = 'UI';
let search = '';
let selectedChatId = null;
let chatDeleteId = null;
let chatTitleEditId = null;
let chatTitle = '';
@@ -82,7 +88,10 @@
});
if (res) {
goto('/');
if ($chatId === id) {
goto('/');
}
await chats.set(await getChatList(localStorage.token));
}
};
@@ -98,7 +107,7 @@
bind:this={navElement}
class="h-screen max-h-[100dvh] min-h-screen {show
? 'lg:relative w-[260px]'
: '-translate-x-[260px] w-[0px]'} bg-black text-gray-200 shadow-2xl text-sm transition z-40 fixed top-0 left-0
: '-translate-x-[260px] w-[0px]'} bg-gray-50 text-gray-900 dark:bg-gray-950 dark:text-gray-200 text-sm transition z-40 fixed top-0 left-0
"
>
<div
@@ -109,9 +118,11 @@
<div class="px-2 flex justify-center space-x-2">
<a
id="sidebar-new-chat-button"
class="flex-grow flex justify-between rounded-xl px-3.5 py-2 hover:bg-gray-900 transition"
class="flex-grow flex justify-between rounded-xl px-4 py-2 hover:bg-gray-200 dark:hover:bg-gray-900 transition"
href="/"
on:click={async () => {
selectedChatId = null;
await goto('/');
const newChatButton = document.getElementById('new-chat-button');
setTimeout(() => {
@@ -123,12 +134,12 @@
<div class="self-center mr-1.5">
<img
src="{WEBUI_BASE_URL}/static/favicon.png"
class=" w-7 -translate-x-1.5 rounded-full"
class=" size-6 -translate-x-1.5 rounded-full"
alt="logo"
/>
</div>
<div class=" self-center font-medium text-sm">New Chat</div>
<div class=" self-center font-medium text-sm">{$i18n.t('New Chat')}</div>
</div>
<div class="self-center">
@@ -152,15 +163,19 @@
{#if $user?.role === 'admin'}
<div class="px-2 flex justify-center mt-0.5">
<a
class="flex-grow flex space-x-3 rounded-xl px-3.5 py-2 hover:bg-gray-900 transition"
class="flex-grow flex space-x-3 rounded-xl px-3.5 py-2 hover:bg-gray-200 dark:hover:bg-gray-900 transition"
href="/modelfiles"
on:click={() => {
selectedChatId = null;
chatId.set('');
}}
>
<div class="self-center">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke-width="2"
stroke="currentColor"
class="w-4 h-4"
>
@@ -173,22 +188,26 @@
</div>
<div class="flex self-center">
<div class=" self-center font-medium text-sm">Modelfiles</div>
<div class=" self-center font-medium text-sm">{$i18n.t('Modelfiles')}</div>
</div>
</a>
</div>
<div class="px-2 flex justify-center">
<a
class="flex-grow flex space-x-3 rounded-xl px-3.5 py-2 hover:bg-gray-900 transition"
class="flex-grow flex space-x-3 rounded-xl px-3.5 py-2 hover:bg-gray-200 dark:hover:bg-gray-900 transition"
href="/prompts"
on:click={() => {
selectedChatId = null;
chatId.set('');
}}
>
<div class="self-center">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke-width="2"
stroke="currentColor"
class="w-4 h-4"
>
@@ -201,22 +220,26 @@
</div>
<div class="flex self-center">
<div class=" self-center font-medium text-sm">Prompts</div>
<div class=" self-center font-medium text-sm">{$i18n.t('Prompts')}</div>
</div>
</a>
</div>
<div class="px-2 flex justify-center mb-1">
<a
class="flex-grow flex space-x-3 rounded-xl px-3.5 py-2 hover:bg-gray-900 transition"
class="flex-grow flex space-x-3 rounded-xl px-3.5 py-2 hover:bg-gray-200 dark:hover:bg-gray-900 transition"
href="/documents"
on:click={() => {
selectedChatId = null;
chatId.set('');
}}
>
<div class="self-center">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke-width="2"
stroke="currentColor"
class="w-4 h-4"
>
@@ -229,7 +252,7 @@
</div>
<div class="flex self-center">
<div class=" self-center font-medium text-sm">Documents</div>
<div class=" self-center font-medium text-sm">{$i18n.t('Documents')}</div>
</div>
</a>
</div>
@@ -237,13 +260,15 @@
<div class="relative flex flex-col flex-1 overflow-y-auto">
{#if !($settings.saveChatHistory ?? true)}
<div class="absolute z-40 w-full h-full bg-black/90 flex justify-center">
<div class="absolute z-40 w-full h-full bg-gray-50/90 dark:bg-black/90 flex justify-center">
<div class=" text-left px-5 py-2">
<div class=" font-medium">Chat History is off for this browser.</div>
<div class=" font-medium">{$i18n.t('Chat History is off for this browser.')}</div>
<div class="text-xs mt-2">
When history is turned off, new chats on this browser won't appear in your history on
any of your devices. <span class=" font-semibold"
>This setting does not sync across browsers or devices.</span
{$i18n.t(
"When history is turned off, new chats on this browser won't appear in your history on any of your devices."
)}
<span class=" font-semibold"
>{$i18n.t('This setting does not sync across browsers or devices.')}</span
>
</div>
@@ -270,7 +295,7 @@
/>
</svg>
<div>Enable Chat History</div>
<div>{$i18n.t('Enable Chat History')}</div>
</button>
</div>
</div>
@@ -279,7 +304,7 @@
<div class="px-2 mt-1 mb-2 flex justify-center space-x-2">
<div class="flex w-full" id="chat-search">
<div class="self-center pl-3 py-2 rounded-l-xl bg-gray-950">
<div class="self-center pl-3 py-2 rounded-l-xl bg-white dark:bg-gray-950">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
@@ -295,37 +320,20 @@
</div>
<input
class="w-full rounded-r-xl py-1.5 pl-2.5 pr-4 text-sm text-gray-300 bg-gray-950 outline-none"
placeholder="Search"
class="w-full rounded-r-xl py-1.5 pl-2.5 pr-4 text-sm dark:text-gray-300 dark:bg-gray-950 outline-none"
placeholder={$i18n.t('Search')}
bind:value={search}
on:focus={() => {
enrichChatsWithContent($chats);
}}
/>
<!-- <div class="self-center pr-3 py-2 bg-gray-900">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-4 h-4"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 01-.659 1.591l-5.432 5.432a2.25 2.25 0 00-.659 1.591v2.927a2.25 2.25 0 01-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 00-.659-1.591L3.659 7.409A2.25 2.25 0 013 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0112 3z"
/>
</svg>
</div> -->
</div>
</div>
{#if $tags.length > 0}
<div class="px-2.5 mt-0.5 mb-2 flex gap-1 flex-wrap">
<button
class="px-2.5 text-xs font-medium bg-gray-900 hover:bg-gray-800 transition rounded-full"
class="px-2.5 text-xs font-medium bg-gray-100 dark:bg-gray-900 dark:hover:bg-gray-800 transition rounded-full"
on:click={async () => {
await chats.set(await getChatList(localStorage.token));
}}
@@ -334,7 +342,7 @@
</button>
{#each $tags as tag}
<button
class="px-2.5 text-xs font-medium bg-gray-900 hover:bg-gray-800 transition rounded-full"
class="px-2.5 text-xs font-medium bg-gray-100 dark:bg-gray-900 dark:hover:bg-gray-800 transition rounded-full"
on:click={async () => {
let chatIds = await getChatListByTagName(localStorage.token, tag.name);
if (chatIds.length === 0) {
@@ -370,24 +378,31 @@
return title.includes(query) || contentMatches;
}
}) as chat, i}
<div class=" w-full pr-2 relative">
<div class=" w-full pr-2 relative group">
{#if chatTitleEditId === chat.id}
<div
class=" w-full flex justify-between rounded-xl px-3 py-2 hover:bg-gray-900 {chat.id ===
$chatId
? 'bg-gray-900'
: ''} transition whitespace-nowrap text-ellipsis"
class=" w-full flex justify-between rounded-xl px-3 py-2 {chat.id === $chatId ||
chat.id === chatTitleEditId ||
chat.id === chatDeleteId
? 'bg-gray-300 dark:bg-gray-900'
: chat.id === selectedChatId
? 'bg-gray-100 dark:bg-gray-950'
: 'group-hover:bg-gray-100 dark:group-hover:bg-gray-950'} whitespace-nowrap text-ellipsis"
>
<input bind:value={chatTitle} class=" bg-transparent w-full outline-none mr-10" />
</div>
{:else}
<a
class=" w-full flex justify-between rounded-xl px-3 py-2 hover:bg-gray-900 {chat.id ===
$chatId
? 'bg-gray-900'
: ''} transition whitespace-nowrap text-ellipsis"
class=" w-full flex justify-between rounded-xl px-3 py-2 {chat.id === $chatId ||
chat.id === chatTitleEditId ||
chat.id === chatDeleteId
? 'bg-gray-300 dark:bg-gray-900'
: chat.id === selectedChatId
? 'bg-gray-100 dark:bg-gray-950'
: ' group-hover:bg-gray-100 dark:group-hover:bg-gray-950'} whitespace-nowrap text-ellipsis"
href="/c/{chat.id}"
on:click={() => {
selectedChatId = chat.id;
if (window.innerWidth < 1024) {
show = false;
}
@@ -395,156 +410,142 @@
draggable="false"
>
<div class=" flex self-center flex-1 w-full">
<div
class=" text-left self-center overflow-hidden {chat.id === $chatId
? 'w-[160px]'
: 'w-full'} h-[20px]"
>
<div class=" text-left self-center overflow-hidden w-full h-[20px]">
{chat.title}
</div>
</div>
</a>
{/if}
{#if chat.id === $chatId}
<div class=" absolute right-[22px] top-[10px]">
{#if chatTitleEditId === chat.id}
<div class="flex self-center space-x-1.5">
<div
class="
{chat.id === $chatId || chat.id === chatTitleEditId || chat.id === chatDeleteId
? 'from-gray-300 dark:from-gray-900'
: chat.id === selectedChatId
? 'from-gray-100 dark:from-gray-950'
: 'invisible group-hover:visible from-gray-100 dark:from-gray-950'}
absolute right-[10px] top-[10px] pr-2 pl-5 bg-gradient-to-l from-80%
to-transparent"
>
{#if chatTitleEditId === chat.id}
<div class="flex self-center space-x-1.5 z-10">
<button
class=" self-center dark:hover:text-white transition"
on:click={() => {
editChatTitle(chat.id, chatTitle);
chatTitleEditId = null;
chatTitle = '';
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
clip-rule="evenodd"
/>
</svg>
</button>
<button
class=" self-center dark:hover:text-white transition"
on:click={() => {
chatTitleEditId = null;
chatTitle = '';
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
{:else if chatDeleteId === chat.id}
<div class="flex self-center space-x-1.5 z-10">
<button
class=" self-center dark:hover:text-white transition"
on:click={() => {
deleteChat(chat.id);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
clip-rule="evenodd"
/>
</svg>
</button>
<button
class=" self-center dark:hover:text-white transition"
on:click={() => {
chatDeleteId = null;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
{:else}
<div class="flex self-center space-x-1.5 z-10">
<ChatMenu
renameHandler={() => {
chatTitle = chat.title;
chatTitleEditId = chat.id;
}}
deleteHandler={() => {
chatDeleteId = chat.id;
}}
onClose={() => {
selectedChatId = null;
}}
>
<button
class=" self-center hover:text-white transition"
aria-label="Chat Menu"
class=" self-center dark:hover:text-white transition"
on:click={() => {
editChatTitle(chat.id, chatTitle);
chatTitleEditId = null;
chatTitle = '';
selectedChatId = chat.id;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
clip-rule="evenodd"
d="M2 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM6.5 8a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0ZM12.5 6.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z"
/>
</svg>
</button>
<button
class=" self-center hover:text-white transition"
on:click={() => {
chatTitleEditId = null;
chatTitle = '';
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
{:else if chatDeleteId === chat.id}
<div class="flex self-center space-x-1.5">
<button
class=" self-center hover:text-white transition"
on:click={() => {
deleteChat(chat.id);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
clip-rule="evenodd"
/>
</svg>
</button>
<button
class=" self-center hover:text-white transition"
on:click={() => {
chatDeleteId = null;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
{:else}
<div class="flex self-center space-x-1.5">
<button
id="delete-chat-button"
class=" hidden"
on:click={() => {
deleteChat(chat.id);
}}
/>
<button
class=" self-center hover:text-white transition"
on:click={() => {
chatTitle = chat.title;
chatTitleEditId = chat.id;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-4 h-4"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
/>
</svg>
</button>
<button
class=" self-center hover:text-white transition"
on:click={() => {
chatDeleteId = chat.id;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-4 h-4"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
/>
</svg>
</button>
</div>
{/if}
</div>
{/if}
</ChatMenu>
</div>
{/if}
</div>
</div>
{/each}
</div>
@@ -556,7 +557,7 @@
<div class="flex flex-col">
{#if $user !== undefined}
<button
class=" flex rounded-xl py-3 px-3.5 w-full hover:bg-gray-900 transition"
class=" flex rounded-xl py-3 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-900 transition"
on:click={() => {
showDropdown = !showDropdown;
}}
@@ -574,13 +575,13 @@
{#if showDropdown}
<div
id="dropdownDots"
class="absolute z-40 bottom-[70px] 4.5rem rounded-xl shadow w-[240px] bg-gray-900"
in:slide={{ duration: 150 }}
class="absolute z-40 bottom-[70px] 4.5rem rounded-xl shadow w-[240px] bg-white dark:bg-gray-900"
transition:fade|slide={{ duration: 100 }}
>
<div class="py-2 w-full">
{#if $user.role === 'admin'}
<button
class="flex py-2.5 px-3.5 w-full hover:bg-gray-800 transition"
class="flex py-2.5 px-3.5 w-full dark:hover:bg-gray-800 transition"
on:click={() => {
goto('/admin');
showDropdown = false;
@@ -602,11 +603,11 @@
/>
</svg>
</div>
<div class=" self-center font-medium">Admin Panel</div>
<div class=" self-center font-medium">{$i18n.t('Admin Panel')}</div>
</button>
<button
class="flex py-2.5 px-3.5 w-full hover:bg-gray-800 transition"
class="flex py-2.5 px-3.5 w-full dark:hover:bg-gray-800 transition"
on:click={() => {
goto('/playground');
showDropdown = false;
@@ -628,12 +629,12 @@
/>
</svg>
</div>
<div class=" self-center font-medium">Playground</div>
<div class=" self-center font-medium">{$i18n.t('Playground')}</div>
</button>
{/if}
<button
class="flex py-2.5 px-3.5 w-full hover:bg-gray-800 transition"
class="flex py-2.5 px-3.5 w-full dark:hover:bg-gray-800 transition"
on:click={async () => {
await showSettings.set(true);
showDropdown = false;
@@ -660,15 +661,15 @@
/>
</svg>
</div>
<div class=" self-center font-medium">Settings</div>
<div class=" self-center font-medium">{$i18n.t('Settings')}</div>
</button>
</div>
<hr class=" border-gray-700 m-0 p-0" />
<hr class=" dark:border-gray-700 m-0 p-0" />
<div class="py-2 w-full">
<button
class="flex py-2.5 px-3.5 w-full hover:bg-gray-800 transition"
class="flex py-2.5 px-3.5 w-full dark:hover:bg-gray-800 transition"
on:click={() => {
localStorage.removeItem('token');
location.href = '/auth';
@@ -694,7 +695,7 @@
/>
</svg>
</div>
<div class=" self-center font-medium">Sign Out</div>
<div class=" self-center font-medium">{$i18n.t('Sign Out')}</div>
</button>
</div>
</div>
@@ -707,7 +708,11 @@
<div
class="fixed left-0 top-[50dvh] z-40 -translate-y-1/2 transition-transform translate-x-[255px] md:translate-x-[260px] rotate-0"
>
<Tooltip placement="right" content={`${show ? 'Close' : 'Open'} sidebar`} touch={false}>
<Tooltip
placement="right"
content={`${show ? $i18n.t('Close') : $i18n.t('Open')} ${$i18n.t('sidebar')}`}
touch={false}
>
<button
id="sidebar-toggle-button"
class=" group"
@@ -716,7 +721,7 @@
}}
><span class="" data-state="closed"
><div
class="flex h-[72px] w-8 items-center justify-center opacity-20 group-hover:opacity-100 transition"
class="flex h-[72px] w-8 items-center justify-center opacity-50 group-hover:opacity-100 transition"
>
<div class="flex h-6 w-6 flex-col items-center">
<div
@@ -0,0 +1,56 @@
<script lang="ts">
import { DropdownMenu } from 'bits-ui';
import { flyAndScale } from '$lib/utils/transitions';
import Dropdown from '$lib/components/common/Dropdown.svelte';
import GarbageBin from '$lib/components/icons/GarbageBin.svelte';
import Pencil from '$lib/components/icons/Pencil.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
export let renameHandler: Function;
export let deleteHandler: Function;
export let onClose: Function;
</script>
<Dropdown
on:change={(e) => {
if (e.detail === false) {
onClose();
}
}}
>
<Tooltip content="More">
<slot />
</Tooltip>
<div slot="content">
<DropdownMenu.Content
class="w-full max-w-[130px] rounded-lg 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"
sideOffset={-2}
side="bottom"
align="start"
transition={flyAndScale}
>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer"
on:click={() => {
renameHandler();
}}
>
<Pencil strokeWidth="2" />
<div class="flex items-center">Rename</div>
</DropdownMenu.Item>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer"
on:click={() => {
deleteHandler();
}}
>
<GarbageBin strokeWidth="2" />
<div class="flex items-center">Delete</div>
</DropdownMenu.Item>
</DropdownMenu.Content>
</div>
</Dropdown>
@@ -1,5 +1,7 @@
<script lang="ts">
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
const i18n = getContext('i18n');
export let messages = [];
let textAreaElement: HTMLTextAreaElement;
@@ -19,16 +21,20 @@
class="px-2 py-1 text-sm font-semibold uppercase min-w-[6rem] text-left dark:group-hover:bg-gray-800 rounded-lg transition"
on:click={() => {
message.role = message.role === 'user' ? 'assistant' : 'user';
}}>{message.role}</button
}}>{$i18n.t(message.role)}</button
>
</div>
<div class="flex-1">
<!-- $i18n.t('a user') -->
<!-- $i18n.t('an assistant') -->
<textarea
id="{message.role}-{idx}-textarea"
bind:this={textAreaElement}
class="w-full bg-transparent outline-none rounded-lg p-2 text-sm resize-none overflow-hidden"
placeholder="Enter {message.role === 'user' ? 'a user' : 'an assistant'} message here"
placeholder={$i18n.t(`Enter {{role}} message here`, {
role: message.role === 'user' ? $i18n.t('a user') : $i18n.t('an assistant')
})}
rows="1"
on:input={(e) => {
textAreaElement.style.height = '';
@@ -100,6 +106,6 @@
</svg>
</div>
<div class=" text-sm font-medium">Add message</div>
<div class=" text-sm font-medium">{$i18n.t('Add message')}</div>
</button>
</div>
+73
View File
@@ -0,0 +1,73 @@
import i18next from 'i18next';
import resourcesToBackend from 'i18next-resources-to-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import type { i18n as i18nType } from 'i18next';
import { writable } from 'svelte/store';
const createI18nStore = (i18n: i18nType) => {
const i18nWritable = writable(i18n);
i18n.on('initialized', () => {
i18nWritable.set(i18n);
});
i18n.on('loaded', () => {
i18nWritable.set(i18n);
});
i18n.on('added', () => i18nWritable.set(i18n));
i18n.on('languageChanged', () => {
i18nWritable.set(i18n);
});
return i18nWritable;
};
const createIsLoadingStore = (i18n: i18nType) => {
const isLoading = writable(false);
// if loaded resources are empty || {}, set loading to true
i18n.on('loaded', (resources) => {
// console.log('loaded:', resources);
Object.keys(resources).length !== 0 && isLoading.set(false);
});
// if resources failed loading, set loading to true
i18n.on('failedLoading', () => {
isLoading.set(true);
});
return isLoading;
};
i18next
.use(
resourcesToBackend(
(language: string, namespace: string) => import(`./locales/${language}/${namespace}.json`)
)
)
.use(LanguageDetector)
.init({
debug: false,
detection: {
order: ['querystring', 'localStorage', 'navigator'],
caches: ['localStorage'],
lookupQuerystring: 'lang',
lookupLocalStorage: 'locale'
},
fallbackLng: {
default: ['en-US']
},
ns: 'translation',
returnEmptyString: false,
interpolation: {
escapeValue: false // not needed for svelte as it escapes by default
}
});
const i18n = createI18nStore(i18next);
const isLoadingStore = createIsLoadingStore(i18next);
export const getLanguages = async () => {
const languages = (await import(`./locales/languages.json`)).default;
return languages;
};
export default i18n;
export const isLoading = isLoadingStore;
+363
View File
@@ -0,0 +1,363 @@
{
"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'с', 'м', 'ч', 'д', 'с' или '-1' за неограничен срок.",
"(Beta)": "(Бета)",
"(e.g. `sh webui.sh --api`)": "(например `sh webui.sh --api`)",
"(latest)": "(последна)",
"{{modelName}} is thinking...": "{{modelName}} мисли ...",
"{{webUIName}} Backend Required": "{{webUIName}} Изисква се Бекенд",
"a user": "потребител",
"About": "Относно",
"Account": "Акаунт",
"Action": "Действие",
"Add a model": "Добавяне на модел",
"Add a model tag name": "Добавяне на име на таг за модел",
"Add a short description about what this modelfile does": "Добавяне на кратко описание за това какво прави този модфайл",
"Add a short title for this prompt": "Добавяне на кратко заглавие за този промпт",
"Add a tag": "Добавяне на таг",
"Add Docs": "Добавяне на Документи",
"Add Files": "Добавяне на Файлове",
"Add message": "Добавяне на съобщение",
"add tags": "добавяне на тагове",
"Adjusting these settings will apply changes universally to all users.": "При промяна на тези настройки промените се прилагат за всички потребители.",
"admin": "админ",
"Admin Panel": "Панел на Администратор",
"Admin Settings": "Настройки на Администратор",
"Advanced Parameters": "Разширени Параметри",
"all": "всички",
"All Users": "Всички Потребители",
"Allow": "Позволи",
"Allow Chat Deletion": "Позволи Изтриване на Чат",
"alphanumeric characters and hyphens": "алфанумерични знаци и тире",
"Already have an account?": "Вече имате акаунт? ",
"an assistant": "асистент",
"and": "и",
"API Base URL": "API Базов URL",
"API Key": "API Ключ",
"API RPM": "API RPM",
"are allowed - Activate this command by typing": "са разрешени - Активирайте тази команда чрез въвеждане",
"Are you sure?": "Сигурни ли сте?",
"Audio": "Аудио",
"Auto-playback response": "Аувтоматично възпроизвеждане на Отговора",
"Auto-send input after 3 sec.": "Аувтоматично изпращане на входа след 3 сек.",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 Базов URL",
"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 Базов URL е задължителен.",
"available!": "наличен!",
"Back": "Назад",
"Builder Mode": "Режим на Създаване",
"Cancel": "Отказ",
"Categories": "Категории",
"Change Password": "Промяна на Парола",
"Chat": "Чат",
"Chat History": "Чат История",
"Chat History is off for this browser.": "Чат История е изключен за този браузър.",
"Chats": "Чатове",
"Check Again": "Проверете Още Веднъж",
"Check for updates": "Проверка за актуализации",
"Checking for updates...": "Проверка за актуализации...",
"Choose a model before saving...": "Изберете модел преди запазване...",
"Chunk Overlap": "Chunk Overlap",
"Chunk Params": "Chunk Params",
"Chunk Size": "Chunk Size",
"Click here for help.": "Натиснете тук за помощ.",
"Click here to check other modelfiles.": "Натиснете тук за проверка на други моделфайлове.",
"Click here to select": "Натиснете тук, за да изберете",
"Click here to select documents.": "Натиснете тук, за да изберете документи.",
"click here.": "натиснете тук.",
"Click on the user role button to change a user's role.": "Натиснете върху бутона за промяна на ролята на потребителя.",
"Close": "Затвори",
"Collection": "Колекция",
"Command": "Команда",
"Confirm Password": "Потвърди Парола",
"Connections": "Връзки",
"Content": "Съдържание",
"Context Length": "Дължина на Контекста",
"Conversation Mode": "Режим на Чат",
"Copy last code block": "Копиране на последен код блок",
"Copy last response": "Копиране на последен отговор",
"Copying to clipboard was successful!": "Копирането в клипборда беше успешно!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Създайте кратка фраза от 3-5 думи като заглавие за следващото запитване, като стриктно спазвате ограничението от 3-5 думи и избягвате използването на думата 'заглавие':",
"Create a modelfile": "Създаване на модфайл",
"Create Account": "Създаване на Акаунт",
"Created at": "Създадено на",
"Created by": "Създадено от",
"Current Model": "Текущ модел",
"Current Password": "Текуща Парола",
"Custom": "Персонализиран",
"Customize Ollama models for a specific purpose": "Персонализиране на Ollama моделите за конкретна цел",
"Dark": "Тъмен",
"Database": "База данни",
"DD/MM/YYYY HH:mm": "DD/MM/YYYY HH:mm",
"Default": "По подразбиране",
"Default (Automatic1111)": "По подразбиране (Automatic1111)",
"Default (Web API)": "По подразбиране (Web API)",
"Default model updated": "Моделът по подразбиране е обновен",
"Default Prompt Suggestions": "Промпт Предложения по подразбиране",
"Default User Role": "Роля на потребителя по подразбиране",
"delete": "изтриване",
"Delete a model": "Изтриване на модел",
"Delete chat": "Изтриване на чат",
"Delete Chats": "Изтриване на Чатове",
"Deleted {{deleteModelTag}}": "Изтрито {{deleteModelTag}}",
"Deleted {tagName}": "Изтрито {tagName}",
"Description": "Описание",
"Desktop Notifications": "Десктоп Известия",
"Disabled": "Деактивиран",
"Discover a modelfile": "Откриване на модфайл",
"Discover a prompt": "Откриване на промпт",
"Discover, download, and explore custom prompts": "Откриване, сваляне и преглед на персонализирани промптове",
"Discover, download, and explore model presets": "Откриване, сваляне и преглед на пресетове на модели",
"Display the username instead of You in the Chat": "Показване на потребителското име вместо Вие в чата",
"Document": "Документ",
"Document Settings": "Документ Настройки",
"Documents": "Документи",
"does not make any external connections, and your data stays securely on your locally hosted server.": "няма външни връзки, и вашите данни остават сигурни на локално назначен сървър.",
"Don't Allow": "Не Позволявай",
"Don't have an account?": "Нямате акаунт?",
"Download as a File": "Сваляне като Файл",
"Download Database": "Сваляне на база данни",
"Drop any files here to add to the conversation": "Пускане на файлове тук, за да ги добавите в чата",
"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "напр. '30с','10м'. Валидни единици са 'с', 'м', 'ч'.",
"Edit Doc": "Редактиране на документ",
"Edit User": "Редактиране на потребител",
"Email": "Имейл",
"Enable Chat History": "Вклюване на Чат История",
"Enable New Sign Ups": "Вклюване на Нови Потребители",
"Enabled": "Включено",
"Enter {{role}} message here": "Въведете съобщение за {{role}} тук",
"Enter API Key": "Въведете API ключ",
"Enter Chunk Overlap": "Въведете Chunk Overlap",
"Enter Chunk Size": "Въведете Chunk Size",
"Enter Image Size (e.g. 512x512)": "Въведете размер на изображението (напр. 512x512)",
"Enter LiteLLM API Base URL (litellm_params.api_base)": "Въведете LiteLLM API Base URL (litellm_params.api_base)",
"Enter LiteLLM API Key (litellm_params.api_key)": "Въведете LiteLLM API Key (litellm_params.api_key)",
"Enter LiteLLM API RPM (litellm_params.rpm)": "Въведете LiteLLM API RPM (litellm_params.rpm)",
"Enter LiteLLM Model (litellm_params.model)": "Въведете LiteLLM Model (litellm_params.model)",
"Enter Max Tokens (litellm_params.max_tokens)": "Въведете Max Tokens (litellm_params.max_tokens)",
"Enter model tag (e.g. {{modelTag}})": "Въведете таг на модел (напр. {{modelTag}})",
"Enter Number of Steps (e.g. 50)": "Въведете брой стъпки (напр. 50)",
"Enter stop sequence": "Въведете стоп последователност",
"Enter Top K": "Въведете Top K",
"Enter URL (e.g. http://127.0.0.1:7860/)": "Въведете URL (напр. http://127.0.0.1:7860/)",
"Enter Your Email": "Въведете имейл",
"Enter Your Full Name": "Въведете вашето пълно име",
"Enter Your Password": "Въведете вашата парола",
"Experimental": "Експериментално",
"Export All Chats (All Users)": "Експортване на всички чатове (За всички потребители)",
"Export Chats": "Експортване на чатове",
"Export Documents Mapping": "Експортване на документен мапинг",
"Export Modelfiles": "Експортване на модфайлове",
"Export Prompts": "Експортване на промптове",
"Failed to read clipboard contents": "Грешка при четене на съдържанието от клипборда",
"File Mode": "Файл Мод",
"File not found.": "Файл не е намерен.",
"Focus chat input": "Фокусиране на чат вход",
"Format your variables using square brackets like this:": "Форматирайте вашите променливи, като използвате квадратни скоби, както следва:",
"From (Base Model)": "От (Базов модел)",
"Full Screen Mode": "На Цял екран",
"General": "Основни",
"General Settings": "Основни Настройки",
"Hello, {{name}}": "Здравей, {{name}}",
"Hide": "Скрий",
"Hide Additional Params": "Скрий допълнителни параметри",
"How can I help you today?": "Как мога да ви помогна днес?",
"Image Generation (Experimental)": "Генерация на изображения (Експериментално)",
"Image Generation Engine": "Двигател за генериране на изображения",
"Image Settings": "Настройки на изображения",
"Images": "Изображения",
"Import Chats": "Импортване на чатове",
"Import Documents Mapping": "Импортване на документен мапинг",
"Import Modelfiles": "Импортване на модфайлове",
"Import Prompts": "Импортване на промптове",
"Include `--api` flag when running stable-diffusion-webui": "Включете флага `--api`, когато стартирате stable-diffusion-webui",
"Interface": "Интерфейс",
"join our Discord for help.": "свържете се с нашия Discord за помощ.",
"JSON": "JSON",
"JWT Expiration": "JWT Expiration",
"JWT Token": "JWT Token",
"Keep Alive": "Keep Alive",
"Keyboard shortcuts": "Клавиши за бърз достъп",
"Language": "Език",
"Light": "Светъл",
"Listening...": "Слушам...",
"LLMs can make mistakes. Verify important information.": "LLMs могат да правят грешки. Проверете важните данни.",
"Made by OpenWebUI Community": "Направено от OpenWebUI общността",
"Make sure to enclose them with": "Уверете се, че са заключени с",
"Manage LiteLLM Models": "Управление на LiteLLM Моделите",
"Manage Models": "Управление на Моделите",
"Manage Ollama Models": "Управление на Ollama Моделите",
"Max Tokens": "Max Tokens",
"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Максимум 3 модели могат да бъдат сваляни едновременно. Моля, опитайте отново по-късно.",
"Mirostat": "Mirostat",
"Mirostat Eta": "Mirostat Eta",
"Mirostat Tau": "Mirostat Tau",
"MMMM DD, YYYY": "MMMM DD, YYYY",
"Model '{{modelName}}' has been successfully downloaded.": "Моделът '{{modelName}}' беше успешно свален.",
"Model '{{modelTag}}' is already in queue for downloading.": "Моделът '{{modelTag}}' е вече в очакване за сваляне.",
"Model {{modelId}} not found": "Моделът {{modelId}} не е намерен",
"Model {{modelName}} already exists.": "Моделът {{modelName}} вече съществува.",
"Model Name": "Име на модел",
"Model not selected": "Не е избран модел",
"Model Tag Name": "Име на таг на модел",
"Model Whitelisting": "Модел Whitelisting",
"Model(s) Whitelisted": "Модели Whitelisted",
"Modelfile": "Модфайл",
"Modelfile Advanced Settings": "Разширени настройки на модфайл",
"Modelfile Content": "Съдържание на модфайл",
"Modelfiles": "Модфайлове",
"Models": "Модели",
"My Documents": "Мои документи",
"My Modelfiles": "Мои модфайлове",
"My Prompts": "Мои промптове",
"Name": "Име",
"Name Tag": "Име Таг",
"Name your modelfile": "Име на модфайла",
"New Chat": "Нов чат",
"New Password": "Нова парола",
"Not sure what to add?": "Не сте сигурни, какво да добавите?",
"Not sure what to write? Switch to": "Не сте сигурни, какво да напишете? Превключете към",
"Off": "Изкл.",
"Okay, Let's Go!": "ОК, Нека започваме!",
"Ollama Base URL": "Ollama Базов URL",
"Ollama Version": "Ollama Версия",
"On": "Вкл.",
"Only": "Само",
"Only alphanumeric characters and hyphens are allowed in the command string.": "Само алфанумерични знаци и тире са разрешени в командния низ.",
"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Упс! Задръжте! Файловете ви все още са в пещта за обработка. Готвим ги до съвършенство. Моля, бъдете търпеливи и ще ви уведомим, когато са готови.",
"Oops! Looks like the URL is invalid. Please double-check and try again.": "Упс! Изглежда URL адресът е невалиден. Моля, проверете отново и опитайте пак.",
"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Упс! Използвате неподдържан метод (само фронтенд). Моля, сервирайте WebUI от бекенда.",
"Open": "Отвори",
"Open AI": "Open AI",
"Open AI (Dall-E)": "Open AI (Dall-E)",
"Open new chat": "Отвори нов чат",
"OpenAI API": "OpenAI API",
"OpenAI API Key": "OpenAI API ключ",
"OpenAI API Key is required.": "OpenAI API ключ е задължителен.",
"or": "или",
"Parameters": "Параметри",
"Password": "Парола",
"PDF Extract Images (OCR)": "PDF Extract Images (OCR)",
"pending": "в очакване",
"Permission denied when accessing microphone: {{error}}": "Permission denied when accessing microphone: {{error}}",
"Playground": "Плейграунд",
"Profile": "Профил",
"Prompt Content": "Съдържание на промпта",
"Prompt suggestions": "Промпт предложения",
"Prompts": "Промптове",
"Pull a model from Ollama.com": "Издърпайте модел от Ollama.com",
"Pull Progress": "Прогрес на издърпването",
"Query Params": "Query Параметри",
"RAG Template": "RAG Шаблон",
"Raw Format": "Raw Формат",
"Record voice": "Записване на глас",
"Redirecting you to OpenWebUI Community": "Пренасочване към OpenWebUI общността",
"Release Notes": "Бележки по изданието",
"Repeat Last N": "Repeat Last N",
"Repeat Penalty": "Repeat Penalty",
"Request Mode": "Request Mode",
"Reset Vector Storage": "Ресет Vector Storage",
"Response AutoCopy to Clipboard": "Аувтоматично копиране на отговор в клипборда",
"Role": "Роля",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"Save": "Запис",
"Save & Create": "Запис & Създаване",
"Save & Submit": "Запис & Изпращане",
"Save & Update": "Запис & Актуализиране",
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Запазването на чат логове директно в хранилището на вашия браузър вече не се поддържа. Моля, отделете малко време, за да изтеглите и изтриете чат логовете си, като щракнете върху бутона по-долу. Не се притеснявайте, можете лесно да импортирате отново чат логовете си в бекенда чрез",
"Scan": "Сканиране",
"Scan complete!": "Сканиране завършено!",
"Scan for documents from {{path}}": "Сканиране за документи в {{path}}",
"Search": "Търси",
"Search Documents": "Търси Документи",
"Search Prompts": "Търси Промптове",
"See readme.md for instructions": "Виж readme.md за инструкции",
"See what's new": "Виж какво е новото",
"Seed": "Seed",
"Select a mode": "Изберете режим",
"Select a model": "Изберете модел",
"Select an Ollama instance": "Изберете Ollama инстанция",
"Send a Message": "Изпращане на Съобщение",
"Send message": "Изпращане на съобщение",
"Server connection verified": "Server connection verified",
"Set as default": "Задай като по подразбиране",
"Set Default Model": "Задай Модел По Подразбиране",
"Set Image Size": "Задай Размер на Изображението",
"Set Steps": "Задай Стъпки",
"Set Title Auto-Generation Model": "Задай Модел за Автоматично Генериране на Заглавие",
"Set Voice": "Задай Глас",
"Settings": "Настройки",
"Settings saved successfully!": "Настройките са запазени успешно!",
"Share to OpenWebUI Community": "Споделите с OpenWebUI Общността",
"short-summary": "short-summary",
"Show": "Покажи",
"Show Additional Params": "Покажи допълнителни параметри",
"Show shortcuts": "Покажи",
"sidebar": "sidebar",
"Sign in": "Вписване",
"Sign Out": "Изход",
"Sign up": "Регистрация",
"Speech recognition error: {{error}}": "Speech recognition error: {{error}}",
"Speech-to-Text Engine": "Speech-to-Text Engine",
"SpeechRecognition API is not supported in this browser.": "SpeechRecognition API is not supported in this browser.",
"Stop Sequence": "Stop Sequence",
"STT Settings": "STT Настройки",
"Submit": "Изпращане",
"Success": "Успех",
"Successfully updated.": "Успешно обновено.",
"Sync All": "Синхронизиране на всички",
"System": "Система",
"System Prompt": "Системен Промпт",
"Tags": "Тагове",
"Temperature": "Температура",
"Template": "Шаблон",
"Text Completion": "Text Completion",
"Text-to-Speech Engine": "Text-to-Speech Engine",
"Tfs Z": "Tfs Z",
"Theme": "Тема",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Това гарантира, че ценните ви разговори се запазват сигурно във вашата бекенд база данни. Благодарим ви!",
"This setting does not sync across browsers or devices.": "Тази настройка не се синхронизира между браузъри или устройства.",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Съвет: Актуализирайте няколко слота за променливи последователно, като натискате клавиша Tab в чат входа след всяка подмяна.",
"Title": "Заглавие",
"Title Auto-Generation": "Автоматично Генериране на Заглавие",
"Title Generation Prompt": "Промпт за Генериране на Заглавие",
"to": "до",
"To access the available model names for downloading,": "За да получите достъп до наличните имена на модели за изтегляне,",
"To access the GGUF models available for downloading,": "За да получите достъп до GGUF моделите, налични за изтегляне,",
"to chat input.": "към чат входа.",
"Toggle settings": "Toggle settings",
"Toggle sidebar": "Toggle sidebar",
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Проблеми с достъпът до Ollama?",
"TTS Settings": "TTS Настройки",
"Type Hugging Face Resolve (Download) URL": "Въведете Hugging Face Resolve (Download) URL",
"Uh-oh! There was an issue connecting to {{provider}}.": "О, не! Възникна проблем при свързването с {{provider}}.",
"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Непознат файлов тип '{{file_type}}', но се приема и обработва като текст",
"Update password": "Обновяване на парола",
"Upload a GGUF model": "Качване на GGUF модел",
"Upload files": "Качване на файлове",
"Upload Progress": "Прогрес на качването",
"URL Mode": "URL Mode",
"Use '#' in the prompt input to load and select your documents.": "Използвайте '#' във промпта за да заредите и изберете вашите документи.",
"Use Gravatar": "Използвайте Gravatar",
"user": "потребител",
"User Permissions": "Права на потребителя",
"Users": "Потребители",
"Utilize": "Използване",
"Valid time units:": "Валидни единици за време:",
"variable": "променлива",
"variable to have them replaced with clipboard content.": "променливи да се заменят съдържанието от клипборд.",
"Version": "Версия",
"Web": "Уеб",
"WebUI Add-ons": "WebUI Добавки",
"WebUI Settings": "WebUI Настройки",
"WebUI will make requests to": "WebUI ще направи заявки към",
"What’s New in": "Какво е новото в",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Когато историята е изключена, нови чатове в този браузър ще не се показват в историята на никои от вашия профил.",
"Whisper (Local)": "Whisper (Локален)",
"Write a prompt suggestion (e.g. Who are you?)": "Напиши предложение за промпт (напр. Кой сте вие?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Напиши описание в 50 знака, което описва [тема или ключова дума].",
"You": "Вие",
"You're a helpful assistant.": "Вие сте полезен асистент.",
"You're now logged in.": "Сега, вие влязохте в системата."
}
+363
View File
@@ -0,0 +1,363 @@
{
"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' or '-1' per no caduca mai.",
"(Beta)": "(Beta)",
"(e.g. `sh webui.sh --api`)": "(p. ex. `sh webui.sh --api`)",
"(latest)": "(últim)",
"{{modelName}} is thinking...": "{{modelName}} està pensant...",
"{{webUIName}} Backend Required": "Es requereix Backend de {{webUIName}}",
"a user": "un usuari",
"About": "Sobre",
"Account": "Compte",
"Action": "Acció",
"Add a model": "Afegeix un model",
"Add a model tag name": "Afegeix un nom d'etiqueta de model",
"Add a short description about what this modelfile does": "Afegeix una descripció curta del que fa aquest arxiu de model",
"Add a short title for this prompt": "Afegeix un títol curt per aquest prompt",
"Add a tag": "Afegeix una etiqueta",
"Add Docs": "Afegeix Documents",
"Add Files": "Afegeix Arxius",
"Add message": "Afegeix missatge",
"add tags": "afegeix etiquetes",
"Adjusting these settings will apply changes universally to all users.": "Ajustar aquests paràmetres aplicarà canvis de manera universal a tots els usuaris.",
"admin": "administrador",
"Admin Panel": "Panell d'Administració",
"Admin Settings": "Configuració d'Administració",
"Advanced Parameters": "Paràmetres Avançats",
"all": "tots",
"All Users": "Tots els Usuaris",
"Allow": "Permet",
"Allow Chat Deletion": "Permet la Supressió del Xat",
"alphanumeric characters and hyphens": "caràcters alfanumèrics i guions",
"Already have an account?": "Ja tens un compte?",
"an assistant": "un assistent",
"and": "i",
"API Base URL": "URL Base de l'API",
"API Key": "Clau de l'API",
"API RPM": "RPM de l'API",
"are allowed - Activate this command by typing": "estan permesos - Activa aquesta comanda escrivint",
"Are you sure?": "Estàs segur?",
"Audio": "Àudio",
"Auto-playback response": "Resposta de reproducció automàtica",
"Auto-send input after 3 sec.": "Enviar entrada automàticament després de 3 segons",
"AUTOMATIC1111 Base URL": "URL Base AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "Es requereix l'URL Base AUTOMATIC1111.",
"available!": "disponible!",
"Back": "Enrere",
"Builder Mode": "Mode Constructor",
"Cancel": "Cancel·la",
"Categories": "Categories",
"Change Password": "Canvia la Contrasenya",
"Chat": "Xat",
"Chat History": "Històric del Xat",
"Chat History is off for this browser.": "L'historial de xat està desactivat per a aquest navegador.",
"Chats": "Xats",
"Check Again": "Comprova-ho de Nou",
"Check for updates": "Comprova si hi ha actualitzacions",
"Checking for updates...": "Comprovant actualitzacions...",
"Choose a model before saving...": "Tria un model abans de guardar...",
"Chunk Overlap": "Solapament de Blocs",
"Chunk Params": "Paràmetres de Blocs",
"Chunk Size": "Mida del Bloc",
"Click here for help.": "Fes clic aquí per ajuda.",
"Click here to check other modelfiles.": "Fes clic aquí per comprovar altres fitxers de model.",
"Click here to select": "Fes clic aquí per seleccionar",
"Click here to select documents.": "Fes clic aquí per seleccionar documents.",
"click here.": "fes clic aquí.",
"Click on the user role button to change a user's role.": "Fes clic al botó de rol d'usuari per canviar el rol d'un usuari.",
"Close": "Tanca",
"Collection": "Col·lecció",
"Command": "Comanda",
"Confirm Password": "Confirma la Contrasenya",
"Connections": "Connexions",
"Content": "Contingut",
"Context Length": "Longitud del Context",
"Conversation Mode": "Mode de Conversa",
"Copy last code block": "Copia l'últim bloc de codi",
"Copy last response": "Copia l'última resposta",
"Copying to clipboard was successful!": "La còpia al porta-retalls ha estat exitosa!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Crea una frase concisa de 3-5 paraules com a capçalera per a la següent consulta, seguint estrictament el límit de 3-5 paraules i evitant l'ús de la paraula 'títol':",
"Create a modelfile": "Crea un fitxer de model",
"Create Account": "Crea un Compte",
"Created at": "Creat el",
"Created by": "Creat per",
"Current Model": "Model Actual",
"Current Password": "Contrasenya Actual",
"Custom": "Personalitzat",
"Customize Ollama models for a specific purpose": "Personalitza els models Ollama per a un propòsit específic",
"Dark": "Fosc",
"Database": "Base de Dades",
"DD/MM/YYYY HH:mm": "DD/MM/YYYY HH:mm",
"Default": "Per defecte",
"Default (Automatic1111)": "Per defecte (Automatic1111)",
"Default (Web API)": "Per defecte (Web API)",
"Default model updated": "Model per defecte actualitzat",
"Default Prompt Suggestions": "Suggeriments de Prompt Per Defecte",
"Default User Role": "Rol d'Usuari Per Defecte",
"delete": "esborra",
"Delete a model": "Esborra un model",
"Delete chat": "Esborra xat",
"Delete Chats": "Esborra Xats",
"Deleted {{deleteModelTag}}": "Esborrat {{deleteModelTag}}",
"Deleted {tagName}": "Esborrat {tagName}",
"Description": "Descripció",
"Desktop Notifications": "Notificacions d'Escriptori",
"Disabled": "Desactivat",
"Discover a modelfile": "Descobreix un fitxer de model",
"Discover a prompt": "Descobreix un prompt",
"Discover, download, and explore custom prompts": "Descobreix, descarrega i explora prompts personalitzats",
"Discover, download, and explore model presets": "Descobreix, descarrega i explora presets de models",
"Display the username instead of You in the Chat": "Mostra el nom d'usuari en lloc de 'Tu' al Xat",
"Document": "Document",
"Document Settings": "Configuració de Documents",
"Documents": "Documents",
"does not make any external connections, and your data stays securely on your locally hosted server.": "no realitza connexions externes, i les teves dades romanen segures al teu servidor allotjat localment.",
"Don't Allow": "No Permetre",
"Don't have an account?": "No tens un compte?",
"Download as a File": "Descarrega com a Arxiu",
"Download Database": "Descarrega Base de Dades",
"Drop any files here to add to the conversation": "Deixa qualsevol arxiu aquí per afegir-lo a la conversa",
"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "p. ex. '30s','10m'. Les unitats de temps vàlides són 's', 'm', 'h'.",
"Edit Doc": "Edita Document",
"Edit User": "Edita Usuari",
"Email": "Correu electrònic",
"Enable Chat History": "Activa Historial de Xat",
"Enable New Sign Ups": "Permet Noves Inscripcions",
"Enabled": "Activat",
"Enter {{role}} message here": "Introdueix aquí el missatge de {{role}}",
"Enter API Key": "Introdueix la Clau API",
"Enter Chunk Overlap": "Introdueix el Solapament de Blocs",
"Enter Chunk Size": "Introdueix la Mida del Bloc",
"Enter Image Size (e.g. 512x512)": "Introdueix la Mida de la Imatge (p. ex. 512x512)",
"Enter LiteLLM API Base URL (litellm_params.api_base)": "Introdueix l'URL Base de LiteLLM API (litellm_params.api_base)",
"Enter LiteLLM API Key (litellm_params.api_key)": "Introdueix la Clau de LiteLLM API (litellm_params.api_key)",
"Enter LiteLLM API RPM (litellm_params.rpm)": "Introdueix RPM de LiteLLM API (litellm_params.rpm)",
"Enter LiteLLM Model (litellm_params.model)": "Introdueix el Model de LiteLLM (litellm_params.model)",
"Enter Max Tokens (litellm_params.max_tokens)": "Introdueix el Màxim de Tokens (litellm_params.max_tokens)",
"Enter model tag (e.g. {{modelTag}})": "Introdueix l'etiqueta del model (p. ex. {{modelTag}})",
"Enter Number of Steps (e.g. 50)": "Introdueix el Nombre de Passos (p. ex. 50)",
"Enter stop sequence": "Introdueix la seqüència de parada",
"Enter Top K": "Introdueix Top K",
"Enter URL (e.g. http://127.0.0.1:7860/)": "Introdueix l'URL (p. ex. http://127.0.0.1:7860/)",
"Enter Your Email": "Introdueix el Teu Correu Electrònic",
"Enter Your Full Name": "Introdueix el Teu Nom Complet",
"Enter Your Password": "Introdueix la Teva Contrasenya",
"Experimental": "Experimental",
"Export All Chats (All Users)": "Exporta Tots els Xats (Tots els Usuaris)",
"Export Chats": "Exporta Xats",
"Export Documents Mapping": "Exporta el Mapatge de Documents",
"Export Modelfiles": "Exporta Fitxers de Model",
"Export Prompts": "Exporta Prompts",
"Failed to read clipboard contents": "No s'ha pogut llegir el contingut del porta-retalls",
"File Mode": "Mode Arxiu",
"File not found.": "Arxiu no trobat.",
"Focus chat input": "Enfoca l'entrada del xat",
"Format your variables using square brackets like this:": "Formata les teves variables utilitzant claudàtors així:",
"From (Base Model)": "Des de (Model Base)",
"Full Screen Mode": "Mode de Pantalla Completa",
"General": "General",
"General Settings": "Configuració General",
"Hello, {{name}}": "Hola, {{name}}",
"Hide": "Amaga",
"Hide Additional Params": "Amaga Paràmetres Addicionals",
"How can I help you today?": "Com et puc ajudar avui?",
"Image Generation (Experimental)": "Generació d'Imatges (Experimental)",
"Image Generation Engine": "Motor de Generació d'Imatges",
"Image Settings": "Configuració d'Imatges",
"Images": "Imatges",
"Import Chats": "Importa Xats",
"Import Documents Mapping": "Importa el Mapa de Documents",
"Import Modelfiles": "Importa Fitxers de Model",
"Import Prompts": "Importa Prompts",
"Include `--api` flag when running stable-diffusion-webui": "Inclou la bandera `--api` quan executis stable-diffusion-webui",
"Interface": "Interfície",
"join our Discord for help.": "uneix-te al nostre Discord per ajuda.",
"JSON": "JSON",
"JWT Expiration": "Expiració de JWT",
"JWT Token": "Token JWT",
"Keep Alive": "Mantén Actiu",
"Keyboard shortcuts": "Dreceres de Teclat",
"Language": "Idioma",
"Light": "Clar",
"Listening...": "Escoltant...",
"LLMs can make mistakes. Verify important information.": "Els LLMs poden cometre errors. Verifica la informació important.",
"Made by OpenWebUI Community": "Creat per la Comunitat OpenWebUI",
"Make sure to enclose them with": "Assegura't d'envoltar-los amb",
"Manage LiteLLM Models": "Gestiona Models LiteLLM",
"Manage Models": "Gestiona Models",
"Manage Ollama Models": "Gestiona Models Ollama",
"Max Tokens": "Màxim de Tokens",
"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Es poden descarregar un màxim de 3 models simultàniament. Si us plau, prova-ho més tard.",
"Mirostat": "Mirostat",
"Mirostat Eta": "Eta de Mirostat",
"Mirostat Tau": "Tau de Mirostat",
"MMMM DD, YYYY": "DD de MMMM, YYYY",
"Model '{{modelName}}' has been successfully downloaded.": "El model '{{modelName}}' s'ha descarregat amb èxit.",
"Model '{{modelTag}}' is already in queue for downloading.": "El model '{{modelTag}}' ja està en cua per ser descarregat.",
"Model {{modelId}} not found": "Model {{modelId}} no trobat",
"Model {{modelName}} already exists.": "El model {{modelName}} ja existeix.",
"Model Name": "Nom del Model",
"Model not selected": "Model no seleccionat",
"Model Tag Name": "Nom de l'Etiqueta del Model",
"Model Whitelisting": "Llista Blanca de Models",
"Model(s) Whitelisted": "Model(s) a la Llista Blanca",
"Modelfile": "Fitxer de Model",
"Modelfile Advanced Settings": "Configuració Avançada de Fitxers de Model",
"Modelfile Content": "Contingut del Fitxer de Model",
"Modelfiles": "Fitxers de Model",
"Models": "Models",
"My Documents": "Els Meus Documents",
"My Modelfiles": "Els Meus Fitxers de Model",
"My Prompts": "Els Meus Prompts",
"Name": "Nom",
"Name Tag": "Etiqueta de Nom",
"Name your modelfile": "Nomena el teu fitxer de model",
"New Chat": "Xat Nou",
"New Password": "Nova Contrasenya",
"Not sure what to add?": "No estàs segur del que afegir?",
"Not sure what to write? Switch to": "No estàs segur del que escriure? Canvia a",
"Off": "Desactivat",
"Okay, Let's Go!": "D'acord, Anem!",
"Ollama Base URL": "URL Base d'Ollama",
"Ollama Version": "Versió d'Ollama",
"On": "Activat",
"Only": "Només",
"Only alphanumeric characters and hyphens are allowed in the command string.": "Només es permeten caràcters alfanumèrics i guions en la cadena de comandes.",
"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Ui! Aguanta! Els teus fitxers encara estan en el forn de processament. Els estem cuinant a la perfecció. Si us plau, tingues paciència i t'avisarem quan estiguin llestos.",
"Oops! Looks like the URL is invalid. Please double-check and try again.": "Ui! Sembla que l'URL és invàlida. Si us plau, revisa-ho i prova de nou.",
"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Ui! Estàs utilitzant un mètode no suportat (només frontend). Si us plau, serveix la WebUI des del backend.",
"Open": "Obre",
"Open AI": "Open AI",
"Open AI (Dall-E)": "Open AI (Dall-E)",
"Open new chat": "Obre un nou xat",
"OpenAI API": "API d'OpenAI",
"OpenAI API Key": "Clau API d'OpenAI",
"OpenAI API Key is required.": "Es requereix la Clau API d'OpenAI.",
"or": "o",
"Parameters": "Paràmetres",
"Password": "Contrasenya",
"PDF Extract Images (OCR)": "Extreu Imatges de PDF (OCR)",
"pending": "pendent",
"Permission denied when accessing microphone: {{error}}": "Permís denegat en accedir al micròfon: {{error}}",
"Playground": "Zona de Jocs",
"Profile": "Perfil",
"Prompt Content": "Contingut del Prompt",
"Prompt suggestions": "Suggeriments de Prompt",
"Prompts": "Prompts",
"Pull a model from Ollama.com": "Treu un model d'Ollama.com",
"Pull Progress": "Progrés de Tracció",
"Query Params": "Paràmetres de Consulta",
"RAG Template": "Plantilla RAG",
"Raw Format": "Format Brut",
"Record voice": "Enregistra veu",
"Redirecting you to OpenWebUI Community": "Redirigint-te a la Comunitat OpenWebUI",
"Release Notes": "Notes de la Versió",
"Repeat Last N": "Repeteix Últim N",
"Repeat Penalty": "Penalització de Repetició",
"Request Mode": "Mode de Sol·licitud",
"Reset Vector Storage": "Reinicia l'Emmagatzematge de Vectors",
"Response AutoCopy to Clipboard": "Resposta AutoCopiar al Portapapers",
"Role": "Rol",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Albada Rosé Pine",
"Save": "Guarda",
"Save & Create": "Guarda i Crea",
"Save & Submit": "Guarda i Envia",
"Save & Update": "Guarda i Actualitza",
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Guardar registres de xat directament a l'emmagatzematge del teu navegador ja no és suportat. Si us plau, pren un moment per descarregar i eliminar els teus registres de xat fent clic al botó de sota. No et preocupis, pots reimportar fàcilment els teus registres de xat al backend a través de",
"Scan": "Escaneja",
"Scan complete!": "Escaneig completat!",
"Scan for documents from {{path}}": "Escaneja documents des de {{path}}",
"Search": "Cerca",
"Search Documents": "Cerca Documents",
"Search Prompts": "Cerca Prompts",
"See readme.md for instructions": "Consulta el readme.md per a instruccions",
"See what's new": "Veure novetats",
"Seed": "Llavor",
"Select a mode": "Selecciona un mode",
"Select a model": "Selecciona un model",
"Select an Ollama instance": "Selecciona una instància d'Ollama",
"Send a Message": "Envia un Missatge",
"Send message": "Envia missatge",
"Server connection verified": "Connexió al servidor verificada",
"Set as default": "Estableix com a predeterminat",
"Set Default Model": "Estableix Model Predeterminat",
"Set Image Size": "Estableix Mida de la Imatge",
"Set Steps": "Estableix Passos",
"Set Title Auto-Generation Model": "Estableix Model d'Auto-Generació de Títol",
"Set Voice": "Estableix Veu",
"Settings": "Configuracions",
"Settings saved successfully!": "Configuracions guardades amb èxit!",
"Share to OpenWebUI Community": "Comparteix amb la Comunitat OpenWebUI",
"short-summary": "resum curt",
"Show": "Mostra",
"Show Additional Params": "Mostra Paràmetres Addicionals",
"Show shortcuts": "Mostra dreceres",
"sidebar": "barra lateral",
"Sign in": "Inicia sessió",
"Sign Out": "Tanca sessió",
"Sign up": "Registra't",
"Speech recognition error: {{error}}": "Error de reconeixement de veu: {{error}}",
"Speech-to-Text Engine": "Motor de Veu a Text",
"SpeechRecognition API is not supported in this browser.": "L'API de Reconèixer Veu no és compatible amb aquest navegador.",
"Stop Sequence": "Atura Seqüència",
"STT Settings": "Configuracions STT",
"Submit": "Envia",
"Success": "Èxit",
"Successfully updated.": "Actualitzat amb èxit.",
"Sync All": "Sincronitza Tot",
"System": "Sistema",
"System Prompt": "Prompt del Sistema",
"Tags": "Etiquetes",
"Temperature": "Temperatura",
"Template": "Plantilla",
"Text Completion": "Completació de Text",
"Text-to-Speech Engine": "Motor de Text a Veu",
"Tfs Z": "Tfs Z",
"Theme": "Tema",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Això assegura que les teves converses valuoses queden segurament guardades a la teva base de dades backend. Gràcies!",
"This setting does not sync across browsers or devices.": "Aquesta configuració no es sincronitza entre navegadors ni dispositius.",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Consell: Actualitza diversos espais de variables consecutivament prement la tecla de tabulació en l'entrada del xat després de cada reemplaçament.",
"Title": "Títol",
"Title Auto-Generation": "Auto-Generació de Títol",
"Title Generation Prompt": "Prompt de Generació de Títol",
"to": "a",
"To access the available model names for downloading,": "Per accedir als noms dels models disponibles per descarregar,",
"To access the GGUF models available for downloading,": "Per accedir als models GGUF disponibles per descarregar,",
"to chat input.": "a l'entrada del xat.",
"Toggle settings": "Commuta configuracions",
"Toggle sidebar": "Commuta barra lateral",
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Problemes accedint a Ollama?",
"TTS Settings": "Configuracions TTS",
"Type Hugging Face Resolve (Download) URL": "Escriu URL de Resolució (Descàrrega) de Hugging Face",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uf! Hi va haver un problema connectant-se a {{provider}}.",
"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Tipus d'Arxiu Desconegut '{{file_type}}', però acceptant i tractant com a text pla",
"Update password": "Actualitza contrasenya",
"Upload a GGUF model": "Puja un model GGUF",
"Upload files": "Puja arxius",
"Upload Progress": "Progrés de Càrrega",
"URL Mode": "Mode URL",
"Use '#' in the prompt input to load and select your documents.": "Utilitza '#' a l'entrada del prompt per carregar i seleccionar els teus documents.",
"Use Gravatar": "Utilitza Gravatar",
"user": "usuari",
"User Permissions": "Permisos d'Usuari",
"Users": "Usuaris",
"Utilize": "Utilitza",
"Valid time units:": "Unitats de temps vàlides:",
"variable": "variable",
"variable to have them replaced with clipboard content.": "variable per tenir-les reemplaçades amb el contingut del porta-retalls.",
"Version": "Versió",
"Web": "Web",
"WebUI Add-ons": "Complements de WebUI",
"WebUI Settings": "Configuració de WebUI",
"WebUI will make requests to": "WebUI farà peticions a",
"What’s New in": "Què hi ha de Nou en",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Quan l'historial està desactivat, els nous xats en aquest navegador no apareixeran en el teu historial en cap dels teus dispositius.",
"Whisper (Local)": "Whisper (Local)",
"Write a prompt suggestion (e.g. Who are you?)": "Escriu una suggerència de prompt (p. ex. Qui ets tu?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Escriu un resum en 50 paraules que resumeixi [tema o paraula clau].",
"You": "Tu",
"You're a helpful assistant.": "Ets un assistent útil.",
"You're now logged in.": "Ara estàs connectat."
}
+363
View File
@@ -0,0 +1,363 @@
{
"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' oder '-1' für kein Ablaufdatum.",
"(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": "",
"About": "Über",
"Account": "Account",
"Action": "Aktion",
"Add a model": "Füge ein Modell hinzu",
"Add a model tag name": "Benenne dein Modell-Tag",
"Add a short description about what this modelfile does": "Füge eine kurze Beschreibung hinzu, was dieses Modelfile kann",
"Add a short title for this prompt": "Füge einen kurzen Titel für diesen Prompt hinzu",
"Add a tag": "Tag hinzugügen",
"Add Docs": "Dokumente hinzufügen",
"Add Files": "Dateien hinzufügen",
"Add message": "Nachricht eingeben",
"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",
"Admin Panel": "Admin Panel",
"Admin Settings": "Admin Einstellungen",
"Advanced Parameters": "Erweiterte Parameter",
"all": "Alle",
"All Users": "Alle Benutzer",
"Allow": "Erlauben",
"Allow Chat Deletion": "Chat Löschung erlauben",
"alphanumeric characters and hyphens": "alphanumerische Zeichen und Bindestriche",
"Already have an account?": "Hast du vielleicht schon ein Account?",
"an assistant": "",
"and": "und",
"API Base URL": "API Basis URL",
"API Key": "API Key",
"API RPM": "API RPM",
"are allowed - Activate this command by typing": "sind erlaubt - Aktiviere diesen Befehl, indem du",
"Are you sure?": "",
"Audio": "Audio",
"Auto-playback response": "Automatische Wiedergabe der Antwort",
"Auto-send input after 3 sec.": "Automatisches Senden der Eingabe nach 3 Sek",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 Basis URL",
"AUTOMATIC1111 Base URL is required.": "",
"available!": "verfügbar!",
"Back": "Zurück",
"Builder Mode": "Builder Modus",
"Cancel": "Abbrechen",
"Categories": "Kategorien",
"Change Password": "Passwort ändern",
"Chat": "Chat",
"Chat History": "Chat Verlauf",
"Chat History is off for this browser.": "Chat Verlauf ist für diesen Browser ausgeschaltet.",
"Chats": "Chats",
"Check Again": "Erneut überprüfen",
"Check for updates": "Nach Updates suchen",
"Checking for updates...": "Nach Updates suchen...",
"Choose a model before saving...": "Wähle bitte zuerst ein Modell, bevor du speicherst...",
"Chunk Overlap": "Chunk Overlap",
"Chunk Params": "Chunk Parameter",
"Chunk Size": "Chunk Size",
"Click here for help.": "Klicke hier für Hilfe.",
"Click here to check other modelfiles.": "Klicke hier, um andere Modelfiles zu überprüfen.",
"Click here to select": "",
"Click here to select documents.": "",
"click here.": "hier klicken.",
"Click on the user role button to change a user's role.": "Klicke auf die Benutzerrollenschaltfläche, um die Rolle eines Benutzers zu ändern.",
"Close": "Schließe",
"Collection": "Kollektion",
"Command": "Befehl",
"Confirm Password": "Passwort bestätigen",
"Connections": "Verbindungen",
"Content": "Inhalt",
"Context Length": "Context Length",
"Conversation Mode": "Konversationsmodus",
"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!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Erstelle einen prägnanten Satz mit 3-5 Wörtern als Überschrift für die folgende Abfrage. Halte dich dabei strikt an die 3-5-Wort-Grenze und vermeide die Verwendung des Wortes Titel:",
"Create a modelfile": "Modelfiles erstellen",
"Create Account": "Konto erstellen",
"Created at": "Erstellt am",
"Created by": "Erstellt von",
"Current Model": "Aktuelles Modell",
"Current Password": "Aktuelles Passwort",
"Custom": "Benutzerdefiniert",
"Customize Ollama models for a specific purpose": "Ollama-Modelle für einen bestimmten Zweck anpassen",
"Dark": "Dunkel",
"Database": "Datenbank",
"DD/MM/YYYY HH:mm": "DD.MM.YYYY HH:mm",
"Default": "Standard",
"Default (Automatic1111)": "",
"Default (Web API)": "Standard (Web-API)",
"Default model updated": "Standardmodell aktualisiert",
"Default Prompt Suggestions": "Standard-Prompt-Vorschläge",
"Default User Role": "Standardbenutzerrolle",
"delete": "löschen",
"Delete a model": "Ein Modell löschen",
"Delete chat": "Chat löschen",
"Delete Chats": "Chats löschen",
"Deleted {{deleteModelTag}}": "{{deleteModelTag}} gelöscht",
"Deleted {tagName}": "{tagName} gelöscht",
"Description": "Beschreibung",
"Desktop Notifications": "Desktop-Benachrichtigungen",
"Disabled": "Deaktiviert",
"Discover a modelfile": "Eine Modelfiles entdecken",
"Discover a prompt": "Einen Prompt entdecken",
"Discover, download, and explore custom prompts": "Benutzerdefinierte Prompts entdecken, herunterladen und erkunden",
"Discover, download, and explore model presets": "Modellvorgaben entdecken, herunterladen und erkunden",
"Display the username instead of You in the Chat": "Den Benutzernamen anstelle von 'Du' im Chat anzeigen",
"Document": "Dokument",
"Document Settings": "Dokumenteinstellungen",
"Documents": "Dokumente",
"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 Account?",
"Download as a File": "Als Datei herunterladen",
"Download Database": "Datenbank herunterladen",
"Drop any files here to add to the conversation": "Lasse Dateien hier fallen, um sie dem 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 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": "",
"Enter API Key": "",
"Enter Chunk Overlap": "",
"Enter Chunk Size": "",
"Enter Image Size (e.g. 512x512)": "",
"Enter LiteLLM API Base URL (litellm_params.api_base)": "",
"Enter LiteLLM API Key (litellm_params.api_key)": "",
"Enter LiteLLM API RPM (litellm_params.rpm)": "",
"Enter LiteLLM Model (litellm_params.model)": "",
"Enter Max Tokens (litellm_params.max_tokens)": "",
"Enter model tag (e.g. {{modelTag}})": "",
"Enter Number of Steps (e.g. 50)": "",
"Enter stop sequence": "Stop-Sequenz eingeben",
"Enter Top K": "",
"Enter URL (e.g. http://127.0.0.1:7860/)": "",
"Enter Your Email": "Geben Deine E-Mail-Adresse ein",
"Enter Your Full Name": "Gebe Deinen vollständigen Namen ein",
"Enter Your Password": "Gebe Dein Passwort ein",
"Experimental": "Experimentell",
"Export All Chats (All Users)": "Alle Chats exportieren (alle Benutzer)",
"Export Chats": "Chats exportieren",
"Export Documents Mapping": "Dokumentenmapping exportieren",
"Export Modelfiles": "Modelfiles exportieren",
"Export Prompts": "Prompts exportieren",
"Failed to read clipboard contents": "Fehler beim Lesen des Zwischenablageninhalts",
"File Mode": "File Mode",
"File not found.": "Datei nicht gefunden.",
"Focus chat input": "Chat-Eingabe fokussieren",
"Format your variables using square brackets like this:": "Formatiere Deine Variablen mit eckigen Klammern wie folgt:",
"From (Base Model)": "Von (Basismodell)",
"Full Screen Mode": "Vollbildmodus",
"General": "Allgemein",
"General Settings": "Allgemeine Einstellungen",
"Hello, {{name}}": "Hallo, {{name}}",
"Hide": "Verbergen",
"Hide Additional Params": "Hide Additional Params",
"How can I help you today?": "Wie kann ich Dir heute helfen?",
"Image Generation (Experimental)": "Bildgenerierung (experimentell)",
"Image Generation Engine": "",
"Image Settings": "Bildeinstellungen",
"Images": "Bilder",
"Import Chats": "Chats importieren",
"Import Documents Mapping": "Dokumentenmapping importieren",
"Import Modelfiles": "Modelfiles importieren",
"Import Prompts": "Prompts importieren",
"Include `--api` flag when running stable-diffusion-webui": "Füge das `--api`-Flag hinzu, wenn Du stable-diffusion-webui nutzt",
"Interface": "Benutzeroberfläche",
"join our Discord for help.": "Trete unserem Discord bei, um Hilfe zu erhalten.",
"JSON": "JSON",
"JWT Expiration": "JWT-Ablauf",
"JWT Token": "JWT-Token",
"Keep Alive": "Keep Alive",
"Keyboard shortcuts": "Tastenkürzel",
"Language": "Sprache",
"Light": "Hell",
"Listening...": "Hören...",
"LLMs can make mistakes. Verify important information.": "LLMs können Fehler machen. Überprüfe wichtige Informationen.",
"Made by OpenWebUI Community": "Von der OpenWebUI-Community",
"Make sure to enclose them with": "Formatiere Deine Variablen mit:",
"Manage LiteLLM Models": "LiteLLM-Modelle verwalten",
"Manage Models": "Modelle verwalten",
"Manage Ollama Models": "Ollama-Modelle verwalten",
"Max Tokens": "Maximale Tokens",
"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Es können maximal 3 Modelle gleichzeitig heruntergeladen werden. Bitte versuche es später erneut.",
"Mirostat": "Mirostat",
"Mirostat Eta": "Mirostat Eta",
"Mirostat Tau": "Mirostat Tau",
"MMMM DD, YYYY": "DD.MM.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(s) Whitelisted": "Modell(e) auf der Whitelist",
"Modelfile": "Modelfiles",
"Modelfile Advanced Settings": "Erweiterte Modelfileseinstellungen",
"Modelfile Content": "Modelfile Content",
"Modelfiles": "Modelfiles",
"Models": "Modelle",
"My Documents": "Meine Dokumente",
"My Modelfiles": "Meine Modelfiles",
"My Prompts": "Meine Prompts",
"Name": "Name",
"Name Tag": "Namens-Tag",
"Name your modelfile": "Name your modelfile",
"New Chat": "Neuer Chat",
"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",
"Off": "Aus",
"Okay, Let's Go!": "Okay, los geht's!",
"Ollama Base URL": "",
"Ollama Version": "Ollama-Version",
"On": "Ein",
"Only": "Nur",
"Only alphanumeric characters and hyphens are allowed in the command string.": "Nur alphanumerische Zeichen und Bindestriche sind im Befehlsstring erlaubt.",
"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Hoppla! Warte noch einen Moment! Die Dateien sind noch im der Verarbeitung. Bitte habe etwas Geduld und wir informieren Dich, sobald sie bereit sind.",
"Oops! Looks like the URL is invalid. Please double-check and try again.": "Oops! Looks like the URL is invalid. Please double-check and try again.",
"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.",
"Open": "Öffne",
"Open AI": "Open AI",
"Open AI (Dall-E)": "",
"Open new chat": "Neuen Chat öffnen",
"OpenAI API": "OpenAI-API",
"OpenAI API Key": "",
"OpenAI API Key is required.": "",
"or": "oder",
"Parameters": "Parameter",
"Password": "Passwort",
"PDF Extract Images (OCR)": "Text von Bilder aus PDFs extrahieren (OCR)",
"pending": "ausstehend",
"Permission denied when accessing microphone: {{error}}": "Zugriff auf das Mikrofon verweigert: {{error}}",
"Playground": "Playground",
"Profile": "Profil",
"Prompt Content": "Prompt-Inhalt",
"Prompt suggestions": "Prompt-Vorschläge",
"Prompts": "Prompts",
"Pull a model from Ollama.com": "Ein Modell von Ollama.com abrufen",
"Pull Progress": "Fortschritt abrufen",
"Query Params": "Query Parameter",
"RAG Template": "RAG-Vorlage",
"Raw Format": "Rohformat",
"Record voice": "Stimme aufnehmen",
"Redirecting you to OpenWebUI Community": "Du wirst zur OpenWebUI-Community weitergeleitet",
"Release Notes": "Versionshinweise",
"Repeat Last N": "Repeat Last N",
"Repeat Penalty": "Repeat Penalty",
"Request Mode": "Request-Modus",
"Reset Vector Storage": "Vektorspeicher zurücksetzen",
"Response AutoCopy to Clipboard": "Antwort automatisch in die Zwischenablage kopieren",
"Role": "Rolle",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"Save": "Speichern",
"Save & Create": "Speichern und erstellen",
"Save & Submit": "Speichern und senden",
"Save & Update": "Speichern und aktualisieren",
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Das direkte Speichern von Chat-Protokollen im Browser-Speicher wird nicht mehr unterstützt. Bitte nehme Dir einen Moment Zeit, um Deine Chat-Protokolle herunterzuladen und zu löschen, indem Du auf die Schaltfläche unten klickst. Keine Sorge, Du kannst Deine Chat-Protokolle problemlos über das Backend wieder importieren.",
"Scan": "Scannen",
"Scan complete!": "Scan abgeschlossen!",
"Scan for documents from {{path}}": "Dokumente von {{path}} scannen",
"Search": "Suchen",
"Search Documents": "Dokumente suchen",
"Search Prompts": "Prompts suchen",
"See readme.md for instructions": "Anleitung in readme.md anzeigen",
"See what's new": "Was gibt's Neues",
"Seed": "Seed",
"Select a mode": "",
"Select a model": "Ein Modell auswählen",
"Select an Ollama instance": "",
"Send a Message": "Eine Nachricht senden",
"Send message": "Nachricht senden",
"Server connection verified": "Serververbindung überprüft",
"Set as default": "Als Standard festlegen",
"Set Default Model": "Standardmodell festlegen",
"Set Image Size": "Bildgröße festlegen",
"Set Steps": "Schritte festlegen",
"Set Title Auto-Generation Model": "Modell für automatische Titelgenerierung festlegen",
"Set Voice": "Stimme festlegen",
"Settings": "Einstellungen",
"Settings saved successfully!": "Einstellungen erfolgreich gespeichert!",
"Share to OpenWebUI Community": "Mit OpenWebUI Community teilen",
"short-summary": "kurze-zusammenfassung",
"Show": "Anzeigen",
"Show Additional Params": "Show Additional Params",
"Show shortcuts": "Verknüpfungen anzeigen",
"sidebar": "Seitenleiste",
"Sign in": "Anmelden",
"Sign Out": "Abmelden",
"Sign up": "Registrieren",
"Speech recognition error: {{error}}": "Spracherkennungsfehler: {{error}}",
"Speech-to-Text Engine": "Sprache-zu-Text-Engine",
"SpeechRecognition API is not supported in this browser.": "Die SpeechRecognition-API wird in diesem Browser nicht unterstützt.",
"Stop Sequence": "Stop Sequence",
"STT Settings": "STT-Einstellungen",
"Submit": "Senden",
"Success": "Erfolg",
"Successfully updated.": "Erfolgreich aktualisiert.",
"Sync All": "Alles synchronisieren",
"System": "System",
"System Prompt": "System-Prompt",
"Tags": "Tags",
"Temperature": "Temperatur",
"Template": "Vorlage",
"Text Completion": "Textvervollständigung",
"Text-to-Speech Engine": "Text-zu-Sprache-Engine",
"Tfs Z": "Tfs Z",
"Theme": "Design",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Dadurch werden Deine wertvollen Unterhaltungen sicher in der Backend-Datenbank gespeichert. Vielen Dank!",
"This setting does not sync across browsers or devices.": "Diese Einstellung wird nicht zwischen Browsern oder Geräten synchronisiert.",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.",
"Title": "Titel",
"Title Auto-Generation": "Automatische Titelgenerierung",
"Title Generation Prompt": "Prompt für Titelgenerierung",
"to": "für",
"To access the available model names for downloading,": "Um auf die verfügbaren Modellnamen zum Herunterladen zuzugreifen,",
"To access the GGUF models available for downloading,": "To access the GGUF models available for downloading,",
"to chat input.": "to chat input.",
"Toggle settings": "Einstellungen umschalten",
"Toggle sidebar": "Seitenleiste umschalten",
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Probleme beim Zugriff auf Ollama?",
"TTS Settings": "TTS-Einstellungen",
"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": "Unknown File Type '{{file_type}}', but accepting and treating as plain text",
"Update password": "Passwort aktualisieren",
"Upload a GGUF model": "Upload a GGUF model",
"Upload files": "Dateien hochladen",
"Upload Progress": "Upload Progress",
"URL Mode": "URL Mode",
"Use '#' in the prompt input to load and select your documents.": "Verwende '#' in der Prompt-Eingabe, um Deine Dokumente zu laden und auszuwählen.",
"Use Gravatar": "",
"user": "Benutzer",
"User Permissions": "Benutzerberechtigungen",
"Users": "Benutzer",
"Utilize": "Nutze die",
"Valid time units:": "Gültige Zeiteinheiten:",
"variable": "Variable",
"variable to have them replaced with clipboard content.": "Variable, um den Inhalt der Zwischenablage beim Nutzen des Prompts zu ersetzen.",
"Version": "Version",
"Web": "Web",
"WebUI Add-ons": "WebUI-Add-Ons",
"WebUI Settings": "WebUI-Einstellungen",
"WebUI will make requests to": "Wenn aktiviert sendet WebUI externe Anfragen an",
"What’s New in": "Was gibt's Neues in",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Wenn die Historie ausgeschaltet ist, werden neue Chats nicht in Deiner Historie auf Deine Geräte angezeigt.",
"Whisper (Local)": "Whisper (Lokal)",
"Write a prompt suggestion (e.g. Who are you?)": "Gebe einen Prompt-Vorschlag ein (z.B. Wer bist du?)",
"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."
}
+363
View File
@@ -0,0 +1,363 @@
{
"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.",
"(Beta)": "(Beta)",
"(e.g. `sh webui.sh --api`)": "(e.g. `sh webui.sh --api`)",
"(latest)": "(latest)",
"{{modelName}} is thinking...": "{{modelName}} is thinking...",
"{{webUIName}} Backend Required": "{{webUIName}} Backend Required",
"a user": "",
"About": "About",
"Account": "Account",
"Action": "Action",
"Add a model": "Add a model",
"Add a model tag name": "Add a model tag name",
"Add a short description about what this modelfile does": "Add a short description about what this modelfile does",
"Add a short title for this prompt": "Add a short title for this prompt",
"Add a tag": "Add a tag",
"Add Docs": "Add Docs",
"Add Files": "Add Files",
"Add message": "Add message",
"add tags": "add tags",
"Adjusting these settings will apply changes universally to all users.": "Adjusting these settings will apply changes universally to all users.",
"admin": "admin",
"Admin Panel": "Admin Panel",
"Admin Settings": "Admin Settings",
"Advanced Parameters": "Advanced Parameters",
"all": "all",
"All Users": "All Users",
"Allow": "Allow",
"Allow Chat Deletion": "Allow Chat Deletion",
"alphanumeric characters and hyphens": "alphanumeric characters and hyphens",
"Already have an account?": "Already have an account?",
"an assistant": "",
"and": "and",
"API Base URL": "API Base URL",
"API Key": "API Key",
"API RPM": "API RPM",
"are allowed - Activate this command by typing": "are allowed - Activate this command by typing",
"Are you sure?": "",
"Audio": "Audio",
"Auto-playback response": "Auto-playback response",
"Auto-send input after 3 sec.": "Auto-send input after 3 sec.",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 Base URL",
"AUTOMATIC1111 Base URL is required.": "",
"available!": "available!",
"Back": "Back",
"Builder Mode": "Builder Mode",
"Cancel": "Cancel",
"Categories": "Categories",
"Change Password": "Change Password",
"Chat": "Chat",
"Chat History": "Chat History",
"Chat History is off for this browser.": "Chat History is off for this browser.",
"Chats": "Chats",
"Check Again": "Check Again",
"Check for updates": "Check for updates",
"Checking for updates...": "Checking for updates...",
"Choose a model before saving...": "Choose a model before saving...",
"Chunk Overlap": "Chunk Overlap",
"Chunk Params": "Chunk Params",
"Chunk Size": "Chunk Size",
"Click here for help.": "Click here for help.",
"Click here to check other modelfiles.": "Click here to check other modelfiles.",
"Click here to select": "",
"Click here to select documents.": "",
"click here.": "click here.",
"Click on the user role button to change a user's role.": "Click on the user role button to change a user's role.",
"Close": "Close",
"Collection": "Collection",
"Command": "Command",
"Confirm Password": "Confirm Password",
"Connections": "Connections",
"Content": "Content",
"Context Length": "Context Length",
"Conversation Mode": "Conversation Mode",
"Copy last code block": "Copy last code block",
"Copy last response": "Copy last response",
"Copying to clipboard was successful!": "Copying to clipboard was successful!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':",
"Create a modelfile": "Create a modelfile",
"Create Account": "Create Account",
"Created at": "Created at",
"Created by": "Created by",
"Current Model": "Current Model",
"Current Password": "Current Password",
"Custom": "Custom",
"Customize Ollama models for a specific purpose": "Customize Ollama models for a specific purpose",
"Dark": "Dark",
"Database": "Database",
"DD/MM/YYYY HH:mm": "DD/MM/YYYY HH:mm",
"Default": "Default",
"Default (Automatic1111)": "",
"Default (Web API)": "Default (Web API)",
"Default model updated": "Default model updated",
"Default Prompt Suggestions": "Default Prompt Suggestions",
"Default User Role": "Default User Role",
"delete": "delete",
"Delete a model": "Delete a model",
"Delete chat": "Delete chat",
"Delete Chats": "Delete Chats",
"Deleted {{deleteModelTag}}": "Deleted {{deleteModelTag}}",
"Deleted {tagName}": "Deleted {tagName}",
"Description": "Description",
"Desktop Notifications": "Notification",
"Disabled": "Disabled",
"Discover a modelfile": "Discover a modelfile",
"Discover a prompt": "Discover a prompt",
"Discover, download, and explore custom prompts": "Discover, download, and explore custom prompts",
"Discover, download, and explore model presets": "Discover, download, and explore model presets",
"Display the username instead of You in the Chat": "Display the username instead of 'You' in the Chat",
"Document": "Document",
"Document Settings": "Document Settings",
"Documents": "Documents",
"does not make any external connections, and your data stays securely on your locally hosted server.": "does not make any external connections, and your data stays securely on your locally hosted server.",
"Don't Allow": "Don't Allow",
"Don't have an account?": "Don't have an account?",
"Download as a File": "Download as a File",
"Download Database": "Download Database",
"Drop any files here to add to the conversation": "Drop any files here to add to the conversation",
"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.",
"Edit Doc": "Edit Doc",
"Edit User": "Edit User",
"Email": "Email",
"Enable Chat History": "Enable Chat History",
"Enable New Sign Ups": "Enable New Sign Ups",
"Enabled": "Enabled",
"Enter {{role}} message here": "",
"Enter API Key": "",
"Enter Chunk Overlap": "",
"Enter Chunk Size": "",
"Enter Image Size (e.g. 512x512)": "",
"Enter LiteLLM API Base URL (litellm_params.api_base)": "",
"Enter LiteLLM API Key (litellm_params.api_key)": "",
"Enter LiteLLM API RPM (litellm_params.rpm)": "",
"Enter LiteLLM Model (litellm_params.model)": "",
"Enter Max Tokens (litellm_params.max_tokens)": "",
"Enter model tag (e.g. {{modelTag}})": "",
"Enter Number of Steps (e.g. 50)": "",
"Enter stop sequence": "Enter stop sequence",
"Enter Top K": "",
"Enter URL (e.g. http://127.0.0.1:7860/)": "",
"Enter Your Email": "Enter Your Email",
"Enter Your Full Name": "Enter Your Full Name",
"Enter Your Password": "Enter Your Password",
"Experimental": "Experimental",
"Export All Chats (All Users)": "Export All Chats (All Users)",
"Export Chats": "Export Chats",
"Export Documents Mapping": "Export Documents Mapping",
"Export Modelfiles": "Export Modelfiles",
"Export Prompts": "Export Prompts",
"Failed to read clipboard contents": "Failed to read clipboard contents",
"File Mode": "File Mode",
"File not found.": "File not found.",
"Focus chat input": "Focus chat input",
"Format your variables using square brackets like this:": "Format your variables using square brackets like this:",
"From (Base Model)": "From (Base Model)",
"Full Screen Mode": "Full Screen Mode",
"General": "General",
"General Settings": "General Settings",
"Hello, {{name}}": "Hello, {{name}}",
"Hide": "Hide",
"Hide Additional Params": "Hide Additional Params",
"How can I help you today?": "How can I help you today?",
"Image Generation (Experimental)": "Image Generation (Experimental)",
"Image Generation Engine": "",
"Image Settings": "Image Settings",
"Images": "Images",
"Import Chats": "Import Chats",
"Import Documents Mapping": "Import Documents Mapping",
"Import Modelfiles": "Import Modelfiles",
"Import Prompts": "Import Prompts",
"Include `--api` flag when running stable-diffusion-webui": "Include `--api` flag when running stable-diffusion-webui",
"Interface": "Interface",
"join our Discord for help.": "join our Discord for help.",
"JSON": "JSON",
"JWT Expiration": "JWT Expiration",
"JWT Token": "JWT Token",
"Keep Alive": "Keep Alive",
"Keyboard shortcuts": "Keyboard shortcuts",
"Language": "Language",
"Light": "Light",
"Listening...": "Listening...",
"LLMs can make mistakes. Verify important information.": "LLMs can make mistakes. Verify important information.",
"Made by OpenWebUI Community": "Made by OpenWebUI Community",
"Make sure to enclose them with": "Make sure to enclose them with",
"Manage LiteLLM Models": "Manage LiteLLM Models",
"Manage Models": "Manage Models",
"Manage Ollama Models": "Manage Ollama Models",
"Max Tokens": "Max Tokens",
"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Maximum of 3 models can be downloaded simultaneously. Please try again later.",
"Mirostat": "Mirostat",
"Mirostat Eta": "Mirostat Eta",
"Mirostat Tau": "Mirostat Tau",
"MMMM DD, YYYY": "MMMM DD, YYYY",
"Model '{{modelName}}' has been successfully downloaded.": "Model '{{modelName}}' has been successfully downloaded.",
"Model '{{modelTag}}' is already in queue for downloading.": "Model '{{modelTag}}' is already in queue for downloading.",
"Model {{modelId}} not found": "Model {{modelId}} not found",
"Model {{modelName}} already exists.": "Model {{modelName}} already exists.",
"Model Name": "Model Name",
"Model not selected": "Model not selected",
"Model Tag Name": "Model Tag Name",
"Model Whitelisting": "Model Whitelisting",
"Model(s) Whitelisted": "Model(s) Whitelisted",
"Modelfile": "Modelfile",
"Modelfile Advanced Settings": "Modelfile Advanced Settings",
"Modelfile Content": "Modelfile Content",
"Modelfiles": "Modelfiles",
"Models": "Models",
"My Documents": "My Documents",
"My Modelfiles": "My Modelfiles",
"My Prompts": "My Prompts",
"Name": "Name",
"Name Tag": "Name Tag",
"Name your modelfile": "Name your modelfile",
"New Chat": "New Chat",
"New Password": "New Password",
"Not sure what to add?": "Not sure what to add?",
"Not sure what to write? Switch to": "Not sure what to write? Switch to",
"Off": "Off",
"Okay, Let's Go!": "Okay, Let's Go!",
"Ollama Base URL": "",
"Ollama Version": "Ollama Version",
"On": "On",
"Only": "Only",
"Only alphanumeric characters and hyphens are allowed in the command string.": "Only alphanumeric characters and hyphens are allowed in the command string.",
"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.",
"Oops! Looks like the URL is invalid. Please double-check and try again.": "Oops! Looks like the URL is invalid. Please double-check and try again.",
"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.",
"Open": "Open",
"Open AI": "Open AI",
"Open AI (Dall-E)": "",
"Open new chat": "Open new chat",
"OpenAI API": "OpenAI API",
"OpenAI API Key": "",
"OpenAI API Key is required.": "",
"or": "or",
"Parameters": "Parameters",
"Password": "Password",
"PDF Extract Images (OCR)": "PDF Extract Images (OCR)",
"pending": "pending",
"Permission denied when accessing microphone: {{error}}": "Permission denied when accessing microphone: {{error}}",
"Playground": "Playground",
"Profile": "Profile",
"Prompt Content": "Prompt Content",
"Prompt suggestions": "Prompt suggestions",
"Prompts": "Prompts",
"Pull a model from Ollama.com": "Pull a model from Ollama.com",
"Pull Progress": "Pull Progress",
"Query Params": "Query Params",
"RAG Template": "RAG Template",
"Raw Format": "Raw Format",
"Record voice": "Record voice",
"Redirecting you to OpenWebUI Community": "Redirecting you to OpenWebUI Community",
"Release Notes": "Release Notes",
"Repeat Last N": "Repeat Last N",
"Repeat Penalty": "Repeat Penalty",
"Request Mode": "Request Mode",
"Reset Vector Storage": "Reset Vector Storage",
"Response AutoCopy to Clipboard": "Response AutoCopy to Clipboard",
"Role": "Role",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"Save": "Save",
"Save & Create": "Save & Create",
"Save & Submit": "Save & Submit",
"Save & Update": "Save & Update",
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through",
"Scan": "Scan",
"Scan complete!": "Scan complete!",
"Scan for documents from {{path}}": "Scan for documents from {{path}}",
"Search": "Search",
"Search Documents": "Search Documents",
"Search Prompts": "Search Prompts",
"See readme.md for instructions": "See readme.md for instructions",
"See what's new": "See what's new",
"Seed": "Seed",
"Select a mode": "",
"Select a model": "Select a model",
"Select an Ollama instance": "",
"Send a Message": "Send a Message",
"Send message": "Send message",
"Server connection verified": "Server connection verified",
"Set as default": "Set as default",
"Set Default Model": "Set Default Model",
"Set Image Size": "Set Image Size",
"Set Steps": "Set Steps",
"Set Title Auto-Generation Model": "Set Title Auto-Generation Model",
"Set Voice": "Set Voice",
"Settings": "Settings",
"Settings saved successfully!": "Settings saved successfully!",
"Share to OpenWebUI Community": "Share to OpenWebUI Community",
"short-summary": "short-summary",
"Show": "Show",
"Show Additional Params": "Show Additional Params",
"Show shortcuts": "Show shortcuts",
"sidebar": "sidebar",
"Sign in": "Sign in",
"Sign Out": "Sign Out",
"Sign up": "Sign up",
"Speech recognition error: {{error}}": "Speech recognition error: {{error}}",
"Speech-to-Text Engine": "Speech-to-Text Engine",
"SpeechRecognition API is not supported in this browser.": "SpeechRecognition API is not supported in this browser.",
"Stop Sequence": "Stop Sequence",
"STT Settings": "STT Settings",
"Submit": "Submit",
"Success": "Success",
"Successfully updated.": "Successfully updated.",
"Sync All": "Sync All",
"System": "System",
"System Prompt": "System Prompt",
"Tags": "Tags",
"Temperature": "Temperature",
"Template": "Template",
"Text Completion": "Text Completion",
"Text-to-Speech Engine": "Text-to-Speech Engine",
"Tfs Z": "Tfs Z",
"Theme": "Theme",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "This ensures that your valuable conversations are securely saved to your backend database. Thank you!",
"This setting does not sync across browsers or devices.": "This setting does not sync across browsers or devices.",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.",
"Title": "Title",
"Title Auto-Generation": "Title Auto-Generation",
"Title Generation Prompt": "Title Generation Prompt",
"to": "to",
"To access the available model names for downloading,": "To access the available model names for downloading,",
"To access the GGUF models available for downloading,": "To access the GGUF models available for downloading,",
"to chat input.": "to chat input.",
"Toggle settings": "Toggle settings",
"Toggle sidebar": "Toggle sidebar",
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Trouble accessing Ollama?",
"TTS Settings": "TTS Settings",
"Type Hugging Face Resolve (Download) URL": "",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! There was an issue connecting to {{provider}}.",
"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Unknown File Type '{{file_type}}', but accepting and treating as plain text",
"Update password": "Update password",
"Upload a GGUF model": "Upload a GGUF model",
"Upload files": "Upload files",
"Upload Progress": "Upload Progress",
"URL Mode": "URL Mode",
"Use '#' in the prompt input to load and select your documents.": "Use '#' in the prompt input to load and select your documents.",
"Use Gravatar": "",
"user": "user",
"User Permissions": "User Permissions",
"Users": "Users",
"Utilize": "Utilize",
"Valid time units:": "Valid time units:",
"variable": "variable",
"variable to have them replaced with clipboard content.": "variable to have them replaced with clipboard content.",
"Version": "Version",
"Web": "Web",
"WebUI Add-ons": "WebUI Add-ons",
"WebUI Settings": "WebUI Settings",
"WebUI will make requests to": "WebUI will make requests to",
"What’s New in": "What’s New in",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "When history is turned off, new chats on this browser won't appear in your history on any of your devices.",
"Whisper (Local)": "Whisper (Local)",
"Write a prompt suggestion (e.g. Who are you?)": "Write a prompt suggestion (e.g. Who are you?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Write a summary in 50 words that summarizes [topic or keyword].",
"You": "You",
"You're a helpful assistant.": "You're a helpful assistant.",
"You're now logged in.": "You're now logged in."
}
+363
View File
@@ -0,0 +1,363 @@
{
"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' o '-1' para evitar expiración.",
"(Beta)": "(Beta)",
"(e.g. `sh webui.sh --api`)": "(p.ej. `sh webui.sh --api`)",
"(latest)": "(latest)",
"{{modelName}} is thinking...": "{{modelName}} está pensando...",
"{{webUIName}} Backend Required": "{{webUIName}} Servidor Requerido",
"a user": "un usuario",
"About": "Sobre nosotros",
"Account": "Cuenta",
"Action": "Acción",
"Add a model": "Agregar un modelo",
"Add a model tag name": "Agregar un nombre de etiqueta de modelo",
"Add a short description about what this modelfile does": "Agregue una descripción corta de lo que este modelfile hace",
"Add a short title for this prompt": "Agregue un título corto para este Prompt",
"Add a tag": "Agregar una etiqueta",
"Add Docs": "Agregar Documentos",
"Add Files": "Agregar Archivos",
"Add message": "Agregar Prompt",
"add tags": "agregar etiquetas",
"Adjusting these settings will apply changes universally to all users.": "Ajustar estas opciones aplicará los cambios universalmente a todos los usuarios.",
"admin": "admin",
"Admin Panel": "Panel de Administrador",
"Admin Settings": "Configuración de Administrador",
"Advanced Parameters": "Parametros Avanzados",
"all": "todo",
"All Users": "Todos los Usuarios",
"Allow": "Permitir",
"Allow Chat Deletion": "Permitir Borrar Chats",
"alphanumeric characters and hyphens": "caracteres alfanuméricos y guiones",
"Already have an account?": "¿Ya tienes una cuenta?",
"an assistant": "un asistente",
"and": "y",
"API Base URL": "Dirección URL de la API",
"API Key": "Clave de la API ",
"API RPM": "RPM de la API",
"are allowed - Activate this command by typing": "están permitidos - Active este comando escribiendo",
"Are you sure?": "Esta usted seguro?",
"Audio": "Audio",
"Auto-playback response": "Respuesta de reproducción automática",
"Auto-send input after 3 sec.": "Envía la información entrada automáticamente luego de 3 segundos.",
"AUTOMATIC1111 Base URL": "Dirección URL de AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "La dirección URL de AUTOMATIC1111 es requerida.",
"available!": "¡disponible!",
"Back": "Vuelve atrás",
"Builder Mode": "Modo de Constructor",
"Cancel": "Cancela",
"Categories": "Categorías",
"Change Password": "Cambia la Contraseña",
"Chat": "Chat",
"Chat History": "Historial del Chat",
"Chat History is off for this browser.": "El Historial del Chat está apagado para este navegador.",
"Chats": "Chats",
"Check Again": "Verifica de nuevo",
"Check for updates": "Verifica actualizaciones",
"Checking for updates...": "Verificando actualizaciones...",
"Choose a model before saving...": "Escoge un modelo antes de guardar los cambios...",
"Chunk Overlap": "Superposición de fragmentos",
"Chunk Params": "Parámetros de fragmentos",
"Chunk Size": "Tamaño de fragmentos",
"Click here for help.": "Presiona aquí para ayuda.",
"Click here to check other modelfiles.": "Presiona aquí para otros modelfiles.",
"Click here to select": "Presiona aquí para seleccionar",
"Click here to select documents.": "Presiona aquí para seleccionar documentos",
"click here.": "Presiona aquí.",
"Click on the user role button to change a user's role.": "Presiona en el botón de roles del usuario para cambiar el rol de un usuario.",
"Close": "Cerrar",
"Collection": "Colección",
"Command": "Comando",
"Confirm Password": "Confirmar Contraseña",
"Connections": "Conexiones",
"Content": "Contenido",
"Context Length": "Largura del contexto",
"Conversation Mode": "Modo de Conversación",
"Copy last code block": "Copia el último bloque de código",
"Copy last response": "Copia la última respuesta",
"Copying to clipboard was successful!": "¡Copiar al portapapeles fue exitoso!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Cree una frase concisa de 3 a 5 palabras como encabezado para la siguiente consulta, respetando estrictamente el límite de 3 a 5 palabras y evitando el uso de la palabra 'título':",
"Create a modelfile": "Crea un modelfile",
"Create Account": "Crear una cuenta",
"Created at": "Creado en",
"Created by": "Creado por",
"Current Model": "Modelo Actual",
"Current Password": "Contraseña Actual",
"Custom": "Personalizado",
"Customize Ollama models for a specific purpose": "Personaliza modelos de Ollama para un propósito específico",
"Dark": "Oscuro",
"Database": "Base de datos",
"DD/MM/YYYY HH:mm": "DD/MM/YYYY HH:mm",
"Default": "Por defecto",
"Default (Automatic1111)": "Por defecto (Automatic1111)",
"Default (Web API)": "Por defecto (Web API)",
"Default model updated": "El modelo por defecto ha sido actualizado",
"Default Prompt Suggestions": "Sugerencias de mensajes por defecto",
"Default User Role": "Rol por defecto para usuarios",
"delete": "borrar",
"Delete a model": "Borra un modelo",
"Delete chat": "Borrar chat",
"Delete Chats": "Borrar Chats",
"Deleted {{deleteModelTag}}": "Se borró {{deleteModelTag}}",
"Deleted {tagName}": "Se borró {tagName}",
"Description": "Descripción",
"Desktop Notifications": "Notificaciones",
"Disabled": "Desactivado",
"Discover a modelfile": "Descubre un modelfile",
"Discover a prompt": "Descubre un Prompt",
"Discover, download, and explore custom prompts": "Descubre, descarga, y explora Prompts personalizados",
"Discover, download, and explore model presets": "Descubra, descargue y explore ajustes preestablecidos de modelos",
"Display the username instead of You in the Chat": "Mostrar el nombre de usuario en lugar de Usted en el chat",
"Document": "Documento",
"Document Settings": "Configuración de Documento",
"Documents": "Documentos",
"does not make any external connections, and your data stays securely on your locally hosted server.": "no realiza ninguna conexión externa y sus datos permanecen seguros en su servidor alojado localmente.",
"Don't Allow": "No Permitir",
"Don't have an account?": "No tienes una cuenta?",
"Download as a File": "Descarga como un Archivo",
"Download Database": "Descarga la Base de Datos",
"Drop any files here to add to the conversation": "Suelta cualquier archivo aquí para agregarlo a la conversación",
"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "p.ej. '30s','10m'. Unidades válidas de tiempo son 's', 'm', 'h'.",
"Edit Doc": "Editar Documento",
"Edit User": "Editar Usuario",
"Email": "Email",
"Enable Chat History": "Activa el Historial de Chat",
"Enable New Sign Ups": "Habilitar Nuevos Registros",
"Enabled": "Habilitado",
"Enter {{role}} message here": "Introduzca el mensaje {{role}} aquí",
"Enter API Key": "Ingrese la clave API",
"Enter Chunk Overlap": "Ingresar superposición de fragmentos",
"Enter Chunk Size": "Introduzca el tamaño del fragmento",
"Enter Image Size (e.g. 512x512)": "Ingrese el tamaño de la imagen (p.ej. 512x512)",
"Enter LiteLLM API Base URL (litellm_params.api_base)": "Ingrese la URL base de la API LiteLLM (litellm_params.api_base)",
"Enter LiteLLM API Key (litellm_params.api_key)": "Ingrese la clave API LiteLLM (litellm_params.api_key)",
"Enter LiteLLM API RPM (litellm_params.rpm)": "Ingrese el RPM de la API LiteLLM (litellm_params.rpm)",
"Enter LiteLLM Model (litellm_params.model)": "Ingrese el modelo LiteLLM (litellm_params.model)",
"Enter Max Tokens (litellm_params.max_tokens)": "Ingrese tokens máximos (litellm_params.max_tokens)",
"Enter model tag (e.g. {{modelTag}})": "Ingrese la etiqueta del modelo (p.ej. {{modelTag}})",
"Enter Number of Steps (e.g. 50)": "Ingrese el número de pasos (p.ej., 50)",
"Enter stop sequence": "Introduzca la secuencia de parada",
"Enter Top K": "Introduzca el Top K",
"Enter URL (e.g. http://127.0.0.1:7860/)": "Ingrese la URL (p.ej., http://127.0.0.1:7860/)",
"Enter Your Email": "Introduce tu correo electrónico",
"Enter Your Full Name": "Introduce tu nombre completo",
"Enter Your Password": "Introduce tu contraseña",
"Experimental": "Experimental",
"Export All Chats (All Users)": "Exportar todos los chats (Todos los usuarios)",
"Export Chats": "Exportar Chats",
"Export Documents Mapping": "Exportar el mapeo de documentos",
"Export Modelfiles": "Exportal Modelfiles",
"Export Prompts": "Exportar Prompts",
"Failed to read clipboard contents": "No se pudo leer el contenido del portapapeles",
"File Mode": "Modo de archivo",
"File not found.": "Archivo no encontrado.",
"Focus chat input": "Enfoca la entrada del chat",
"Format your variables using square brackets like this:": "Formatee sus variables usando corchetes así:",
"From (Base Model)": "Desde (Modelo Base)",
"Full Screen Mode": "Modo de Pantalla Completa",
"General": "General",
"General Settings": "Opciones Generales",
"Hello, {{name}}": "Hola, {{name}}",
"Hide": "Esconder",
"Hide Additional Params": "Esconde los Parámetros Adicionales",
"How can I help you today?": "¿Cómo puedo ayudarte hoy?",
"Image Generation (Experimental)": "Generación de imágenes (experimental)",
"Image Generation Engine": "Motor de generación de imágenes",
"Image Settings": "Configuración de Imágen",
"Images": "Imágenes",
"Import Chats": "Importar chats",
"Import Documents Mapping": "Importar Mapeo de Documentos",
"Import Modelfiles": "Importar Modelfiles",
"Import Prompts": "Importar Prompts",
"Include `--api` flag when running stable-diffusion-webui": "Incluir el indicador `--api` al ejecutar stable-diffusion-webui",
"Interface": "Interface",
"join our Discord for help.": "Únase a nuestro Discord para obtener ayuda.",
"JSON": "JSON",
"JWT Expiration": "Expiración del JWT",
"JWT Token": "Token JWT",
"Keep Alive": "Mantener Vivo",
"Keyboard shortcuts": "Atajos de teclado",
"Language": "Lenguaje",
"Light": "Claro",
"Listening...": "Escuchando...",
"LLMs can make mistakes. Verify important information.": "Los LLM pueden cometer errores. Verifica la información importante.",
"Made by OpenWebUI Community": "Hecho por la comunidad de OpenWebUI",
"Make sure to enclose them with": "Make sure to enclose them with",
"Manage LiteLLM Models": "Administrar Modelos LiteLLM",
"Manage Models": "Administrar Modelos",
"Manage Ollama Models": "Administrar Modelos Ollama",
"Max Tokens": "Máximo de Tokens",
"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Se pueden descargar un máximo de 3 modelos simultáneamente. Por favor, inténtelo de nuevo más tarde.",
"Mirostat": "Mirostat",
"Mirostat Eta": "Mirostat Eta",
"Mirostat Tau": "Mirostat Tau",
"MMMM DD, YYYY": "MMMM DD, YYYY",
"Model '{{modelName}}' has been successfully downloaded.": "El modelo '{{modelName}}' se ha descargado correctamente.",
"Model '{{modelTag}}' is already in queue for downloading.": "El modelo '{{modelTag}}' ya está en cola para descargar.",
"Model {{modelId}} not found": "El modelo {{modelId}} no fue encontrado",
"Model {{modelName}} already exists.": "El modelo {{modelName}} ya existe.",
"Model Name": "Nombre del modelo",
"Model not selected": "Modelo no seleccionado",
"Model Tag Name": "Nombre de la etiqueta del modelo",
"Model Whitelisting": "Listado de Modelos habilitados",
"Model(s) Whitelisted": "Modelo(s) habilitados",
"Modelfile": "Modelfile",
"Modelfile Advanced Settings": "Opciones avanzadas del Modelfile",
"Modelfile Content": "Contenido del Modelfile",
"Modelfiles": "Modelfiles",
"Models": "Modelos",
"My Documents": "Mis Documentos",
"My Modelfiles": "Mis Modelfiles",
"My Prompts": "Mis Prompts",
"Name": "Nombre",
"Name Tag": "Nombre de etiqueta",
"Name your modelfile": "Nombra tu modelfile",
"New Chat": "Nuevo Chat",
"New Password": "Nueva Contraseña",
"Not sure what to add?": "¿No estás seguro de qué añadir?",
"Not sure what to write? Switch to": "¿No estás seguro de qué escribir? Cambia a",
"Off": "Apagado",
"Okay, Let's Go!": "Okay, Let's Go!",
"Ollama Base URL": "URL base de Ollama",
"Ollama Version": "Version de Ollama",
"On": "Encendido",
"Only": "Solamente",
"Only alphanumeric characters and hyphens are allowed in the command string.": "Sólo se permiten caracteres alfanuméricos y guiones en la cadena de comando.",
"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "¡Ups! ¡Agárrate fuerte! Tus archivos todavía están en el horno de procesamiento. Los estamos cocinando a la perfección. Tenga paciencia y le avisaremos una vez que estén listos.",
"Oops! Looks like the URL is invalid. Please double-check and try again.": "¡Ups! Parece que la URL no es válida. Vuelva a verificar e inténtelo nuevamente.",
"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "¡Ups! Estás utilizando un método no compatible (solo frontend). Sirve la WebUI desde el backend.",
"Open": "Abrir",
"Open AI": "Open AI",
"Open AI (Dall-E)": "",
"Open new chat": "Abrir nuevo chat",
"OpenAI API": "OpenAI API",
"OpenAI API Key": "Clave de OpenAI API",
"OpenAI API Key is required.": "La Clave de OpenAI API es requerida.",
"or": "o",
"Parameters": "Parametros",
"Password": "Contraseña",
"PDF Extract Images (OCR)": "Extraer imágenes de PDF (OCR)",
"pending": "pendiente",
"Permission denied when accessing microphone: {{error}}": "Permiso denegado al acceder al micrófono: {{error}}",
"Playground": "Playground",
"Profile": "Perfil",
"Prompt Content": "Contenido del Prompt",
"Prompt suggestions": "Sugerencias de Prompts",
"Prompts": "Prompts",
"Pull a model from Ollama.com": "Extraer un modelo de Ollama.com",
"Pull Progress": "Progreso de extracción",
"Query Params": "Parámetros de consulta",
"RAG Template": "Plantilla de RAG",
"Raw Format": "Formato en crudo",
"Record voice": "Grabar voz",
"Redirecting you to OpenWebUI Community": "Redireccionándote a la comunidad OpenWebUI",
"Release Notes": "Notas de la versión",
"Repeat Last N": "Repetir las últimas N",
"Repeat Penalty": "Penalidad de repetición",
"Request Mode": "Modo de petición",
"Reset Vector Storage": "Restablecer almacenamiento vectorial",
"Response AutoCopy to Clipboard": "Copiar respuesta automáticamente al portapapeles",
"Role": "personalizados",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"Save": "Guardar",
"Save & Create": "Guardar y Crear",
"Save & Submit": "Guardar y Enviar",
"Save & Update": "Guardar y Actualizar",
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Ya no se admite guardar registros de chat directamente en el almacenamiento de su navegador. Tómese un momento para descargar y eliminar sus registros de chat haciendo clic en el botón a continuación. No te preocupes, puedes volver a importar fácilmente tus registros de chat al backend a través de",
"Scan": "Escanear",
"Scan complete!": "Escaneo completado!",
"Scan for documents from {{path}}": "Escanear en busca de documentos desde {{path}}",
"Search": "Buscar",
"Search Documents": "Buscar Documentos",
"Search Prompts": "Buscar Prompts",
"See readme.md for instructions": "Vea el readme.md para instrucciones",
"See what's new": "Ver qué hay de nuevo",
"Seed": "Seed",
"Select a mode": "Selecciona un modo",
"Select a model": "Selecciona un modelo",
"Select an Ollama instance": "Seleccione una instancia de Ollama",
"Send a Message": "Enviar un Mensaje",
"Send message": "Enviar Mensaje",
"Server connection verified": "Conexión del servidor verificada",
"Set as default": "Establecer por defecto",
"Set Default Model": "Establecer modelo predeterminado",
"Set Image Size": "Establecer tamaño de imagen",
"Set Steps": "Establecer Pasos",
"Set Title Auto-Generation Model": "Establecer modelo de generación automática de títulos",
"Set Voice": "Establecer la voz",
"Settings": "Configuración",
"Settings saved successfully!": "Configuración guardada exitosamente!",
"Share to OpenWebUI Community": "Compartir con la comunidad OpenWebUI",
"short-summary": "resumen-corto",
"Show": "Mostrar",
"Show Additional Params": "Mostrar parámetros adicionales",
"Show shortcuts": "Mostrar atajos",
"sidebar": "barra lateral",
"Sign in": "Iniciar sesión",
"Sign Out": "Desconectar",
"Sign up": "Inscribirse",
"Speech recognition error: {{error}}": "Error de reconocimiento de voz: {{error}}",
"Speech-to-Text Engine": "Motor de voz a texto",
"SpeechRecognition API is not supported in this browser.": "La API SpeechRecognition no es compatible con este navegador.",
"Stop Sequence": "Detener secuencia",
"STT Settings": "Configuraciones de STT",
"Submit": "Enviar",
"Success": "Éxito",
"Successfully updated.": "Actualizado exitosamente.",
"Sync All": "Sincronizar todo",
"System": "Sistema",
"System Prompt": "Prompt del sistema",
"Tags": "Etiquetas",
"Temperature": "Temperatura",
"Template": "Plantilla",
"Text Completion": "Finalización de texto",
"Text-to-Speech Engine": "Motor de texto a voz",
"Tfs Z": "Tfs Z",
"Theme": "Tema",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Esto garantiza que sus valiosas conversaciones se guarden de forma segura en su base de datos en el backend. ¡Gracias!",
"This setting does not sync across browsers or devices.": "Esta configuración no se sincroniza entre navegadores o dispositivos.",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Consejo: actualice varias variables consecutivamente presionando la tecla tab en la entrada del chat después de cada reemplazo.",
"Title": "Título",
"Title Auto-Generation": "Generación automática de títulos",
"Title Generation Prompt": "Prompt de generación de título",
"to": "para",
"To access the available model names for downloading,": "Para acceder a los nombres de modelos disponibles para descargar,",
"To access the GGUF models available for downloading,": "Para acceder a los modelos GGUF disponibles para descargar,",
"to chat input.": "a la entrada del chat.",
"Toggle settings": "Alternar configuración",
"Toggle sidebar": "Alternar barra lateral",
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "¿Problemas para acceder a Ollama?",
"TTS Settings": "Configuración de TTS",
"Type Hugging Face Resolve (Download) URL": "Type Hugging Face Resolve (Download) URL",
"Uh-oh! There was an issue connecting to {{provider}}.": "¡UH oh! Hubo un problema al conectarse a {{provider}}.",
"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Tipo de archivo desconocido '{{file_type}}', pero se acepta y se trata como texto sin formato",
"Update password": "Actualiza contraseña",
"Upload a GGUF model": "Sube un modelo GGUF",
"Upload files": "Subir archivos",
"Upload Progress": "Progreso de carga",
"URL Mode": "Modo de URL",
"Use '#' in the prompt input to load and select your documents.": "Utilice '#' en el prompt para cargar y seleccionar sus documentos.",
"Use Gravatar": "Usar Gravatar",
"user": "usuario",
"User Permissions": "Permisos de usuario",
"Users": "Usuarios",
"Utilize": "Utilizar",
"Valid time units:": "Unidades válidas de tiempo:",
"variable": "variable",
"variable to have them replaced with clipboard content.": "variable para reemplazarlos con el contenido del portapapeles.",
"Version": "Version",
"Web": "Web",
"WebUI Add-ons": "WebUI Add-ons",
"WebUI Settings": "Configuración del WebUI",
"WebUI will make requests to": "WebUI realizará solicitudes a",
"What’s New in": "Lo qué hay de nuevo en",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Cuando el historial está desactivado, los nuevos chats en este navegador no aparecerán en el historial de ninguno de sus dispositivos..",
"Whisper (Local)": "Whisper (Local)",
"Write a prompt suggestion (e.g. Who are you?)": "Escribe una sugerencia para un prompt (por ejemplo, ¿quién eres?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Escribe un resumen en 50 palabras que resuma [tema o palabra clave].",
"You": "Usted",
"You're a helpful assistant.": "Eres un asistente útil.",
"You're now logged in.": "Ya has iniciado sesión."
}
+363
View File
@@ -0,0 +1,363 @@
{
"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' یا '-1' برای غیر فعال کردن انقضا.",
"(Beta)": "(بتا)",
"(e.g. `sh webui.sh --api`)": "(e.g. `sh webui.sh --api`)",
"(latest)": "(آخرین)",
"{{modelName}} is thinking...": "{{modelName}} در حال فکر کردن است...",
"{{webUIName}} Backend Required": "بکند {{webUIName}} نیاز است.",
"a user": "یک کاربر",
"About": "درباره",
"Account": "حساب کاربری",
"Action": "عمل",
"Add a model": "اضافه کردن یک مدل",
"Add a model tag name": "اضافه کردن یک نام تگ برای مدل",
"Add a short description about what this modelfile does": "توضیح کوتاهی در مورد کاری که این فایل\u200cمدل انجام می دهد اضافه کنید",
"Add a short title for this prompt": "یک عنوان کوتاه برای این درخواست اضافه کنید",
"Add a tag": "اضافه کردن یک تگ",
"Add Docs": "اضافه کردن اسناد",
"Add Files": "اضافه کردن فایل\u200cها",
"Add message": "اضافه کردن پیغام",
"add tags": "اضافه کردن تگ\u200cها",
"Adjusting these settings will apply changes universally to all users.": "با تنظیم این تنظیمات، تغییرات به طور کلی برای همه کاربران اعمال می شود.",
"admin": "مدیر",
"Admin Panel": "پنل مدیریت",
"Admin Settings": "تنظیمات مدیریت",
"Advanced Parameters": "پارامترهای پیشرفته",
"all": "همه",
"All Users": "همه کاربران",
"Allow": "اجازه دادن",
"Allow Chat Deletion": "اجازه حذف گپ",
"alphanumeric characters and hyphens": "حروف الفبایی و خط فاصله",
"Already have an account?": "از قبل حساب کاربری دارید؟",
"an assistant": "یک دستیار",
"and": "و",
"API Base URL": "API Base URL",
"API Key": "API Key",
"API RPM": "API RPM",
"are allowed - Activate this command by typing": "مجاز هستند - این دستور را با تایپ کردن این فعال کنید:",
"Are you sure?": "آیا مطمئن هستید؟",
"Audio": "صدا",
"Auto-playback response": "پخش خودکار پاسخ ",
"Auto-send input after 3 sec.": "به طور خودکار ورودی را پس از 3 ثانیه ارسال کن.",
"AUTOMATIC1111 Base URL": "پایه URL AUTOMATIC1111 ",
"AUTOMATIC1111 Base URL is required.": "به URL پایه AUTOMATIC1111 مورد نیاز است.",
"available!": "در دسترس!",
"Back": "بازگشت",
"Builder Mode": "حالت سازنده",
"Cancel": "لغو",
"Categories": "دسته\u200cبندی\u200cها",
"Change Password": "تغییر رمز عبور",
"Chat": "گپ",
"Chat History": "تاریخچه\u200cی گفتگو",
"Chat History is off for this browser.": "سابقه گپ برای این مرورگر خاموش است.",
"Chats": "گپ\u200cها",
"Check Again": "چک مجدد",
"Check for updates": "بررسی به\u200cروزرسانی",
"Checking for updates...": "در حال بررسی برای به\u200cروزرسانی..",
"Choose a model before saving...": "قبل از ذخیره یک مدل را انتخاب کنید...",
"Chunk Overlap": "همپوشانی تکه",
"Chunk Params": "پارامترهای تکه",
"Chunk Size": "اندازه تکه",
"Click here for help.": "برای کمک اینجا را کلیک کنید.",
"Click here to check other modelfiles.": "برای بررسی سایر فایل\u200cهای مدل اینجا را کلیک کنید.",
"Click here to select": "برای انتخاب اینجا کلیک کنید",
"Click here to select documents.": "برای انتخاب اسناد اینجا را کلیک کنید.",
"click here.": "اینجا کلیک کنید.",
"Click on the user role button to change a user's role.": "برای تغییر نقش کاربر، روی دکمه نقش کاربر کلیک کنید.",
"Close": "بسته",
"Collection": "مجموعه",
"Command": "دستور",
"Confirm Password": "تایید رمز عبور",
"Connections": "ارتباطات",
"Content": "محتوا",
"Context Length": "طول زمینه",
"Conversation Mode": "حالت مکالمه",
"Copy last code block": "کپی آخرین بلوک کد",
"Copy last response": "کپی آخرین پاسخ",
"Copying to clipboard was successful!": "کپی کردن در کلیپ بورد با موفقیت انجام شد!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "یک عبارت مختصر و ۳ تا ۵ کلمه ای را به عنوان سرفصل برای پرس و جو زیر ایجاد کنید، به شدت محدودیت ۳-۵ کلمه را رعایت کنید و از استفاده از کلمه 'عنوان' خودداری کنید:",
"Create a modelfile": "ایجاد یک فایل مدل",
"Create Account": "ساخت حساب کاربری",
"Created at": "ایجاد شده در",
"Created by": "ایجاد شده توسط",
"Current Model": "مدل فعلی",
"Current Password": "رمز عبور فعلی",
"Custom": "دلخواه",
"Customize Ollama models for a specific purpose": "مدل های اولاما را برای یک هدف خاص سفارشی کنید",
"Dark": "تیره",
"Database": "پایگاه داده",
"DD/MM/YYYY HH:mm": "DD/MM/YYYY HH:mm",
"Default": "پیشفرض",
"Default (Automatic1111)": "پیشفرض (Automatic1111)",
"Default (Web API)": "پیشفرض (Web API)",
"Default model updated": "مدل پیشفرض به\u200cروزرسانی شد",
"Default Prompt Suggestions": "پیشنهادات پرامپت پیش فرض",
"Default User Role": "نقش کاربر پیش فرض",
"delete": "حذف",
"Delete a model": "حذف یک مدل",
"Delete chat": "حذف گپ",
"Delete Chats": "حذف گپ\u200cها",
"Deleted {{deleteModelTag}}": "{{deleteModelTag}} پاک شد",
"Deleted {tagName}": "{tagName} حذف شد",
"Description": "توضیحات",
"Desktop Notifications": "اعلان",
"Disabled": "غیرفعال",
"Discover a modelfile": "فایل مدل را کشف کنید",
"Discover a prompt": "یک اعلان را کشف کنید",
"Discover, download, and explore custom prompts": "پرامپت\u200cهای سفارشی را کشف، دانلود و کاوش کنید",
"Discover, download, and explore model presets": "پیش تنظیمات مدل را کشف، دانلود و کاوش کنید",
"Display the username instead of You in the Chat": "نمایش نام کاربری به جای «شما» در چت",
"Document": "سند",
"Document Settings": "تنظیمات سند",
"Documents": "اسناد",
"does not make any external connections, and your data stays securely on your locally hosted server.": "هیچ اتصال خارجی ایجاد نمی کند و داده های شما به طور ایمن در سرور میزبان محلی شما باقی می ماند.",
"Don't Allow": "اجازه نده",
"Don't have an account?": "حساب کاربری ندارید؟",
"Download as a File": "دانلود به صورت فایل",
"Download Database": "دانلود پایگاه داده",
"Drop any files here to add to the conversation": "هر فایلی را اینجا رها کنید تا به مکالمه اضافه شود",
"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "به طور مثال '30s','10m'. واحد\u200cهای زمانی معتبر 's', 'm', 'h' هستند.",
"Edit Doc": "ویرایش سند",
"Edit User": "ویرایش کاربر",
"Email": "ایمیل",
"Enable Chat History": "تاریخچه چت را فعال کنید",
"Enable New Sign Ups": "فعال کردن ثبت نام\u200cهای جدید",
"Enabled": "فعال",
"Enter {{role}} message here": "پیام {{role}} را اینجا وارد کنید",
"Enter API Key": "کلید API را وارد کنید",
"Enter Chunk Overlap": "مقدار Chunk Overlap را وارد کنید",
"Enter Chunk Size": "مقدار Chunk Size را وارد کنید",
"Enter Image Size (e.g. 512x512)": "اندازه تصویر را وارد کنید (مثال: 512x512)",
"Enter LiteLLM API Base URL (litellm_params.api_base)": "URL پایه مربوط به LiteLLM API را وارد کنید (litellm_params.api_base)",
"Enter LiteLLM API Key (litellm_params.api_key)": "کلید API مربوط به LiteLLM را وارد کنید (litellm_params.api_key)",
"Enter LiteLLM API RPM (litellm_params.rpm)": "RPM API مربوط به LiteLLM را وارد کنید (litellm_params.rpm)",
"Enter LiteLLM Model (litellm_params.model)": "مدل مربوط به LiteLLM را وارد کنید (litellm_params.model)",
"Enter Max Tokens (litellm_params.max_tokens)": "حداکثر تعداد توکن را وارد کنید (litellm_params.max_tokens)",
"Enter model tag (e.g. {{modelTag}})": "تگ مدل را وارد کنید (مثلا {{modelTag}})",
"Enter Number of Steps (e.g. 50)": "تعداد گام ها را وارد کنید (مثال: 50)",
"Enter stop sequence": "توالی توقف را وارد کنید",
"Enter Top K": "مقدار Top K را وارد کنید",
"Enter URL (e.g. http://127.0.0.1:7860/)": "مقدار URL را وارد کنید (مثال http://127.0.0.1:7860/)",
"Enter Your Email": "ایمیل خود را وارد کنید",
"Enter Your Full Name": "نام کامل خود را وارد کنید",
"Enter Your Password": "رمز عبور خود را وارد کنید",
"Experimental": "آزمایشی",
"Export All Chats (All Users)": "اکسپورت از همه گپ\u200cها(همه کاربران)",
"Export Chats": "اکسپورت از گپ\u200cها",
"Export Documents Mapping": "اکسپورت از نگاشت اسناد",
"Export Modelfiles": "اکسپورت از فایل\u200cهای مدل",
"Export Prompts": "اکسپورت از پرامپت\u200cها",
"Failed to read clipboard contents": "خواندن محتوای کلیپ بورد ناموفق بود",
"File Mode": "حالت فایل",
"File not found.": "فایل یافت نشد.",
"Focus chat input": "فوکوس کردن ورودی گپ",
"Format your variables using square brackets like this:": "متغیرهای خود را با استفاده از براکت مربع به شکل زیر قالب بندی کنید:",
"From (Base Model)": "از (مدل پایه)",
"Full Screen Mode": "حالت تمام صفحه",
"General": "عمومی",
"General Settings": "تنظیمات عمومی",
"Hello, {{name}}": "سلام، {{name}}",
"Hide": "پنهان",
"Hide Additional Params": "پنهان کردن پارامترهای اضافه",
"How can I help you today?": "امروز چطور می توانم کمک تان کنم؟",
"Image Generation (Experimental)": "تولید تصویر (آزمایشی)",
"Image Generation Engine": "موتور تولید تصویر",
"Image Settings": "تنظیمات تصویر",
"Images": "تصاویر",
"Import Chats": "ایمپورت گپ\u200cها",
"Import Documents Mapping": "ایمپورت نگاشت اسناد",
"Import Modelfiles": "ایمپورت فایل\u200cهای مدل",
"Import Prompts": "ایمپورت پرامپت\u200cها",
"Include `--api` flag when running stable-diffusion-webui": "فلگ `--api` را هنکام اجرای stable-diffusion-webui استفاده کنید.",
"Interface": "رابط",
"join our Discord for help.": "برای کمک به دیسکورد ما بپیوندید.",
"JSON": "JSON",
"JWT Expiration": "JWT انقضای",
"JWT Token": "JWT توکن",
"Keep Alive": "Keep Alive",
"Keyboard shortcuts": "میانبرهای صفحه کلید",
"Language": "زبان",
"Light": "روشن",
"Listening...": "در حال گوش دادن...",
"LLMs can make mistakes. Verify important information.": "مدل\u200cهای زبانی بزرگ می\u200cتوانند اشتباه کنند. اطلاعات مهم را راستی\u200cآزمایی کنید.",
"Made by OpenWebUI Community": "ساخته شده توسط OpenWebUI Community",
"Make sure to enclose them with": "مطمئن شوید که آنها را با این محصور کنید:",
"Manage LiteLLM Models": "Manage LiteLLM Models",
"Manage Models": "مدیریت مدل\u200cها",
"Manage Ollama Models": "مدیریت مدل\u200cهای اولاما",
"Max Tokens": "حداکثر توکن",
"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "حداکثر 3 مدل را می توان به طور همزمان دانلود کرد. لطفاً بعداً دوباره امتحان کنید.",
"Mirostat": "Mirostat",
"Mirostat Eta": "Mirostat Eta",
"Mirostat Tau": "Mirostat Tau",
"MMMM DD, YYYY": "MMMM DD, YYYY",
"Model '{{modelName}}' has been successfully downloaded.": "مدل '{{modelName}}' با موفقیت دانلود شد.",
"Model '{{modelTag}}' is already in queue for downloading.": "مدل '{{modelTag}}' در حال حاضر در صف برای دانلود است.",
"Model {{modelId}} not found": "مدل {{modelId}} یافت نشد",
"Model {{modelName}} already exists.": "مدل {{modelName}} در حال حاضر وجود دارد.",
"Model Name": "نام مدل",
"Model not selected": "مدل انتخاب نشده",
"Model Tag Name": "نام تگ مدل",
"Model Whitelisting": "لیست سفید مدل",
"Model(s) Whitelisted": "مدل در لیست سفید ثبت شد",
"Modelfile": "فایل مدل",
"Modelfile Advanced Settings": "تنظیمات پیشرفته فایل\u200cمدل",
"Modelfile Content": "محتویات فایل مدل",
"Modelfiles": "فایل\u200cهای مدل",
"Models": "مدل\u200cها",
"My Documents": "اسناد من",
"My Modelfiles": "فایل\u200cهای مدل من",
"My Prompts": "پرامپت\u200cهای من",
"Name": "نام",
"Name Tag": "نام تگ",
"Name your modelfile": "فایل مدل را نام\u200cگذاری کنید",
"New Chat": "گپ جدید",
"New Password": "رمز عبور جدید",
"Not sure what to add?": "مطمئن نیستید چه چیزی را اضافه کنید؟",
"Not sure what to write? Switch to": "مطمئن نیستید چه بنویسید؟ تغییر به",
"Off": "خاموش",
"Okay, Let's Go!": "باشه، بزن بریم!",
"Ollama Base URL": "URL پایه اولاما",
"Ollama Version": "نسخه اولاما",
"On": "روشن",
"Only": "فقط",
"Only alphanumeric characters and hyphens are allowed in the command string.": "فقط کاراکترهای الفبایی و خط فاصله در رشته فرمان مجاز هستند.",
"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "اوه! فایل های شما هنوز در فر پردازش هستند. ما آنها را کامل می پزیم. لطفا صبور باشید، به محض آماده شدن به شما اطلاع خواهیم داد.",
"Oops! Looks like the URL is invalid. Please double-check and try again.": "اوه! به نظر می رسد URL نامعتبر است. لطفاً دوباره بررسی کنید و دوباره امتحان کنید.",
"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "اوه! شما از یک روش پشتیبانی نشده (فقط frontend) استفاده می کنید. لطفاً WebUI را از بکند اجرا کنید.",
"Open": "باز",
"Open AI": "Open AI",
"Open AI (Dall-E)": "Open AI (Dall-E)",
"Open new chat": "باز کردن گپ جدید",
"OpenAI API": "OpenAI API",
"OpenAI API Key": "کلید OpenAI API",
"OpenAI API Key is required.": "مقدار کلید OpenAI API مورد نیاز است.",
"or": "روشن",
"Parameters": "پارامترها",
"Password": "رمز عبور",
"PDF Extract Images (OCR)": "استخراج تصاویر از PDF (OCR)",
"pending": "در انتظار",
"Permission denied when accessing microphone: {{error}}": "هنگام دسترسی به میکروفون، اجازه داده نشد: {{error}}",
"Playground": "زمین بازی",
"Profile": "پروفایل",
"Prompt Content": "محتویات پرامپت",
"Prompt suggestions": "پیشنهادات پرامپت",
"Prompts": "پرامپت\u200cها",
"Pull a model from Ollama.com": "دریافت یک مدل از Ollama.com",
"Pull Progress": "پیشرفت دریافت",
"Query Params": "پارامترهای پرس و جو",
"RAG Template": "RAG الگوی",
"Raw Format": "فرمت خام",
"Record voice": "ضبط صدا",
"Redirecting you to OpenWebUI Community": "در حال هدایت به OpenWebUI Community",
"Release Notes": "یادداشت\u200cهای انتشار",
"Repeat Last N": "Repeat Last N",
"Repeat Penalty": "Repeat Penalty",
"Request Mode": "حالت درخواست",
"Reset Vector Storage": "بازنشانی ذخیره سازی برداری",
"Response AutoCopy to Clipboard": "کپی خودکار پاسخ به کلیپ بورد",
"Role": "نقش",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"Save": "ذخیره",
"Save & Create": "ذخیره و ایجاد",
"Save & Submit": "ذخیره و ارسال",
"Save & Update": "ذخیره و به\u200cروزرسانی",
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "ذخیره گزارش\u200cهای چت مستقیماً در حافظه مرورگر شما دیگر پشتیبانی نمی\u200cشود. لطفاً با کلیک بر روی دکمه زیر، چند لحظه برای دانلود و حذف گزارش های چت خود وقت بگذارید. نگران نباشید، شما به راحتی می توانید گزارش های چت خود را از طریق بکند دوباره وارد کنید",
"Scan": "اسکن",
"Scan complete!": "اسکن کامل شد!",
"Scan for documents from {{path}}": "اسکن اسناد از {{path}}",
"Search": "جستجو",
"Search Documents": "جستجوی اسناد",
"Search Prompts": "جستجوی پرامپت\u200cها",
"See readme.md for instructions": "برای مشاهده دستورالعمل\u200cها به readme.md مراجعه کنید",
"See what's new": "ببینید موارد جدید چه بوده",
"Seed": "Seed",
"Select a mode": "یک حالت انتخاب کنید",
"Select a model": "انتخاب یک مدل",
"Select an Ollama instance": "انتخاب یک نمونه از اولاما",
"Send a Message": "ارسال یک پیام",
"Send message": "ارسال پیام",
"Server connection verified": "اتصال سرور تأیید شد",
"Set as default": "تنظیم به عنوان پیشفرض",
"Set Default Model": "تنظیم مدل پیش فرض",
"Set Image Size": "تنظیم اندازه تصویر",
"Set Steps": "تنظیم گام\u200cها",
"Set Title Auto-Generation Model": "تنظیم مدل تولید خودکار عنوان",
"Set Voice": "تنظیم صدا",
"Settings": "تنظیمات",
"Settings saved successfully!": "تنظیمات با موفقیت ذخیره شد!",
"Share to OpenWebUI Community": "اشتراک گذاری با OpenWebUI Community",
"short-summary": "خلاصه کوتاه",
"Show": "نمایش",
"Show Additional Params": "نمایش پارامترهای اضافه",
"Show shortcuts": "نمایش میانبرها",
"sidebar": "نوار کناری",
"Sign in": "ورود",
"Sign Out": "خروج",
"Sign up": "ثبت نام",
"Speech recognition error: {{error}}": "خطای تشخیص گفتار: {{error}}",
"Speech-to-Text Engine": "موتور گفتار به متن",
"SpeechRecognition API is not supported in this browser.": "API تشخیص گفتار در این مرورگر پشتیبانی نمی شود.",
"Stop Sequence": "توالی توقف",
"STT Settings": "STT تنظیمات",
"Submit": "ارسال",
"Success": "موفقیت",
"Successfully updated.": "با موفقیت به روز شد",
"Sync All": "همگام سازی همه",
"System": "سیستم",
"System Prompt": "پرامپت سیستم",
"Tags": "تگ\u200cها",
"Temperature": "دما",
"Template": "الگو",
"Text Completion": "تکمیل متن",
"Text-to-Speech Engine": "موتور تبدیل متن به گفتار",
"Tfs Z": "Tfs Z",
"Theme": "قالب",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "این تضمین می کند که مکالمات ارزشمند شما به طور ایمن در پایگاه داده بکند ذخیره می شود. تشکر!",
"This setting does not sync across browsers or devices.": "این تنظیم در مرورگرها یا دستگاه\u200cها همگام\u200cسازی نمی\u200cشود.",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "با فشردن کلید Tab در ورودی چت پس از هر بار تعویض، چندین متغیر را به صورت متوالی به روزرسانی کنید.",
"Title": "عنوان",
"Title Auto-Generation": "تولید خودکار عنوان",
"Title Generation Prompt": "پرامپت تولید عنوان",
"to": "به",
"To access the available model names for downloading,": "برای دسترسی به نام مدل های موجود برای دانلود،",
"To access the GGUF models available for downloading,": "برای دسترسی به مدل\u200cهای GGUF موجود برای دانلود،",
"to chat input.": "در ورودی گپ.",
"Toggle settings": "نمایش/عدم نمایش تنظیمات",
"Toggle sidebar": "نمایش/عدم نمایش نوار کناری",
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "در دسترسی به اولاما مشکل دارید؟",
"TTS Settings": "تنظیمات TTS",
"Type Hugging Face Resolve (Download) URL": "مقدار URL دانلود (Resolve) Hugging Face را وارد کنید",
"Uh-oh! There was an issue connecting to {{provider}}.": "اوه اوه! مشکلی در اتصال به {{provider}} وجود داشت.",
"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "نوع فایل '{{file_type}}' ناشناخته است، به عنوان یک فایل متنی ساده با آن برخورد می شود.",
"Update password": "به روزرسانی رمزعبور",
"Upload a GGUF model": "آپلود یک مدل GGUF",
"Upload files": "بارگذاری فایل\u200cها",
"Upload Progress": "پیشرفت آپلود",
"URL Mode": "حالت URL",
"Use '#' in the prompt input to load and select your documents.": "در پرامپت از '#' برای لود و انتخاب اسناد خود استفاده کنید.",
"Use Gravatar": "استفاده از گراواتار",
"user": "کاربر",
"User Permissions": "مجوزهای کاربر",
"Users": "کاربران",
"Utilize": "استفاده کنید",
"Valid time units:": "واحدهای زمانی معتبر:",
"variable": "متغیر",
"variable to have them replaced with clipboard content.": "متغیر برای جایگزینی آنها با محتوای کلیپ بورد.",
"Version": "نسخه",
"Web": "وب",
"WebUI Add-ons": "WebUI افزونه\u200cهای",
"WebUI Settings": "تنظیمات WebUI",
"WebUI will make requests to": "WebUI درخواست\u200cها را ارسال خواهد کرد به",
"What’s New in": "موارد جدید در",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "وقتی سابقه خاموش است، چت\u200cهای جدید در این مرورگر در سابقه شما در هیچ یک از دستگاه\u200cهایتان ظاهر نمی\u200cشوند.",
"Whisper (Local)": "ویسپر (محلی)",
"Write a prompt suggestion (e.g. Who are you?)": "یک پیشنهاد پرامپت بنویسید (مثلاً شما کی هستید؟)",
"Write a summary in 50 words that summarizes [topic or keyword].": "خلاصه ای در 50 کلمه بنویسید که [موضوع یا کلمه کلیدی] را خلاصه کند.",
"You": "شما",
"You're a helpful assistant.": "تو یک دستیار سودمند هستی.",
"You're now logged in.": "شما اکنون وارد شده\u200cاید."
}
+363
View File
@@ -0,0 +1,363 @@
{
"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' ou '-1' pour aucune expiration.",
"(Beta)": "(Bêta)",
"(e.g. `sh webui.sh --api`)": "(par ex. `sh webui.sh --api`)",
"(latest)": "",
"{{modelName}} is thinking...": "{{modelName}} réfléchit...",
"{{webUIName}} Backend Required": "Backend {{webUIName}} requis",
"a user": "un utilisateur",
"About": "À propos",
"Account": "Compte",
"Action": "Action",
"Add a model": "Ajouter un modèle",
"Add a model tag name": "Ajouter un nom de tag pour le modèle",
"Add a short description about what this modelfile does": "Ajouter une courte description de ce que fait ce fichier de modèle",
"Add a short title for this prompt": "Ajouter un court titre pour ce prompt",
"Add a tag": "Ajouter un tag",
"Add Docs": "Ajouter des documents",
"Add Files": "Ajouter des fichiers",
"Add message": "Ajouter un message",
"add tags": "ajouter des tags",
"Adjusting these settings will apply changes universally to all users.": "L'ajustement de ces paramètres appliquera les changements à tous les utilisateurs.",
"admin": "Administrateur",
"Admin Panel": "Panneau d'administration",
"Admin Settings": "Paramètres d'administration",
"Advanced Parameters": "Paramètres avancés",
"all": "tous",
"All Users": "Tous les utilisateurs",
"Allow": "Autoriser",
"Allow Chat Deletion": "Autoriser la suppression des discussions",
"alphanumeric characters and hyphens": "caractères alphanumériques et tirets",
"Already have an account?": "Vous avez déjà un compte ?",
"an assistant": "un assistant",
"and": "et",
"API Base URL": "URL de base de l'API",
"API Key": "Clé API",
"API RPM": "RPM API",
"are allowed - Activate this command by typing": "sont autorisés - Activez cette commande en tapant",
"Are you sure?": "Êtes-vous sûr ?",
"Audio": "Audio",
"Auto-playback response": "Réponse en lecture automatique",
"Auto-send input after 3 sec.": "Envoyer automatiquement l'entrée après 3 sec.",
"AUTOMATIC1111 Base URL": "URL de base AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "L'URL de base AUTOMATIC1111 est requise.",
"available!": "disponible !",
"Back": "Retour",
"Builder Mode": "Mode Constructeur",
"Cancel": "Annuler",
"Categories": "Catégories",
"Change Password": "Changer le mot de passe",
"Chat": "Discussion",
"Chat History": "Historique des discussions",
"Chat History is off for this browser.": "L'historique des discussions est désactivé pour ce navigateur.",
"Chats": "Discussions",
"Check Again": "Vérifier à nouveau",
"Check for updates": "Vérifier les mises à jour",
"Checking for updates...": "Vérification des mises à jour...",
"Choose a model before saving...": "Choisissez un modèle avant d'enregistrer...",
"Chunk Overlap": "Chevauchement de bloc",
"Chunk Params": "Paramètres de bloc",
"Chunk Size": "Taille de bloc",
"Click here for help.": "Cliquez ici pour de l'aide.",
"Click here to check other modelfiles.": "Cliquez ici pour vérifier d'autres fichiers de modèle.",
"Click here to select": "Cliquez ici pour sélectionner",
"Click here to select documents.": "Cliquez ici pour sélectionner des documents.",
"click here.": "cliquez ici.",
"Click on the user role button to change a user's role.": "Cliquez sur le bouton de rôle d'utilisateur pour changer le rôle d'un utilisateur.",
"Close": "Fermer",
"Collection": "Collection",
"Command": "Commande",
"Confirm Password": "Confirmer le mot de passe",
"Connections": "Connexions",
"Content": "Contenu",
"Context Length": "Longueur du contexte",
"Conversation Mode": "Mode de conversation",
"Copy last code block": "Copier le dernier bloc de code",
"Copy last response": "Copier la dernière réponse",
"Copying to clipboard was successful!": "La copie dans le presse-papiers a réussi !",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Créez une phrase concise de 3 à 5 mots comme en-tête pour la requête suivante, en respectant strictement la limite de 3 à 5 mots et en évitant l'utilisation du mot 'titre' :",
"Create a modelfile": "Créer un fichier de modèle",
"Create Account": "Créer un compte",
"Created at": "Créé le",
"Created by": "Créé par",
"Current Model": "Modèle actuel",
"Current Password": "Mot de passe actuel",
"Custom": "Personnalisé",
"Customize Ollama models for a specific purpose": "Personnaliser les modèles Ollama pour un objectif spécifique",
"Dark": "Sombre",
"Database": "Base de données",
"DD/MM/YYYY HH:mm": "DD/MM/YYYY HH:mm",
"Default": "Par défaut",
"Default (Automatic1111)": "Par défaut (Automatic1111)",
"Default (Web API)": "Par défaut (API Web)",
"Default model updated": "Modèle par défaut mis à jour",
"Default Prompt Suggestions": "Suggestions de prompt par défaut",
"Default User Role": "Rôle d'utilisateur par défaut",
"delete": "supprimer",
"Delete a model": "Supprimer un modèle",
"Delete chat": "Supprimer la discussion",
"Delete Chats": "Supprimer les discussions",
"Deleted {{deleteModelTag}}": "{{deleteModelTag}} supprimé",
"Deleted {tagName}": "{tagName} supprimé",
"Description": "Description",
"Desktop Notifications": "Notifications de bureau",
"Disabled": "Désactivé",
"Discover a modelfile": "Découvrir un fichier de modèle",
"Discover a prompt": "Découvrir un prompt",
"Discover, download, and explore custom prompts": "Découvrir, télécharger et explorer des prompts personnalisés",
"Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préconfigurations de modèles",
"Display the username instead of You in the Chat": "Afficher le nom d'utilisateur au lieu de 'Vous' dans la Discussion",
"Document": "Document",
"Document Settings": "Paramètres du document",
"Documents": "Documents",
"does not make any external connections, and your data stays securely on your locally hosted server.": "ne fait aucune connexion externe, et vos données restent en sécurité sur votre serveur hébergé localement.",
"Don't Allow": "Ne pas autoriser",
"Don't have an account?": "Vous n'avez pas de compte ?",
"Download as a File": "Télécharger en tant que fichier",
"Download Database": "Télécharger la base de données",
"Drop any files here to add to the conversation": "Déposez n'importe quel fichier ici pour les ajouter à la conversation",
"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "p. ex. '30s', '10m'. Les unités de temps valides sont 's', 'm', 'h'.",
"Edit Doc": "Éditer le document",
"Edit User": "Éditer l'utilisateur",
"Email": "Email",
"Enable Chat History": "Activer l'historique des discussions",
"Enable New Sign Ups": "Activer les nouvelles inscriptions",
"Enabled": "Activé",
"Enter {{role}} message here": "Entrez le message {{role}} ici",
"Enter API Key": "Entrez la clé API",
"Enter Chunk Overlap": "Entrez le chevauchement de bloc",
"Enter Chunk Size": "Entrez la taille du bloc",
"Enter Image Size (e.g. 512x512)": "Entrez la taille de l'image (p. ex. 512x512)",
"Enter LiteLLM API Base URL (litellm_params.api_base)": "Entrez l'URL de base de l'API LiteLLM (litellm_params.api_base)",
"Enter LiteLLM API Key (litellm_params.api_key)": "Entrez la clé API LiteLLM (litellm_params.api_key)",
"Enter LiteLLM API RPM (litellm_params.rpm)": "Entrez le RPM de l'API LiteLLM (litellm_params.rpm)",
"Enter LiteLLM Model (litellm_params.model)": "Entrez le modèle LiteLLM (litellm_params.model)",
"Enter Max Tokens (litellm_params.max_tokens)": "Entrez le nombre max de tokens (litellm_params.max_tokens)",
"Enter model tag (e.g. {{modelTag}})": "Entrez le tag du modèle (p. ex. {{modelTag}})",
"Enter Number of Steps (e.g. 50)": "Entrez le nombre d'étapes (p. ex. 50)",
"Enter stop sequence": "Entrez la séquence de fin",
"Enter Top K": "Entrez Top K",
"Enter URL (e.g. http://127.0.0.1:7860/)": "Entrez l'URL (p. ex. http://127.0.0.1:7860/)",
"Enter Your Email": "Entrez votre adresse email",
"Enter Your Full Name": "Entrez votre nom complet",
"Enter Your Password": "Entrez votre mot de passe",
"Experimental": "Expérimental",
"Export All Chats (All Users)": "Exporter toutes les discussions (Tous les utilisateurs)",
"Export Chats": "Exporter les discussions",
"Export Documents Mapping": "Exporter le mappage des documents",
"Export Modelfiles": "Exporter les fichiers de modèle",
"Export Prompts": "Exporter les prompts",
"Failed to read clipboard contents": "Échec de la lecture du contenu du presse-papiers",
"File Mode": "Mode fichier",
"File not found.": "Fichier introuvable.",
"Focus chat input": "Se concentrer sur l'entrée de la discussion",
"Format your variables using square brackets like this:": "Formatez vos variables en utilisant des crochets comme ceci :",
"From (Base Model)": "De (Modèle de base)",
"Full Screen Mode": "Mode plein écran",
"General": "Général",
"General Settings": "Paramètres généraux",
"Hello, {{name}}": "Bonjour, {{name}}",
"Hide": "Cacher",
"Hide Additional Params": "Cacher les paramètres supplémentaires",
"How can I help you today?": "Comment puis-je vous aider aujourd'hui ?",
"Image Generation (Experimental)": "Génération d'image (Expérimental)",
"Image Generation Engine": "Moteur de génération d'image",
"Image Settings": "Paramètres de l'image",
"Images": "Images",
"Import Chats": "Importer les discussions",
"Import Documents Mapping": "Importer le mappage des documents",
"Import Modelfiles": "Importer les fichiers de modèle",
"Import Prompts": "Importer les prompts",
"Include `--api` flag when running stable-diffusion-webui": "Inclure l'indicateur `--api` lors de l'exécution de stable-diffusion-webui",
"Interface": "Interface",
"join our Discord for help.": "rejoignez notre Discord pour obtenir de l'aide.",
"JSON": "JSON",
"JWT Expiration": "Expiration du JWT",
"JWT Token": "Jeton JWT",
"Keep Alive": "Garder actif",
"Keyboard shortcuts": "Raccourcis clavier",
"Language": "Langue",
"Light": "Lumière",
"Listening...": "Écoute...",
"LLMs can make mistakes. Verify important information.": "Les LLMs peuvent faire des erreurs. Vérifiez les informations importantes.",
"Made by OpenWebUI Community": "Réalisé par la communauté OpenWebUI",
"Make sure to enclose them with": "Assurez-vous de les entourer avec",
"Manage LiteLLM Models": "Gérer les modèles LiteLLM",
"Manage Models": "Gérer les modèles",
"Manage Ollama Models": "Gérer les modèles Ollama",
"Max Tokens": "Tokens maximaux",
"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Un maximum de 3 modèles peut être téléchargé simultanément. Veuillez réessayer plus tard.",
"Mirostat": "Mirostat",
"Mirostat Eta": "Mirostat Eta",
"Mirostat Tau": "Mirostat Tau",
"MMMM DD, YYYY": "MMMM DD, YYYY",
"Model '{{modelName}}' has been successfully downloaded.": "Le modèle '{{modelName}}' a été téléchargé avec succès.",
"Model '{{modelTag}}' is already in queue for downloading.": "Le modèle '{{modelTag}}' est déjà dans la file d'attente pour le téléchargement.",
"Model {{modelId}} not found": "Modèle {{modelId}} non trouvé",
"Model {{modelName}} already exists.": "Le modèle {{modelName}} existe déjà.",
"Model Name": "Nom du modèle",
"Model not selected": "Modèle non sélectionné",
"Model Tag Name": "Nom de tag du modèle",
"Model Whitelisting": "Liste blanche de modèle",
"Model(s) Whitelisted": "Modèle(s) sur liste blanche",
"Modelfile": "Fichier de modèle",
"Modelfile Advanced Settings": "Paramètres avancés du fichier de modèle",
"Modelfile Content": "Contenu du fichier de modèle",
"Modelfiles": "Fichiers de modèle",
"Models": "Modèles",
"My Documents": "Mes documents",
"My Modelfiles": "Mes fichiers de modèle",
"My Prompts": "Mes prompts",
"Name": "Nom",
"Name Tag": "Tag de nom",
"Name your modelfile": "Nommez votre fichier de modèle",
"New Chat": "Nouvelle discussion",
"New Password": "Nouveau mot de passe",
"Not sure what to add?": "Pas sûr de quoi ajouter ?",
"Not sure what to write? Switch to": "Pas sûr de quoi écrire ? Changez pour",
"Off": "Éteint",
"Okay, Let's Go!": "Okay, Allons-y !",
"Ollama Base URL": "URL de Base Ollama",
"Ollama Version": "Version Ollama",
"On": "Activé",
"Only": "Seulement",
"Only alphanumeric characters and hyphens are allowed in the command string.": "Seuls les caractères alphanumériques et les tirets sont autorisés dans la chaîne de commande.",
"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Oups ! Tenez bon ! Vos fichiers sont encore dans le four de traitement. Nous les préparons jusqu'à la perfection. Soyez patient et nous vous informerons dès qu'ils seront prêts.",
"Oops! Looks like the URL is invalid. Please double-check and try again.": "Oups ! Il semble que l'URL soit invalide. Merci de vérifier et réessayer.",
"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Oups ! Vous utilisez une méthode non prise en charge (frontal uniquement). Veuillez servir WebUI depuis le backend.",
"Open": "Ouvrir",
"Open AI": "Open AI",
"Open AI (Dall-E)": "Open AI (Dall-E)",
"Open new chat": "Ouvrir une nouvelle discussion",
"OpenAI API": "API OpenAI",
"OpenAI API Key": "Clé API OpenAI",
"OpenAI API Key is required.": "La clé API OpenAI est requise.",
"or": "ou",
"Parameters": "Paramètres",
"Password": "Mot de passe",
"PDF Extract Images (OCR)": "Extraction d'images PDF (OCR)",
"pending": "en attente",
"Permission denied when accessing microphone: {{error}}": "Permission refusée lors de l'accès au microphone : {{error}}",
"Playground": "Aire de jeu",
"Profile": "Profil",
"Prompt Content": "Contenu du prompt",
"Prompt suggestions": "Suggestions de prompt",
"Prompts": "Prompts",
"Pull a model from Ollama.com": "Tirer un modèle de Ollama.com",
"Pull Progress": "Progression du téléchargement",
"Query Params": "Paramètres de requête",
"RAG Template": "Modèle RAG",
"Raw Format": "Format brut",
"Record voice": "Enregistrer la voix",
"Redirecting you to OpenWebUI Community": "Vous redirige vers la communauté OpenWebUI",
"Release Notes": "Notes de version",
"Repeat Last N": "Répéter les N derniers",
"Repeat Penalty": "Pénalité de répétition",
"Request Mode": "Mode de requête",
"Reset Vector Storage": "Réinitialiser le stockage vectoriel",
"Response AutoCopy to Clipboard": "Copie automatique de la réponse vers le presse-papiers",
"Role": "Rôle",
"Rosé Pine": "Pin Rosé",
"Rosé Pine Dawn": "Aube Pin Rosé",
"Save": "Enregistrer",
"Save & Create": "Enregistrer & Créer",
"Save & Submit": "Enregistrer & Soumettre",
"Save & Update": "Enregistrer & Mettre à jour",
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "La sauvegarde des journaux de discussion directement dans le stockage de votre navigateur n'est plus prise en charge. Veuillez prendre un moment pour télécharger et supprimer vos journaux de discussion en cliquant sur le bouton ci-dessous. Ne vous inquiétez pas, vous pouvez facilement réimporter vos journaux de discussion dans le backend via",
"Scan": "Scanner",
"Scan complete!": "Scan terminé !",
"Scan for documents from {{path}}": "Scanner des documents depuis {{path}}",
"Search": "Recherche",
"Search Documents": "Rechercher des documents",
"Search Prompts": "Rechercher des prompts",
"See readme.md for instructions": "Voir readme.md pour les instructions",
"See what's new": "Voir les nouveautés",
"Seed": "Graine",
"Select a mode": "Sélectionnez un mode",
"Select a model": "Sélectionnez un modèle",
"Select an Ollama instance": "Sélectionner une instance Ollama",
"Send a Message": "Envoyer un message",
"Send message": "Envoyer un message",
"Server connection verified": "Connexion au serveur vérifiée",
"Set as default": "Définir par défaut",
"Set Default Model": "Définir le modèle par défaut",
"Set Image Size": "Définir la taille de l'image",
"Set Steps": "Définir les étapes",
"Set Title Auto-Generation Model": "Définir le modèle de génération automatique de titre",
"Set Voice": "Définir la voix",
"Settings": "Paramètres",
"Settings saved successfully!": "Paramètres enregistrés avec succès !",
"Share to OpenWebUI Community": "Partager avec la communauté OpenWebUI",
"short-summary": "résumé court",
"Show": "Afficher",
"Show Additional Params": "Afficher les paramètres supplémentaires",
"Show shortcuts": "Afficher les raccourcis",
"sidebar": "barre latérale",
"Sign in": "Se connecter",
"Sign Out": "Se déconnecter",
"Sign up": "S'inscrire",
"Speech recognition error: {{error}}": "Erreur de reconnaissance vocale : {{error}}",
"Speech-to-Text Engine": "Moteur reconnaissance vocale",
"SpeechRecognition API is not supported in this browser.": "L'API SpeechRecognition n'est pas prise en charge dans ce navigateur.",
"Stop Sequence": "Séquence d'arrêt",
"STT Settings": "Paramètres de STT",
"Submit": "Soumettre",
"Success": "Succès",
"Successfully updated.": "Mis à jour avec succès.",
"Sync All": "Synchroniser tout",
"System": "Système",
"System Prompt": "Prompt Système",
"Tags": "Tags",
"Temperature": "Température",
"Template": "Modèle",
"Text Completion": "Complétion de texte",
"Text-to-Speech Engine": "Moteur de texte à la parole",
"Tfs Z": "Tfs Z",
"Theme": "Thème",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Cela garantit que vos précieuses conversations sont enregistrées en toute sécurité dans votre base de données backend. Merci !",
"This setting does not sync across browsers or devices.": "Ce réglage ne se synchronise pas entre les navigateurs ou les appareils.",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Astuce : Mettez à jour plusieurs emplacements de variables consécutivement en appuyant sur la touche tabulation dans l'entrée de chat après chaque remplacement.",
"Title": "Titre",
"Title Auto-Generation": "Génération automatique de titre",
"Title Generation Prompt": "Prompt de génération de titre",
"to": "à",
"To access the available model names for downloading,": "Pour accéder aux noms de modèles disponibles pour le téléchargement,",
"To access the GGUF models available for downloading,": "Pour accéder aux modèles GGUF disponibles pour le téléchargement,",
"to chat input.": "à l'entrée du chat.",
"Toggle settings": "Basculer les paramètres",
"Toggle sidebar": "Basculer la barre latérale",
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Des problèmes pour accéder à Ollama ?",
"TTS Settings": "Paramètres TTS",
"Type Hugging Face Resolve (Download) URL": "Entrez l'URL de résolution (téléchargement) Hugging Face",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh ! Il y a eu un problème de connexion à {{provider}}.",
"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Type de fichier inconnu '{{file_type}}', mais accepté et traité comme du texte brut",
"Update password": "Mettre à jour le mot de passe",
"Upload a GGUF model": "Téléverser un modèle GGUF",
"Upload files": "Téléverser des fichiers",
"Upload Progress": "Progression du Téléversement",
"URL Mode": "Mode URL",
"Use '#' in the prompt input to load and select your documents.": "Utilisez '#' dans l'entrée de prompt pour charger et sélectionner vos documents.",
"Use Gravatar": "Utiliser Gravatar",
"user": "utilisateur",
"User Permissions": "Permissions de l'utilisateur",
"Users": "Utilisateurs",
"Utilize": "Utiliser",
"Valid time units:": "Unités de temps valides :",
"variable": "variable",
"variable to have them replaced with clipboard content.": "variable pour les remplacer par le contenu du presse-papiers.",
"Version": "Version",
"Web": "Web",
"WebUI Add-ons": "Add-ons WebUI",
"WebUI Settings": "Paramètres WebUI",
"WebUI will make requests to": "WebUI effectuera des demandes à",
"What’s New in": "Quoi de neuf dans",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Lorsque l'historique est désactivé, les nouvelles discussions sur ce navigateur n'apparaîtront pas dans votre historique sur aucun de vos appareils.",
"Whisper (Local)": "Whisper (Local)",
"Write a prompt suggestion (e.g. Who are you?)": "Rédigez une suggestion de prompt (p. ex. Qui êtes-vous ?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Rédigez un résumé en 50 mots qui résume [sujet ou mot-clé].",
"You": "You",
"You're a helpful assistant.": "Vous êtes un assistant utile",
"You're now logged in.": "Vous êtes maintenant connecté."
}
+363
View File
@@ -0,0 +1,363 @@
{
"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' ou '-1' pour aucune expiration.",
"(Beta)": "(Bêta)",
"(e.g. `sh webui.sh --api`)": "(par ex. `sh webui.sh --api`)",
"(latest)": "",
"{{modelName}} is thinking...": "{{modelName}} réfléchit...",
"{{webUIName}} Backend Required": "Backend {{webUIName}} requis",
"a user": "un utilisateur",
"About": "À propos",
"Account": "Compte",
"Action": "Action",
"Add a model": "Ajouter un modèle",
"Add a model tag name": "Ajouter un nom de tag pour le modèle",
"Add a short description about what this modelfile does": "Ajouter une courte description de ce que fait ce fichier de modèle",
"Add a short title for this prompt": "Ajouter un court titre pour ce prompt",
"Add a tag": "Ajouter un tag",
"Add Docs": "Ajouter des documents",
"Add Files": "Ajouter des fichiers",
"Add message": "Ajouter un message",
"add tags": "ajouter des tags",
"Adjusting these settings will apply changes universally to all users.": "L'ajustement de ces paramètres appliquera les changements à tous les utilisateurs.",
"admin": "Administrateur",
"Admin Panel": "Panneau d'administration",
"Admin Settings": "Paramètres d'administration",
"Advanced Parameters": "Paramètres avancés",
"all": "tous",
"All Users": "Tous les utilisateurs",
"Allow": "Autoriser",
"Allow Chat Deletion": "Autoriser la suppression du chat",
"alphanumeric characters and hyphens": "caractères alphanumériques et tirets",
"Already have an account?": "Vous avez déjà un compte ?",
"an assistant": "un assistant",
"and": "et",
"API Base URL": "URL de base de l'API",
"API Key": "Clé API",
"API RPM": "RPM API",
"are allowed - Activate this command by typing": "sont autorisés - Activez cette commande en tapant",
"Are you sure?": "Êtes-vous sûr ?",
"Audio": "Audio",
"Auto-playback response": "Réponse en lecture automatique",
"Auto-send input after 3 sec.": "Envoyer automatiquement l'entrée après 3 sec.",
"AUTOMATIC1111 Base URL": "URL de base AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "L'URL de base AUTOMATIC1111 est requise.",
"available!": "disponible !",
"Back": "Retour",
"Builder Mode": "Mode Constructeur",
"Cancel": "Annuler",
"Categories": "Catégories",
"Change Password": "Changer le mot de passe",
"Chat": "Chat",
"Chat History": "Historique du chat",
"Chat History is off for this browser.": "L'historique du chat est désactivé pour ce navigateur.",
"Chats": "Chats",
"Check Again": "Vérifier à nouveau",
"Check for updates": "Vérifier les mises à jour",
"Checking for updates...": "Vérification des mises à jour...",
"Choose a model before saving...": "Choisissez un modèle avant d'enregistrer...",
"Chunk Overlap": "Chevauchement de bloc",
"Chunk Params": "Paramètres de bloc",
"Chunk Size": "Taille de bloc",
"Click here for help.": "Cliquez ici pour de l'aide.",
"Click here to check other modelfiles.": "Cliquez ici pour vérifier d'autres fichiers de modèle.",
"Click here to select": "Cliquez ici pour sélectionner",
"Click here to select documents.": "Cliquez ici pour sélectionner des documents.",
"click here.": "cliquez ici.",
"Click on the user role button to change a user's role.": "Cliquez sur le bouton de rôle d'utilisateur pour changer le rôle d'un utilisateur.",
"Close": "Fermer",
"Collection": "Collection",
"Command": "Commande",
"Confirm Password": "Confirmer le mot de passe",
"Connections": "Connexions",
"Content": "Contenu",
"Context Length": "Longueur du contexte",
"Conversation Mode": "Mode de conversation",
"Copy last code block": "Copier le dernier bloc de code",
"Copy last response": "Copier la dernière réponse",
"Copying to clipboard was successful!": "La copie dans le presse-papiers a réussi !",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Créez une phrase concise de 3-5 mots comme en-tête pour la requête suivante, en respectant strictement la limite de 3-5 mots et en évitant l'utilisation du mot 'titre' :",
"Create a modelfile": "Créer un fichier de modèle",
"Create Account": "Créer un compte",
"Created at": "Créé le",
"Created by": "Créé par",
"Current Model": "Modèle actuel",
"Current Password": "Mot de passe actuel",
"Custom": "Personnalisé",
"Customize Ollama models for a specific purpose": "Personnaliser les modèles Ollama pour un objectif spécifique",
"Dark": "Sombre",
"Database": "Base de données",
"DD/MM/YYYY HH:mm": "DD/MM/YYYY HH:mm",
"Default": "Par défaut",
"Default (Automatic1111)": "Par défaut (Automatic1111)",
"Default (Web API)": "Par défaut (API Web)",
"Default model updated": "Modèle par défaut mis à jour",
"Default Prompt Suggestions": "Suggestions de prompt par défaut",
"Default User Role": "Rôle d'utilisateur par défaut",
"delete": "supprimer",
"Delete a model": "Supprimer un modèle",
"Delete chat": "Supprimer le chat",
"Delete Chats": "Supprimer les chats",
"Deleted {{deleteModelTag}}": "{{deleteModelTag}} supprimé",
"Deleted {tagName}": "{tagName} supprimé",
"Description": "Description",
"Desktop Notifications": "Notifications de bureau",
"Disabled": "Désactivé",
"Discover a modelfile": "Découvrir un fichier de modèle",
"Discover a prompt": "Découvrir un prompt",
"Discover, download, and explore custom prompts": "Découvrir, télécharger et explorer des prompts personnalisés",
"Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préconfigurations de modèles",
"Display the username instead of You in the Chat": "Afficher le nom d'utilisateur au lieu de 'Vous' dans le Chat",
"Document": "Document",
"Document Settings": "Paramètres du document",
"Documents": "Documents",
"does not make any external connections, and your data stays securely on your locally hosted server.": "ne fait aucune connexion externe, et vos données restent en sécurité sur votre serveur hébergé localement.",
"Don't Allow": "Ne pas autoriser",
"Don't have an account?": "Vous n'avez pas de compte ?",
"Download as a File": "Télécharger en tant que fichier",
"Download Database": "Télécharger la base de données",
"Drop any files here to add to the conversation": "Déposez des fichiers ici pour les ajouter à la conversation",
"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "par ex. '30s', '10m'. Les unités de temps valides sont 's', 'm', 'h'.",
"Edit Doc": "Éditer le document",
"Edit User": "Éditer l'utilisateur",
"Email": "Email",
"Enable Chat History": "Activer l'historique du chat",
"Enable New Sign Ups": "Activer les nouvelles inscriptions",
"Enabled": "Activé",
"Enter {{role}} message here": "Entrez le message {{role}} ici",
"Enter API Key": "Entrez la clé API",
"Enter Chunk Overlap": "Entrez le chevauchement de bloc",
"Enter Chunk Size": "Entrez la taille du bloc",
"Enter Image Size (e.g. 512x512)": "Entrez la taille de l'image (p. ex. 512x512)",
"Enter LiteLLM API Base URL (litellm_params.api_base)": "Entrez l'URL de base de l'API LiteLLM (litellm_params.api_base)",
"Enter LiteLLM API Key (litellm_params.api_key)": "Entrez la clé API LiteLLM (litellm_params.api_key)",
"Enter LiteLLM API RPM (litellm_params.rpm)": "Entrez le RPM de l'API LiteLLM (litellm_params.rpm)",
"Enter LiteLLM Model (litellm_params.model)": "Entrez le modèle LiteLLM (litellm_params.model)",
"Enter Max Tokens (litellm_params.max_tokens)": "Entrez le nombre max de tokens (litellm_params.max_tokens)",
"Enter model tag (e.g. {{modelTag}})": "Entrez le tag du modèle (p. ex. {{modelTag}})",
"Enter Number of Steps (e.g. 50)": "Entrez le nombre d'étapes (p. ex. 50)",
"Enter stop sequence": "Entrez la séquence de fin",
"Enter Top K": "Entrez Top K",
"Enter URL (e.g. http://127.0.0.1:7860/)": "Entrez l'URL (p. ex. http://127.0.0.1:7860/)",
"Enter Your Email": "Entrez votre email",
"Enter Your Full Name": "Entrez votre nom complet",
"Enter Your Password": "Entrez votre mot de passe",
"Experimental": "Expérimental",
"Export All Chats (All Users)": "Exporter tous les chats (tous les utilisateurs)",
"Export Chats": "Exporter les chats",
"Export Documents Mapping": "Exporter la correspondance des documents",
"Export Modelfiles": "Exporter les fichiers de modèle",
"Export Prompts": "Exporter les prompts",
"Failed to read clipboard contents": "Échec de la lecture du contenu du presse-papiers",
"File Mode": "Mode fichier",
"File not found.": "Fichier non trouvé.",
"Focus chat input": "Concentrer sur l'entrée du chat",
"Format your variables using square brackets like this:": "Formatez vos variables en utilisant des crochets comme ceci :",
"From (Base Model)": "De (Modèle de base)",
"Full Screen Mode": "Mode plein écran",
"General": "Général",
"General Settings": "Paramètres généraux",
"Hello, {{name}}": "Bonjour, {{name}}",
"Hide": "Cacher",
"Hide Additional Params": "Hide additional params",
"How can I help you today?": "Comment puis-je vous aider aujourd'hui ?",
"Image Generation (Experimental)": "Génération d'image (Expérimental)",
"Image Generation Engine": "Moteur de génération d'image",
"Image Settings": "Paramètres d'image",
"Images": "Images",
"Import Chats": "Importer les chats",
"Import Documents Mapping": "Importer la correspondance des documents",
"Import Modelfiles": "Importer les fichiers de modèle",
"Import Prompts": "Importer les prompts",
"Include `--api` flag when running stable-diffusion-webui": "Inclure le drapeau `--api` lors de l'exécution de stable-diffusion-webui",
"Interface": "Interface",
"join our Discord for help.": "rejoignez notre Discord pour obtenir de l'aide.",
"JSON": "JSON",
"JWT Expiration": "Expiration JWT",
"JWT Token": "Jeton JWT",
"Keep Alive": "Garder en vie",
"Keyboard shortcuts": "Raccourcis clavier",
"Language": "Langue",
"Light": "Clair",
"Listening...": "Écoute...",
"LLMs can make mistakes. Verify important information.": "Les LLMs peuvent faire des erreurs. Vérifiez les informations importantes.",
"Made by OpenWebUI Community": "Réalisé par la communauté OpenWebUI",
"Make sure to enclose them with": "Assurez-vous de les entourer avec",
"Manage LiteLLM Models": "Gérer les modèles LiteLLM",
"Manage Models": "Gérer les modèles",
"Manage Ollama Models": "Gérer les modèles Ollama",
"Max Tokens": "Tokens maximaux",
"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Un maximum de 3 modèles peut être téléchargé simultanément. Veuillez réessayer plus tard.",
"Mirostat": "Mirostat",
"Mirostat Eta": "Mirostat Eta",
"Mirostat Tau": "Mirostat Tau",
"MMMM DD, YYYY": "MMMM DD, YYYY",
"Model '{{modelName}}' has been successfully downloaded.": "Le modèle '{{modelName}}' a été téléchargé avec succès.",
"Model '{{modelTag}}' is already in queue for downloading.": "Le modèle '{{modelTag}}' est déjà dans la file d'attente pour le téléchargement.",
"Model {{modelId}} not found": "Modèle {{modelId}} non trouvé",
"Model {{modelName}} already exists.": "Le modèle {{modelName}} existe déjà.",
"Model Name": "Nom du modèle",
"Model not selected": "Modèle non sélectionné",
"Model Tag Name": "Nom de tag du modèle",
"Model Whitelisting": "Liste blanche de modèle",
"Model(s) Whitelisted": "Modèle(s) sur liste blanche",
"Modelfile": "Fichier de modèle",
"Modelfile Advanced Settings": "Paramètres avancés du fichier de modèle",
"Modelfile Content": "Contenu du fichier de modèle",
"Modelfiles": "Fichiers de modèle",
"Models": "Modèles",
"My Documents": "Mes documents",
"My Modelfiles": "Mes fichiers de modèle",
"My Prompts": "Mes prompts",
"Name": "Nom",
"Name Tag": "Tag de nom",
"Name your modelfile": "Nommez votre fichier de modèle",
"New Chat": "Nouveau chat",
"New Password": "Nouveau mot de passe",
"Not sure what to add?": "Vous ne savez pas quoi ajouter ?",
"Not sure what to write? Switch to": "Vous ne savez pas quoi écrire ? Basculer vers",
"Off": "Désactivé",
"Okay, Let's Go!": "D'accord, allons-y !",
"Ollama Base URL": "URL de Base Ollama",
"Ollama Version": "Version Ollama",
"On": "Activé",
"Only": "Seulement",
"Only alphanumeric characters and hyphens are allowed in the command string.": "Seuls les caractères alphanumériques et les tirets sont autorisés dans la chaîne de commande.",
"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Oups ! Tenez bon ! Vos fichiers sont encore dans le four. Nous les cuisinons à la perfection. Soyez patient et nous vous informerons dès qu'ils seront prêts.",
"Oops! Looks like the URL is invalid. Please double-check and try again.": "Oops! Looks like the URL is invalid. Please double-check and try again.",
"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.",
"Open": "Ouvrir",
"Open AI": "Open AI",
"Open AI (Dall-E)": "Open AI (Dall-E)",
"Open new chat": "Ouvrir un nouveau chat",
"OpenAI API": "API OpenAI",
"OpenAI API Key": "Clé API OpenAI",
"OpenAI API Key is required.": "La clé API OpenAI est requise.",
"or": "ou",
"Parameters": "Paramètres",
"Password": "Mot de passe",
"PDF Extract Images (OCR)": "Extraction d'images PDF (OCR)",
"pending": "en attente",
"Permission denied when accessing microphone: {{error}}": "Permission refusée lors de l'accès au microphone : {{error}}",
"Playground": "Aire de jeu",
"Profile": "Profil",
"Prompt Content": "Contenu du prompt",
"Prompt suggestions": "Suggestions de prompt",
"Prompts": "Prompts",
"Pull a model from Ollama.com": "Tirer un modèle de Ollama.com",
"Pull Progress": "Progression du tirage",
"Query Params": "Paramètres de requête",
"RAG Template": "Modèle RAG",
"Raw Format": "Format brut",
"Record voice": "Enregistrer la voix",
"Redirecting you to OpenWebUI Community": "Vous redirige vers la communauté OpenWebUI",
"Release Notes": "Notes de version",
"Repeat Last N": "Répéter les derniers N",
"Repeat Penalty": "Pénalité de répétition",
"Request Mode": "Mode de demande",
"Reset Vector Storage": "Réinitialiser le stockage de vecteur",
"Response AutoCopy to Clipboard": "Copie automatique de la réponse dans le presse-papiers",
"Role": "Rôle",
"Rosé Pine": "Pin Rosé",
"Rosé Pine Dawn": "Aube Pin Rosé",
"Save": "Enregistrer",
"Save & Create": "Enregistrer & Créer",
"Save & Submit": "Enregistrer & Soumettre",
"Save & Update": "Enregistrer & Mettre à jour",
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "La sauvegarde des chat directement dans le stockage de votre navigateur n'est plus prise en charge. Veuillez prendre un moment pour télécharger et supprimer vos journaux de chat en cliquant sur le bouton ci-dessous. Ne vous inquiétez pas, vous pouvez facilement importer vos sauvegardes de chat via",
"Scan": "Scanner",
"Scan complete!": "Scan terminé !",
"Scan for documents from {{path}}": "Scanner des documents depuis {{path}}",
"Search": "Recherche",
"Search Documents": "Rechercher des documents",
"Search Prompts": "Rechercher des prompts",
"See readme.md for instructions": "Voir readme.md pour les instructions",
"See what's new": "Voir les nouveautés",
"Seed": "Graine",
"Select a mode": "Sélectionnez un mode",
"Select a model": "Sélectionner un modèle",
"Select an Ollama instance": "Sélectionner une instance Ollama",
"Send a Message": "Envoyer un message",
"Send message": "Envoyer un message",
"Server connection verified": "Connexion au serveur vérifiée",
"Set as default": "Définir par défaut",
"Set Default Model": "Définir le modèle par défaut",
"Set Image Size": "Définir la taille de l'image",
"Set Steps": "Définir les étapes",
"Set Title Auto-Generation Model": "Définir le modèle de génération automatique de titre",
"Set Voice": "Définir la voix",
"Settings": "Paramètres",
"Settings saved successfully!": "Paramètres enregistrés avec succès !",
"Share to OpenWebUI Community": "Partager avec la communauté OpenWebUI",
"short-summary": "résumé court",
"Show": "Montrer",
"Show Additional Params": "Afficher les paramètres supplémentaires",
"Show shortcuts": "Afficher les raccourcis",
"sidebar": "barre latérale",
"Sign in": "Se connecter",
"Sign Out": "Se déconnecter",
"Sign up": "S'inscrire",
"Speech recognition error: {{error}}": "Erreur de reconnaissance vocale : {{error}}",
"Speech-to-Text Engine": "Moteur de reconnaissance vocale",
"SpeechRecognition API is not supported in this browser.": "L'API SpeechRecognition n'est pas prise en charge dans ce navigateur.",
"Stop Sequence": "Séquence d'arrêt",
"STT Settings": "Paramètres STT",
"Submit": "Soumettre",
"Success": "Succès",
"Successfully updated.": "Mis à jour avec succès.",
"Sync All": "Synchroniser tout",
"System": "Système",
"System Prompt": "Invite de système",
"Tags": "Tags",
"Temperature": "Température",
"Template": "Modèle",
"Text Completion": "Complétion de texte",
"Text-to-Speech Engine": "Moteur de synthèse vocale",
"Tfs Z": "Tfs Z",
"Theme": "Thème",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Cela garantit que vos précieuses conversations sont en sécurité dans votre base de données. Merci !",
"This setting does not sync across browsers or devices.": "Ce paramètre ne se synchronise pas entre les navigateurs ou les appareils.",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.",
"Title": "Titre",
"Title Auto-Generation": "Génération automatique de titre",
"Title Generation Prompt": "Prompt de génération de titre",
"to": "à",
"To access the available model names for downloading,": "Pour accéder aux noms de modèles disponibles pour le téléchargement,",
"To access the GGUF models available for downloading,": "Pour accéder aux modèles GGUF disponibles pour le téléchargement,",
"to chat input.": "à l'entrée du chat.",
"Toggle settings": "Basculer les paramètres",
"Toggle sidebar": "Basculer la barre latérale",
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Problèmes d'accès à Ollama ?",
"TTS Settings": "Paramètres TTS",
"Type Hugging Face Resolve (Download) URL": "Entrez l'URL de résolution (téléchargement) Hugging Face",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh ! Il y a eu un problème de connexion à {{provider}}.",
"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Type de fichier inconnu '{{file_type}}', mais accepté et traité comme du texte brut",
"Update password": "Mettre à jour le mot de passe",
"Upload a GGUF model": "Téléverser un modèle GGUF",
"Upload files": "Téléverser des fichiers",
"Upload Progress": "Progression du Téléversement",
"URL Mode": "Mode URL",
"Use '#' in the prompt input to load and select your documents.": "Utilisez '#' dans l'entrée du prompt pour charger et sélectionner vos documents.",
"Use Gravatar": "Utiliser Gravatar",
"user": "utilisateur",
"User Permissions": "Permissions d'utilisateur",
"Users": "Utilisateurs",
"Utilize": "Utiliser",
"Valid time units:": "Unités de temps valides :",
"variable": "variable",
"variable to have them replaced with clipboard content.": "variable pour les remplacer par le contenu du presse-papiers.",
"Version": "Version",
"Web": "Web",
"WebUI Add-ons": "Add-ons WebUI",
"WebUI Settings": "Paramètres WebUI",
"WebUI will make requests to": "WebUI effectuera des demandes à",
"What’s New in": "Quoi de neuf dans",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Lorsque l'historique est désactivé, les nouveaux chats sur ce navigateur n'apparaîtront pas dans votre historique sur aucun de vos appareils.",
"Whisper (Local)": "Whisper (Local)",
"Write a prompt suggestion (e.g. Who are you?)": "Écrivez un prompt (e.x. Qui est-tu ?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Ecrivez un résumé en 50 mots [sujet ou mot-clé]",
"You": "You",
"You're a helpful assistant.": "Vous êtes un assistant utile",
"You're now logged in.": "Vous êtes maintenant connecté."
}
+363
View File
@@ -0,0 +1,363 @@
{
"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' o '-1' per nessuna scadenza.",
"(Beta)": "(Beta)",
"(e.g. sh webui.sh --api)": "(ad esempio sh webui.sh --api)",
"(latest)": "(ultima)",
"{{modelName}} is thinking...": "{{modelName}} sta pensando...",
"{{webUIName}} Backend Required": "{{webUIName}} Backend richiesto",
"a user": "un utente",
"About": "Informazioni",
"Account": "Account",
"Action": "Azione",
"Add a model": "Aggiungi un modello",
"Add a model tag name": "Aggiungi un nome tag del modello",
"Add a short description about what this modelfile does": "Aggiungi una breve descrizione di ciò che fa questo file modello",
"Add a short title for this prompt": "Aggiungi un titolo breve per questo prompt",
"Add a tag": "Aggiungi un tag",
"Add Docs": "Aggiungi documenti",
"Add Files": "Aggiungi file",
"Add message": "Aggiungi messaggio",
"add tags": "aggiungi tag",
"Adjusting these settings will apply changes universally to all users.": "La modifica di queste impostazioni applicherà le modifiche universalmente a tutti gli utenti.",
"admin": "amministratore",
"Admin Panel": "Pannello di amministrazione",
"Admin Settings": "Impostazioni amministratore",
"Advanced Parameters": "Parametri avanzati",
"all": "tutti",
"All Users": "Tutti gli utenti",
"Allow": "Consenti",
"Allow Chat Deletion": "Consenti l'eliminazione della chat",
"alphanumeric characters and hyphens": "caratteri alfanumerici e trattini",
"Already have an account?": "Hai già un account?",
"an assistant": "un assistente",
"and": "e",
"API Base URL": "URL base API",
"API Key": "Chiave API",
"API RPM": "API RPM",
"are allowed - Activate this command by typing": "sono consentiti - Attiva questo comando digitando",
"Are you sure?": "Sei sicuro?",
"Audio": "Audio",
"Auto-playback response": "Riproduzione automatica della risposta",
"Auto-send input after 3 sec.": "Invio automatico dell'input dopo 3 secondi.",
"AUTOMATIC1111 Base URL": "URL base AUTOMATIC1111",
"AUTOMATIC1111 Base URL is required.": "L'URL base AUTOMATIC1111 è obbligatorio.",
"available!": "disponibile!",
"Back": "Indietro",
"Builder Mode": "Modalità costruttore",
"Cancel": "Annulla",
"Categories": "Categorie",
"Change Password": "Cambia password",
"Chat": "Chat",
"Chat History": "Cronologia chat",
"Chat History is off for this browser.": "La cronologia chat è disattivata per questo browser.",
"Chats": "Chat",
"Check Again": "Controlla di nuovo",
"Check for updates": "Controlla aggiornamenti",
"Checking for updates...": "Controllo aggiornamenti...",
"Choose a model before saving...": "Scegli un modello prima di salvare...",
"Chunk Overlap": "Sovrapposizione chunk",
"Chunk Params": "Parametri chunk",
"Chunk Size": "Dimensione chunk",
"Click here for help.": "Clicca qui per aiuto.",
"Click here to check other modelfiles.": "Clicca qui per controllare altri file modello.",
"Click here to select": "Clicca qui per selezionare",
"Click here to select documents.": "Clicca qui per selezionare i documenti.",
"click here.": "clicca qui.",
"Click on the user role button to change a user's role.": "Clicca sul pulsante del ruolo utente per modificare il ruolo di un utente.",
"Close": "Chiudi",
"Collection": "Collezione",
"Command": "Comando",
"Confirm Password": "Conferma password",
"Connections": "Connessioni",
"Content": "Contenuto",
"Context Length": "Lunghezza contesto",
"Conversation Mode": "Modalità conversazione",
"Copy last code block": "Copia ultimo blocco di codice",
"Copy last response": "Copia ultima risposta",
"Copying to clipboard was successful!": "Copia negli appunti riuscita!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Crea una frase concisa di 3-5 parole come intestazione per la seguente query, aderendo rigorosamente al limite di 3-5 parole ed evitando l'uso della parola 'titolo':",
"Create a modelfile": "Crea un file modello",
"Create Account": "Crea account",
"Created at": "Creato il",
"Created by": "Creato da",
"Current Model": "Modello corrente",
"Current Password": "Password corrente",
"Custom": "Personalizzato",
"Customize Ollama models for a specific purpose": "Personalizza i modelli Ollama per uno scopo specifico",
"Dark": "Scuro",
"Database": "Database",
"DD/MM/YYYY HH:mm": "DD/MM/YYYY HH:mm",
"Default": "Predefinito",
"Default (Automatic1111)": "Predefinito (Automatic1111)",
"Default (Web API)": "Predefinito (API Web)",
"Default model updated": "Modello predefinito aggiornato",
"Default Prompt Suggestions": "Suggerimenti prompt predefiniti",
"Default User Role": "Ruolo utente predefinito",
"delete": "elimina",
"Delete a model": "Elimina un modello",
"Delete chat": "Elimina chat",
"Delete Chats": "Elimina chat",
"Deleted {{deleteModelTag}}": "Eliminato {{deleteModelTag}}",
"Deleted {tagName}": "Eliminato {tagName}",
"Description": "Descrizione",
"Desktop Notifications": "Notifiche desktop",
"Disabled": "Disabilitato",
"Discover a modelfile": "Scopri un file modello",
"Discover a prompt": "Scopri un prompt",
"Discover, download, and explore custom prompts": "Scopri, scarica ed esplora prompt personalizzati",
"Discover, download, and explore model presets": "Scopri, scarica ed esplora i preset del modello",
"Display the username instead of You in the Chat": "Visualizza il nome utente invece di Tu nella chat",
"Document": "Documento",
"Document Settings": "Impostazioni documento",
"Documents": "Documenti",
"does not make any external connections, and your data stays securely on your locally hosted server.": "non effettua connessioni esterne e i tuoi dati rimangono al sicuro sul tuo server ospitato localmente.",
"Don't Allow": "Non consentire",
"Don't have an account?": "Non hai un account?",
"Download as a File": "Scarica come file",
"Download Database": "Scarica database",
"Drop any files here to add to the conversation": "Trascina qui i file da aggiungere alla conversazione",
"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "ad esempio '30s','10m'. Le unità di tempo valide sono 's', 'm', 'h'.",
"Edit Doc": "Modifica documento",
"Edit User": "Modifica utente",
"Email": "Email",
"Enable Chat History": "Abilita cronologia chat",
"Enable New Sign Ups": "Abilita nuove iscrizioni",
"Enabled": "Abilitato",
"Enter {{role}} message here": "Inserisci il messaggio per {{role}} qui",
"Enter API Key": "Inserisci la chiave API",
"Enter Chunk Overlap": "Inserisci la sovrapposizione chunk",
"Enter Chunk Size": "Inserisci la dimensione chunk",
"Enter Image Size (e.g. 512x512)": "Inserisci la dimensione dell'immagine (ad esempio 512x512)",
"Enter LiteLLM API Base URL (litellm_params.api_base)": "Inserisci l'URL base dell'API LiteLLM (litellm_params.api_base)",
"Enter LiteLLM API Key (litellm_params.api_key)": "Inserisci la chiave API LiteLLM (litellm_params.api_key)",
"Enter LiteLLM API RPM (litellm_params.rpm)": "Inserisci LiteLLM API RPM (litellm_params.rpm)",
"Enter LiteLLM Model (litellm_params.model)": "Inserisci il modello LiteLLM (litellm_params.model)",
"Enter Max Tokens (litellm_params.max_tokens)": "Inserisci Max Tokens (litellm_params.max_tokens)",
"Enter model tag (e.g. {{modelTag}})": "Inserisci il tag del modello (ad esempio {{modelTag}})",
"Enter Number of Steps (e.g. 50)": "Inserisci il numero di passaggi (ad esempio 50)",
"Enter stop sequence": "Inserisci la sequenza di arresto",
"Enter Top K": "Inserisci Top K",
"Enter URL (e.g. http://127.0.0.1:7860/)": "Inserisci URL (ad esempio http://127.0.0.1:7860/)",
"Enter Your Email": "Inserisci la tua email",
"Enter Your Full Name": "Inserisci il tuo nome completo",
"Enter Your Password": "Inserisci la tua password",
"Experimental": "Sperimentale",
"Export All Chats (All Users)": "Esporta tutte le chat (tutti gli utenti)",
"Export Chats": "Esporta chat",
"Export Documents Mapping": "Esporta mappatura documenti",
"Export Modelfiles": "Esporta file modello",
"Export Prompts": "Esporta prompt",
"Failed to read clipboard contents": "Impossibile leggere il contenuto degli appunti",
"File Mode": "Modalità file",
"File not found.": "File non trovato.",
"Focus chat input": "Metti a fuoco l'input della chat",
"Format your variables using square brackets like this:": "Formatta le tue variabili usando parentesi quadre come questa:",
"From (Base Model)": "Da (modello base)",
"Full Screen Mode": "Modalità a schermo intero",
"General": "Generale",
"General Settings": "Impostazioni generali",
"Hello, {{name}}": "Ciao, {{name}}",
"Hide": "Nascondi",
"Hide Additional Params": "Nascondi parametri aggiuntivi",
"How can I help you today?": "Come posso aiutarti oggi?",
"Image Generation (Experimental)": "Generazione di immagini (sperimentale)",
"Image Generation Engine": "Motore di generazione immagini",
"Image Settings": "Impostazioni immagine",
"Images": "Immagini",
"Import Chats": "Importa chat",
"Import Documents Mapping": "Importa mappatura documenti",
"Import Modelfiles": "Importa file modello",
"Import Prompts": "Importa prompt",
"Include --api flag when running stable-diffusion-webui": "Includi il flag --api quando esegui stable-diffusion-webui",
"Interface": "Interfaccia",
"join our Discord for help.": "unisciti al nostro Discord per ricevere aiuto.",
"JSON": "JSON",
"JWT Expiration": "Scadenza JWT",
"JWT Token": "Token JWT",
"Keep Alive": "Mantieni attivo",
"Keyboard shortcuts": "Scorciatoie da tastiera",
"Language": "Lingua",
"Light": "Chiaro",
"Listening...": "Ascolto...",
"LLMs can make mistakes. Verify important information.": "Gli LLM possono commettere errori. Verifica le informazioni importanti.",
"Made by OpenWebUI Community": "Realizzato dalla comunità OpenWebUI",
"Make sure to enclose them with": "Assicurati di racchiuderli con",
"Manage LiteLLM Models": "Gestisci modelli LiteLLM",
"Manage Models": "Gestisci modelli",
"Manage Ollama Models": "Gestisci modelli Ollama",
"Max Tokens": "Max token",
"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "È possibile scaricare un massimo di 3 modelli contemporaneamente. Riprova più tardi.",
"Mirostat": "Mirostat",
"Mirostat Eta": "Mirostat Eta",
"Mirostat Tau": "Mirostat Tau",
"MMMM DD, YYYY": "MMMM DD, YYYY",
"Model '{{modelName}}' has been successfully downloaded.": "Il modello '{{modelName}}' è stato scaricato con successo.",
"Model '{{modelTag}}' is already in queue for downloading.": "Il modello '{{modelTag}}' è già in coda per il download.",
"Model {{modelId}} not found": "Modello {{modelId}} non trovato",
"Model {{modelName}} already exists.": "Il modello {{modelName}} esiste già.",
"Model Name": "Nome modello",
"Model not selected": "Modello non selezionato",
"Model Tag Name": "Nome tag del modello",
"Model Whitelisting": "Whitelisting del modello",
"Model(s) Whitelisted": "Modello/i in whitelist",
"Modelfile": "File modello",
"Modelfile Advanced Settings": "Impostazioni avanzate del file modello",
"Modelfile Content": "Contenuto del file modello",
"Modelfiles": "File modello",
"Models": "Modelli",
"My Documents": "I miei documenti",
"My Modelfiles": "I miei file modello",
"My Prompts": "I miei prompt",
"Name": "Nome",
"Name Tag": "Nome tag",
"Name your modelfile": "Assegna un nome al tuo file modello",
"New Chat": "Nuova chat",
"New Password": "Nuova password",
"Not sure what to add?": "Non sei sicuro di cosa aggiungere?",
"Not sure what to write? Switch to": "Non sei sicuro di cosa scrivere? Passa a",
"Off": "Disattivato",
"Okay, Let's Go!": "Ok, andiamo!",
"Ollama Base URL": "URL base Ollama",
"Ollama Version": "Versione Ollama",
"On": "Attivato",
"Only": "Solo",
"Only alphanumeric characters and hyphens are allowed in the command string.": "Nella stringa di comando sono consentiti solo caratteri alfanumerici e trattini.",
"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Ops! Aspetta! I tuoi file sono ancora in fase di elaborazione. Li stiamo cucinando alla perfezione. Per favore sii paziente e ti faremo sapere quando saranno pronti.",
"Oops! Looks like the URL is invalid. Please double-check and try again.": "Ops! Sembra che l'URL non sia valido. Si prega di ricontrollare e riprovare.",
"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Ops! Stai utilizzando un metodo non supportato (solo frontend). Si prega di servire la WebUI dal backend.",
"Open": "Apri",
"Open AI": "Open AI",
"Open AI (Dall-E)": "Open AI (Dall-E)",
"Open new chat": "Apri nuova chat",
"OpenAI API": "API OpenAI",
"OpenAI API Key": "Chiave API OpenAI",
"OpenAI API Key is required.": "La chiave API OpenAI è obbligatoria.",
"or": "o",
"Parameters": "Parametri",
"Password": "Password",
"PDF Extract Images (OCR)": "Estrazione immagini PDF (OCR)",
"pending": "in sospeso",
"Permission denied when accessing microphone: {{error}}": "Autorizzazione negata durante l'accesso al microfono: {{error}}",
"Playground": "Playground",
"Profile": "Profilo",
"Prompt Content": "Contenuto del prompt",
"Prompt suggestions": "Suggerimenti prompt",
"Prompts": "Prompt",
"Pull a model from Ollama.com": "Estrai un modello da Ollama.com",
"Pull Progress": "Avanzamento estrazione",
"Query Params": "Parametri query",
"RAG Template": "Modello RAG",
"Raw Format": "Formato raw",
"Record voice": "Registra voce",
"Redirecting you to OpenWebUI Community": "Reindirizzamento alla comunità OpenWebUI",
"Release Notes": "Note di rilascio",
"Repeat Last N": "Ripeti ultimi N",
"Repeat Penalty": "Penalità di ripetizione",
"Request Mode": "Modalità richiesta",
"Reset Vector Storage": "Reimposta archivio vettoriale",
"Response AutoCopy to Clipboard": "Copia automatica della risposta negli appunti",
"Role": "Ruolo",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"Save": "Salva",
"Save & Create": "Salva e crea",
"Save & Submit": "Salva e invia",
"Save & Update": "Salva e aggiorna",
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Il salvataggio dei registri della chat direttamente nell'archivio del browser non è più supportato. Si prega di dedicare un momento per scaricare ed eliminare i registri della chat facendo clic sul pulsante in basso. Non preoccuparti, puoi facilmente reimportare i registri della chat nel backend tramite",
"Scan": "Scansione",
"Scan complete!": "Scansione completata!",
"Scan for documents from {{path}}": "Cerca documenti da {{path}}",
"Search": "Cerca",
"Search Documents": "Cerca documenti",
"Search Prompts": "Cerca prompt",
"See readme.md for instructions": "Vedi readme.md per le istruzioni",
"See what's new": "Guarda le novità",
"Seed": "Seme",
"Select a mode": "Seleziona una modalità",
"Select a model": "Seleziona un modello",
"Select an Ollama instance": "Seleziona un'istanza Ollama",
"Send a Message": "Invia un messaggio",
"Send message": "Invia messaggio",
"Server connection verified": "Connessione al server verificata",
"Set as default": "Imposta come predefinito",
"Set Default Model": "Imposta modello predefinito",
"Set Image Size": "Imposta dimensione immagine",
"Set Steps": "Imposta passaggi",
"Set Title Auto-Generation Model": "Imposta modello di generazione automatica del titolo",
"Set Voice": "Imposta voce",
"Settings": "Impostazioni",
"Settings saved successfully!": "Impostazioni salvate con successo!",
"Share to OpenWebUI Community": "Condividi con la comunità OpenWebUI",
"short-summary": "riassunto-breve",
"Show": "Mostra",
"Show Additional Params": "Mostra parametri aggiuntivi",
"Show shortcuts": "Mostra",
"sidebar": "barra laterale",
"Sign in": "Accedi",
"Sign Out": "Esci",
"Sign up": "Registrati",
"Speech recognition error: {{error}}": "Errore di riconoscimento vocale: {{error}}",
"Speech-to-Text Engine": "Motore da voce a testo",
"SpeechRecognition API is not supported in this browser.": "L'API SpeechRecognition non è supportata in questo browser.",
"Stop Sequence": "Sequenza di arresto",
"STT Settings": "Impostazioni STT",
"Submit": "Invia",
"Success": "Successo",
"Successfully updated.": "Aggiornato con successo.",
"Sync All": "Sincronizza tutto",
"System": "Sistema",
"System Prompt": "Prompt di sistema",
"Tags": "Tag",
"Temperature": "Temperatura",
"Template": "Modello",
"Text Completion": "Completamento del testo",
"Text-to-Speech Engine": "Motore da testo a voce",
"Tfs Z": "Tfs Z",
"Theme": "Tema",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Ciò garantisce che le tue preziose conversazioni siano salvate in modo sicuro nel tuo database backend. Grazie!",
"This setting does not sync across browsers or devices.": "Questa impostazione non si sincronizza tra browser o dispositivi.",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Suggerimento: aggiorna più slot di variabili consecutivamente premendo il tasto tab nell'input della chat dopo ogni sostituzione.",
"Title": "Titolo",
"Title Auto-Generation": "Generazione automatica del titolo",
"Title Generation Prompt": "Prompt di generazione del titolo",
"to": "a",
"To access the available model names for downloading,": "Per accedere ai nomi dei modelli disponibili per il download,",
"To access the GGUF models available for downloading,": "Per accedere ai modelli GGUF disponibili per il download,",
"to chat input.": "all'input della chat.",
"Toggle settings": "Attiva/disattiva impostazioni",
"Toggle sidebar": "Attiva/disattiva barra laterale",
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Problemi di accesso a Ollama?",
"TTS Settings": "Impostazioni TTS",
"Type Hugging Face Resolve (Download) URL": "Digita l'URL di Hugging Face Resolve (Download)",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Si è verificato un problema durante la connessione a {{provider}}.",
"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Tipo di file sconosciuto '{{file_type}}', ma accettato e trattato come testo normale",
"Update password": "Aggiorna password",
"Upload a GGUF model": "Carica un modello GGUF",
"Upload files": "Carica file",
"Upload Progress": "Avanzamento caricamento",
"URL Mode": "Modalità URL",
"Use '#' in the prompt input to load and select your documents.": "Usa '#' nell'input del prompt per caricare e selezionare i tuoi documenti.",
"Use Gravatar": "Usa Gravatar",
"user": "utente",
"User Permissions": "Autorizzazioni utente",
"Users": "Utenti",
"Utilize": "Utilizza",
"Valid time units:": "Unità di tempo valide:",
"variable": "variabile",
"variable to have them replaced with clipboard content.": "variabile per farli sostituire con il contenuto degli appunti.",
"Version": "Versione",
"Web": "Web",
"WebUI Add-ons": "Componenti aggiuntivi WebUI",
"WebUI Settings": "Impostazioni WebUI",
"WebUI will make requests to": "WebUI effettuerà richieste a",
"What’s New in": "Novità in",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Quando la cronologia è disattivata, le nuove chat su questo browser non verranno visualizzate nella cronologia su nessuno dei tuoi dispositivi.",
"Whisper (Local)": "Whisper (locale)",
"Write a prompt suggestion (e.g. Who are you?)": "Scrivi un suggerimento per il prompt (ad esempio Chi sei?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Scrivi un riassunto in 50 parole che riassume [argomento o parola chiave].",
"You": "Tu",
"You're a helpful assistant.": "Sei un assistente utile.",
"You're now logged in.": "Ora hai effettuato l'accesso."
}
+363
View File
@@ -0,0 +1,363 @@
{
"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'秒', '分', '時間', '日', '週' または '-1' で無期限。",
"(Beta)": "(ベータ版)",
"(e.g. sh webui.sh --api)": "(例: sh webui.sh --api)",
"(latest)": "(最新)",
"{{modelName}} is thinking...": "{{modelName}} は思考中です...",
"{{webUIName}} Backend Required": "{{webUIName}} バックエンドが必要です",
"a user": "ユーザー",
"About": "概要",
"Account": "アカウント",
"Action": "アクション",
"Add a model": "モデルを追加",
"Add a model tag name": "モデルタグ名を追加",
"Add a short description about what this modelfile does": "このモデルファイルの機能に関する簡単な説明を追加",
"Add a short title for this prompt": "このプロンプトの短いタイトルを追加",
"Add a tag": "タグを追加",
"Add Docs": "ドキュメントを追加",
"Add Files": "ファイルを追加",
"Add message": "メッセージを追加",
"add tags": "タグを追加",
"Adjusting these settings will apply changes universally to all users.": "これらの設定を調整すると、すべてのユーザーに普遍的に変更が適用されます。",
"admin": "管理者",
"Admin Panel": "管理者パネル",
"Admin Settings": "管理者設定",
"Advanced Parameters": "詳細パラメーター",
"all": "すべて",
"All Users": "すべてのユーザー",
"Allow": "許可",
"Allow Chat Deletion": "チャットの削除を許可",
"alphanumeric characters and hyphens": "英数字とハイフン",
"Already have an account?": "すでにアカウントをお持ちですか?",
"an assistant": "アシスタント",
"and": "および",
"API Base URL": "API ベース URL",
"API Key": "API キー",
"API RPM": "API RPM",
"are allowed - Activate this command by typing": "が許可されています - 次のように入力してこのコマンドをアクティブ化します",
"Are you sure?": "よろしいですか?",
"Audio": "オーディオ",
"Auto-playback response": "応答の自動再生",
"Auto-send input after 3 sec.": "3 秒後に自動的に出力を送信",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 ベース URL",
"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 ベース URL が必要です。",
"available!": "利用可能!",
"Back": "戻る",
"Builder Mode": "ビルダーモード",
"Cancel": "キャンセル",
"Categories": "カテゴリ",
"Change Password": "パスワードを変更",
"Chat": "チャット",
"Chat History": "チャット履歴",
"Chat History is off for this browser.": "このブラウザではチャット履歴が無効になっています。",
"Chats": "チャット",
"Check Again": "再確認",
"Check for updates": "アップデートを確認",
"Checking for updates...": "アップデートを確認しています...",
"Choose a model before saving...": "保存する前にモデルを選択してください...",
"Chunk Overlap": "チャンクオーバーラップ",
"Chunk Params": "チャンクパラメーター",
"Chunk Size": "チャンクサイズ",
"Click here for help.": "ヘルプについてはここをクリックしてください。",
"Click here to check other modelfiles.": "他のモデルファイルを確認するにはここをクリックしてください。",
"Click here to select": "選択するにはここをクリックしてください",
"Click here to select documents.": "ドキュメントを選択するにはここをクリックしてください。",
"click here.": "ここをクリックしてください。",
"Click on the user role button to change a user's role.": "ユーザーの役割を変更するには、ユーザー役割ボタンをクリックしてください。",
"Close": "閉じる",
"Collection": "コレクション",
"Command": "コマンド",
"Confirm Password": "パスワードを確認",
"Connections": "接続",
"Content": "コンテンツ",
"Context Length": "コンテキストの長さ",
"Conversation Mode": "会話モード",
"Copy last code block": "最後のコードブロックをコピー",
"Copy last response": "最後の応答をコピー",
"Copying to clipboard was successful!": "クリップボードへのコピーが成功しました!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "次のクエリの見出しとして、3〜5語の簡潔なフレーズを作成してください。3〜5語の制限を厳守し、「タイトル」という単語の使用を避けてください。",
"Create a modelfile": "モデルファイルを作成",
"Create Account": "アカウントを作成",
"Created at": "作成日時",
"Created by": "作成者",
"Current Model": "現在のモデル",
"Current Password": "現在のパスワード",
"Custom": "カスタム",
"Customize Ollama models for a specific purpose": "特定の目的に合わせて Ollama モデルをカスタマイズ",
"Dark": "ダーク",
"Database": "データベース",
"DD/MM/YYYY HH:mm": "DD/MM/YYYY HH:mm",
"Default": "デフォルト",
"Default (Automatic1111)": "デフォルト (Automatic1111)",
"Default (Web API)": "デフォルト (Web API)",
"Default model updated": "デフォルトモデルが更新されました",
"Default Prompt Suggestions": "デフォルトのプロンプトの提案",
"Default User Role": "デフォルトのユーザー役割",
"delete": "削除",
"Delete a model": "モデルを削除",
"Delete chat": "チャットを削除",
"Delete Chats": "チャットを削除",
"Deleted {{deleteModelTag}}": "{{deleteModelTag}} を削除しました",
"Deleted {tagName}": "{tagName} を削除しました",
"Description": "説明",
"Desktop Notifications": "デスクトップ通知",
"Disabled": "無効",
"Discover a modelfile": "モデルファイルを見つける",
"Discover a prompt": "プロンプトを見つける",
"Discover, download, and explore custom prompts": "カスタムプロンプトを見つけて、ダウンロードして、探索",
"Discover, download, and explore model presets": "モデルプリセットを見つけて、ダウンロードして、探索",
"Display the username instead of You in the Chat": "チャットで「あなた」の代わりにユーザー名を表示",
"Document": "ドキュメント",
"Document Settings": "ドキュメント設定",
"Documents": "ドキュメント",
"does not make any external connections, and your data stays securely on your locally hosted server.": "外部接続を行わず、データはローカルでホストされているサーバー上に安全に保持されます。",
"Don't Allow": "許可しない",
"Don't have an account?": "アカウントをお持ちではありませんか?",
"Download as a File": "ファイルとしてダウンロード",
"Download Database": "データベースをダウンロード",
"Drop any files here to add to the conversation": "会話を追加するには、ここにファイルをドロップしてください",
"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "例: '30秒'、'10分'。有効な時間単位は '秒'、'分'、'時間' です。",
"Edit Doc": "ドキュメントを編集",
"Edit User": "ユーザーを編集",
"Email": "メールアドレス",
"Enable Chat History": "チャット履歴を有効化",
"Enable New Sign Ups": "新規登録を有効化",
"Enabled": "有効",
"Enter {{role}} message here": "{{role}} メッセージをここに入力してください",
"Enter API Key": "API キーを入力してください",
"Enter Chunk Overlap": "チャンクオーバーラップを入力してください",
"Enter Chunk Size": "チャンクサイズを入力してください",
"Enter Image Size (e.g. 512x512)": "画像サイズを入力してください (例: 512x512)",
"Enter LiteLLM API Base URL (litellm_params.api_base)": "LiteLLM API ベース URL を入力してください (litellm_params.api_base)",
"Enter LiteLLM API Key (litellm_params.api_key)": "LiteLLM API キーを入力してください (litellm_params.api_key)",
"Enter LiteLLM API RPM (litellm_params.rpm)": "LiteLLM API RPM を入力してください (litellm_params.rpm)",
"Enter LiteLLM Model (litellm_params.model)": "LiteLLM モデルを入力してください (litellm_params.model)",
"Enter Max Tokens (litellm_params.max_tokens)": "最大トークン数を入力してください (litellm_params.max_tokens)",
"Enter model tag (e.g. {{modelTag}})": "モデルタグを入力してください (例: {{modelTag}})",
"Enter Number of Steps (e.g. 50)": "ステップ数を入力してください (例: 50)",
"Enter stop sequence": "ストップシーケンスを入力してください",
"Enter Top K": "トップ K を入力してください",
"Enter URL (e.g. http://127.0.0.1:7860/)": "URL を入力してください (例: http://127.0.0.1:7860/)",
"Enter Your Email": "メールアドレスを入力してください",
"Enter Your Full Name": "フルネームを入力してください",
"Enter Your Password": "パスワードを入力してください",
"Experimental": "実験的",
"Export All Chats (All Users)": "すべてのチャットをエクスポート (すべてのユーザー)",
"Export Chats": "チャットをエクスポート",
"Export Documents Mapping": "ドキュメントマッピングをエクスポート",
"Export Modelfiles": "モデルファイルをエクスポート",
"Export Prompts": "プロンプトをエクスポート",
"Failed to read clipboard contents": "クリップボードの内容を読み取れませんでした",
"File Mode": "ファイルモード",
"File not found.": "ファイルが見つかりません。",
"Focus chat input": "チャット入力をフォーカス",
"Format your variables using square brackets like this:": "次のように角括弧を使用して変数をフォーマットします。",
"From (Base Model)": "From (ベースモデル)",
"Full Screen Mode": "フルスクリーンモード",
"General": "一般",
"General Settings": "一般設定",
"Hello, {{name}}": "こんにちは、{{name}} さん",
"Hide": "非表示",
"Hide Additional Params": "追加パラメーターを非表示",
"How can I help you today?": "今日はどのようにお手伝いしましょうか?",
"Image Generation (Experimental)": "画像生成 (実験的)",
"Image Generation Engine": "画像生成エンジン",
"Image Settings": "画像設定",
"Images": "画像",
"Import Chats": "チャットをインポート",
"Import Documents Mapping": "ドキュメントマッピングをインポート",
"Import Modelfiles": "モデルファイルをインポート",
"Import Prompts": "プロンプトをインポート",
"Include --api flag when running stable-diffusion-webui": "stable-diffusion-webui を実行するときに --api フラグを含める",
"Interface": "インターフェース",
"join our Discord for help.": "ヘルプについては、Discord に参加してください。",
"JSON": "JSON",
"JWT Expiration": "JWT 有効期限",
"JWT Token": "JWT トークン",
"Keep Alive": "キープアライブ",
"Keyboard shortcuts": "キーボードショートカット",
"Language": "言語",
"Light": "ライト",
"Listening...": "聞いています...",
"LLMs can make mistakes. Verify important information.": "LLM は間違いを犯す可能性があります。重要な情報を検証してください。",
"Made by OpenWebUI Community": "OpenWebUI コミュニティによって作成",
"Make sure to enclose them with": "必ず次で囲んでください",
"Manage LiteLLM Models": "LiteLLM モデルを管理",
"Manage Models": "モデルを管理",
"Manage Ollama Models": "Ollama モデルを管理",
"Max Tokens": "最大トークン数",
"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "同時にダウンロードできるモデルは最大 3 つです。後でもう一度お試しください。",
"Mirostat": "ミロスタット",
"Mirostat Eta": "ミロスタット Eta",
"Mirostat Tau": "ミロスタット Tau",
"MMMM DD, YYYY": "MMMM DD, YYYY",
"Model '{{modelName}}' has been successfully downloaded.": "モデル '{{modelName}}' が正常にダウンロードされました。",
"Model '{{modelTag}}' is already in queue for downloading.": "モデル '{{modelTag}}' はすでにダウンロード待ち行列に入っています。",
"Model {{modelId}} not found": "モデル {{modelId}} が見つかりません",
"Model {{modelName}} already exists.": "モデル {{modelName}} はすでに存在します。",
"Model Name": "モデル名",
"Model not selected": "モデルが選択されていません",
"Model Tag Name": "モデルタグ名",
"Model Whitelisting": "モデルホワイトリスト",
"Model(s) Whitelisted": "ホワイトリストに登録されたモデル",
"Modelfile": "モデルファイル",
"Modelfile Advanced Settings": "モデルファイルの詳細設定",
"Modelfile Content": "モデルファイルの内容",
"Modelfiles": "モデルファイル",
"Models": "モデル",
"My Documents": "マイ ドキュメント",
"My Modelfiles": "マイ モデルファイル",
"My Prompts": "マイ プロンプト",
"Name": "名前",
"Name Tag": "名前タグ",
"Name your modelfile": "モデルファイルに名前を付ける",
"New Chat": "新しいチャット",
"New Password": "新しいパスワード",
"Not sure what to add?": "何を追加すればよいかわからない?",
"Not sure what to write? Switch to": "何を書けばよいかわからない? 次に切り替える",
"Off": "オフ",
"Okay, Let's Go!": "OK、始めましょう!",
"Ollama Base URL": "Ollama ベース URL",
"Ollama Version": "Ollama バージョン",
"On": "オン",
"Only": "のみ",
"Only alphanumeric characters and hyphens are allowed in the command string.": "コマンド文字列には英数字とハイフンのみが許可されています。",
"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "おっと! しばらくお待ちください! ファイルはまだ処理中です。完璧に仕上げていますので、しばらくお待ちください。準備ができたらお知らせします。",
"Oops! Looks like the URL is invalid. Please double-check and try again.": "おっと! URL が無効なようです。もう一度確認してやり直してください。",
"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "おっと! サポートされていない方法 (フロントエンドのみ) を使用しています。バックエンドから WebUI を提供してください。",
"Open": "開く",
"Open AI": "Open AI",
"Open AI (Dall-E)": "Open AI (Dall-E)",
"Open new chat": "新しいチャットを開く",
"OpenAI API": "OpenAI API",
"OpenAI API Key": "OpenAI API キー",
"OpenAI API Key is required.": "OpenAI API キーが必要です。",
"or": "または",
"Parameters": "パラメーター",
"Password": "パスワード",
"PDF Extract Images (OCR)": "PDF 画像抽出 (OCR)",
"pending": "保留中",
"Permission denied when accessing microphone: {{error}}": "マイクへのアクセス時に権限が拒否されました: {{error}}",
"Playground": "プレイグラウンド",
"Profile": "プロフィール",
"Prompt Content": "プロンプトの内容",
"Prompt suggestions": "プロンプトの提案",
"Prompts": "プロンプト",
"Pull a model from Ollama.com": "Ollama.com からモデルをプル",
"Pull Progress": "プルの進行状況",
"Query Params": "クエリパラメーター",
"RAG Template": "RAG テンプレート",
"Raw Format": "Raw 形式",
"Record voice": "音声を録音",
"Redirecting you to OpenWebUI Community": "OpenWebUI コミュニティにリダイレクトしています",
"Release Notes": "リリースノート",
"Repeat Last N": "最後の N を繰り返す",
"Repeat Penalty": "繰り返しペナルティ",
"Request Mode": "リクエストモード",
"Reset Vector Storage": "ベクトルストレージをリセット",
"Response AutoCopy to Clipboard": "クリップボードへの応答の自動コピー",
"Role": "役割",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"Save": "保存",
"Save & Create": "保存して作成",
"Save & Submit": "保存して送信",
"Save & Update": "保存して更新",
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "チャットログをブラウザのストレージに直接保存する機能はサポートされなくなりました。下のボタンをクリックして、チャットログをダウンロードして削除してください。ご心配なく。チャットログは、次の方法でバックエンドに簡単に再インポートできます。",
"Scan": "スキャン",
"Scan complete!": "スキャン完了!",
"Scan for documents from {{path}}": "{{path}} からドキュメントをスキャン",
"Search": "検索",
"Search Documents": "ドキュメントを検索",
"Search Prompts": "プロンプトを検索",
"See readme.md for instructions": "手順については readme.md を参照してください",
"See what's new": "新機能を見る",
"Seed": "シード",
"Select a mode": "モードを選択",
"Select a model": "モデルを選択",
"Select an Ollama instance": "Ollama インスタンスを選択",
"Send a Message": "メッセージを送信",
"Send message": "メッセージを送信",
"Server connection verified": "サーバー接続が確認されました",
"Set as default": "デフォルトに設定",
"Set Default Model": "デフォルトモデルを設定",
"Set Image Size": "画像サイズを設定",
"Set Steps": "ステップを設定",
"Set Title Auto-Generation Model": "タイトル自動生成モデルを設定",
"Set Voice": "音声を設定",
"Settings": "設定",
"Settings saved successfully!": "設定が正常に保存されました!",
"Share to OpenWebUI Community": "OpenWebUI コミュニティに共有",
"short-summary": "short-summary",
"Show": "表示",
"Show Additional Params": "追加パラメーターを表示",
"Show shortcuts": "表示",
"sidebar": "サイドバー",
"Sign in": "サインイン",
"Sign Out": "サインアウト",
"Sign up": "サインアップ",
"Speech recognition error: {{error}}": "音声認識エラー: {{error}}",
"Speech-to-Text Engine": "音声テキスト変換エンジン",
"SpeechRecognition API is not supported in this browser.": "このブラウザでは SpeechRecognition API がサポートされていません。",
"Stop Sequence": "ストップシーケンス",
"STT Settings": "STT 設定",
"Submit": "送信",
"Success": "成功",
"Successfully updated.": "正常に更新されました。",
"Sync All": "すべてを同期",
"System": "システム",
"System Prompt": "システムプロンプト",
"Tags": "タグ",
"Temperature": "温度",
"Template": "テンプレート",
"Text Completion": "テキスト補完",
"Text-to-Speech Engine": "テキスト音声変換エンジン",
"Tfs Z": "Tfs Z",
"Theme": "テーマ",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "これは、貴重な会話がバックエンドデータベースに安全に保存されることを保証します。ありがとうございます!",
"This setting does not sync across browsers or devices.": "この設定は、ブラウザやデバイス間で同期されません。",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "ヒント: 各置換後にチャット入力で Tab キーを押すことで、複数の変数スロットを連続して更新できます。",
"Title": "タイトル",
"Title Auto-Generation": "タイトル自動生成",
"Title Generation Prompt": "タイトル生成プロンプト",
"to": "まで",
"To access the available model names for downloading,": "ダウンロード可能なモデル名にアクセスするには、",
"To access the GGUF models available for downloading,": "ダウンロード可能な GGUF モデルにアクセスするには、",
"to chat input.": "チャット入力へ。",
"Toggle settings": "設定を切り替え",
"Toggle sidebar": "サイドバーを切り替え",
"Top K": "トップ K",
"Top P": "トップ P",
"Trouble accessing Ollama?": "Ollama へのアクセスに問題がありますか?",
"TTS Settings": "TTS 設定",
"Type Hugging Face Resolve (Download) URL": "Hugging Face Resolve (ダウンロード) URL を入力してください",
"Uh-oh! There was an issue connecting to {{provider}}.": "おっと! {{provider}} への接続に問題が発生しました。",
"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "不明なファイルタイプ '{{file_type}}' ですが、プレーンテキストとして受け入れて処理します",
"Update password": "パスワードを更新",
"Upload a GGUF model": "GGUF モデルをアップロード",
"Upload files": "ファイルをアップロード",
"Upload Progress": "アップロードの進行状況",
"URL Mode": "URL モード",
"Use '#' in the prompt input to load and select your documents.": "プロンプト入力で '#' を使用して、ドキュメントを読み込んで選択します。",
"Use Gravatar": "Gravatar を使用する",
"user": "ユーザー",
"User Permissions": "ユーザー権限",
"Users": "ユーザー",
"Utilize": "活用",
"Valid time units:": "有効な時間単位:",
"variable": "変数",
"variable to have them replaced with clipboard content.": "クリップボードの内容に置き換える変数。",
"Version": "バージョン",
"Web": "ウェブ",
"WebUI Add-ons": "WebUI アドオン",
"WebUI Settings": "WebUI 設定",
"WebUI will make requests to": "WebUI は次に対してリクエストを行います",
"What’s New in": "新機能",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "履歴が無効になっている場合、このブラウザでの新しいチャットは、どのデバイスの履歴にも表示されません。",
"Whisper (Local)": "Whisper (ローカル)",
"Write a prompt suggestion (e.g. Who are you?)": "プロンプトの提案を書いてください (例: あなたは誰ですか?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "[トピックまたはキーワード] を要約する 50 語の概要を書いてください。",
"You": "あなた",
"You're a helpful assistant.": "あなたは役に立つアシスタントです。",
"You're now logged in.": "ログインしました。"
}
+70
View File
@@ -0,0 +1,70 @@
[
{
"code": "en-US",
"title": "English (US)"
},
{
"code": "bg-BG",
"title": "Bulgarian (BG)"
},
{
"code": "ca-ES",
"title": "Catalan"
},
{
"code": "de-DE",
"title": "Deutsch"
},
{
"code": "es-ES",
"title": "Spanish"
},
{
"code": "fa-IR",
"title": "فارسی (Farsi)"
},
{
"code": "fr-CA",
"title": "French (Canada)"
},
{
"code": "fr-FR",
"title": "French (France)"
},
{
"code": "it-IT",
"title": "Italian"
},
{
"code": "ja-JP",
"title": "Japanese"
},
{
"code": "nl-NL",
"title": "Dutch (Netherlands)"
},
{
"code": "pt-PT",
"title": "Portuguese (Portugal)"
},
{
"code": "ru-RU",
"title": "Russian (Russia)"
},
{
"code": "uk-UA",
"title": "Ukrainian"
},
{
"code": "vi-VN",
"title": "Tiếng Việt"
},
{
"code": "zh-CN",
"title": "Chinese (Simplified)"
},
{
"code": "zh-TW",
"title": "Chinese (Traditional)"
}
]
+363
View File
@@ -0,0 +1,363 @@
{
"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' of '-1' for geen vervaldatum.",
"(Beta)": "(Beta)",
"(e.g. `sh webui.sh --api`)": "(e.g. `sh webui.sh --api`)",
"(latest)": "(nieuwste)",
"{{modelName}} is thinking...": "{{modelName}} is aan het denken...",
"{{webUIName}} Backend Required": "{{webUIName}} Backend Verlpicht",
"a user": "",
"About": "Over",
"Account": "Account",
"Action": "Actie",
"Add a model": "Voeg een model toe",
"Add a model tag name": "Voeg een model tag naam toe",
"Add a short description about what this modelfile does": "Voeg een korte beschrijving toe over wat dit modelfile doet",
"Add a short title for this prompt": "Voeg een korte titel toe voor deze prompt",
"Add a tag": "Voeg een tag toe",
"Add Docs": "Voeg Docs toe",
"Add Files": "Voege Bestanden toe",
"Add message": "Voeg bericht toe",
"add tags": "voeg tags toe",
"Adjusting these settings will apply changes universally to all users.": "Het aanpassen van deze instellingen zal universeel worden toegepast op alle gebruikers.",
"admin": "admin",
"Admin Panel": "Administratieve Paneel",
"Admin Settings": "Administratieve Settings",
"Advanced Parameters": "Geavanceerde Parameters",
"all": "alle",
"All Users": "Alle Gebruikers",
"Allow": "Toestaan",
"Allow Chat Deletion": "Sta Chat Verwijdering toe",
"alphanumeric characters and hyphens": "alfanumerieke karakters en streepjes",
"Already have an account?": "Heb je al een account?",
"an assistant": "een assistent",
"and": "en",
"API Base URL": "API Base URL",
"API Key": "API Key",
"API RPM": "API RPM",
"are allowed - Activate this command by typing": "zijn toegestaan - Activeer deze commando door te typen",
"Are you sure?": "",
"Audio": "Audio",
"Auto-playback response": "Automatisch afspelen van antwoord",
"Auto-send input after 3 sec.": "Automatisch verzenden van input na 3 sec.",
"AUTOMATIC1111 Base URL": "AUTOMATIC1111 Base URL",
"AUTOMATIC1111 Base URL is required.": "",
"available!": "beschikbaar!",
"Back": "Terug",
"Builder Mode": "Bouwer Modus",
"Cancel": "Annuleren",
"Categories": "Categorieën",
"Change Password": "Wijzig Wachtwoord",
"Chat": "Chat",
"Chat History": "Chat Geschiedenis",
"Chat History is off for this browser.": "Chat Geschiedenis is uitgeschakeld voor deze browser.",
"Chats": "Chats",
"Check Again": "Controleer Opnieuw",
"Check for updates": "Controleer op updates",
"Checking for updates...": "Controleren op updates...",
"Choose a model before saving...": "Kies een model voordat je opslaat...",
"Chunk Overlap": "Chunk Overlap",
"Chunk Params": "Chunk Params",
"Chunk Size": "Chunk Grootte",
"Click here for help.": "Klik hier voor help.",
"Click here to check other modelfiles.": "Klik hier om andere modelfiles te controleren.",
"Click here to select": "",
"Click here to select documents.": "",
"click here.": "click here.",
"Click on the user role button to change a user's role.": "Klik op de gebruikersrol knop om de rol van een gebruiker te wijzigen.",
"Close": "Sluiten",
"Collection": "Verzameling",
"Command": "Commando",
"Confirm Password": "Bevestig Wachtwoord",
"Connections": "Verbindingen",
"Content": "Inhoud",
"Context Length": "Context Lengte",
"Conversation Mode": "Gespreksmodus",
"Copy last code block": "Kopieer laatste code blok",
"Copy last response": "Kopieer laatste antwoord",
"Copying to clipboard was successful!": "Kopiëren naar klembord was succesvol!",
"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Maak een beknopte, 3-5 woorden tellende zin als kop voor de volgende query, strikt aanhoudend aan de 3-5 woorden limiet en het vermijden van het gebruik van het woord 'titel':",
"Create a modelfile": "Maak een modelfile",
"Create Account": "Maak Account",
"Created at": "Gemaakt op",
"Created by": "Gemaakt door",
"Current Model": "Huidig Model",
"Current Password": "Huidig Wachtwoord",
"Custom": "Aangepast",
"Customize Ollama models for a specific purpose": "Pas Ollama modellen aan voor een specifiek doel",
"Dark": "Donker",
"Database": "Database",
"DD/MM/YYYY HH:mm": "YYYY/MM/DD HH:mm",
"Default": "Standaard",
"Default (Automatic1111)": "",
"Default (Web API)": "Standaard (Web API)",
"Default model updated": "Standaard model bijgewerkt",
"Default Prompt Suggestions": "Standaard Prompt Suggesties",
"Default User Role": "Standaard Gebruikersrol",
"delete": "verwijderen",
"Delete a model": "Verwijder een model",
"Delete chat": "Verwijder chat",
"Delete Chats": "Verwijder Chats",
"Deleted {{deleteModelTag}}": "{{deleteModelTag}} is verwijderd",
"Deleted {tagName}": "{tagName} is verwijderd",
"Description": "Beschrijving",
"Desktop Notifications": "Desktop Notificaties",
"Disabled": "Uitgeschakeld",
"Discover a modelfile": "Ontdek een modelfile",
"Discover a prompt": "Ontdek een prompt",
"Discover, download, and explore custom prompts": "Ontdek, download en verken aangepaste prompts",
"Discover, download, and explore model presets": "Ontdek, download en verken model presets",
"Display the username instead of You in the Chat": "Toon de gebruikersnaam in plaats van Jij in de Chat",
"Document": "Document",
"Document Settings": "Document Instellingen",
"Documents": "Documenten",
"does not make any external connections, and your data stays securely on your locally hosted server.": "maakt geen externe verbindingen, en je gegevens blijven veilig op je lokaal gehoste server.",
"Don't Allow": "Niet Toestaan",
"Don't have an account?": "Heb je geen account?",
"Download as a File": "Download als Bestand",
"Download Database": "Download Database",
"Drop any files here to add to the conversation": "Sleep bestanden hier om toe te voegen aan het gesprek",
"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "bijv. '30s', '10m'. Geldige tijdseenheden zijn 's', 'm', 'h'.",
"Edit Doc": "Wijzig Doc",
"Edit User": "Wijzig Gebruiker",
"Email": "Email",
"Enable Chat History": "Schakel Chat Geschiedenis in",
"Enable New Sign Ups": "Schakel Nieuwe Registraties in",
"Enabled": "Ingeschakeld",
"Enter {{role}} message here": "",
"Enter API Key": "",
"Enter Chunk Overlap": "",
"Enter Chunk Size": "",
"Enter Image Size (e.g. 512x512)": "",
"Enter LiteLLM API Base URL (litellm_params.api_base)": "",
"Enter LiteLLM API Key (litellm_params.api_key)": "",
"Enter LiteLLM API RPM (litellm_params.rpm)": "",
"Enter LiteLLM Model (litellm_params.model)": "",
"Enter Max Tokens (litellm_params.max_tokens)": "",
"Enter model tag (e.g. {{modelTag}})": "",
"Enter Number of Steps (e.g. 50)": "",
"Enter stop sequence": "Zet stop sequentie",
"Enter Top K": "",
"Enter URL (e.g. http://127.0.0.1:7860/)": "",
"Enter Your Email": "Voer je Email in",
"Enter Your Full Name": "Voer je Volledige Naam in",
"Enter Your Password": "Voer je Wachtwoord in",
"Experimental": "Experimenteel",
"Export All Chats (All Users)": "Exporteer Alle Chats (Alle Gebruikers)",
"Export Chats": "Exporteer Chats",
"Export Documents Mapping": "Exporteer Documenten Mapping",
"Export Modelfiles": "Exporteer Modelfiles",
"Export Prompts": "Exporteer Prompts",
"Failed to read clipboard contents": "Kan klembord inhoud niet lezen",
"File Mode": "Bestandsmodus",
"File not found.": "Bestand niet gevonden.",
"Focus chat input": "Focus chat input",
"Format your variables using square brackets like this:": "Formatteer je variabelen met vierkante haken zoals dit:",
"From (Base Model)": "Van (Basis Model)",
"Full Screen Mode": "Volledig Scherm Modus",
"General": "Algemeen",
"General Settings": "Algemene Instellingen",
"Hello, {{name}}": "Hallo, {{name}}",
"Hide": "Verberg",
"Hide Additional Params": "Verberg Extra Params",
"How can I help you today?": "Hoe kan ik je vandaag helpen?",
"Image Generation (Experimental)": "Afbeelding Generatie (Experimenteel)",
"Image Generation Engine": "",
"Image Settings": "Afbeelding Instellingen",
"Images": "Afbeeldingen",
"Import Chats": "Importeer Chats",
"Import Documents Mapping": "Importeer Documenten Mapping",
"Import Modelfiles": "Importeer Modelfiles",
"Import Prompts": "Importeer Prompts",
"Include `--api` flag when running stable-diffusion-webui": "Voeg `--api` vlag toe bij het uitvoeren van stable-diffusion-webui",
"Interface": "Interface",
"join our Discord for help.": "join onze Discord voor hulp.",
"JSON": "JSON",
"JWT Expiration": "JWT Expiration",
"JWT Token": "JWT Token",
"Keep Alive": "Houd Actief",
"Keyboard shortcuts": "Toetsenbord snelkoppelingen",
"Language": "Taal",
"Light": "Licht",
"Listening...": "Luisteren...",
"LLMs can make mistakes. Verify important information.": "LLMs kunnen fouten maken. Verifieer belangrijke informatie.",
"Made by OpenWebUI Community": "Gemaakt door OpenWebUI Community",
"Make sure to enclose them with": "Zorg ervoor dat je ze omringt met",
"Manage LiteLLM Models": "Beheer LiteLLM Modellen",
"Manage Models": "Beheer Modellen",
"Manage Ollama Models": "Beheer Ollama Modellen",
"Max Tokens": "Max Tokens",
"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Maximaal 3 modellen kunnen tegelijkertijd worden gedownload. Probeer het later opnieuw.",
"Mirostat": "Mirostat",
"Mirostat Eta": "Mirostat Eta",
"Mirostat Tau": "Mirostat Tau",
"MMMM DD, YYYY": "MMMM DD, YYYY",
"Model '{{modelName}}' has been successfully downloaded.": "Model '{{modelName}}' is succesvol gedownload.",
"Model '{{modelTag}}' is already in queue for downloading.": "Model '{{modelTag}}' staat al in de wachtrij voor downloaden.",
"Model {{modelId}} not found": "Model {{modelId}} niet gevonden",
"Model {{modelName}} already exists.": "Model {{modelName}} bestaat al.",
"Model Name": "Model Naam",
"Model not selected": "Model niet geselecteerd",
"Model Tag Name": "Model Tag Naam",
"Model Whitelisting": "Model Whitelisting",
"Model(s) Whitelisted": "Model(len) zijn ge-whitelist",
"Modelfile": "Modelfile",
"Modelfile Advanced Settings": "Modelfile Geavanceerde Instellingen",
"Modelfile Content": "Modelfile Inhoud",
"Modelfiles": "Modelfiles",
"Models": "Modellen",
"My Documents": "Mijn Documenten",
"My Modelfiles": "Mijn Modelfiles",
"My Prompts": "Mijn Prompts",
"Name": "Naam",
"Name Tag": "Naam Tag",
"Name your modelfile": "Benoem je modelfile",
"New Chat": "Nieuwe Chat",
"New Password": "Nieuw Wachtwoord",
"Not sure what to add?": "Niet zeker wat toe te voegen?",
"Not sure what to write? Switch to": "Niet zeker wat te schrijven? Schakel over naar",
"Off": "Uit",
"Okay, Let's Go!": "Okay, Laten we gaan!",
"Ollama Base URL": "",
"Ollama Version": "Ollama Versie",
"On": "Aan",
"Only": "Alleen",
"Only alphanumeric characters and hyphens are allowed in the command string.": "Alleen alfanumerieke karakters en streepjes zijn toegestaan in de commando string.",
"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Oops! Houd vast! Je bestanden zijn nog steeds in de verwerkingsoven. We zijn ze aan het bereiden tot perfectie. Wees geduldig en we laten je weten wanneer ze klaar zijn.",
"Oops! Looks like the URL is invalid. Please double-check and try again.": "Oops! Het lijkt erop dat de URL ongeldig is. Controleer het nogmaals en probeer opnieuw.",
"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Oops! Je gebruikt een niet-ondersteunde methode (alleen frontend). Serveer de WebUI vanuit de backend.",
"Open": "Open",
"Open AI": "Open AI",
"Open AI (Dall-E)": "",
"Open new chat": "Open nieuwe chat",
"OpenAI API": "OpenAI API",
"OpenAI API Key": "",
"OpenAI API Key is required.": "",
"or": "of",
"Parameters": "Parameters",
"Password": "Wachtwoord",
"PDF Extract Images (OCR)": "PDF Extract Afbeeldingen (OCR)",
"pending": "wachtend",
"Permission denied when accessing microphone: {{error}}": "Toestemming geweigerd bij toegang tot microfoon: {{error}}",
"Playground": "Speeltuin",
"Profile": "Profiel",
"Prompt Content": "Prompt Inhoud",
"Prompt suggestions": "Prompt suggesties",
"Prompts": "Prompts",
"Pull a model from Ollama.com": "Haal een model van Ollama.com",
"Pull Progress": "Haal Voortgang op",
"Query Params": "Query Params",
"RAG Template": "RAG Template",
"Raw Format": "Raw Formaat",
"Record voice": "Neem stem op",
"Redirecting you to OpenWebUI Community": "Je wordt doorgestuurd naar OpenWebUI Community",
"Release Notes": "Release Notes",
"Repeat Last N": "Herhaal Laatste N",
"Repeat Penalty": "Herhaal Straf",
"Request Mode": "Request Modus",
"Reset Vector Storage": "Reset Vector Opslag",
"Response AutoCopy to Clipboard": "Antwoord Automatisch Kopiëren naar Klembord",
"Role": "Rol",
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"Save": "Opslaan",
"Save & Create": "Opslaan & Creëren",
"Save & Submit": "Opslaan & Verzenden",
"Save & Update": "Opslaan & Bijwerken",
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Chat logs direct opslaan in de opslag van je browser wordt niet langer ondersteund. Neem even de tijd om je chat logs te downloaden en te verwijderen door op de knop hieronder te klikken. Maak je geen zorgen, je kunt je chat logs eenvoudig opnieuw importeren naar de backend via",
"Scan": "Scan",
"Scan complete!": "Scan voltooid!",
"Scan for documents from {{path}}": "Scan voor documenten van {{path}}",
"Search": "Zoeken",
"Search Documents": "Zoek Documenten",
"Search Prompts": "Zoek Prompts",
"See readme.md for instructions": "Zie readme.md voor instructies",
"See what's new": "Zie wat er nieuw is",
"Seed": "Seed",
"Select a mode": "",
"Select a model": "Selecteer een model",
"Select an Ollama instance": "",
"Send a Message": "Stuur een Bericht",
"Send message": "Stuur bericht",
"Server connection verified": "Server verbinding geverifieerd",
"Set as default": "Stel in als standaard",
"Set Default Model": "Stel Standaard Model in",
"Set Image Size": "Stel Afbeelding Grootte in",
"Set Steps": "Stel Stappen in",
"Set Title Auto-Generation Model": "Stel Titel Auto-Generatie Model in",
"Set Voice": "Stel Stem in",
"Settings": "Instellingen",
"Settings saved successfully!": "Instellingen succesvol opgeslagen!",
"Share to OpenWebUI Community": "Deel naar OpenWebUI Community",
"short-summary": "korte-samenvatting",
"Show": "Toon",
"Show Additional Params": "Toon Extra Params",
"Show shortcuts": "Toon snelkoppelingen",
"sidebar": "sidebar",
"Sign in": "Inloggen",
"Sign Out": "Uitloggen",
"Sign up": "Registreren",
"Speech recognition error: {{error}}": "Spraakherkenning fout: {{error}}",
"Speech-to-Text Engine": "Spraak-naar-tekst Engine",
"SpeechRecognition API is not supported in this browser.": "SpeechRecognition API wordt niet ondersteund in deze browser.",
"Stop Sequence": "Stop Sequentie",
"STT Settings": "STT Instellingen",
"Submit": "Verzenden",
"Success": "Succes",
"Successfully updated.": "Succesvol bijgewerkt.",
"Sync All": "Synchroniseer Alles",
"System": "Systeem",
"System Prompt": "Systeem Prompt",
"Tags": "Tags",
"Temperature": "Temperatuur",
"Template": "Template",
"Text Completion": "Tekst Aanvulling",
"Text-to-Speech Engine": "Tekst-naar-Spraak Engine",
"Tfs Z": "Tfs Z",
"Theme": "Thema",
"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Dit zorgt ervoor dat je waardevolle gesprekken veilig worden opgeslagen in je backend database. Dank je wel!",
"This setting does not sync across browsers or devices.": "Deze instelling wordt niet gesynchroniseerd tussen browsers of apparaten.",
"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tip: Werk meerdere variabele slots achtereenvolgens bij door op de tab-toets te drukken in de chat input na elke vervanging.",
"Title": "Titel",
"Title Auto-Generation": "Titel Auto-Generatie",
"Title Generation Prompt": "Titel Generatie Prompt",
"to": "naar",
"To access the available model names for downloading,": "Om de beschikbare modelnamen voor downloaden te openen,",
"To access the GGUF models available for downloading,": "Om toegang te krijgen tot de GGUF modellen die beschikbaar zijn voor downloaden,",
"to chat input.": "naar chat input.",
"Toggle settings": "Wissel instellingen",
"Toggle sidebar": "Wissel sidebar",
"Top K": "Top K",
"Top P": "Top P",
"Trouble accessing Ollama?": "Problemen met toegang tot Ollama?",
"TTS Settings": "TTS instellingen",
"Type Hugging Face Resolve (Download) URL": "",
"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Er was een probleem met verbinden met {{provider}}.",
"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Onbekend Bestandstype '{{file_type}}', maar accepteren en behandelen als platte tekst",
"Update password": "Wijzig wachtwoord",
"Upload a GGUF model": "Upload een GGUF model",
"Upload files": "Upload bestanden",
"Upload Progress": "Upload Voortgang",
"URL Mode": "URL Modus",
"Use '#' in the prompt input to load and select your documents.": "Gebruik '#' in de prompt input om je documenten te laden en te selecteren.",
"Use Gravatar": "",
"user": "user",
"User Permissions": "Gebruikers Rechten",
"Users": "Gebruikers",
"Utilize": "Utilize",
"Valid time units:": "Geldige tijdseenheden:",
"variable": "variabele",
"variable to have them replaced with clipboard content.": "variabele om ze te laten vervangen door klembord inhoud.",
"Version": "Versie",
"Web": "Web",
"WebUI Add-ons": "WebUI Add-ons",
"WebUI Settings": "WebUI Instellingen",
"WebUI will make requests to": "WebUI zal verzoeken doen naar",
"What’s New in": "Wat is nieuw in",
"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Wanneer geschiedenis is uitgeschakeld, zullen nieuwe chats op deze browser niet verschijnen in je geschiedenis op een van je apparaten.",
"Whisper (Local)": "Fluister (Lokaal)",
"Write a prompt suggestion (e.g. Who are you?)": "Schrijf een prompt suggestie (bijv. Wie ben je?)",
"Write a summary in 50 words that summarizes [topic or keyword].": "Schrijf een samenvatting in 50 woorden die [onderwerp of trefwoord] samenvat.",
"You": "Jij",
"You're a helpful assistant.": "Jij bent een behulpzame assistent.",
"You're now logged in.": "Je bent nu ingelogd."
}

Some files were not shown because too many files have changed in this diff Show More