mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-20 01:50:58 +00:00
feat(i18n): translate the log levels, access events and calendar labels (#6226)
* feat(i18n): translate the log levels, access events and calendar labels The log-level selector, the access-log event tags, the Sub Formats sidebar entry and the calendar choices were hardcoded English, so a fully translated locale still showed them in English on core screens. Add eleven keys across the 13 locales and reference them. Russian and Ukrainian are translated; the remaining locales carry the English string, the same convention the existing files already use for untranslated entries. Two module-level constants had to move: the calendar list and the access-event map were built outside the component, where t is not in scope. The event map now stores keys and resolves them at render. * fix(i18n): keep the log export language-independent and fit the translations Three follow-ups from review. The downloaded x-ui.log had started carrying the translated event text, so its contents depended on the panel language and the Russian value for PROXY contains a space in a field format whose other values are single tokens. The export keeps DIRECT/BLOCKED/PROXY; only the on-screen tag is translated. The log-level select had a fixed 95px width sized for "Warning", which clips "Предупреждение"; it now grows with its content. The three access filters stayed English while the tags they filter became translated, so they use the same keys. --------- Co-authored-by: n0ctal <n0ctal@users.noreply.github.com>
This commit is contained in:
@@ -7,8 +7,8 @@
|
||||
* - Please do NOT modify this file.
|
||||
*/
|
||||
|
||||
const PACKAGE_VERSION = '2.14.7'
|
||||
const INTEGRITY_CHECKSUM = '4db4a41e972cec1b64cc569c66952d82'
|
||||
const PACKAGE_VERSION = '2.15.0'
|
||||
const INTEGRITY_CHECKSUM = '03cb67ac84128e63d7cd722a6e5b7f1e'
|
||||
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
|
||||
const activeClientIds = new Set()
|
||||
|
||||
@@ -137,8 +137,18 @@ async function handleRequest(event, requestId, requestInterceptedAt) {
|
||||
if (client && activeClientIds.has(client.id)) {
|
||||
const serializedRequest = await serializeRequest(requestCloneForEvents)
|
||||
|
||||
// Omit the body of server-sent event stream responses.
|
||||
// Cloning such responses would prevent client-side stream cancelations
|
||||
// from reaching the original stream (a teed stream only cancels its
|
||||
// source once both of its branches cancel) and would buffer the
|
||||
// entire stream into the unconsumed clone indefinitely.
|
||||
const isEventStreamResponse = response.headers
|
||||
.get('content-type')
|
||||
?.toLowerCase()
|
||||
.startsWith('text/event-stream')
|
||||
|
||||
// Clone the response so both the client and the library could consume it.
|
||||
const responseClone = response.clone()
|
||||
const responseClone = isEventStreamResponse ? null : response.clone()
|
||||
|
||||
sendToClient(
|
||||
client,
|
||||
@@ -151,15 +161,17 @@ async function handleRequest(event, requestId, requestInterceptedAt) {
|
||||
...serializedRequest,
|
||||
},
|
||||
response: {
|
||||
type: responseClone.type,
|
||||
status: responseClone.status,
|
||||
statusText: responseClone.statusText,
|
||||
headers: Object.fromEntries(responseClone.headers.entries()),
|
||||
body: responseClone.body,
|
||||
type: response.type,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
headers: Object.fromEntries(response.headers.entries()),
|
||||
body: responseClone ? responseClone.body : null,
|
||||
},
|
||||
},
|
||||
},
|
||||
responseClone.body ? [serializedRequest.body, responseClone.body] : [],
|
||||
responseClone && responseClone.body
|
||||
? [serializedRequest.body, responseClone.body]
|
||||
: [],
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ export default function AppSidebar() {
|
||||
{ key: '/settings#subscription', icon: <CloudServerOutlined />, label: t('pages.settings.subSettings') },
|
||||
];
|
||||
if (showSubFormats) {
|
||||
children.push({ key: '/settings#subscription-formats', icon: <CodeOutlined />, label: 'Sub Formats' });
|
||||
children.push({ key: '/settings#subscription-formats', icon: <CodeOutlined />, label: t('menu.subFormats') });
|
||||
}
|
||||
return children;
|
||||
}, [t, showSubFormats]);
|
||||
|
||||
@@ -127,7 +127,7 @@ export default function IndexPage() {
|
||||
|
||||
async function copyConfig() {
|
||||
const ok = await ClipboardManager.copyText(configText || '');
|
||||
if (ok) messageApi.success('Copied');
|
||||
if (ok) messageApi.success(t('copied'));
|
||||
}
|
||||
|
||||
function downloadConfig() {
|
||||
|
||||
@@ -105,14 +105,14 @@ export default function LogModal({ open, onClose }: LogModalProps) {
|
||||
<Select
|
||||
value={level}
|
||||
size="small"
|
||||
style={{ width: 95 }}
|
||||
style={{ minWidth: 95 }}
|
||||
onChange={setLevel}
|
||||
options={[
|
||||
{ value: 'debug', label: 'Debug' },
|
||||
{ value: 'info', label: 'Info' },
|
||||
{ value: 'notice', label: 'Notice' },
|
||||
{ value: 'warning', label: 'Warning' },
|
||||
{ value: 'err', label: 'Error' },
|
||||
{ value: 'debug', label: t('pages.index.logLevelDebug') },
|
||||
{ value: 'info', label: t('pages.index.logLevelInfo') },
|
||||
{ value: 'notice', label: t('pages.index.logLevelNotice') },
|
||||
{ value: 'warning', label: t('pages.index.logLevelWarning') },
|
||||
{ value: 'err', label: t('pages.index.logLevelError') },
|
||||
]}
|
||||
/>
|
||||
</Space.Compact>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import type { TFunction } from 'i18next';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Checkbox, Form, Input, Modal, Select, Tag } from 'antd';
|
||||
import { DownloadOutlined, SyncOutlined } from '@ant-design/icons';
|
||||
@@ -24,11 +25,24 @@ interface XrayLogEntry {
|
||||
Event?: number;
|
||||
}
|
||||
|
||||
const EVENT_LABELS: Record<number, string> = { 0: 'DIRECT', 1: 'BLOCKED', 2: 'PROXY' };
|
||||
// The downloaded log is a data format people grep, so it keeps the stable
|
||||
// tokens; only what is rendered on screen follows the panel language.
|
||||
const EVENT_TOKENS: Record<number, string> = { 0: 'DIRECT', 1: 'BLOCKED', 2: 'PROXY' };
|
||||
|
||||
const EVENT_KEYS: Record<number, string> = {
|
||||
0: 'pages.index.accessDirect',
|
||||
1: 'pages.index.accessBlocked',
|
||||
2: 'pages.index.accessProxy',
|
||||
};
|
||||
const EVENT_COLORS: Record<number, string> = { 0: 'green', 1: 'red', 2: 'blue' };
|
||||
|
||||
function eventLabel(ev?: number): string {
|
||||
return EVENT_LABELS[ev ?? -1] ?? String(ev ?? '');
|
||||
function eventToken(ev?: number): string {
|
||||
return EVENT_TOKENS[ev ?? -1] ?? String(ev ?? '');
|
||||
}
|
||||
|
||||
function eventLabel(t: TFunction, ev?: number): string {
|
||||
const key = EVENT_KEYS[ev ?? -1];
|
||||
return key ? t(key) : String(ev ?? '');
|
||||
}
|
||||
|
||||
function eventColor(ev?: number): string {
|
||||
@@ -112,7 +126,7 @@ export default function XrayLogModal({ open, onClose }: XrayLogModalProps) {
|
||||
try {
|
||||
const dt = l.DateTime ? new Date(l.DateTime) : null;
|
||||
const dateStr = dt && !isNaN(dt.getTime()) ? dt.toISOString() : '';
|
||||
const eventText = eventLabel(l.Event);
|
||||
const eventText = eventToken(l.Event);
|
||||
const emailPart = l.Email ? ` Email=${l.Email}` : '';
|
||||
return `${dateStr} FROM=${l.FromAddress || ''} TO=${l.ToAddress || ''} INBOUND=${l.Inbound || ''} OUTBOUND=${l.Outbound || ''}${emailPart} EVENT=${eventText}`.trim();
|
||||
} catch {
|
||||
@@ -193,7 +207,7 @@ export default function XrayLogModal({ open, onClose }: XrayLogModalProps) {
|
||||
{shortTime(log.DateTime)}
|
||||
</span>
|
||||
<Tag color={eventColor(log.Event)} className="log-event-tag">
|
||||
{eventLabel(log.Event)}
|
||||
{eventLabel(t, log.Event)}
|
||||
</Tag>
|
||||
</div>
|
||||
<div className="log-route">
|
||||
|
||||
@@ -34,10 +34,6 @@ interface GeneralTabProps {
|
||||
updateSetting: (patch: Partial<AllSetting>) => void;
|
||||
}
|
||||
|
||||
const DATEPICKER_LIST: { name: string; value: 'gregorian' | 'jalalian' }[] = [
|
||||
{ name: 'Gregorian (Standard)', value: 'gregorian' },
|
||||
{ name: 'Jalalian (شمسی)', value: 'jalalian' },
|
||||
];
|
||||
|
||||
export default function GeneralTab({ allSetting, updateSetting }: GeneralTabProps) {
|
||||
const { t } = useTranslation();
|
||||
@@ -290,7 +286,10 @@ export default function GeneralTab({ allSetting, updateSetting }: GeneralTabProp
|
||||
value={allSetting.datepicker || 'gregorian'}
|
||||
onChange={(v) => updateSetting({ datepicker: v as 'gregorian' | 'jalalian' })}
|
||||
style={{ width: '100%' }}
|
||||
options={DATEPICKER_LIST.map((d) => ({ value: d.value, label: d.name }))}
|
||||
options={[
|
||||
{ value: 'gregorian', label: t('pages.settings.calendarGregorian') },
|
||||
{ value: 'jalalian', label: t('pages.settings.calendarJalalian') },
|
||||
]}
|
||||
/>
|
||||
</SettingListItem>
|
||||
</>
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "التوثيق",
|
||||
"openMenu": "فتح القائمة",
|
||||
"pinSidebar": "تثبيت الشريط الجانبي",
|
||||
"unpinSidebar": "إلغاء تثبيت الشريط الجانبي"
|
||||
"unpinSidebar": "إلغاء تثبيت الشريط الجانبي",
|
||||
"subFormats": "Sub Formats"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — حرج",
|
||||
"panel": "اللوحة",
|
||||
"threads": "الخيوط",
|
||||
"uptime": "مدة التشغيل"
|
||||
"uptime": "مدة التشغيل",
|
||||
"logLevelDebug": "Debug",
|
||||
"logLevelInfo": "Info",
|
||||
"logLevelNotice": "Notice",
|
||||
"logLevelWarning": "Warning",
|
||||
"logLevelError": "Error",
|
||||
"accessDirect": "DIRECT",
|
||||
"accessBlocked": "BLOCKED",
|
||||
"accessProxy": "PROXY"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "إجمالي المرسل/المستقبل",
|
||||
@@ -1352,7 +1361,9 @@
|
||||
"pathLeadingSlash": "يجب أن يبدأ المسار بالرمز /"
|
||||
},
|
||||
"secretClear": "مسح",
|
||||
"secretClearUndo": "تراجع عن المسح"
|
||||
"secretClearUndo": "تراجع عن المسح",
|
||||
"calendarGregorian": "Gregorian (Standard)",
|
||||
"calendarJalalian": "Jalalian (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"save": "احفظ",
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "Documentation",
|
||||
"openMenu": "Open menu",
|
||||
"pinSidebar": "Pin sidebar",
|
||||
"unpinSidebar": "Unpin sidebar"
|
||||
"unpinSidebar": "Unpin sidebar",
|
||||
"subFormats": "Sub Formats"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — critical",
|
||||
"panel": "Panel",
|
||||
"threads": "Threads",
|
||||
"uptime": "Uptime"
|
||||
"uptime": "Uptime",
|
||||
"logLevelDebug": "Debug",
|
||||
"logLevelInfo": "Info",
|
||||
"logLevelNotice": "Notice",
|
||||
"logLevelWarning": "Warning",
|
||||
"logLevelError": "Error",
|
||||
"accessDirect": "DIRECT",
|
||||
"accessBlocked": "BLOCKED",
|
||||
"accessProxy": "PROXY"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "Total Sent/Received",
|
||||
@@ -1469,7 +1478,9 @@
|
||||
"pathLeadingSlash": "Path must start with /"
|
||||
},
|
||||
"secretClear": "Clear",
|
||||
"secretClearUndo": "Undo clear"
|
||||
"secretClearUndo": "Undo clear",
|
||||
"calendarGregorian": "Gregorian (Standard)",
|
||||
"calendarJalalian": "Jalalian (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"save": "Save",
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "Documentación",
|
||||
"openMenu": "Abrir menú",
|
||||
"pinSidebar": "Fijar barra lateral",
|
||||
"unpinSidebar": "Desfijar barra lateral"
|
||||
"unpinSidebar": "Desfijar barra lateral",
|
||||
"subFormats": "Sub Formats"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — crítico",
|
||||
"panel": "Panel",
|
||||
"threads": "Hilos",
|
||||
"uptime": "Tiempo activo"
|
||||
"uptime": "Tiempo activo",
|
||||
"logLevelDebug": "Debug",
|
||||
"logLevelInfo": "Info",
|
||||
"logLevelNotice": "Notice",
|
||||
"logLevelWarning": "Warning",
|
||||
"logLevelError": "Error",
|
||||
"accessDirect": "DIRECT",
|
||||
"accessBlocked": "BLOCKED",
|
||||
"accessProxy": "PROXY"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "Subidas/Descargas Totales",
|
||||
@@ -1352,7 +1361,9 @@
|
||||
"pathLeadingSlash": "La ruta debe comenzar con /"
|
||||
},
|
||||
"secretClear": "Borrar",
|
||||
"secretClearUndo": "Deshacer borrado"
|
||||
"secretClearUndo": "Deshacer borrado",
|
||||
"calendarGregorian": "Gregorian (Standard)",
|
||||
"calendarJalalian": "Jalalian (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"save": "Guardar configuración",
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "مستندات",
|
||||
"openMenu": "باز کردن منو",
|
||||
"pinSidebar": "ثابت کردن نوار کناری",
|
||||
"unpinSidebar": "برداشتن تثبیت نوار کناری"
|
||||
"unpinSidebar": "برداشتن تثبیت نوار کناری",
|
||||
"subFormats": "Sub Formats"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — بحرانی",
|
||||
"panel": "پنل",
|
||||
"threads": "نخها",
|
||||
"uptime": "مدت کارکرد"
|
||||
"uptime": "مدت کارکرد",
|
||||
"logLevelDebug": "Debug",
|
||||
"logLevelInfo": "Info",
|
||||
"logLevelNotice": "Notice",
|
||||
"logLevelWarning": "Warning",
|
||||
"logLevelError": "Error",
|
||||
"accessDirect": "DIRECT",
|
||||
"accessBlocked": "BLOCKED",
|
||||
"accessProxy": "PROXY"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "دریافت/ارسال کل",
|
||||
@@ -1352,7 +1361,9 @@
|
||||
"pathLeadingSlash": "مسیر باید با / شروع شود"
|
||||
},
|
||||
"secretClear": "پاک کردن",
|
||||
"secretClearUndo": "لغو پاک کردن"
|
||||
"secretClearUndo": "لغو پاک کردن",
|
||||
"calendarGregorian": "Gregorian (Standard)",
|
||||
"calendarJalalian": "Jalalian (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"save": "ذخیره",
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "Dokumentasi",
|
||||
"openMenu": "Buka menu",
|
||||
"pinSidebar": "Sematkan bilah sisi",
|
||||
"unpinSidebar": "Lepas sematan bilah sisi"
|
||||
"unpinSidebar": "Lepas sematan bilah sisi",
|
||||
"subFormats": "Sub Formats"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — kritis",
|
||||
"panel": "Panel",
|
||||
"threads": "Thread",
|
||||
"uptime": "Waktu aktif"
|
||||
"uptime": "Waktu aktif",
|
||||
"logLevelDebug": "Debug",
|
||||
"logLevelInfo": "Info",
|
||||
"logLevelNotice": "Notice",
|
||||
"logLevelWarning": "Warning",
|
||||
"logLevelError": "Error",
|
||||
"accessDirect": "DIRECT",
|
||||
"accessBlocked": "BLOCKED",
|
||||
"accessProxy": "PROXY"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "Total Terkirim/Diterima",
|
||||
@@ -1352,7 +1361,9 @@
|
||||
"pathLeadingSlash": "Path harus diawali dengan /"
|
||||
},
|
||||
"secretClear": "Hapus",
|
||||
"secretClearUndo": "Batalkan hapus"
|
||||
"secretClearUndo": "Batalkan hapus",
|
||||
"calendarGregorian": "Gregorian (Standard)",
|
||||
"calendarJalalian": "Jalalian (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"save": "Simpan",
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "ドキュメント",
|
||||
"openMenu": "メニューを開く",
|
||||
"pinSidebar": "サイドバーを固定",
|
||||
"unpinSidebar": "サイドバーの固定を解除"
|
||||
"unpinSidebar": "サイドバーの固定を解除",
|
||||
"subFormats": "Sub Formats"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — 危険水準",
|
||||
"panel": "パネル",
|
||||
"threads": "スレッド",
|
||||
"uptime": "稼働時間"
|
||||
"uptime": "稼働時間",
|
||||
"logLevelDebug": "Debug",
|
||||
"logLevelInfo": "Info",
|
||||
"logLevelNotice": "Notice",
|
||||
"logLevelWarning": "Warning",
|
||||
"logLevelError": "Error",
|
||||
"accessDirect": "DIRECT",
|
||||
"accessBlocked": "BLOCKED",
|
||||
"accessProxy": "PROXY"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "総アップロード / ダウンロード",
|
||||
@@ -1352,7 +1361,9 @@
|
||||
"pathLeadingSlash": "パスは / で始まる必要があります"
|
||||
},
|
||||
"secretClear": "クリア",
|
||||
"secretClearUndo": "クリアを取り消す"
|
||||
"secretClearUndo": "クリアを取り消す",
|
||||
"calendarGregorian": "Gregorian (Standard)",
|
||||
"calendarJalalian": "Jalalian (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"importRules": "ルールをインポート",
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "Documentação",
|
||||
"openMenu": "Abrir menu",
|
||||
"pinSidebar": "Fixar barra lateral",
|
||||
"unpinSidebar": "Desafixar barra lateral"
|
||||
"unpinSidebar": "Desafixar barra lateral",
|
||||
"subFormats": "Sub Formats"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — crítico",
|
||||
"panel": "Painel",
|
||||
"threads": "Threads",
|
||||
"uptime": "Tempo ativo"
|
||||
"uptime": "Tempo ativo",
|
||||
"logLevelDebug": "Debug",
|
||||
"logLevelInfo": "Info",
|
||||
"logLevelNotice": "Notice",
|
||||
"logLevelWarning": "Warning",
|
||||
"logLevelError": "Error",
|
||||
"accessDirect": "DIRECT",
|
||||
"accessBlocked": "BLOCKED",
|
||||
"accessProxy": "PROXY"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "Total Enviado/Recebido",
|
||||
@@ -1352,7 +1361,9 @@
|
||||
"pathLeadingSlash": "O caminho deve começar com /"
|
||||
},
|
||||
"secretClear": "Limpar",
|
||||
"secretClearUndo": "Desfazer limpeza"
|
||||
"secretClearUndo": "Desfazer limpeza",
|
||||
"calendarGregorian": "Gregorian (Standard)",
|
||||
"calendarJalalian": "Jalalian (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"importRules": "Importar regras",
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "Документация",
|
||||
"openMenu": "Открыть меню",
|
||||
"pinSidebar": "Закрепить боковую панель",
|
||||
"unpinSidebar": "Открепить боковую панель"
|
||||
"unpinSidebar": "Открепить боковую панель",
|
||||
"subFormats": "Форматы подписки"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — критический уровень",
|
||||
"panel": "Панель",
|
||||
"threads": "Потоки",
|
||||
"uptime": "Время работы"
|
||||
"uptime": "Время работы",
|
||||
"logLevelDebug": "Отладка",
|
||||
"logLevelInfo": "Информация",
|
||||
"logLevelNotice": "Уведомление",
|
||||
"logLevelWarning": "Предупреждение",
|
||||
"logLevelError": "Ошибка",
|
||||
"accessDirect": "НАПРЯМУЮ",
|
||||
"accessBlocked": "ЗАБЛОКИРОВАНО",
|
||||
"accessProxy": "ЧЕРЕЗ ПРОКСИ"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "Отправлено/получено",
|
||||
@@ -1352,7 +1361,9 @@
|
||||
"pathLeadingSlash": "Путь должен начинаться с /"
|
||||
},
|
||||
"secretClear": "Очистить",
|
||||
"secretClearUndo": "Отменить очистку"
|
||||
"secretClearUndo": "Отменить очистку",
|
||||
"calendarGregorian": "Григорианский (обычный)",
|
||||
"calendarJalalian": "Джалали (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"importRules": "Импорт правил",
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "Belgeler",
|
||||
"openMenu": "Menüyü aç",
|
||||
"pinSidebar": "Kenar çubuğunu sabitle",
|
||||
"unpinSidebar": "Kenar çubuğu sabitlemesini kaldır"
|
||||
"unpinSidebar": "Kenar çubuğu sabitlemesini kaldır",
|
||||
"subFormats": "Sub Formats"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — kritik",
|
||||
"panel": "Panel",
|
||||
"threads": "İş parçacıkları",
|
||||
"uptime": "Çalışma süresi"
|
||||
"uptime": "Çalışma süresi",
|
||||
"logLevelDebug": "Debug",
|
||||
"logLevelInfo": "Info",
|
||||
"logLevelNotice": "Notice",
|
||||
"logLevelWarning": "Warning",
|
||||
"logLevelError": "Error",
|
||||
"accessDirect": "DIRECT",
|
||||
"accessBlocked": "BLOCKED",
|
||||
"accessProxy": "PROXY"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "Toplam Gönderilen/Alınan",
|
||||
@@ -1352,7 +1361,9 @@
|
||||
"pathLeadingSlash": "Yol / ile başlamalıdır"
|
||||
},
|
||||
"secretClear": "Temizle",
|
||||
"secretClearUndo": "Temizlemeyi geri al"
|
||||
"secretClearUndo": "Temizlemeyi geri al",
|
||||
"calendarGregorian": "Gregorian (Standard)",
|
||||
"calendarJalalian": "Jalalian (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"save": "Kaydet",
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "Документація",
|
||||
"openMenu": "Відкрити меню",
|
||||
"pinSidebar": "Закріпити бічну панель",
|
||||
"unpinSidebar": "Відкріпити бічну панель"
|
||||
"unpinSidebar": "Відкріпити бічну панель",
|
||||
"subFormats": "Формати підписки"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — критичний рівень",
|
||||
"panel": "Панель",
|
||||
"threads": "Потоки",
|
||||
"uptime": "Час роботи"
|
||||
"uptime": "Час роботи",
|
||||
"logLevelDebug": "Налагодження",
|
||||
"logLevelInfo": "Інформація",
|
||||
"logLevelNotice": "Сповіщення",
|
||||
"logLevelWarning": "Попередження",
|
||||
"logLevelError": "Помилка",
|
||||
"accessDirect": "НАПРЯМУ",
|
||||
"accessBlocked": "ЗАБЛОКОВАНО",
|
||||
"accessProxy": "ЧЕРЕЗ ПРОКСІ"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "Всього надісланих/отриманих",
|
||||
@@ -1352,7 +1361,9 @@
|
||||
"pathLeadingSlash": "Шлях має починатися з /"
|
||||
},
|
||||
"secretClear": "Очистити",
|
||||
"secretClearUndo": "Скасувати очищення"
|
||||
"secretClearUndo": "Скасувати очищення",
|
||||
"calendarGregorian": "Григоріанський (звичайний)",
|
||||
"calendarJalalian": "Джалалі (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"save": "Зберегти",
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "Tài liệu",
|
||||
"openMenu": "Mở menu",
|
||||
"pinSidebar": "Ghim thanh bên",
|
||||
"unpinSidebar": "Bỏ ghim thanh bên"
|
||||
"unpinSidebar": "Bỏ ghim thanh bên",
|
||||
"subFormats": "Sub Formats"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — nguy cấp",
|
||||
"panel": "Panel",
|
||||
"threads": "Luồng",
|
||||
"uptime": "Thời gian chạy"
|
||||
"uptime": "Thời gian chạy",
|
||||
"logLevelDebug": "Debug",
|
||||
"logLevelInfo": "Info",
|
||||
"logLevelNotice": "Notice",
|
||||
"logLevelWarning": "Warning",
|
||||
"logLevelError": "Error",
|
||||
"accessDirect": "DIRECT",
|
||||
"accessBlocked": "BLOCKED",
|
||||
"accessProxy": "PROXY"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "Tổng tải lên/tải xuống",
|
||||
@@ -1352,7 +1361,9 @@
|
||||
"pathLeadingSlash": "Đường dẫn phải bắt đầu bằng /"
|
||||
},
|
||||
"secretClear": "Xóa",
|
||||
"secretClearUndo": "Hoàn tác xóa"
|
||||
"secretClearUndo": "Hoàn tác xóa",
|
||||
"calendarGregorian": "Gregorian (Standard)",
|
||||
"calendarJalalian": "Jalalian (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"importRules": "Nhập quy tắc",
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "文档",
|
||||
"openMenu": "打开菜单",
|
||||
"pinSidebar": "固定侧边栏",
|
||||
"unpinSidebar": "取消固定侧边栏"
|
||||
"unpinSidebar": "取消固定侧边栏",
|
||||
"subFormats": "Sub Formats"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — 危险",
|
||||
"panel": "面板",
|
||||
"threads": "线程",
|
||||
"uptime": "运行时间"
|
||||
"uptime": "运行时间",
|
||||
"logLevelDebug": "Debug",
|
||||
"logLevelInfo": "Info",
|
||||
"logLevelNotice": "Notice",
|
||||
"logLevelWarning": "Warning",
|
||||
"logLevelError": "Error",
|
||||
"accessDirect": "DIRECT",
|
||||
"accessBlocked": "BLOCKED",
|
||||
"accessProxy": "PROXY"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "总上传 / 下载",
|
||||
@@ -1352,7 +1361,9 @@
|
||||
"pathLeadingSlash": "路径必须以 / 开头"
|
||||
},
|
||||
"secretClear": "清除",
|
||||
"secretClearUndo": "撤销清除"
|
||||
"secretClearUndo": "撤销清除",
|
||||
"calendarGregorian": "Gregorian (Standard)",
|
||||
"calendarJalalian": "Jalalian (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"importRules": "导入规则",
|
||||
|
||||
@@ -112,7 +112,8 @@
|
||||
"docs": "文件",
|
||||
"openMenu": "開啟選單",
|
||||
"pinSidebar": "固定側邊欄",
|
||||
"unpinSidebar": "取消固定側邊欄"
|
||||
"unpinSidebar": "取消固定側邊欄",
|
||||
"subFormats": "Sub Formats"
|
||||
},
|
||||
"pages": {
|
||||
"login": {
|
||||
@@ -257,7 +258,15 @@
|
||||
"healthCritical": "{list} — 危險",
|
||||
"panel": "面板",
|
||||
"threads": "執行緒",
|
||||
"uptime": "執行時間"
|
||||
"uptime": "執行時間",
|
||||
"logLevelDebug": "Debug",
|
||||
"logLevelInfo": "Info",
|
||||
"logLevelNotice": "Notice",
|
||||
"logLevelWarning": "Warning",
|
||||
"logLevelError": "Error",
|
||||
"accessDirect": "DIRECT",
|
||||
"accessBlocked": "BLOCKED",
|
||||
"accessProxy": "PROXY"
|
||||
},
|
||||
"inbounds": {
|
||||
"totalDownUp": "總上傳 / 下載",
|
||||
@@ -1352,7 +1361,9 @@
|
||||
"pathLeadingSlash": "路徑必須以 / 開頭"
|
||||
},
|
||||
"secretClear": "清除",
|
||||
"secretClearUndo": "復原清除"
|
||||
"secretClearUndo": "復原清除",
|
||||
"calendarGregorian": "Gregorian (Standard)",
|
||||
"calendarJalalian": "Jalalian (شمسی)"
|
||||
},
|
||||
"xray": {
|
||||
"save": "儲存",
|
||||
|
||||
Reference in New Issue
Block a user