diff --git a/docs/superpowers/plans/2026-04-17-default-language-setting.md b/docs/superpowers/plans/2026-04-17-default-language-setting.md
new file mode 100644
index 0000000..add5d61
--- /dev/null
+++ b/docs/superpowers/plans/2026-04-17-default-language-setting.md
@@ -0,0 +1,307 @@
+# Default Language Setting Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Allow admin to configure a global default language in System Settings, which is forced for unauthenticated users and logged-in users without a personal language preference.
+
+**Architecture:** Backend adds a `DefaultLanguage` option to the existing flat-key option system (same pattern as `SystemName`, `ServerAddress`). The value flows to frontend via `/api/status`. Frontend applies it in two places: `PageLayout.jsx` (for unauthenticated users) and `UserContext` (for logged-in users without preference).
+
+**Tech Stack:** Go (backend), React + Semi UI (frontend), i18next (i18n)
+
+**Spec:** `docs/superpowers/specs/2026-04-17-default-language-setting-design.md`
+
+---
+
+## File Map
+
+| File | Action | Responsibility |
+|------|--------|---------------|
+| `common/constants.go` | Modify | Declare `DefaultLanguage` variable |
+| `model/option.go` | Modify | Handle `DefaultLanguage` in option update switch |
+| `controller/misc.go` | Modify | Expose `default_language` in `/api/status` response |
+| `web/src/components/settings/SystemSetting.jsx` | Modify | Admin UI: language dropdown in system settings |
+| `web/src/components/layout/PageLayout.jsx` | Modify | Apply default language for unauthenticated users |
+| `web/src/context/User/index.jsx` | Modify | Fall back to default language when user has no preference |
+
+---
+
+### Task 1: Backend — Add DefaultLanguage variable and option handling
+
+**Files:**
+- Modify: `common/constants.go:17-18` (after `TopUpLink` declaration)
+- Modify: `model/option.go:457-458` (after `Logo` case in `updateOptionMap` switch)
+
+- [ ] **Step 1: Add `DefaultLanguage` variable to `common/constants.go`**
+
+In `common/constants.go`, after line 18 (`var TopUpLink = ""`), add:
+
+```go
+var DefaultLanguage = "" // admin-configured default language; empty = follow browser detection
+```
+
+- [ ] **Step 2: Add case handler in `model/option.go`**
+
+In `model/option.go`, after the `case "Logo":` block (line 457-458), add:
+
+```go
+case "DefaultLanguage":
+ common.DefaultLanguage = value
+```
+
+- [ ] **Step 3: Verify the Go code compiles**
+
+Run: `go build ./...`
+Expected: no errors
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add common/constants.go model/option.go
+git commit -m "feat(default-language): add DefaultLanguage variable and option handler"
+```
+
+---
+
+### Task 2: Backend — Expose default_language in /api/status
+
+**Files:**
+- Modify: `controller/misc.go:89` (after `"default_use_auto_group"` line)
+
+- [ ] **Step 1: Add `default_language` field to GetStatus response**
+
+In `controller/misc.go`, inside `GetStatus()`, after the line containing `"default_use_auto_group": setting.DefaultUseAutoGroup,` (line 89), add:
+
+```go
+"default_language": common.DefaultLanguage,
+```
+
+Place it right before the blank line at line 90, aligned with the surrounding entries.
+
+- [ ] **Step 2: Verify the Go code compiles**
+
+Run: `go build ./...`
+Expected: no errors
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add controller/misc.go
+git commit -m "feat(default-language): expose default_language in /api/status response"
+```
+
+---
+
+### Task 3: Frontend — Add DefaultLanguage dropdown in System Settings
+
+**Files:**
+- Modify: `web/src/components/settings/SystemSetting.jsx`
+
+- [ ] **Step 1: Add `DefaultLanguage` to `inputs` state**
+
+In `web/src/components/settings/SystemSetting.jsx`, in the `inputs` useState (around line 49-112), add `DefaultLanguage: ''` after `ServerAddress: ''` (line 102):
+
+```javascript
+ServerAddress: '',
+DefaultLanguage: '',
+```
+
+- [ ] **Step 2: Add `submitDefaultLanguage` function**
+
+After `submitServerAddress` (line 315-318), add a new function:
+
+```javascript
+const submitDefaultLanguage = async () => {
+ await updateOptions([{ key: 'DefaultLanguage', value: inputs.DefaultLanguage || '' }]);
+};
+```
+
+- [ ] **Step 3: Add language dropdown UI in the 通用设置 Card**
+
+In the `通用设置` `Form.Section` (line 715-733), inside the `` block, after the `ServerAddress` `
` closing tag (line 728) and before the `` closing tag (line 729), add a new `
`:
+
+```jsx
+
+
+
+```
+
+Also change the `ServerAddress` Col from `md={24} lg={24} xl={24}` to `md={24} lg={12} xl={12}` so both fields sit side by side on large screens.
+
+- [ ] **Step 4: Add save button for DefaultLanguage**
+
+After the existing `submitServerAddress` button (line 730-732), add:
+
+```jsx
+
+```
+
+- [ ] **Step 5: Verify frontend compiles**
+
+Run: `cd web && bun run build`
+Expected: build succeeds
+
+- [ ] **Step 6: Commit**
+
+```bash
+git add web/src/components/settings/SystemSetting.jsx
+git commit -m "feat(default-language): add language dropdown in system settings"
+```
+
+---
+
+### Task 4: Frontend — Apply default language for unauthenticated users
+
+**Files:**
+- Modify: `web/src/components/layout/PageLayout.jsx:87-100` (loadStatus function)
+
+- [ ] **Step 1: Modify `loadStatus` to apply default language**
+
+In `web/src/components/layout/PageLayout.jsx`, in the `loadStatus` function (line 87-100), after `setStatusData(data)` (line 93) and before the `} else {` (line 94), add:
+
+```javascript
+// Apply admin-configured default language for unauthenticated users
+if (data.default_language && !localStorage.getItem('user')) {
+ i18n.changeLanguage(data.default_language);
+}
+```
+
+- [ ] **Step 2: Update the existing localStorage language fallback logic**
+
+In the same file, the existing `useEffect` (line 102-120) reads `localStorage.getItem('i18nextLng')` and calls `i18n.changeLanguage(savedLang)`. This logic should be kept as-is — it handles the case where `default_language` is not set (admin chose "auto"). No changes needed to this block.
+
+- [ ] **Step 3: Verify frontend compiles**
+
+Run: `cd web && bun run build`
+Expected: build succeeds
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add web/src/components/layout/PageLayout.jsx
+git commit -m "feat(default-language): apply default language for unauthenticated users"
+```
+
+---
+
+### Task 5: Frontend — Fall back to default language for logged-in users without preference
+
+**Files:**
+- Modify: `web/src/context/User/index.jsx:20-45`
+
+- [ ] **Step 1: Import StatusContext**
+
+At the top of `web/src/context/User/index.jsx`, add `StatusContext` import after the existing imports:
+
+```javascript
+import { StatusContext } from '../Status';
+```
+
+- [ ] **Step 2: Access StatusContext inside UserProvider**
+
+Inside `UserProvider` (line 29), before the `useEffect`, add:
+
+```javascript
+const [statusState] = React.useContext(StatusContext);
+```
+
+- [ ] **Step 3: Update language sync logic**
+
+Replace the existing `useEffect` (lines 34-45) with:
+
+```javascript
+// Sync language preference when user data is loaded
+useEffect(() => {
+ if (state.user?.setting) {
+ try {
+ const settings = JSON.parse(state.user.setting);
+ if (settings.language && settings.language !== i18n.language) {
+ i18n.changeLanguage(settings.language);
+ } else if (!settings.language && statusState.status?.default_language) {
+ // No personal preference — fall back to admin default
+ i18n.changeLanguage(statusState.status.default_language);
+ }
+ } catch (e) {
+ // Ignore parse errors
+ }
+ }
+}, [state.user?.setting, statusState.status?.default_language, i18n]);
+```
+
+- [ ] **Step 4: Verify frontend compiles**
+
+Run: `cd web && bun run build`
+Expected: build succeeds
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add web/src/context/User/index.jsx
+git commit -m "feat(default-language): fall back to default language for users without preference"
+```
+
+---
+
+### Task 6: Integration verification
+
+- [ ] **Step 1: Start full-stack dev server**
+
+Terminal 1: `cd web && bun run dev`
+Terminal 2: `go run main.go`
+
+- [ ] **Step 2: Test admin setting**
+
+1. Login as admin, navigate to Settings → System Settings (系统设置)
+2. Find the "默认语言" dropdown in the 通用设置 section
+3. Select "English" and click "保存默认语言"
+4. Verify success toast appears
+5. Refresh the page — the dropdown should still show "English"
+
+- [ ] **Step 3: Test unauthenticated user behavior**
+
+1. Open an incognito/private browser window
+2. Visit the site
+3. Expected: The page renders in English (not following browser language)
+4. The header language selector still shows English as active
+
+- [ ] **Step 4: Test logged-in user with personal preference**
+
+1. Login as a regular user
+2. Go to personal settings, set language to "Français"
+3. Refresh — page should be in French (personal preference overrides admin default)
+
+- [ ] **Step 5: Test logged-in user without personal preference**
+
+1. Login as a user who has never set a language preference
+2. Expected: Page renders in English (admin default), not browser language
+
+- [ ] **Step 6: Test "auto" mode**
+
+1. As admin, set "默认语言" back to "自动(跟随浏览器)"
+2. Save, then test in incognito — should follow browser language again
+
+- [ ] **Step 7: Verify /api/status returns the field**
+
+```bash
+curl -s http://localhost:3000/api/status | python -m json.tool | grep default_language
+```
+
+Expected: `"default_language": "en"` (or the set value, or `""` if auto)