Skip to content

[Feat]添加跟随前端变化的i18n设置#5213

Closed
Li-shi-ling wants to merge 7 commits intoAstrBotDevs:masterfrom
united-pooh:feat/i18n-switch-api
Closed

[Feat]添加跟随前端变化的i18n设置#5213
Li-shi-ling wants to merge 7 commits intoAstrBotDevs:masterfrom
united-pooh:feat/i18n-switch-api

Conversation

@Li-shi-ling
Copy link
Contributor

@Li-shi-ling Li-shi-ling commented Feb 18, 2026

Modifications / 改动点

astrbot/dashboard/routes/lang_route.py
给这个地方添加了个文件用于注册lang相关的路由

astrbot/dashboard/server.py
在这个代码的AstrBotDashboard添加了LangRoute的实例化

astrbot/core/lang.py
给Lang添加了load_locale方法,方便外部进行t的语言更新

dashboard/src/i18n/composables.ts
在切换和初始化部分添加了向后端的请求,用于切换i18n

实现的功能是能够让webui在操作i18n时能够实时反映到后端的日志上面去

  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

没有,先这样改吧,后续讨论!


Checklist / 检查清单

  • [ X ] 😊 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。/ If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
  • [ ] 👀 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”。/ My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    没有测试喵
  • [ X ] 🤓 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到了 requirements.txtpyproject.toml 文件相应位置。/ I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
  • [ X ] 😮 我的更改没有引入恶意代码。/ My changes do not introduce malicious code.

Summary by Sourcery

添加一个共享的 i18n 系统,使得 WebUI 语言环境更改时可以更新后端语言并本地化核心消息。

新功能:

  • 引入 Lang 本地化辅助工具和全局翻译器,用于根据语言环境在后端查找字符串。
  • 暴露 /api/setLang 仪表盘路由,以便从 WebUI 在运行时更新后端语言。
  • 更新 WebUI 的 i18n composable,在初始化以及切换语言时将当前语言环境通知后端。

改进:

  • main.py 中使用本地化消息键对关键启动日志和 CLI 帮助文本进行国际化。
  • 为主模块消息添加英文和简体中文的 Fluent 语言资源文件。
Original summary in English

Summary by Sourcery

Add a shared i18n system so WebUI locale changes update backend language and localize core messages.

New Features:

  • Introduce a Lang localization helper and global translator for backend string lookup based on locale.
  • Expose a /api/setLang dashboard route to update the backend language at runtime from the WebUI.
  • Update the WebUI i18n composable to notify the backend of the current locale on initialization and when switching languages.

Enhancements:

  • Internationalize key startup logs and CLI help text in main.py using localized message keys.
  • Add English and Simplified Chinese Fluent locale resource files for main module messages.

@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Feb 18, 2026
@Li-shi-ling
Copy link
Contributor Author

我开错位置了

@dosubot
Copy link

dosubot bot commented Feb 18, 2026

Related Documentation

Checked 1 published document(s) in 1 knowledge base(s). No updates required.

How did I do? Any feedback?  Join Discord

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 4 个问题,并给出了一些整体层面的反馈:

  • 前端调用的是 axios.post('/api/setLang', { lang }),但 LangRoute 目前注册的是 '/setLang'GET 方法并读取 JSON body;二者在路径和 HTTP 方法上都需要对齐,以避免运行时出现 404 / 方法不匹配以及请求体相关的问题。
  • main.py 中新增的 t(...) 调用使用了位置参数(例如 t('main-use-specified-webui', webui_dir)),但 Lang.__call__ 期望的是关键字参数,并且 FTL 中的变量(如 $webui_dir, $v, $version, $error)必须和这些关键字参数名保持一致;请将调用改为使用命名参数,并确保 .ftl 文件中的变量名和代码中的参数名一致。
  • zh-CN 的 FTL 条目使用了 {webui_dir}, {v}, {VERSION}, {e} 这样的占位符,没有 $ 前缀,而且名称也与英文版本不同;为避免格式化错误,请统一改为 Fluent 语法(例如 { $webui_dir }),并将变量名与 Python 代码中传入的参数保持一致。
给 AI Agent 的提示词
Please address the comments from this code review:

## Overall Comments
- The frontend calls `axios.post('/api/setLang', { lang })`, but `LangRoute` currently registers `'/setLang'` with the `GET` method and reads a JSON body; this should be aligned (path and HTTP verb) to avoid runtime 404/method and request-body issues.
- The new `t(...)` usages in `main.py` pass positional arguments (e.g. `t('main-use-specified-webui', webui_dir)`), but `Lang.__call__` expects keyword arguments and the FTL variables (e.g. `$webui_dir`, `$v`, `$version`, `$error`) must match those keyword names; update calls to use named arguments and ensure the variable names in the .ftl files and code are consistent.
- The zh-CN FTL entries use placeholders like `{webui_dir}`, `{v}`, `{VERSION}`, `{e}` without the `$` prefix and with names that differ from the English version; to prevent formatting errors, standardize them to Fluent syntax (e.g. `{ $webui_dir }`) and align variable names with the arguments you pass from Python.

## Individual Comments

### Comment 1
<location> `main.py:71` </location>
<code_context>
     if webui_dir:
         if os.path.exists(webui_dir):
-            logger.info(f"使用指定的 WebUI 目录: {webui_dir}")
+            logger.info(t("main-use-specified-webui", webui_dir))
             return webui_dir
-        logger.warning(f"指定的 WebUI 目录 {webui_dir} 不存在,将使用默认逻辑。")
</code_context>

<issue_to_address>
**issue (bug_risk):** Fluent translation calls use positional args, which will raise TypeError and also don't match the variable names in the FTL files.

`Lang.__call__` is defined as `def __call__(self, key: str, **kwargs)`, so `t("main-use-specified-webui", webui_dir)` will raise `TypeError` due to the extra positional argument. The FTL entries also expect named variables (`$webui_dir`, `$v`, `$version`, `$error`), so these should be passed as keyword args, e.g.:

```python
logger.info(t("main-use-specified-webui", webui_dir=webui_dir))
logger.warning(t("main-webui-not-found", webui_dir=webui_dir))
logger.warning(t("main-webui-version-mismatch", v=v, version=VERSION))
logger.critical(t("main-download-dashboard-failed", error=e))
```

This avoids the runtime error and matches Fluent's variable naming.
</issue_to_address>

### Comment 2
<location> `locales/zh-cn/main.ftl:2-7` </location>
<code_context>
+main-python-version-error = 请使用 Python3.10+ 运行本项目。
+main-use-specified-webui = 使用指定的 WebUI 目录: {webui_dir}
+main-webui-not-found = 指定的 WebUI 目录 {webui_dir} 不存在,将使用默认逻辑。
+main-webui-latest = WebUI 版本已是最新
+main-webui-version-mismatch = 检测到 WebUI 版本 ({v}) 与当前 AstrBot 版本 (v{VERSION}) 不符。
+main-downloading-dashboard =  开始下载管理面板文件...高峰期(晚上)可能导致较慢的速度。如多次下载失败,请前往 https://github.com/AstrBotDevs/AstrBot/releases/latest 下载 dist.zip,并将其中的 dist 文件夹解压至 data 目录下。
+main-download-dashboard-failed = 下载管理面板文件失败: {e}。
+main-download-dashboard-success = 管理面板下载完成。
+main-argparse-webui-dir-help = 指定 WebUI 静态文件目录路径
</code_context>

<issue_to_address>
**issue (bug_risk):** The zh-CN FTL file uses non-Fluent placeholder syntax that won’t be substituted correctly.

In Fluent, external arguments must be referenced with a leading `$`, e.g. `{ $webui_dir }`, `{ $v }`, `{ $version }`, `{ $error }`. The current zh-CN entries omit the `$` and use `VERSION`/`e`, which don’t match the variables you’ll pass from Python. Please align them with the en file and your Python kwargs, for example:

