From 03c05bdb5fee113d7277d00c43caa2e3434253d9 Mon Sep 17 00:00:00 2001 From: JustSong Date: Sat, 24 Jun 2023 10:07:49 +0800 Subject: [PATCH] feat: add English support --- .github/workflows/docker-image-amd64-en.yml | 57 +++ i18n/en.json | 419 ++++++++++++++++++++ i18n/translate.py | 64 +++ 3 files changed, 540 insertions(+) create mode 100644 .github/workflows/docker-image-amd64-en.yml create mode 100644 i18n/en.json create mode 100644 i18n/translate.py 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)