-
-
Notifications
You must be signed in to change notification settings - Fork 2k
feat(i18n): 增加国际化信息 #1657
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: alpha
Are you sure you want to change the base?
feat(i18n): 增加国际化信息 #1657
Conversation
WalkthroughReplaced many hard-coded Chinese UI strings with i18n wrappers, extracted JSON examples from translation calls, added extensive English translations to Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested reviewers
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/src/components/settings/SystemSetting.jsx (1)
721-726
: Add missing English translation for the TagInput placeholderThe placeholder key
输入域名后回车
is not defined in your English locale file. Without it, English users will see the raw Chinese text instead of an English prompt.• File to update:
web/src/i18n/locales/en.json
• Action: add the following entry (adjust wording as needed for your style guide):
{ // …existing keys… "输入域名后回车": "Enter a domain and press Enter" // …remaining keys… }
🧹 Nitpick comments (8)
web/src/pages/Setting/Ratio/GroupRatioSettings.jsx (1)
123-127
: Prefer JSX with code markup and i18n interpolation over string concatenation for examplesConcatenating translated fragments with raw JSON strings can produce awkward phrasing in some locales and is harder to style/accessibly render. ExtraText accepts React nodes—use code markup and let translators reorder via placeholders if/when you move to keyed strings.
Apply diffs like these to render examples as code and avoid brittle string concatenation:
- extraText={ - t('分组倍率设置,可以在此处新增分组或修改现有分组的倍率,格式为 JSON 字符串,例如:') + - '{"vip": 0.5, "test": 1}' + - t(',表示 vip 分组的倍率为 0.5,test 分组的倍率为 1') - } + extraText={ + <> + {t('分组倍率设置,可以在此处新增分组或修改现有分组的倍率,格式为 JSON 字符串,例如:')}{' '} + <code>{'{"vip": 0.5, "test": 1}'}</code>{' '} + {t(',表示 vip 分组的倍率为 0.5,test 分组的倍率为 1')} + </> + }- extraText={ - t('用户新建令牌时可选的分组,格式为 JSON 字符串,例如:') + - '{"vip": "VIP 用户", "test": "测试"}' + - t(',表示用户可以选择 vip 分组和 test 分组') - } + extraText={ + <> + {t('用户新建令牌时可选的分组,格式为 JSON 字符串,例如:')}{' '} + <code>{'{"vip": "VIP 用户", "test": "测试"}'}</code>{' '} + {t(',表示用户可以选择 vip 分组和 test 分组')} + </> + }- extraText={ - t('键为分组名称,值为另一个 JSON 对象,键为分组名称,值为该分组的用户的特殊分组倍率,例如:') + - '{"vip": {"default": 0.5, "test": 1}}' + - t(',表示 vip 分组的用户在使用default分组的令牌时倍率为0.5,使用test分组时倍率为1') - } + extraText={ + <> + {t('键为分组名称,值为另一个 JSON 对象,键为分组名称,值为该分组的用户的特殊分组倍率,例如:')}{' '} + <code>{'{"vip": {"default": 0.5, "test": 1}}'}</code>{' '} + {t(',表示 vip 分组的用户在使用default分组的令牌时倍率为0.5,使用test分组时倍率为1')} + </> + }Follow-up (optional): consider switching to t('…{{example}}…', { example }) so translators can reorder around the example. I can help generate keys and migrate usages.
Also applies to: 150-153, 176-179
web/src/pages/Setting/Model/SettingGeminiModel.jsx (1)
193-196
: Use and code markup for multi-sentence guidance and formulasThree consecutive t() calls and a formula string reduce translator flexibility and readability. Use a single so translators can reorder sentences, and render identifiers/formulas with
.
Apply diffs to these blocks:
- <Text> - {t('和Claude不同,默认情况下Gemini的思考模型会自动决定要不要思考,就算不开启适配模型也可以正常使用,')} - {t('如果您需要计费,推荐设置无后缀模型价格按思考价格设置。')} - {t('支持使用 gemini-2.5-pro-preview-06-05-thinking-128 格式来精确传递思考预算。')} - </Text> + <Text> + <Trans i18nKey='gemini.thinking_adapter.intro' /> + </Text>- <Text> - {t('Gemini思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比')} - </Text> + <Text> + <Trans + i18nKey='gemini.thinking_adapter.formula' + components={{ code: <code /> }} + /> + </Text>And add the import:
- import { useTranslation } from 'react-i18next'; + import { useTranslation, Trans } from 'react-i18next';If you’d prefer staying with t(), at least wrap model IDs and variables (e.g., gemini-2.5-pro-preview-06-05-thinking-128, BudgetTokens, MaxTokens) in
for clarity.
Also applies to: 217-218
web/src/pages/Setting/Payment/SettingsPaymentGatewayStripe.jsx (2)
134-151
: Prefer for anchor-containing sentences to keep anchors translatable and movableComposing a sentence with multiple t() calls and plain anchors fixes the link order for all locales. Using lets translators reposition links naturally.
Example refactor for this paragraph:
- <Text> - {t('Stripe 密钥、Webhook 等设置请')} - <a - href='https://dashboard.stripe.com/developers' - target='_blank' - rel='noopener noreferrer' - > - {t('点击此处')} - </a> - {t('进行设置,最好先在')} - <a - href='https://dashboard.stripe.com/test/developers' - target='_blank' - rel='noopener noreferrer' - > - {t('测试环境')} - </a> - {t('进行测试。')} - <br /> - </Text> + <Text> + <Trans + i18nKey='stripe.settings.paragraph' + components={{ + linkProd: <a href='https://dashboard.stripe.com/developers' target='_blank' rel='noopener noreferrer' />, + linkTest: <a href='https://dashboard.stripe.com/test/developers' target='_blank' rel='noopener noreferrer' /> + }} + /> + <br /> + </Text>Also add Trans to imports if you take this route:
- import { useTranslation } from 'react-i18next'; + import { useTranslation, Trans } from 'react-i18next';
156-161
: Ensure translation entries with interpolation placeholders are addedTo keep the URL and event names as language-agnostic tokens and make the entire string fully translatable, introduce interpolation keys in your locale files and update the code to use those keys.
• Add these new keys to zh.json and en.json (or your locale files):
•"Webhook 填:{{url}}"
→ e.g."Webhook fill in: {{url}}"
•"需要包含事件:{{e1}} 和 {{e2}}"
→ e.g."Need to include events: {{e1}} and {{e2}}"
• Update the code in SettingsPaymentGatewayStripe.jsx:
- description={t('Webhook 填:') + `${props.options.ServerAddress ? removeTrailingSlash(props.options.ServerAddress) : t('网站地址')}/api/stripe/webhook`} + description={t('Webhook 填:{{url}}', { + url: `${props.options.ServerAddress + ? removeTrailingSlash(props.options.ServerAddress) + : t('网站地址')}/api/stripe/webhook` + })}- description={t('需要包含事件:') + 'checkout.session.completed 和 checkout.session.expired'} + description={t('需要包含事件:{{e1}} 和 {{e2}}', { + e1: 'checkout.session.completed', + e2: 'checkout.session.expired' + })}• Alternatively, if you prefer rendering the tokens as
<code>
blocks and avoid adding a standalone “和” key, you can write:- description={t('需要包含事件:') + 'checkout.session.completed 和 checkout.session.expired'} + description={ + <span> + {t('需要包含事件:')} + <code>checkout.session.completed</code>{' '} + <code>和</code>{' '} + <code>checkout.session.expired</code> + </span> + }This ensures your translations remain consistent, the dynamic pieces stay in code form, and translators can manage the entire string in one place.
web/src/components/settings/SystemSetting.jsx (3)
541-553
: Localize punctuation and add noopener for security on external link
- Use ASCII parentheses to avoid CJK brackets leaking into non-CJK locales, or include the punctuation inside the translation.
- Add rel="noopener" in addition to noreferrer to prevent window.opener leaks for target="_blank".
Apply this diff:
- <Text> - ({t('支持')}{' '} + <Text> + ({t('支持')}{' '} <a href='https://github.com/Calcium-Ion/new-api-worker' target='_blank' - rel='noreferrer' + rel='noopener noreferrer' > new-api-worker </a> - ) + ) </Text>
559-563
: Ensure a space after “For example:” in placeholderConcatenation currently produces "For example:https://..." in English. Insert a space after the colon.
- placeholder={t('例如:') + 'https://workername.yourdomain.workers.dev'} + placeholder={`${t('例如:')} https://workername.yourdomain.workers.dev`}
673-681
: Double-check Semi UI field path syntax for OIDC checkboxField is set to the string "['oidc.enabled']". If Semi Form expects a plain string path (e.g., 'oidc.enabled') or an actual array value, this quoted form may be brittle. It appears elsewhere in this file for OIDC inputs too and may be legacy, but worth verifying against @douyinfe/semi-ui Form docs.
If valid, ignore. If not, consider:
- field="['oidc.enabled']" + field='oidc.enabled'web/src/i18n/locales/en.json (1)
2000-2107
: New i18n keys: solid coverage; minor wording polishGreat job filling in the missing English strings for proxy, SMTP, OIDC, LinuxDO, Telegram, Stripe, and rate-limit settings. A few tiny wording tweaks would read more naturally in English:
- "允许通过 Linux DO 账户登录 & 注册": "Allow login & registration through Linux DO account", + "允许通过 Linux DO 账户登录 & 注册": "Allow login & registration via Linux DO account", - "主页链接填": "Homepage URL fill in", + "主页链接填": "Set Homepage URL to", - "重定向 URL 填": "Redirect URL fill in", + "重定向 URL 填": "Set Redirect URL to"Note:
- Many UIs concatenate “例如:” before examples. Since code often stitches this directly to a URL, either ensure a space in code (preferred; see SystemSetting.jsx fix) or change the English translation to “For example: ” (with a trailing space) project-wide.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📥 Commits
Reviewing files that changed from the base of the PR and between 98db90768007857b41d84c439934668817b2e2b7 and 2800e531c853a7dc94a2fcf2d96e1cf3f1ed7451.
📒 Files selected for processing (7)
web/src/components/settings/SystemSetting.jsx
(5 hunks)
web/src/i18n/locales/en.json
(1 hunks)
web/src/pages/Setting/Model/SettingGeminiModel.jsx
(2 hunks)
web/src/pages/Setting/Model/SettingGlobalModel.jsx
(3 hunks)
web/src/pages/Setting/Payment/SettingsPaymentGatewayStripe.jsx
(1 hunks)
web/src/pages/Setting/RateLimit/SettingsRequestRateLimit.jsx
(1 hunks)
web/src/pages/Setting/Ratio/GroupRatioSettings.jsx
(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
web/src/pages/Setting/Payment/SettingsPaymentGatewayStripe.jsx (1)
web/src/helpers/utils.jsx (2)
a
(250-250)
removeTrailingSlash
(168-175)
🔇 Additional comments (3)
web/src/components/settings/SystemSetting.jsx (3)
567-571
: LGTM: secret placeholder is now localized
Using t('敏感信息不会发送到前端显示') improves i18n consistency for sensitive fields.
703-705
: LGTM: checkbox labels localized
Both “启用邮箱域名白名单” and “启用邮箱别名限制” are correctly wrapped with t(...), and keys are present in en.json.
Also applies to: 717-719
779-781
: LGTM: localized SMTP token placeholder
Consistent with other sensitive fields; improves UX for non-Chinese locales.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
web/src/pages/Setting/Model/SettingGeminiModel.jsx (1)
217-218
: Render the formula with code markup; consider clearer token namingMinor i18n polish: mark tokens as code to prevent accidental translation and improve readability. If product terminology allows, consider “BudgetTokensPercentage” (or localized equivalent) to remove ambiguity.
- <Text> - {t('Gemini思考适配 BudgetTokens = MaxTokens * BudgetTokens 百分比')} - </Text> + <Text> + <Trans i18nKey='settings.gemini.thinkingAdapter.formula'> + Gemini思考适配 <code>BudgetTokens</code> = <code>MaxTokens</code> * <code>BudgetTokens</code> 百分比 + </Trans> + </Text>If you adopt the new i18n key, also add it to your locale files (en.json/zh.json) with the same literal tokens inside
…
.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (7)
web/src/components/settings/SystemSetting.jsx
(5 hunks)web/src/i18n/locales/en.json
(1 hunks)web/src/pages/Setting/Model/SettingGeminiModel.jsx
(2 hunks)web/src/pages/Setting/Model/SettingGlobalModel.jsx
(3 hunks)web/src/pages/Setting/Payment/SettingsPaymentGatewayStripe.jsx
(1 hunks)web/src/pages/Setting/RateLimit/SettingsRequestRateLimit.jsx
(1 hunks)web/src/pages/Setting/Ratio/GroupRatioSettings.jsx
(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
- web/src/pages/Setting/RateLimit/SettingsRequestRateLimit.jsx
- web/src/pages/Setting/Payment/SettingsPaymentGatewayStripe.jsx
- web/src/pages/Setting/Model/SettingGlobalModel.jsx
- web/src/pages/Setting/Ratio/GroupRatioSettings.jsx
- web/src/components/settings/SystemSetting.jsx
- web/src/i18n/locales/en.json
Summary by CodeRabbit