Commit 547611b7 authored by Michael Poluektov's avatar Michael Poluektov
Browse files

Merge branch 'dev' of https://github.com/open-webui/open-webui into remove-ollama

parents 204a4fbe 1b2ae7bb
......@@ -153,7 +153,7 @@ async def update_engine_url(
r = requests.head(url)
app.state.config.AUTOMATIC1111_BASE_URL = url
except Exception as e:
raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e))
raise HTTPException(status_code=400, detail="Invalid URL provided.")
if form_data.COMFYUI_BASE_URL == None:
app.state.config.COMFYUI_BASE_URL = COMFYUI_BASE_URL
......
......@@ -29,6 +29,7 @@
"js-sha256": "^0.10.1",
"katex": "^0.16.9",
"marked": "^9.1.0",
"marked-katex-extension": "^5.1.1",
"mermaid": "^10.9.1",
"pyodide": "^0.26.1",
"socket.io-client": "^4.2.0",
......@@ -1544,6 +1545,11 @@
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
"dev": true
},
"node_modules/@types/katex": {
"version": "0.16.7",
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz",
"integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ=="
},
"node_modules/@types/mdast": {
"version": "3.0.15",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz",
......@@ -6036,6 +6042,18 @@
"node": ">= 16"
}
},
"node_modules/marked-katex-extension": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/marked-katex-extension/-/marked-katex-extension-5.1.1.tgz",
"integrity": "sha512-piquiCyZpZ1aiocoJlJkRXr+hkk5UI4xw9GhRZiIAAgvX5rhzUDSJ0seup1JcsgueC8MLNDuqe5cRcAzkFE42Q==",
"dependencies": {
"@types/katex": "^0.16.7"
},
"peerDependencies": {
"katex": ">=0.16 <0.17",
"marked": ">=4 <15"
}
},
"node_modules/matcher-collection": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/matcher-collection/-/matcher-collection-2.0.1.tgz",
......
<script lang="ts">
import Spinner from '$lib/components/common/Spinner.svelte';
import { copyToClipboard } from '$lib/utils';
import hljs from 'highlight.js';
import 'highlight.js/styles/github-dark.min.css';
import { loadPyodide } from 'pyodide';
import { onMount, tick } from 'svelte';
import { getContext, getAllContexts } from 'svelte';
import { copyToClipboard } from '$lib/utils';
import 'highlight.js/styles/github-dark.min.css';
import PyodideWorker from '$lib/workers/pyodide.worker?worker';
const i18n = getContext('i18n');
export let id = '';
export let lang = '';
......@@ -233,12 +236,12 @@ __builtins__.input = input`);
class="copy-code-button bg-none border-none p-1"
on:click={() => {
executePython(code);
}}>Run</button
}}>{$i18n.t('Run')}</button
>
{/if}
{/if}
<button class="copy-code-button bg-none border-none p-1" on:click={copyCode}
>{copied ? 'Copied' : 'Copy Code'}</button
>{copied ? $i18n.t('Copied') : $i18n.t('Copy Code')}</button
>
</div>
</div>
......
<script lang="ts">
import katex from 'katex';
import 'katex/contrib/mhchem';
export let content: string;
export let displayMode: boolean = false;
</script>
{@html katex.renderToString(content, { displayMode, throwOnError: false })}
<script lang="ts">
import type { Token } from 'marked';
import { unescapeHtml } from '$lib/utils';
import { revertSanitizedResponseContent, unescapeHtml } from '$lib/utils';
import { onMount } from 'svelte';
import Image from '$lib/components/common/Image.svelte';
import KatexRenderer from './KatexRenderer.svelte';
export let id: string;
export let tokens: Token[];
</script>
......@@ -25,14 +28,21 @@
<svelte:self id={`${id}-em`} tokens={token.tokens} />
</em>
{:else if token.type === 'codespan'}
<code class="codespan">{unescapeHtml(token.text.replaceAll('&amp;', '&'))}</code>
<code class="codespan">{revertSanitizedResponseContent(token.raw)}</code>
{:else if token.type === 'br'}
<br />
{:else if token.type === 'del'}
<del>
<svelte:self id={`${id}-del`} tokens={token.tokens} />
</del>
{:else if token.type === 'inlineKatex'}
{#if token.text}
<KatexRenderer
content={revertSanitizedResponseContent(token.text)}
displayMode={token?.displayMode ?? false}
/>
{/if}
{:else if token.type === 'text'}
{unescapeHtml(token.text)}
{token.raw}
{/if}
{/each}
<script lang="ts">
import { marked } from 'marked';
import { onMount } from 'svelte';
import type { Token } from 'marked';
import { revertSanitizedResponseContent, unescapeHtml } from '$lib/utils';
import { onMount } from 'svelte';
import Image from '$lib/components/common/Image.svelte';
import CodeBlock from '$lib/components/chat/Messages/CodeBlock.svelte';
import MarkdownInlineTokens from '$lib/components/chat/Messages/MarkdownInlineTokens.svelte';
import KatexRenderer from './KatexRenderer.svelte';
export let id: string;
export let tokens: Token[];
export let top = true;
let containerElement;
const headerComponent = (depth: number) => {
return 'h' + depth;
};
const renderer = new marked.Renderer();
// For code blocks with simple backticks
renderer.codespan = (code) => {
return `<code class="codespan">${code.replaceAll('&amp;', '&')}</code>`;
};
let codes = [];
renderer.code = (code, lang) => {
codes.push({
code: code,
lang: lang
});
codes = codes;
const codeId = `${id}-${codes.length}`;
const interval = setInterval(() => {
const codeElement = document.getElementById(`code-${codeId}`);
if (codeElement) {
clearInterval(interval);
// If the code is already loaded, don't load it again
if (codeElement.innerHTML) {
return;
}
new CodeBlock({
target: codeElement,
props: {
id: `${id}-${codes.length}`,
lang: lang,
code: revertSanitizedResponseContent(code)
},
hydrate: true,
$$inline: true
});
}
}, 10);
return `<div id="code-${id}-${codes.length}"></div>`;
};
let images = [];
renderer.image = (href, title, text) => {
images.push({
href: href,
title: title,
text: text
});
images = images;
const imageId = `${id}-${images.length}`;
const interval = setInterval(() => {
const imageElement = document.getElementById(`image-${imageId}`);
if (imageElement) {
clearInterval(interval);
// If the image is already loaded, don't load it again
if (imageElement.innerHTML) {
return;
}
console.log('image', href, text);
new Image({
target: imageElement,
props: {
src: href,
alt: text
},
$$inline: true
});
}
}, 10);
return `<div id="image-${id}-${images.length}"></div>`;
};
// Open all links in a new tab/window (from https://github.com/markedjs/marked/issues/655#issuecomment-383226346)
const origLinkRenderer = renderer.link;
renderer.link = (href, title, text) => {
const html = origLinkRenderer.call(renderer, href, title, text);
return html.replace(/^<a /, '<a target="_blank" rel="nofollow" ');
};
const { extensions, ...defaults } = marked.getDefaults() as marked.MarkedOptions & {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
extensions: any;
};
$: if (tokens) {
images = [];
codes = [];
}
</script>
<div bind:this={containerElement} class="flex flex-col">
{#each tokens as token, tokenIdx (`${id}-${tokenIdx}`)}
{#if token.type === 'code'}
{#if token.lang === 'mermaid'}
<pre class="mermaid">{revertSanitizedResponseContent(token.text)}</pre>
{:else}
<!-- {JSON.stringify(tokens)} -->
{#each tokens as token, tokenIdx}
{#if token.type === 'hr'}
<hr />
{:else if token.type === 'heading'}
<svelte:element this={headerComponent(token.depth)}>
<MarkdownInlineTokens id={`${id}-${tokenIdx}-h`} tokens={token.tokens} />
</svelte:element>
{:else if token.type === 'code'}
<CodeBlock
id={`${id}-${tokenIdx}`}
{id}
lang={token?.lang ?? ''}
code={revertSanitizedResponseContent(token?.text ?? '')}
/>
{:else if token.type === 'table'}
<table>
<thead>
<tr>
{#each token.header as header, headerIdx}
<th style={token.align[headerIdx] ? '' : `text-align: ${token.align[headerIdx]}`}>
<MarkdownInlineTokens
id={`${id}-${tokenIdx}-header-${headerIdx}`}
tokens={header.tokens}
/>
</th>
{/each}
</tr>
</thead>
<tbody>
{#each token.rows as row, rowIdx}
<tr>
{#each row ?? [] as cell, cellIdx}
<td style={token.align[cellIdx] ? '' : `text-align: ${token.align[cellIdx]}`}>
<MarkdownInlineTokens
id={`${id}-${tokenIdx}-row-${rowIdx}-${cellIdx}`}
tokens={cell.tokens}
/>
</td>
{/each}
</tr>
{/each}
</tbody>
</table>
{:else if token.type === 'blockquote'}
<blockquote>
<svelte:self id={`${id}-${tokenIdx}`} tokens={token.tokens} />
</blockquote>
{:else if token.type === 'list'}
{#if token.ordered}
<ol start={token.start || 1}>
{#each token.items as item, itemIdx}
<li>
<svelte:self
id={`${id}-${tokenIdx}-${itemIdx}`}
tokens={item.tokens}
top={token.loose}
/>
</li>
{/each}
</ol>
{:else}
<ul>
{#each token.items as item, itemIdx}
<li>
<svelte:self
id={`${id}-${tokenIdx}-${itemIdx}`}
tokens={item.tokens}
top={token.loose}
/>
</li>
{/each}
</ul>
{/if}
{:else if token.type === 'html'}
{@html token.text}
{:else if token.type === 'paragraph'}
<p>
<MarkdownInlineTokens id={`${id}-${tokenIdx}-p`} tokens={token.tokens ?? []} />
</p>
{:else if token.type === 'text'}
{#if top}
<p>
{#if token.tokens}
<MarkdownInlineTokens id={`${id}-${tokenIdx}-t`} tokens={token.tokens} />
{:else}
{@html marked.parse(token.raw, {
...defaults,
gfm: true,
breaks: true,
renderer
})}
{unescapeHtml(token.text)}
{/if}
{/each}
</div>
</p>
{:else if token.tokens}
<MarkdownInlineTokens id={`${id}-${tokenIdx}-p`} tokens={token.tokens ?? []} />
{:else}
{unescapeHtml(token.text)}
{/if}
{:else if token.type === 'inlineKatex'}
{#if token.text}
<KatexRenderer
content={revertSanitizedResponseContent(token.text)}
displayMode={token?.displayMode ?? false}
/>
{/if}
{:else if token.type === 'space'}
{''}
{:else}
{console.log('Unknown token', token)}
{/if}
{/each}
......@@ -4,7 +4,6 @@
import { marked } from 'marked';
import tippy from 'tippy.js';
import auto_render from 'katex/dist/contrib/auto-render.mjs';
import 'katex/dist/katex.min.css';
import mermaid from 'mermaid';
import { fade } from 'svelte/transition';
......@@ -79,76 +78,26 @@
let tokens;
import 'katex/dist/katex.min.css';
import markedKatex from '$lib/utils/katex-extension';
const options = {
throwOnError: false
};
marked.use(markedKatex(options));
$: (async () => {
if (message?.content) {
tokens = marked.lexer(
replaceTokens(sanitizeResponseContent(message?.content), model?.name, $user?.name)
);
// console.log(message?.content, tokens);
}
})();
$: if (message) {
renderStyling();
}
const renderStyling = async () => {
await tick();
if (tooltipInstance) {
tooltipInstance[0]?.destroy();
}
$: if (message?.done ?? false) {
renderLatex();
if (message.info) {
let tooltipContent = '';
if (message.info.openai) {
tooltipContent = `prompt_tokens: ${message.info.prompt_tokens ?? 'N/A'}<br/>
completion_tokens: ${message.info.completion_tokens ?? 'N/A'}<br/>
total_tokens: ${message.info.total_tokens ?? 'N/A'}`;
} else {
tooltipContent = `response_token/s: ${
`${
Math.round(
((message.info.eval_count ?? 0) / (message.info.eval_duration / 1000000000)) * 100
) / 100
} tokens` ?? 'N/A'
}<br/>
prompt_token/s: ${
Math.round(
((message.info.prompt_eval_count ?? 0) /
(message.info.prompt_eval_duration / 1000000000)) *
100
) / 100 ?? 'N/A'
} tokens<br/>
total_duration: ${
Math.round(((message.info.total_duration ?? 0) / 1000000) * 100) / 100 ??
'N/A'
}ms<br/>
load_duration: ${
Math.round(((message.info.load_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A'
}ms<br/>
prompt_eval_count: ${message.info.prompt_eval_count ?? 'N/A'}<br/>
prompt_eval_duration: ${
Math.round(((message.info.prompt_eval_duration ?? 0) / 1000000) * 100) /
100 ?? 'N/A'
}ms<br/>
eval_count: ${message.info.eval_count ?? 'N/A'}<br/>
eval_duration: ${
Math.round(((message.info.eval_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A'
}ms<br/>
approximate_total: ${approximateToHumanReadable(message.info.total_duration)}`;
}
tooltipInstance = tippy(`#info-${message.id}`, {
content: `<span class="text-xs" id="tooltip-${message.id}">${tooltipContent}</span>`,
allowHTML: true,
theme: 'dark',
arrow: false,
offset: [0, 4]
});
}
};
const renderLatex = () => {
let chatMessageElements = document
......@@ -330,14 +279,14 @@
editedContent = '';
await tick();
renderStyling();
renderLatex();
};
const cancelEditMessage = async () => {
edit = false;
editedContent = '';
await tick();
renderStyling();
renderLatex();
};
const generateImage = async (message) => {
......@@ -362,7 +311,7 @@
$: if (!edit) {
(async () => {
await tick();
renderStyling();
renderLatex();
await mermaid.run({
querySelector: '.mermaid'
......@@ -372,7 +321,7 @@
onMount(async () => {
await tick();
renderStyling();
renderLatex();
await mermaid.run({
querySelector: '.mermaid'
......@@ -420,7 +369,7 @@
{/if}
<div
class="prose chat-{message.role} w-full max-w-full dark:prose-invert prose-p:my-0 prose-img:my-1 prose-headings:my-1 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-ul:-my-2 prose-ol:-my-2 prose-li:-my-3 whitespace-pre-line"
class="prose chat-{message.role} w-full max-w-full dark:prose-invert prose-p:my-0 prose-img:my-1 prose-headings:my-1 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-ul:-my-0 prose-ol:-my-0 prose-li:-my-0 whitespace-pre-line"
>
<div>
{#if (message?.statusHistory ?? [...(message?.status ? [message?.status] : [])]).length > 0}
......@@ -841,6 +790,45 @@
{/if}
{#if message.info}
<Tooltip
content={message.info.openai
? `prompt_tokens: ${message.info.prompt_tokens ?? 'N/A'}<br/>
completion_tokens: ${message.info.completion_tokens ?? 'N/A'}<br/>
total_tokens: ${message.info.total_tokens ?? 'N/A'}`
: `response_token/s: ${
`${
Math.round(
((message.info.eval_count ?? 0) /
(message.info.eval_duration / 1000000000)) *
100
) / 100
} tokens` ?? 'N/A'
}<br/>
prompt_token/s: ${
Math.round(
((message.info.prompt_eval_count ?? 0) /
(message.info.prompt_eval_duration / 1000000000)) *
100
) / 100 ?? 'N/A'
} tokens<br/>
total_duration: ${
Math.round(((message.info.total_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A'
}ms<br/>
load_duration: ${
Math.round(((message.info.load_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A'
}ms<br/>
prompt_eval_count: ${message.info.prompt_eval_count ?? 'N/A'}<br/>
prompt_eval_duration: ${
Math.round(((message.info.prompt_eval_duration ?? 0) / 1000000) * 100) / 100 ??
'N/A'
}ms<br/>
eval_count: ${message.info.eval_count ?? 'N/A'}<br/>
eval_duration: ${
Math.round(((message.info.eval_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A'
}ms<br/>
approximate_total: ${approximateToHumanReadable(message.info.total_duration)}`}
placement="top"
>
<Tooltip content={$i18n.t('Generation Info')} placement="bottom">
<button
class=" {isLastMessage
......@@ -867,6 +855,7 @@
</svg>
</button>
</Tooltip>
</Tooltip>
{/if}
{#if !readOnly}
......
......@@ -134,8 +134,10 @@
"Continue Response": "متابعة الرد",
"Continue with {{provider}}": "",
"Controls": "",
"Copied": "",
"Copied shared chat URL to clipboard!": "تم نسخ عنوان URL للدردشة المشتركة إلى الحافظة",
"Copy": "نسخ",
"Copy Code": "",
"Copy last code block": "انسخ كتلة التعليمات البرمجية الأخيرة",
"Copy last response": "انسخ الرد الأخير",
"Copy Link": "أنسخ الرابط",
......@@ -499,6 +501,7 @@
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "من اليمين إلى اليسار",
"Run": "",
"Run Llama 2, Code Llama, and other models. Customize and create your own.": "",
"Running": "",
"Save": "حفظ",
......
......@@ -134,8 +134,10 @@
"Continue Response": "Продължи отговора",
"Continue with {{provider}}": "",
"Controls": "",
"Copied": "",
"Copied shared chat URL to clipboard!": "Копирана е връзката за чат!",
"Copy": "Копирай",
"Copy Code": "",
"Copy last code block": "Копиране на последен код блок",
"Copy last response": "Копиране на последен отговор",
"Copy Link": "Копиране на връзка",
......@@ -499,6 +501,7 @@
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "RTL",
"Run": "",
"Run Llama 2, Code Llama, and other models. Customize and create your own.": "",
"Running": "",
"Save": "Запис",
......
......@@ -134,8 +134,10 @@
"Continue Response": "যাচাই করুন",
"Continue with {{provider}}": "",
"Controls": "",
"Copied": "",
"Copied shared chat URL to clipboard!": "শেয়ারকৃত কথা-ব্যবহারের URL ক্লিপবোর্ডে কপি করা হয়েছে!",
"Copy": "অনুলিপি",
"Copy Code": "",
"Copy last code block": "সর্বশেষ কোড ব্লক কপি করুন",
"Copy last response": "সর্বশেষ রেসপন্স কপি করুন",
"Copy Link": "লিংক কপি করুন",
......@@ -499,6 +501,7 @@
"Rosé Pine": "রোজ পাইন",
"Rosé Pine Dawn": "ভোরের রোজ পাইন",
"RTL": "RTL",
"Run": "",
"Run Llama 2, Code Llama, and other models. Customize and create your own.": "",
"Running": "",
"Save": "সংরক্ষণ",
......
......@@ -134,8 +134,10 @@
"Continue Response": "Continuar la resposta",
"Continue with {{provider}}": "Continuar amb {{provider}}",
"Controls": "Controls",
"Copied": "Copiat",
"Copied shared chat URL to clipboard!": "S'ha copiat l'URL compartida al porta-retalls!",
"Copy": "Copiar",
"Copy Code": "Copiar el codi",
"Copy last code block": "Copiar l'últim bloc de codi",
"Copy last response": "Copiar l'última resposta",
"Copy Link": "Copiar l'enllaç",
......@@ -499,6 +501,7 @@
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Albada Rosé Pine",
"RTL": "RTL",
"Run": "Executar",
"Run Llama 2, Code Llama, and other models. Customize and create your own.": "Executa Llama 2, Code Llama, i altres models. Personalitza i crea els teus propis models.",
"Running": "S'està executant",
"Save": "Desar",
......@@ -509,7 +512,7 @@
"Scan": "Escanejar",
"Scan complete!": "Escaneigr completat!",
"Scan for documents from {{path}}": "Escanejar documents des de {{path}}",
"Scroll to bottom when switching between branches": "",
"Scroll to bottom when switching between branches": "Desplaçar a la part inferior quan es canviï de branca",
"Search": "Cercar",
"Search a model": "Cercar un model",
"Search Chats": "Cercar xats",
......@@ -624,7 +627,7 @@
"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Per accedir a la WebUI, poseu-vos en contacte amb l'administrador. Els administradors poden gestionar els estats dels usuaris des del tauler d'administració.",
"To add documents here, upload them to the \"Documents\" workspace first.": "Per afegir documents aquí, puja-ls primer a l'espai de treball \"Documents\".",
"to chat input.": "a l'entrada del xat.",
"To select actions here, add them to the \"Functions\" workspace first.": "Per seleccionar accions aquí, afegeix-los primer a l'espai de treball \"Funcions\".",
"To select actions here, add them to the \"Functions\" workspace first.": "Per seleccionar accions aquí, afegeix-les primer a l'espai de treball \"Funcions\".",
"To select filters here, add them to the \"Functions\" workspace first.": "Per seleccionar filtres aquí, afegeix-los primer a l'espai de treball \"Funcions\".",
"To select toolkits here, add them to the \"Tools\" workspace first.": "Per seleccionar kits d'eines aquí, afegeix-los primer a l'espai de treball \"Eines\".",
"Today": "Avui",
......
......@@ -134,8 +134,10 @@
"Continue Response": "",
"Continue with {{provider}}": "",
"Controls": "",
"Copied": "",
"Copied shared chat URL to clipboard!": "",
"Copy": "",
"Copy Code": "",
"Copy last code block": "Kopyaha ang katapusang bloke sa code",
"Copy last response": "Kopyaha ang kataposang tubag",
"Copy Link": "",
......@@ -499,6 +501,7 @@
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Aube Pine Rosé",
"RTL": "",
"Run": "",
"Run Llama 2, Code Llama, and other models. Customize and create your own.": "",
"Running": "",
"Save": "Tipigi",
......
......@@ -134,8 +134,10 @@
"Continue Response": "Antwort fortsetzen",
"Continue with {{provider}}": "Mit {{provider}} fortfahren",
"Controls": "",
"Copied": "",
"Copied shared chat URL to clipboard!": "Freigabelink in die Zwischenablage kopiert!",
"Copy": "Kopieren",
"Copy Code": "",
"Copy last code block": "Letzten Codeblock kopieren",
"Copy last response": "Letzte Antwort kopieren",
"Copy Link": "Link kopieren",
......@@ -499,6 +501,7 @@
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "RTL",
"Run": "",
"Run Llama 2, Code Llama, and other models. Customize and create your own.": "",
"Running": "Läuft",
"Save": "Speichern",
......
......@@ -134,8 +134,10 @@
"Continue Response": "",
"Continue with {{provider}}": "",
"Controls": "",
"Copied": "",
"Copied shared chat URL to clipboard!": "",
"Copy": "",
"Copy Code": "",
"Copy last code block": "Copy last code block",
"Copy last response": "Copy last response",
"Copy Link": "",
......@@ -499,6 +501,7 @@
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "",
"Run": "",
"Run Llama 2, Code Llama, and other models. Customize and create your own.": "",
"Running": "",
"Save": "Save much wow",
......
......@@ -134,8 +134,10 @@
"Continue Response": "",
"Continue with {{provider}}": "",
"Controls": "",
"Copied": "",
"Copied shared chat URL to clipboard!": "",
"Copy": "",
"Copy Code": "",
"Copy last code block": "",
"Copy last response": "",
"Copy Link": "",
......@@ -499,6 +501,7 @@
"Rosé Pine": "",
"Rosé Pine Dawn": "",
"RTL": "",
"Run": "",
"Run Llama 2, Code Llama, and other models. Customize and create your own.": "",
"Running": "",
"Save": "",
......
......@@ -134,8 +134,10 @@
"Continue Response": "",
"Continue with {{provider}}": "",
"Controls": "",
"Copied": "",
"Copied shared chat URL to clipboard!": "",
"Copy": "",
"Copy Code": "",
"Copy last code block": "",
"Copy last response": "",
"Copy Link": "",
......@@ -499,6 +501,7 @@
"Rosé Pine": "",
"Rosé Pine Dawn": "",
"RTL": "",
"Run": "",
"Run Llama 2, Code Llama, and other models. Customize and create your own.": "",
"Running": "",
"Save": "",
......
......@@ -134,8 +134,10 @@
"Continue Response": "Continuar Respuesta",
"Continue with {{provider}}": "Continuar con {{provider}}",
"Controls": "",
"Copied": "",
"Copied shared chat URL to clipboard!": "¡URL de chat compartido copiado al portapapeles!",
"Copy": "Copiar",
"Copy Code": "",
"Copy last code block": "Copia el último bloque de código",
"Copy last response": "Copia la última respuesta",
"Copy Link": "Copiar enlace",
......@@ -499,6 +501,7 @@
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "RTL",
"Run": "",
"Run Llama 2, Code Llama, and other models. Customize and create your own.": "",
"Running": "Ejecutando",
"Save": "Guardar",
......
......@@ -134,8 +134,10 @@
"Continue Response": "ادامه پاسخ",
"Continue with {{provider}}": "",
"Controls": "",
"Copied": "",
"Copied shared chat URL to clipboard!": "URL چت به کلیپ بورد کپی شد!",
"Copy": "کپی",
"Copy Code": "",
"Copy last code block": "کپی آخرین بلوک کد",
"Copy last response": "کپی آخرین پاسخ",
"Copy Link": "کپی لینک",
......@@ -499,6 +501,7 @@
"Rosé Pine": "Rosé Pine",
"Rosé Pine Dawn": "Rosé Pine Dawn",
"RTL": "RTL",
"Run": "",
"Run Llama 2, Code Llama, and other models. Customize and create your own.": "",
"Running": "",
"Save": "ذخیره",
......
......@@ -134,8 +134,10 @@
"Continue Response": "Jatka vastausta",
"Continue with {{provider}}": "",
"Controls": "",
"Copied": "",
"Copied shared chat URL to clipboard!": "Jaettu keskustelulinkki kopioitu leikepöydälle!",
"Copy": "Kopioi",
"Copy Code": "",
"Copy last code block": "Kopioi viimeisin koodilohko",
"Copy last response": "Kopioi viimeisin vastaus",
"Copy Link": "Kopioi linkki",
......@@ -499,6 +501,7 @@
"Rosé Pine": "Rosee-mänty",
"Rosé Pine Dawn": "Aamuinen Rosee-mänty",
"RTL": "RTL",
"Run": "",
"Run Llama 2, Code Llama, and other models. Customize and create your own.": "",
"Running": "",
"Save": "Tallenna",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment