mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-05-26 07:08:01 +00:00
i18n: translate hardcoded inbound action + security warning strings (#4502)
The inbound row actions (delete / reset traffic / clone / export links / export subscription links / show JSON / export-all variants) and the security warning alert on the Settings page were emitting English text directly. Replace them with i18n keys and add translations across all 13 supported locales.
This commit is contained in:
@@ -235,15 +235,15 @@ export default function InboundsPage() {
|
||||
const exportInboundLinks = useCallback((dbInbound: any) => {
|
||||
const projected = checkFallback(dbInbound);
|
||||
openText({
|
||||
title: 'Export inbound links',
|
||||
title: t('pages.inbounds.exportLinksTitle'),
|
||||
content: projected.genInboundLinks(remarkModel, hostOverrideFor(dbInbound)),
|
||||
fileName: projected.remark || 'inbound',
|
||||
});
|
||||
}, [checkFallback, remarkModel, hostOverrideFor, openText]);
|
||||
}, [checkFallback, remarkModel, hostOverrideFor, openText, t]);
|
||||
|
||||
const exportInboundClipboard = useCallback((dbInbound: any) => {
|
||||
openText({ title: 'Inbound JSON', content: JSON.stringify(dbInbound, null, 2) });
|
||||
}, [openText]);
|
||||
openText({ title: t('pages.inbounds.inboundJsonTitle'), content: JSON.stringify(dbInbound, null, 2) });
|
||||
}, [openText, t]);
|
||||
|
||||
const exportInboundSubs = useCallback((dbInbound: any) => {
|
||||
const inbound = dbInbound.toInbound();
|
||||
@@ -255,11 +255,11 @@ export default function InboundsPage() {
|
||||
}
|
||||
}
|
||||
openText({
|
||||
title: 'Export subscription links',
|
||||
title: t('pages.inbounds.exportSubsTitle'),
|
||||
content: [...new Set(subLinks)].join('\n'),
|
||||
fileName: `${dbInbound.remark || 'inbound'}-Subs`,
|
||||
});
|
||||
}, [subSettings, openText]);
|
||||
}, [subSettings, openText, t]);
|
||||
|
||||
const exportAllLinks = useCallback(async () => {
|
||||
const hydrated = await Promise.all(
|
||||
@@ -270,8 +270,8 @@ export default function InboundsPage() {
|
||||
const projected = checkFallback(ib);
|
||||
out.push(projected.genInboundLinks(remarkModel, hostOverrideFor(ib)));
|
||||
}
|
||||
openText({ title: 'Export all inbound links', content: out.join('\r\n'), fileName: 'All-Inbounds' });
|
||||
}, [dbInbounds, hydrateInbound, checkFallback, remarkModel, hostOverrideFor, openText]);
|
||||
openText({ title: t('pages.inbounds.exportAllLinksTitle'), content: out.join('\r\n'), fileName: 'All-Inbounds' });
|
||||
}, [dbInbounds, hydrateInbound, checkFallback, remarkModel, hostOverrideFor, openText, t]);
|
||||
|
||||
const exportAllSubs = useCallback(async () => {
|
||||
const hydrated = await Promise.all(
|
||||
@@ -287,8 +287,8 @@ export default function InboundsPage() {
|
||||
}
|
||||
}
|
||||
}
|
||||
openText({ title: 'Export all subscription links', content: [...new Set(out)].join('\r\n'), fileName: 'All-Inbounds-Subs' });
|
||||
}, [dbInbounds, hydrateInbound, subSettings, openText]);
|
||||
openText({ title: t('pages.inbounds.exportAllSubsTitle'), content: [...new Set(out)].join('\r\n'), fileName: 'All-Inbounds-Subs' });
|
||||
}, [dbInbounds, hydrateInbound, subSettings, openText, t]);
|
||||
|
||||
const importInbound = useCallback(() => {
|
||||
openPrompt({
|
||||
@@ -321,37 +321,37 @@ export default function InboundsPage() {
|
||||
|
||||
const confirmDelete = useCallback((dbInbound: any) => {
|
||||
modal.confirm({
|
||||
title: `Delete inbound "${dbInbound.remark}"?`,
|
||||
content: 'This removes the inbound and all its clients. This cannot be undone.',
|
||||
okText: 'Delete',
|
||||
title: t('pages.inbounds.deleteConfirmTitle', { remark: dbInbound.remark }),
|
||||
content: t('pages.inbounds.deleteConfirmContent'),
|
||||
okText: t('delete'),
|
||||
okType: 'danger',
|
||||
cancelText: 'Cancel',
|
||||
cancelText: t('cancel'),
|
||||
onOk: async () => {
|
||||
const msg = await HttpUtil.post(`/panel/api/inbounds/del/${dbInbound.id}`);
|
||||
if (msg?.success) await refresh();
|
||||
},
|
||||
});
|
||||
}, [modal, refresh]);
|
||||
}, [modal, refresh, t]);
|
||||
|
||||
const confirmResetTraffic = useCallback((dbInbound: any) => {
|
||||
modal.confirm({
|
||||
title: `Reset traffic for "${dbInbound.remark}"?`,
|
||||
content: 'Resets up/down counters to 0 for this inbound.',
|
||||
okText: 'Reset',
|
||||
cancelText: 'Cancel',
|
||||
title: t('pages.inbounds.resetConfirmTitle', { remark: dbInbound.remark }),
|
||||
content: t('pages.inbounds.resetConfirmContent'),
|
||||
okText: t('reset'),
|
||||
cancelText: t('cancel'),
|
||||
onOk: async () => {
|
||||
const msg = await HttpUtil.post(`/panel/api/inbounds/${dbInbound.id}/resetTraffic`);
|
||||
if (msg?.success) await refresh();
|
||||
},
|
||||
});
|
||||
}, [modal, refresh]);
|
||||
}, [modal, refresh, t]);
|
||||
|
||||
const confirmClone = useCallback((dbInbound: any) => {
|
||||
modal.confirm({
|
||||
title: `Clone inbound "${dbInbound.remark}"?`,
|
||||
content: 'Creates a copy with a new port and an empty client list.',
|
||||
okText: 'Clone',
|
||||
cancelText: 'Cancel',
|
||||
title: t('pages.inbounds.cloneConfirmTitle', { remark: dbInbound.remark }),
|
||||
content: t('pages.inbounds.cloneConfirmContent'),
|
||||
okText: t('pages.inbounds.clone'),
|
||||
cancelText: t('cancel'),
|
||||
onOk: async () => {
|
||||
const baseInbound = dbInbound.toInbound();
|
||||
let clonedSettings: string;
|
||||
@@ -380,7 +380,7 @@ export default function InboundsPage() {
|
||||
if (msg?.success) await refresh();
|
||||
},
|
||||
});
|
||||
}, [modal, refresh]);
|
||||
}, [modal, refresh, t]);
|
||||
|
||||
const onGeneralAction = useCallback((key: GeneralAction) => {
|
||||
switch (key) {
|
||||
|
||||
@@ -175,14 +175,14 @@ export default function SettingsPage() {
|
||||
const confAlerts = useMemo<string[]>(() => {
|
||||
const out: string[] = [];
|
||||
if (window.location.protocol !== 'https:') {
|
||||
out.push('Panel is served over plain HTTP — set up TLS for production.');
|
||||
out.push(t('pages.settings.warnHttp'));
|
||||
}
|
||||
if (allSetting.webPort === 2053) {
|
||||
out.push('Default port 2053 is well-known — change it to a random port.');
|
||||
out.push(t('pages.settings.warnDefaultPort'));
|
||||
}
|
||||
const segs = window.location.pathname.split('/').length < 4;
|
||||
if (segs && allSetting.webBasePath === '/') {
|
||||
out.push('Default base path "/" is well-known — change it to a random path.');
|
||||
out.push(t('pages.settings.warnDefaultBasePath'));
|
||||
}
|
||||
if (allSetting.subEnable) {
|
||||
let subPath = allSetting.subPath;
|
||||
@@ -190,7 +190,7 @@ export default function SettingsPage() {
|
||||
try { subPath = new URL(allSetting.subURI).pathname; } catch { /* noop */ }
|
||||
}
|
||||
if (subPath === '/sub/') {
|
||||
out.push('Default subscription path "/sub/" is well-known — change it.');
|
||||
out.push(t('pages.settings.warnDefaultSubPath'));
|
||||
}
|
||||
}
|
||||
if (allSetting.subJsonEnable) {
|
||||
@@ -199,11 +199,11 @@ export default function SettingsPage() {
|
||||
try { p = new URL(allSetting.subJsonURI).pathname; } catch { /* noop */ }
|
||||
}
|
||||
if (p === '/json/') {
|
||||
out.push('Default JSON subscription path "/json/" is well-known — change it.');
|
||||
out.push(t('pages.settings.warnDefaultJsonPath'));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}, [allSetting]);
|
||||
}, [allSetting, t]);
|
||||
|
||||
const pageClass = useMemo(() => {
|
||||
const classes = ['settings-page'];
|
||||
@@ -286,10 +286,10 @@ export default function SettingsPage() {
|
||||
closable
|
||||
className="conf-alert"
|
||||
onClose={() => setAlertVisible(false)}
|
||||
title="Security warnings"
|
||||
title={t('pages.settings.securityWarnings')}
|
||||
description={(
|
||||
<>
|
||||
<b>Your panel may be exposed:</b>
|
||||
<b>{t('pages.settings.panelExposed')}</b>
|
||||
<ul>
|
||||
{confAlerts.map((msg, i) => <li key={i}>{msg}</li>)}
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user