From 1cea96f09f14fa2a2825f751b239bfbaead6e662 Mon Sep 17 00:00:00 2001 From: "Dedy F. Setyawan" Date: Fri, 12 Jun 2026 15:08:58 +0700 Subject: [PATCH] feat(react-ui): add Indonesian language support (#10266) Signed-off-by: Dedy F. Setyawan --- core/http/react-ui/i18next-parser.config.js | 2 +- .../react-ui/public/locales/id/admin.json | 85 ++++++++++ .../react-ui/public/locales/id/agents.json | 55 +++++++ .../http/react-ui/public/locales/id/auth.json | 112 +++++++++++++ .../http/react-ui/public/locales/id/chat.json | 117 +++++++++++++ .../public/locales/id/collections.json | 43 +++++ .../react-ui/public/locales/id/common.json | 109 +++++++++++++ .../react-ui/public/locales/id/errors.json | 17 ++ .../http/react-ui/public/locales/id/home.json | 66 ++++++++ .../public/locales/id/importModel.json | 142 ++++++++++++++++ .../react-ui/public/locales/id/media.json | 154 ++++++++++++++++++ .../react-ui/public/locales/id/models.json | 93 +++++++++++ core/http/react-ui/public/locales/id/nav.json | 54 ++++++ .../react-ui/public/locales/id/skills.json | 79 +++++++++ .../react-ui/scripts/translate-locales.mjs | 5 +- core/http/react-ui/src/i18n/index.js | 1 + 16 files changed, 1131 insertions(+), 3 deletions(-) create mode 100644 core/http/react-ui/public/locales/id/admin.json create mode 100644 core/http/react-ui/public/locales/id/agents.json create mode 100644 core/http/react-ui/public/locales/id/auth.json create mode 100644 core/http/react-ui/public/locales/id/chat.json create mode 100644 core/http/react-ui/public/locales/id/collections.json create mode 100644 core/http/react-ui/public/locales/id/common.json create mode 100644 core/http/react-ui/public/locales/id/errors.json create mode 100644 core/http/react-ui/public/locales/id/home.json create mode 100644 core/http/react-ui/public/locales/id/importModel.json create mode 100644 core/http/react-ui/public/locales/id/media.json create mode 100644 core/http/react-ui/public/locales/id/models.json create mode 100644 core/http/react-ui/public/locales/id/nav.json create mode 100644 core/http/react-ui/public/locales/id/skills.json diff --git a/core/http/react-ui/i18next-parser.config.js b/core/http/react-ui/i18next-parser.config.js index 1db8d4a25..ff3706aec 100644 --- a/core/http/react-ui/i18next-parser.config.js +++ b/core/http/react-ui/i18next-parser.config.js @@ -1,5 +1,5 @@ export default { - locales: ['en', 'it', 'es', 'de', 'zh-CN'], + locales: ['en', 'it', 'es', 'de', 'zh-CN', 'id'], defaultNamespace: 'common', output: 'public/locales/$LOCALE/$NAMESPACE.json', input: ['src/**/*.{js,jsx}'], diff --git a/core/http/react-ui/public/locales/id/admin.json b/core/http/react-ui/public/locales/id/admin.json new file mode 100644 index 000000000..5e83eb37f --- /dev/null +++ b/core/http/react-ui/public/locales/id/admin.json @@ -0,0 +1,85 @@ +{ + "manage": { + "title": "Sistem", + "subtitle": "Kelola model dan backend yang terinstal" + }, + "settings": { + "title": "Pengaturan", + "subtitle": "Konfigurasi pengaturan runtime LocalAI", + "saved": "Pengaturan berhasil disimpan", + "saveFailed": "Gagal menyimpan: {{message}}", + "loadFailed": "Gagal memuat pengaturan: {{message}}", + "sections": { + "branding": "Branding", + "watchdog": "Watchdog", + "memory": "Memori", + "backends": "Backend", + "performance": "Performa", + "tracing": "Tracing", + "api": "API & CORS", + "p2p": "P2P", + "galleries": "Galeri", + "apikeys": "API Key", + "agents": "Agent Job", + "agentpool": "Agent Pool", + "assistant": "Asisten LocalAI", + "responses": "Respons" + } + }, + "backends": { + "title": "Manajemen Backend", + "subtitle": "Temukan dan instal backend AI untuk mendukung model Anda" + }, + "backendLogs": { + "title": "Log Backend", + "subtitle": "Lihat log dari backend yang sedang berjalan", + "empty": "Tidak ada log yang tersedia" + }, + "traces": { + "title": "Trace", + "subtitle": "Lihat log permintaan API, respons, dan operasi backend" + }, + "nodes": { + "title": "Node Terdistribusi", + "subtitle": "Kelola node backend dan node worker" + }, + "p2p": { + "title": "Komputasi AI Terdistribusi", + "subtitle": "Skalakan beban kerja AI Anda ke beberapa perangkat dengan distribusi peer-to-peer" + }, + "users": { + "title": "Pengguna", + "subtitle": "Kelola pengguna terdaftar, peran, dan undangan" + }, + "usage": { + "title": "Penggunaan", + "subtitle": "Statistik penggunaan token API", + "sources": { + "tab": "Sumber", + "mixTitle": "Campuran sumber", + "ribbonAria": "{{apikey}}% API Key, {{web}}% Web UI, {{legacy}}% Legasi", + "topSources": "Sumber teratas dari waktu ke waktu", + "searchPlaceholder": "Cari berdasarkan nama atau awalan", + "sortBy": "Urutkan", + "sortTokens": "Token", + "sortRequests": "Permintaan", + "sortLastUsed": "Terakhir digunakan", + "sortName": "Nama", + "sortUser": "Pengguna", + "webUI": "Web UI", + "legacy": "Legasi", + "revoked": " dicabut", + "filteredTo": "Difilter ke: {{name}}", + "clearFilter": "Hapus filter", + "other": "Lainnya ({{count}})", + "noTrafficShort": "Tidak ada permintaan dalam periode ini.", + "noKeysYet": "Setelah permintaan masuk, Anda akan melihat rinciannya di sini.", + "createKey": "Buat API Key pertama Anda", + "truncatedWarning": "Menampilkan 200 key teratas. Terapkan filter untuk mempersempit pencarian." + } + }, + "explorer": { + "title": "Penjelajah", + "subtitle": "Jelajahi file dan konfigurasi" + } +} \ No newline at end of file diff --git a/core/http/react-ui/public/locales/id/agents.json b/core/http/react-ui/public/locales/id/agents.json new file mode 100644 index 000000000..7431bc417 --- /dev/null +++ b/core/http/react-ui/public/locales/id/agents.json @@ -0,0 +1,55 @@ +{ + "title": "Agen", + "subtitle": "Kelola agen AI otonom", + "actions": { + "agentHub": "Pusat Agen", + "import": "Impor", + "createAgent": "Buat Agen", + "edit": "Edit", + "chat": "Obrolan", + "export": "Ekspor", + "delete": "Hapus", + "pause": "Jeda", + "resume": "Lanjutkan" + }, + "table": { + "name": "Nama", + "status": "Status", + "events": "Event", + "actions": "Aksi", + "eventsTooltip": "{{count}} event - Klik untuk melihat" + }, + "search": { + "placeholder": "Cari agen...", + "summary_one": "{{shown}} dari {{total}} agen", + "summary_other": "{{shown}} dari {{total}} agen" + }, + "empty": { + "noConfigured": "Belum ada agen yang dikonfigurasi", + "noConfiguredText": "Buat agen untuk memulai alur kerja AI otonom.", + "browseHub": "Tidak tahu harus mulai dari mana? Jelajahi <1>Pusat Agen untuk menemukan konfigurasi agen siap pakai yang bisa Anda impor.", + "noMatching": "Tidak ada agen yang cocok", + "noMatchingText": "Tidak ada agen yang cocok dengan \"{{query}}\"" + }, + "sections": { + "yourAgents": "Agent Anda", + "otherUsersAgents": "Agent Pengguna Lain" + }, + "deleteDialog": { + "title": "Hapus Agen", + "message": "Hapus agen \"{{name}}\"? Tindakan ini tidak dapat dibatalkan.", + "confirm": "Hapus" + }, + "toasts": { + "loadFailed": "Gagal memuat agen: {{message}}", + "deleted": "Agen \"{{name}}\" berhasil dihapus", + "deleteFailed": "Gagal menghapus agen: {{message}}", + "paused": "Agen \"{{name}}\" dijeda", + "resumed": "Agen \"{{name}}\" dilanjutkan", + "pauseFailed": "Gagal menjeda agen: {{message}}", + "resumeFailed": "Gagal melanjutkan agen: {{message}}", + "exported": "Agen \"{{name}}\" berhasil diekspor", + "exportFailed": "Gagal mengekspor agen: {{message}}", + "parseFailed": "Gagal melakukan parse file agen: {{message}}" + } +} \ No newline at end of file diff --git a/core/http/react-ui/public/locales/id/auth.json b/core/http/react-ui/public/locales/id/auth.json new file mode 100644 index 000000000..ca5387e18 --- /dev/null +++ b/core/http/react-ui/public/locales/id/auth.json @@ -0,0 +1,112 @@ +{ + "login": { + "subtitle": "Masuk untuk melanjutkan", + "registerSubtitle": "Buat akun", + "createAdminSubtitle": "Buat akun admin Anda", + "tokenSubtitle": "Masukkan API key Anda untuk melanjutkan", + "email": "Email", + "emailPlaceholder": "anda@example.com", + "name": "Nama", + "namePlaceholder": "Nama Anda (opsional)", + "password": "Kata Sandi", + "passwordPlaceholder": "Masukkan kata sandi...", + "newPasswordPlaceholder": "Minimal 12 karakter", + "confirmPassword": "Konfirmasi Kata Sandi", + "confirmPasswordPlaceholder": "Ulangi kata sandi", + "inviteCodeLabel": "Kode Undangan", + "inviteCodeOptional": " (opsional — lewati waktu tunggu persetujuan)", + "inviteCodePlaceholder": "Tempel kode undangan Anda...", + "tokenPlaceholder": "Masukkan API key...", + "tokenAltPlaceholder": "Masukkan token API...", + "signIn": "Masuk", + "signingIn": "Sedang masuk...", + "register": "Daftar", + "creatingAccount": "Membuat akun...", + "createAdminAccount": "Buat Akun Admin", + "signInWithGitHub": "Masuk dengan GitHub", + "signInWithSSO": "Masuk dengan SSO", + "loginWithToken": "Masuk dengan Token", + "showTokenLogin": "Masuk dengan Token API", + "hideTokenLogin": "Sembunyikan Token API", + "noAccount": "Belum punya akun?", + "hasAccount": "Sudah punya akun?", + "or": "atau", + "errors": { + "loginFailed": "Gagal masuk", + "registrationFailed": "Gagal mendaftar", + "invalidToken": "Token tidak valid", + "passwordsDoNotMatch": "Kata sandi tidak cocok", + "enterToken": "Silahkan masukkan token", + "networkError": "Eror jaringan", + "inviteRequired": "Kode undangan yang valid diperlukan untuk mendaftar" + }, + "messages": { + "registrationPending": "Pendaftaran berhasil, menunggu persetujuan." + } + }, + "account": { + "title": "Akun", + "subtitle": "Profil, kredensial, dan API key", + "unavailable": "Akun tidak tersedia", + "unavailableText": "Autentikasi harus diaktifkan untuk mengelola akun Anda.", + "tabs": { + "profile": "Profil", + "security": "Keamanan", + "apiKeys": "API Key" + }, + "profile": { + "displayName": "Nama tampilan", + "displayNameDescription": "Nama tampilan publik Anda", + "avatarUrl": "URL Avatar", + "avatarUrlDescription": "URL ke gambar profil Anda", + "avatarUrlPlaceholder": "https://example.com/avatar.png", + "save": "Simpan", + "saving": "Menyimpan...", + "updated": "Profil berhasil diperbarui", + "updateFailed": "Gagal memperbarui profil: {{message}}" + }, + "security": { + "currentPassword": "Kata sandi saat ini", + "currentPasswordDescription": "Masukkan kata sandi Anda saat ini untuk memverifikasi identitas Anda", + "currentPasswordPlaceholder": "Kata sandi saat ini", + "newPassword": "Kata sandi baru", + "newPasswordDescription": "Minimal harus 12 karakter", + "newPasswordPlaceholder": "Kata sandi baru", + "confirmPassword": "Konfirmasi kata sandi", + "confirmPasswordDescription": "Masukkan kembali kata sandi baru Anda", + "confirmPasswordPlaceholder": "Konfirmasi kata sandi baru", + "changePassword": "Ubah kata sandi", + "changing": "Mengubah...", + "changed": "Kata sandi berhasil diubah", + "passwordsDoNotMatch": "Kata sandi tidak cocok", + "tooShort": "Kata sandi baru minimal harus 12 karakter", + "oauthOnly": "Manajemen kata sandi tidak tersedia untuk akun {{provider}}." + }, + "apiKeys": { + "create": "Buat API key", + "createDescription": "Buat key untuk akses terprogram", + "namePlaceholder": "Nama key (misal: my-app)", + "createButton": "Buat", + "creating": "Membuat...", + "createdToast": "API key berhasil dibuat", + "createFailed": "Gagal membuat API key: {{message}}", + "loadFailed": "Failed to load API keys: {{message}}", + "revoke": "Cabut", + "revokeKey": "Cabut key", + "revokeTitle": "Cabut API Key", + "revokeMessage": "Cabut API key \"{{name}}\"? Tindakan ini tidak dapat dibatalkan.", + "revoked": "API key dicabut", + "revokeFailed": "Gagal mencabut API key: {{message}}", + "copyNow": "Salin sekarang — key ini tidak akan ditampilkan lagi", + "copiedToast": "Berhasil disalin ke papan klip", + "copyFailed": "Gagal menyalin", + "empty": "Belum ada API key. Buat satu di atas untuk akses terprogram.", + "lastUsed": "terakhir digunakan {{date}}" + } + }, + "notFound": { + "title": "Halaman Tidak Ditemukan", + "text": "Sepertinya halaman yang Anda cari tidak ditemukan. Mari kembalikan ke halaman sebelumnya.", + "goHome": "Kembali ke Beranda" + } +} \ No newline at end of file diff --git a/core/http/react-ui/public/locales/id/chat.json b/core/http/react-ui/public/locales/id/chat.json new file mode 100644 index 000000000..079c84914 --- /dev/null +++ b/core/http/react-ui/public/locales/id/chat.json @@ -0,0 +1,117 @@ +{ + "activity": { + "thought": "Penalaran", + "tool": "Alat", + "result": "Hasil", + "toolResult": "Hasil {{name}}", + "thinking": "Berpikir..." + }, + "header": { + "manageModeTooltip": "Obrolan ini dapat menginstal model, mengedit konfigurasi, dan mengelola backend dengan berbicara melalui LocalAI.", + "modelInfo": "Info model", + "chatSettings": "Pengaturan Obrolan", + "modelInfoTitle": "Info model: {{model}}", + "editConfig": "Edit konfigurasi", + "close": "Tutup" + }, + "modelInfo": { + "backend": "Backend", + "modelFile": "File model", + "contextSize": "Ukuran konteks", + "threads": "Thread", + "mcp": "MCP", + "configured": "Dikonfigurasi", + "chatTemplate": "Templat Obrolan", + "yes": "Ya", + "gpuLayers": "Layer GPU" + }, + "context": { + "label": "Konteks: {{percent}}%", + "labelWithTokens": "Konteks: {{percent}}% ({{tokens}} tokens)" + }, + "settings": { + "title": "Pengaturan Obrolan", + "manageMode": "Mode Manajemen", + "manageModeDesc": "Izinkan obrolan ini menginstal model, mengganti backend, dan mengedit konfigurasi dengan berbicara melalui LocalAI.", + "systemPrompt": "System Prompt", + "systemPromptPlaceholder": "Anda adalah asisten yang membantu...", + "temperature": "Temperatur", + "topP": "Top P", + "topK": "Top K", + "contextSize": "Ukuran Konteks", + "contextSizePlaceholder": "2048", + "clearHistory": "Hapus riwayat obrolan" + }, + "empty": { + "manageTitle": "Kelola LocalAI dengan obrolan", + "manageText": "Izinkan untuk menginstal model, mengganti backend, mengedit konfigurasi, atau memeriksa status. Asisten akan merangkum tindakan dan menunggu konfirmasi Anda sebelum mengubah apa pun.", + "startTitle": "Mulai percakapan", + "readyText": "Siap untuk mengobrol dengan {{model}}", + "selectModelText": "Pilih model di atas untuk memulai", + "suggestionsManage": [ + "Apa saja yang terinstal?", + "Instal model obrolan", + "Tampilkan status sistem", + "Perbarui backend" + ], + "suggestionsChat": [ + "Jelaskan cara kerjanya", + "Bantu saya menulis kode", + "Rangkum dokumen", + "Gali ide" + ], + "recent": "Terbaru", + "noMessages": "Belum ada pesan", + "hintEnter": "Enter untuk mengirim", + "hintShiftEnter": "Shift+Enter untuk baris baru", + "hintAttach": "Lampirkan file" + }, + "errors": { + "viewTraces": "Lihat trace untuk detailnya" + }, + "actions": { + "copy": "Salin", + "regenerate": "Hasilkan ulang" + }, + "streaming": { + "transferring": "Mentransfer model...", + "transferringTo": "Mentransfer model ke {{node}}..." + }, + "tokens": { + "perSec": "{{count}} tok/s", + "peak": "Puncak: {{count}} tok/s", + "usage": "{{prompt}}p + {{completion}}c = {{total}}" + }, + "input": { + "placeholder": "Pesan...", + "attachFile": "Lampirkan file", + "stopGenerating": "Hentikan pembuatan", + "canvasTitle": "Canvas — ekstrak blok kode dan media ke panel samping untuk pratinjau, salin, dan unduh", + "canvasLabel": "Canvas", + "openCanvas": "Buka panel canvas" + }, + "deleteAllDialog": { + "title": "Hapus Semua Obrolan", + "message": "Hapus semua obrolan? Tindakan ini tidak dapat dibatalkan.", + "confirm": "Hapus semua" + }, + "toasts": { + "selectModel": "Silahkan pilih model", + "copied": "Berhasil disalin ke papan klip", + "copyFailed": "Gagal menyalin ke papan klip" + }, + "menu": { + "trigger": "Obrolan", + "triggerTitle": "Percakapan (Ctrl/Cmd+K)", + "search": "Cari percakapan...", + "clearSearch": "Hapus pencarian", + "noMatch": "Tidak ada percakapan yang cocok dengan pencarian Anda", + "noConversations": "Belum ada percakapan", + "rename": "Ubah nama", + "exportMarkdown": "Ekspor sebagai Markdown", + "deleteChat": "Hapus obrolan", + "newChat": "Obrolan baru", + "clearAll": "Hapus semua", + "deleteAllTitle": "Hapus semua percakapan" + } +} \ No newline at end of file diff --git a/core/http/react-ui/public/locales/id/collections.json b/core/http/react-ui/public/locales/id/collections.json new file mode 100644 index 000000000..36f70e570 --- /dev/null +++ b/core/http/react-ui/public/locales/id/collections.json @@ -0,0 +1,43 @@ +{ + "title": "Basis Pengetahuan", + "subtitle": "Kelola koleksi dokumen untuk agen RAG", + "newPlaceholder": "Nama koleksi baru...", + "actions": { + "create": "Buat", + "creating": "Membuat...", + "details": "Detail", + "reset": "Reset", + "delete": "Hapus", + "viewDetails": "Lihat detail", + "resetCollection": "Reset koleksi", + "deleteCollection": "Hapus koleksi" + }, + "sections": { + "yourCollections": "Koleksi Anda", + "otherUsersCollections": "Koleksi Pengguna Lain" + }, + "empty": { + "title": "Belum ada koleksi", + "text": "Koleksi memungkinkan Anda mengatur dokumen ke dalam basis pengetahuan yang dapat dicari oleh agen menggunakan RAG (Retrieval-Augmented Generation). Buat koleksi di atas untuk memulai.", + "noPersonal": "Anda belum memiliki koleksi." + }, + "deleteDialog": { + "title": "Hapus koleksi", + "message": "Hapus koleksi \"{{name}}\"? Tindakan ini akan menghapus semua entri dan tidak dapat dibatalkan.", + "confirm": "Hapus" + }, + "resetDialog": { + "title": "Reset koleksi", + "message": "Reset koleksi \"{{name}}\"? Tindakan ini akan menghapus semua entri tetapi mempertahankan koleksinya.", + "confirm": "Reset" + }, + "toasts": { + "loadFailed": "Gagal memuat koleksi: {{message}}", + "created": "Koleksi \"{{name}}\" berhasil dibuat", + "createFailed": "Gagal membuat koleksi: {{message}}", + "deleted": "Koleksi \"{{name}}\" berhasil dihapus", + "deleteFailed": "Gagal menghapus koleksi: {{message}}", + "reset": "Koleksi \"{{name}}\" berhasil direset", + "resetFailed": "Gagal mereset koleksi: {{message}}" + } +} \ No newline at end of file diff --git a/core/http/react-ui/public/locales/id/common.json b/core/http/react-ui/public/locales/id/common.json new file mode 100644 index 000000000..b20eeb00a --- /dev/null +++ b/core/http/react-ui/public/locales/id/common.json @@ -0,0 +1,109 @@ +{ + "actions": { + "save": "Simpan", + "saving": "Menyimpan...", + "cancel": "Batal", + "close": "Tutup", + "confirm": "Konfirmasi", + "delete": "Hapus", + "edit": "Edit", + "add": "Tambah", + "remove": "Hapus", + "create": "Buat", + "update": "Perbarui", + "refresh": "Segarkan", + "reload": "Muat Ulang", + "retry": "Coba Lagi", + "search": "Cari", + "filter": "Filter", + "clear": "Hapus", + "reset": "Reset", + "apply": "Terapkan", + "back": "Kembali", + "next": "Berikutnya", + "previous": "Sebelumnya", + "open": "Buka", + "submit": "Kirim", + "select": "Pilih", + "selectAll": "Pilih semua", + "copy": "Salin", + "copied": "Disalin", + "download": "Unduh", + "upload": "Unggah", + "import": "Impor", + "export": "Ekspor", + "view": "Lihat", + "details": "Detail", + "settings": "Pengaturan", + "help": "Bantuan", + "yes": "Ya", + "no": "Tidak", + "loading": "Memuat..." + }, + "status": { + "loading": "Memuat...", + "saving": "Menyimpan...", + "saved": "Tersimpan", + "ready": "Siap", + "running": "Berjalan", + "stopped": "Berhenti", + "starting": "Memulai...", + "stopping": "Menghentikan...", + "pending": "Pending", + "active": "Aktif", + "inactive": "Tidak aktif", + "enabled": "Diaktifkan", + "disabled": "Dinonaktifkan", + "online": "Online", + "offline": "Offline", + "error": "Eror", + "success": "Sukses", + "warning": "Peringatan", + "info": "Info", + "empty": "Tidak ada item", + "none": "Tidak ada", + "unknown": "Tidak diketahui" + }, + "dialogs": { + "confirmDelete": { + "title": "Konfirmasi penghapusan", + "message": "Apakah Anda yakin ingin menghapus ini? Tindakan ini tidak dapat dibatalkan.", + "confirm": "Hapus", + "cancel": "Batal" + }, + "unsavedChanges": { + "title": "Perubahan belum disimpan", + "message": "Anda memiliki perubahan yang belum disimpan. Apakah Anda ingin membuangnya?", + "discard": "Buang", + "keepEditing": "Tetap mengedit" + } + }, + "forms": { + "required": "Wajib", + "optional": "Opsional", + "name": "Nama", + "description": "Deskripsi", + "type": "Tipe", + "value": "Nilai", + "search": "Cari...", + "selectPlaceholder": "Pilih opsi..." + }, + "time": { + "now": "baru saja", + "secondsAgo_one": "{{count}} detik yang lalu", + "secondsAgo_other": "{{count}} detik yang lalu", + "minutesAgo_one": "{{count}} menit yang lalu", + "minutesAgo_other": "{{count}} menit yang lalu", + "hoursAgo_one": "{{count}} jam yang lalu", + "hoursAgo_other": "{{count}} jam yang lalu", + "daysAgo_one": "{{count}} hari yang lalu", + "daysAgo_other": "{{count}} hari yang lalu" + }, + "units": { + "bytes": "B", + "kilobytes": "KB", + "megabytes": "MB", + "gigabytes": "GB", + "terabytes": "TB" + } +} \ No newline at end of file diff --git a/core/http/react-ui/public/locales/id/errors.json b/core/http/react-ui/public/locales/id/errors.json new file mode 100644 index 000000000..9913cad3d --- /dev/null +++ b/core/http/react-ui/public/locales/id/errors.json @@ -0,0 +1,17 @@ +{ + "generic": "Terjadi kesalahan", + "network": "Eror jaringan. Periksa koneksi Anda dan coba lagi.", + "unauthorized": "Anda tidak memiliki izin untuk melakukan tindakan ini.", + "forbidden": "Akses ditolak.", + "notFound": "Sumber daya yang diminta tidak ditemukan.", + "serverError": "Eror server. Silahkan coba lagi nanti.", + "loadFailed": "Gagal memuat: {{message}}", + "saveFailed": "Gagal menyimpan: {{message}}", + "deleteFailed": "Gagal menghapus: {{message}}", + "updateFailed": "Gagal memperbarui: {{message}}", + "createFailed": "Gagal membuat: {{message}}", + "operationFailed": "Operasi gagal: {{message}}", + "invalidInput": "Input tidak valid. Silahkan periksa formulir dan coba lagi.", + "tryAgain": "Silahkan coba lagi.", + "contactAdmin": "Jika masalah terus berlanjut, hubungi administrator Anda." +} \ No newline at end of file diff --git a/core/http/react-ui/public/locales/id/home.json b/core/http/react-ui/public/locales/id/home.json new file mode 100644 index 000000000..b01529c1b --- /dev/null +++ b/core/http/react-ui/public/locales/id/home.json @@ -0,0 +1,66 @@ +{ + "cluster": { + "vram": "VRAM Kluster", + "ram": "RAM Kluster", + "nodesOnline": "{{healthy}}/{{total}} node online" + }, + "resourceGpu": "GPU", + "resourceRam": "RAM", + "assistant": { + "title": "Kelola LocalAI melalui obrolan", + "description": "Instal model, ganti backend, edit konfigurasi dan periksa status dengan berbicara pada LocalAI.", + "open": "Buka asisten", + "tooltip": "Kelola LocalAI melalui obrolan" + }, + "input": { + "placeholder": "Pesan...", + "attachImage": "Lampirkan gambar", + "attachAudio": "Lampirkan audio", + "attachFile": "Lampirkan file", + "enterToSend": "Enter untuk mengirim", + "selectModelFirst": "Pilih model terlebih dahulu", + "sendMessage": "Kirim pesan", + "selectModelToast": "Silahkan pilih model terlebih dahulu" + }, + "quickLinks": { + "manageByChat": "Kelola melalui obrolan", + "installedModels": "Model Terinstal", + "browseGallery": "Jelajahi Galeri", + "importModel": "Impor Model", + "documentation": "Dokumentasi" + }, + "loadedModels": { + "count_one": "{{count}} model dimuat", + "count_other": "{{count}} model dimuat", + "stop": "Hentikan model", + "stopAll": "Hentikan semua" + }, + "stopDialog": { + "title": "Hentikan Model", + "message": "Hentikan model {{model}}?", + "confirm": "Hentikan {{model}}", + "stopAllTitle": "Hentikan Semua model", + "stopAllMessage": "Hentikan semua {{count}} model yang dimuat?", + "stopAllConfirm": "Hentikan semua", + "stoppedToast": "{{model}} berhasil dihentikan", + "allStoppedToast": "Semua model berhasil dihentikan", + "stopFailed": "Gagal menghentikan: {{message}}" + }, + "wizard": { + "getStarted": "Memulai dengan {{name}}", + "intro": "Instal model pertama Anda untuk memulai. Jelajahi galeri atau impor punya Anda sendiri.", + "steps": { + "step1Title": "Jelajahi Galeri Model", + "step1Body": "Temukan model yang tepat untuk kebutuhan Anda dari koleksi pilihan kami.", + "step2Title": "Instal Model", + "step2Body": "Klik instal untuk mengunduh dan mengonfigurasinya secara otomatis.", + "step3Title": "Mulai Mengobrol", + "step3Body": "Mengobrol dengan model Anda langsung dari peramban atau gunakan API." + }, + "browseGallery": "Jelajahi Galeri Model", + "importModel": "Impor Model", + "docs": "Dokumentasi", + "noModelsTitle": "Tidak Ada Model yang Tersedia", + "noModelsBody": "Belum ada model yang terinstal. Hubungi administrator Anda untuk menyiapkan model agar Anda dapat mulai mengobrol." + } +} \ No newline at end of file diff --git a/core/http/react-ui/public/locales/id/importModel.json b/core/http/react-ui/public/locales/id/importModel.json new file mode 100644 index 000000000..0e3a8c49d --- /dev/null +++ b/core/http/react-ui/public/locales/id/importModel.json @@ -0,0 +1,142 @@ +{ + "title": "Impor Model Baru", + "subtitle": { + "simple": "Import model dari URI — deteksi otomatis memilih backend.", + "powerYaml": "Tulis konfigurasi YAML lengkap untuk model.", + "powerPrefs": "Preferensi impor tingkat lanjut." + }, + "actions": { + "import": "Impor Model", + "importing": "Mengimpor...", + "create": "Buat", + "saving": "Menyimpan...", + "browseHF": "Jelajahi model di HF", + "addCustom": "Tambah Tersuai", + "copy": "Salin" + }, + "form": { + "modelUri": "URI Model", + "uriPlaceholder": "huggingface://TheBloke/Llama-2-7B-Chat-GGUF atau https://example.com/model.gguf", + "uriHint": "Masukkan URI atau path ke file model yang ingin Anda impor", + "supportedFormats": "Format URI yang Didukung", + "options": "Opsi", + "preferences": "Preferensi (Opsional)", + "commonPreferences": "Preferensi Umum", + "customPreferences": "Preferensi Tersuai", + "customKeyValueHint": "Tambahkan pasangan key-value tersuai untuk konfigurasi tingkat lanjutan.", + "preferenceKey": "Key preferensi untuk baris {{index}}", + "preferenceValue": "Nilai preferensi untuk baris {{index}}", + "removePref": "Hapus preferensi ini", + "key": "Key", + "value": "Value", + "backend": "Backend", + "backendAuto": "Deteksi otomatis (berdasarkan URI)", + "backendLoading": "Memuat backend…", + "backendSearch": "Cari backend...", + "backendHint": "Paksa backend tertentu. Biarkan kosong untuk deteksi otomatis dari URI. Item yang ditandai \"pilih manual\" tidak dapat dideteksi otomatis — pilih sendiri jika Anda tahu apa yang dibutuhkan model.", + "backendErrorHint": "Tidak dapat memuat daftar backend — hanya menggunakan deteksi otomatis.", + "backendNotInstalled": "Backend ini belum terinstal. Proses impor akan mengunduhnya terlebih dahulu.", + "modelName": "Nama Model", + "modelNamePlaceholder": "Kosongkan untuk menggunakan nama file", + "modelNameHint": "Nama tersuai untuk model. Jika kosong, nama file akan digunakan.", + "description": "Deskripsi", + "descriptionPlaceholder": "Kosongkan untuk menggunakan deskripsi bawaan", + "descriptionHint": "Deskripsi tersuai untuk model.", + "quantizations": "Kuantisasi", + "quantizationsPlaceholder": "q4_k_m,q4_k_s,q3_k_m (dipisahkan koma)", + "quantizationsHint": "Kuantisasi pilihan (dipisahkan koma). Kosongkan untuk nilai bawaan (q4_k_m).", + "mmprojQuantizations": "Kuantisasi MMProj", + "mmprojQuantizationsPlaceholder": "fp16,fp32 (dipisahkan koma)", + "mmprojQuantizationsHint": "Kuantisasi MMProj pilihan. Kosongkan untuk nilai bawaan (fp16).", + "embeddings": "Embedding", + "embeddingsHint": "Aktifkan dukungan embedding untuk model ini.", + "modelType": "Tipe Model", + "modelTypePlaceholder": "AutoModelForCausalLM (untuk backend transformers)", + "modelTypeHint": "Tipe model untuk backend transformers. Contoh: AutoModelForCausalLM, SentenceTransformer, Mamba.", + "pipelineType": "Tipe Pipeline", + "pipelineTypeHint": "Tipe pipeline untuk backend diffusers.", + "schedulerType": "Tipe Scheduler", + "schedulerTypePlaceholder": "k_dpmpp_2m (optional)", + "schedulerTypeHint": "Tipe scheduler untuk backend diffusers. Contoh: k_dpmpp_2m, euler_a, ddim.", + "enableParameters": "Aktifkan parameter", + "enableParametersPlaceholder": "negative_prompt,num_inference_steps (dipisahkan koma)", + "enableParametersHint": "Parameter aktif untuk backend diffusers (dipisahkan koma).", + "cuda": "CUDA", + "cudaHint": "Aktifkan dukungan CUDA untuk akselerasi GPU.", + "yamlEditor": "Editor Konfigurasi YAML", + "manualPick": "pilih manual", + "manualPickTooltip": "Deteksi otomatis tidak akan merutekan ke backend ini. Pilih di sini jika Anda tahu bahwa ini yang Anda inginkan." + }, + "modality": { + "text": "LLM Teks", + "asr": "Pengenalan suara", + "tts": "Text-to-speech", + "image": "Gambar / Video", + "embeddings": "Embedding", + "reranker": "Reranker", + "detection": "Deteksi object", + "vad": "Deteksi aktivitas suara", + "other": "Lainnya" + }, + "powerTabs": { + "ariaLabel": "Tab mode tingkat lanjutan", + "preferences": "Preferensi", + "yaml": "YAML" + }, + "switchDialog": { + "title": "Pertahankan preferensi tersuai Anda?", + "body": "Beralih ke mode Sederhana akan menyembunyikan preferensi selain backend, nama, dan deskripsi. Preferensi tersebut tetap akan dikirim saat mengimpor.", + "cancel": "Batal", + "discard": "Buang & beralih", + "keep": "Pertahankan & beralih" + }, + "estimate": { + "title": "Estimasi kebutuhan", + "download": "Unduhan: {{size}}", + "vram": "VRAM: {{vram}}" + }, + "toasts": { + "noUri": "Silahkan masukkan URI model", + "noYaml": "Silahkan masukkan konfigurasi YAML", + "started": "Impor dimulai! Melacak progress...", + "startedWithMeta": "Impor dimulai! Melacak progress... ({{meta}})", + "imported": "Model berhasil diimpor!", + "importedYaml": "Konfigurasi model berhasil diimpor!", + "importFailed": "Gagal mengimpor: {{message}}", + "startImportFailed": "Gagal memulai impor: {{message}}", + "backendsLoadFailed": "Tidak dapat memuat daftar backend — hanya menggunakan deteksi otomatis.", + "modalityClearedBackend": "Pilihan backend dikosongkan — tidak termasuk dalam grup {{label}}.", + "copied": "Disalin ke papan klip" + }, + "uriFormats": { + "huggingface": { + "title": "HuggingFace", + "standard": "Format standar HuggingFace", + "short": "Format ringkas HuggingFace", + "fullUrl": "URL lengkap HuggingFace" + }, + "http": { + "title": "URL HTTP/HTTPS", + "direct": "Unduh langsung dari URL HTTPS mana pun" + }, + "local": { + "title": "File Lokal", + "filePath": "Path file lokal (absolut)", + "directYaml": "File konfigurasi YAML lokal langsung" + }, + "oci": { + "title": "Registri OCI", + "registry": "Registri kontainer OCI", + "tarball": "File tarball OCI lokal" + }, + "ollama": { + "title": "Ollama", + "model": "Format model Ollama" + }, + "yaml": { + "title": "File Konfigurasi YAML", + "remote": "File konfigurasi YAML jarak jauh", + "local": "File konfigurasi YAML lokal" + } + } +} \ No newline at end of file diff --git a/core/http/react-ui/public/locales/id/media.json b/core/http/react-ui/public/locales/id/media.json new file mode 100644 index 000000000..bf7b7bc13 --- /dev/null +++ b/core/http/react-ui/public/locales/id/media.json @@ -0,0 +1,154 @@ +{ + "studio": { + "tabs": { + "images": "Gambar", + "video": "Video", + "tts": "TTS", + "sound": "Suara" + } + }, + "image": { + "title": "Pembuatan Gambar", + "labels": { + "model": "Model", + "prompt": "Prompt", + "promptPlaceholder": "Deskripsikan gambar yang ingin Anda buat...", + "negativePrompt": "Prompt Negatif", + "negativePromptPlaceholder": "Apa yang harus dihindari...", + "size": "Ukuran", + "count": "Jumlah (1-4)", + "advanced": "Pengaturan Tingkat Lanjutan", + "imageInputs": "Input Gambar", + "steps": "Steps", + "stepsPlaceholder": "20", + "seed": "Seed", + "seedPlaceholder": "Acak", + "sourceImage": "Gambar Sumber (img2img)", + "refImages": "Gambar Referensi", + "refImagesAdded_one": "{{count}} gambar ditambahkan", + "refImagesAdded_other": "{{count}} gambar ditambahkan" + }, + "actions": { + "generate": "Hasilkan", + "generating": "Menghasilkan..." + }, + "empty": "Gambar yang dihasilkan akan muncul di sini", + "toasts": { + "noPrompt": "Silahkan masukkan prompt", + "noModel": "Silahkan pilih model", + "noResults": "Tidak ada gambar yang dihasilkan" + } + }, + "video": { + "title": "Pembuatan Video", + "labels": { + "model": "Model", + "prompt": "Prompt", + "promptPlaceholder": "Deskripsikan video yang ingin Anda buat...", + "duration": "Durasi (detik)", + "fps": "FPS", + "size": "Ukuran", + "advanced": "Pengaturan Tingkat Lanjutan", + "seed": "Seed", + "seedPlaceholder": "Acak" + }, + "actions": { + "generate": "Hasilkan", + "generating": "Menghasilkan..." + }, + "empty": "Video yang dihasilkan akan muncul di sini", + "toasts": { + "noPrompt": "Silahkan masukkan prompt", + "noModel": "Silahkan pilih model", + "noResults": "Tidak ada video yang dihasilkan" + } + }, + "tts": { + "title": "Teks ke Suara", + "labels": { + "model": "Model", + "voice": "Suara", + "voicePlaceholder": "ID suara opsional", + "input": "Teks", + "inputPlaceholder": "Masukkan teks untuk disintesis..." + }, + "actions": { + "generate": "Hasilkan", + "generating": "Menghasilkan..." + }, + "empty": "Audio yang dihasilkan akan muncul di sini", + "toasts": { + "noText": "Silahkan masukkan teks", + "noModel": "Silahkan pilih model", + "generateFailed": "Gagal menghasilkan" + } + }, + "sound": { + "title": "Pembuatan Suara", + "labels": { + "model": "Model", + "prompt": "Prompt", + "promptPlaceholder": "Deskripsikan suara yang ingin Anda buat...", + "duration": "Durasi (detik)", + "language": "Bahasa", + "vocalLanguage": "Bahasa vokal", + "lyrics": "Lirik (opsional)", + "lyricsPlaceholder": "Lirik untuk generasi vokal", + "advanced": "Pengaturan Tingkat Lanjutan", + "seed": "Seed", + "seedPlaceholder": "Acak" + }, + "actions": { + "generate": "Hasilkan", + "generating": "Menghasilkan..." + }, + "empty": "Audio yang dihasilkan akan muncul di sini", + "toasts": { + "noPrompt": "Silahkan masukkan prompt", + "noModel": "Silahkan pilih model", + "generateFailed": "Gagal menghasilkan" + } + }, + "talk": { + "title": "Percakapan", + "subtitle": "Percakapan suara realtime", + "actions": { + "start": "Mulai sesi", + "stop": "Akhiri sesi", + "connecting": "Menghubungkan...", + "muted": "Disenyapkan", + "mute": "Senyapkan", + "unmute": "Aktifkan Suara" + }, + "labels": { + "model": "Model", + "voice": "Suara", + "voicePlaceholder": "alloy", + "language": "Bahasa", + "languagePlaceholder": "en", + "instructions": "Instruksi", + "instructionsPlaceholder": "Atur persona asisten..." + }, + "status": { + "idle": "Idle", + "connecting": "Menghubungkan...", + "listening": "Mendengarkan...", + "speaking": "Berbicara...", + "ended": "Sesi berakhir" + }, + "toasts": { + "noModel": "Silahkan pilih model terlebih dahulu", + "connectFailed": "Gagal terhubung: {{message}}" + } + }, + "history": { + "title": "Riwayat", + "empty": "Tidak ada riwayat", + "deleteEntry": "Hapus entri", + "clear": "Hapus riwayat", + "clearTitle": "Hapus semua riwayat", + "clearMessage": "Hapus semua entri riwayat? Tindakan ini tidak dapat dibatalkan.", + "clearConfirm": "Hapus", + "cleared": "Riwayat dihapus" + } +} \ No newline at end of file diff --git a/core/http/react-ui/public/locales/id/models.json b/core/http/react-ui/public/locales/id/models.json new file mode 100644 index 000000000..d88a04116 --- /dev/null +++ b/core/http/react-ui/public/locales/id/models.json @@ -0,0 +1,93 @@ +{ + "title": "Instal Model", + "subtitle": "Telusuri dan instal model AI dari galeri", + "stats": { + "available": "Tersedia", + "installed": "Terinstal" + }, + "actions": { + "addModel": "Tambah Model", + "importModel": "Impor Model", + "install": "Instal", + "reinstall": "Instal Ulang", + "delete": "Hapus" + }, + "filters": { + "all": "Semua", + "llm": "Obrolan", + "image": "Gambar", + "video": "Video", + "multimodal": "Multimodal", + "vision": "Vision", + "tts": "TTS", + "stt": "STT", + "diarization": "Diarization", + "soundGen": "Suara", + "audioTransform": "Efek Audio", + "realtimeAudio": "Audio Realtime", + "embedding": "Embedding", + "rerank": "Rerank", + "detection": "Deteksi", + "vad": "VAD", + "fitsGpu": "Muat di GPU", + "allBackends": "Semua Backend", + "searchBackends": "Cari backends..." + }, + "search": { + "placeholder": "Cari model...", + "clearFilters": "Hapus filter" + }, + "table": { + "modelName": "Nama Model", + "description": "Deskripsi", + "backend": "Backend", + "sizeVram": "Ukuran / VRAM", + "status": "Status", + "actions": "Aksi", + "size": "Ukuran: {{size}}", + "vram": "VRAM: {{vram}}", + "fits": "Muat", + "mayNotFit": "Mungkin tidak muat", + "trustRemoteCode": "Trust Remote Code", + "installing": "Menginstal", + "installingPct": "Menginstal · {{percent}}%", + "installed": "Terinstal", + "notInstalled": "Belum Terinstal" + }, + "detail": { + "description": "Deskripsi", + "gallery": "Galeri", + "backend": "Backend", + "size": "Ukuran", + "vram": "VRAM", + "license": "Lisensi", + "tags": "Tag", + "links": "Tautan", + "warning": "Peringatan", + "files": "File", + "fitsGpu": "Muat di GPU", + "mayNotFitGpu": "Mungkin tidak muat di GPU", + "requiresTrustRemoteCode": "Memerlukan Trust Remote Code", + "fileCount_one": "{{count}} file", + "fileCount_other": "{{count}} file", + "filename": "Nama file", + "uri": "URI", + "sha256": "SHA256" + }, + "empty": { + "title": "Model tidak ditemukan", + "withFilters": "Tidak ada model yang cocok dengan pencarian atau filter Anda.", + "noFilters": "Galeri model kosong." + }, + "deleteDialog": { + "title": "Hapus Model", + "message": "Hapus model {{model}}?", + "confirm": "Hapus {{model}}", + "deletingToast": "Menghapus {{model}}..." + }, + "errors": { + "loadFailed": "Gagal memuat model: {{message}}", + "installFailed": "Gagal menginstal: {{message}}", + "deleteFailed": "Gagal menghapus: {{message}}" + } +} \ No newline at end of file diff --git a/core/http/react-ui/public/locales/id/nav.json b/core/http/react-ui/public/locales/id/nav.json new file mode 100644 index 000000000..f06ba0c28 --- /dev/null +++ b/core/http/react-ui/public/locales/id/nav.json @@ -0,0 +1,54 @@ +{ + "appName": "LocalAI", + "openMenu": "Buka menu", + "closeMenu": "Tutup menu", + "primaryNavigation": "Navigasi utama", + "switchToLightMode": "Ganti ke mode terang", + "switchToDarkMode": "Ganti ke mode gelap", + "expandSidebar": "Perluas sidebar", + "collapseSidebar": "Ciutkan sidebar", + "changeLanguage": "Ubah bahasa", + "logout": "Keluar", + "accountSettings": "Pengaturan akun", + "account": "Akun", + "accountFor": "Akun: {{name}}", + "sections": { + "tools": "Peralatan", + "enhance": "Peningkatan", + "biometrics": "Biometrik", + "agents": "Agen", + "system": "Sistem" + }, + "items": { + "home": "Beranda", + "installModels": "Instal Model", + "chat": "Obrolan", + "studio": "Studio", + "talk": "Bicara", + "fineTune": "Fine-Tune (Eksperimental)", + "quantize": "Kuantisasi (Eksperimental)", + "audioTransform": "Transformasi Audio", + "faceRecognition": "Pengenalan Wajah", + "voiceRecognition": "Pengenalan Suara", + "agents": "Agen", + "skills": "Skill", + "memory": "Memori", + "mcpJobs": "MCP CI Jobs", + "usage": "Penggunaan", + "users": "Pengguna", + "middleware": "Middleware", + "backends": "Backend", + "traces": "Trace", + "nodes": "Node", + "swarm": "Swarm", + "system": "Sistem", + "settings": "Pengaturan", + "api": "API" + }, + "footer": { + "github": "GitHub", + "documentation": "Dokumentasi", + "author": "Penulis", + "copyright": "© 2023-{{year}} {{author}}" + } +} \ No newline at end of file diff --git a/core/http/react-ui/public/locales/id/skills.json b/core/http/react-ui/public/locales/id/skills.json new file mode 100644 index 000000000..7ba932cd2 --- /dev/null +++ b/core/http/react-ui/public/locales/id/skills.json @@ -0,0 +1,79 @@ +{ + "title": "Skill", + "subtitle": "Kelola skill agen (instruksi dan sumber daya yang dapat digunakan kembali)", + "unavailable": { + "subtitle": "Layanan Skill tidak tersedia atau indeks sedang dibangun ulang. Coba beberapa saat lagi.", + "retry": "Coba lagi" + }, + "actions": { + "newSkill": "Skill baru", + "createSkill": "Buat skill", + "import": "Impor", + "importing": "Mengimpor...", + "gitRepos": "Repo Git", + "edit": "Edit", + "delete": "Hapus", + "export": "Ekspor", + "sync": "Sinkronisasi", + "addRepo": "Tambah repo", + "adding": "Menambahkan...", + "remove": "Hapus", + "enable": "Aktifkan", + "disable": "Nonaktifkan" + }, + "search": { + "placeholder": "Cari skill..." + }, + "git": { + "title": "Repositori git", + "description": "Tambah repositori Git untuk mengambil skill. Skill akan muncul di daftar setelah sinkronisasi.", + "urlPlaceholder": "https://github.com/user/repo atau git@github.com:user/repo.git", + "noRepos": "Tidak ada repositori Git yang dikonfigurasi. Tambahkan satu di atas.", + "disabled": "Dinonaktifkan", + "removeRepo": "Hapus repo" + }, + "card": { + "noDescription": "Tidak ada deskripsi", + "readOnly": "Hanya baca", + "editTitle": "Edit skill", + "deleteTitle": "Hapus skill", + "exportTitle": "Ekspor sebagai .tar.gz" + }, + "empty": { + "title": "Tidak ada skill yang ditemukan", + "text": "Buat atau impor skill untuk memulai.", + "noPersonal": "Anda belum memiliki skill." + }, + "sections": { + "yourSkills": "Skill Anda", + "otherUsersSkills": "Skill Pengguna Lain" + }, + "deleteDialog": { + "title": "Hapus Skill", + "message": "Hapus skill \"{{name}}\"? Tindakan ini tidak dapat dibatalkan.", + "confirm": "Hapus" + }, + "removeRepoDialog": { + "title": "Hapus Repositori Git", + "message": "Hapus repositori Git ini? Skill dari repo ini tidak akan tersedia lagi.", + "confirm": "Hapus" + }, + "toasts": { + "loadFailed": "Gagal memuat skill", + "deleted": "Skill \"{{name}}\" berhasil dihapus", + "deleteFailed": "Gagal menghapus skill", + "exported": "Skill \"{{name}}\" berhasil diekspor", + "exportFailed": "Gagal mengekspor", + "imported": "Skill berhasil diimpor dari \"{{file}}\" ", + "importFailed": "Gagal mengimpor", + "loadReposFailed": "Gagal memuat repositori Git", + "repoAdded": "Repo Git berhasil ditambahkan dan sedang sinkronisasi", + "addRepoFailed": "Gagal menambahkan repo", + "synced": "Repo berhasil disinkronisasi", + "syncFailed": "Gagal sinkronisasi", + "toggled": "Berhasil mengubah status repo", + "toggleFailed": "Gagal mengubah status repo", + "removed": "Repo berhasil dihapus", + "removeFailed": "Gagal menghapus repo" + } +} \ No newline at end of file diff --git a/core/http/react-ui/scripts/translate-locales.mjs b/core/http/react-ui/scripts/translate-locales.mjs index d9aefc90f..b85baa6f1 100644 --- a/core/http/react-ui/scripts/translate-locales.mjs +++ b/core/http/react-ui/scripts/translate-locales.mjs @@ -17,7 +17,7 @@ // // Behavior: // - Reads public/locales/en/*.json as source of truth. -// - For each other locale (it, es, de, zh-CN), opens the matching file +// - For each other locale (it, es, de, zh-CN, id), opens the matching file // (or creates it). Walks the source object; for each leaf string: // * If the target already has a non-empty translation, leave it. // * If --copy mode, fill with the English value. @@ -36,13 +36,14 @@ const __dirname = dirname(fileURLToPath(import.meta.url)) const ROOT = join(__dirname, '..') const LOCALES_DIR = join(ROOT, 'public', 'locales') const SOURCE_LOCALE = 'en' -const TARGET_LOCALES = ['it', 'es', 'de', 'zh-CN'] +const TARGET_LOCALES = ['it', 'es', 'de', 'zh-CN', 'id'] const LANGUAGE_NAMES = { it: 'Italian', es: 'Spanish', de: 'German', 'zh-CN': 'Simplified Chinese', + id: 'Indonesian', } const argv = process.argv.slice(2) diff --git a/core/http/react-ui/src/i18n/index.js b/core/http/react-ui/src/i18n/index.js index a0a81da14..b6432be27 100644 --- a/core/http/react-ui/src/i18n/index.js +++ b/core/http/react-ui/src/i18n/index.js @@ -10,6 +10,7 @@ export const SUPPORTED_LANGUAGES = [ { code: 'es', name: 'Español', flag: 'ES' }, { code: 'de', name: 'Deutsch', flag: 'DE' }, { code: 'zh-CN', name: '简体中文', flag: 'ZH' }, + { code: 'id', name: 'Bahasa Indonesia', flag: 'ID' }, ] export const NAMESPACES = [