Update language files and fix UI issues

This commit is contained in:
n4ze3m
2024-03-24 17:07:21 +05:30
parent d9ce1e2d2c
commit 502759fae6
24 changed files with 485 additions and 54 deletions

View File

@@ -26,7 +26,7 @@ const LinkComponent = (item: {
item.current === item.href
? "bg-gray-100 text-gray-600 dark:bg-[#262626] dark:text-white"
: "text-gray-700 hover:text-gray-600 hover:bg-gray-100 dark:text-gray-200 dark:hover:text-white dark:hover:bg-[#262626]",
"group flex gap-x-3 rounded-md py-2 pl-2 pr-3 text-sm leading-6 font-semibold"
"group flex gap-x-3 rounded-md py-2 pl-2 pr-3 text-sm font-semibold"
)}>
<item.icon
className={classNames(

View File

@@ -14,7 +14,7 @@ dayjs.extend(relativeTime)
export const ModelsBody = () => {
const queryClient = useQueryClient()
const [open, setOpen] = useState(false)
const { t } = useTranslation("option")
const { t } = useTranslation(["option", "common"])
const form = useForm({
initialValues: {
@@ -188,9 +188,13 @@ export const ModelsBody = () => {
}
]}
dataSource={[record.details]}
locale={{
emptyText: t("common:noData")
}}
/>
),
defaultExpandAllRows: false
defaultExpandAllRows: false,
}}
bordered
dataSource={data}

View File

@@ -1,6 +1,7 @@
import { useQuery } from "@tanstack/react-query"
import { RotateCcw } from "lucide-react"
import { useEffect, useState } from "react"
import { useTranslation } from "react-i18next"
import {
getOllamaURL,
isOllamaRunning,
@@ -9,6 +10,7 @@ import {
export const PlaygroundEmpty = () => {
const [ollamaURL, setOllamaURL] = useState<string>("")
const { t } = useTranslation(["playground", "common"])
const {
data: ollamaInfo,
status: ollamaStatus,
@@ -40,7 +42,7 @@ export const PlaygroundEmpty = () => {
<div className="inline-flex items-center space-x-2">
<div className="w-3 h-3 bg-blue-500 rounded-full animate-bounce"></div>
<p className="dark:text-gray-400 text-gray-900">
Searching for Your Ollama 🦙
{t("ollamaState.searching")}
</p>
</div>
)}
@@ -49,7 +51,7 @@ export const PlaygroundEmpty = () => {
<div className="inline-flex items-center space-x-2">
<div className="w-3 h-3 bg-green-500 rounded-full"></div>
<p className="dark:text-gray-400 text-gray-900">
Ollama is running 🦙
{t("ollamaState.running")}
</p>
</div>
) : (
@@ -57,7 +59,7 @@ export const PlaygroundEmpty = () => {
<div className="inline-flex space-x-2">
<div className="w-3 h-3 bg-red-500 rounded-full"></div>
<p className="dark:text-gray-400 text-gray-900">
Unable to connect to Ollama 🦙
{t("ollamaState.notRunning")}
</p>
</div>
@@ -75,7 +77,7 @@ export const PlaygroundEmpty = () => {
}}
className="inline-flex mt-4 items-center rounded-md border border-transparent bg-black px-2 py-2 text-sm font-medium leading-4 text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-white dark:text-gray-800 dark:hover:bg-gray-100 dark:focus:ring-gray-500 dark:focus:ring-offset-gray-100 disabled:opacity-50 ">
<RotateCcw className="h-4 w-4 mr-3" />
Retry
{t("common:retry")}
</button>
</div>
)

View File

@@ -11,12 +11,14 @@ import { useWebUI } from "~/store/webui"
import { defaultEmbeddingModelForRag } from "~/services/ollama"
import { ImageIcon, MicIcon, StopCircleIcon, X } from "lucide-react"
import { getVariable } from "~/utils/select-varaible"
import { useTranslation } from "react-i18next"
type Props = {
dropedFile: File | undefined
}
export const PlaygroundForm = ({ dropedFile }: Props) => {
const { t } = useTranslation(["playground", "common"])
const inputRef = React.useRef<HTMLInputElement>(null)
const [typing, setTyping] = React.useState<boolean>(false)
const {
@@ -117,13 +119,13 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
})
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === "Process" || e.key === "229" ) return
if (e.key === "Process" || e.key === "229") return
if (
!typing &&
e.key === "Enter" &&
!e.shiftKey &&
!isSending &&
sendWhenEnter
sendWhenEnter
) {
e.preventDefault()
form.onSubmit(async (value) => {
@@ -131,16 +133,13 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
return
}
if (!selectedModel || selectedModel.length === 0) {
form.setFieldError("message", "Please select a model")
form.setFieldError("message", t("formError.noModel"))
return
}
if (webSearch) {
const defaultEM = await defaultEmbeddingModelForRag()
if (!defaultEM) {
form.setFieldError(
"message",
"Please set an embedding model on the Settings > Ollama page"
)
form.setFieldError("message", t("formError.noEmbeddingModel"))
return
}
}
@@ -181,16 +180,13 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
<form
onSubmit={form.onSubmit(async (value) => {
if (!selectedModel || selectedModel.length === 0) {
form.setFieldError("message", "Please select a model")
form.setFieldError("message", t("formError.noModel"))
return
}
if (webSearch) {
const defaultEM = await defaultEmbeddingModelForRag()
if (!defaultEM) {
form.setFieldError(
"message",
"Please set an embedding model on the Settings > Ollama page"
)
form.setFieldError("message", t("formError.noEmbeddingModel"))
return
}
}
@@ -223,12 +219,12 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
rows={1}
style={{ minHeight: "60px" }}
tabIndex={0}
placeholder="Type a message..."
placeholder={t("form.textarea.placeholder")}
{...form.getInputProps("message")}
/>
<div className="mt-4 flex justify-between items-center">
<div className="flex">
<Tooltip title="Search Internet">
<Tooltip title={t("tooltip.searchInternet")}>
<div className="inline-flex items-center gap-2">
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -246,14 +242,14 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
<Switch
value={webSearch}
onChange={(e) => setWebSearch(e)}
checkedChildren="On"
unCheckedChildren="Off"
checkedChildren={t("form.webSearch.on")}
unCheckedChildren={t("form.webSearch.off")}
/>
</div>
</Tooltip>
</div>
<div className="flex !justify-end gap-3">
<Tooltip title="Voice Message">
<Tooltip title={t("tooltip.speechToText")}>
<button
type="button"
onClick={() => {
@@ -277,7 +273,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
)}
</button>
</Tooltip>
<Tooltip title="Upload Image">
<Tooltip title={t("tooltip.uploadImage")}>
<button
type="button"
onClick={() => {
@@ -319,7 +315,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
onChange={(e) =>
setSendWhenEnter(e.target.checked)
}>
Send when Enter pressed
{t("sendWhenEnter")}
</Checkbox>
)
}
@@ -340,11 +336,11 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
<path d="M20 4v7a4 4 0 01-4 4H4"></path>
</svg>
) : null}
Submit
{t("common:submit")}
</div>
</Dropdown.Button>
) : (
<Tooltip title="Stop Streaming">
<Tooltip title={t("tooltip.stopStreaming")}>
<button
type="button"
onClick={stopStreamingRequest}

View File

@@ -7,7 +7,8 @@ import {
Modal,
Input,
Form,
Switch
Switch,
Empty
} from "antd"
import { Trash2, Pen, Computer, Zap } from "lucide-react"
import { useState } from "react"

View File

@@ -7,6 +7,7 @@ import { SUPPORTED_LANGUAGES } from "~/utils/supporetd-languages"
import { MoonIcon, SunIcon } from "lucide-react"
import { SearchModeSettings } from "./search-mode"
import { useTranslation } from "react-i18next"
import { useI18n } from "@/hooks/useI18n"
export const SettingOther = () => {
const { clearChat, speechToTextLanguage, setSpeechToTextLanguage } =
@@ -16,6 +17,11 @@ export const SettingOther = () => {
const { mode, toggleDarkMode } = useDarkMode()
const { t } = useTranslation("option")
const {
changeLocale,
locale,
supportLanguage
}= useI18n()
return (
@@ -46,6 +52,26 @@ export const SettingOther = () => {
}}
/>
</div>
<div className="flex flex-row justify-between">
<span className="text-gray-500 dark:text-neutral-50">
{t("generalSettings.settings.language.label")}
</span>
<Select
placeholder={t("generalSettings.settings.language.placeholder")}
allowClear
showSearch
options={supportLanguage}
value={locale}
filterOption={(input, option) =>
option!.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
option!.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
onChange={(value) => {
changeLocale(value)
}}
/>
</div>
<div className="flex flex-row justify-between">
<span className="text-gray-500 dark:text-neutral-50 ">
{t("generalSettings.settings.darkMode.label")}

View File

@@ -8,9 +8,9 @@ import {
} from "~/libs/db"
import { Empty, Skeleton } from "antd"
import { useMessageOption } from "~/hooks/useMessageOption"
import { useState } from "react"
import { PencilIcon, Trash2 } from "lucide-react"
import { useNavigate } from "react-router-dom"
import { useTranslation } from "react-i18next"
type Props = {
onClose: () => void
@@ -19,6 +19,7 @@ type Props = {
export const Sidebar = ({ onClose }: Props) => {
const { setMessages, setHistory, setHistoryId, historyId, clearChat } =
useMessageOption()
const { t } = useTranslation(["option", "common"])
const client = useQueryClient()
const navigate = useNavigate()
@@ -60,7 +61,7 @@ export const Sidebar = ({ onClose }: Props) => {
<div className="overflow-y-auto z-99">
{status === "success" && chatHistories.length === 0 && (
<div className="flex justify-center items-center mt-20 overflow-hidden">
<Empty description="No history yet" />
<Empty description={t("common:noHistory")} />
</div>
)}
{status === "pending" && (
@@ -95,7 +96,7 @@ export const Sidebar = ({ onClose }: Props) => {
<div className="flex flex-row gap-3">
<button
onClick={() => {
const newTitle = prompt("Enter new title", chat.title)
const newTitle = prompt(t("editHistoryTitle"), chat.title)
if (newTitle) {
editHistory({ id: chat.id, title: newTitle })
@@ -107,10 +108,7 @@ export const Sidebar = ({ onClose }: Props) => {
<button
onClick={() => {
if (
!confirm("Are you sure you want to delete this history?")
)
return
if (!confirm(t("deleteHistoryConfirmation"))) return
deleteHistory(chat.id)
}}
className="text-red-500 dark:text-red-400 opacity-80">