fix: Kill auto language (#21)

* fix: Kill auto language

Kill the background automatic recognition of language to prevent backend
Language file correction

* refactor(Aggregate): Ports and install hosts

Optimize multi-language

* fix(I18n): Kill spurious shortcuts

Fix wrong import
This commit is contained in:
GuGuGu
2024-12-02 13:57:03 +01:00
committed by GitHub
parent 51c0af6146
commit 22c53cf723
10 changed files with 68 additions and 63 deletions

View File

@@ -210,7 +210,7 @@ const FMComponent: React.FC<FMProps & JSX.IntrinsicElements["div"]> = ({ wsUrl,
if (uOpen) setuOpen(false);
listFile();
} else {
throw new Error("Unknown identifier");
throw new Error(t("Results.UnknownIdentifier"));
}
} else {
await waitForHandleReady();

View File

@@ -117,7 +117,7 @@ export default function Header() {
<AvatarFallback>{profile.username}</AvatarFallback>
</Avatar>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
<DropdownMenuContent className="w-32">
<DropdownMenuLabel>{profile.username}</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
@@ -125,14 +125,12 @@ export default function Header() {
<Link to="/dashboard/profile" className="flex items-center gap-2 w-full">
<User2 />
{t('Profile')}
<DropdownMenuShortcut>P</DropdownMenuShortcut>
</Link>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => { setDropdownOpen(false) }}>
<Link to="/dashboard/settings" className="flex items-center gap-2 w-full">
<Settings />
{t('Settings')}
<DropdownMenuShortcut>S</DropdownMenuShortcut>
</Link>
</DropdownMenuItem>
</DropdownMenuGroup>
@@ -140,7 +138,6 @@ export default function Header() {
<DropdownMenuItem onClick={logout} className="cursor-pointer">
<LogOut />
{t('Logout')}
<DropdownMenuShortcut>Q</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>

View File

@@ -10,9 +10,10 @@ import useSettings from "@/hooks/useSetting"
import { ModelConfig } from "@/types"
import { Check, Clipboard } from "lucide-react"
import { toast } from "sonner"
import { copyToClipboard } from "@/lib/utils"
import { useTranslation } from "react-i18next"
import { copyToClipboard } from "@/lib/utils"
import i18next from "i18next"
enum OSTypes {
Linux = 1,
@@ -61,22 +62,23 @@ export const InstallCommandsMenu = forwardRef<HTMLButtonElement, ButtonProps>((p
);
})
const generateCommand = (type: number, { agent_secret_key, install_host, listen_port, tls }: ModelConfig) => {
const generateCommand = (type: number, { agent_secret_key, install_host, tls }: ModelConfig) => {
if (!install_host)
throw new Error("You have not specify the installed host.")
throw new Error(i18next.t("Results.InstallHostRequired"));
const env = `NZ_SERVER=${install_host}:${listen_port} NZ_TLS=${tls || false} NZ_CLIENT_SECRET=${agent_secret_key}`;
const env = `NZ_SERVER=${install_host} NZ_TLS=${tls || false} NZ_CLIENT_SECRET=${agent_secret_key}`;
switch (type) {
case OSTypes.Linux:
case OSTypes.macOS: {
return `curl -L https://raw.githubusercontent.com/nezhahq/scripts/main/agent/install.sh -o nezha.sh && chmod +x nezha.sh && env ${env} ./nezha.sh`
}
case OSTypes.Windows: {
return `${env} [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Ssl3 -bor [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12;set-ExecutionPolicy RemoteSigned;Invoke-WebRequest https://raw.githubusercontent.com/nezhahq/scripts/main/agent/install.ps1 -OutFile C:\install.ps1;powershell.exe C:\install.ps1`
}
default: {
throw new Error(`Unknown OS: ${type}`);
}
case OSTypes.Linux:
case OSTypes.macOS: {
return `curl -L https://raw.githubusercontent.com/nezhahq/scripts/main/agent/install.sh -o nezha.sh && chmod +x nezha.sh && env ${env} ./nezha.sh`
}
case OSTypes.Windows: {
return `${env} [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Ssl3 -bor [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12;set-ExecutionPolicy RemoteSigned;Invoke-WebRequest https://raw.githubusercontent.com/nezhahq/scripts/main/agent/install.ps1 -OutFile C:\install.ps1;powershell.exe C:\install.ps1`
}
default: {
throw new Error(`Unknown OS: ${type}`);
}
}
}

View File

@@ -1,6 +1,5 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import enTranslation from "../locales/en/translation.json";
import itTranslation from "../locales/it/translation.json";
@@ -22,16 +21,22 @@ const resources = {
},
};
const getStoredLanguage = () => {
return localStorage.getItem("language") || "zh-CN";
};
i18n.use(initReactI18next)
.use(LanguageDetector)
.init({
resources,
lng: getStoredLanguage(), // 使用localStorage中存储的语言或默认值
fallbackLng: "en", // 当前语言的翻译没有找到时,使用的备选语言
interpolation: {
escapeValue: false, // react已经安全地转义
},
});
i18n.on("languageChanged", (lng) => {
localStorage.setItem("language", lng);
});
export default i18n;

View File

@@ -17,7 +17,9 @@
"NoRowsAreSelected": "No rows are selected",
"ThisOperationIsUnrecoverable": "This operation cannot be undone!",
"TaskTriggeredSuccessfully": "The task triggered successfully",
"TheServerDoesNotOnline": "The server does not exist or has not been connected yet"
"TheServerDoesNotOnline": "The server does not exist or has not been connected yet",
"InstallHostRequired": "The Agent docking address has not been filled in in the settings.",
"UnknownIdentifier": "Unknown identifier"
},
"Login": "Log in",
"Server": "Server",
@@ -101,7 +103,7 @@
"Domains": "domain name",
"MaximumRetryAttempts": "Maximum number of retries",
"Refresh": "Refresh",
"CopyPath": "copy path",
"CopyPath": "Copy path",
"Goto": "Go to",
"UpdateProfile": "Update profile",
"NewUsername": "New username",
@@ -117,19 +119,18 @@
"Uploading": "Uploading",
"EditNAT": "Edit intranet penetration",
"CreateNAT": "Create intranet penetration",
"LocalService": "local service",
"LocalService": "Local service",
"BindHostname": "Bind domain name",
"EditServerGroup": "Edit server group",
"CreateServerGroup": "Create server group",
"User": "User",
"WAF": "Web application firewall",
"SiteName": "Site name",
"DashboardOriginalHost": "Dashboard Server Domain/IP without CDN",
"Auto": "Automatic",
"DashboardOriginalHost": "Agent docking address [domain name/IP:port]",
"LoginFailed": "Login failed",
"BruteForceAttackingToken": "Brute Force Attacking Token",
"BruteForceAttackingAgentSecret": "Brute Force Attacking Agent Secret",
"Language": "language",
"Language": "Language",
"CustomCodes": "Custom Codes (Style and Script)",
"CustomCodesDashboard": "Custom Codes for Dashboard",
"CustomPublicDNSNameserversforDDNS": "Custom Public DNS Nameservers for DDNS",
@@ -137,7 +138,7 @@
"UseDirectConnectingIP": "Use direct connection IP",
"IPChangeNotification": "IP Change notification",
"FullIPNotification": "Show Full IP Address in Notification Messages",
"EditService": "Editing services",
"EditService": "Edit service",
"CreateService": "Create service",
"EditTask": "Edit task",
"CreateTask": "Create task",
@@ -147,8 +148,8 @@
"CreateAlertRule": "Create alert rules",
"EditNotifierGroup": "Edit notification group",
"CreateNotifierGroup": "Create notification group",
"NewUser": "new user",
"NewUser": "New user",
"Count": "Count",
"LastBlockReason": "Last Block Reason",
"LastBlockTime": "Last ban time"
}
}

View File

@@ -17,7 +17,9 @@
"NoRowsAreSelected": "Nessuna riga selezionata",
"ThisOperationIsUnrecoverable": "Questa operazione non può essere annullata!",
"TaskTriggeredSuccessfully": "Attività avviata correttamente",
"TheServerDoesNotOnline": "Il server non esiste o non è stato ancora connesso"
"TheServerDoesNotOnline": "Il server non esiste o non è stato ancora connesso",
"InstallHostRequired": "L'indirizzo di aggancio dell'Agent non è stato inserito nelle impostazioni.",
"UnknownIdentifier": "identificatore sconosciuto"
},
"Login": "Accedi",
"Server": "Server",
@@ -45,23 +47,23 @@
"Done": "Fine",
"Offline": "Non in linea",
"Failure": "Fallire",
"Loading": "caricamento",
"NoResults": "nessun contenuto",
"Loading": "Caricamento",
"NoResults": "Nessun contenuto",
"Actions": "Azione",
"EditServer": "Modifica server",
"Weight": "Peso (più grande è il numero, più alto sarà visualizzato)",
"DDNSProfiles": "ID profilo DDNS",
"SeparateWithComma": "(separati da virgole)",
"Public": "Pubblico",
"Private": "privato",
"Submit": "invia",
"Private": "Privato",
"Submit": "Invia",
"Target": "Bersaglio",
"Coverage": "Copertura",
"CoverAll": "Copri tutto",
"IgnoreAll": "Ignorare tutto",
"SpecificServers": "Server specifico",
"Type": "Tipo",
"Interval": "intervallo",
"Interval": "Intervallo",
"NotifierGroupID": "ID del gruppo di notifiche",
"Trigger": "Grilletto",
"TasksToTriggerOnAlert": "L'attività che ha attivato l'avviso",
@@ -82,7 +84,7 @@
"EnableTriggerTask": "Abilita attività di attivazione",
"CronExpression": "Espressione cron",
"Command": "Ordine",
"NotifierGroup": "gruppo di notifica",
"NotifierGroup": "Gruppo di notifica",
"SendSuccessNotification": "Invia notifica di successo",
"LastExecution": "Ultimo giustiziato",
"Result": "Risultato",
@@ -96,16 +98,16 @@
"RequestHeader": "Intestazione della richiesta",
"DoNotSendTestMessage": "Non inviare messaggi di prova",
"Always": "Sempre",
"Once": "solo una volta",
"Provider": "fornitore",
"Domains": "nome di dominio",
"Once": "Solo una volta",
"Provider": "Fornitore",
"Domains": "Nome di dominio",
"MaximumRetryAttempts": "Numero massimo di tentativi",
"Refresh": "aggiornare",
"CopyPath": "percorso di copia",
"CopyPath": "Percorso di copia",
"Goto": "Vai a",
"UpdateProfile": "Aggiorna il profilo",
"NewUsername": "Nuovo nome utente",
"OriginalPassword": "password originale",
"OriginalPassword": "Password originale",
"NewPassword": "Nuova parola d'ordine",
"EditDDNS": "Modifica DDNS",
"CreateDDNS": "Crea DDNS",
@@ -125,7 +127,6 @@
"CreateService": "Crea servizio",
"EditTask": "Modifica attività",
"CreateTask": "Crea attività",
"Auto": "automatico",
"CreateNotifier": "Crea notifica",
"EditNotifier": "Modifica notifica",
"EditAlertRule": "Modifica le regole degli allarmi",
@@ -135,10 +136,10 @@
"User": "Utente",
"WAF": "Firewall dell'applicazione Web",
"SiteName": "Nome del sito",
"Language": "lingua",
"Language": "Lingua",
"CustomCodes": "Codice personalizzato (stili e script)",
"CustomCodesDashboard": "Codice personalizzato per dashboard",
"DashboardOriginalHost": "Nome di dominio/IP del server Dashboard (no CDN)",
"DashboardOriginalHost": "Indirizzo di ancoraggio dell'agente [nome dominio/IP:porta]",
"CustomPublicDNSNameserversforDDNS": "Server dei nomi DNS pubblici personalizzati per DDNS",
"RealIPHeader": "Intestazione della richiesta IP reale",
"UseDirectConnectingIP": "Utilizzare l'IP di connessione diretta",
@@ -147,8 +148,8 @@
"LoginFailed": "Accesso non riuscito",
"BruteForceAttackingToken": "Segnalino di attacco di forza bruta",
"BruteForceAttackingAgentSecret": "Segreti proxy dell'attacco di forza bruta",
"NewUser": "nuovo utente",
"Count": "contare",
"NewUser": "Nuovo utente",
"Count": "Contare",
"LastBlockReason": "Motivo dell'ultimo divieto",
"LastBlockTime": "L'ultima volta che è stato vietato"
}
}

