Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

9.9 KiB

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)

In common/constants.go, after line 18 (var TopUpLink = ""), add:

var DefaultLanguage = "" // admin-configured default language; empty = follow browser detection

In model/option.go, after the case "Logo": block (line 457-458), add:

case "DefaultLanguage":
	common.DefaultLanguage = value

Run: go build ./... Expected: no errors

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)

In controller/misc.go, inside GetStatus(), after the line containing "default_use_auto_group": setting.DefaultUseAutoGroup, (line 89), add:

"default_language":                common.DefaultLanguage,

Place it right before the blank line at line 90, aligned with the surrounding entries.

Run: go build ./... Expected: no errors

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

In web/src/components/settings/SystemSetting.jsx, in the inputs useState (around line 49-112), add DefaultLanguage: '' after ServerAddress: '' (line 102):

ServerAddress: '',
DefaultLanguage: '',

After submitServerAddress (line 315-318), add a new function:

const submitDefaultLanguage = async () => {
  await updateOptions([{ key: 'DefaultLanguage', value: inputs.DefaultLanguage || '' }]);
};

In the 通用设置 Form.Section (line 715-733), inside the <Row> block, after the ServerAddress <Col> closing tag (line 728) and before the </Row> closing tag (line 729), add a new <Col>:

<Col xs={24} sm={24} md={24} lg={12} xl={12}>
  <Form.Select
    field='DefaultLanguage'
    label={t('默认语言')}
    placeholder={t('未设置时跟随浏览器语言')}
    optionList={[
      { label: t('自动(跟随浏览器)'), value: '' },
      { label: '简体中文', value: 'zh-CN' },
      { label: '繁體中文', value: 'zh-TW' },
      { label: 'English', value: 'en' },
      { label: 'Français', value: 'fr' },
      { label: '日本語', value: 'ja' },
      { label: 'Русский', value: 'ru' },
      { label: 'Tiếng Việt', value: 'vi' },
    ]}
    extraText={t(
      '设置后,未登录用户和未设置语言偏好的已登录用户将强制使用此语言',
    )}
  />
</Col>

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.

After the existing submitServerAddress button (line 730-732), add:

<Button onClick={submitDefaultLanguage}>
  {t('保存默认语言')}
</Button>

Run: cd web && bun run build Expected: build succeeds

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)

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:

// Apply admin-configured default language for unauthenticated users
if (data.default_language && !localStorage.getItem('user')) {
  i18n.changeLanguage(data.default_language);
}

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.

Run: cd web && bun run build Expected: build succeeds

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

At the top of web/src/context/User/index.jsx, add StatusContext import after the existing imports:

import { StatusContext } from '../Status';

Inside UserProvider (line 29), before the useEffect, add:

const [statusState] = React.useContext(StatusContext);

Replace the existing useEffect (lines 34-45) with:

// 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]);

Run: cd web && bun run build Expected: build succeeds

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

Terminal 1: cd web && bun run dev Terminal 2: go run main.go

  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”
  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
  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)
  1. Login as a user who has never set a language preference
  2. Expected: Page renders in English (admin default), not browser language
  1. As admin, set “默认语言” back to “自动(跟随浏览器)”
  2. Save, then test in incognito — should follow browser language again
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)