feat(i18n): add Indonesian locale

This commit is contained in:
Aqil Aziz
2026-05-07 16:48:05 +08:00
committed by GitHub
parent 6efac8887e
commit fcc37c6c2d
6 changed files with 982 additions and 3 deletions
+2
View File
@@ -11,6 +11,7 @@ import {
} from 'react';
import { de } from './locales/de';
import { en } from './locales/en';
import { id } from './locales/id';
import { esES } from './locales/es-ES';
import { fa } from './locales/fa';
import { ar } from './locales/ar';
@@ -34,6 +35,7 @@ type DictKey = keyof Dict;
const DICTS: Record<Locale, Dict> = {
'en': en,
'id': id,
'de': de,
'zh-CN': zhCN,
'zh-TW': zhTW,
+971
View File
@@ -0,0 +1,971 @@
import type { Dict } from '../types';
export const id: Dict = {
'common.cancel': 'Batal',
'common.save': 'Simpan',
'common.close': 'Tutup',
'common.delete': 'Hapus',
'common.rename': 'Ganti nama',
'common.preview': 'Pratinjau',
'common.share': 'Bagikan',
'common.search': 'Cari',
'common.searchEllipsis': 'Cari...',
'common.loading': 'Memuat...',
'common.all': 'Semua',
'common.none': 'Tidak ada',
'common.default': 'Default',
'common.installed': 'terpasang',
'common.notInstalled': 'belum terpasang',
'common.active': 'aktif',
'common.offline': 'offline',
'common.selected': 'dipilih',
'common.create': 'Buat',
'common.openPreview': 'Buka pratinjau',
'common.exitFullscreen': 'Keluar layar penuh',
'common.fullscreen': 'Layar penuh',
'common.openInNewTab': 'Buka di tab baru',
'common.exportPdf': 'Ekspor sebagai PDF',
'common.exportZip': 'Unduh sebagai .zip',
'common.exportHtml': 'Ekspor sebagai HTML mandiri',
'common.justNow': 'baru saja',
'common.minutesAgo': '{n}m lalu',
'common.hoursAgo': '{n}j lalu',
'common.daysAgo': '{n}h lalu',
'common.now': 'sekarang',
'common.minutesShort': '{n}m',
'common.hoursShort': '{n}j',
'common.daysShort': '{n}h',
'common.untitled': 'Tanpa judul',
'app.brand': 'Open Design',
'app.brandPill': 'Pratinjau Riset',
'app.brandSubtitle': 'oleh Nexu Labs',
'app.welcomeLoading': 'Memuat workspace...',
'settings.welcomeKicker': 'Selamat datang',
'settings.welcomeTitle': 'Siapkan Open Design',
'settings.welcomeSubtitle': 'Pilih cara menjalankan generasi. Ini bisa diubah kapan saja dari tombol Settings di bar atas.',
'settings.kicker': 'Pengaturan',
'settings.title': 'Eksekusi & model',
'settings.subtitle': 'Pilih antara CLI code-agent lokal dan Anthropic API (BYOK). API key hanya disimpan di browser ini.',
'settings.modeAria': 'Mode eksekusi',
'settings.protocolAria': 'Protokol API',
'settings.modeDaemon': 'CLI lokal',
'settings.modeDaemonHelp': 'Jalankan lewat code-agent CLI di komputer ini',
'settings.modeDaemonOffline': 'Daemon tidak berjalan',
'settings.modeDaemonOfflineMeta': 'daemon offline',
'settings.modeDaemonInstalledMeta': '{count} terpasang',
'settings.modeApi': 'Anthropic API',
'settings.modeApiMeta': 'BYOK',
'settings.codeAgent': 'Code agent',
'settings.codeAgentHint': 'Terdeteksi dari PATH. Pilih CLI yang ingin dipakai untuk menjalankan generasi.',
'settings.rescan': 'Pindai ulang',
'settings.rescanTitle': 'Pindai ulang PATH',
'settings.rescanRunning': 'Memindai...',
'settings.rescanSuccess': 'Pemindaian selesai. {count} tersedia.',
'settings.rescanFailed': 'Pemindaian gagal. Periksa daemon lalu coba lagi.',
'settings.noAgentsDetected':
'Belum ada agent terdeteksi. Pasang salah satu dari Claude Code, Codex, Devin for Terminal, Gemini CLI, OpenCode, Cursor Agent, Qwen, atau GitHub Copilot CLI, lalu klik pindai ulang.',
'settings.apiSection': 'Anthropic API',
'settings.quickFillProvider': 'Provider isi cepat',
'settings.customProvider': 'Provider kustom',
'settings.apiKey': 'API key',
'settings.showKey': 'Tampilkan key',
'settings.hideKey': 'Sembunyikan key',
'settings.show': 'Tampilkan',
'settings.hide': 'Sembunyikan',
'settings.model': 'Model',
'settings.suggestedModelsHint': 'Ini model yang disarankan untuk protokol ini. Provider kamu mungkin mendukung model lain.',
'settings.baseUrl': 'Base URL',
'settings.baseUrlInvalid':
'Masukkan URL publik http:// atau https:// yang valid. Localhost diizinkan; IP jaringan privat diblokir.',
'settings.azureDeploymentModel': 'Nama deployment',
'settings.azureDeploymentModelHint':
'Untuk Azure OpenAI, field ini digunakan sebagai nama deployment di /openai/deployments/<model>. Masukkan nama deployment yang kamu buat di Azure.',
'settings.apiVersion': 'Versi API',
'settings.maxTokens': 'Token maks (opsional)',
'settings.maxTokensHint':
'Batas panjang respons. Setiap model punya default sendiri; kosongkan untuk memakainya, atau isi angka untuk menimpa.',
'settings.apiHint':
'Panggilan dikirim langsung dari browser ini ke base URL yang kamu atur. Tanpa proxy. Key tidak keluar dari localStorage.',
'settings.skipForNow': 'Lewati dulu',
'settings.getStarted': 'Mulai',
'settings.envConfigure': 'Atur mode eksekusi',
'settings.localCli': 'CLI lokal',
'settings.anthropicApi': 'Anthropic API',
'settings.noAgentSelected': 'belum ada agent dipilih',
'settings.language': 'Bahasa',
'settings.languageHint': 'Ganti bahasa antarmuka. Disimpan di browser ini.',
'settings.appearance': 'Tampilan',
'settings.appearanceHint': 'Pilih terang, gelap atau ikuti pengaturan sistem.',
'settings.themeSystem': 'Sistem',
'settings.themeLight': 'Terang',
'settings.themeDark': 'Gelap',
'settings.modelPicker': 'Model',
'settings.reasoningPicker': 'Kekuatan penalaran',
'settings.modelPickerHint':
'Diambil dari CLI jika tersedia. "Default" mengikuti konfigurasi CLI; "Custom..." untuk mengetik model id sendiri.',
'settings.cliEnvTitle': 'Lokasi konfigurasi CLI',
'settings.cliEnvHint': 'Atur direktori konfigurasi non-rahasia untuk menjalankan aplikasi paket dan deteksi agent.',
'settings.cliEnvClaudeConfigDir': 'Direktori konfigurasi Claude Code',
'settings.cliEnvCodexHome': 'Home Codex',
'settings.modelCustom': 'Kustom (isi di bawah)...',
'settings.modelCustomLabel': 'ID model kustom',
'settings.modelCustomPlaceholder': 'mis. anthropic/claude-sonnet-4-6',
'settings.mediaProviders': 'Provider media',
'settings.mediaProvidersHint': 'API key untuk generasi gambar, video, dan audio. Disimpan lokal dan disinkronkan ke daemon lokal.',
'settings.mediaProviderApiKey': 'API key',
'settings.mediaProviderBaseUrl': 'Base URL',
'settings.mediaProviderConfigured': 'Sudah diatur',
'settings.mediaProviderUnset': 'Belum diatur',
'settings.mediaProviderClear': 'Bersihkan',
'settings.mediaProviderPlaceholder': 'Tempel API key',
'settings.mediaProviderBaseUrlPlaceholder': 'Timpa base URL default',
'settings.about': 'Tentang',
'settings.aboutHint': 'Detail versi dan runtime',
'settings.appVersion': 'Versi',
'settings.appChannel': 'Channel',
'settings.appRuntime': 'Runtime',
'settings.appPlatform': 'Platform',
'settings.appArchitecture': 'Arsitektur',
'settings.runtimePackaged': 'Aplikasi paket',
'settings.runtimeDevelopment': 'Development',
'settings.versionUnavailable': 'Detail versi tidak tersedia saat daemon offline.',
'entry.tabDesigns': 'Desain',
'entry.tabExamples': 'Contoh',
'entry.tabDesignSystems': 'Sistem desain',
'entry.tabConnectors': 'Konektor',
'entry.openSettingsTitle': 'Pengaturan',
'entry.openSettingsAria': 'Buka pengaturan',
'entry.resizeAria': 'Ubah ukuran sidebar',
'entry.loadingWorkspace': 'Memuat workspace...',
'entry.tabImageTemplates': 'Templat gambar',
'entry.tabVideoTemplates': 'Templat video',
'promptTemplates.searchPlaceholder': 'Cari templat...',
'promptTemplates.countLabel': '{n} hasil',
'promptTemplates.emptyImage': 'Belum ada templat prompt gambar.',
'promptTemplates.emptyVideo': 'Belum ada templat prompt video.',
'promptTemplates.emptyNoMatch': 'Tidak ada templat yang cocok dengan pencarianmu.',
'promptTemplates.attributionFooter': 'Diadaptasi dari library prompt publik. Tiap kartu menautkan ke author asli.',
'promptTemplates.openPreviewTitle': 'Buka prompt dan pratinjau',
'promptTemplates.sourcePrefix': 'Sumber:',
'promptTemplates.fetchError': 'Tidak bisa memuat isi templat ini.',
'promptTemplates.promptLabel': 'Isi prompt',
'promptTemplates.copyPrompt': 'Salin prompt',
'promptTemplates.copyDone': 'Tersalin!',
'promptTemplates.modelHint': 'Model disarankan: {model}',
'promptTemplates.openSource': 'Lihat asli',
'promptTemplates.openFullscreen': 'Buka pratinjau layar penuh',
'promptTemplates.closeFullscreen': 'Tutup pratinjau layar penuh',
'promptTemplates.allSources': 'Semua sumber',
'promptTemplates.sourceFilterAria': 'Filter berdasarkan sumber',
'promptTemplates.retry': 'Coba lagi',
'connectors.title': 'Konektor',
'connectors.subtitle': 'Sumber data lokal dan mendatang yang bisa mendukung live artifact.',
'connectors.account': 'Akun',
'connectors.noAccount': 'Belum terhubung',
'connectors.tools': 'Alat',
'connectors.connect': 'Hubungkan',
'connectors.disconnect': 'Putuskan',
'connectors.configure': 'Konfigurasikan',
'connectors.unavailable': 'Tidak tersedia',
'connectors.phaseStubTitle': 'API konektor hadir di Fase 3; ini adalah area pratinjau.',
'connectors.statusAvailable': 'Tersedia',
'connectors.statusConnected': 'Terhubung',
'connectors.statusError': 'Error',
'connectors.statusDisabled': 'Nonaktif',
'connectors.gateTitle': 'Konfigurasikan API key Composio',
'connectors.gateBody':
'Konektor membutuhkan API key Composio. Tambahkan di Pengaturan untuk membuka integrasi yang tersedia.',
'connectors.gateAction': 'Buka pengaturan',
'connectors.aboutLabel': 'Tentang',
'connectors.detailsLabel': 'Detail',
'connectors.statusLabel': 'Status',
'connectors.categoryLabel': 'Kategori',
'connectors.providerLabel': 'Provider',
'connectors.toolsSection': 'Alat',
'connectors.toolsLoading': 'Memuat alat...',
'connectors.noToolsAvailable': 'Belum ada alat tersedia. Hubungkan untuk melihat apa yang disediakan integrasi ini.',
'connectors.openDetailsAria': 'Buka detail {name}',
'connectors.toolsBadgeNone': 'Tidak ada alat',
'connectors.toolsBadgeOne': '{n} alat',
'connectors.toolsBadgeMany': '{n} alat',
'connectors.searchPlaceholder': 'Cari konektor...',
'connectors.searchAriaLabel': 'Cari konektor berdasarkan nama, provider, atau alat',
'connectors.searchClear': 'Bersihkan pencarian',
'connectors.emptyNoMatchTitle': 'Tidak ada konektor yang cocok dengan "{query}"',
'connectors.emptyNoMatchBody': 'Coba kata kunci lain, atau bersihkan pencarian untuk melihat seluruh katalog.',
'connectors.emptyNoMatchAction': 'Bersihkan pencarian',
'newproj.tabPrototype': 'Prototype',
'newproj.tabLiveArtifact': 'Live artifact',
'newproj.tabDeck': 'Slide deck',
'newproj.tabTemplate': 'Dari templat',
'newproj.tabOther': 'Lainnya',
'newproj.titlePrototype': 'Prototype baru',
'newproj.titleLiveArtifact': 'Live artifact baru',
'newproj.titleDeck': 'Slide deck baru',
'newproj.titleTemplate': 'Mulai dari templat',
'newproj.titleImage': 'Gambar baru',
'newproj.titleVideo': 'Video baru',
'newproj.titleAudio': 'Audio baru',
'newproj.titleOther': 'Proyek baru',
'newproj.namePlaceholder': 'Nama proyek',
'newproj.fidelityLabel': 'Fidelity',
'newproj.fidelityWireframe': 'Wireframe',
'newproj.fidelityHigh': 'High fidelity',
'newproj.toggleSpeakerNotes': 'Gunakan catatan pembicara',
'newproj.toggleSpeakerNotesHint': 'Kurangi teks di slide; simpan poin bicara di catatan.',
'newproj.toggleAnimations': 'Sertakan animasi',
'newproj.toggleAnimationsHint': 'Tambahkan motion, hover, dan transisi di atas templat.',
'newproj.templateLabel': 'Templat',
'newproj.noTemplatesTitle': 'Belum ada templat',
'newproj.noTemplatesBody': 'Buka proyek apa pun, lalu pakai menu Share di penampil berkas untuk mengubahnya menjadi templat.',
'newproj.savedTemplate': 'Templat tersimpan',
'newproj.fileSingular': 'berkas',
'newproj.filePlural': 'berkas',
'newproj.create': 'Buat',
'newproj.createLiveArtifact': 'Buat live artifact',
'newproj.createFromTemplate': 'Buat dari templat',
'newproj.createDisabledTitle': 'Simpan proyek sebagai templat dulu.',
'newproj.importClaudeZip': 'Impor ZIP Claude Design',
'newproj.importClaudeZipTitle': 'Impor file .zip hasil ekspor Claude Design',
'newproj.importingClaudeZip': 'Mengimpor...',
'newproj.privacyFooter': 'Secara default hanya kamu yang bisa melihat proyekmu.',
'newproj.designSystem': 'Sistem desain',
'newproj.dsNoneFreeform': 'Tidak ada - bebas',
'newproj.dsNoneSubtitleEmpty': 'Tanpa token sistem, pilih palet sendiri',
'newproj.dsNoneSubtitleSelected': 'Lewati token sistem. Agent memilih paletnya sendiri.',
'newproj.dsCategoryFallback': 'Sistem desain',
'newproj.dsSearch': 'Cari sistem desain...',
'newproj.dsModeAria': 'Mode pilihan',
'newproj.dsModeSingle': 'Tunggal',
'newproj.dsModeMulti': 'Multi',
'newproj.dsNoneTitle': 'Tidak ada - bebas',
'newproj.dsNoneSub': 'Lewati token sistem. Agent memilih paletnya sendiri.',
'newproj.dsEmpty': 'Tidak ada sistem desain yang cocok dengan "{query}".',
'newproj.dsFootSingular': 'hanya sebagai inspirasi.',
'newproj.dsFootPlural': 'hanya sebagai inspirasi.',
'newproj.dsFootClear': 'Bersihkan',
'newproj.dsBadgeDefault': 'DEFAULT',
'newproj.dsPrimaryFallback': 'Utama',
'newproj.surfaceImage': 'Gambar',
'newproj.surfaceVideo': 'Video',
'newproj.surfaceAudio': 'Audio',
'newproj.modelLabel': 'Model',
'newproj.aspectLabel': 'Aspek',
'newproj.imageStyleLabel': 'Catatan gaya',
'newproj.imageStylePlaceholder': 'Foto editorial, cahaya siang lembut, palet kalem',
'newproj.videoLengthLabel': 'Durasi',
'newproj.videoLengthSeconds': '{n}d',
'newproj.audioKindLabel': 'Jenis audio',
'newproj.audioKindMusic': 'Musik',
'newproj.audioKindSpeech': 'Speech / TTS',
'newproj.audioKindSfx': 'SFX',
'newproj.audioDurationLabel': 'Durasi',
'newproj.audioDurationSeconds': '{n}d',
'newproj.voiceLabel': 'Suara',
'newproj.voicePlaceholder': 'ID suara provider, opsional',
'newproj.connectorsLabel': 'Konektor',
'newproj.connectorsHint': 'Sumber data yang bisa diambil artifact ini.',
'newproj.connectorsEmptyTitle': 'Belum ada konektor dikonfigurasi',
'newproj.connectorsEmptyBody': 'Hubungkan sumber data agar live artifact dapat mengambil angka nyata, bukan placeholder.',
'newproj.connectorsEmptyCta': 'Atur konektor ->',
'newproj.connectorsLoading': 'Memuat konektor...',
'newproj.connectorsCountOne': '{n} terhubung',
'newproj.connectorsCountMany': '{n} terhubung',
'newproj.connectorsManage': 'Kelola',
'newproj.promptTemplateLabel': 'Templat referensi',
'newproj.promptTemplateNoneTitle': 'Tidak ada - tulis sendiri',
'newproj.promptTemplateNoneSub': 'Lewati galeri, jelaskan brief sendiri',
'newproj.promptTemplateRefSub': 'Templat referensi',
'newproj.promptTemplateSearch': 'Cari templat...',
'newproj.promptTemplateEmpty': 'Belum ada templat untuk tipe ini.',
'newproj.promptTemplateBodyLabel': 'Prompt (bisa diedit)',
'newproj.promptTemplateOptimizeHint': 'Edit prompt sebelum membuat proyek agar sesuai dengan kebutuhanmu.',
'newproj.promptTemplateBodyEmpty': 'Prompt kosong - agent tidak menerima referensi templat.',
'designs.subRecent': 'Terbaru',
'designs.subYours': 'Desainmu',
'designs.filterAria': 'Filter proyek',
'designs.searchPlaceholder': 'Cari...',
'designs.emptyNoProjects': 'Belum ada proyek. Buat satu dari panel kiri.',
'designs.emptyNoMatch': 'Tidak ada proyek yang cocok dengan pencarianmu.',
'designs.deleteTitle': 'Hapus proyek',
'designs.deleteConfirm': 'Hapus "{name}"?',
'designs.cardFreeform': 'Bebas',
'designs.badgeLive': 'Live',
'designs.liveArtifactBadgesAria': 'Badge live artifact',
'designs.liveCount': '{n} live',
'designs.statusLive': 'Live artifact',
'designs.statusArchived': 'Diarsipkan',
'designs.statusError': 'Error',
'designs.statusRefreshing': 'Memperbarui...',
'designs.statusRefreshFailed': 'Refresh gagal',
'designs.statusRefreshed': 'Diperbarui',
'designs.status.notStarted': 'Belum dimulai',
'designs.status.queued': 'Dalam antrean',
'designs.status.running': 'Berjalan',
'designs.status.awaitingInput': 'Menunggu input',
'designs.status.succeeded': 'Selesai',
'designs.status.failed': 'Gagal',
'designs.status.canceled': 'Dibatalkan',
'designs.viewToggleAria': 'Mode tampilan',
'designs.viewGrid': 'Tampilan grid',
'designs.viewKanban': 'Tampilan kanban',
'designs.kanbanEmptyColumn': 'Tidak ada desain',
'designs.deleteAria': 'Hapus proyek {name}',
'examples.typeLabel': 'Tipe',
'examples.surfaceLabel': 'Surface',
'examples.surfaceWeb': 'Web',
'examples.surfaceImage': 'Gambar',
'examples.surfaceVideo': 'Video',
'examples.surfaceAudio': 'Audio',
'examples.scenarioLabel': 'Skenario',
'examples.modeAll': 'Semua',
'examples.modePrototypeDesktop': 'Prototype - desktop',
'examples.modePrototypeMobile': 'Prototype - mobile',
'examples.modeDeck': 'Slide',
'examples.modeDocument': 'Dokumen & templat',
'examples.modeOrbit': 'Orbit',
'examples.scenarioGeneral': 'Umum',
'examples.scenarioEngineering': 'Engineering',
'examples.scenarioProduct': 'Produk',
'examples.scenarioDesign': 'Desain',
'examples.scenarioMarketing': 'Marketing',
'examples.scenarioSales': 'Sales',
'examples.scenarioFinance': 'Keuangan',
'examples.scenarioHr': 'HR',
'examples.scenarioOperations': 'Operasi',
'examples.scenarioSupport': 'Support',
'examples.scenarioLegal': 'Legal',
'examples.scenarioEducation': 'Edukasi',
'examples.scenarioPersonal': 'Personal',
'examples.searchPlaceholder': 'Cari contoh...',
'examples.searchAria': 'Cari contoh berdasarkan nama',
'examples.emptyNoSkills': 'Tidak ada skill tersedia. Apakah daemon berjalan?',
'examples.emptyNoMatch': 'Tidak ada contoh yang cocok dengan filter ini.',
'examples.openPreview': 'Buka pratinjau',
'examples.loadingPreview': 'Memuat pratinjau...',
'examples.hoverPreview': 'Arahkan kursor untuk pratinjau',
'examples.usePrompt': 'Gunakan prompt ini',
'examples.previewModalTitle': 'Buka pratinjau penuh',
'examples.shareTitle': 'Bagikan contoh ini',
'examples.shareLoadFirst': 'Arahkan kursor dulu untuk memuat pratinjau',
'examples.shareMenu': 'Bagikan',
'examples.exportPdfAllSlides': 'Ekspor PDF (semua slide)',
'examples.exportPptxLocked': 'Ekspor PPTX... (buka templat dulu)',
'examples.tagSlideDeck': 'Slide deck',
'examples.tagTemplate': 'Templat',
'examples.tagDesignSystem': 'Sistem desain',
'examples.tagMobilePrototype': 'Prototype mobile',
'examples.tagDesktopPrototype': 'Prototype desktop',
'examples.tagImage': 'Gambar',
'examples.tagVideo': 'Video',
'examples.tagAudio': 'Audio',
'examples.previewLabel': 'Pratinjau',
'ds.surfaceLabel': 'Surface',
'ds.surfaceWeb': 'Web',
'ds.surfaceImage': 'Gambar',
'ds.surfaceVideo': 'Video',
'ds.surfaceAudio': 'Audio',
'ds.searchPlaceholder': 'Cari sistem desain...',
'ds.emptyNoMatch': 'Tidak ada sistem desain yang cocok.',
'ds.badgeDefault': 'Default',
'ds.preview': 'Pratinjau',
'ds.previewTitle': 'Pratinjau sistem desain',
'ds.categoryAll': 'Semua',
'ds.categoryUncategorized': 'Tanpa kategori',
'ds.showcase': 'Showcase',
'ds.tokens': 'Token',
'ds.specToggle': 'Spesifikasi',
'ds.specLoading': 'Memuat spesifikasi...',
'avatar.title': 'Akun & pengaturan',
'avatar.localCli': 'CLI lokal',
'avatar.anthropicApi': 'Anthropic API',
'avatar.useLocal': 'Gunakan CLI lokal',
'avatar.useApi': 'Gunakan Anthropic API',
'avatar.codeAgent': 'Code agent',
'avatar.rescan': 'Pindai ulang PATH',
'avatar.settings': 'Pengaturan',
'avatar.backToProjects': 'Kembali ke proyek',
'avatar.metaActive': 'aktif',
'avatar.metaOffline': 'offline',
'avatar.metaSelected': 'dipilih',
'avatar.noAgentSelected': 'Belum ada agent dipilih',
'avatar.modelSection': 'Model',
'avatar.modelLabel': 'Model',
'avatar.reasoningLabel': 'Penalaran',
'avatar.customSuffix': '(kustom)',
'project.backToProjects': 'Kembali ke proyek',
'project.metaFreeform': 'Bebas',
'project.resizeChatPanel': 'Ubah ukuran panel chat',
'chat.tabChat': 'Chat',
'chat.tabComments': 'Komentar',
'chat.commentsSoon': 'Komentar - segera hadir',
'chat.comments.attached': 'Dilampirkan ke chat',
'chat.comments.emptyAttached': 'Tidak ada komentar terlampir.',
'chat.comments.saved': 'Komentar tersimpan',
'chat.comments.emptySaved': 'Tidak ada komentar tersimpan.',
'chat.comments.add': 'Tambah',
'chat.comments.addAll': 'Tambah semua',
'chat.comments.remove': 'Hapus',
'chat.comments.placeholder': 'Komentari elemen ini...',
'chat.comments.addSend': 'Tambah & kirim',
'chat.comments.updateSend': 'Perbarui & kirim',
'chat.comments.removeAttachment': 'Hapus lampiran komentar',
'chat.comments.removeAttachmentAria': 'Hapus lampiran komentar untuk {name}',
'chat.conversationsTitle': 'Percakapan',
'chat.conversationsAria': 'Buka percakapan',
'chat.newConversation': 'Percakapan baru',
'chat.newConversationsTitle': 'Mulai percakapan baru',
'chat.conversationsHeading': 'Percakapan',
'chat.new': 'Baru',
'chat.emptyConversations': 'Belum ada percakapan.',
'chat.deleteConversation': 'Hapus percakapan',
'chat.deleteConversationConfirm': 'Hapus "{title}"? Semua pesannya ikut dihapus.',
'chat.untitledConversation': 'Percakapan tanpa judul',
'chat.startTitle': 'Mulai percakapan',
'chat.startHint': 'Jelaskan apa yang ingin kamu buat. Agent akan menulis file dan menampilkan pratinjau di sini.',
'chat.fillInputTitle': 'Isi brief dulu',
'chat.jumpToLatest': 'Lompat ke terbaru',
'chat.scrollToLatest': 'Scroll ke terbaru',
'chat.you': 'Kamu',
'chat.openFile': 'Buka {name}',
'chat.composerPlaceholder': 'Jelaskan desain, perubahan, atau artifact yang kamu inginkan...',
'chat.composerHint': 'Tekan Enter untuk kirim, Shift+Enter untuk baris baru.',
'chat.cliSettingsTitle': 'Pengaturan CLI',
'chat.cliSettingsAria': 'Buka pengaturan CLI',
'chat.attachTitle': 'Lampirkan',
'chat.attachAria': 'Lampirkan file atau konteks',
'chat.importTitle': 'Impor',
'chat.importLabel': 'Impor konteks',
'chat.importComingSoon': 'Segera hadir',
'chat.importSoon': 'Segera',
'chat.importFig': 'File desain',
'chat.importGitHub': 'GitHub',
'chat.importWeb': 'Web',
'chat.importFolder': 'Tautkan folder kode',
'chat.importSkills': 'Skills',
'chat.importProject': 'Proyek',
'chat.linkedFolderRemoveAria': 'Hapus folder tertaut {path}',
'chat.linkedFolderNotFound': 'Folder tidak ada',
'chat.linkedFolderAlready': 'Folder ini sudah tertaut',
'chat.linkedFolderPickError': 'Tidak bisa membuka pemilih folder',
'chat.send': 'Kirim',
'chat.stop': 'Stop',
'chat.removeAria': 'Hapus {name}',
'chat.example1Title': 'Pitch editorial',
'chat.example1Tag': 'Majalah',
'chat.example1Prompt': 'Buat pitch deck bergaya majalah untuk seed round startup AI.',
'chat.example2Title': 'Dashboard analitik SaaS',
'chat.example2Tag': 'Data',
'chat.example2Prompt':
'Buat dashboard analitik padat untuk SaaS developer tools dengan KPI, grafik MRR, peta heatmap penggunaan, kohort retensi, dan feed event real-time.',
'chat.example3Title': 'Laporan tahunan long-scroll',
'chat.example3Tag': 'Editorial',
'chat.example3Prompt': 'Buat laporan tahunan long-scroll dengan hero editorial, angka utama, timeline, dan visualisasi data.',
'preview.shareMenu': 'Bagikan',
'preview.openInNewTab': 'Buka di tab baru',
'preview.exit': 'Keluar',
'preview.fullscreen': 'Layar penuh',
'preview.closeTitle': 'Tutup pratinjau',
'preview.loading': 'Memuat {label}...',
'preview.showSidebar': 'Tampilkan {label}',
'preview.hideSidebar': 'Sembunyikan {label}',
'misc.savedTemplate': 'Templat tersimpan',
'misc.primary': 'Utama',
'misc.designSystem': 'Sistem desain',
'workspace.designFiles': 'File desain',
'workspace.focusMode': 'Fokus workspace',
'workspace.showChat': 'Tampilkan chat',
'workspace.closeTab': 'Tutup tab',
'workspace.deleteFileConfirm': 'Hapus "{name}" dari folder proyek?',
'workspace.openFromDesignFiles': 'Buka file dari',
'workspace.designFilesLink': 'File desain',
'workspace.loadingSketch': 'Memuat sketsa...',
'designFiles.title': 'File desain',
'designFiles.upload': 'Upload file',
'designFiles.pasteText': 'Tempel sebagai file teks',
'designFiles.newSketch': 'Sketsa baru',
'designFiles.empty': 'Belum ada file desain.',
'designFiles.refresh': 'Refresh',
'designFiles.delete': 'Hapus',
'designFiles.searchPlaceholder': 'Cari file...',
'designFiles.up': 'Naik',
'designFiles.back': 'Kembali',
'designFiles.crumbs': 'Proyek',
'designFiles.rowMenu': 'Menu baris',
'designFiles.openInTab': 'Buka di tab',
'designFiles.download': 'Unduh',
'designFiles.downloadSelected': 'Unduh {n} sebagai ZIP',
'designFiles.clearSelection': 'Bersihkan',
'designFiles.selectAll': 'Pilih semua',
'designFiles.dropTitle': 'Lepaskan file di sini',
'designFiles.dropDesc': 'Upload file desain, gambar, dokumen, atau aset lain ke proyek ini.',
'designFiles.upload.title': 'Upload file',
'designFiles.paste.title': 'Tempel teks sebagai file',
'designFiles.upload.label': 'Upload',
'designFiles.paste.label': 'Tempel',
'designFiles.previewOpen': 'Buka',
'designFiles.previewClose': 'Tutup pratinjau',
'designFiles.modified': 'Diubah {time} - {size}',
'designFiles.weeksAgo': '{n} minggu lalu',
'designFiles.sectionPages': 'Halaman',
'designFiles.sectionScripts': 'Skrip',
'designFiles.sectionImages': 'Gambar',
'designFiles.sectionSketches': 'Sketsa',
'designFiles.sectionLiveArtifacts': 'Live artifact',
'designFiles.sectionOther': 'Lainnya',
'designFiles.showMore': 'Tampilkan +{n} lagi',
'designFiles.kindHtml': 'Halaman HTML',
'designFiles.kindImage': 'Gambar',
'designFiles.kindSketch': 'Sketsa',
'designFiles.kindText': 'Teks',
'designFiles.kindCode': 'Skrip',
'designFiles.kindPdf': 'PDF',
'designFiles.kindDocument': 'Dokumen',
'designFiles.kindPresentation': 'Presentasi',
'designFiles.kindSpreadsheet': 'Spreadsheet',
'designFiles.kindLiveArtifact': 'Live artifact',
'designFiles.kindBinary': 'Biner',
'quickSwitcher.placeholder': 'Buka file...',
'quickSwitcher.empty': 'Tidak ada file di proyek ini',
'quickSwitcher.noMatches': 'Tidak ada yang cocok',
'quickSwitcher.navigate': 'navigasi',
'quickSwitcher.open': 'buka',
'quickSwitcher.close': 'tutup',
'pasteDialog.title': 'Tempel teks',
'pasteDialog.hint': 'Disimpan ke folder proyek. Pilih nama apa saja.',
'pasteDialog.fileNameLabel': 'Nama berkas',
'pasteDialog.namePlaceholder': 'catatan.txt',
'pasteDialog.contentLabel': 'Konten',
'pasteDialog.contentPlaceholder': 'Tempel apa saja...',
'pasteDialog.save': 'Simpan',
'pasteDialog.cancel': 'Batal',
'sketch.save': 'Simpan',
'sketch.cancel': 'Batal',
'sketch.saving': 'Menyimpan...',
'sketch.tooltipDirty': 'Ada perubahan belum disimpan',
'sketch.tooltipClean': 'Tersimpan',
'fileViewer.empty': 'Pilih file untuk dilihat.',
'fileViewer.loading': 'Memuat file...',
'fileViewer.exportPptx': 'Ekspor PPTX',
'fileViewer.openInNewTab': 'Buka di tab baru',
'fileViewer.copyPath': 'Salin path',
'fileViewer.copied': 'Tersalin',
'fileViewer.share': 'Bagikan',
'fileViewer.binaryMeta': 'Biner - {size}',
'fileViewer.binaryNote': 'Berkas biner ({size} byte). Unduh atau buka dari disk untuk memeriksanya.',
'fileViewer.pdfMeta': 'PDF - {size}',
'fileViewer.documentMeta': 'Dokumen',
'fileViewer.presentationMeta': 'Presentasi',
'fileViewer.spreadsheetMeta': 'Spreadsheet',
'fileViewer.previewUnavailable': 'Pratinjau tidak tersedia untuk file ini.',
'fileViewer.download': 'Unduh',
'fileViewer.open': 'Buka',
'fileViewer.imageMeta': 'Gambar - {size}',
'fileViewer.reactMeta': 'Komponen React - {size}',
'fileViewer.sketchMeta': 'Sketsa - {size}',
'fileViewer.markdownStreamingMeta': 'Memuat pratinjau...',
'fileViewer.markdownErrorMeta': 'Pratinjau mungkin belum lengkap (error generasi).',
'fileViewer.markdownStreamingStatus': 'Memuat... menampilkan markdown sebagian.',
'fileViewer.markdownErrorStatus': 'Error generasi. Menampilkan konten terakhir yang tersedia.',
'fileViewer.videoMeta': 'Video - {size}',
'fileViewer.audioMeta': 'Audio - {size}',
'fileViewer.reload': 'Muat ulang',
'fileViewer.reloadDisk': 'Muat ulang dari disk',
'fileViewer.copy': 'Salin',
'fileViewer.copyTitle': 'Salin konten',
'fileViewer.saveDisabled': 'Tidak ada perubahan untuk disimpan',
'fileViewer.save': 'Simpan',
'fileViewer.preview': 'Pratinjau',
'fileViewer.source': 'Sumber',
'fileViewer.tweaks': 'Tweaks',
'fileViewer.comment': 'Komentar',
'fileViewer.edit': 'Edit',
'fileViewer.draw': 'Gambar',
'manualEdit.layers': 'Lapisan',
'manualEdit.editableCount': '{count} dapat diedit',
'manualEdit.title': 'Editor manual',
'manualEdit.selectLayer': 'Pilih lapisan',
'manualEdit.empty': 'Klik elemen di pratinjau atau pilih lapisan.',
'manualEdit.noClass': 'tanpa class',
'manualEdit.tabsAria': 'Tab edit manual',
'manualEdit.tabContent': 'Konten',
'manualEdit.tabStyle': 'Gaya',
'manualEdit.tabAttributes': 'Atribut',
'manualEdit.tabHtml': 'HTML',
'manualEdit.tabSource': 'Sumber',
'manualEdit.attributesJson': 'JSON atribut',
'manualEdit.selectedHtml': 'HTML elemen terpilih',
'manualEdit.fullSource': 'Sumber artifact lengkap',
'manualEdit.applyContent': 'Terapkan konten',
'manualEdit.applyStyle': 'Terapkan gaya',
'manualEdit.applyAttributes': 'Terapkan atribut',
'manualEdit.applyHtml': 'Terapkan HTML',
'manualEdit.applySource': 'Terapkan sumber',
'manualEdit.invalidAttributes': 'JSON atribut tidak valid.',
'manualEdit.changes': 'Perubahan',
'manualEdit.undo': 'Undo',
'manualEdit.redo': 'Redo',
'manualEdit.noChanges': 'Belum ada edit manual.',
'manualEdit.imageUrl': 'URL gambar',
'manualEdit.altText': 'Teks alt',
'manualEdit.label': 'Label',
'manualEdit.text': 'Teks',
'manualEdit.href': 'Href',
'manualEdit.textColor': 'Warna teks',
'manualEdit.background': 'Latar belakang',
'manualEdit.fontSize': 'Ukuran font',
'manualEdit.weight': 'Bobot',
'manualEdit.align': 'Rata',
'manualEdit.padding': 'Padding',
'manualEdit.margin': 'Margin',
'manualEdit.radius': 'Radius',
'manualEdit.border': 'Border',
'manualEdit.width': 'Lebar',
'manualEdit.minHeight': 'Tinggi minimum',
'fileViewer.zoomOut': 'Perkecil',
'fileViewer.zoomIn': 'Perbesar',
'fileViewer.resetZoom': 'Atur ulang zoom',
'fileViewer.reloadAria': 'Muat ulang file',
'fileViewer.previousSlide': 'Slide sebelumnya',
'fileViewer.nextSlide': 'Slide berikutnya',
'fileViewer.slideNavAria': 'Navigasi slide',
'fileViewer.present': 'Presentasikan',
'fileViewer.presentInTab': 'Presentasikan di tab',
'fileViewer.presentFullscreen': 'Presentasi layar penuh',
'fileViewer.presentNewTab': 'Presentasi di tab baru',
'fileViewer.exitPresentation': 'Keluar presentasi',
'fileViewer.shareLabel': 'Bagikan',
'fileViewer.exportPdf': 'Ekspor PDF',
'fileViewer.exportPdfAllSlides': 'Ekspor PDF semua slide',
'fileViewer.exportPptxBusy': 'Mengekspor PPTX...',
'fileViewer.exportPptxHint': 'Buat deck terlebih dahulu untuk mengekspor PPTX.',
'fileViewer.exportPptxNa': 'PPTX tidak tersedia',
'fileViewer.exportZip': 'Ekspor ZIP',
'fileViewer.exportHtml': 'Ekspor HTML',
'fileViewer.exportMd': 'Ekspor Markdown',
'fileViewer.exportJsx': 'Ekspor JSX',
'fileViewer.exportReactHtml': 'Ekspor React HTML',
'fileViewer.saveAsTemplate': 'Simpan sebagai templat',
'fileViewer.savingTemplate': 'Menyimpan templat...',
'fileViewer.savedTemplate': 'Disimpan sebagai "{name}"',
'fileViewer.savedTemplateFail': 'Gagal menyimpan templat',
'fileViewer.templateNamePrompt': 'Nama templat',
'fileViewer.templateNameDefault': 'Templat baru',
'fileViewer.templateDescPrompt': 'Deskripsi templat',
'liveArtifact.refresh.button': 'Refresh',
'liveArtifact.refresh.buttonTitle': 'Refresh live artifact ini',
'liveArtifact.refresh.loadingTitle': 'Memuat live artifact...',
'liveArtifact.refresh.noSourceTitle': 'Belum ada sumber refresh yang tersedia.',
'liveArtifact.refresh.running': 'Memperbarui...',
'liveArtifact.refresh.runningMessage': 'Memperbarui data dan pratinjau. Ini bisa butuh waktu sebentar.',
'liveArtifact.refresh.runningAction': 'Pratinjau sebelumnya tetap terlihat sampai refresh berhasil.',
'liveArtifact.refresh.successOne': 'Refresh selesai. Data diperbarui.',
'liveArtifact.refresh.successMany': 'Refresh selesai. Data diperbarui.',
'liveArtifact.refresh.successAction': 'Pratinjau sudah dimuat ulang dengan data committed terbaru.',
'liveArtifact.refresh.previousFailure': 'Refresh sebelumnya gagal: {message}',
'liveArtifact.refresh.failureAction': 'Periksa riwayat refresh, perbaiki sumber atau masalah izin, lalu coba lagi.',
'liveArtifact.refresh.networkFailure': 'Permintaan refresh gagal. Periksa koneksi lalu coba lagi.',
'liveArtifact.refresh.genericFailure': 'Refresh gagal.',
'liveArtifact.refresh.statusNever': 'Tidak bisa di-refresh',
'liveArtifact.refresh.statusReady': 'Siap di-refresh',
'liveArtifact.refresh.statusSucceeded': 'Sudah terbaru',
'liveArtifact.refresh.statusFailed': 'Refresh gagal',
'fileViewer.deployToVercel': 'Deploy ke Vercel',
'fileViewer.redeployToVercel': 'Deploy ulang ke Vercel',
'fileViewer.deployingToVercel': 'Deploying ke Vercel...',
'fileViewer.preparingPublicLink': 'Menyiapkan link publik...',
'fileViewer.copyDeployLink': 'Salin link deploy',
'fileViewer.deployModalTitle': 'Deploy ke Vercel',
'fileViewer.deployModalSubtitle': 'Masukkan token Vercel untuk membuat link publik.',
'fileViewer.vercelToken': 'Token Vercel',
'fileViewer.vercelTokenGetLink': 'Buat token',
'fileViewer.vercelTokenPlaceholder': 'Tempel token Vercel',
'fileViewer.vercelTokenReuseHint': 'Token disimpan lokal untuk deploy berikutnya.',
'fileViewer.vercelTokenRequired': 'Token Vercel wajib diisi.',
'fileViewer.vercelTeamId': 'Team ID Vercel',
'fileViewer.vercelTeamSlug': 'Team slug Vercel',
'fileViewer.optional': 'opsional',
'fileViewer.vercelPreviewOnly': 'Buat preview deployment saja',
'fileViewer.savingConfig': 'Menyimpan konfigurasi...',
'fileViewer.deployConfigSaveFailed': 'Gagal menyimpan konfigurasi deploy.',
'fileViewer.deployFailed': 'Deploy gagal.',
'fileViewer.deployResultLabel': 'Hasil deploy',
'fileViewer.deployLinkPreparingLabel': 'Link deploy sedang disiapkan',
'fileViewer.deployLinkDelayed': 'Link publik belum siap. Coba lagi sebentar lagi.',
'fileViewer.deployLinkProtectedLabel': 'Deployment dilindungi',
'fileViewer.deployLinkProtected': 'Vercel meminta autentikasi untuk membuka link ini.',
'fileViewer.retryLink': 'Coba link lagi',
'questionForm.submit': 'Kirim',
'questionForm.skip': 'Lewati',
'questionForm.locked': 'Terkunci',
'conv.switch': 'Ganti percakapan',
'conv.label': 'Percakapan',
'conv.heading': 'Percakapan',
'conv.new': 'Baru',
'conv.empty': 'Belum ada percakapan.',
'conv.untitled': 'Tanpa judul',
'conv.renameTooltip': 'Ganti nama percakapan',
'conv.delete': 'Hapus percakapan',
'conv.deleteConfirm': 'Hapus "{title}"? Semua pesannya ikut dihapus.',
'agentPicker.label': 'Agent',
'agentPicker.modeChoose': 'Pilih mode',
'agentPicker.localCli': 'CLI lokal',
'agentPicker.daemonOff': 'Daemon mati',
'agentPicker.byok': 'BYOK',
'agentPicker.selectAgent': 'Pilih agent',
'agentPicker.noAgents': 'Tidak ada agent',
'agentPicker.notInstalled': 'Belum terpasang',
'agentPicker.rescan': 'Pindai ulang',
'tool.openInTab': 'Buka {name} di tab',
'tool.open': 'Buka',
'tool.todos': 'Todo',
'tool.write': 'Tulis',
'tool.edit': 'Edit',
'tool.read': 'Baca',
'tool.bash': 'Bash',
'tool.glob': 'Glob',
'tool.grep': 'Grep',
'tool.fetch': 'Fetch',
'tool.search': 'Cari',
'tool.lines': '{n} baris',
'tool.changeSingular': 'perubahan',
'tool.changePlural': 'perubahan',
'tool.in': 'di {path}',
'tool.hide': 'Sembunyikan',
'tool.output': 'Output',
'tool.running': 'Berjalan',
'tool.error': 'Error',
'tool.done': 'Selesai',
'assistant.role': 'Asisten',
'assistant.workingLabel': 'Sedang bekerja',
'assistant.doneLabel': 'Selesai',
'assistant.unfinishedLabel': 'Belum selesai',
'assistant.unfinishedSummary': '{n} tugas tersisa',
'assistant.unfinishedMore': '+{n} lagi',
'assistant.continueRemaining': 'Lanjutkan',
'assistant.outTokens': '{n} keluar',
'assistant.producedFiles': 'File yang dibuat',
'assistant.openFile': 'Buka file',
'assistant.downloadFile': 'Unduh file',
'assistant.thinking': 'Berpikir...',
'assistant.systemReminder': 'Pengingat sistem',
'assistant.waitingFirstOutput': 'Menunggu output pertama...',
'assistant.statusBootingAgent': 'Menyalakan agent...',
'assistant.statusStarting': 'Memulai...',
'assistant.statusRequesting': 'Mengirim permintaan...',
'assistant.statusThinking': 'Berpikir...',
'assistant.statusStreaming': 'Memuat...',
'assistant.slowHint': 'Ini mungkin butuh waktu sebentar.',
'assistant.verbEditing': 'mengedit',
'assistant.verbWriting': 'menulis',
'assistant.verbReading': 'membaca',
'assistant.verbSearching': 'mencari',
'assistant.verbRunning': 'menjalankan',
'assistant.verbTodos': 'memperbarui todo',
'assistant.verbFetching': 'mengambil',
'assistant.verbCalling': 'memanggil',
'qf.answered': 'Terjawab',
'qf.choose': 'Pilih',
'qf.required': 'Wajib',
'qf.lockedSubmitted': 'Jawaban terkunci setelah dikirim.',
'qf.lockedPrev': 'Jawaban sebelumnya',
'qf.hint': 'Pilih opsi atau isi jawaban singkat.',
'qf.submitDefault': 'Kirim jawaban',
'qf.submitDisabledTitle': 'Lengkapi pertanyaan wajib dulu.',
'qf.submitTitle': 'Kirim jawaban',
'qf.cardSelected': 'Dipilih',
'qf.cardRefs': 'Referensi',
'qf.cardSampleText': 'Contoh teks',
'sketch.toolSelect': 'Pilih',
'sketch.toolPen': 'Pena',
'sketch.toolText': 'Teks',
'sketch.toolRect': 'Kotak',
'sketch.toolArrow': 'Panah',
'sketch.toolEraser': 'Penghapus',
'sketch.color': 'Warna',
'sketch.strokeSize': 'Ukuran garis',
'sketch.undo': 'Undo',
'sketch.clear': 'Bersihkan',
'sketch.close': 'Tutup',
'sketch.textPrompt': 'Teks',
'pet.title': 'Teman kerja',
'pet.subtitle': 'Pilih teman kecil untuk melayang di workspace.',
'pet.navTitle': 'Pets',
'pet.navHint': 'Pilih teman untuk melayang di workspace.',
'pet.tabBuiltIn': 'Bawaan',
'pet.tabBuiltInHint': 'Pet pilihan yang disertakan dengan Open Design - pilih satu lalu adopsi.',
'pet.builtInEmpty': 'Pet bawaan belum tersedia. Coba refresh tab Komunitas setelah daemon online.',
'pet.tabCustom': 'Kustom',
'pet.tabCustomHint': 'Buat sendiri dengan nama, glyph, warna, atau sprite.',
'pet.tabCommunity': 'Komunitas',
'pet.tabCommunityHint': 'Pet hasil hatch dari Codex - adopsi satu atau buat yang baru.',
'pet.tabsAria': 'Sumber pet',
'pet.adopt': 'Adopsi pet',
'pet.adoptedBadge': 'Diadopsi',
'pet.adoptCallout': 'Pet aktif akan muncul di workspace.',
'pet.changePet': 'Ganti pet',
'pet.wake': 'Bangunkan',
'pet.tuck': 'Tidurkan',
'pet.wakeTitle': 'Tampilkan pet',
'pet.tuckTitle': 'Sembunyikan pet',
'pet.settingsTitle': 'Kustomisasi pet',
'pet.useCustom': 'Gunakan kustom',
'pet.customTitle': 'Kustom Pet',
'pet.customHint': 'Buat nama, simbol, dan sapaan sendiri.',
'pet.customGreetingPlaceholder': 'Halo, aku siap membantu.',
'pet.fieldName': 'Nama',
'pet.fieldGlyph': 'Glyph',
'pet.fieldGlyphHint': 'Satu karakter atau simbol singkat.',
'pet.fieldGreeting': 'Sapaan',
'pet.fieldAccent': 'Aksen',
'pet.fieldAccentCustom': 'Kustom',
'pet.overlayAria': 'Overlay pet',
'pet.spriteAria': '{name} - geser untuk memindahkan, klik untuk chat',
'pet.spriteTitle': 'Halo dari {name}! Klik untuk chat.',
'pet.railAria': 'Panel pet',
'pet.railTitle': 'Pets',
'pet.railHint': 'Pilih teman untuk melayang di workspace.',
'pet.railExpand': 'Perluas panel pet',
'pet.railCollapse': 'Ciutkan panel pet',
'pet.railHide': 'Sembunyikan panel pet',
'pet.railShow': 'Tampilkan panel pet',
'pet.railCustomFlavor': 'Punyamu sendiri - nama, glyph, warna.',
'pet.railCustomize': 'Kustomisasi...',
'pet.composerTitle': 'Pet',
'pet.composerMenuTitle': 'Perintah pet',
'pet.composerMenuHint': 'Kelola pet dari composer.',
'pet.composerOpenSettings': 'Buka pengaturan pet',
'pet.welcomeTeaserTitle': 'Tambahkan teman kecil',
'pet.welcomeTeaserBody': 'Pet bisa menemani workspace saat agent bekerja.',
'pet.welcomeTeaserCta': 'Pilih pet',
'pet.imageUpload': 'Upload sprite',
'pet.imageReplace': 'Ganti sprite',
'pet.imageRemove': 'Gunakan emoji',
'pet.imageHintIdle': 'PNG, JPG, WebP, GIF, atau SVG. Upload sheet? Letakkan strip horizontal dan atur jumlah frame.',
'pet.imageHintActive': 'Sprite kamu sedang ditampilkan. Atur frame > 1 untuk menjalankan spritesheet horizontal.',
'pet.fieldFrames': 'Frame',
'pet.fieldFramesHint': '1 = statis. > 1 = spritesheet horizontal.',
'pet.fieldFps': 'Kecepatan (fps)',
'pet.fieldFpsHint': 'Seberapa cepat frame berganti.',
'pet.atlasImport': 'Impor sprite Codex',
'pet.atlasImportTitle': 'Impor atlas hatch-pet 8x9 / 192x208 (PNG atau WebP).',
'pet.atlasPickerTitle': 'Pilih baris animasi',
'pet.atlasPickerHint':
'Pet Codex memiliki 9 baris animasi. Secara default, atlas penuh dipertahankan agar pet mengganti baris saat hover, drag, dan idle. Kamu juga bisa membekukannya ke satu loop.',
'pet.atlasCancel': 'Buang atlas',
'pet.atlasAdopt': 'Bekukan ke baris ini',
'pet.atlasAdoptFull': 'Gunakan atlas penuh (animasi)',
'pet.atlasAdoptFullTitle': 'Pertahankan semua baris agar pet bereaksi terhadap hover, arah drag, dan idle lama.',
'pet.atlasAdoptRowTitle': 'Potong baris yang disorot menjadi satu strip loop.',
'pet.atlasActiveHint': 'Atlas animasi aktif - pet memilih baris dari interaksimu (hover, drag, idle).',
'pet.atlasRow.idle': 'Idle',
'pet.atlasRow.running-right': 'Lari kanan',
'pet.atlasRow.running-left': 'Lari kiri',
'pet.atlasRow.waving': 'Melambai',
'pet.atlasRow.jumping': 'Melompat',
'pet.atlasRow.failed': 'Gagal',
'pet.atlasRow.waiting': 'Menunggu',
'pet.atlasRow.running': 'Berjalan',
'pet.atlasRow.review': 'Review',
'pet.hatchTitle': 'Hatch pet baru dengan AI',
'pet.hatchHint': 'Gunakan skill hatch-pet bawaan di chat untuk membuat spritesheet bergaya Codex, lalu impor di sini.',
'pet.hatchConcept': 'Konsep pet (opsional)',
'pet.hatchConceptPlaceholder': 'mis. shiba pixel-art kecil memakai sweater nyaman',
'pet.hatchCopy': 'Salin prompt',
'pet.hatchCopied': 'Tersalin!',
'pet.hatchFoot': 'Setelah skill menyimpan pet, kembali ke sini dan pilih "Impor sprite Codex".',
'pet.slashPopoverAria': 'Perintah slash',
'pet.slashPopoverTitle': 'Perintah',
'pet.slashPopoverHint': 'atas/bawah untuk navigasi - enter untuk pilih - esc untuk tutup',
'pet.slashPet': 'Toggle, adopsi, atau buka pengaturan pet.',
'pet.slashPetWake': 'Bangunkan overlay pet melayang.',
'pet.slashPetTuck': 'Sembunyikan pet untuk sekarang.',
'pet.slashHatch': 'Buat pet Codex lewat skill hatch-pet.',
'pet.slashHatchArg': '<konsep>',
'pet.codexTitle': 'Baru di-hatch',
'pet.codexSubtitle': 'Pet yang dikemas oleh skill hatch-pet muncul di sini untuk adopsi sekali klik.',
'pet.codexSubtitleWithDir': 'Memindai {dir} untuk pet yang dikemas oleh skill hatch-pet.',
'pet.codexEmpty': 'Belum ada pet hasil hatch. Ketik /hatch di chat untuk membuat satu.',
'pet.codexLoading': 'Mencari pet hasil hatch...',
'pet.codexRefresh': 'Refresh',
'pet.codexAdopt': 'Adopsi',
'pet.codexAdopting': 'Mengadopsi...',
'pet.communitySync': 'Unduh pet komunitas',
'pet.communitySyncing': 'Mengunduh...',
'pet.communitySyncTitle': 'Sinkronkan pet terbaru dari Codex Pet Share + j20 Hatchery ke ~/.codex/pets/.',
'pet.communitySyncDone': 'Tersinkron {wrote} pet baru ({total} total).',
'pet.communitySyncFailed': 'Sinkronisasi gagal: {error}',
'pet.codexBundled': 'Bawaan',
'pet.codexBundledTitle': 'Disertakan dengan Open Design - tidak perlu diunduh.',
'settings.notifications': 'Notifikasi',
'settings.notificationsHint': 'Atur suara dan notifikasi desktop.',
'settings.notifyCompletionSound': 'Suara saat selesai',
'settings.notifyCompletionSoundHint': 'Putar suara ketika generasi selesai.',
'settings.notifySuccessSound': 'Suara berhasil',
'settings.notifyFailureSound': 'Suara gagal',
'settings.notifyDesktop': 'Notifikasi desktop',
'settings.notifyDesktopHint': 'Tampilkan notifikasi sistem saat generasi selesai.',
'settings.notifyDesktopBlocked': 'Notifikasi diblokir oleh browser.',
'settings.notifyDesktopUnsupported': 'Browser ini tidak mendukung notifikasi desktop.',
'settings.notifyTest': 'Tes notifikasi',
'settings.notifyTestSent': 'Notifikasi tes terkirim.',
'settings.notifyTestFailed': 'Gagal mengirim notifikasi tes.',
'settings.notifySoundDing': 'Ding',
'settings.notifySoundChime': 'Chime',
'settings.notifySoundTwoToneUp': 'Dua nada naik',
'settings.notifySoundPluck': 'Pluck',
'settings.notifySoundBuzz': 'Buzz',
'settings.notifySoundTwoToneDown': 'Dua nada turun',
'settings.notifySoundThud': 'Thud',
'settings.library': 'Skill & Sistem Desain',
'settings.libraryHint': 'Jelajahi, pratinjau, dan aktifkan/nonaktifkan library kontenmu',
'settings.librarySkills': 'Skill',
'settings.libraryDesignSystems': 'Sistem desain',
'settings.librarySearch': 'Cari...',
'settings.libraryAll': 'Semua',
'settings.libraryPreview': 'Pratinjau',
'settings.libraryPreviewClose': 'Tutup',
'settings.libraryLoading': 'Memuat...',
'settings.libraryNoResults': 'Tidak ada item yang cocok dengan pencarianmu.',
'settings.libraryEnabled': 'Aktif',
'settings.libraryDisabled': 'Nonaktif',
'settings.libraryToggleLabel': 'Toggle',
'notify.successTitle': 'Pembuatan selesai',
'notify.failureTitle': 'Pembuatan gagal',
'notify.successBody': 'Artifact siap dilihat.',
'notify.failureBody': 'Cek chat untuk detail error.',
};
+3 -2
View File
@@ -1,11 +1,12 @@
// Supported UI locales. Adding a new locale requires creating a new
// dictionary in `./locales/` and registering it in `./index.tsx`.
export type Locale = 'en' | 'de' | 'zh-CN' | 'zh-TW' | 'pt-BR' | 'es-ES' | 'ru' | 'fa' | 'ar' | 'ja' | 'ko' | 'pl' | 'hu' | 'fr' | 'uk' | 'tr';
export type Locale = 'en' | 'id' | 'de' | 'zh-CN' | 'zh-TW' | 'pt-BR' | 'es-ES' | 'ru' | 'fa' | 'ar' | 'ja' | 'ko' | 'pl' | 'hu' | 'fr' | 'uk' | 'tr';
export const LOCALES: Locale[] = ['en', 'de', 'zh-CN', 'zh-TW', 'pt-BR', 'es-ES', 'ru', 'fa', 'ar', 'ja', 'ko', 'pl', 'hu', 'fr', 'uk', 'tr'];
export const LOCALES: Locale[] = ['en', 'id', 'de', 'zh-CN', 'zh-TW', 'pt-BR', 'es-ES', 'ru', 'fa', 'ar', 'ja', 'ko', 'pl', 'hu', 'fr', 'uk', 'tr'];
export const LOCALE_LABEL: Record<Locale, string> = {
'en': 'English',
'id': 'Bahasa Indonesia',
'de': 'Deutsch',
'zh-CN': '简体中文',
'zh-TW': '繁體中文',
@@ -5,6 +5,7 @@ import { en } from '../../src/i18n/locales/en';
import { esES } from '../../src/i18n/locales/es-ES';
import { fa } from '../../src/i18n/locales/fa';
import { fr } from '../../src/i18n/locales/fr';
import { id } from '../../src/i18n/locales/id';
import { ja } from '../../src/i18n/locales/ja';
import { ptBR } from '../../src/i18n/locales/pt-BR';
import { ru } from '../../src/i18n/locales/ru';
@@ -17,6 +18,7 @@ const LOCALE_DICTS = {
esES,
fa,
fr,
id,
ja,
ptBR,
ru,
@@ -5,6 +5,7 @@ import { en } from '../../src/i18n/locales/en';
import { esES } from '../../src/i18n/locales/es-ES';
import { fa } from '../../src/i18n/locales/fa';
import { fr } from '../../src/i18n/locales/fr';
import { id } from '../../src/i18n/locales/id';
import { ja } from '../../src/i18n/locales/ja';
import { ptBR } from '../../src/i18n/locales/pt-BR';
import { ru } from '../../src/i18n/locales/ru';
@@ -17,6 +18,7 @@ const LOCALE_DICTS = {
esES,
fa,
fr,
id,
ja,
ptBR,
ru,
+2 -1
View File
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
import { en } from '../../src/i18n/locales/en';
import { LOCALES, LOCALE_LABEL, type Dict, type Locale } from '../../src/i18n/types';
const EXPECTED_LOCALES = ['en', 'de', 'zh-CN', 'zh-TW', 'pt-BR', 'es-ES', 'ru', 'fa', 'ar', 'ja', 'ko', 'pl', 'hu', 'fr', 'uk', 'tr'];
const EXPECTED_LOCALES = ['en', 'id', 'de', 'zh-CN', 'zh-TW', 'pt-BR', 'es-ES', 'ru', 'fa', 'ar', 'ja', 'ko', 'pl', 'hu', 'fr', 'uk', 'tr'];
function placeholders(value: string): string[] {
const names: string[] = [];
@@ -28,6 +28,7 @@ async function loadDict(locale: Locale): Promise<Dict> {
describe('i18n locales', () => {
it('registers every supported locale in the language menu', () => {
expect(LOCALES).toEqual(EXPECTED_LOCALES);
expect((LOCALE_LABEL as Record<string, string>).id).toBe('Bahasa Indonesia');
expect((LOCALE_LABEL as Record<string, string>).de).toBe('Deutsch');
expect((LOCALE_LABEL as Record<string, string>).ja).toBe('日本語');
});