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 (