diff --git a/common/constants.go b/common/constants.go index 6823b2c..40d77ce 100644 --- a/common/constants.go +++ b/common/constants.go @@ -16,6 +16,7 @@ var SystemName = "New API" var Footer = "" var Logo = "" var TopUpLink = "" +var DefaultLanguage = "" // admin-configured default language; empty = follow browser detection // var ChatLink = "" // var ChatLink2 = "" diff --git a/controller/misc.go b/controller/misc.go index b24a74a..28e767f 100644 --- a/controller/misc.go +++ b/controller/misc.go @@ -87,6 +87,7 @@ func GetStatus(c *gin.Context) { "demo_site_enabled": operation_setting.DemoSiteEnabled, "self_use_mode_enabled": operation_setting.SelfUseModeEnabled, "default_use_auto_group": setting.DefaultUseAutoGroup, + "default_language": common.DefaultLanguage, "usd_exchange_rate": operation_setting.USDExchangeRate, "price": operation_setting.Price, diff --git a/model/option.go b/model/option.go index e8aee77..5bbe0ad 100644 --- a/model/option.go +++ b/model/option.go @@ -456,6 +456,8 @@ func updateOptionMap(key string, value string) (err error) { common.SystemName = value case "Logo": common.Logo = value + case "DefaultLanguage": + common.DefaultLanguage = value case "WeChatServerAddress": common.WeChatServerAddress = value case "WeChatServerToken": diff --git a/web/src/components/layout/PageLayout.jsx b/web/src/components/layout/PageLayout.jsx index 49c47e6..ebba8d5 100644 --- a/web/src/components/layout/PageLayout.jsx +++ b/web/src/components/layout/PageLayout.jsx @@ -91,6 +91,10 @@ const PageLayout = () => { if (success) { statusDispatch({ type: 'set', payload: data }); setStatusData(data); + // Apply admin-configured default language for unauthenticated users + if (data.default_language && !localStorage.getItem('user')) { + i18n.changeLanguage(data.default_language); + } } else { showError('Unable to connect to server'); } diff --git a/web/src/components/settings/SystemSetting.jsx b/web/src/components/settings/SystemSetting.jsx index 8334c01..fbc2f43 100644 --- a/web/src/components/settings/SystemSetting.jsx +++ b/web/src/components/settings/SystemSetting.jsx @@ -100,6 +100,7 @@ const SystemSetting = () => { LinuxDOClientSecret: '', LinuxDOMinimumTrustLevel: '', ServerAddress: '', + DefaultLanguage: '', // SSRF防护配置 'fetch_setting.enable_ssrf_protection': true, 'fetch_setting.allow_private_ip': '', @@ -317,6 +318,10 @@ const SystemSetting = () => { await updateOptions([{ key: 'ServerAddress', value: ServerAddress }]); }; + const submitDefaultLanguage = async () => { + await updateOptions([{ key: 'DefaultLanguage', value: inputs.DefaultLanguage || '' }]); + }; + const submitSMTP = async () => { const options = []; @@ -716,7 +721,7 @@ const SystemSetting = () => { - + { )} /> + + + + diff --git a/web/src/context/User/index.jsx b/web/src/context/User/index.jsx index 2dd9100..7ecdebf 100644 --- a/web/src/context/User/index.jsx +++ b/web/src/context/User/index.jsx @@ -20,6 +20,7 @@ For commercial licensing, please contact support@quantumnous.com import React, { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { reducer, initialState } from './reducer'; +import { StatusContext } from '../Status'; export const UserContext = React.createContext({ state: initialState, @@ -29,6 +30,7 @@ export const UserContext = React.createContext({ export const UserProvider = ({ children }) => { const [state, dispatch] = React.useReducer(reducer, initialState); const { i18n } = useTranslation(); + const [statusState] = React.useContext(StatusContext); // Sync language preference when user data is loaded useEffect(() => { @@ -37,12 +39,15 @@ export const UserProvider = ({ children }) => { 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, i18n]); + }, [state.user?.setting, statusState.status?.default_language, i18n]); return (