diff --git a/.github/workflows/docker-image-amd64-en.yml b/.github/workflows/docker-image-amd64-en.yml
new file mode 100644
index 00000000..bf25669b
--- /dev/null
+++ b/.github/workflows/docker-image-amd64-en.yml
@@ -0,0 +1,57 @@
+name: Publish Docker image (amd64)
+
+on:
+ push:
+ tags:
+ - '*'
+ workflow_dispatch:
+ inputs:
+ name:
+ description: 'reason'
+ required: false
+jobs:
+ push_to_registries:
+ name: Push Docker image to multiple registries
+ runs-on: ubuntu-latest
+ permissions:
+ packages: write
+ contents: read
+ steps:
+ - name: Check out the repo
+ uses: actions/checkout@v3
+
+ - name: Save version info
+ run: |
+ git describe --tags > VERSION
+
+ - name: Translate
+ run: |
+ python ./i18n/translate.py --repository_path . --json_file_path ./i18n/en.json
+ - name: Log in to Docker Hub
+ uses: docker/login-action@v2
+ with:
+ 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
+ with:
+ context: .
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
\ No newline at end of file
diff --git a/i18n/en.json b/i18n/en.json
new file mode 100644
index 00000000..60897045
--- /dev/null
+++ b/i18n/en.json
@@ -0,0 +1,419 @@
+{
+ "$%.6f 额度": "$%.6f quota",
+ "%d 点额度": "%d point quota",
+ "尚未实现": "Not yet implemented",
+ "余额不足": "Insufficient balance",
+ "\"通道「%s」(#%d)已被禁用\"": "\"Channel %s (#%d) has been disabled\"",
+ "通道「%s」(#%d)已被禁用,原因:%s": "Channel %s (#%d) has been disabled, reason: %s",
+ "测试已在运行中": "Test is already running",
+ "响应时间 %.2fs 超过阈值 %.2fs": "Response time %.2fs exceeds threshold %.2fs",
+ "通道测试完成": "Channel test completed",
+ "通道测试完成,如果没有收到禁用通知,说明所有通道都正常": "Channel test completed, if you have not received the disable notification, it means that all channels are normal",
+ "无法连接至 GitHub 服务器,请稍后重试!": "Unable to connect to GitHub server, please try again later!",
+ "返回值非法,用户字段为空,请稍后重试!": "The return value is illegal, the user field is empty, please try again later!",
+ "管理员未开启通过 GitHub 登录以及注册": "The administrator did not turn on login and registration via GitHub",
+ "管理员关闭了新用户注册": "The administrator has turned off new user registration",
+ "用户已被封禁": "User has been banned",
+ "该 GitHub 账户已被绑定": "The GitHub account has been bound",
+ "邮箱地址已被占用": "Email address is occupied",
+ "%s邮箱验证邮件": "%s Email verification email",
+ "
您好,你正在进行%s邮箱验证。
": "Hello, you are verifying %s email.
",
+ "您的验证码为: %s
": "Your verification code is: %s
",
+ "验证码 %d 分钟内有效,如果不是本人操作,请忽略。
": "The verification code is valid within %d minutes. If it is not your operation, please ignore it.
",
+ "无效的参数": "Invalid parameter",
+ "该邮箱地址未注册": "The email address is not registered",
+ "%s密码重置": "%s Password reset",
+ "您好,你正在进行%s密码重置。
": "Hello, you are resetting %s password.
",
+ "点击此处进行密码重置。
": "Click here to reset your password.
",
+ "重置链接 %d 分钟内有效,如果不是本人操作,请忽略。
": "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)