```ftl
main-use-specified-webui = 使用指定的 WebUI 目录: { $webui_dir }
main-webui-not-found = 指定的 WebUI 目录 { $webui_dir } 不存在,将使用默认逻辑。
main-webui-version-mismatch = 检测到 WebUI 版本 ({ $v }) 与当前 AstrBot 版本 (v{ $version }) 不符。
main-download-dashboard-failed = 下载管理面板文件失败: { $error }。
```

This way the Fluent runtime can correctly interpolate the values.
</issue_to_address>

### Comment 3
<location> `astrbot/dashboard/routes/lang_route.py:8-9` </location>
<code_context>
+class LangRoute(Route):
+    def __init__(self, context: RouteContext) -> None:
+        super().__init__(context)
+        self.routes = {
+            "/setLang": ("GET", self.set_Lang),
+        }
+        self.register_routes()
</code_context>

<issue_to_address>
**issue (bug_risk):** Route is registered as GET but the frontend uses POST with a JSON body, leading to a method mismatch.

The frontend calls `axios.post("/api/setLang", { lang: ... })`, but this route is registered as `"GET"`. Because `set_Lang` uses `await request.get_json()`, this should be exposed as a POST endpoint instead:

```python
self.routes = {
    "/setLang": ("POST", self.set_Lang),
}
```
</issue_to_address>

### Comment 4
<location> `dashboard/src/i18n/composables.ts:101-110` </location>
<code_context>
         detail: { locale: newLocale }
       }));
