feat: localize all hardcoded strings in Root CA Management and Archive UI

This commit is contained in:
dyzulk
2026-01-07 10:58:15 +07:00
parent 8ff136d086
commit a1c38e4ab2
6 changed files with 92 additions and 36 deletions

View File

@@ -62,25 +62,21 @@ export default function RootCaManagementClient() {
setActiveSync(syncKey);
try {
let endpoint = "/api/admin/ca-certificates/sync-cdn";
let msg = `Sync successful (Mode: ${mode})`;
if (type === 'crt') {
endpoint = "/api/admin/ca-certificates/sync-crt";
msg = `CRT Files Sync successful (${mode})`;
} else if (type === 'installers') {
endpoint = "/api/admin/ca-certificates/sync-installers";
msg = `Individual Installers Sync successful (${mode})`;
} else if (type === 'bundles') {
endpoint = "/api/admin/ca-certificates/sync-bundles";
msg = "Global Bundles Sync successful";
}
const response = await axios.post(endpoint, { mode });
addToast(response.data.message || msg, "success");
addToast(response.data.message || t("toast_sync_success"), "success");
mutate();
} catch (err: any) {
console.error(err);
addToast(err.response?.data?.message || "Sync failed", "error");
addToast(err.response?.data?.message || t("toast_sync_failed"), "error");
} finally {
setActiveSync(null);
}
@@ -90,11 +86,11 @@ export default function RootCaManagementClient() {
setIsPromoting(true);
try {
const response = await axios.post(`/api/admin/ca-certificates/${uuid}/promote`);
addToast(response.data.message || "Promoted successfully", "success");
addToast(response.data.message || t("toast_promote_success"), "success");
mutate();
} catch (err: any) {
console.error(err);
addToast(err.response?.data?.message || "Promotion failed", "error");
addToast(err.response?.data?.message || t("toast_promote_failed"), "error");
} finally {
setIsPromoting(false);
}
@@ -192,8 +188,8 @@ export default function RootCaManagementClient() {
{/* Full-width Archive History */}
<ComponentCard
title="Version Archives"
desc="Browse historical versions and promote them back to Latest if needed. This table provides full visibility into your CDN audit trail."
title={t("archive_management_title")}
desc={t("archive_management_desc")}
>
<ArchiveManagementTable
certificates={certificates}

View File

@@ -72,10 +72,10 @@ export default function ArchiveManagementTable({
<div className="space-y-4">
{/* Table Header Controls */}
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between px-1">
<h4 className="text-sm font-bold text-gray-800 dark:text-white/90">CDN Archive History</h4>
<h4 className="text-sm font-bold text-gray-800 dark:text-white/90">{t("archive_history_title")}</h4>
<div className="w-full sm:w-64">
<InputField
placeholder="Search version/CN..."
placeholder={t("archive_search_placeholder")}
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="!py-2"
@@ -89,10 +89,10 @@ export default function ArchiveManagementTable({
<TableHeader className="border-b border-gray-100 dark:border-white/[0.05]">
<TableRow>
<TableCell isHeader className="px-5 py-3 font-medium text-gray-500 text-start text-theme-xs dark:text-gray-400">
Version (UUID)
{t("th_version_uuid")}
</TableCell>
<TableCell isHeader className="px-5 py-3 font-medium text-gray-500 text-start text-theme-xs dark:text-gray-400">
Family
{t("th_family")}
</TableCell>
<TableCell isHeader className="px-5 py-3 font-medium text-gray-500 text-start text-theme-xs dark:text-gray-400">
{t("common_name_th")}
@@ -104,7 +104,7 @@ export default function ArchiveManagementTable({
{t("validity_th")}
</TableCell>
<TableCell isHeader className="px-5 py-3 font-medium text-gray-500 text-start text-theme-xs dark:text-gray-400">
Status
{t("th_status")}
</TableCell>
<TableCell isHeader className="px-5 py-3 font-medium text-gray-500 text-center text-theme-xs dark:text-gray-400">
{t("actions_th")}
@@ -121,12 +121,12 @@ export default function ArchiveManagementTable({
{cert.last_synced_at ? (
<div className="flex items-center gap-1.5">
<span className="flex h-1.5 w-1.5 rounded-full bg-success-500"></span>
<span className="text-[9px] text-success-600 font-bold uppercase tracking-wider">Synced to CDN</span>
<span className="text-[9px] text-success-600 font-bold uppercase tracking-wider">{t("status_synced")}</span>
</div>
) : (
<div className="flex items-center gap-1.5 opacity-60">
<span className="flex h-1.5 w-1.5 rounded-full bg-warning-500"></span>
<span className="text-[9px] text-warning-600 font-bold uppercase tracking-wider">Local Only</span>
<span className="text-[9px] text-warning-600 font-bold uppercase tracking-wider">{t("status_local")}</span>
</div>
)}
</div>
@@ -181,11 +181,11 @@ export default function ArchiveManagementTable({
onClick={() => onPromote(cert.uuid)}
loading={isPromoting}
>
Set as Latest
{t("btn_set_latest")}
</Button>
)}
{cert.is_latest && (
<span className="text-[10px] text-gray-400 font-medium">Currently Public</span>
<span className="text-[10px] text-gray-400 font-medium">{t("status_currently_public")}</span>
)}
</TableCell>
</TableRow>
@@ -193,7 +193,7 @@ export default function ArchiveManagementTable({
{filteredAndSortedCertificates.length === 0 && (
<TableRow>
<TableCell colSpan={7} className="px-5 py-10 text-center text-gray-500 dark:text-gray-400">
No versions found.
{t("no_archives_found")}
</TableCell>
</TableRow>
)}

View File

@@ -60,7 +60,7 @@ export default function CdnManagementCard({ onSync, activeSync, disabled }: CdnM
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" />
</svg>
)}
{isLoading ? "Syncing..." : "Sync Now"}
{isLoading ? t("syncing_label") : t("sync_now_btn")}
</button>
</div>
</div>
@@ -79,22 +79,22 @@ export default function CdnManagementCard({ onSync, activeSync, disabled }: CdnM
<SyncButton
type="crt"
mode="both"
label="Update CRT Only"
desc="Hanya unggah file sertifikat publik (.crt, .der)."
label={t("label_update_crt")}
desc={t("desc_update_crt")}
variant="blue"
/>
<SyncButton
type="installers"
mode="both"
label="Update Scripts Only"
desc="Hanya perbarui skrip installer individual (.sh, .bat, .mac)."
label={t("label_update_scripts")}
desc={t("desc_update_scripts")}
variant="purple"
/>
<SyncButton
type="bundles"
mode="latest"
label="Update Global Bundles"
desc="Perbarui paket installer sapujagat (Recommended)."
label={t("label_update_bundles")}
desc={t("desc_update_bundles")}
variant="success"
/>
</div>
@@ -109,22 +109,22 @@ export default function CdnManagementCard({ onSync, activeSync, disabled }: CdnM
<SyncButton
type="all"
mode="both"
label="Dual Sync (Latest & Archive)"
desc="Sinkronisasi massal ke kedua jalur. Paling aman untuk integritas data."
label={t("label_dual_sync")}
desc={t("desc_dual_sync")}
variant="indigo"
/>
<SyncButton
type="all"
mode="latest"
label="Latest Sync (Clean URLs)"
desc="Hanya perbarui link publik utama pendukung installer."
label={t("label_latest_sync")}
desc={t("desc_latest_sync")}
variant="blue"
/>
<SyncButton
type="all"
mode="archive"
label="Archive Sync (Versioned)"
desc="Hanya simpan arsip permanen tanpa mengubah link publik."
label={t("label_archive_sync")}
desc={t("desc_archive_sync")}
variant="gray"
/>
</div>

View File

@@ -80,7 +80,7 @@ export default function RootCaTable({
{t("type_th")}
</TableCell>
<TableCell isHeader className="px-5 py-3 font-medium text-gray-500 text-start text-theme-xs dark:text-gray-400">
Family
{t("th_family")}
</TableCell>
<TableCell isHeader className="px-5 py-3 font-medium text-gray-500 text-start text-theme-xs dark:text-gray-400">
{t("common_name_th")}

View File

@@ -676,7 +676,37 @@
"self_signed": "Self-Signed",
"renew_button": "Renew",
"no_ca_search": "No CAs matched \"{term}\"",
"no_ca_found": "No Root CA certificates found. Start by initializing the Certification Authority."
"no_ca_found": "No Root CA certificates found. Start by initializing the Certification Authority.",
"archive_history_title": "CDN Archive History",
"archive_search_placeholder": "Search version/CN...",
"th_version_uuid": "Version (UUID)",
"th_family": "Family",
"th_status": "Status",
"status_synced": "Synced to CDN",
"status_local": "Local Only",
"btn_set_latest": "Set as Latest",
"status_currently_public": "Currently Public",
"no_archives_found": "No versions found.",
"archive_management_title": "Version Archives",
"archive_management_desc": "Browse historical versions and promote them back to Latest if needed. This table provides full visibility into your CDN audit trail.",
"toast_sync_success": "Synchronization successful",
"toast_sync_failed": "Synchronization failed",
"toast_promote_success": "Promoted to latest successfully",
"toast_promote_failed": "Failed to promote version",
"syncing_label": "Syncing...",
"sync_now_btn": "Sync Now",
"label_update_crt": "Update CRT Only",
"desc_update_crt": "Only upload public certificate files (.crt, .der).",
"label_update_scripts": "Update Scripts Only",
"desc_update_scripts": "Only update individual installer scripts (.sh, .bat, .mac).",
"label_update_bundles": "Update Global Bundles",
"desc_update_bundles": "Update all-in-one installer packages (Recommended).",
"label_dual_sync": "Dual Sync (Latest & Archive)",
"desc_dual_sync": "Bulk sync to both paths. Safest for data integrity.",
"label_latest_sync": "Latest Sync (Clean URLs)",
"desc_latest_sync": "Only update the primary public links for installers.",
"label_archive_sync": "Archive Sync (Versioned)",
"desc_archive_sync": "Only save permanent archives without changing public links."
},
"SmtpTester": {
"page_title": "SMTP Tester",

View File

@@ -676,7 +676,37 @@
"self_signed": "Self-Signed",
"renew_button": "Perbarui",
"no_ca_search": "Tidak ada CA yang cocok dengan \"{term}\"",
"no_ca_found": "Sertifikat Root CA tidak ditemukan. Mulailah dengan menginisialisasi Certification Authority."
"no_ca_found": "Sertifikat Root CA tidak ditemukan. Mulailah dengan menginisialisasi Certification Authority.",
"archive_history_title": "Riwayat Arsip CDN",
"archive_search_placeholder": "Cari versi/CN...",
"th_version_uuid": "Versi (UUID)",
"th_family": "Keluarga",
"th_status": "Status",
"status_synced": "Tersinkronisasi ke CDN",
"status_local": "Hanya Lokal",
"btn_set_latest": "Jadikan Terbaru",
"status_currently_public": "Publik Saat Ini",
"no_archives_found": "Versi tidak ditemukan.",
"archive_management_title": "Arsip Versi",
"archive_management_desc": "Telusuri versi historis dan jadikan kembali sebagai Versi Terbaru jika diperlukan. Tabel ini memberikan visibilitas penuh terhadap jejak audit CDN Anda.",
"toast_sync_success": "Sinkronisasi berhasil",
"toast_sync_failed": "Sinkronisasi gagal",
"toast_promote_success": "Berhasil dijadikan versi terbaru",
"toast_promote_failed": "Gagal menjadikan versi terbaru",
"syncing_label": "Menyinkronkan...",
"sync_now_btn": "Sinkronisasi",
"label_update_crt": "Perbarui CRT Saja",
"desc_update_crt": "Hanya unggah file sertifikat publik (.crt, .der).",
"label_update_scripts": "Perbarui Skrip Saja",
"desc_update_scripts": "Hanya perbarui skrip installer individual (.sh, .bat, .mac).",
"label_update_bundles": "Perbarui Paket Global",
"desc_update_bundles": "Perbarui paket installer sapujagat (Disarankan).",
"label_dual_sync": "Sinkronisasi Ganda (Terbaru & Arsip)",
"desc_dual_sync": "Sinkronisasi massal ke kedua jalur. Paling aman untuk integritas data.",
"label_latest_sync": "Sinkronisasi Terbaru (URL Bersih)",
"desc_latest_sync": "Hanya perbarui link publik utama pendukung installer.",
"label_archive_sync": "Sinkronisasi Arsip (Versi)",
"desc_archive_sync": "Hanya simpan arsip permanen tanpa mengubah link publik."
},
"SmtpTester": {
"page_title": "Pengetes SMTP",