The reset link is valid within %d minutes. If it is not your operation, please ignore it.
",
+ "重置链接非法或已过期": "Reset link is illegal or expired",
+ "无法启用 GitHub OAuth,请先填入 GitHub Client ID 以及 GitHub Client Secret!": "Unable to enable GitHub OAuth, please fill in GitHub Client ID and GitHub Client Secret first!",
+ "无法启用微信登录,请先填入微信登录相关配置信息!": "Unable to enable WeChat login, please fill in the relevant configuration information for WeChat login first!",
+ "无法启用 Turnstile 校验,请先填入 Turnstile 校验相关配置信息!": "Unable to enable Turnstile verification, please fill in the relevant configuration information for Turnstile verification first!",
+ "兑换码名称长度必须在1-20之间": "The length of the redemption code name must be between 1-20",
+ "兑换码个数必须大于0": "The number of redemption codes must be greater than 0",
+ "一次兑换码批量生成的个数不能大于 100": "The number of redemption codes generated in a batch cannot be greater than 100",
+ "通过令牌「%s」使用模型 %s 消耗 %s(模型倍率 %.2f,分组倍率 %.2f)": "Using model %s with token %s consumes %s (model rate %.2f, group rate %.2f)",
+ "当前分组负载已饱和,请稍后再试,或升级账户以提升服务质量。": "The current group load is saturated, please try again later, or upgrade your account to improve service quality.",
+ "令牌名称长度必须在1-20之间": "The length of the token name must be between 1-20",
+ "令牌已过期,无法启用,请先修改令牌过期时间": "The token has expired and cannot be enabled. Please modify the token expiration time first",
+ "令牌可用额度已用尽,无法启用,请先修改令牌剩余额度,或者设置为无限额度": "The available quota of the token has been used up and cannot be enabled. Please modify the remaining quota of the token, or set it to unlimited quota",
+ "管理员关闭了密码登录": "The administrator has turned off password login",
+ "无法保存会话信息,请重试": "Unable to save session information, please try again",
+ "管理员关闭了通过密码进行注册,请使用第三方账户验证的形式进行注册": "The administrator has turned off registration via password. Please use the form of third-party account verification to register",
+ "输入不合法 ": "Input is illegal ",
+ "管理员开启了邮箱验证,请输入邮箱地址和验证码": "The administrator has turned on email verification, please enter the email address and verification code",
+ "验证码错误或已过期": "Verification code error or expired",
+ "无权获取同级或更高等级用户的信息": "No permission to get information of users at the same level or higher",
+ "请重试,系统生成的 UUID 竟然重复了!": "Please try again, the system-generated UUID is actually duplicated!",
+ "输入不合法": "Input is illegal",
+ "无权更新同权限等级或更高权限等级的用户信息": "No permission to update user information with the same permission level or higher permission level",
+ "管理员将用户额度从 %s修改为 %s": "The administrator changed the user quota from %s to %s",
+ "无权删除同权限等级或更高权限等级的用户": "No permission to delete users with the same permission level or higher permission level",
+ "无法创建权限大于等于自己的用户": "Unable to create users with permissions greater than or equal to your own",
+ "用户不存在": "User does not exist",
+ "无法禁用超级管理员用户": "Unable to disable super administrator user",
+ "无法删除超级管理员用户": "Unable to delete super administrator user",
+ "普通管理员用户无法提升其他用户为管理员": "Ordinary administrator users cannot promote other users to administrators",
+ "该用户已经是管理员": "The user is already an administrator",
+ "无法降级超级管理员用户": "Unable to downgrade super administrator user",
+ "该用户已经是普通用户": "The user is already an ordinary user",
+ "管理员未开启通过微信登录以及注册": "The administrator has not enabled login and registration via WeChat",
+ "该微信账号已被绑定": "The WeChat account has been bound",
+ "无权进行此操作,未登录且未提供 access token": "No permission to perform this operation, not logged in and no access token provided",
+ "无权进行此操作,access token 无效": "No permission to perform this operation, access token is invalid",
+ "无权进行此操作,权限不足": "No permission to perform this operation, insufficient permissions",
+ "普通用户不支持指定渠道": "Ordinary users do not support specifying channels",
+ "无效的渠道 ID": "Invalid channel ID",
+ "该渠道已被禁用": "The channel has been disabled",
+ "无效的请求": "Invalid request",
+ "无可用渠道": "No available channels",
+ "Turnstile token 为空": "Turnstile token is empty",
+ "Turnstile 校验失败,请刷新重试!": "Turnstile verification failed, please refresh and try again!",
+ "id 为空!": "id is empty!",
+ "未提供兑换码": "No redemption code provided",
+ "无效的 user id": "Invalid user id",
+ "无效的兑换码": "Invalid redemption code",
+ "该兑换码已被使用": "The redemption code has been used",
+ "通过兑换码充值 %s": "Recharge %s through redemption code",
+ "未提供令牌": "No token provided",
+ "该令牌状态不可用": "The token status is not available",
+ "该令牌已过期": "The token has expired",
+ "该令牌额度已用尽": "The token quota has been used up",
+ "无效的令牌": "Invalid token",
+ "id 或 userId 为空!": "id or userId is empty!",
+ "quota 不能为负数!": "quota cannot be negative!",
+ "令牌额度不足": "Insufficient token quota",
+ "用户额度不足": "Insufficient user quota",
+ "您的额度即将用尽": "Your quota is about to run out",
+ "您的额度已用尽": "Your quota has been used up",
+ "%s,当前剩余额度为 %d,为了不影响您的使用,请及时充值。 充值链接:%s": "%s, the current remaining quota is %d, in order not to affect your use, please recharge in time. Recharge link: %s",
+ "affCode 为空!": "affCode is empty!",
+ "新用户注册赠送 %s": "New user registration gives %s",
+ "使用邀请码赠送 %s": "Use invitation code to give %s",
+ "邀请用户赠送 %s": "Invite users to give %s",
+ "用户名或密码为空": "Username or password is empty",
+ "用户名或密码错误,或用户已被封禁": "Username or password is wrong, or user has been banned",
+ "email 为空!": "email is empty!",
+ "GitHub id 为空!": "GitHub id is empty!",
+ "WeChat id 为空!": "WeChat id is empty!",
+ "username 为空!": "username is empty!",
+ "邮箱地址或密码为空!": "Email address or password is empty!",
+ "OpenAI 接口聚合管理,支持多种渠道包括 Azure,可用于二次分发管理 key,仅单可执行文件,已打包好 Docker 镜像,一键部署,开箱即用": "OpenAI interface aggregation management, supports multiple channels including Azure, can be used for secondary distribution management key, only single executable file, Docker image has been packaged, one-click deployment, out of the box",
+ "未知类型": "Unknown type",
+ "不支持": "Not supported",
+ "操作成功完成!": "Operation completed successfully!",
+ "已启用": "Enabled",
+ "已禁用": "Disabled",
+ "未知状态": "Unknown status",
+ " 秒": "s",
+ "未测试": "Not tested",
+ "通道 ${name} 测试成功,耗时 ${time.toFixed(2)} 秒。": "Channel ${name} test succeeded, time consumed ${time.toFixed(2)} s.",
+ "已成功开始测试所有已启用通道,请刷新页面查看结果。": "All enabled channels have been successfully tested, please refresh the page to view the results.",
+ "通道 ${name} 余额更新成功!": "Channel ${name} balance updated successfully!",
+ "已更新完毕所有已启用通道余额!": "The balance of all enabled channels has been updated!",
+ "搜索渠道的 ID,名称和密钥 ...": "Search for channel ID, name and key ...",
+ "名称": "Name",
+ "分组": "Group",
+ "类型": "Type",
+ "状态": "Status",
+ "响应时间": "Response time",
+ "余额": "Balance",
+ "操作": "Operation",
+ "未更新": "Not updated",
+ "测试": "Test",
+ "更新余额": "Update balance",
+ "删除": "Delete",
+ "删除渠道 {channel.name}": "Delete channel {channel.name}",
+ "禁用": "Disable",
+ "启用": "Enable",
+ "编辑": "Edit",
+ "添加新的渠道": "Add a new channel",
+ "测试所有已启用通道": "Test all enabled channels",
+ "更新所有已启用通道余额": "Update the balance of all enabled channels",
+ "刷新": "Refresh",
+ "处理中...": "Processing...",
+ "绑定成功!": "Binding succeeded!",
+ "登录成功!": "Login succeeded!",
+ "操作失败,重定向至登录界面中...": "Operation failed, redirecting to the login page...",
+ "出现错误,第 ${count} 次重试中...": "An error occurred, retrying for the ${count} time...",
+ "首页": "Home",
+ "渠道": "Channel",
+ "令牌": "Token",
+ "兑换": "Redeem",
+ "充值": "Recharge",
+ "用户": "User",
+ "日志": "Log",
+ "设置": "Settings",
+ "关于": "About",
+ "聊天": "Chat",
+ "注销成功!": "Logout succeeded!",
+ "注销": "Logout",
+ "登录": "Login",
+ "注册": "Register",
+ "加载{name}中...": "Loading {name}...",
+ "未登录或登录已过期,请重新登录!": "Not logged in or login has expired, please log in again!",
+ "用户登录": "User login",
+ "\"用户名\"": "\"Username\"",
+ "\"密码\"": "\"Password\"",
+ "忘记密码?": "Forget password?",
+ "点击重置": "Click to reset",
+ "; 没有账户?": "; No account?",
+ "点击注册": "Click to register",
+ "微信扫码关注公众号,输入「验证码」获取验证码(三分钟内有效)": "Scan the QR code of WeChat to follow the official account, enter \"verification code\" to get the verification code (valid within three minutes)",
+ "\"验证码\"": "\"Verification code\"",
+ "全部用户": "All users",
+ "当前用户": "Current user",
+ "'全部'": "'All'",
+ "'充值'": "'Recharge'",
+ "'消费'": "'Consumption'",
+ "'管理'": "'Management'",
+ "'系统'": "'System'",
+ " 充值 ": " Recharge ",
+ " 消费 ": " Consumption ",
+ " 管理 ": " Management ",
+ " 系统 ": " System ",
+ " 未知 ": " Unknown ",
+ "时间": "Time",
+ "详情": "Details",
+ "选择模式": "Select mode",
+ "选择明细分类": "Select details category",
+ "模型倍率不是合法的 JSON 字符串": "Model rate is not a valid JSON string",
+ "分组倍率不是合法的 JSON 字符串": "Group rate is not a valid JSON string",
+ "通用设置": "General Settings",
+ "充值链接": "Recharge Link",
+ "例如发卡网站的购买链接": "For example, the purchase link of the card issuing website",
+ "聊天页面链接": "Chat Page Link",
+ "例如 ChatGPT Next Web 的部署地址": "For example, the deployment address of ChatGPT Next Web",
+ "单位美元额度": "Unit Dollar Quota",
+ "一单位货币能兑换的额度": "Quota that can be exchanged for one unit of currency",
+ "启用额度消费日志记录": "Enable quota consumption log recording",
+ "以货币形式显示额度": "Display quota in the form of currency",
+ "相关 API 显示令牌额度而非用户额度": "Related API displays token quota instead of user quota",
+ "保存通用设置": "Save General Settings",
+ "监控设置": "Monitoring Settings",
+ "最长响应时间": "Longest Response Time",
+ "单位秒": "Unit in seconds",
+ "当运行通道全部测试时": "When all operating channels are tested",
+ "超过此时间将自动禁用通道": "Channels will be automatically disabled if this time is exceeded",
+ "额度提醒阈值": "Quota reminder threshold",
+ "低于此额度时将发送邮件提醒用户": "Email will be sent to remind users when the quota is below this",
+ "失败时自动禁用通道": "Automatically disable the channel when it fails",
+ "保存监控设置": "Save Monitoring Settings",
+ "额度设置": "Quota Settings",
+ "新用户初始额度": "Initial quota for new users",
+ "例如": "For example",
+ "请求预扣费额度": "Request for pre-deducted quota",
+ "请求结束后多退少补": "Refund more or less after the request ends",
+ "邀请新用户奖励额度": "Invite new users to reward quota",
+ "新用户使用邀请码奖励额度": "New user rewards quota using invitation code",
+ "保存额度设置": "Save Quota Settings",
+ "倍率设置": "Rate Settings",
+ "模型倍率": "Model rate",
+ "为一个 JSON 文本": "Is a JSON text",
+ "键为模型名称": "Key is model name",
+ "值为倍率": "Value is the rate",
+ "分组倍率": "Group rate",
+ "键为分组名称": "Key is group name",
+ "保存倍率设置": "Save Rate Settings",
+ "已是最新版本": "Is the latest version",
+ "检查更新": "Check for updates",
+ "公告": "Announcement",
+ "在此输入新的公告内容": "Enter new announcement content here",
+ "保存公告": "Save Announcement",
+ "个性化设置": "Personalization Settings",
+ "系统名称": "System Name",
+ "在此输入系统名称": "Enter the system name here",
+ "设置系统名称": "Set system name",
+ "图片地址": "Image URL",
+ "在此输入 Logo 图片地址": "Enter the Logo image URL here",
+ "首页内容": "Home Page Content",
+ "在此输入首页内容,支持 Markdown & HTML 代码,设置后首页的状态信息将不再显示。如果输入的是一个链接,则会使用该链接作为 iframe 的 src 属性,这允许你设置任意网页作为首页": "Enter the homepage content here, supports Markdown & HTML code. Once set, the status information of the homepage will not be displayed. If a link is entered, it will be used as the src attribute of the iframe, allowing you to set any webpage as the homepage.",
+ "保存首页内容": "Save Home Page Content",
+ "在此输入新的关于内容,支持 Markdown & HTML 代码。如果输入的是一个链接,则会使用该链接作为 iframe 的 src 属性,这允许你设置任意网页作为关于页面": "Enter new about content here, supports Markdown & HTML code. If a link is entered, it will be used as the src attribute of the iframe, allowing you to set any webpage as the about page.",
+ "保存关于": "Save About",
+ "移除 One API 的版权标识必须首先获得授权,项目维护需要花费大量精力,如果本项目对你有意义,请主动支持本项目": "Removal of One API copyright mark must first be authorized. Project maintenance requires a lot of effort. If this project is meaningful to you, please actively support it.",
+ "页脚": "Footer",
+ "在此输入新的页脚,留空则使用默认页脚,支持 HTML 代码": "Enter the new footer here, leave blank to use the default footer, supports HTML code.",
+ "设置页脚": "Set Footer",
+ "新版本": "New Version",
+ "关闭": "Close",
+ "密码已重置并已复制到剪贴板": "Password has been reset and copied to clipboard",
+ "密码重置确认": "Password Reset Confirmation",
+ "邮箱地址": "Email Address",
+ "提交": "Submit",
+ "请稍后几秒重试": "Please retry in a few seconds",
+ "正在检查用户环境": "Checking user environment",
+ "重置邮件发送成功": "Reset mail sent successfully",
+ "请检查邮箱": "Please check your email",
+ "密码重置": "Password Reset",
+ "令牌已重置并已复制到剪贴板": "Token has been reset and copied to clipboard",
+ "邀请链接已复制到剪切板": "Invitation link has been copied to clipboard",
+ "微信账户绑定成功": "WeChat account binding succeeded",
+ "验证码发送成功": "Verification code sent successfully",
+ "邮箱账户绑定成功": "Email account binding succeeded",
+ "注意": "Note",
+ "此处生成的令牌用于系统管理": "The token generated here is used for system management",
+ "而非用于请求 OpenAI 相关的服务": "Not for requesting OpenAI related services",
+ "请知悉": "Please be aware",
+ "更新个人信息": "Update Personal Information",
+ "生成系统访问令牌": "Generate System Access Token",
+ "复制邀请链接": "Copy Invitation Link",
+ "账号绑定": "Account Binding",
+ "绑定微信账号": "Bind WeChat Account",
+ "微信扫码关注公众号": "Scan the QR code with WeChat to follow the official account",
+ "输入": "Enter",
+ "验证码": "Verification Code",
+ "获取验证码": "Get Verification Code",
+ "三分钟内有效": "Valid for three minutes",
+ "绑定": "Bind",
+ "绑定 GitHub 账号": "Bind GitHub Account",
+ "绑定邮箱地址": "Bind Email Address",
+ "输入邮箱地址": "Enter Email Address",
+ "未使用": "Unused",
+ "已使用": "Used",
+ "操作成功完成": "Operation successfully completed",
+ "搜索兑换码的 ID 和名称": "Search for ID and name",
+ "额度": "Quota",
+ "创建时间": "Creation Time",
+ "兑换时间": "Redemption Time",
+ "尚未兑换": "Not yet redeemed",
+ "已复制到剪贴板": "Copied to clipboard",
+ "无法复制到剪贴板": "Unable to copy to clipboard",
+ "请手动复制": "Please copy manually",
+ "已将兑换码填入搜索框": "The voucher code has been filled into the search box",
+ "复制": "Copy",
+ "添加新的兑换码": "Add a new voucher",
+ "密码长度不得小于 8 位": "Password length must not be less than 8 characters",
+ "两次输入的密码不一致": "The two passwords entered do not match",
+ "注册成功": "Registration succeeded",
+ "请稍后几秒重试,Turnstile 正在检查用户环境": "Please retry in a few seconds, Turnstile is checking user environment",
+ "验证码发送成功,请检查你的邮箱": "Verification code sent successfully, please check your email",
+ "新用户注册": "New User Registration",
+ "输入用户名,最长 12 位": "Enter username, up to 12 characters",
+ "输入密码,最短 8 位,最长 20 位": "Enter password, at least 8 characters and up to 20 characters",
+ "输入验证码": "Enter Verification Code",
+ "已有账户": "Already have an account",
+ "点击登录": "Click to log in",
+ "服务器地址": "Server Address",
+ "更新服务器地址": "Update Server Address",
+ "配置登录注册": "Configure Login/Registration",
+ "允许通过密码进行登录": "Allow login via password",
+ "允许通过密码进行注册": "Allow registration via password",
+ "通过密码注册时需要进行邮箱验证": "Email verification is required when registering via password",
+ "允许通过 GitHub 账户登录 & 注册": "Allow login & registration via GitHub account",
+ "允许通过微信登录 & 注册": "Allow login & registration via WeChat",
+ "允许新用户注册(此项为否时,新用户将无法以任何方式进行注册": "Allow new user registration (if this option is off, new users will not be able to register in any way",
+ "启用 Turnstile 用户校验": "Enable Turnstile user verification",
+ "配置 SMTP": "Configure SMTP",
+ "用以支持系统的邮件发送": "To support the system email sending",
+ "SMTP 服务器地址": "SMTP Server Address",
+ "例如:smtp.qq.com": "For example: smtp.qq.com",
+ "SMTP 端口": "SMTP Port",
+ "默认: 587": "Default: 587",
+ "SMTP 账户": "SMTP Account",
+ "通常是邮箱地址": "Usually an email address",
+ "发送者邮箱": "Sender email",
+ "通常和邮箱地址保持一致": "Usually consistent with the email address",
+ "SMTP 访问凭证": "SMTP Access Credential",
+ "敏感信息不会发送到前端显示": "Sensitive information will not be displayed in the frontend",
+ "保存 SMTP 设置": "Save SMTP Settings",
+ "配置 GitHub OAuth App": "Configure GitHub OAuth App",
+ "用以支持通过 GitHub 进行登录注册": "To support login & registration via GitHub",
+ "点击此处": "Click here",
+ "管理你的 GitHub OAuth App": "Manage your GitHub OAuth App",
+ "输入你注册的 GitHub OAuth APP 的 ID": "Enter your registered GitHub OAuth APP ID",
+ "保存 GitHub OAuth 设置": "Save GitHub OAuth Settings",
+ "配置 WeChat Server": "Configure WeChat Server",
+ "用以支持通过微信进行登录注册": "To support login & registration via WeChat",
+ "了解 WeChat Server": "Learn about WeChat Server",
+ "WeChat Server 访问凭证": "WeChat Server Access Credential",
+ "微信公众号二维码图片链接": "WeChat Public Account QR Code Image Link",
+ "输入一个图片链接": "Enter an image link",
+ "保存 WeChat Server 设置": "Save WeChat Server Settings",
+ "配置 Turnstile": "Configure Turnstile",
+ "用以支持用户校验": "To support user verification",
+ "管理你的 Turnstile Sites,推荐选择 Invisible Widget Type": "Manage your Turnstile Sites, recommend selecting Invisible Widget Type",
+ "输入你注册的 Turnstile Site Key": "Enter your registered Turnstile Site Key",
+ "保存 Turnstile 设置": "Save Turnstile Settings",
+ "已过期": "Expired",
+ "已耗尽": "Exhausted",
+ "搜索令牌的名称 ...": "Search for the name of the token...",
+ "已用额度": "Quota used",
+ "剩余额度": "Remaining quota",
+ "过期时间": "Expiration time",
+ "无": "None",
+ "无限制": "Unlimited",
+ "永不过期": "Never expires",
+ "无法复制到剪贴板,请手动复制,已将令牌填入搜索框": "Unable to copy to clipboard, please copy manually, the token has been entered into the search box",
+ "删除令牌": "Delete Token",
+ "添加新的令牌": "Add New Token",
+ "普通用户": "Regular User",
+ "管理员": "Admin",
+ "超级管理员": "Super Admin",
+ "未知身份": "Unknown Identity",
+ "已激活": "Activated",
+ "已封禁": "Banned",
+ "搜索用户的 ID,用户名,显示名称,以及邮箱地址 ...": "Search user ID, username, display name, and email address...",
+ "用户名": "Username",
+ "统计信息": "Statistics",
+ "用户角色": "User Role",
+ "未绑定邮箱地址": "Email not bound",
+ "请求次数": "Number of Requests",
+ "提升": "Promote",
+ "降级": "Demote",
+ "删除用户": "Delete User",
+ "添加新的用户": "Add New User",
+ "自定义": "Custom",
+ "等价金额": "Equivalent Amount",
+ "错误": "Error",
+ "错误:未登录或登录已过期,请重新登录": "Error: Not logged in or login has expired, please log in again",
+ "错误:请求次数过多,请稍后再试": "Error: Too many requests, please try again later",
+ "错误:服务器内部错误,请联系管理员": "Error: Server internal error, please contact the administrator",
+ "本站仅作演示之用,无服务端": "This site is for demonstration purposes only, no server-side",
+ "错误:": "Error:",
+ "新版本可用:${data.version},请使用快捷键 Shift + F5 刷新页面": "New version available: ${data.version}, please refresh the page using shortcut Shift + F5",
+ "无法正常连接至服务器": "Unable to connect to the server normally",
+ "管理渠道": "Manage Channels",
+ "系统状况": "System Status",
+ "系统信息": "System Information",
+ "系统信息总览": "System Information Overview",
+ "版本": "Version",
+ "源码": "Source Code",
+ "启动时间": "Startup Time",
+ "系统配置": "System Configuration",
+ "系统配置总览": "System Configuration Overview",
+ "邮箱验证": "Email Verification",
+ "未": "Not ",
+ "GitHub 身份验证": "GitHub Authentication",
+ "微信身份验证": "WeChat Authentication",
+ "Turnstile 用户校验": "Turnstile User Verification",
+ "创建新的渠道": "Create New Channel",
+ "镜像": "Mirror",
+ "请输入镜像站地址,格式为:https://domain.com,可不填,不填则使用渠道默认值": "Please enter the mirror site address, the format is: https://domain.com, it can be left blank, if left blank, the default value of the channel will be used",
+ "模型": "Model",
+ "请选择该通道所支持的模型": "Please select the model supported by the channel",
+ "填入基础模型": "Fill in the basic model",
+ "填入所有模型": "Fill in all models",
+ "清除所有模型": "Clear all models",
+ "密钥": "Key",
+ "请输入密钥": "Please enter the key",
+ "批量创建": "Batch Create",
+ "更新渠道信息": "Update Channel Information",
+ "我的令牌": "My Tokens",
+ "管理兑换码": "Manage Redeem Codes",
+ "兑换码": "Redeem Code",
+ "管理用户": "Manage Users",
+ "额度明细": "Quota Details",
+ "个人设置": "Personal Settings",
+ "运营设置": "Operation Settings",
+ "系统设置": "System Settings",
+ "其他设置": "Other Settings",
+ "项目仓库地址": "Project Repository Address",
+ "可在设置页面设置关于内容,支持 HTML & Markdown": "You can set the content about in the settings page, support HTML & Markdown",
+ "由{' '}": "build by{' '}",
+ "构建,源代码遵循{' '}": ", the source code licensed under{' '}",
+ "MIT 协议": "MIT License",
+ "充值额度": "Recharge Quota",
+ "获取兑换码": "Get Redeem Code"
+}
\ No newline at end of file
diff --git a/i18n/translate.py b/i18n/translate.py
new file mode 100644
index 00000000..df1fd035
--- /dev/null
+++ b/i18n/translate.py
@@ -0,0 +1,64 @@
+import argparse
+import json
+import os
+
+from tqdm import tqdm
+
+
+def list_file_paths(path):
+ file_paths = []
+ for root, dirs, files in os.walk(path):
+ if "node_modules" in dirs:
+ dirs.remove("node_modules")
+ if "build" in dirs:
+ dirs.remove("build")
+ if "i18n" in dirs:
+ dirs.remove("i18n")
+ for file in files:
+ file_path = os.path.join(root, file)
+ if file_path.endswith("png") or file_path.endswith("ico") or file_path.endswith("db") or file_path.endswith("exe"):
+ continue
+ file_paths.append(file_path)
+
+ for dir in dirs:
+ dir_path = os.path.join(root, dir)
+ file_paths += list_file_paths(dir_path)
+
+ return file_paths
+
+
+def replace_keys_in_repository(repo_path, json_file_path):
+ with open(json_file_path, 'r', encoding="utf-8") as json_file:
+ key_value_pairs = json.load(json_file)
+
+ pairs = []
+ for key, value in key_value_pairs.items():
+ pairs.append((key, value))
+ pairs.sort(key=lambda x: len(x[0]), reverse=True)
+
+ files = list_file_paths(repo_path)
+ print('Total files: {}'.format(len(files)))
+ for file_path in tqdm(files, total=len(files)):
+ replace_keys_in_file(file_path, pairs)
+
+
+def replace_keys_in_file(file_path, pairs):
+ try:
+ with open(file_path, 'r', encoding="utf-8") as file:
+ content = file.read()
+
+ for key, value in pairs:
+ content = content.replace(key, value)
+
+ with open(file_path, 'w', encoding="utf-8") as file:
+ file.write(content)
+ except UnicodeDecodeError:
+ print('UnicodeDecodeError: {}'.format(file_path))
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description='Replace keys in repository.')
+ parser.add_argument('--repository_path', help='Path to repository')
+ parser.add_argument('--json_file_path', help='Path to JSON file')
+ args = parser.parse_args()
+ replace_keys_in_repository(args.repository_path, args.json_file_path)
From f55647278c94877fe9e58e6ea1265a18c60b77cc Mon Sep 17 00:00:00 2001
From: JustSong
Date: Sat, 24 Jun 2023 10:09:42 +0800
Subject: [PATCH 140/410] fix: remove tqdm dependency
---
i18n/translate.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/i18n/translate.py b/i18n/translate.py
index df1fd035..6ba9bc5d 100644
--- a/i18n/translate.py
+++ b/i18n/translate.py
@@ -2,9 +2,6 @@ import argparse
import json
import os
-from tqdm import tqdm
-
-
def list_file_paths(path):
file_paths = []
for root, dirs, files in os.walk(path):
@@ -38,7 +35,7 @@ def replace_keys_in_repository(repo_path, json_file_path):
files = list_file_paths(repo_path)
print('Total files: {}'.format(len(files)))
- for file_path in tqdm(files, total=len(files)):
+ for file_path in files:
replace_keys_in_file(file_path, pairs)
From 61dc117da7e8aadc0b9b1a928f56bb4fe63af0dd Mon Sep 17 00:00:00 2001
From: JustSong
Date: Sat, 24 Jun 2023 10:12:34 +0800
Subject: [PATCH 141/410] ci: rename GitHub Actions file
---
.github/workflows/docker-image-amd64-en.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/docker-image-amd64-en.yml b/.github/workflows/docker-image-amd64-en.yml
index bf25669b..58e93fc7 100644
--- a/.github/workflows/docker-image-amd64-en.yml
+++ b/.github/workflows/docker-image-amd64-en.yml
@@ -1,4 +1,4 @@
-name: Publish Docker image (amd64)
+name: Publish Docker image (amd64, English)
on:
push:
From 2dd4ad0e067905a5b4093565133258eb446c47e8 Mon Sep 17 00:00:00 2001
From: JustSong
Date: Sat, 24 Jun 2023 10:22:13 +0800
Subject: [PATCH 142/410] chore: update en.json
---
i18n/en.json | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/i18n/en.json b/i18n/en.json
index 60897045..4f09fc2e 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -415,5 +415,14 @@
"构建,源代码遵循{' '}": ", the source code licensed under{' '}",
"MIT 协议": "MIT License",
"充值额度": "Recharge Quota",
- "获取兑换码": "Get Redeem Code"
+ "获取兑换码": "Get Redeem Code",
+ "一个月后过期": "Expires after one month",
+ "一天后过期": "Expires after one day",
+ "一小时后过期": "Expires after one hour",
+ "一分钟后过期": "Expires after one minute",
+ "创建新的令牌": "Create New Token",
+ "注意,令牌的额度仅用于限制令牌本身的最大额度使用量,实际的使用受到账户的剩余额度限制。": "Note that the quota of the token is only used to limit the maximum quota usage of the token itself, and the actual usage is limited by the remaining quota of the account.",
+ "设置为无限额度": "Set to unlimited quota",
+ "更新令牌信息": "Update Token Information",
+ "请输入充值码!": "Please enter the recharge code!"
}
\ No newline at end of file
From 25017219f5383f90d08c961bb81d919e2f4c38dc Mon Sep 17 00:00:00 2001
From: JustSong
Date: Sat, 24 Jun 2023 10:45:37 +0800
Subject: [PATCH 143/410] ci: fix GitHub Actions config
---
.github/workflows/docker-image-amd64-en.yml | 8 --------
1 file changed, 8 deletions(-)
diff --git a/.github/workflows/docker-image-amd64-en.yml b/.github/workflows/docker-image-amd64-en.yml
index 58e93fc7..44dc0bc0 100644
--- a/.github/workflows/docker-image-amd64-en.yml
+++ b/.github/workflows/docker-image-amd64-en.yml
@@ -33,20 +33,12 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- - name: Log in to the Container registry
- uses: docker/login-action@v2
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: |
justsong/one-api-en
- ghcr.io/one-api-en
- name: Build and push Docker images
uses: docker/build-push-action@v3
From 604ff20541ecaae8a113a1efb7932322a805aa99 Mon Sep 17 00:00:00 2001
From: JustSong
Date: Sat, 24 Jun 2023 11:17:46 +0800
Subject: [PATCH 144/410] chore: fix translation
---
i18n/en.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/i18n/en.json b/i18n/en.json
index 4f09fc2e..c4bb1613 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -384,7 +384,7 @@
"系统配置": "System Configuration",
"系统配置总览": "System Configuration Overview",
"邮箱验证": "Email Verification",
- "未": "Not ",
+ "未启用": "Not Enabled",
"GitHub 身份验证": "GitHub Authentication",
"微信身份验证": "WeChat Authentication",
"Turnstile 用户校验": "Turnstile User Verification",
@@ -411,7 +411,7 @@
"其他设置": "Other Settings",
"项目仓库地址": "Project Repository Address",
"可在设置页面设置关于内容,支持 HTML & Markdown": "You can set the content about in the settings page, support HTML & Markdown",
- "由{' '}": "build by{' '}",
+ "由{' '}": "built by{' '}",
"构建,源代码遵循{' '}": ", the source code licensed under{' '}",
"MIT 协议": "MIT License",
"充值额度": "Recharge Quota",
From 827942c8a9a1f2aae71fd13f6dee9495da50c601 Mon Sep 17 00:00:00 2001
From: JustSong
Date: Sat, 24 Jun 2023 11:30:16 +0800
Subject: [PATCH 145/410] docs: update README
---
README.en.md | 284 +++++++++++++++++++++++++++++++++++++++++++++++++++
README.md | 5 +
2 files changed, 289 insertions(+)
create mode 100644 README.en.md
diff --git a/README.en.md b/README.en.md
new file mode 100644
index 00000000..c1e6b2bb
--- /dev/null
+++ b/README.en.md
@@ -0,0 +1,284 @@
+
+
+> **Warning**: This README is translated by ChatGPT. Please feel free to submit a PR if you find any translation errors.
+
+> **Note**: The latest image pulled from Docker may be an `alpha` release. Specify the version manually if you require stability.
+
+> **Warning**: Manual migration of the database is necessary when upgrading from version `v0.3` to `v0.4`. Please manually execute the [database migration script](./bin/migration_v0.3-v0.4.sql).
+
+## Features
+1. Supports multiple API access channels. Welcome PRs or issue submissions for additional channels:
+ + [x] Official OpenAI channel (support proxy configuration)
+ + [x] **Azure OpenAI API**
+ + [x] [OpenAI-SB](https://openai-sb.com)
+ + [x] [API2D](https://api2d.com/r/197971)
+ + [x] [OhMyGPT](https://aigptx.top?aff=uFpUl2Kf)
+ + [x] [AI Proxy](https://aiproxy.io/?i=OneAPI) (invitation code: `OneAPI`)
+ + [x] [API2GPT](http://console.api2gpt.com/m/00002S)
+ + [x] [CloseAI](https://console.closeai-asia.com/r/2412)
+ + [x] [AI.LS](https://ai.ls)
+ + [x] [OpenAI Max](https://openaimax.com)
+ + [x] Custom channel: Various third-party proxy services not included in the list
+2. Supports access to multiple channels through **load balancing**.
+3. Supports **stream mode** that enables typewriter-like effect through stream transmission.
+4. Supports **multi-machine deployment**. [See here](#multi-machine-deployment) for more details.
+5. Supports **token management** that allows setting token expiration time and usage count.
+6. Supports **voucher management** that enables batch generation and export of vouchers. Vouchers can be used for account balance replenishment.
+7. Supports **channel management** that allows bulk creation of channels.
+8. Supports **user grouping** and **channel grouping** for setting different rates for different groups.
+9. Supports channel **model list configuration**.
+10. Supports **quota details checking**.
+11. Supports **user invite rewards**.
+12. Allows display of balance in USD.
+13. Supports announcement publishing, recharge link setting, and initial balance setting for new users.
+14. Offers rich **customization** options:
+ 1. Supports customization of system name, logo, and footer.
+ 2. Supports customization of homepage and about page using HTML & Markdown code, or embedding a standalone webpage through iframe.
+15. Supports management API access through system access tokens.
+16. Supports Cloudflare Turnstile user verification.
+17. Supports user management and multiple user login/registration methods:
+ + Email login/registration and password reset via email.
+ + [GitHub OAuth](https://github.com/settings/applications/new).
+ + WeChat Official Account authorization (requires additional deployment of [WeChat Server](https://github.com/songquanpeng/wechat-server)).
+18. Immediate support and encapsulation of other major model APIs as they become available.
+
+## Deployment
+### Docker Deployment
+Deployment command: `docker run --name one-api -d --restart always -p 3000:3000 -e TZ=Asia/Shanghai -v /home/ubuntu/data/one-api:/data justsong/one-api`
+
+Update command: `docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower -cR`
+
+The first `3000` in `-p 3000:3000` is the port of the host, which can be modified as needed.
+
+Data will be saved in the `/home/ubuntu/data/one-api` directory on the host. Ensure that the directory exists and has write permissions, or change it to a suitable directory.
+
+Nginx reference configuration:
+```
+server{
+ server_name openai.justsong.cn; # Modify your domain name accordingly
+
+ location / {
+ client_max_body_size 64m;
+ proxy_http_version 1.1;
+ proxy_pass http://localhost:3000; # Modify your port accordingly
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For $remote_addr;
+ proxy_cache_bypass $http_upgrade;
+ proxy_set_header Accept-Encoding gzip;
+ }
+}
+```
+
+Next, configure HTTPS with Let's Encrypt certbot:
+```bash
+# Install certbot on Ubuntu:
+sudo snap install --classic certbot
+sudo ln -s /snap/bin/certbot /usr/bin/certbot
+# Generate certificates & modify Nginx configuration
+sudo certbot --nginx
+# Follow the prompts
+# Restart Nginx
+sudo service nginx restart
+```
+
+The initial account username is `root` and password is `123456`.
+
+### Manual Deployment
+1. Download the executable file from [GitHub Releases](https://github.com/songquanpeng/one-api/releases/latest) or compile from source:
+ ```shell
+ git clone https://github.com/songquanpeng/one-api.git
+
+ # Build the frontend
+ cd one-api/web
+ npm install
+ npm run build
+
+ # Build the backend
+ cd ..
+ go mod download
+ go build -ldflags "-s -w" -o one-api
+ ```
+2. Run:
+ ```shell
+ chmod u+x one-api
+ ./one-api --port 3000 --log-dir ./logs
+ ```
+3. Access [http://localhost:3000/](http://localhost:3000/) and log in. The initial account username is `root` and password is `123456`.
+
+For more detailed deployment tutorials, please refer to [this page](https://iamazing.cn/page/how-to-deploy-a-website).
+
+### Multi-machine Deployment
+1. Set the same `SESSION_SECRET` for all servers.
+2. Set `SQL_DSN` and use MySQL instead of SQLite. All servers should connect to the same database.
+3. Set the `NODE_TYPE` for all non-master nodes to `slave`.
+4. Set `SYNC_FREQUENCY` for servers to periodically sync configurations from the database.
+5. Non-master nodes can optionally set `FRONTEND_BASE_URL` to redirect page requests to the master server.
+6. Install Redis separately on non-master nodes, and configure `REDIS_CONN_STRING` so that the database can be accessed with zero latency when the cache has not expired.
+7. If the main server also has high latency accessing the database, Redis must be enabled and `SYNC_FREQUENCY` must be set to periodically sync configurations from the database.
+
+Please refer to the [environment variables](#environment-variables) section for details on using environment variables.
+
+### Deployment on Control Panels (e.g., Baota)
+Refer to [#175](https://github.com/songquanpeng/one-api/issues/175) for detailed instructions.
+
+If you encounter a blank page after deployment, refer to [#97](https://github.com/songquanpeng/one-api/issues/97) for possible solutions.
+
+### Deployment on Third-Party Platforms
+
+Deployment on Zeabur
+
+
+> Zeabur's servers are located overseas, automatically solving network issues, and the free quota is sufficient for personal usage.
+
+1. First, fork the code.
+2. Go to [Zeabur](https://zeabur.com/), log in, and enter the console.
+3. Create a new project. In Service -> Add Service, select Marketplace, and choose MySQL. Note down the connection parameters (username, password, address, and port).
+4. Copy the connection parameters and run ```create database `one-api` ``` to create the database.
+5. Then, in Service -> Add Service, select Git (authorization is required for the first use) and choose your forked repository.
+6. Automatic deployment will start, but please cancel it for now. Go to the Variable tab, add a `PORT` with a value of `3000`, and then add a `SQL_DSN` with a value of `:@tcp(:)/one-api`. Save the changes. Please note that if `SQL_DSN` is not set, data will not be persisted, and the data will be lost after redeployment.
+7. Select Redeploy.
+8. In the Domains tab, select a suitable domain name prefix, such as "my-one-api". The final domain name will be "my-one-api.zeabur.app". You can also CNAME your own domain name.
+9. Wait for the deployment to complete, and click on the generated domain name to access One API.
+
+
+
+
+## Configuration
+The system is ready to use out of the box.
+
+You can configure it by setting environment variables or command line parameters.
+
+After the system starts, log in as the `root` user to further configure the system.
+
+## Usage
+Add your API Key on the `Channels` page, and then add an access token on the `Tokens` page.
+
+You can then use your access token to access One API. The usage is consistent with the [OpenAI API](https://platform.openai.com/docs/api-reference/introduction).
+
+In places where the OpenAI API is used, remember to set the API Base to your One API deployment address, for example: `https://openai.justsong.cn`. The API Key should be the token generated in One API.
+
+Note that the specific API Base format depends on the client you are using.
+
+```mermaid
+graph LR
+ A(User)
+ A --->|Request| B(One API)
+ B -->|Relay Request| C(OpenAI)
+ B -->|Relay Request| D(Azure)
+ B -->|Relay Request| E(Other downstream channels)
+```
+
+To specify which channel to use for the current request, you can add the channel ID after the token, for example: `Authorization: Bearer ONE_API_KEY-CHANNEL_ID`.
+Note that the token needs to be created by an administrator to specify the channel ID.
+
+If the channel ID is not provided, load balancing will be used to distribute the requests to multiple channels.
+
+### Environment Variables
+1. `REDIS_CONN_STRING`: When set, Redis will be used as the storage for request rate limiting instead of memory.
+ + Example: `REDIS_CONN_STRING=redis://default:redispw@localhost:49153`
+2. `SESSION_SECRET`: When set, a fixed session key will be used to ensure that cookies of logged-in users are still valid after the system restarts.
+ + Example: `SESSION_SECRET=random_string`
+3. `SQL_DSN`: When set, the specified database will be used instead of SQLite. Please use MySQL version 8.0.
+ + Example: `SQL_DSN=root:123456@tcp(localhost:3306)/oneapi`
+4. `FRONTEND_BASE_URL`: When set, the specified frontend address will be used instead of the backend address.
+ + Example: `FRONTEND_BASE_URL=https://openai.justsong.cn`
+5. `SYNC_FREQUENCY`: When set, the system will periodically sync configurations from the database, with the unit in seconds. If not set, no sync will happen.
+ + Example: `SYNC_FREQUENCY=60`
+6. `NODE_TYPE`: When set, specifies the node type. Valid values are `master` and `slave`. If not set, it defaults to `master`.
+ + Example: `NODE_TYPE=slave`
+7. `CHANNEL_UPDATE_FREQUENCY`: When set, it periodically updates the channel balances, with the unit in minutes. If not set, no update will happen.
+ + Example: `CHANNEL_UPDATE_FREQUENCY=1440`
+8. `CHANNEL_TEST_FREQUENCY`: When set, it periodically tests the channels, with the unit in minutes. If not set, no test will happen.
+ + Example: `CHANNEL_TEST_FREQUENCY=1440`
+9. `REQUEST_INTERVAL`: The time interval (in seconds) between requests when updating channel balances and testing channel availability. Default is no interval.
+ + Example: `POLLING_INTERVAL=5`
+
+### Command Line Parameters
+1. `--port `: Specifies the port number on which the server listens. Defaults to `3000`.
+ + Example: `--port 3000`
+2. `--log-dir `: Specifies the log directory. If not set, the logs will not be saved.
+ + Example: `--log-dir ./logs`
+3. `--version`: Prints the system version number and exits.
+4. `--help`: Displays the command usage help and parameter descriptions.
+
+## Screenshots
+
+
+
+## FAQ
+1. What is quota? How is it calculated? Does One API have quota calculation issues?
+ + Quota = Group multiplier * Model multiplier * (number of prompt tokens + number of completion tokens * completion multiplier)
+ + The completion multiplier is fixed at 1.33 for GPT3.5 and 2 for GPT4, consistent with the official definition.
+ + If it is not a stream mode, the official API will return the total number of tokens consumed. However, please note that the consumption multipliers for prompts and completions are different.
+2. Why does it prompt "insufficient quota" even though my account balance is sufficient?
+ + Please check if your token quota is sufficient. It is separate from the account balance.
+ + The token quota is used to set the maximum usage and can be freely set by the user.
+3. It says "No available channels" when trying to use a channel. What should I do?
+ + Please check the user and channel group settings.
+ + Also check the channel model settings.
+4. Channel testing reports an error: "invalid character '<' looking for beginning of value"
+ + This error occurs when the returned value is not valid JSON but an HTML page.
+ + Most likely, the IP of your deployment site or the node of the proxy has been blocked by CloudFlare.
+5. ChatGPT Next Web reports an error: "Failed to fetch"
+ + Do not set `BASE_URL` during deployment.
+ + Double-check that your interface address and API Key are correct.
+
+## Related Projects
+[FastGPT](https://github.com/c121914yu/FastGPT): Build an AI knowledge base in three minutes
+
+## Note
+This project is an open-source project. Please use it in compliance with OpenAI's [Terms of Use](https://openai.com/policies/terms-of-use) and **applicable laws and regulations**. It must not be used for illegal purposes.
+
+This project is open-sourced under the MIT license. One must somehow retain the copyright information of One API.
+
+According to the MIT license, users should bear the risk and responsibility of using this project, and the developer of this open-source project is not responsible for this.
diff --git a/README.md b/README.md
index ed0a397a..f4712561 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,8 @@
+
From 89bcaaf98983121645b057465cba3477b65cf7d1 Mon Sep 17 00:00:00 2001
From: a497625414 <55976729+a497625414@users.noreply.github.com>
Date: Sun, 6 Aug 2023 13:19:54 +0800
Subject: [PATCH 274/410] docs: update readme (#359)
* update-deploy-on-sealos
* update-deploy-on-sealos
---
README.en.md | 6 +++++-
README.md | 8 +++++---
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/README.en.md b/README.en.md
index c43ee3af..2ea6e65e 100644
--- a/README.en.md
+++ b/README.en.md
@@ -137,7 +137,7 @@ The initial account username is `root` and password is `123456`.
cd one-api/web
npm install
npm run build
-
+
# Build the backend
cd ..
go mod download
@@ -173,6 +173,10 @@ If you encounter a blank page after deployment, refer to [#97](https://github.co
Deploy on Sealos
+> Sealos supports high concurrency, dynamic scaling, and stable operations for millions of users.
+
+> Click the button below to deploy with one click.👇
+
[](https://cloud.sealos.io/?openapp=system-fastdeploy?templateName=one-api)
diff --git a/README.md b/README.md
index a7c06fc5..fcabd2c5 100644
--- a/README.md
+++ b/README.md
@@ -153,7 +153,7 @@ sudo service nginx restart
cd one-api/web
npm install
npm run build
-
+
# 构建后端
cd ..
go mod download
@@ -211,9 +211,11 @@ docker run --name chatgpt-web -d -p 3002:3002 -e OPENAI_API_BASE_URL=https://ope
部署到 Sealos