View File

@@ -17,7 +17,9 @@
"NoRowsAreSelected": "未选择任何行",
"ThisOperationIsUnrecoverable": "这个操作将无法恢复!",
"TaskTriggeredSuccessfully": "任务触发成功",
"TheServerDoesNotOnline": "服务器不存在或者还未连接"
"TheServerDoesNotOnline": "服务器不存在或者还未连接",
"InstallHostRequired": "设置中尚未填写Agent对接地址",
"UnknownIdentifier": "未知标识符"
},
"Login": "登录",
"Server": "服务器",
@@ -137,7 +139,7 @@
"Language": "语言",
"CustomCodes": "自定义代码(样式和脚本)",
"CustomCodesDashboard": "仪表板的自定义代码",
"DashboardOriginalHost": "仪表板服务器域名/IP无 CDN",
"DashboardOriginalHost": "Agent对接地址【域名/IP:端口】",
"CustomPublicDNSNameserversforDDNS": "DDNS 的自定义公共 DNS 名称服务器",
"RealIPHeader": "真实IP请求头",
"UseDirectConnectingIP": "使用直连 IP",
@@ -149,6 +151,5 @@
"NewUser": "新用户",
"Count": "计数",
"LastBlockReason": "最后封禁原因",
"LastBlockTime": "最后封禁时间",
"Auto": "自动"
}
"LastBlockTime": "最后封禁时间"
}

