Procházet zdrojové kódy

Merge branch 'main' of https://github.com/Yidadaa/ChatGPT-Next-Web

GH Action - Upstream Sync před 1 rokem
rodič
revize
ff72e8abab

+ 2 - 1
app/locales/cn.ts

@@ -67,7 +67,7 @@ const cn = {
       ConfirmClearAll: "确认清除所有数据?",
     },
     Lang: {
-      Name: "Language",
+      Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
       All: "所有语言",
       Options: {
         cn: "简体中文",
@@ -79,6 +79,7 @@ const cn = {
         jp: "日本語",
         de: "Deutsch",
         vi: "Vietnamese",
+        ru: "Русский",
       },
     },
     Avatar: "头像",

+ 2 - 1
app/locales/de.ts

@@ -71,7 +71,7 @@ const de: LocaleType = {
     },
     Lang: {
       Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
-      All: "All Languages",
+      All: "Alle Sprachen",
       Options: {
         cn: "简体中文",
         en: "English",
@@ -82,6 +82,7 @@ const de: LocaleType = {
         jp: "日本語",
         de: "Deutsch",
         vi: "Vietnamese",
+        ru: "Русский",
       },
     },
     Avatar: "Avatar",

+ 1 - 0
app/locales/en.ts

@@ -81,6 +81,7 @@ const en: LocaleType = {
         jp: "日本語",
         de: "Deutsch",
         vi: "Vietnamese",
+        ru: "Русский",
       },
     },
     Avatar: "Avatar",

+ 4 - 3
app/locales/es.ts

@@ -69,11 +69,11 @@ const es: LocaleType = {
       ConfirmClearAll: "Are you sure you want to reset all chat?",
     },
     Lang: {
-      Name: "Language",
-      All: "All Languages",
+      Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
+      All: "Todos los idiomas",
       Options: {
         cn: "简体中文",
-        en: "Inglés",
+        en: "English",
         tw: "繁體中文",
         es: "Español",
         it: "Italiano",
@@ -81,6 +81,7 @@ const es: LocaleType = {
         jp: "日本語",
         de: "Deutsch",
         vi: "Vietnamese",
+        ru: "Русский",
       },
     },
     Avatar: "Avatar",

+ 3 - 0
app/locales/index.ts

@@ -7,6 +7,7 @@ import TR from "./tr";
 import JP from "./jp";
 import DE from "./de";
 import VI from "./vi";
+import RU from "./ru";
 
 export type { LocaleType } from "./cn";
 
@@ -20,6 +21,7 @@ export const AllLangs = [
   "jp",
   "de",
   "vi",
+  "ru",
 ] as const;
 export type Lang = (typeof AllLangs)[number];
 
@@ -82,4 +84,5 @@ export default {
   jp: JP,
   de: DE,
   vi: VI,
+  ru: RU,
 }[getLang()] as typeof CN;

+ 3 - 2
app/locales/it.ts

@@ -69,8 +69,8 @@ const it: LocaleType = {
       ConfirmClearAll: "Sei sicuro vuoi cancellare tutte le chat?",
     },
     Lang: {
-      Name: "Lingue",
-      All: "All Languages",
+      Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
+      All: "Tutte le lingue",
       Options: {
         cn: "简体中文",
         en: "English",
@@ -81,6 +81,7 @@ const it: LocaleType = {
         jp: "日本語",
         de: "Deutsch",
         vi: "Vietnamese",
+        ru: "Русский",
       },
     },
     Avatar: "Avatar",

+ 2 - 1
app/locales/jp.ts

@@ -69,7 +69,7 @@ const jp: LocaleType = {
       ConfirmClearAll: "すべてのチャットをリセットしてもよろしいですか?",
     },
     Lang: {
-      Name: "Language",
+      Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
       All: "所有语言",
       Options: {
         cn: "简体中文",
@@ -81,6 +81,7 @@ const jp: LocaleType = {
         jp: "日本語",
         de: "Deutsch",
         vi: "Vietnamese",
+        ru: "Русский",
       },
     },
     Avatar: "アバター",

+ 244 - 0
app/locales/ru.ts

@@ -0,0 +1,244 @@
+import { SubmitKey } from "../store/config";
+import type { LocaleType } from "./index";
+
+const ru: LocaleType = {
+  WIP: "Скоро...",
+  Error: {
+    Unauthorized:
+      "Несанкционированный доступ. Пожалуйста, введите код доступа на странице настроек.",
+  },
+  ChatItem: {
+    ChatItemCount: (count: number) => `${count} сообщений`,
+  },
+  Chat: {
+    SubTitle: (count: number) => `${count} сообщений с ChatGPT`,
+    Actions: {
+      ChatList: "Перейти к списку чатов",
+      CompressedHistory: "Сжатая история памяти",
+      Export: "Экспортировать все сообщения в формате Markdown",
+      Copy: "Копировать",
+      Stop: "Остановить",
+      Retry: "Повторить",
+      Delete: "Удалить",
+    },
+    Rename: "Переименовать чат",
+    Typing: "Печатает…",
+    Input: (submitKey: string) => {
+      var inputHints = `${submitKey} для отправки сообщения`;
+      if (submitKey === String(SubmitKey.Enter)) {
+        inputHints += ", Shift + Enter для переноса строки";
+      }
+      return inputHints + ", / для поиска подсказок";
+    },
+    Send: "Отправить",
+    Config: {
+      Reset: "Сбросить настройки",
+      SaveAs: "Сохранить как маску",
+    },
+  },
+  Export: {
+    Title: "Все сообщения",
+    Copy: "Копировать все",
+    Download: "Скачать",
+    MessageFromYou: "Сообщение от вас",
+    MessageFromChatGPT: "Сообщение от ChatGPT",
+  },
+  Memory: {
+    Title: "Память",
+    EmptyContent: "Пусто.",
+    Send: "Отправить память",
+    Copy: "Копировать память",
+    Reset: "Сбросить сессию",
+    ResetConfirm:
+      "При сбросе текущая история переписки и историческая память будут удалены. Вы уверены, что хотите сбросить?",
+  },
+  Home: {
+    NewChat: "Новый чат",
+    DeleteChat: "Вы действительно хотите удалить выбранный разговор?",
+    DeleteToast: "Чат удален",
+    Revert: "Отмена",
+  },
+  Settings: {
+    Title: "Настройки",
+    SubTitle: "Все настройки",
+    Actions: {
+      ClearAll: "Очистить все данные",
+      ResetAll: "Сбросить все настройки",
+      Close: "Закрыть",
+      ConfirmResetAll: "Вы уверены, что хотите сбросить все настройки?",
+      ConfirmClearAll: "Вы уверены, что хотите очистить все данные?",
+    },
+    Lang: {
+      Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
+      All: "Все языки",
+      Options: {
+        cn: "简体中文",
+        en: "English",
+        tw: "繁體中文",
+        es: "Español",
+        it: "Italiano",
+        tr: "Türkçe",
+        jp: "日本語",
+        de: "Deutsch",
+        vi: "Vietnamese",
+        ru: "Русский",
+      },
+    },
+      Avatar: "Аватар",
+      FontSize: {
+        Title: "Размер шрифта",
+        SubTitle: "Настроить размер шрифта контента чата",
+      },
+      Update: {
+        Version: (x: string) => `Версия: ${x}`,
+        IsLatest: "Последняя версия",
+        CheckUpdate: "Проверить обновление",
+        IsChecking: "Проверка обновления...",
+        FoundUpdate: (x: string) => `Найдена новая версия: ${x}`,
+        GoToUpdate: "Обновить",
+      },
+      SendKey: "Клавиша отправки",
+      Theme: "Тема",
+      TightBorder: "Узкая граница",
+      SendPreviewBubble: {
+        Title: "Отправить предпросмотр",
+        SubTitle: "Предварительный просмотр markdown в пузыре",
+      },
+      Mask: {
+        Title: "Экран заставки маски",
+        SubTitle: "Показывать экран заставки маски перед началом нового чата",
+      },
+      Prompt: {
+        Disable: {
+          Title: "Отключить автозаполнение",
+          SubTitle: "Ввод / для запуска автозаполнения",
+        },
+        List: "Список подсказок",
+        ListCount: (builtin: number, custom: number) =>
+          `${builtin} встроенных, ${custom} пользовательских`,
+        Edit: "Редактировать",
+        Modal: {
+          Title: "Список подсказок",
+          Add: "Добавить",
+          Search: "Поиск подсказок",
+        },
+        EditModal: {
+          Title: "Редактировать подсказку",
+        },
+      },
+      HistoryCount: {
+        Title: "Количество прикрепляемых сообщений",
+        SubTitle: "Количество отправляемых сообщений, прикрепляемых к каждому запросу",
+    },
+    CompressThreshold: {
+      Title: "Порог сжатия истории",
+      SubTitle:
+        "Будет сжимать, если длина несжатых сообщений превышает указанное значение",
+    },
+    Token: {
+      Title: "API ключ",
+      SubTitle: "Используйте свой ключ, чтобы игнорировать лимит доступа",
+      Placeholder: "API ключ OpenAI",
+    },
+    Usage: {
+      Title: "Баланс аккаунта",
+      SubTitle(used: any, total: any) {
+        return `Использовано в этом месяце $${used}, подписка $${total}`;
+      },
+      IsChecking: "Проверка...",
+      Check: "Проверить",
+      NoAccess: "Введите API ключ, чтобы проверить баланс",
+    },
+    AccessCode: {
+      Title: "Код доступа",
+      SubTitle: "Контроль доступа включен",
+      Placeholder: "Требуется код доступа",
+    },
+    Model: "Модель",
+    Temperature: {
+      Title: "Температура",
+      SubTitle: "Чем выше значение, тем более случайный вывод",
+    },
+    MaxTokens: {
+      Title: "Максимальное количество токенов",
+      SubTitle: "Максимальная длина вводных и генерируемых токенов",
+    },
+    PresencePenlty: {
+      Title: "Штраф за повторения",
+      SubTitle:
+        "Чем выше значение, тем больше вероятность общения на новые темы",
+    },
+  },
+  Store: {
+    DefaultTopic: "Новый разговор",
+    BotHello: "Здравствуйте! Как я могу вам помочь сегодня?",
+    Error: "Что-то пошло не так. Пожалуйста, попробуйте еще раз позже.",
+    Prompt: {
+      History: (content: string) =>
+        "Это краткое содержание истории чата между ИИ и пользователем: " +
+        content,
+      Topic:
+        "Пожалуйста, создайте заголовок из четырех или пяти слов, который кратко описывает нашу беседу, без введения, знаков пунктуации, кавычек, точек, символов или дополнительного текста. Удалите кавычки.",
+      Summarize:
+        "Кратко изложите нашу дискуссию в 200 словах или менее для использования в будущем контексте.",
+    },
+  },
+  Copy: {
+    Success: "Скопировано в буфер обмена",
+    Failed: "Не удалось скопировать, пожалуйста, предоставьте разрешение на доступ к буферу обмена",
+  },
+  Context: {
+    Toast: (x: any) => `С ${x} контекстными подсказками`,
+    Edit: "Контекстные и памятные подсказки",
+    Add: "Добавить подсказку",
+  },
+  Plugin: {
+    Name: "Плагин",
+  },
+  Mask: {
+    Name: "Маска",
+    Page: {
+      Title: "Шаблон подсказки",
+      SubTitle: (count: number) => `${count} шаблонов подсказок`,
+      Search: "Поиск шаблонов",
+      Create: "Создать",
+    },
+    Item: {
+      Info: (count: number) => `${count} подсказок`,
+      Chat: "Чат",
+      View: "Просмотр",
+      Edit: "Редактировать",
+      Delete: "Удалить",
+      DeleteConfirm: "Подтвердить удаление?",
+    },
+    EditModal: {
+      Title: (readonly: boolean) =>
+        `Редактирование шаблона подсказки ${readonly ? "(только для чтения)" : ""}`,
+      Download: "Скачать",
+      Clone: "Клонировать",
+    },
+    Config: {
+      Avatar: "Аватар бота",
+      Name: "Имя бота",
+    },
+  },
+  NewChat: {
+    Return: "Вернуться",
+    Skip: "Пропустить",
+    Title: "Выберите маску",
+    SubTitle: "Общайтесь с душой за маской",
+    More: "Найти еще",
+    NotShow: "Не показывать снова",
+    ConfirmNoShow: "Подтвердите отключение? Вы можете включить это позже в настройках.",
+  },
+
+  UI: {
+    Confirm: "Подтвердить",
+    Cancel: "Отмена",
+    Close: "Закрыть",
+    Create: "Создать",
+    Edit: "Редактировать",
+  },
+};
+
+export default ru;

+ 2 - 1
app/locales/tr.ts

@@ -70,7 +70,7 @@ const tr: LocaleType = {
     },
     Lang: {
       Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
-      All: "All Languages",
+      All: "Tüm Diller",
       Options: {
         cn: "简体中文",
         en: "English",
@@ -81,6 +81,7 @@ const tr: LocaleType = {
         jp: "日本語",
         de: "Deutsch",
         vi: "Vietnamese",
+        ru: "Русский",
       },
     },
     Avatar: "Avatar",

+ 2 - 1
app/locales/tw.ts

@@ -67,7 +67,7 @@ const tw: LocaleType = {
       ConfirmClearAll: "您確定要清除所有数据嗎?",
     },
     Lang: {
-      Name: "Language",
+      Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
       All: "所有语言",
       Options: {
         cn: "简体中文",
@@ -79,6 +79,7 @@ const tw: LocaleType = {
         jp: "日本語",
         de: "Deutsch",
         vi: "Vietnamese",
+        ru: "Русский",
       },
     },
     Avatar: "大頭貼",

+ 1 - 0
app/locales/vi.ts

@@ -81,6 +81,7 @@ const vi: LocaleType = {
         jp: "日本語",
         de: "Deutsch",
         vi: "Vietnamese",
+        ru: "Русский",
       },
     },
     Avatar: "Ảnh đại diện",

+ 4 - 4
app/utils.ts

@@ -158,15 +158,15 @@ export function autoGrowTextArea(dom: HTMLTextAreaElement) {
 
   const width = getDomContentWidth(dom);
   measureDom.style.width = width + "px";
-  measureDom.innerText = dom.value.trim().length > 0 ? dom.value : "1";
-
-  const emptyLineWrap = Math.max(0, dom.value.split("\n\n").length - 1);
+  measureDom.innerText = dom.value !== "" ? dom.value : "1";
+  const endWithEmptyLine = dom.value.endsWith("\n");
   const height = parseFloat(window.getComputedStyle(measureDom).height);
   const singleLineHeight = parseFloat(
     window.getComputedStyle(singleLineDom).height,
   );
 
-  const rows = Math.round(height / singleLineHeight) + emptyLineWrap;
+  const rows =
+    Math.round(height / singleLineHeight) + (endWithEmptyLine ? 1 : 0);
 
   return rows;
 }

+ 39 - 0
docs/cloudflare-pages-cn.md

@@ -0,0 +1,39 @@
+# Cloudflare Pages 部署指南
+
+## 如何新建项目
+在 Github 上 fork 本项目,然后登录到 dash.cloudflare.com 并进入 Pages。
+
+1. 点击 "Create a project"。
+2. 选择 "Connect to Git"。
+3. 关联 Cloudflare Pages 和你的 GitHub 账号。
+4. 选中你 fork 的此项目。
+5. 点击 "Begin setup"。
+6. 对于 "Project name" 和 "Production branch",可以使用默认值,也可以根据需要进行更改。
+7. 在 "Build Settings" 中,选择 "Framework presets" 选项并选择 "Next.js"。
+8. 由于 node:buffer 的 bug,暂时不要使用默认的 "Build command"。请使用以下命令:
+   ```
+   npx https://prerelease-registry.devprod.cloudflare.dev/next-on-pages/runs/4930842298/npm-package-next-on-pages-230 --experimental-minify
+   ```
+9. 对于 "Build output directory",使用默认值并且不要修改。
+10. 不要修改 "Root Directory"。
+11. 对于 "Environment variables",点击 ">" 然后点击 "Add variable"。按照以下信息填写:
+
+    - `NODE_VERSION=20.1`
+    - `NEXT_TELEMETRY_DISABLE=1`
+    - `OPENAI_API_KEY=你自己的API Key`
+    - `YARN_VERSION=1.22.19`
+    - `PHP_VERSION=7.4`
+
+    根据实际需要,可以选择填写以下选项:
+
+    - `CODE= 可选填,访问密码,可以使用逗号隔开多个密码`
+    - `OPENAI_ORG_ID= 可选填,指定 OpenAI 中的组织 ID`
+    - `HIDE_USER_API_KEY=1 可选,不让用户自行填入 API Key`
+    - `DISABLE_GPT4=1 可选,不让用户使用 GPT-4`
+    
+12. 点击 "Save and Deploy"。
+13. 点击 "Cancel deployment",因为需要填写 Compatibility flags。
+14. 前往 "Build settings"、"Functions",找到 "Compatibility flags"。
+15. 在 "Configure Production compatibility flag" 和 "Configure Preview compatibility flag" 中填写 "nodejs_compat"。
+16. 前往 "Deployments",点击 "Retry deployment"。
+17. Enjoy.

+ 38 - 0
docs/cloudflare-pages-en.md

@@ -0,0 +1,38 @@
+# Cloudflare Pages Deployment Guide
+
+## How to create a new project
+Fork this project on GitHub, then log in to dash.cloudflare.com and go to Pages.
+
+1. Click "Create a project".
+2. Choose "Connect to Git".
+3. Connect Cloudflare Pages to your GitHub account.
+4. Select the forked project.
+5. Click "Begin setup".
+6. For "Project name" and "Production branch", use the default values or change them as needed.
+7. In "Build Settings", choose the "Framework presets" option and select "Next.js".
+8. Do not use the default "Build command" due to a node:buffer bug. Instead, use the following command:
+    ```
+    npx https://prerelease-registry.devprod.cloudflare.dev/next-on-pages/runs/4930842298/npm-package-next-on-pages-230 --experimental-minify
+    ```
+9. For "Build output directory", use the default value and do not modify it.
+10. Do not modify "Root Directory".
+11. For "Environment variables", click ">" and then "Add variable". Fill in the following information:
+    - `NODE_VERSION=20.1`
+    - `NEXT_TELEMETRY_DISABLE=1`
+    - `OPENAI_API_KEY=your_own_API_key`
+    - `YARN_VERSION=1.22.19`
+    - `PHP_VERSION=7.4`
+
+    Optionally fill in the following based on your needs:
+
+    - `CODE= Optional, access passwords, multiple passwords can be separated by commas`
+    - `OPENAI_ORG_ID= Optional, specify the organization ID in OpenAI`
+    - `HIDE_USER_API_KEY=1 Optional, do not allow users to enter their own API key`
+    - `DISABLE_GPT4=1 Optional, do not allow users to use GPT-4`
+    
+12. Click "Save and Deploy".
+13. Click "Cancel deployment" because you need to fill in Compatibility flags.
+14. Go to "Build settings", "Functions", and find "Compatibility flags".
+15. Fill in "nodejs_compat" for both "Configure Production compatibility flag" and "Configure Preview compatibility flag".
+16. Go to "Deployments" and click "Retry deployment".
+17. Enjoy.