Merge branch 'main' into reset

# Conflicts:
#	app/components/settings.tsx
This commit is contained in:
AprilNEA
2023-04-02 13:45:34 +08:00
44 changed files with 2646 additions and 1124 deletions

View File

@@ -1,3 +1,5 @@
import { SubmitKey } from "../store/app";
const cn = {
WIP: "该功能仍在开发中……",
Error: {
@@ -16,8 +18,15 @@ const cn = {
Stop: "停止",
Retry: "重试",
},
Rename: "重命名对话",
Typing: "正在输入…",
Input: (submitKey: string) => `输入消息,${submitKey} 发送`,
Input: (submitKey: string) => {
var inputHints = `输入消息,${submitKey} 发送`;
if (submitKey === String(SubmitKey.Enter)) {
inputHints += "Shift + Enter 换行";
}
return inputHints;
},
Send: "发送",
},
Export: {
@@ -45,11 +54,18 @@ const cn = {
Lang: {
Name: "Language",
Options: {
cn: "中文",
cn: "简体中文",
en: "English",
tw: "繁體中文",
es: "Español",
},
},
Avatar: "头像",
FontSize: {
Title: "字体大小",
SubTitle: "聊天内容的字体大小",
},
Update: {
Version: (x: string) => `当前版本:${x}`,
IsLatest: "已是最新版本",
@@ -61,6 +77,16 @@ const cn = {
SendKey: "发送键",
Theme: "主题",
TightBorder: "紧凑边框",
Prompt: {
Disable: {
Title: "禁用提示词自动补全",
SubTitle: "在输入框开头输入 / 即可触发自动补全",
},
List: "自定义提示词列表",
ListCount: (builtin: number, custom: number) =>
`内置 ${builtin} 条,用户定义 ${custom}`,
Edit: "编辑",
},
HistoryCount: {
Title: "附带历史消息数",
SubTitle: "每次请求携带的历史消息数",
@@ -74,6 +100,14 @@ const cn = {
SubTitle: "使用自己的 Key 可绕过受控访问限制",
Placeholder: "OpenAI API Key",
},
Usage: {
Title: "账户余额",
SubTitle(granted: any, used: any) {
return `总共 $${granted},已使用 $${used}`;
},
IsChecking: "正在检查…",
Check: "重新检查",
},
AccessCode: {
Title: "访问码",
SubTitle: "现在是受控访问状态",
@@ -101,7 +135,7 @@ const cn = {
History: (content: string) =>
"这是 ai 和用户的历史聊天总结作为前情提要:" + content,
Topic:
"直接返回这句话的简要主题,不要解释,如果没有主题,请直接返回“闲聊”",
"使用四到五个字直接返回这句话的简要主题,不要解释、不要标点、不要语气词、不要多余文本,如果没有主题,请直接返回“闲聊”",
Summarize:
"简要总结一下你和用户的对话,用作后续的上下文提示 prompt控制在 50 字以内",
},

View File

@@ -1,3 +1,4 @@
import { SubmitKey } from "../store/app";
import type { LocaleType } from "./index";
const en: LocaleType = {
@@ -19,9 +20,15 @@ const en: LocaleType = {
Stop: "Stop",
Retry: "Retry",
},
Rename: "Rename Chat",
Typing: "Typing…",
Input: (submitKey: string) =>
`Type something and press ${submitKey} to send`,
Input: (submitKey: string) => {
var inputHints = `Type something and press ${submitKey} to send`;
if (submitKey === String(SubmitKey.Enter)) {
inputHints += ", press Shift + Enter to newline";
}
return inputHints;
},
Send: "Send",
},
Export: {
@@ -47,13 +54,19 @@ const en: LocaleType = {
Close: "Close",
},
Lang: {
Name: "语言",
Name: "Language",
Options: {
cn: "中文",
cn: "简体中文",
en: "English",
tw: "繁體中文",
es: "Español",
},
},
Avatar: "Avatar",
FontSize: {
Title: "Font Size",
SubTitle: "Adjust font size of chat content",
},
Update: {
Version: (x: string) => `Version: ${x}`,
IsLatest: "Latest version",
@@ -65,6 +78,16 @@ const en: LocaleType = {
SendKey: "Send Key",
Theme: "Theme",
TightBorder: "Tight Border",
Prompt: {
Disable: {
Title: "Disable auto-completion",
SubTitle: "Input / to trigger auto-completion",
},
List: "Prompt List",
ListCount: (builtin: number, custom: number) =>
`${builtin} built-in, ${custom} user-defined`,
Edit: "Edit",
},
HistoryCount: {
Title: "Attached Messages Count",
SubTitle: "Number of sent messages attached per request",
@@ -79,6 +102,14 @@ const en: LocaleType = {
SubTitle: "Use your key to ignore access code limit",
Placeholder: "OpenAI API Key",
},
Usage: {
Title: "Account Balance",
SubTitle(granted: any, used: any) {
return `Total $${granted}, Used $${used}`;
},
IsChecking: "Checking...",
Check: "Check Again",
},
AccessCode: {
Title: "Access Code",
SubTitle: "Access control enabled",
@@ -108,7 +139,7 @@ const en: LocaleType = {
"This is a summary of the chat history between the AI and the user as a recap: " +
content,
Topic:
"Provide a brief topic of the sentence without explanation. If there is no topic, return 'Chitchat'.",
"Please generate a four to five word title summarizing our conversation without any lead-in, punctuation, quotation marks, periods, symbols, or additional text. Remove enclosing quotation marks.",
Summarize:
"Summarize our discussion briefly in 50 characters or less to use as a prompt for future context.",
},

156
app/locales/es.ts Normal file
View File

@@ -0,0 +1,156 @@
import { SubmitKey } from "../store/app";
import type { LocaleType } from "./index";
const es: LocaleType = {
WIP: "En construcción...",
Error: {
Unauthorized:
"Acceso no autorizado, por favor ingrese el código de acceso en la página de configuración.",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} mensajes`,
},
Chat: {
SubTitle: (count: number) => `${count} mensajes con ChatGPT`,
Actions: {
ChatList: "Ir a la lista de chats",
CompressedHistory: "Historial de memoria comprimido",
Export: "Exportar todos los mensajes como Markdown",
Copy: "Copiar",
Stop: "Detener",
Retry: "Reintentar",
},
Rename: "Renombrar chat",
Typing: "Escribiendo...",
Input: (submitKey: string) => {
var inputHints = `Escribe algo y presiona ${submitKey} para enviar`;
if (submitKey === String(SubmitKey.Enter)) {
inputHints += ", presiona Shift + Enter para nueva línea";
}
return inputHints;
},
Send: "Enviar",
},
Export: {
Title: "Todos los mensajes",
Copy: "Copiar todo",
Download: "Descargar",
},
Memory: {
Title: "Historial de memoria",
EmptyContent: "Aún no hay nada.",
Copy: "Copiar todo",
},
Home: {
NewChat: "Nuevo chat",
DeleteChat: "¿Confirmar eliminación de la conversación seleccionada?",
},
Settings: {
Title: "Configuración",
SubTitle: "Todas las configuraciones",
Actions: {
ClearAll: "Borrar todos los datos",
ResetAll: "Restablecer todas las configuraciones",
Close: "Cerrar",
},
Lang: {
Name: "Language",
Options: {
cn: "简体中文",
en: "Inglés",
tw: "繁體中文",
es: "Español",
},
},
Avatar: "Avatar",
FontSize: {
Title: "Tamaño de fuente",
SubTitle: "Ajustar el tamaño de fuente del contenido del chat",
},
Update: {
Version: (x: string) => `Versión: ${x}`,
IsLatest: "Última versión",
CheckUpdate: "Buscar actualizaciones",
IsChecking: "Buscando actualizaciones...",
FoundUpdate: (x: string) => `Se encontró una nueva versión: ${x}`,
GoToUpdate: "Actualizar",
},
SendKey: "Tecla de envío",
Theme: "Tema",
TightBorder: "Borde ajustado",
Prompt: {
Disable: {
Title: "Desactivar autocompletado",
SubTitle: "Escribe / para activar el autocompletado",
},
List: "Lista de autocompletado",
ListCount: (builtin: number, custom: number) =>
`${builtin} incorporado, ${custom} definido por el usuario`,
Edit: "Editar",
},
HistoryCount: {
Title: "Cantidad de mensajes adjuntos",
SubTitle: "Número de mensajes enviados adjuntos por solicitud",
},
CompressThreshold: {
Title: "Umbral de compresión de historial",
SubTitle:
"Se comprimirán los mensajes si la longitud de los mensajes no comprimidos supera el valor",
},
Token: {
Title: "Clave de API",
SubTitle: "Utiliza tu clave para ignorar el límite de código de acceso",
Placeholder: "Clave de la API de OpenAI",
},
Usage: {
Title: "Saldo de la cuenta",
SubTitle(granted: any, used: any) {
return `Total $${granted}, Usado $${used}`;
},
IsChecking: "Comprobando...",
Check: "Comprobar de nuevo",
},
AccessCode: {
Title: "Código de acceso",
SubTitle: "Control de acceso habilitado",
Placeholder: "Necesita código de acceso",
},
Model: "Modelo",
Temperature: {
Title: "Temperatura",
SubTitle: "Un valor mayor genera una salida más aleatoria",
},
MaxTokens: {
Title: "Máximo de tokens",
SubTitle: "Longitud máxima de tokens de entrada y tokens generados",
},
PresencePenlty: {
Title: "Penalización de presencia",
SubTitle:
"Un valor mayor aumenta la probabilidad de hablar sobre nuevos temas",
},
},
Store: {
DefaultTopic: "Nueva conversación",
BotHello: "¡Hola! ¿Cómo puedo ayudarte hoy?",
Error: "Algo salió mal, por favor intenta nuevamente más tarde.",
Prompt: {
History: (content: string) =>
"Este es un resumen del historial del chat entre la IA y el usuario como recapitulación: " +
content,
Topic:
"Por favor, genera un título de cuatro a cinco palabras que resuma nuestra conversación sin ningún inicio, puntuación, comillas, puntos, símbolos o texto adicional. Elimina las comillas que lo envuelven.",
Summarize:
"Resuma nuestra discusión brevemente en 50 caracteres o menos para usarlo como un recordatorio para futuros contextos.",
},
ConfirmClearAll:
"¿Confirmar para borrar todos los datos de chat y configuración?",
},
Copy: {
Success: "Copiado al portapapeles",
Failed:
"La copia falló, por favor concede permiso para acceder al portapapeles",
},
};
export default es;

View File

@@ -1,53 +1,60 @@
import CN from './cn'
import EN from './en'
import CN from "./cn";
import EN from "./en";
import TW from "./tw";
import ES from "./es";
export type { LocaleType } from './cn'
export type { LocaleType } from "./cn";
type Lang = 'en' | 'cn'
export const AllLangs = ["en", "cn", "tw", "es"] as const;
type Lang = (typeof AllLangs)[number];
const LANG_KEY = 'lang'
const LANG_KEY = "lang";
function getItem(key: string) {
try {
return localStorage.getItem(key)
} catch {
return null
}
try {
return localStorage.getItem(key);
} catch {
return null;
}
}
function setItem(key: string, value: string) {
try {
localStorage.setItem(key, value)
} catch { }
try {
localStorage.setItem(key, value);
} catch {}
}
function getLanguage() {
try {
return navigator.language.toLowerCase()
} catch {
return 'cn'
}
try {
return navigator.language.toLowerCase();
} catch {
return "cn";
}
}
export function getLang(): Lang {
const savedLang = getItem(LANG_KEY)
const savedLang = getItem(LANG_KEY);
if (['en', 'cn'].includes(savedLang ?? '')) {
return savedLang as Lang
}
if (AllLangs.includes((savedLang ?? "") as Lang)) {
return savedLang as Lang;
}
const lang = getLanguage()
const lang = getLanguage();
if (lang.includes('zh') || lang.includes('cn')) {
return 'cn'
} else {
return 'en'
}
if (lang.includes("zh") || lang.includes("cn")) {
return "cn";
} else if (lang.includes("tw")) {
return "tw";
} else if (lang.includes("es")) {
return "es";
} else {
return "en";
}
}
export function changeLang(lang: Lang) {
setItem(LANG_KEY, lang)
location.reload()
setItem(LANG_KEY, lang);
location.reload();
}
export default { en: EN, cn: CN }[getLang()]
export default { en: EN, cn: CN, tw: TW, es: ES }[getLang()];

149
app/locales/tw.ts Normal file
View File

@@ -0,0 +1,149 @@
import { SubmitKey } from "../store/app";
import type { LocaleType } from "./index";
const tw: LocaleType = {
WIP: "該功能仍在開發中……",
Error: {
Unauthorized: "目前您的狀態是未授權,請前往設定頁面填寫授權碼。",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} 條對話`,
},
Chat: {
SubTitle: (count: number) => `您已經與 ChatGPT 進行了 ${count} 條對話`,
Actions: {
ChatList: "查看消息列表",
CompressedHistory: "查看壓縮後的歷史 Prompt",
Export: "匯出聊天紀錄",
Copy: "複製",
Stop: "停止",
Retry: "重試",
},
Rename: "重命名對話",
Typing: "正在輸入…",
Input: (submitKey: string) => {
var inputHints = `輸入訊息後,按下 ${submitKey} 鍵即可發送`;
if (submitKey === String(SubmitKey.Enter)) {
inputHints += "Shift + Enter 鍵換行";
}
return inputHints;
},
Send: "發送",
},
Export: {
Title: "匯出聊天記錄為 Markdown",
Copy: "複製全部",
Download: "下載檔案",
},
Memory: {
Title: "上下文記憶 Prompt",
EmptyContent: "尚未記憶",
Copy: "複製全部",
},
Home: {
NewChat: "新的對話",
DeleteChat: "確定要刪除選取的對話嗎?",
},
Settings: {
Title: "設定",
SubTitle: "設定選項",
Actions: {
ClearAll: "清除所有數據",
ResetAll: "重置所有設定",
Close: "關閉",
},
Lang: {
Name: "Language",
Options: {
cn: "简体中文",
en: "English",
tw: "繁體中文",
es: "Español",
},
},
Avatar: "大頭貼",
FontSize: {
Title: "字型大小",
SubTitle: "聊天內容的字型大小",
},
Update: {
Version: (x: string) => `當前版本:${x}`,
IsLatest: "已是最新版本",
CheckUpdate: "檢查更新",
IsChecking: "正在檢查更新...",
FoundUpdate: (x: string) => `發現新版本:${x}`,
GoToUpdate: "前往更新",
},
SendKey: "發送鍵",
Theme: "主題",
TightBorder: "緊湊邊框",
Prompt: {
Disable: {
Title: "停用提示詞自動補全",
SubTitle: "在輸入框開頭輸入 / 即可觸發自動補全",
},
List: "自定義提示詞列表",
ListCount: (builtin: number, custom: number) =>
`內置 ${builtin} 條,用戶定義 ${custom}`,
Edit: "編輯",
},
HistoryCount: {
Title: "附帶歷史訊息數",
SubTitle: "每次請求附帶的歷史訊息數",
},
CompressThreshold: {
Title: "歷史訊息長度壓縮閾值",
SubTitle: "當未壓縮的歷史訊息超過該值時,將進行壓縮",
},
Token: {
Title: "API Key",
SubTitle: "使用自己的 Key 可規避受控訪問限制",
Placeholder: "OpenAI API Key",
},
Usage: {
Title: "帳戶餘額",
SubTitle(granted: any, used: any) {
return `總共 $${granted},已使用 $${used}`;
},
IsChecking: "正在檢查…",
Check: "重新檢查",
},
AccessCode: {
Title: "訪問碼",
SubTitle: "現在是受控訪問狀態",
Placeholder: "請輸入訪問碼",
},
Model: "模型 (model)",
Temperature: {
Title: "隨機性 (temperature)",
SubTitle: "值越大,回復越隨機",
},
MaxTokens: {
Title: "單次回復限制 (max_tokens)",
SubTitle: "單次交互所用的最大 Token 數",
},
PresencePenlty: {
Title: "話題新穎度 (presence_penalty)",
SubTitle: "值越大,越有可能擴展到新話題",
},
},
Store: {
DefaultTopic: "新的對話",
BotHello: "請問需要我的協助嗎?",
Error: "出錯了,請稍後再嘗試",
Prompt: {
History: (content: string) =>
"這是 AI 與用戶的歷史聊天總結,作為前情提要:" + content,
Topic: "直接返回這句話的簡要主題,無須解釋,若無主題,請直接返回「閒聊」",
Summarize:
"簡要總結一下你和用戶的對話,作為後續的上下文提示 prompt且字數控制在 50 字以內",
},
ConfirmClearAll: "確認清除所有對話、設定數據?",
},
Copy: {
Success: "已複製到剪貼簿中",
Failed: "複製失敗,請賦予剪貼簿權限",
},
};
export default tw;