B6 frontend: notification settings + cf-probe retirement checklist on the public-page tab; probeNotify i18n x13
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
} from 'antd';
|
||||
import { DeleteOutlined, SettingOutlined, UploadOutlined } from '@ant-design/icons';
|
||||
import { HttpUtil } from '@/utils';
|
||||
import { onNumber } from '@/utils/onNumber';
|
||||
|
||||
// Item 7 B5: the public status page's settings + theme store. Like
|
||||
// the probe-meta section this surface is self-contained — it loads
|
||||
@@ -60,6 +61,35 @@ interface ThemesPayload {
|
||||
touchIcon: string;
|
||||
}
|
||||
|
||||
// Notify settings wire shape (B6) — mirrors probenotify.SettingsView.
|
||||
// The webhook URL and headers are secrets: the GET answers only
|
||||
// whether they are set, and the PUT omits them unless the admin
|
||||
// edited the field (an explicit clear sends "").
|
||||
interface NotifySettingsWire {
|
||||
notifyGrace: number;
|
||||
notifyTraffic: number;
|
||||
notifyExpiry: number;
|
||||
notifyLogin: string;
|
||||
notifyTelegramText: string;
|
||||
notifyWebhookBody: string;
|
||||
telegramConfigured: boolean;
|
||||
webhookConfigured: boolean;
|
||||
webhookUrlSet: boolean;
|
||||
webhookHeadersSet: boolean;
|
||||
}
|
||||
|
||||
interface CoverageRow {
|
||||
name: string;
|
||||
online: boolean;
|
||||
hasProbe: boolean;
|
||||
probeAt: number;
|
||||
}
|
||||
|
||||
interface NotifyPayload {
|
||||
settings: NotifySettingsWire;
|
||||
coverage: CoverageRow[];
|
||||
}
|
||||
|
||||
const JSON_HEADERS = { headers: { 'Content-Type': 'application/json' } };
|
||||
const UPLOAD_CHUNK = 1 << 20;
|
||||
const MAX_ICON_BYTES = 20 * 1024;
|
||||
@@ -123,6 +153,14 @@ export default function PublicPageTab() {
|
||||
const [installing, setInstalling] = useState(false);
|
||||
const [uploadPct, setUploadPct] = useState<number | null>(null);
|
||||
const [busyShort, setBusyShort] = useState('');
|
||||
const [notify, setNotify] = useState<NotifySettingsWire | null>(null);
|
||||
const [coverage, setCoverage] = useState<CoverageRow[]>([]);
|
||||
const [webhookUrl, setWebhookUrl] = useState('');
|
||||
const [webhookHeaders, setWebhookHeaders] = useState('');
|
||||
const [urlTouched, setUrlTouched] = useState(false);
|
||||
const [headersTouched, setHeadersTouched] = useState(false);
|
||||
const [notifySaving, setNotifySaving] = useState(false);
|
||||
const [notifyTesting, setNotifyTesting] = useState(false);
|
||||
const fileRef = useRef<HTMLInputElement>(null);
|
||||
const faviconRef = useRef<HTMLInputElement>(null);
|
||||
const touchRef = useRef<HTMLInputElement>(null);
|
||||
@@ -144,11 +182,71 @@ export default function PublicPageTab() {
|
||||
HttpUtil.get<ThemesPayload>('/panel/api/probe/themes', { silent: true }).then((msg) => {
|
||||
if (!cancelled && msg?.success && msg.obj) applyPayload(msg.obj);
|
||||
});
|
||||
HttpUtil.get<NotifyPayload>('/panel/api/probe/notify', { silent: true }).then((msg) => {
|
||||
if (!cancelled && msg?.success && msg.obj) {
|
||||
setNotify(msg.obj.settings);
|
||||
setCoverage(msg.obj.coverage ?? []);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [applyPayload]);
|
||||
|
||||
async function saveNotify() {
|
||||
if (!notify) return;
|
||||
setNotifySaving(true);
|
||||
try {
|
||||
const body: Record<string, unknown> = {
|
||||
notifyGrace: notify.notifyGrace,
|
||||
notifyTraffic: notify.notifyTraffic,
|
||||
notifyExpiry: notify.notifyExpiry,
|
||||
notifyLogin: notify.notifyLogin,
|
||||
notifyTelegramText: notify.notifyTelegramText,
|
||||
notifyWebhookBody: notify.notifyWebhookBody,
|
||||
};
|
||||
// Secrets ride along only when the field was edited; an
|
||||
// edited-but-empty field clears the stored value server-side.
|
||||
if (urlTouched) body.notifyWebhookUrl = webhookUrl;
|
||||
if (headersTouched) body.notifyWebhookHeaders = webhookHeaders;
|
||||
const msg = await HttpUtil.put<NotifyPayload>('/panel/api/probe/notify', body, {
|
||||
silent: true,
|
||||
...JSON_HEADERS,
|
||||
});
|
||||
if (msg?.success && msg.obj) {
|
||||
setNotify(msg.obj.settings);
|
||||
setCoverage(msg.obj.coverage ?? []);
|
||||
setWebhookUrl('');
|
||||
setWebhookHeaders('');
|
||||
setUrlTouched(false);
|
||||
setHeadersTouched(false);
|
||||
messageApi.success(t('pages.settings.probeThemes.saved'));
|
||||
} else {
|
||||
messageApi.error(msg?.msg || t('pages.settings.probeThemes.saveFailed'));
|
||||
}
|
||||
} finally {
|
||||
setNotifySaving(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function testNotify() {
|
||||
setNotifyTesting(true);
|
||||
try {
|
||||
const msg = await HttpUtil.post<string[]>('/panel/api/probe/notify/test', undefined, {
|
||||
silent: true,
|
||||
});
|
||||
if (msg?.success) {
|
||||
messageApi.success(
|
||||
t('pages.settings.probeNotify.testSent', { channels: (msg.obj ?? []).join('、') }),
|
||||
);
|
||||
} else {
|
||||
messageApi.error(msg?.msg || t('pages.settings.probeThemes.saveFailed'));
|
||||
}
|
||||
} finally {
|
||||
setNotifyTesting(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSettings() {
|
||||
setSaving(true);
|
||||
try {
|
||||
@@ -474,6 +572,226 @@ export default function PublicPageTab() {
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
|
||||
<Typography.Title level={5} style={{ marginTop: 28 }}>
|
||||
{t('pages.settings.probeNotify.notifyTitle')}
|
||||
</Typography.Title>
|
||||
<Typography.Paragraph type="secondary">
|
||||
{t('pages.settings.probeNotify.notifyHint')}
|
||||
</Typography.Paragraph>
|
||||
{notify ? (
|
||||
<>
|
||||
<Row gutter={[16, 12]}>
|
||||
<Col xs={24} md={8}>
|
||||
<div style={{ marginBottom: 4 }}>{t('pages.settings.probeNotify.grace')}</div>
|
||||
<InputNumber
|
||||
min={1}
|
||||
max={30}
|
||||
value={notify.notifyGrace}
|
||||
onChange={onNumber((v) => setNotify({ ...notify, notifyGrace: v }))}
|
||||
/>
|
||||
<div>
|
||||
<Typography.Text type="secondary">
|
||||
{t('pages.settings.probeNotify.graceHint')}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</Col>
|
||||
<Col xs={24} md={8}>
|
||||
<div style={{ marginBottom: 4 }}>{t('pages.settings.probeNotify.trafficPct')}</div>
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={100}
|
||||
value={notify.notifyTraffic}
|
||||
onChange={onNumber((v) => setNotify({ ...notify, notifyTraffic: v }))}
|
||||
/>
|
||||
<div>
|
||||
<Typography.Text type="secondary">
|
||||
{t('pages.settings.probeNotify.trafficHint')}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</Col>
|
||||
<Col xs={24} md={8}>
|
||||
<div style={{ marginBottom: 4 }}>{t('pages.settings.probeNotify.expiryDays')}</div>
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={365}
|
||||
value={notify.notifyExpiry}
|
||||
onChange={onNumber((v) => setNotify({ ...notify, notifyExpiry: v }))}
|
||||
/>
|
||||
<div>
|
||||
<Typography.Text type="secondary">
|
||||
{t('pages.settings.probeNotify.expiryHint')}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</Col>
|
||||
<Col xs={24} md={8}>
|
||||
<div style={{ marginBottom: 4 }}>{t('pages.settings.probeNotify.loginAlert')}</div>
|
||||
<Switch
|
||||
checked={notify.notifyLogin !== 'off'}
|
||||
onChange={(v) => setNotify({ ...notify, notifyLogin: v ? 'on' : 'off' })}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={24} md={8}>
|
||||
<div style={{ marginBottom: 4 }}>
|
||||
{t('pages.settings.probeNotify.telegramChannel')}
|
||||
</div>
|
||||
{notify.telegramConfigured ? (
|
||||
<Tag color="green">{t('pages.settings.probeNotify.configured')}</Tag>
|
||||
) : (
|
||||
<Tag>{t('pages.settings.probeNotify.notConfigured')}</Tag>
|
||||
)}
|
||||
<div>
|
||||
<Typography.Text type="secondary">
|
||||
{t('pages.settings.probeNotify.telegramHint')}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</Col>
|
||||
<Col xs={24} md={8}>
|
||||
<div style={{ marginBottom: 4 }}>
|
||||
{t('pages.settings.probeNotify.webhookChannel')}
|
||||
</div>
|
||||
{notify.webhookConfigured ? (
|
||||
<Tag color="green">{t('pages.settings.probeNotify.configured')}</Tag>
|
||||
) : (
|
||||
<Tag>{t('pages.settings.probeNotify.notConfigured')}</Tag>
|
||||
)}
|
||||
</Col>
|
||||
<Col xs={24}>
|
||||
<div style={{ marginBottom: 4 }}>{t('pages.settings.probeNotify.telegramText')}</div>
|
||||
<Input.TextArea
|
||||
rows={3}
|
||||
value={notify.notifyTelegramText}
|
||||
placeholder={'{{title}}\n{{message}}'}
|
||||
onChange={(e) => setNotify({ ...notify, notifyTelegramText: e.target.value })}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={24} md={12}>
|
||||
<div style={{ marginBottom: 4 }}>{t('pages.settings.probeNotify.webhookUrl')}</div>
|
||||
<Input
|
||||
value={webhookUrl}
|
||||
placeholder={
|
||||
notify.webhookUrlSet ? t('pages.settings.probeNotify.secretSet') : 'https://'
|
||||
}
|
||||
onChange={(e) => {
|
||||
setWebhookUrl(e.target.value);
|
||||
setUrlTouched(true);
|
||||
}}
|
||||
/>
|
||||
{notify.webhookUrlSet && !urlTouched ? (
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setWebhookUrl('');
|
||||
setUrlTouched(true);
|
||||
}}
|
||||
>
|
||||
{t('pages.settings.probeNotify.clearSecret')}
|
||||
</Button>
|
||||
) : null}
|
||||
</Col>
|
||||
<Col xs={24} md={12}>
|
||||
<div style={{ marginBottom: 4 }}>
|
||||
{t('pages.settings.probeNotify.webhookHeaders')}
|
||||
</div>
|
||||
<Input.TextArea
|
||||
rows={2}
|
||||
value={webhookHeaders}
|
||||
placeholder={
|
||||
notify.webhookHeadersSet
|
||||
? t('pages.settings.probeNotify.secretSet')
|
||||
: 'Authorization: Bearer …'
|
||||
}
|
||||
onChange={(e) => {
|
||||
setWebhookHeaders(e.target.value);
|
||||
setHeadersTouched(true);
|
||||
}}
|
||||
/>
|
||||
{notify.webhookHeadersSet && !headersTouched ? (
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setWebhookHeaders('');
|
||||
setHeadersTouched(true);
|
||||
}}
|
||||
>
|
||||
{t('pages.settings.probeNotify.clearSecret')}
|
||||
</Button>
|
||||
) : null}
|
||||
</Col>
|
||||
<Col xs={24}>
|
||||
<div style={{ marginBottom: 4 }}>{t('pages.settings.probeNotify.webhookBody')}</div>
|
||||
<Input.TextArea
|
||||
rows={3}
|
||||
value={notify.notifyWebhookBody}
|
||||
onChange={(e) => setNotify({ ...notify, notifyWebhookBody: e.target.value })}
|
||||
/>
|
||||
<div>
|
||||
<Typography.Text type="secondary">
|
||||
{t('pages.settings.probeNotify.templateHint')}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<Space style={{ marginTop: 12 }}>
|
||||
<Button type="primary" loading={notifySaving} onClick={saveNotify}>
|
||||
{t('save')}
|
||||
</Button>
|
||||
<Button loading={notifyTesting} onClick={testNotify}>
|
||||
{t('pages.settings.probeNotify.testSend')}
|
||||
</Button>
|
||||
</Space>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
<Typography.Title level={5} style={{ marginTop: 28 }}>
|
||||
{t('pages.settings.probeNotify.retireTitle')}
|
||||
</Typography.Title>
|
||||
<Typography.Paragraph type="secondary">
|
||||
{t('pages.settings.probeNotify.retireHint')}
|
||||
</Typography.Paragraph>
|
||||
<Space direction="vertical">
|
||||
<span>
|
||||
{t('pages.settings.probeNotify.retirePublicPage')}:
|
||||
{settings.publicPage ? (
|
||||
<Tag color="green">{t('pages.settings.probeNotify.configured')}</Tag>
|
||||
) : (
|
||||
<Tag color="orange">{t('pages.settings.probeNotify.retirePublicPageOff')}</Tag>
|
||||
)}
|
||||
</span>
|
||||
{coverage.map((row) => (
|
||||
<span key={row.name}>
|
||||
{row.name}:
|
||||
{row.hasProbe ? (
|
||||
<Tag color="green">{t('pages.settings.probeNotify.retireHasProbe')}</Tag>
|
||||
) : (
|
||||
<Tag color="red">{t('pages.settings.probeNotify.retireNoProbe')}</Tag>
|
||||
)}
|
||||
{row.online ? (
|
||||
<Tag color="green">{t('pages.settings.probeNotify.retireOnline')}</Tag>
|
||||
) : (
|
||||
<Tag>{t('pages.settings.probeNotify.retireOffline')}</Tag>
|
||||
)}
|
||||
{row.probeAt > 0 ? (
|
||||
<Typography.Text type="secondary">
|
||||
{t('pages.settings.probeNotify.retireProbeAt', {
|
||||
time: new Date(row.probeAt * 1000).toLocaleString(),
|
||||
})}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
</span>
|
||||
))}
|
||||
{coverage.length > 0 && coverage.every((row) => row.hasProbe) ? (
|
||||
<Typography.Text type="success">
|
||||
{t('pages.settings.probeNotify.retireAllReady')}
|
||||
</Typography.Text>
|
||||
) : (
|
||||
<Typography.Text type="warning">
|
||||
{t('pages.settings.probeNotify.retireNotReady')}
|
||||
</Typography.Text>
|
||||
)}
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1019,6 +1019,42 @@
|
||||
"alreadyLatest": "Already the latest version",
|
||||
"config": "Theme settings"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "Notifications",
|
||||
"notifyHint": "Offline, traffic and expiry alerts, delivered to the channels below (Telegram reuses the panel bot settings).",
|
||||
"grace": "Offline grace (minutes)",
|
||||
"graceHint": "An alert fires only after reporting has stopped for this long; a recovery inside the grace stays silent.",
|
||||
"trafficPct": "Traffic alert threshold (%)",
|
||||
"trafficHint": "Alerts once at this percentage and once more at 100%, once per billing period each; 0 disables traffic alerts.",
|
||||
"expiryDays": "Expiry alert (days)",
|
||||
"expiryHint": "A daily digest of nodes expiring within this many days; online nodes roll over automatically by billing cycle; 0 disables.",
|
||||
"loginAlert": "Panel sign-in alerts",
|
||||
"telegramChannel": "Telegram channel",
|
||||
"telegramHint": "The token and chat IDs are configured in the Telegram bot settings.",
|
||||
"webhookChannel": "Webhook channel",
|
||||
"configured": "Configured",
|
||||
"notConfigured": "Not configured",
|
||||
"telegramText": "Telegram text template",
|
||||
"webhookUrl": "Webhook URL",
|
||||
"webhookHeaders": "Headers (one Name: value per line)",
|
||||
"webhookBody": "Body template (JSON)",
|
||||
"secretSet": "Set (leave empty to keep)",
|
||||
"clearSecret": "Clear",
|
||||
"templateHint": "Placeholders: {{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "Send a test alert",
|
||||
"testSent": "Test alert sent: {{channels}}",
|
||||
"retireTitle": "cf-probe retirement checklist",
|
||||
"retireHint": "Only once every node is served by the panel may the old public page be switched off, in the order given in the deployment notes.",
|
||||
"retirePublicPage": "Public page",
|
||||
"retirePublicPageOff": "Off (enable it above)",
|
||||
"retireHasProbe": "Probe reporting",
|
||||
"retireNoProbe": "No probe data",
|
||||
"retireOnline": "Online",
|
||||
"retireOffline": "Offline",
|
||||
"retireProbeAt": "Last report {{time}}",
|
||||
"retireAllReady": "Every node is served by the panel; cf-probe can be retired in the documented order.",
|
||||
"retireNotReady": "Some nodes have no probe data yet; do not take cf-probe down."
|
||||
},
|
||||
"defaultTag": "افتراضي",
|
||||
"title": "إعدادات البانل",
|
||||
"save": "حفظ",
|
||||
|
||||
@@ -1159,6 +1159,42 @@
|
||||
"alreadyLatest": "Already the latest version",
|
||||
"config": "Theme settings"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "Notifications",
|
||||
"notifyHint": "Offline, traffic and expiry alerts, delivered to the channels below (Telegram reuses the panel bot settings).",
|
||||
"grace": "Offline grace (minutes)",
|
||||
"graceHint": "An alert fires only after reporting has stopped for this long; a recovery inside the grace stays silent.",
|
||||
"trafficPct": "Traffic alert threshold (%)",
|
||||
"trafficHint": "Alerts once at this percentage and once more at 100%, once per billing period each; 0 disables traffic alerts.",
|
||||
"expiryDays": "Expiry alert (days)",
|
||||
"expiryHint": "A daily digest of nodes expiring within this many days; online nodes roll over automatically by billing cycle; 0 disables.",
|
||||
"loginAlert": "Panel sign-in alerts",
|
||||
"telegramChannel": "Telegram channel",
|
||||
"telegramHint": "The token and chat IDs are configured in the Telegram bot settings.",
|
||||
"webhookChannel": "Webhook channel",
|
||||
"configured": "Configured",
|
||||
"notConfigured": "Not configured",
|
||||
"telegramText": "Telegram text template",
|
||||
"webhookUrl": "Webhook URL",
|
||||
"webhookHeaders": "Headers (one Name: value per line)",
|
||||
"webhookBody": "Body template (JSON)",
|
||||
"secretSet": "Set (leave empty to keep)",
|
||||
"clearSecret": "Clear",
|
||||
"templateHint": "Placeholders: {{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "Send a test alert",
|
||||
"testSent": "Test alert sent: {{channels}}",
|
||||
"retireTitle": "cf-probe retirement checklist",
|
||||
"retireHint": "Only once every node is served by the panel may the old public page be switched off, in the order given in the deployment notes.",
|
||||
"retirePublicPage": "Public page",
|
||||
"retirePublicPageOff": "Off (enable it above)",
|
||||
"retireHasProbe": "Probe reporting",
|
||||
"retireNoProbe": "No probe data",
|
||||
"retireOnline": "Online",
|
||||
"retireOffline": "Offline",
|
||||
"retireProbeAt": "Last report {{time}}",
|
||||
"retireAllReady": "Every node is served by the panel; cf-probe can be retired in the documented order.",
|
||||
"retireNotReady": "Some nodes have no probe data yet; do not take cf-probe down."
|
||||
},
|
||||
"defaultTag": "Default",
|
||||
"title": "Panel Settings",
|
||||
"save": "Save",
|
||||
|
||||
@@ -1019,6 +1019,42 @@
|
||||
"alreadyLatest": "Already the latest version",
|
||||
"config": "Theme settings"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "Notifications",
|
||||
"notifyHint": "Offline, traffic and expiry alerts, delivered to the channels below (Telegram reuses the panel bot settings).",
|
||||
"grace": "Offline grace (minutes)",
|
||||
"graceHint": "An alert fires only after reporting has stopped for this long; a recovery inside the grace stays silent.",
|
||||
"trafficPct": "Traffic alert threshold (%)",
|
||||
"trafficHint": "Alerts once at this percentage and once more at 100%, once per billing period each; 0 disables traffic alerts.",
|
||||
"expiryDays": "Expiry alert (days)",
|
||||
"expiryHint": "A daily digest of nodes expiring within this many days; online nodes roll over automatically by billing cycle; 0 disables.",
|
||||
"loginAlert": "Panel sign-in alerts",
|
||||
"telegramChannel": "Telegram channel",
|
||||
"telegramHint": "The token and chat IDs are configured in the Telegram bot settings.",
|
||||
"webhookChannel": "Webhook channel",
|
||||
"configured": "Configured",
|
||||
"notConfigured": "Not configured",
|
||||
"telegramText": "Telegram text template",
|
||||
"webhookUrl": "Webhook URL",
|
||||
"webhookHeaders": "Headers (one Name: value per line)",
|
||||
"webhookBody": "Body template (JSON)",
|
||||
"secretSet": "Set (leave empty to keep)",
|
||||
"clearSecret": "Clear",
|
||||
"templateHint": "Placeholders: {{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "Send a test alert",
|
||||
"testSent": "Test alert sent: {{channels}}",
|
||||
"retireTitle": "cf-probe retirement checklist",
|
||||
"retireHint": "Only once every node is served by the panel may the old public page be switched off, in the order given in the deployment notes.",
|
||||
"retirePublicPage": "Public page",
|
||||
"retirePublicPageOff": "Off (enable it above)",
|
||||
"retireHasProbe": "Probe reporting",
|
||||
"retireNoProbe": "No probe data",
|
||||
"retireOnline": "Online",
|
||||
"retireOffline": "Offline",
|
||||
"retireProbeAt": "Last report {{time}}",
|
||||
"retireAllReady": "Every node is served by the panel; cf-probe can be retired in the documented order.",
|
||||
"retireNotReady": "Some nodes have no probe data yet; do not take cf-probe down."
|
||||
},
|
||||
"defaultTag": "Predeterminado",
|
||||
"title": "Configuraciones",
|
||||
"save": "Guardar",
|
||||
|
||||
@@ -1019,6 +1019,42 @@
|
||||
"alreadyLatest": "Already the latest version",
|
||||
"config": "Theme settings"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "Notifications",
|
||||
"notifyHint": "Offline, traffic and expiry alerts, delivered to the channels below (Telegram reuses the panel bot settings).",
|
||||
"grace": "Offline grace (minutes)",
|
||||
"graceHint": "An alert fires only after reporting has stopped for this long; a recovery inside the grace stays silent.",
|
||||
"trafficPct": "Traffic alert threshold (%)",
|
||||
"trafficHint": "Alerts once at this percentage and once more at 100%, once per billing period each; 0 disables traffic alerts.",
|
||||
"expiryDays": "Expiry alert (days)",
|
||||
"expiryHint": "A daily digest of nodes expiring within this many days; online nodes roll over automatically by billing cycle; 0 disables.",
|
||||
"loginAlert": "Panel sign-in alerts",
|
||||
"telegramChannel": "Telegram channel",
|
||||
"telegramHint": "The token and chat IDs are configured in the Telegram bot settings.",
|
||||
"webhookChannel": "Webhook channel",
|
||||
"configured": "Configured",
|
||||
"notConfigured": "Not configured",
|
||||
"telegramText": "Telegram text template",
|
||||
"webhookUrl": "Webhook URL",
|
||||
"webhookHeaders": "Headers (one Name: value per line)",
|
||||
"webhookBody": "Body template (JSON)",
|
||||
"secretSet": "Set (leave empty to keep)",
|
||||
"clearSecret": "Clear",
|
||||
"templateHint": "Placeholders: {{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "Send a test alert",
|
||||
"testSent": "Test alert sent: {{channels}}",
|
||||
"retireTitle": "cf-probe retirement checklist",
|
||||
"retireHint": "Only once every node is served by the panel may the old public page be switched off, in the order given in the deployment notes.",
|
||||
"retirePublicPage": "Public page",
|
||||
"retirePublicPageOff": "Off (enable it above)",
|
||||
"retireHasProbe": "Probe reporting",
|
||||
"retireNoProbe": "No probe data",
|
||||
"retireOnline": "Online",
|
||||
"retireOffline": "Offline",
|
||||
"retireProbeAt": "Last report {{time}}",
|
||||
"retireAllReady": "Every node is served by the panel; cf-probe can be retired in the documented order.",
|
||||
"retireNotReady": "Some nodes have no probe data yet; do not take cf-probe down."
|
||||
},
|
||||
"defaultTag": "پیشفرض",
|
||||
"title": "تنظیمات پنل",
|
||||
"save": "ذخیره",
|
||||
|
||||
@@ -1019,6 +1019,42 @@
|
||||
"alreadyLatest": "Already the latest version",
|
||||
"config": "Theme settings"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "Notifications",
|
||||
"notifyHint": "Offline, traffic and expiry alerts, delivered to the channels below (Telegram reuses the panel bot settings).",
|
||||
"grace": "Offline grace (minutes)",
|
||||
"graceHint": "An alert fires only after reporting has stopped for this long; a recovery inside the grace stays silent.",
|
||||
"trafficPct": "Traffic alert threshold (%)",
|
||||
"trafficHint": "Alerts once at this percentage and once more at 100%, once per billing period each; 0 disables traffic alerts.",
|
||||
"expiryDays": "Expiry alert (days)",
|
||||
"expiryHint": "A daily digest of nodes expiring within this many days; online nodes roll over automatically by billing cycle; 0 disables.",
|
||||
"loginAlert": "Panel sign-in alerts",
|
||||
"telegramChannel": "Telegram channel",
|
||||
"telegramHint": "The token and chat IDs are configured in the Telegram bot settings.",
|
||||
"webhookChannel": "Webhook channel",
|
||||
"configured": "Configured",
|
||||
"notConfigured": "Not configured",
|
||||
"telegramText": "Telegram text template",
|
||||
"webhookUrl": "Webhook URL",
|
||||
"webhookHeaders": "Headers (one Name: value per line)",
|
||||
"webhookBody": "Body template (JSON)",
|
||||
"secretSet": "Set (leave empty to keep)",
|
||||
"clearSecret": "Clear",
|
||||
"templateHint": "Placeholders: {{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "Send a test alert",
|
||||
"testSent": "Test alert sent: {{channels}}",
|
||||
"retireTitle": "cf-probe retirement checklist",
|
||||
"retireHint": "Only once every node is served by the panel may the old public page be switched off, in the order given in the deployment notes.",
|
||||
"retirePublicPage": "Public page",
|
||||
"retirePublicPageOff": "Off (enable it above)",
|
||||
"retireHasProbe": "Probe reporting",
|
||||
"retireNoProbe": "No probe data",
|
||||
"retireOnline": "Online",
|
||||
"retireOffline": "Offline",
|
||||
"retireProbeAt": "Last report {{time}}",
|
||||
"retireAllReady": "Every node is served by the panel; cf-probe can be retired in the documented order.",
|
||||
"retireNotReady": "Some nodes have no probe data yet; do not take cf-probe down."
|
||||
},
|
||||
"defaultTag": "Bawaan",
|
||||
"title": "Pengaturan Panel",
|
||||
"save": "Simpan",
|
||||
|
||||
@@ -1019,6 +1019,42 @@
|
||||
"alreadyLatest": "Already the latest version",
|
||||
"config": "Theme settings"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "Notifications",
|
||||
"notifyHint": "Offline, traffic and expiry alerts, delivered to the channels below (Telegram reuses the panel bot settings).",
|
||||
"grace": "Offline grace (minutes)",
|
||||
"graceHint": "An alert fires only after reporting has stopped for this long; a recovery inside the grace stays silent.",
|
||||
"trafficPct": "Traffic alert threshold (%)",
|
||||
"trafficHint": "Alerts once at this percentage and once more at 100%, once per billing period each; 0 disables traffic alerts.",
|
||||
"expiryDays": "Expiry alert (days)",
|
||||
"expiryHint": "A daily digest of nodes expiring within this many days; online nodes roll over automatically by billing cycle; 0 disables.",
|
||||
"loginAlert": "Panel sign-in alerts",
|
||||
"telegramChannel": "Telegram channel",
|
||||
"telegramHint": "The token and chat IDs are configured in the Telegram bot settings.",
|
||||
"webhookChannel": "Webhook channel",
|
||||
"configured": "Configured",
|
||||
"notConfigured": "Not configured",
|
||||
"telegramText": "Telegram text template",
|
||||
"webhookUrl": "Webhook URL",
|
||||
"webhookHeaders": "Headers (one Name: value per line)",
|
||||
"webhookBody": "Body template (JSON)",
|
||||
"secretSet": "Set (leave empty to keep)",
|
||||
"clearSecret": "Clear",
|
||||
"templateHint": "Placeholders: {{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "Send a test alert",
|
||||
"testSent": "Test alert sent: {{channels}}",
|
||||
"retireTitle": "cf-probe retirement checklist",
|
||||
"retireHint": "Only once every node is served by the panel may the old public page be switched off, in the order given in the deployment notes.",
|
||||
"retirePublicPage": "Public page",
|
||||
"retirePublicPageOff": "Off (enable it above)",
|
||||
"retireHasProbe": "Probe reporting",
|
||||
"retireNoProbe": "No probe data",
|
||||
"retireOnline": "Online",
|
||||
"retireOffline": "Offline",
|
||||
"retireProbeAt": "Last report {{time}}",
|
||||
"retireAllReady": "Every node is served by the panel; cf-probe can be retired in the documented order.",
|
||||
"retireNotReady": "Some nodes have no probe data yet; do not take cf-probe down."
|
||||
},
|
||||
"defaultTag": "デフォルト",
|
||||
"title": "パネル設定",
|
||||
"save": "保存",
|
||||
|
||||
@@ -1019,6 +1019,42 @@
|
||||
"alreadyLatest": "Already the latest version",
|
||||
"config": "Theme settings"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "Notifications",
|
||||
"notifyHint": "Offline, traffic and expiry alerts, delivered to the channels below (Telegram reuses the panel bot settings).",
|
||||
"grace": "Offline grace (minutes)",
|
||||
"graceHint": "An alert fires only after reporting has stopped for this long; a recovery inside the grace stays silent.",
|
||||
"trafficPct": "Traffic alert threshold (%)",
|
||||
"trafficHint": "Alerts once at this percentage and once more at 100%, once per billing period each; 0 disables traffic alerts.",
|
||||
"expiryDays": "Expiry alert (days)",
|
||||
"expiryHint": "A daily digest of nodes expiring within this many days; online nodes roll over automatically by billing cycle; 0 disables.",
|
||||
"loginAlert": "Panel sign-in alerts",
|
||||
"telegramChannel": "Telegram channel",
|
||||
"telegramHint": "The token and chat IDs are configured in the Telegram bot settings.",
|
||||
"webhookChannel": "Webhook channel",
|
||||
"configured": "Configured",
|
||||
"notConfigured": "Not configured",
|
||||
"telegramText": "Telegram text template",
|
||||
"webhookUrl": "Webhook URL",
|
||||
"webhookHeaders": "Headers (one Name: value per line)",
|
||||
"webhookBody": "Body template (JSON)",
|
||||
"secretSet": "Set (leave empty to keep)",
|
||||
"clearSecret": "Clear",
|
||||
"templateHint": "Placeholders: {{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "Send a test alert",
|
||||
"testSent": "Test alert sent: {{channels}}",
|
||||
"retireTitle": "cf-probe retirement checklist",
|
||||
"retireHint": "Only once every node is served by the panel may the old public page be switched off, in the order given in the deployment notes.",
|
||||
"retirePublicPage": "Public page",
|
||||
"retirePublicPageOff": "Off (enable it above)",
|
||||
"retireHasProbe": "Probe reporting",
|
||||
"retireNoProbe": "No probe data",
|
||||
"retireOnline": "Online",
|
||||
"retireOffline": "Offline",
|
||||
"retireProbeAt": "Last report {{time}}",
|
||||
"retireAllReady": "Every node is served by the panel; cf-probe can be retired in the documented order.",
|
||||
"retireNotReady": "Some nodes have no probe data yet; do not take cf-probe down."
|
||||
},
|
||||
"defaultTag": "Padrão",
|
||||
"title": "Configurações do Painel",
|
||||
"save": "Salvar",
|
||||
|
||||
@@ -1019,6 +1019,42 @@
|
||||
"alreadyLatest": "Already the latest version",
|
||||
"config": "Theme settings"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "Notifications",
|
||||
"notifyHint": "Offline, traffic and expiry alerts, delivered to the channels below (Telegram reuses the panel bot settings).",
|
||||
"grace": "Offline grace (minutes)",
|
||||
"graceHint": "An alert fires only after reporting has stopped for this long; a recovery inside the grace stays silent.",
|
||||
"trafficPct": "Traffic alert threshold (%)",
|
||||
"trafficHint": "Alerts once at this percentage and once more at 100%, once per billing period each; 0 disables traffic alerts.",
|
||||
"expiryDays": "Expiry alert (days)",
|
||||
"expiryHint": "A daily digest of nodes expiring within this many days; online nodes roll over automatically by billing cycle; 0 disables.",
|
||||
"loginAlert": "Panel sign-in alerts",
|
||||
"telegramChannel": "Telegram channel",
|
||||
"telegramHint": "The token and chat IDs are configured in the Telegram bot settings.",
|
||||
"webhookChannel": "Webhook channel",
|
||||
"configured": "Configured",
|
||||
"notConfigured": "Not configured",
|
||||
"telegramText": "Telegram text template",
|
||||
"webhookUrl": "Webhook URL",
|
||||
"webhookHeaders": "Headers (one Name: value per line)",
|
||||
"webhookBody": "Body template (JSON)",
|
||||
"secretSet": "Set (leave empty to keep)",
|
||||
"clearSecret": "Clear",
|
||||
"templateHint": "Placeholders: {{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "Send a test alert",
|
||||
"testSent": "Test alert sent: {{channels}}",
|
||||
"retireTitle": "cf-probe retirement checklist",
|
||||
"retireHint": "Only once every node is served by the panel may the old public page be switched off, in the order given in the deployment notes.",
|
||||
"retirePublicPage": "Public page",
|
||||
"retirePublicPageOff": "Off (enable it above)",
|
||||
"retireHasProbe": "Probe reporting",
|
||||
"retireNoProbe": "No probe data",
|
||||
"retireOnline": "Online",
|
||||
"retireOffline": "Offline",
|
||||
"retireProbeAt": "Last report {{time}}",
|
||||
"retireAllReady": "Every node is served by the panel; cf-probe can be retired in the documented order.",
|
||||
"retireNotReady": "Some nodes have no probe data yet; do not take cf-probe down."
|
||||
},
|
||||
"defaultTag": "По умолчанию",
|
||||
"title": "Настройки",
|
||||
"save": "Сохранить",
|
||||
|
||||
@@ -1019,6 +1019,42 @@
|
||||
"alreadyLatest": "Already the latest version",
|
||||
"config": "Theme settings"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "Notifications",
|
||||
"notifyHint": "Offline, traffic and expiry alerts, delivered to the channels below (Telegram reuses the panel bot settings).",
|
||||
"grace": "Offline grace (minutes)",
|
||||
"graceHint": "An alert fires only after reporting has stopped for this long; a recovery inside the grace stays silent.",
|
||||
"trafficPct": "Traffic alert threshold (%)",
|
||||
"trafficHint": "Alerts once at this percentage and once more at 100%, once per billing period each; 0 disables traffic alerts.",
|
||||
"expiryDays": "Expiry alert (days)",
|
||||
"expiryHint": "A daily digest of nodes expiring within this many days; online nodes roll over automatically by billing cycle; 0 disables.",
|
||||
"loginAlert": "Panel sign-in alerts",
|
||||
"telegramChannel": "Telegram channel",
|
||||
"telegramHint": "The token and chat IDs are configured in the Telegram bot settings.",
|
||||
"webhookChannel": "Webhook channel",
|
||||
"configured": "Configured",
|
||||
"notConfigured": "Not configured",
|
||||
"telegramText": "Telegram text template",
|
||||
"webhookUrl": "Webhook URL",
|
||||
"webhookHeaders": "Headers (one Name: value per line)",
|
||||
"webhookBody": "Body template (JSON)",
|
||||
"secretSet": "Set (leave empty to keep)",
|
||||
"clearSecret": "Clear",
|
||||
"templateHint": "Placeholders: {{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "Send a test alert",
|
||||
"testSent": "Test alert sent: {{channels}}",
|
||||
"retireTitle": "cf-probe retirement checklist",
|
||||
"retireHint": "Only once every node is served by the panel may the old public page be switched off, in the order given in the deployment notes.",
|
||||
"retirePublicPage": "Public page",
|
||||
"retirePublicPageOff": "Off (enable it above)",
|
||||
"retireHasProbe": "Probe reporting",
|
||||
"retireNoProbe": "No probe data",
|
||||
"retireOnline": "Online",
|
||||
"retireOffline": "Offline",
|
||||
"retireProbeAt": "Last report {{time}}",
|
||||
"retireAllReady": "Every node is served by the panel; cf-probe can be retired in the documented order.",
|
||||
"retireNotReady": "Some nodes have no probe data yet; do not take cf-probe down."
|
||||
},
|
||||
"defaultTag": "Varsayılan",
|
||||
"title": "Panel Ayarları",
|
||||
"save": "Kaydet",
|
||||
|
||||
@@ -1019,6 +1019,42 @@
|
||||
"alreadyLatest": "Already the latest version",
|
||||
"config": "Theme settings"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "Notifications",
|
||||
"notifyHint": "Offline, traffic and expiry alerts, delivered to the channels below (Telegram reuses the panel bot settings).",
|
||||
"grace": "Offline grace (minutes)",
|
||||
"graceHint": "An alert fires only after reporting has stopped for this long; a recovery inside the grace stays silent.",
|
||||
"trafficPct": "Traffic alert threshold (%)",
|
||||
"trafficHint": "Alerts once at this percentage and once more at 100%, once per billing period each; 0 disables traffic alerts.",
|
||||
"expiryDays": "Expiry alert (days)",
|
||||
"expiryHint": "A daily digest of nodes expiring within this many days; online nodes roll over automatically by billing cycle; 0 disables.",
|
||||
"loginAlert": "Panel sign-in alerts",
|
||||
"telegramChannel": "Telegram channel",
|
||||
"telegramHint": "The token and chat IDs are configured in the Telegram bot settings.",
|
||||
"webhookChannel": "Webhook channel",
|
||||
"configured": "Configured",
|
||||
"notConfigured": "Not configured",
|
||||
"telegramText": "Telegram text template",
|
||||
"webhookUrl": "Webhook URL",
|
||||
"webhookHeaders": "Headers (one Name: value per line)",
|
||||
"webhookBody": "Body template (JSON)",
|
||||
"secretSet": "Set (leave empty to keep)",
|
||||
"clearSecret": "Clear",
|
||||
"templateHint": "Placeholders: {{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "Send a test alert",
|
||||
"testSent": "Test alert sent: {{channels}}",
|
||||
"retireTitle": "cf-probe retirement checklist",
|
||||
"retireHint": "Only once every node is served by the panel may the old public page be switched off, in the order given in the deployment notes.",
|
||||
"retirePublicPage": "Public page",
|
||||
"retirePublicPageOff": "Off (enable it above)",
|
||||
"retireHasProbe": "Probe reporting",
|
||||
"retireNoProbe": "No probe data",
|
||||
"retireOnline": "Online",
|
||||
"retireOffline": "Offline",
|
||||
"retireProbeAt": "Last report {{time}}",
|
||||
"retireAllReady": "Every node is served by the panel; cf-probe can be retired in the documented order.",
|
||||
"retireNotReady": "Some nodes have no probe data yet; do not take cf-probe down."
|
||||
},
|
||||
"defaultTag": "Типово",
|
||||
"title": "Параметри панелі",
|
||||
"save": "Зберегти",
|
||||
|
||||
@@ -1019,6 +1019,42 @@
|
||||
"alreadyLatest": "Already the latest version",
|
||||
"config": "Theme settings"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "Notifications",
|
||||
"notifyHint": "Offline, traffic and expiry alerts, delivered to the channels below (Telegram reuses the panel bot settings).",
|
||||
"grace": "Offline grace (minutes)",
|
||||
"graceHint": "An alert fires only after reporting has stopped for this long; a recovery inside the grace stays silent.",
|
||||
"trafficPct": "Traffic alert threshold (%)",
|
||||
"trafficHint": "Alerts once at this percentage and once more at 100%, once per billing period each; 0 disables traffic alerts.",
|
||||
"expiryDays": "Expiry alert (days)",
|
||||
"expiryHint": "A daily digest of nodes expiring within this many days; online nodes roll over automatically by billing cycle; 0 disables.",
|
||||
"loginAlert": "Panel sign-in alerts",
|
||||
"telegramChannel": "Telegram channel",
|
||||
"telegramHint": "The token and chat IDs are configured in the Telegram bot settings.",
|
||||
"webhookChannel": "Webhook channel",
|
||||
"configured": "Configured",
|
||||
"notConfigured": "Not configured",
|
||||
"telegramText": "Telegram text template",
|
||||
"webhookUrl": "Webhook URL",
|
||||
"webhookHeaders": "Headers (one Name: value per line)",
|
||||
"webhookBody": "Body template (JSON)",
|
||||
"secretSet": "Set (leave empty to keep)",
|
||||
"clearSecret": "Clear",
|
||||
"templateHint": "Placeholders: {{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "Send a test alert",
|
||||
"testSent": "Test alert sent: {{channels}}",
|
||||
"retireTitle": "cf-probe retirement checklist",
|
||||
"retireHint": "Only once every node is served by the panel may the old public page be switched off, in the order given in the deployment notes.",
|
||||
"retirePublicPage": "Public page",
|
||||
"retirePublicPageOff": "Off (enable it above)",
|
||||
"retireHasProbe": "Probe reporting",
|
||||
"retireNoProbe": "No probe data",
|
||||
"retireOnline": "Online",
|
||||
"retireOffline": "Offline",
|
||||
"retireProbeAt": "Last report {{time}}",
|
||||
"retireAllReady": "Every node is served by the panel; cf-probe can be retired in the documented order.",
|
||||
"retireNotReady": "Some nodes have no probe data yet; do not take cf-probe down."
|
||||
},
|
||||
"defaultTag": "Mặc định",
|
||||
"title": "Cài đặt",
|
||||
"save": "Lưu",
|
||||
|
||||
@@ -1041,6 +1041,42 @@
|
||||
"alreadyLatest": "已是最新版本",
|
||||
"config": "主题设置"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "通知",
|
||||
"notifyHint": "节点掉线、流量超限与到期提醒,发送到下方配置的渠道(Telegram 复用面板机器人设置)。",
|
||||
"grace": "离线宽限(分钟)",
|
||||
"graceHint": "停止上报超过该时长才报离线;宽限内恢复不报警。",
|
||||
"trafficPct": "流量提醒阈值(%)",
|
||||
"trafficHint": "达到该百分比提醒一次、达到 100% 再提醒一次,每个计费周期内各一次;0 = 关闭流量提醒。",
|
||||
"expiryDays": "到期提醒(天)",
|
||||
"expiryHint": "每天汇总一次将在该天数内到期的节点;在线节点到期后按计费周期自动续期;0 = 关闭。",
|
||||
"loginAlert": "面板登录提醒",
|
||||
"telegramChannel": "Telegram 渠道",
|
||||
"telegramHint": "令牌与会话 ID 在 Telegram 机器人设置中配置。",
|
||||
"webhookChannel": "Webhook 渠道",
|
||||
"configured": "已配置",
|
||||
"notConfigured": "未配置",
|
||||
"telegramText": "Telegram 文案模板",
|
||||
"webhookUrl": "Webhook 地址",
|
||||
"webhookHeaders": "请求头(每行 名: 值)",
|
||||
"webhookBody": "请求体模板(JSON)",
|
||||
"secretSet": "已设置(留空不改)",
|
||||
"clearSecret": "清除",
|
||||
"templateHint": "可用占位符:{{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "发送测试通知",
|
||||
"testSent": "测试通知已发送:{{channels}}",
|
||||
"retireTitle": "cf-probe 退役前提",
|
||||
"retireHint": "全部节点都由面板供数后,旧公开页才可按部署文档顺序切换/下线。",
|
||||
"retirePublicPage": "公开页",
|
||||
"retirePublicPageOff": "未开启(在上方开启)",
|
||||
"retireHasProbe": "探针已上报",
|
||||
"retireNoProbe": "探针未上报",
|
||||
"retireOnline": "在线",
|
||||
"retireOffline": "离线",
|
||||
"retireProbeAt": "最近上报 {{time}}",
|
||||
"retireAllReady": "全部节点已由主控供数,可按文档顺序退役 cf-probe。",
|
||||
"retireNotReady": "仍有节点未供数,先不要下线 cf-probe。"
|
||||
},
|
||||
"defaultTag": "默认",
|
||||
"title": "面板设置",
|
||||
"save": "保存",
|
||||
|
||||
@@ -1019,6 +1019,42 @@
|
||||
"alreadyLatest": "Already the latest version",
|
||||
"config": "Theme settings"
|
||||
},
|
||||
"probeNotify": {
|
||||
"notifyTitle": "Notifications",
|
||||
"notifyHint": "Offline, traffic and expiry alerts, delivered to the channels below (Telegram reuses the panel bot settings).",
|
||||
"grace": "Offline grace (minutes)",
|
||||
"graceHint": "An alert fires only after reporting has stopped for this long; a recovery inside the grace stays silent.",
|
||||
"trafficPct": "Traffic alert threshold (%)",
|
||||
"trafficHint": "Alerts once at this percentage and once more at 100%, once per billing period each; 0 disables traffic alerts.",
|
||||
"expiryDays": "Expiry alert (days)",
|
||||
"expiryHint": "A daily digest of nodes expiring within this many days; online nodes roll over automatically by billing cycle; 0 disables.",
|
||||
"loginAlert": "Panel sign-in alerts",
|
||||
"telegramChannel": "Telegram channel",
|
||||
"telegramHint": "The token and chat IDs are configured in the Telegram bot settings.",
|
||||
"webhookChannel": "Webhook channel",
|
||||
"configured": "Configured",
|
||||
"notConfigured": "Not configured",
|
||||
"telegramText": "Telegram text template",
|
||||
"webhookUrl": "Webhook URL",
|
||||
"webhookHeaders": "Headers (one Name: value per line)",
|
||||
"webhookBody": "Body template (JSON)",
|
||||
"secretSet": "Set (leave empty to keep)",
|
||||
"clearSecret": "Clear",
|
||||
"templateHint": "Placeholders: {{title}} {{message}} {{node}} {{event}} {{time}} {{count}} {{site}}",
|
||||
"testSend": "Send a test alert",
|
||||
"testSent": "Test alert sent: {{channels}}",
|
||||
"retireTitle": "cf-probe retirement checklist",
|
||||
"retireHint": "Only once every node is served by the panel may the old public page be switched off, in the order given in the deployment notes.",
|
||||
"retirePublicPage": "Public page",
|
||||
"retirePublicPageOff": "Off (enable it above)",
|
||||
"retireHasProbe": "Probe reporting",
|
||||
"retireNoProbe": "No probe data",
|
||||
"retireOnline": "Online",
|
||||
"retireOffline": "Offline",
|
||||
"retireProbeAt": "Last report {{time}}",
|
||||
"retireAllReady": "Every node is served by the panel; cf-probe can be retired in the documented order.",
|
||||
"retireNotReady": "Some nodes have no probe data yet; do not take cf-probe down."
|
||||
},
|
||||
"defaultTag": "預設",
|
||||
"title": "面板設定",
|
||||
"save": "儲存",
|
||||
|
||||
Reference in New Issue
Block a user