View File

@@ -17,7 +17,9 @@
"NoRowsAreSelected": "未選擇任何行",
"ThisOperationIsUnrecoverable": "這個操作將無法恢復!",
"TaskTriggeredSuccessfully": "任務觸發成功",
"TheServerDoesNotOnline": "伺服器不存在或尚未連接"
"TheServerDoesNotOnline": "伺服器不存在或尚未連接",
"InstallHostRequired": "設定中尚未填寫Agent對接位址",
"UnknownIdentifier": "未知標識符"
},
"Login": "登入",
"Server": "伺服器",
@@ -137,7 +139,7 @@
"Language": "語言",
"CustomCodes": "自訂程式碼(樣式和腳本)",
"CustomCodesDashboard": "儀表板的自訂程式碼",
"DashboardOriginalHost": "儀表板伺服器網域/IP無 CDN",
"DashboardOriginalHost": "Agent對接位址【網域名稱/IP:連接埠】",
"CustomPublicDNSNameserversforDDNS": "DDNS 的自訂公共 DNS 名稱伺服器",
"RealIPHeader": "真實IP請求頭",
"UseDirectConnectingIP": "使用直連 IP",
@@ -149,6 +151,5 @@
"NewUser": "新用戶",
"Count": "計數",
"LastBlockReason": "最後封鎖原因",
"LastBlockTime": "最後封鎖時間",
"Auto": "自動"
}
"LastBlockTime": "最後封鎖時間"
}

View File

@@ -105,11 +105,9 @@ export default function SettingsPage() {
if (e instanceof Error) setError(e);
return;
} finally {
if (values.language != "auto") {
if (values.language != i18n.language) {
i18n.changeLanguage(values.language);
} else {
i18n.changeLanguage(i18n.services.languageDetector.detect());
}
}
toast(t("Success"));
}
};

View File

@@ -5,7 +5,6 @@ export const settingCoverageTypes: Record<number, string> = {
}
export const nezhaLang: Record<string, string> = {
"auto": i18next.t("Auto"),
"zh-CN": "简体中文(中国大陆)",
"zh-TW": "正體中文(台灣)",
"en-US": "English",