chore(i18n): delete 230 dead translation keys and guard against new ones (#6132)

* chore(i18n): delete 230 dead translation keys and guard against new ones

The 13 locale files carried 230 keys (11% of the set) that nothing in
the frontend or Go sources references — leftovers of renamed features
(the email notifier reuses tgbot.messages.* for subjects, the old
email.subject*/title* set was orphaned; likewise menu.*, the clients
bulk-copy strings, and the secAlert* family). Nothing detected this:
a missing key falls back to en-US and an unused key fails nothing.

A new test now fails the build when an en-US key has no reference in
frontend/src or internal Go sources (dynamic keys are covered by
harvesting concatenation and template-literal prefixes), and pins
that all 13 locales carry exactly the en-US key set, so parity drift
surfaces at test time instead of as a silent fallback.

Each locale shrinks by the same 230 keys; net -2,900 lines across
the translation set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(i18n): restore the 29 live remarkVars keys, match whole tokens, unmask 9 more

From review: the template-literal harvester required the prefix to end
on a dot, so pages.hosts.remarkVars.desc${token} harvested nothing
and all 29 desc* tooltip keys were wrongly deleted — and the guard
shared the flawed logic, so CI stayed green while the Hosts page
would have shown raw key names in 13 languages. Restored from the
parent commit; the harvester now requires at least one dot but not a
trailing one.

Also from review: references are matched as whole dotted tokens
instead of substrings (a dead key can no longer hide behind a longer
sibling — that unmasked 9 more genuinely dead keys, each verified by
hand before deletion), and the test excludes itself from the scan so
its own prose cannot whitelist a subtree.

Net: -210 keys per locale instead of the previous -230.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
PathGao
2026-07-29 13:59:25 +08:00
committed by GitHub
parent 17e6b5a460
commit ea35884390
14 changed files with 117 additions and 2834 deletions
+2 -218
View File
@@ -48,7 +48,6 @@
"copySuccess": "Berhasil Disalin",
"sure": "Yakin",
"encryption": "Enkripsi",
"useIPv4ForHost": "Gunakan IPv4 untuk host",
"transmission": "Transmisi",
"host": "Host",
"path": "Path",
@@ -74,18 +73,9 @@
"twoFactorCode": "Kode",
"remained": "Tersisa",
"security": "Keamanan",
"secAlertTitle": "Peringatan keamanan",
"secAlertSsl": "Koneksi ini tidak aman. Harap hindari memasukkan informasi sensitif sampai TLS diaktifkan untuk perlindungan data.",
"secAlertConf": "Beberapa pengaturan rentan terhadap serangan. Disarankan untuk memperkuat protokol keamanan guna mencegah pelanggaran potensial.",
"secAlertSSL": "Panel kekurangan koneksi yang aman. Harap instal sertifikat TLS untuk perlindungan data.",
"secAlertPanelPort": "Port default panel rentan. Harap konfigurasi port acak atau tertentu.",
"secAlertPanelURI": "Jalur URI default panel tidak aman. Harap konfigurasi jalur URI kompleks.",
"secAlertSubURI": "Jalur URI default langganan tidak aman. Harap konfigurasi jalur URI kompleks.",
"secAlertSubJsonURI": "Jalur URI default JSON langganan tidak aman. Harap konfigurasikan jalur URI kompleks.",
"emptyDnsDesc": "Tidak ada server DNS yang ditambahkan.",
"emptyFakeDnsDesc": "Tidak ada server Fake DNS yang ditambahkan.",
"emptyBalancersDesc": "Tidak ada penyeimbang yang ditambahkan.",
"emptyReverseDesc": "Tidak ada proxy terbalik yang ditambahkan.",
"somethingWentWrong": "Terjadi kesalahan",
"subscription": {
"title": "Info langganan",
@@ -106,8 +96,6 @@
},
"menu": {
"theme": "Tema",
"dark": "Gelap",
"ultraDark": "Sangat Gelap",
"dashboard": "Ikhtisar",
"inbounds": "Inbound",
"clients": "Klien",
@@ -118,7 +106,6 @@
"routing": "Pengalihan",
"outbounds": "Outbound",
"apiDocs": "Dokumentasi API",
"logout": "Keluar",
"link": "Kelola",
"donate": "Donasi",
"hosts": "Host",
@@ -139,7 +126,6 @@
}
},
"index": {
"title": "Ikhtisar",
"cpu": "CPU",
"logicalProcessors": "Prosesor logis",
"frequency": "Frekuensi",
@@ -152,7 +138,6 @@
"restartXray": "Mulai ulang",
"xraySwitch": "Versi",
"xrayUpdates": "Pembaruan Xray",
"xraySwitchClick": "Pilih versi yang ingin Anda pindah.",
"xraySwitchClickDesk": "Pilih dengan hati-hati, karena versi yang lebih lama mungkin tidak kompatibel dengan konfigurasi saat ini.",
"updatePanel": "Perbarui Panel",
"panelUpdateDesc": "Ini akan memperbarui 3X-UI ke rilis terbaru dan me-restart layanan panel.",
@@ -164,12 +149,10 @@
"currentCommit": "Commit saat ini",
"latestCommit": "Commit terbaru",
"updateChannelChanged": "Kanal pembaruan diubah",
"upToDate": "Terbaru",
"xrayStatusUnknown": "Tidak diketahui",
"xrayStatusRunning": "Berjalan",
"xrayStatusStop": "Berhenti",
"xrayStatusError": "Error",
"xrayErrorPopoverTitle": "Terjadi kesalahan saat menjalankan Xray",
"operationHours": "Waktu Aktif",
"systemHistoryTitle": "Riwayat Sistem",
"historyTitleCpu": "Penggunaan CPU",
@@ -211,9 +194,6 @@
"xrayObservatoryDead": "Mati",
"xrayObservatoryLastSeen": "Terakhir terlihat",
"xrayObservatoryLastTry": "Percobaan terakhir",
"trendLast2Min": "2 menit terakhir",
"systemLoad": "Beban Sistem",
"systemLoadDesc": "Rata-rata beban sistem selama 1, 5, dan 15 menit terakhir",
"connectionCount": "Statistik Koneksi",
"ipAddresses": "Alamat IP",
"toggleIpVisibility": "Alihkan visibilitas IP",
@@ -223,13 +203,11 @@
"totalData": "Total data",
"sent": "Dikirim",
"received": "Diterima",
"documentation": "Dokumentasi",
"xraySwitchVersionDialog": "Apakah Anda yakin ingin mengubah versi Xray?",
"xraySwitchVersionDialogDesc": "Ini akan mengubah versi Xray ke #version#.",
"xraySwitchVersionPopover": "Xray berhasil diperbarui",
"panelUpdateDialog": "Apakah Anda benar-benar ingin memperbarui panel?",
"panelUpdateDialogDesc": "Ini akan memperbarui 3X-UI ke #version# dan me-restart layanan panel.",
"panelUpdateCheckPopover": "Pemeriksaan pembaruan panel gagal",
"panelUpdateStartedPopover": "Pembaruan panel dimulai",
"panelUpdateFailedTitle": "Pembaruan panel gagal",
"panelUpdateFailedDesc": "Pembaruan tidak selesai dengan sukses. Periksa log server, atau jalankan 'x-ui update' dari baris perintah.",
@@ -258,7 +236,6 @@
"accessLogs": "Log Akses",
"autoUpdate": "Pembaruan Otomatis",
"config": "Konfigurasi",
"backup": "Cadangan",
"backupTitle": "Cadangan & Pulihkan",
"exportDatabase": "Cadangkan",
"exportDatabaseDesc": "Klik untuk mengunduh file .db yang berisi cadangan dari database Anda saat ini ke perangkat Anda. Berkas yang sama juga dapat dipulihkan ke panel yang berjalan di PostgreSQL.",
@@ -276,7 +253,6 @@
"migrationDownloadPgDesc": "Klik untuk mengunduh basis data SQLite .db yang dibuat dari data PostgreSQL Anda, siap menjalankan panel ini di SQLite."
},
"inbounds": {
"title": "Inbound",
"totalDownUp": "Total Terkirim/Diterima",
"totalUsage": "Penggunaan Total",
"inboundCount": "Total Masuk",
@@ -288,21 +264,11 @@
"localPanel": "Panel lokal",
"fallbacks": {
"title": "Fallback",
"help": "Saat koneksi pada inbound ini tidak cocok dengan client mana pun, arahkan ke tempat lain. Pilih inbound child di bawah untuk mengisi otomatis field routing (SNI / ALPN / Path / xver) dari transport-nya, atau biarkan pemilih kosong dan atur Dest langsung (mis. 8080 atau 127.0.0.1:8080) untuk mengarahkan ke server eksternal seperti Nginx. Setiap inbound child harus listen di 127.0.0.1 dengan security=none.",
"empty": "Belum ada fallback",
"add": "Tambah fallback",
"pickInbound": "Pilih inbound",
"matchAny": "apa pun",
"destPlaceholder": "otomatis (listen:port child)",
"rederive": "Isi ulang dari child",
"rederived": "Diisi ulang dari child",
"editAdvanced": "Edit field routing",
"hideAdvanced": "Sembunyikan lanjutan",
"quickAddAll": "Tambah cepat semua yang memenuhi syarat",
"quickAdded": "Menambahkan {n} fallback",
"quickAddedNone": "Tidak ada inbound baru yang memenuhi syarat",
"routesWhen": "Diarahkan ketika",
"defaultCatchAll": "Default — menangkap apa pun lainnya",
"needsTls": "Fallback tersedia setelah memilih TLS atau Reality di tab Keamanan (hanya VLESS/Trojan melalui RAW)."
},
"protocol": "Protokol",
@@ -310,8 +276,6 @@
"portMap": "Pemetaan port",
"traffic": "Trafik",
"speed": "Kecepatan",
"details": "Rincian",
"transportConfig": "Transport",
"expireDate": "Durasi",
"createdAt": "Dibuat",
"updatedAt": "Diperbarui",
@@ -319,8 +283,6 @@
"addInbound": "Tambahkan Masuk",
"generalActions": "Tindakan Umum",
"modifyInbound": "Ubah Masuk",
"deleteInbound": "Hapus Masuk",
"deleteInboundContent": "Apakah Anda yakin ingin menghapus masuk?",
"deleteConfirmTitle": "Hapus inbound \"{remark}\"?",
"deleteConfirmContent": "Tindakan ini menghapus inbound beserta semua kliennya. Tidak dapat dibatalkan.",
"resetConfirmTitle": "Reset trafik \"{remark}\"?",
@@ -364,8 +326,6 @@
"exportAllLinksFileName": "Semua-Inbound",
"exportAllSubsFileName": "Semua-Inbound-Subs",
"inboundJsonTitle": "JSON inbound",
"deleteClient": "Hapus Klien",
"deleteClientContent": "Apakah Anda yakin ingin menghapus klien?",
"resetTrafficContent": "Apakah Anda yakin ingin mereset traffic?",
"copyLink": "Salin URL",
"address": "Alamat",
@@ -376,36 +336,19 @@
"meansNoLimit": "= Tanpa batas. (satuan: GB)",
"totalFlow": "Total Aliran",
"leaveBlankToNeverExpire": "Biarkan kosong untuk tidak pernah kedaluwarsa",
"noRecommendKeepDefault": "Disarankan untuk tetap menggunakan pengaturan default",
"certificatePath": "Path Berkas",
"certificateContent": "Konten Berkas",
"publicKey": "Kunci Publik",
"privatekey": "Kunci Pribadi",
"clickOnQRcode": "Klik pada Kode QR untuk Menyalin",
"client": "Klien",
"export": "Ekspor Semua URL",
"clone": "Duplikat",
"cloneInbound": "Duplikat",
"cloneInboundContent": "Semua pengaturan masuk ini, kecuali Port, Listening IP, dan Klien, akan diterapkan pada duplikat.",
"cloneInboundOk": "Duplikat",
"resetAllTraffic": "Reset Semua Traffic Masuk",
"resetAllTrafficTitle": "Reset Semua Traffic Masuk",
"resetAllTrafficContent": "Apakah Anda yakin ingin mereset traffic semua masuk?",
"resetInboundClientTraffics": "Reset Traffic Klien Masuk",
"resetInboundClientTrafficTitle": "Reset Traffic Klien Masuk",
"resetInboundClientTrafficContent": "Apakah Anda yakin ingin mereset traffic klien masuk ini?",
"resetAllClientTraffics": "Reset Traffic Semua Klien",
"resetAllClientTrafficTitle": "Reset Traffic Semua Klien",
"resetAllClientTrafficContent": "Apakah Anda yakin ingin mereset traffic semua klien?",
"delDepletedClients": "Hapus Klien Habis",
"delDepletedClientsTitle": "Hapus Klien Habis",
"delDepletedClientsContent": "Apakah Anda yakin ingin menghapus semua klien yang habis?",
"email": "Email",
"emailDesc": "Harap berikan alamat email yang unik.",
"IPLimit": "Batas IP",
"IPLimitDesc": "Menonaktifkan masuk jika jumlah melebihi nilai yang ditetapkan. (0 = nonaktif)",
"IPLimitlog": "Log IP",
"IPLimitlogDesc": "Log histori IP. (untuk mengaktifkan masuk setelah menonaktifkan, hapus log)",
"IPLimitlogclear": "Hapus Log",
"setDefaultCert": "Atur Sertifikat dari Panel",
"setDefaultCertEmpty": "Tidak ada sertifikat yang dikonfigurasi untuk panel. Atur dulu di Pengaturan.",
@@ -438,21 +381,15 @@
"sniffing": "Sniffing",
"sniffingHelp": "Pembungkus blok sniffing Xray:",
"stream": "Stream",
"streamHelp": "Pembungkus blok stream Xray:",
"jsonErrorPrefix": "JSON lanjutan"
"streamHelp": "Pembungkus blok stream Xray:"
},
"telegramDesc": "Harap berikan ID Obrolan Telegram. (gunakan perintah '/id' di bot) atau ({'@'}userinfobot)",
"subscriptionDesc": "Untuk menemukan URL langganan Anda, buka 'Rincian'. Selain itu, Anda dapat menggunakan nama yang sama untuk beberapa klien.",
"subSortIndex": "Urutan sub",
"same": "Sama",
"inboundInfo": "Informasi Inbound",
"exportInbound": "Ekspor Masuk",
"import": "Impor",
"importInbound": "Impor Masuk",
"periodicTrafficResetTitle": "Reset Trafik Berkala",
"periodicTrafficResetDesc": "Reset otomatis penghitung trafik pada interval tertentu",
"periodicTrafficResetDay": "Hari reset bulanan",
"lastReset": "Reset Terakhir",
"periodicTrafficReset": {
"never": "Tidak Pernah",
"daily": "Harian",
@@ -464,7 +401,6 @@
"obtain": "Dapatkan",
"updateSuccess": "Pembaruan berhasil",
"logCleanSuccess": "Log telah dibersihkan",
"inboundsUpdateSuccess": "Inbound berhasil diperbarui",
"inboundUpdateSuccess": "Inbound berhasil diperbarui",
"inboundCreateSuccess": "Inbound berhasil dibuat",
"bulkDeleted": "{count} inbound dihapus",
@@ -474,7 +410,6 @@
"inboundClientDeleteSuccess": "Klien inbound telah dihapus",
"inboundClientUpdateSuccess": "Klien inbound telah diperbarui",
"savedNodeOfflineWillSync": "Disimpan secara lokal. Node pendukung sedang offline atau dinonaktifkan — perubahan akan disinkronkan setelah terhubung kembali.",
"delDepletedClientsSuccess": "Semua klien yang habis telah dihapus",
"resetAllClientTrafficSuccess": "Semua lalu lintas klien telah direset",
"resetAllTrafficSuccess": "Semua lalu lintas telah direset",
"resetInboundClientTrafficSuccess": "Lalu lintas telah direset",
@@ -717,23 +652,6 @@
"peerNumber": "Peer {n}",
"peerNumberConfig": "Konfig Peer {n}"
},
"stream": {
"general": {
"request": "Permintaan",
"response": "Respons",
"name": "Nama",
"value": "Nilai"
},
"tcp": {
"version": "Versi",
"method": "Metode",
"path": "Path",
"status": "Status",
"statusDescription": "Deskripsi Status",
"requestHeader": "Header Permintaan",
"responseHeader": "Header Respons"
}
},
"sniffingDestOverride": "Penggantian tujuan"
},
"clients": {
@@ -747,24 +665,9 @@
"addExternalSubscription": "Tambah Langganan Eksternal",
"noExternalLinks": "Belum ada tautan eksternal.",
"noExternalSubscriptions": "Belum ada langganan eksternal.",
"add": "Tambah klien",
"edit": "Ubah klien",
"submitAdd": "Tambah klien",
"submitEdit": "Simpan perubahan",
"clientCount": "Jumlah klien",
"bulk": "Tambah massal",
"copyFromInbound": "Salin klien dari inbound",
"copyToInbound": "Salin klien ke",
"copySelected": "Salin terpilih",
"copySource": "Sumber",
"copyEmailPreview": "Pratinjau email hasil",
"copySelectSourceFirst": "Pilih inbound sumber terlebih dahulu.",
"copyResult": "Hasil salinan",
"copyResultSuccess": "Berhasil disalin",
"copyResultNone": "Tidak ada yang disalin: tidak ada klien terpilih atau sumber kosong",
"copyResultErrors": "Kesalahan salin",
"copyFlowLabel": "Flow untuk klien baru (VLESS)",
"copyFlowHint": "Diterapkan ke semua klien yang disalin. Kosongkan untuk dilewati.",
"selectAll": "Pilih semua",
"clearAll": "Hapus semua",
"method": "Metode",
@@ -775,7 +678,6 @@
"postfix": "Akhiran",
"delayedStart": "Mulai setelah penggunaan pertama",
"expireDays": "Durasi (hari)",
"days": "Hari",
"renew": "Perpanjangan otomatis",
"renewDesc": "Perpanjangan otomatis setelah kedaluwarsa. (0 = nonaktif) (satuan: hari)",
"renewDays": "Perpanjangan otomatis (hari)",
@@ -798,7 +700,6 @@
"sortExpiringSoonest": "Segera kedaluwarsa",
"has": "Memiliki",
"hasNot": "Tidak memiliki",
"title": "Klien",
"actions": "Aksi",
"totalGB": "Batas Trafik (GB)",
"totalGBDesc": "Kuota data untuk klien ini. 0 = tidak terbatas.",
@@ -826,8 +727,6 @@
"addClient": "Tambah klien",
"qrCode": "Kode QR",
"clientInfo": "Informasi Klien",
"delete": "Hapus",
"reset": "Reset lalu lintas",
"editClient": "Ubah klien",
"client": "Klien",
"enabled": "Aktif",
@@ -841,13 +740,11 @@
"noLinks": "Tidak ada tautan yang bisa dibagikan — lampirkan klien ini ke inbound yang mendukung protokol terlebih dahulu.",
"link": "Tautan",
"resetNotPossible": "Lampirkan klien ini ke inbound terlebih dahulu.",
"general": "Umum",
"resetAllTraffics": "Reset lalu lintas semua klien",
"resetAllTrafficsTitle": "Reset lalu lintas semua klien?",
"resetAllTrafficsContent": "Penghitung kirim/terima setiap klien turun ke nol. Kuota dan kedaluwarsa tidak terpengaruh. Tidak dapat dibatalkan.",
"deleteConfirmTitle": "Hapus klien {email}?",
"deleteConfirmContent": "Tindakan ini menghapus klien dari setiap inbound terlampir dan menghapus catatan lalu lintasnya. Tidak dapat dibatalkan.",
"deleteSelected": "Hapus ({count})",
"adjustSelected": "Sesuaikan ({count})",
"subLinksSelected": "Tautan sub ({count})",
"addToGroupTitle": "Tambahkan {count} klien ke grup",
@@ -869,12 +766,10 @@
"bulkDisableConfirmTitle": "Nonaktifkan {count} klien?",
"bulkDisableConfirmContent": "Menonaktifkan setiap klien yang dipilih di semua inbound yang terlampir. Mereka langsung kehilangan akses, tetapi catatan dan trafiknya tetap disimpan.",
"selectedCount": "{count} dipilih",
"attachSelected": "Lampirkan ({count})",
"attachToInboundsTitle": "Lampirkan {count} klien ke inbound",
"attachToInboundsDesc": "Melampirkan {count} klien terpilih (UUID/kata sandi sama dan trafik bersama) ke inbound terpilih. Lampiran yang ada tetap dipertahankan.",
"attachToInboundsTargets": "Inbound tujuan",
"attachToInboundsNoTargets": "Tidak ada inbound multi-pengguna untuk dilampirkan.",
"detachSelected": "Lepas ({count})",
"detach": "Lepas",
"detachFromInboundsTitle": "Lepas {count} klien dari inbound",
"detachFromInboundsDesc": "Menghapus {count} klien terpilih dari inbound terpilih. Pasangan di mana klien tidak terlampir akan dilewati secara diam-diam. Catatan klien dipertahankan (gunakan Delete untuk menghapus sepenuhnya).",
@@ -928,8 +823,6 @@
"reverseTagPlaceholder": "Reverse tag opsional",
"telegramId": "ID pengguna Telegram",
"telegramIdPlaceholder": "ID numerik pengguna Telegram (0 = tidak ada)",
"created": "Dibuat",
"updated": "Diperbarui",
"ipLimit": "Batas IP",
"toasts": {
"deleted": "Klien dihapus",
@@ -952,7 +845,6 @@
}
},
"groups": {
"title": "Grup",
"name": "Nama",
"clientCount": "Klien",
"totalGroups": "Total grup",
@@ -994,7 +886,6 @@
"removeFromGroupResult": "{count} klien dihapus dari {name}."
},
"nodes": {
"title": "Node",
"addNode": "Tambah Node",
"editNode": "Edit node",
"totalNodes": "Total Node",
@@ -1013,8 +904,6 @@
"apiTokenPlaceholder": "Token dari halaman Pengaturan panel jarak jauh",
"apiTokenHint": "Panel jarak jauh menampilkan token API-nya di Otentikasi → Token API.",
"apiTokenKeepHint": "Biarkan kosong untuk mempertahankan token saat ini",
"regenerate": "Buat Ulang Token",
"regenerateConfirm": "Membuat ulang akan membatalkan token saat ini. Setiap panel pusat yang menggunakannya akan kehilangan akses sampai diperbarui. Lanjutkan?",
"allowPrivateAddress": "Izinkan alamat pribadi",
"allowPrivateAddressHint": "Aktifkan hanya untuk node di jaringan pribadi atau VPN.",
"outboundTag": "Outbound koneksi",
@@ -1046,7 +935,6 @@
"updatePanel": "Perbarui Panel",
"updateSelected": "Perbarui Terpilih ({count})",
"updateAvailable": "Pembaruan tersedia",
"upToDate": "Terbaru",
"updateConfirmTitle": "Perbarui {count} node ke versi terbaru?",
"updateConfirmContent": "Setiap node terpilih mengunduh rilis terbaru dan memulai ulang. Hanya node aktif dan online yang diperbarui.",
"updateDevChannel": "Perbarui ke kanal dev (commit terbaru)",
@@ -1447,13 +1335,8 @@
"secretClearUndo": "Batalkan hapus"
},
"xray": {
"title": "Konfigurasi Xray",
"save": "Simpan",
"restart": "Mulai ulang Xray",
"restartSuccess": "Xray berhasil diluncurkan ulang",
"restartOutputTitle": "Output mulai ulang Xray",
"restartConfirmTitle": "Mulai ulang xray?",
"restartConfirmContent": "Memuat ulang layanan xray dengan konfigurasi tersimpan.",
"stopSuccess": "Xray telah berhasil dihentikan",
"restartError": "Terjadi kesalahan saat memulai ulang Xray.",
"stopError": "Terjadi kesalahan saat menghentikan Xray.",
@@ -1463,7 +1346,6 @@
"generalConfigsDesc": "Opsi ini akan menentukan penyesuaian strategi umum.",
"logConfigs": "Log",
"logConfigsDesc": "Log dapat mempengaruhi efisiensi server Anda. Disarankan untuk mengaktifkannya dengan bijak hanya jika diperlukan",
"blockConfigsDesc": "Opsi ini akan memblokir lalu lintas berdasarkan protokol dan situs web yang diminta.",
"basicRouting": "Perutean Dasar",
"blockConnectionsConfigsDesc": "Opsi ini akan memblokir lalu lintas berdasarkan negara yang diminta.",
"directConnectionsConfigsDesc": "Koneksi langsung memastikan bahwa lalu lintas tertentu tidak dialihkan melalui server lain.",
@@ -1473,10 +1355,6 @@
"directdomains": "Domain Langsung",
"ipv4Routing": "Perutean IPv4",
"ipv4RoutingDesc": "Opsi ini akan mengalihkan lalu lintas berdasarkan tujuan tertentu melalui IPv4.",
"warpRouting": "Perutean WARP",
"warpRoutingDesc": "Opsi ini akan mengalihkan lalu lintas berdasarkan tujuan tertentu melalui WARP.",
"nordRouting": "Routing NordVPN",
"nordRoutingDesc": "Opsi ini akan mengalihkan lalu lintas berdasarkan tujuan tertentu melalui NordVPN.",
"Template": "Template Konfigurasi Xray Lanjutan",
"TemplateDesc": "File konfigurasi Xray akhir akan dibuat berdasarkan template ini.",
"FreedomStrategy": "Strategi Protokol Freedom",
@@ -1490,7 +1368,6 @@
"outboundTestUrlDesc": "URL yang digunakan saat menguji konektivitas outbound",
"Torrent": "Blokir Protokol BitTorrent",
"Inbounds": "Inbound",
"InboundsDesc": "Menerima klien tertentu.",
"Outbounds": "Outbound",
"importRules": "Impor aturan",
"exportRules": "Ekspor aturan",
@@ -1500,8 +1377,6 @@
"metricsListen": "Endpoint metrik",
"metricsListenDesc": "Tampilkan metrik gaya Prometheus dari Xray pada alamat:port ini (mis. 127.0.0.1:11111). Biarkan kosong untuk menonaktifkan. Ikat ke localhost dan reverse-proxy — endpoint ini tanpa autentikasi.",
"metricsTag": "Tag metrik",
"OutboundSubscriptions": "Langganan Outbound",
"OutboundSubscriptionsDesc": "Impor outbound dari URL langganan jarak jauh (vmess/vless/trojan/ss/...). Tag dijaga tetap stabil untuk digunakan pada penyeimbang dan aturan routing. Pembaruan berjalan otomatis.",
"Balancers": "Penyeimbang",
"balancerTagRequired": "Tag wajib diisi",
"balancerSelectorRequired": "Pilih setidaknya satu outbound",
@@ -1520,9 +1395,7 @@
"routeTesterMatchedOutbound": "Outbound yang cocok",
"routeTesterViaBalancer": "melalui penyeimbang",
"routeTesterDefaultOutbound": "Tidak ada aturan routing yang cocok — lalu lintas menuju outbound default (pertama).",
"OutboundsDesc": "Atur jalur lalu lintas keluar.",
"Routings": "Aturan Pengalihan",
"RoutingsDesc": "Prioritas setiap aturan penting!",
"completeTemplate": "Semua",
"logLevel": "Tingkat Log",
"logLevelDesc": "Tingkat log untuk log kesalahan, menunjukkan informasi yang perlu dicatat.",
@@ -1536,13 +1409,9 @@
"maskAddressDesc": "Masker alamat IP, ketika diaktifkan, akan secara otomatis mengganti alamat IP yang muncul di log.",
"statistics": "Statistik",
"statsInboundUplink": "Statistik Unggah Masuk",
"statsInboundUplinkDesc": "Mengaktifkan pengumpulan statistik untuk lalu lintas unggah dari semua proxy masuk.",
"statsInboundDownlink": "Statistik Unduh Masuk",
"statsInboundDownlinkDesc": "Mengaktifkan pengumpulan statistik untuk lalu lintas unduh dari semua proxy masuk.",
"statsOutboundUplink": "Statistik Unggah Keluar",
"statsOutboundUplinkDesc": "Mengaktifkan pengumpulan statistik untuk lalu lintas unggah dari semua proxy keluar.",
"statsOutboundDownlink": "Statistik Unduh Keluar",
"statsOutboundDownlinkDesc": "Mengaktifkan pengumpulan statistik untuk lalu lintas unduh dari semua proxy keluar.",
"connectionLimits": "Batas Koneksi",
"connectionLimitsDesc": "Kebijakan tingkat koneksi untuk level pengguna 0. Biarkan kolom kosong untuk menggunakan nilai bawaan Xray.",
"connIdle": "Batas Waktu Idle",
@@ -1552,18 +1421,10 @@
"bufferSizePlaceholder": "otomatis",
"seconds": "detik",
"rules": {
"first": "Pertama",
"last": "Terakhir",
"up": "Naik",
"down": "Turun",
"source": "Sumber",
"dest": "Tujuan",
"inbound": "Masuk",
"outbound": "Keluar",
"balancer": "Pengimbang",
"info": "Info",
"add": "Tambahkan Aturan",
"edit": "Edit Aturan",
"useComma": "Item yang dipisahkan koma"
},
"routing": {
@@ -1604,7 +1465,6 @@
"ruleN": "Aturan {n}",
"action": "Aksi",
"redirect": "Redirect",
"fragment": "Fragment",
"finalRules": "Aturan akhir",
"overrideXrayPrivateIp": "Timpa blok IP privat default Xray",
"blockDelay": "Penundaan blokir (ms)",
@@ -1630,43 +1490,17 @@
"keepAliveInterval": "Interval keep alive",
"markFwmark": "Mark (fwmark)",
"interface": "Interface",
"ipv6Only": "Hanya IPv6",
"acceptProxyProtocol": "Terima proxy protocol",
"proxyProtocol": "Proxy protocol",
"tcpUserTimeoutMs": "TCP user timeout (ms)",
"tcpKeepAliveIdleS": "TCP keep-alive idle (d)"
},
"outbound": {
"addOutbound": "Tambahkan Keluar",
"addReverse": "Tambahkan Revers",
"editOutbound": "Edit Keluar",
"editReverse": "Edit Revers",
"reverseTag": "Tag Revers",
"reverseTagDesc": "Tag outbound proxy revers sederhana VLESS. Kosongkan untuk menonaktifkan.",
"reverseTagPlaceholder": "tag outbound (kosong untuk menonaktifkan)",
"tag": "Tag",
"tagDesc": "Tag Unik",
"address": "Alamat",
"egress": "Egress",
"egressHint": "Run an HTTP test to show egress IP and country.",
"reverse": "Revers",
"domain": "Domain",
"type": "Tipe",
"bridge": "Bridge",
"portal": "Portal",
"link": "Tautan",
"intercon": "Interkoneksi",
"settings": "Pengaturan",
"accountInfo": "Informasi Akun",
"outboundStatus": "Status Keluar",
"sendThrough": "Kirim Melalui",
"targetStrategy": "Strategi Target",
"test": "Tes",
"testResult": "Hasil Tes",
"testing": "Menguji koneksi...",
"testSuccess": "Tes berhasil",
"testFailed": "Tes gagal",
"testError": "Gagal menguji outbound",
"modeRealDelay": "Delay nyata",
"testModeTooltip": "TCP: probe dial-only cepat. HTTP: permintaan penuh via xray. Delay nyata: total waktu termasuk pembentukan koneksi.",
"testAll": "Tes semua",
@@ -1674,14 +1508,10 @@
"breakdownConnect": "Koneksi proxy",
"breakdownTls": "TLS melalui outbound",
"breakdownTtfb": "Byte pertama",
"nordvpn": "NordVPN",
"accessToken": "Token Akses",
"country": "Negara",
"server": "Server",
"city": "Kota",
"allCities": "Semua Kota",
"privateKey": "Kunci Privat",
"load": "Beban",
"moveToTop": "Pindahkan ke atas"
},
"outboundSub": {
@@ -1711,16 +1541,11 @@
"active": "Langganan aktif",
"empty": "Belum ada langganan. Tambahkan satu di atas.",
"colRemark": "Catatan",
"colPrefix": "Awalan",
"colInterval": "Interval",
"colLastFetch": "Pengambilan terakhir",
"colEnabled": "Aktif",
"auto": "otomatis",
"never": "tidak pernah",
"yes": "Ya",
"no": "Tidak",
"refreshNow": "Segarkan sekarang",
"lastError": "Kesalahan terakhir",
"deleteConfirm": "Hapus langganan ini?",
"restartHint": "Setelah menambahkan atau menyegarkan, mulai ulang Xray (atau tunggu muat ulang otomatis berikutnya) agar outbound menjadi aktif.",
"fromSubsTitle": "Dari langganan outbound (hanya-baca)",
@@ -1737,8 +1562,6 @@
"tabBalancerSettings": "Pengaturan Balancer",
"tabObservatory": "Observatory",
"observatory": {
"title": "Observatory",
"burstTitle": "Burst Observatory",
"autoManaged": "Observer dikelola otomatis dari balancer Anda. Atur cara mereka melakukan probe di bawah; outbound yang dipantau mengikuti selector balancer.",
"emptyHint": "Tidak ada observer koneksi yang aktif. Satu akan ditambahkan otomatis saat Anda membuat balancer Least Ping atau Least Load — atau balancer Random / Round-robin dengan fallback — sehingga balancer yang memakai observer dapat memeriksa kesehatan outbound sebelum memilih target.",
"mixedLegacy": "Konfigurasi ini berisi Observatory dan Burst Observatory sekaligus. Xray memakai satu observer global, jadi status campuran lama ini tidak didukung; menyimpan balancer akan menormalkannya menjadi satu observer.",
@@ -1772,12 +1595,8 @@
"balancerRemoved": "Balancer {tag} — dihapus (tidak ada target tersisa)"
},
"balancer": {
"addBalancer": "Tambahkan Penyeimbang",
"editBalancer": "Sunting Penyeimbang",
"balancerStrategy": "Strategi",
"balancerSelectors": "Penyeleksi",
"tag": "Tag",
"tagDesc": "Label Unik",
"tagDuplicate": "Tag sudah digunakan oleh balancer lain",
"tagPlaceholder": "tag balancer unik",
"selector": "Selector",
@@ -1789,7 +1608,6 @@
"tolerance": "Toleransi",
"baselines": "Baselines",
"costs": "Costs",
"balancerDesc": "BalancerTag dan outboundTag tidak dapat digunakan secara bersamaan. Jika digunakan secara bersamaan, hanya outboundTag yang akan berfungsi.",
"costMatch": "Pola tag",
"costValue": "Bobot",
"costRegexp": "Pencocokan ekspresi reguler",
@@ -1804,14 +1622,10 @@
"publicKey": "Kunci Publik",
"allowedIPs": "IP yang Diizinkan",
"endpoint": "Titik Akhir",
"psk": "Kunci Pra-Bagi",
"domainStrategy": "Strategi Domain"
},
"tun": {
"nameDesc": "Nama antarmuka TUN. Standar adalah 'xray0'",
"mtuDesc": "Unit Transmisi Maksimum. Ukuran maksimum paket data. Standar adalah 1500",
"userLevel": "Level Pengguna",
"userLevelDesc": "Semua koneksi yang dibuat melalui inbound ini akan menggunakan level pengguna ini. Standar adalah 0"
"userLevel": "Level Pengguna"
},
"nord": {
"accessToken": "Access token",
@@ -1896,7 +1710,6 @@
},
"fakedns": {
"add": "Tambahkan DNS Palsu",
"edit": "Edit DNS Palsu",
"ipPool": "Subnet Kumpulan IP",
"poolSize": "Ukuran Kolam"
},
@@ -2032,7 +1845,6 @@
"add": "Tambah",
"month": "Bulan",
"months": "Bulan",
"day": "Hari",
"days": "Hari",
"hours": "Jam",
"minutes": "Menit",
@@ -2071,7 +1883,6 @@
"userSaved": "✅ Pengguna Telegram tersimpan.",
"loginSuccess": "✅ Berhasil masuk ke panel.\r\n",
"loginFailed": "❗️ Gagal masuk ke panel.\r\n",
"2faFailed": "2FA Gagal",
"report": "🕰 Laporan Terjadwal: {{ .RunTime }}\r\n",
"datetime": "⏰ Tanggal & Waktu: {{ .DateTime }}\r\n",
"hostname": "💻 Host: {{ .Hostname }}\r\n",
@@ -2104,7 +1915,6 @@
"download": "🔽 Unduh: ↓{{ .Download }}\r\n",
"total": "📊 Total: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
"TGUser": "👤 Pengguna Telegram: {{ .TelegramID }}\r\n",
"exhaustedMsg": "🚨 Habis {{ .Type }}:\r\n",
"exhaustedCount": "🚨 Jumlah Habis {{ .Type }}:\r\n",
"onlinesCount": "🌐 Klien Online: {{ .Count }}\r\n",
"disabled": "🛑 Dinonaktifkan: {{ .Disabled }}\r\n",
@@ -2113,16 +1923,10 @@
"refreshedOn": "\r\n📋🔄 Diperbarui Pada: {{ .Time }}\r\n\r\n",
"yes": "✅ Ya",
"no": "❌ Tidak",
"received_id": "🔑📥 ID diperbarui.",
"received_password": "🔑📥 Kata sandi diperbarui.",
"received_email": "📧📥 Email diperbarui.",
"received_comment": "💬📥 Komentar diperbarui.",
"id_prompt": "🔑 ID Default: {{ .ClientId }}\n\nMasukkan ID Anda.",
"pass_prompt": "🔑 Kata Sandi Default: {{ .ClientPassword }}\n\nMasukkan kata sandi Anda.",
"email_prompt": "📧 Email Default: {{ .ClientEmail }}\n\nMasukkan email Anda.",
"comment_prompt": "💬 Komentar Default: {{ .ClientComment }}\n\nMasukkan komentar Anda.",
"inbound_client_data_id": "🔄 Masuk: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Lalu lintas: {{ .ClientTraffic }}\n📅 Tanggal Kedaluwarsa: {{ .ClientExp }}\n🌐 Batas IP: {{ .IpLimit }}\n💬 Komentar: {{ .ClientComment }}\n\nSekarang kamu bisa menambahkan klien ke inbound!",
"inbound_client_data_pass": "🔄 Masuk: {{ .InboundRemark }}\n\n🔑 Kata sandi: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Lalu lintas: {{ .ClientTraffic }}\n📅 Tanggal Kedaluwarsa: {{ .ClientExp }}\n🌐 Batas IP: {{ .IpLimit }}\n💬 Komentar: {{ .ClientComment }}\n\nSekarang kamu bisa menambahkan klien ke inbound!",
"cancel": "❌ Proses Dibatalkan! \n\nAnda dapat /start lagi kapan saja. 🔄",
"error_add_client": "⚠️ Error:\n\n {{ .error }}",
"using_default_value": "Oke, saya akan tetap menggunakan nilai default. 😊",
@@ -2139,8 +1943,6 @@
"eventXrayCrashError": "Kesalahan: {{ .Error }}",
"eventNodeDown": "Node {{ .Name }} MATI",
"eventNodeUp": "Node {{ .Name }} AKTIF",
"eventCPUHigh": "CPU tinggi",
"eventCPUHighDetail": "CPU: {{ .Detail }}",
"eventLoginFallback": "Gagal masuk dari {{ .Source }}",
"memoryThreshold": "Penggunaan memori {{ .Percent }}% melebihi ambang batas {{ .Threshold }}%"
},
@@ -2181,11 +1983,8 @@
"submitDisable": "Kirim Sebagai Nonaktif ☑️",
"submitEnable": "Kirim Sebagai Aktif ✅",
"use_default": "🏷️ Gunakan Default",
"change_id": "⚙️🔑 ID",
"change_password": "⚙️🔑 Kata Sandi",
"change_email": "⚙️📧 Email",
"change_comment": "⚙️💬 Komentar",
"change_flow": "⚙️🚦 Flow",
"ResetAllTraffics": "Reset Semua Lalu Lintas",
"SortedTrafficUsageReport": "Laporan Penggunaan Lalu Lintas yang Terurut"
},
@@ -2214,31 +2013,16 @@
}
},
"email": {
"subjectOutboundDown": "Outbound {{ .Tag }} MATI",
"subjectOutboundUp": "Outbound {{ .Tag }} AKTIF",
"subjectXrayCrash": "Xray CRASH",
"subjectCPUHigh": "CPU tinggi",
"subjectLoginSuccess": "Berhasil masuk",
"subjectLoginFailed": "Gagal masuk",
"titleOutboundDown": "Outbound MATI",
"titleOutboundUp": "Outbound AKTIF",
"titleXrayCrash": "Xray CRASH",
"titleCPUHigh": "CPU tinggi",
"titleLoginSuccess": "Berhasil masuk",
"titleLoginFailed": "Gagal masuk",
"labelStatus": "Status",
"labelOutbound": "Outbound",
"labelNode": "Node",
"labelError": "Kesalahan",
"labelDelay": "Penundaan",
"labelDetail": "Detail",
"labelUsername": "Nama Pengguna",
"labelIP": "IP",
"labelReason": "Alasan",
"labelSource": "Sumber",
"labelTime": "Waktu",
"statusCrashed": "CRASH",
"statusRunning": "Berjalan",
"statusHigh": "TINGGI",
"statusSuccess": "BERHASIL",
"statusFailed": "GAGAL",