+
+      axios.post("/api/setLang", { lang: newLocale })
+          .then(response => {
+            if (response.data.code !== 200) {
</code_context>

<issue_to_address>
**suggestion:** The language-setting call is duplicated in both `setLocale` and `setupI18n`, which could drift or complicate behavior changes.

The `axios.post("/api/setLang", ...)` call is implemented both on init and on locale change. To avoid duplication and potential drift, extract this into a helper like `syncLangWithServer(locale)` that both `setLocale` and `setupI18n` use, so future changes (e.g., error handling, retries) stay consistent in one place.

Suggested implementation:

```typescript
import { translations as staticTranslations } from './translations';
import type { Locale } from './types';
import axios from 'axios';

const syncLangWithServer = (locale: Locale) => {
  return axios.post('/api/setLang', { lang: locale })
    .then(response => {
      if (response.data.code !== 200) {
        console.error('Failed to set language on server:', response.data.message);
      }
    })
    .catch(error => {
      console.error('Error setting language on server:', error);
    });
};

// 全局状态
const currentLocale = ref<Locale>('zh-CN');

```

```typescript
      window.dispatchEvent(new CustomEvent('astrbot-locale-changed', {
        detail: { locale: newLocale }
      }));

      syncLangWithServer(newLocale);

```

There is a second `axios.post("/api/setLang", ...)` call in the initialization logic of `setupI18n` (used on first load / init) that is not shown in the snippet. That block should also be replaced with `syncLangWithServer(initialLocale)` (or the appropriate variable used for the initial locale) so both init and runtime changes share the same implementation and error handling.

Sourcery 对开源项目免费——如果你觉得这次 Review 有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进 Review 质量。
Original comment in English

Hey - I've found 4 issues, and left some high level feedback:

  • The frontend calls axios.post('/api/setLang', { lang }), but LangRoute currently registers '/setLang' with the GET method and reads a JSON body; this should be aligned (path and HTTP verb) to avoid runtime 404/method and request-body issues.
  • The new t(...) usages in main.py pass positional arguments (e.g. t('main-use-specified-webui', webui_dir)), but Lang.__call__ expects keyword arguments and the FTL variables (e.g. $webui_dir, $v, $version, $error) must match those keyword names; update calls to use named arguments and ensure the variable names in the .ftl files and code are consistent.
  • The zh-CN FTL entries use placeholders like {webui_dir}, {v}, {VERSION}, {e} without the $ prefix and with names that differ from the English version; to prevent formatting errors, standardize them to Fluent syntax (e.g. { $webui_dir }) and align variable names with the arguments you pass from Python.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The frontend calls `axios.post('/api/setLang', { lang })`, but `LangRoute` currently registers `'/setLang'` with the `GET` method and reads a JSON body; this should be aligned (path and HTTP verb) to avoid runtime 404/method and request-body issues.
- The new `t(...)` usages in `main.py` pass positional arguments (e.g. `t('main-use-specified-webui', webui_dir)`), but `Lang.__call__` expects keyword arguments and the FTL variables (e.g. `$webui_dir`, `$v`, `$version`, `$error`) must match those keyword names; update calls to use named arguments and ensure the variable names in the .ftl files and code are consistent.
- The zh-CN FTL entries use placeholders like `{webui_dir}`, `{v}`, `{VERSION}`, `{e}` without the `$` prefix and with names that differ from the English version; to prevent formatting errors, standardize them to Fluent syntax (e.g. `{ $webui_dir }`) and align variable names with the arguments you pass from Python.

## Individual Comments

### Comment 1
<location> `main.py:71` </location>
<code_context>
     if webui_dir:
         if os.path.exists(webui_dir):
-            logger.info(f"使用指定的 WebUI 目录: {webui_dir}")
+            logger.info(t("main-use-specified-webui", webui_dir))
             return webui_dir
-        logger.warning(f"指定的 WebUI 目录 {webui_dir} 不存在,将使用默认逻辑。")
</code_context>

<issue_to_address>
**issue (bug_risk):** Fluent translation calls use positional args, which will raise TypeError and also don't match the variable names in the FTL files.

`Lang.__call__` is defined as `def __call__(self, key: str, **kwargs)`, so `t("main-use-specified-webui", webui_dir)` will raise `TypeError` due to the extra positional argument. The FTL entries also expect named variables (`$webui_dir`, `$v`, `$version`, `$error`), so these should be passed as keyword args, e.g.:

```python
logger.info(t("main-use-specified-webui", webui_dir=webui_dir))
logger.warning(t("main-webui-not-found", webui_dir=webui_dir))
logger.warning(t("main-webui-version-mismatch", v=v, version=VERSION))
logger.critical(t("main-download-dashboard-failed", error=e))
```

This avoids the runtime error and matches Fluent's variable naming.
</issue_to_address>

### Comment 2
<location> `locales/zh-cn/main.ftl:2-7` </location>
<code_context>
+main-python-version-error = 请使用 Python3.10+ 运行本项目。
+main-use-specified-webui = 使用指定的 WebUI 目录: {webui_dir}
+main-webui-not-found = 指定的 WebUI 目录 {webui_dir} 不存在,将使用默认逻辑。
+main-webui-latest = WebUI 版本已是最新
+main-webui-version-mismatch = 检测到 WebUI 版本 ({v}) 与当前 AstrBot 版本 (v{VERSION}) 不符。
+main-downloading-dashboard =  开始下载管理面板文件...高峰期(晚上)可能导致较慢的速度。如多次下载失败,请前往 https://github.com/AstrBotDevs/AstrBot/releases/latest 下载 dist.zip,并将其中的 dist 文件夹解压至 data 目录下。
+main-download-dashboard-failed = 下载管理面板文件失败: {e}。
+main-download-dashboard-success = 管理面板下载完成。
+main-argparse-webui-dir-help = 指定 WebUI 静态文件目录路径
</code_context>

<issue_to_address>
**issue (bug_risk):** The zh-CN FTL file uses non-Fluent placeholder syntax that won’t be substituted correctly.

In Fluent, external arguments must be referenced with a leading `$`, e.g. `{ $webui_dir }`, `{ $v }`, `{ $version }`, `{ $error }`. The current zh-CN entries omit the `$` and use `VERSION`/`e`, which don’t match the variables you’ll pass from Python. Please align them with the en file and your Python kwargs, for example:

```ftl
main-use-specified-webui = 使用指定的 WebUI 目录: { $webui_dir }
main-webui-not-found = 指定的 WebUI 目录 { $webui_dir } 不存在,将使用默认逻辑。
main-webui-version-mismatch = 检测到 WebUI 版本 ({ $v }) 与当前 AstrBot 版本 (v{ $version }) 不符。
main-download-dashboard-failed = 下载管理面板文件失败: { $error }。
```

This way the Fluent runtime can correctly interpolate the values.
</issue_to_address>

### Comment 3
<location> `astrbot/dashboard/routes/lang_route.py:8-9` </location>
<code_context>
+class LangRoute(Route):
+    def __init__(self, context: RouteContext) -> None:
+        super().__init__(context)
+        self.routes = {
+            "/setLang": ("GET", self.set_Lang),
+        }
+        self.register_routes()
</code_context>

<issue_to_address>
**issue (bug_risk):** Route is registered as GET but the frontend uses POST with a JSON body, leading to a method mismatch.

The frontend calls `axios.post("/api/setLang", { lang: ... })`, but this route is registered as `"GET"`. Because `set_Lang` uses `await request.get_json()`, this should be exposed as a POST endpoint instead:

```python
self.routes = {
    "/setLang": ("POST", self.set_Lang),
}
```
</issue_to_address>

### Comment 4
<location> `dashboard/src/i18n/composables.ts:101-110` </location>
<code_context>
         detail: { locale: newLocale }
       }));
+
+      axios.post("/api/setLang", { lang: newLocale })
+          .then(response => {
+            if (response.data.code !== 200) {
</code_context>

<issue_to_address>
**suggestion:** The language-setting call is duplicated in both `setLocale` and `setupI18n`, which could drift or complicate behavior changes.

The `axios.post("/api/setLang", ...)` call is implemented both on init and on locale change. To avoid duplication and potential drift, extract this into a helper like `syncLangWithServer(locale)` that both `setLocale` and `setupI18n` use, so future changes (e.g., error handling, retries) stay consistent in one place.

Suggested implementation:

```typescript
import { translations as staticTranslations } from './translations';
import type { Locale } from './types';
import axios from 'axios';

const syncLangWithServer = (locale: Locale) => {
  return axios.post('/api/setLang', { lang: locale })
    .then(response => {
      if (response.data.code !== 200) {
        console.error('Failed to set language on server:', response.data.message);
      }
    })
    .catch(error => {
      console.error('Error setting language on server:', error);
    });
};

// 全局状态
const currentLocale = ref<Locale>('zh-CN');

```

```typescript
      window.dispatchEvent(new CustomEvent('astrbot-locale-changed', {
        detail: { locale: newLocale }
      }));

      syncLangWithServer(newLocale);

```

There is a second `axios.post("/api/setLang", ...)` call in the initialization logic of `setupI18n` (used on first load / init) that is not shown in the snippet. That block should also be replaced with `syncLangWithServer(initialLocale)` (or the appropriate variable used for the initial locale) so both init and runtime changes share the same implementation and error handling.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

if webui_dir:
if os.path.exists(webui_dir):
logger.info(f"使用指定的 WebUI 目录: {webui_dir}")
logger.info(t("main-use-specified-webui", webui_dir))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Fluent 的翻译调用使用了位置参数,这会触发 TypeError,并且也与 FTL 文件中的变量名不匹配。

Lang.__call__ 的定义是 def __call__(self, key: str, **kwargs),因此 t("main-use-specified-webui", webui_dir) 会因为多出的那个位置参数触发 TypeError。FTL 条目也期望使用具名变量($webui_dir, $v, $version, $error),因此应该通过关键字参数传入,例如:

logger.info(t("main-use-specified-webui", webui_dir=webui_dir))
logger.warning(t("main-webui-not-found", webui_dir=webui_dir))
logger.warning(t("main-webui-version-mismatch", v=v, version=VERSION))
logger.critical(t("main-download-dashboard-failed", error=e))

这样可以避免运行时错误,并与 Fluent 的变量命名保持一致。

Original comment in English

issue (bug_risk): Fluent translation calls use positional args, which will raise TypeError and also don't match the variable names in the FTL files.

Lang.__call__ is defined as def __call__(self, key: str, **kwargs), so t("main-use-specified-webui", webui_dir) will raise TypeError due to the extra positional argument. The FTL entries also expect named variables ($webui_dir, $v, $version, $error), so these should be passed as keyword args, e.g.:

logger.info(t("main-use-specified-webui", webui_dir=webui_dir))
logger.warning(t("main-webui-not-found", webui_dir=webui_dir))
logger.warning(t("main-webui-version-mismatch", v=v, version=VERSION))
logger.critical(t("main-download-dashboard-failed", error=e))

This avoids the runtime error and matches Fluent's variable naming.

Comment on lines +2 to +7
main-use-specified-webui = 使用指定的 WebUI 目录: {webui_dir}
main-webui-not-found = 指定的 WebUI 目录 {webui_dir} 不存在,将使用默认逻辑。
main-webui-latest = WebUI 版本已是最新
main-webui-version-mismatch = 检测到 WebUI 版本 ({v}) 与当前 AstrBot 版本 (v{VERSION}) 不符。
main-downloading-dashboard = 开始下载管理面板文件...高峰期(晚上)可能导致较慢的速度。如多次下载失败,请前往 https://github.com/AstrBotDevs/AstrBot/releases/latest 下载 dist.zip,并将其中的 dist 文件夹解压至 data 目录下。
main-download-dashboard-failed = 下载管理面板文件失败: {e}。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): zh-CN 的 FTL 文件使用了非 Fluent 的占位符语法,无法被正确替换。

在 Fluent 中,外部参数必须使用带有 $ 前缀的形式引用,例如 { $webui_dir }, { $v }, { $version }, { $error }。当前 zh-CN 条目省略了 $,并使用 VERSION / e,这和你在 Python 中传入的变量名并不匹配。请将它们与英文文件以及 Python 里的关键字参数对齐,例如:

main-use-specified-webui = 使用指定的 WebUI 目录: { $webui_dir }
main-webui-not-found = 指定的 WebUI 目录 { $webui_dir } 不存在,将使用默认逻辑。
main-webui-version-mismatch = 检测到 WebUI 版本 ({ $v }) 与当前 AstrBot 版本 (v{ $version }) 不符。
main-download-dashboard-failed = 下载管理面板文件失败: { $error }。

这样 Fluent 运行时时才能正确插入这些变量值。

Original comment in English

issue (bug_risk): The zh-CN FTL file uses non-Fluent placeholder syntax that won’t be substituted correctly.

In Fluent, external arguments must be referenced with a leading $, e.g. { $webui_dir }, { $v }, { $version }, { $error }. The current zh-CN entries omit the $ and use VERSION/e, which don’t match the variables you’ll pass from Python. Please align them with the en file and your Python kwargs, for example:

main-use-specified-webui = 使用指定的 WebUI 目录: { $webui_dir }
main-webui-not-found = 指定的 WebUI 目录 { $webui_dir } 不存在,将使用默认逻辑。
main-webui-version-mismatch = 检测到 WebUI 版本 ({ $v }) 与当前 AstrBot 版本 (v{ $version }) 不符。
main-download-dashboard-failed = 下载管理面板文件失败: { $error }。

This way the Fluent runtime can correctly interpolate the values.

Comment on lines +8 to +9
self.routes = {
"/setLang": ("GET", self.set_Lang),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): 路由注册为 GET,但前端使用的是带 JSON body 的 POST 请求,导致方法不匹配。

前端调用的是 axios.post("/api/setLang", { lang: ... }),但当前路由注册的是 "GET"。由于 set_Lang 使用了 await request.get_json(),因此应将其暴露为 POST 接口,例如:

self.routes = {
    "/setLang": ("POST", self.set_Lang),
}
Original comment in English

issue (bug_risk): Route is registered as GET but the frontend uses POST with a JSON body, leading to a method mismatch.

The frontend calls axios.post("/api/setLang", { lang: ... }), but this route is registered as "GET". Because set_Lang uses await request.get_json(), this should be exposed as a POST endpoint instead:

self.routes = {
    "/setLang": ("POST", self.set_Lang),
}

Comment on lines +101 to 110
axios.post("/api/setLang", { lang: newLocale })
.then(response => {
if (response.data.code !== 200) {
console.error('Failed to set language on server:', response.data.message);
}
})
.catch(error => {
console.error('Error setting language on server:', error);
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: 语言设置的调用在 setLocalesetupI18n 中都各写了一遍,这可能导致逻辑漂移,也会让之后修改行为变得更复杂。

axios.post("/api/setLang", ...) 在初始化阶段和语言切换时都实现了一遍。为了避免重复和潜在的不一致,可以抽取一个类似 syncLangWithServer(locale) 的帮助函数,让 setLocalesetupI18n 共同使用,这样未来的改动(比如错误处理、重试机制)只需要维护一个地方。

建议实现:

import { translations as staticTranslations } from './translations';
import type { Locale } from './types';
import axios from 'axios';

const syncLangWithServer = (locale: Locale) => {
  return axios.post('/api/setLang', { lang: locale })
    .then(response => {
      if (response.data.code !== 200) {
        console.error('Failed to set language on server:', response.data.message);
      }
    })
    .catch(error => {
      console.error('Error setting language on server:', error);
    });
};

// 全局状态
const currentLocale = ref<Locale>('zh-CN');
      window.dispatchEvent(new CustomEvent('astrbot-locale-changed', {
        detail: { locale: newLocale }
      }));

      syncLangWithServer(newLocale);

setupI18n 的初始化逻辑中还有第二个 axios.post("/api/setLang", ...) 调用(用于首次加载 / 初始化),该代码片段没有出现在当前截取的内容里。那一块也应该替换为 syncLangWithServer(initialLocale)(或使用对应的初始语言变量),这样初始化和运行时的语言同步逻辑及错误处理就能共用同一套实现。

Original comment in English

suggestion: The language-setting call is duplicated in both setLocale and setupI18n, which could drift or complicate behavior changes.

The axios.post("/api/setLang", ...) call is implemented both on init and on locale change. To avoid duplication and potential drift, extract this into a helper like syncLangWithServer(locale) that both setLocale and setupI18n use, so future changes (e.g., error handling, retries) stay consistent in one place.

Suggested implementation:

import { translations as staticTranslations } from './translations';
import type { Locale } from './types';
import axios from 'axios';

const syncLangWithServer = (locale: Locale) => {
  return axios.post('/api/setLang', { lang: locale })
    .then(response => {
      if (response.data.code !== 200) {
        console.error('Failed to set language on server:', response.data.message);
      }
    })
    .catch(error => {
      console.error('Error setting language on server:', error);
    });
};

// 全局状态
const currentLocale = ref<Locale>('zh-CN');
      window.dispatchEvent(new CustomEvent('astrbot-locale-changed', {
        detail: { locale: newLocale }
      }));

      syncLangWithServer(newLocale);

There is a second axios.post("/api/setLang", ...) call in the initialization logic of setupI18n (used on first load / init) that is not shown in the snippet. That block should also be replaced with syncLangWithServer(initialLocale) (or the appropriate variable used for the initial locale) so both init and runtime changes share the same implementation and error handling.

@dosubot dosubot bot added the area:webui The bug / feature is about webui(dashboard) of astrbot. label Feb 18, 2026
@Li-shi-ling Li-shi-ling deleted the feat/i18n-switch-api branch February 19, 2026 04:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:webui The bug / feature is about webui(dashboard) of astrbot. size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments