diff --git a/src/renderer/src/assets/fonts/LICENSE.txt b/src/renderer/src/assets/fonts/LICENSE.txt index 92d8221ca2..8d89c0b135 100644 --- a/src/renderer/src/assets/fonts/LICENSE.txt +++ b/src/renderer/src/assets/fonts/LICENSE.txt @@ -7,7 +7,8 @@ the SIL Open Font License, Version 1.1, whose full text follows the attributions below. The OFL requires this notice to travel with every copy of the software. press-start-2p-latin-400.woff2 - Press Start 2P (latin subset, weight 400) + Press Start 2P (latin subset plus the Turkish letters I-dot, G-breve and + S-cedilla, weight 400) Copyright (c) 2012, Cody "CodeMan38" Boisclair (cody@zone38.net) https://fonts.google.com/specimen/Press+Start+2P diff --git a/src/renderer/src/assets/fonts/press-start-2p-latin-400.woff2 b/src/renderer/src/assets/fonts/press-start-2p-latin-400.woff2 index cefec4c16c..41c1bb85d6 100644 Binary files a/src/renderer/src/assets/fonts/press-start-2p-latin-400.woff2 and b/src/renderer/src/assets/fonts/press-start-2p-latin-400.woff2 differ diff --git a/src/renderer/src/design/fonts.css b/src/renderer/src/design/fonts.css index 2996117310..87c5236a2b 100644 --- a/src/renderer/src/design/fonts.css +++ b/src/renderer/src/design/fonts.css @@ -13,6 +13,13 @@ * when every OS we ship on already has a good one. The token stacks in * tokens.css name those system faces instead. * + * Press Start 2P's latin subset also carries İ Ğ ğ Ş ş (U+0130, U+011E-011F, + * U+015E-015F), cut from the same upstream OFL file. Without them the Turkish + * locale's pixel headings fell back glyph by glyph to a CJK system face, so + * "DİL" read "D:L" and "Bağlantılar" read "Ba;lantılar". Ç ç Ö ö Ü ü ı were + * already in the latin subset. Inter and JetBrains Mono fall back to the system + * sans/mono for those five letters, which looks the same at body sizes. + * * Vite fingerprints and inlines these URLs at build time, so the paths below are * source paths, not runtime ones. */ diff --git a/src/renderer/src/i18n/index.ts b/src/renderer/src/i18n/index.ts index 3068eb7a62..9a5c53b7e7 100644 --- a/src/renderer/src/i18n/index.ts +++ b/src/renderer/src/i18n/index.ts @@ -21,6 +21,7 @@ import { DEFAULT_GOD_NAME } from '@shared/godIdentity'; import en from './locales/en.json'; import zhCN from './locales/zh-CN.json'; import ar from './locales/ar.json'; +import tr from './locales/tr.json'; /** * The languages the Settings picker offers, in display order. @@ -35,7 +36,8 @@ import ar from './locales/ar.json'; export const LANGUAGES = [ { code: 'en', label: 'English', dir: 'ltr' }, { code: 'zh-CN', label: '简体中文', dir: 'ltr' }, - { code: 'ar', label: 'العربية', dir: 'rtl' } + { code: 'ar', label: 'العربية', dir: 'rtl' }, + { code: 'tr', label: 'Türkçe', dir: 'ltr' } ] as const; export type LanguageCode = (typeof LANGUAGES)[number]['code']; @@ -110,11 +112,12 @@ void i18n resources: { en: { translation: en }, 'zh-CN': { translation: zhCN }, - ar: { translation: ar } + ar: { translation: ar }, + tr: { translation: tr } }, lng: detectLanguage(), fallbackLng: 'en', - supportedLngs: ['en', 'zh-CN', 'ar'], + supportedLngs: ['en', 'zh-CN', 'ar', 'tr'], // Resources are bundled inline, so nothing ever suspends — the string is // there at init time. Keeping this false lets every component call // useTranslation() without wrapping the tree in . diff --git a/src/renderer/src/i18n/locales/ar.json b/src/renderer/src/i18n/locales/ar.json index fe74ab7ebc..0efe9ae522 100644 --- a/src/renderer/src/i18n/locales/ar.json +++ b/src/renderer/src/i18n/locales/ar.json @@ -1405,5 +1405,45 @@ "viewSource": "عرض المصدر", "loading": "جارٍ تحميل الصورة…", "decodeFailed": "تعذّر فك ترميز هذه الصورة — قد يكون الملف تالفًا أو امتداده خاطئًا" + }, + "demoFloor": { + "headingTo": { + "shelf": "يتجه إلى الرف", + "terminal": "يتجه إلى الطرفية", + "web": "يتجه إلى الويب", + "board": "يتجه إلى اللوحة", + "mailbox": "يتجه إلى صندوق البريد", + "mcp": "يتجه إلى MCP", + "desk": "يتجه إلى المكتب" + }, + "headingBackToDesk": "يعود إلى المكتب", + "awaiting": "في الانتظار", + "doneWhatNext": "انتهيت من هذه. ما التالي؟", + "samples": { + "read": { + "what": "يقرأ SPEC.md", + "thought": "أفتح المواصفات لأتأكد من آلة الحالات قبل أن ألمس التنفيذ." + }, + "edit": { + "what": "يحرر PixelPanel.tsx", + "thought": "أضبط حساب حدود اللوحة — الخط الداخلي كان منزاحًا بكسلًا واحدًا في الوضع المضمّن." + }, + "bash": { + "what": "يشغّل الاختبارات", + "thought": "أشغّل مجموعة اختبارات الواجهة لأتأكد أن شيئًا لم يتراجع قبل أن أكمل." + }, + "webFetch": { + "what": "يجلب الوثائق", + "thought": "أجلب وثيقة الخطافات لأتحقق من بنية حمولة PreToolUse — لا أتذكر أسماء الحقول جيدًا." + }, + "glob": { + "what": "يبحث عن ملفات المهارات", + "thought": "أعدّد كل ملفات المهارات لأمرّ عليها واحدًا واحدًا بحثًا عن مسارات سكربتات قديمة." + }, + "todoWrite": { + "what": "يحدّث لوحة المهام", + "thought": "أقسّم العمل المتبقي إلى أربع مهام منفصلة لأتابعها أثناء التقدم." + } + } } } diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json index 68aac27438..eee41b644f 100644 --- a/src/renderer/src/i18n/locales/en.json +++ b/src/renderer/src/i18n/locales/en.json @@ -1405,5 +1405,45 @@ "viewSource": "view source", "loading": "loading image…", "decodeFailed": "could not decode this image — the file may be corrupt or misnamed" + }, + "demoFloor": { + "headingTo": { + "shelf": "heading to shelf", + "terminal": "heading to terminal", + "web": "heading to web", + "board": "heading to board", + "mailbox": "heading to mailbox", + "mcp": "heading to mcp", + "desk": "heading to desk" + }, + "headingBackToDesk": "heading back to desk", + "awaiting": "awaiting", + "doneWhatNext": "Done with that one. What next?", + "samples": { + "read": { + "what": "reading SPEC.md", + "thought": "Pulling up the spec so I can confirm the state machine before touching the implementation." + }, + "edit": { + "what": "editing PixelPanel.tsx", + "thought": "Tightening up the panel border math — the inner stroke was a pixel off in inset mode." + }, + "bash": { + "what": "running tests", + "thought": "Running the renderer suite to make sure nothing regressed before I move on." + }, + "webFetch": { + "what": "fetching docs", + "thought": "Grabbing the hooks doc to double-check the PreToolUse payload shape — my memory of the field names is hazy." + }, + "glob": { + "what": "searching for skill files", + "thought": "Enumerating all the skill files so I can walk each one and look for stale script paths." + }, + "todoWrite": { + "what": "updating the todo board", + "thought": "Splitting the remaining work into four discrete tasks so I can track them as I go." + } + } } } diff --git a/src/renderer/src/i18n/locales/tr.json b/src/renderer/src/i18n/locales/tr.json new file mode 100644 index 0000000000..7f5d63cc17 --- /dev/null +++ b/src/renderer/src/i18n/locales/tr.json @@ -0,0 +1,1449 @@ +{ + "common": { + "on": "açık", + "off": "kapalı", + "cancel": "iptal", + "save": "kaydet", + "close": "kapat", + "back": "geri", + "next": "ileri", + "finish": "bitir", + "saving": "kaydediliyor...", + "copy": "kopyala", + "delete": "sil", + "hide": "gizle", + "show": "göster", + "search": "ara", + "tokens": "token", + "restarting": "yeniden başlatılıyor…", + "add": "ekle" + }, + "commandBar": { + "free": "serbest", + "skill": "/skill", + "quick": "hızlı", + "placeholder": "Bir komut yazın", + "placeholderBusy": "Ada çalışıyor...", + "placeholderBlocked": "Ada sizi bekliyor...", + "send": "gönder", + "busyNote": "Ada bir aracın ortasında. Kuyruğa ekleyin ya da duraklatın.", + "blockedNote": "Onay gerekiyor." + }, + "blockedBanner": { + "needsYou": "sizi bekliyor" + }, + "costHud": { + "spendCap": "Harcama limiti", + "none": "yok", + "usd": "USD", + "off": "(kapalı)", + "thisSession": "bu oturumda {{usd}}", + "thisSessionWithCap": "bu oturumda {{usd}} / {{cap}}", + "audioTokens": "{{input}} giriş · {{output}} çıkış ses token", + "overCap": "Harcama limiti aşıldı — toparlama vakti.", + "nearCap": "Harcama limitine yaklaşılıyor.", + "lastSession": "Son oturum: {{usd}}", + "noSession": "Etkin sesli oturum yok.", + "compactTitle": "Bu oturumda {{count}} sesli token", + "tok": "tok" + }, + "badge": { + "idle": "boşta", + "thinking": "çalışıyor", + "working": "çalışıyor", + "waiting": "bekliyor", + "blocked": "sizi bekliyor", + "success": "bitti", + "ghost": "gitti", + "compacting": "sıkıştırılıyor", + "looping": "döngüde", + "typing": "taslağınız" + }, + "agentControl": { + "deliveryPaused": "kuyruktaki mesajlar bekletiliyor (tüm kat)", + "halting": "bu adımdan sonra duruyor…", + "steersQueued": "{{count}} not bekliyor", + "steerPlaceholder": "bu ajana bir not gönderin… (sonraki turunda bağlam olarak ulaşır, terminaline hiçbir şey yazılmaz)", + "steer": "yönlendir", + "flashResumed": "araçlara yeniden izin verildi", + "flashPaused": "araçlar sonraki çağrıdan itibaren engellendi", + "flashHalt": "mevcut adımdan sonra duracak", + "flashSteer": "not kuyruğa eklendi, sonraki turunda ulaşacak", + "allowTools": "araçlara izin ver", + "allowToolsTip": "Araçlarını geri verin. Ajan oturumunu korur ve kaldığı yerden devam eder.", + "allowToolsAria": "Araçlara yeniden izin ver", + "blockTools": "araçları engelle", + "blockToolsTip": "Ajan düşünmeye ve sizinle konuşmaya devam eder, ancak siz yeniden izin verene kadar hiçbir şey okuyamaz, yazamaz veya çalıştıramaz. Anında etkili ve geri alınabilir.", + "blockToolsAria": "Bu ajanın araç kullanmasını engelle", + "stopAfterStep": "bu adımdan sonra durdur", + "stopAfterStepTip": "Üzerinde olduğu adımı bitirsin, sonra dursun. Süreç ve oturumu korunur; Yeniden Başlat ve Devam Et ile kaldığı yerden alınabilir. Süreci tamamen sonlandırmak için X'i kullanın.", + "stopAfterStepAria": "Bu ajanı mevcut adımdan sonra durdur", + "steerTip": "Ajana bir sonraki tur sınırında bir not iletir. Şu an yaptığı işi bölmez ve terminaline hiçbir şey yazılmaz.", + "steerAria": "Bu ajana bir not gönder" + }, + "agentCard": { + "boss": "PATRON", + "contextTitle": "Bağlam: {{used}} / {{limit}} token (%{{pct}})", + "contextGaugeTitle": "Bağlam göstergesi — ajan etkinlik bildirdiğinde dolar", + "doingTasks": "{{count}} görev üzerinde çalışıyor — açmak için tıklayın", + "doingTasksPlural": "{{count}} görev üzerinde çalışıyor — açmak için tıklayın", + "editNote": "Özel notu düzenle", + "addNote": "Özel not ekle", + "editNoteAria": "Notu düzenle: {{name}}", + "noteAria": "Not: {{name}}" + }, + "askMe": { + "emptyTitle": "Şu an sizi bekleyen bir şey yok. 🌿", + "emptySub": "Ekip bir görevi sizin girdinize bağladığında — yanıtlanacak bir soru ya da yalnızca sizin yapabileceğiniz bir iş — burada (ve kattaki BANA SOR panosunda) görünür.", + "openDetail": "görevin tüm ayrıntılarını aç", + "dismissTitle": "kapat — yanıtlamadan BANA SOR panosundan kaldır (geçmiş korunur)", + "dismissAria": "bu soruyu kapat", + "answerPlaceholder": "Yanıtınız — ya da sonuçla birlikte 'tamam'… (göndermek için Ctrl+Enter)", + "sending": "gönderiliyor…", + "respond": "yanıtla ve engeli kaldır", + "viewAnswers": "{{count}} ÖNCEKİ YANITI GÖR", + "viewAnswersPlural": "{{count}} ÖNCEKİ YANITI GÖR", + "viewAnswersHistory": "tüm soru-cevap geçmişiyle görev ayrıntısını aç", + "blockingDownstream": "{{count}} SONRAKİ GÖREVİ ENGELLİYOR", + "blockingDownstreamPlural": "{{count}} SONRAKİ GÖREVİ ENGELLİYOR", + "more": "… +{{count}} daha" + }, + "agentStrip": { + "privateNote": "ÖZEL NOT · {{name}}", + "done": "Tamam", + "closeNoteEditor": "Not düzenleyiciyi kapat", + "notePlaceholder": "her madde için bir satır…", + "oneLineOneBullet": "bir satır = bir madde · kapatmak için esc", + "addAgent": "ajan ekle", + "restoringTitle": "Önceki oturumdaki ajanlarınız özgün kimlikleriyle yeniden başlatılıyor; böylece hafıza ve gelen kutuları yeniden bağlanır.", + "restoreTitle": "Önceki oturum: {{names}}", + "restoringTeam": "ekibiniz geri yükleniyor…", + "restoreTeam": "ekibi geri yükle ({{count}}) ▴", + "previousSession": "önceki oturum", + "restorable": "{{name}} — son oturumdan geri yüklenebilir", + "dismiss": "Kaldır: {{name}} — geri yükleme listesinden kalıcı olarak çıkar", + "dismissAria": "Kaldır: {{name}}", + "restoreAll": "tümünü geri yükle ({{count}})" + }, + "sidebar": { + "terminal": "terminal", + "git": "git", + "messages": "mesajlar", + "traces": "izler" + }, + "toolWaterfall": { + "fresh": "yeni {{tokens}}t", + "cache": "önbellek {{tokens}}t (%{{pct}})", + "total": "toplam {{tokens}}t", + "noTelemetry": "henüz canlı telemetri yok — izlemek için bu ajanı başlatın / yeniden başlatın", + "empty": "Henüz araç çağrısı yakalanmadı. Ajanın çalıştırdığı her araç gerçek süresiyle burada görünür.", + "barOk": "{{tool}} · {{ms}}ms · başarılı", + "barFailed": "{{tool}} · {{ms}}ms · başarısız" + }, + "agentDetail": { + "open": "aç", + "opening": "...", + "ok": "tamam", + "err": "hata", + "inFullscreen": "Odak modunda", + "fullscreenDesc": "Bu terminal odak modunda açık. Buraya geri getirmek için Esc'ye basın veya odak modundan çıkın.", + "noPty": "PTY yok", + "noPtyDesc": "Bu ajanın canlı terminali yok. Terminal sekmesini kullanmak için \"ajan ekle\" ile bir ajan başlatın.", + "killConfirm": "{{name}} kapatılsın mı? PTY süreci sonlanır ve ajan arşivlenir (geçmişte tutulur, kattan çıkarılır).", + "ideTip": "IDE'yi açın: {{project}} içindeki dosyalara göz atın, düzenleyin ve commit edilmemiş değişiklikleri diff olarak görün.", + "terminalTip": "Sistem terminal uygulamanızı {{cwd}} konumunda açın — bu ajanın klasöründe, ajanın kendi terminalinden ayrı normal bir kabuk.", + "openIde": "IDE'yi aç", + "ide": "IDE", + "openTerminalAria": "Bu ajanın klasöründe bir sistem terminali aç" + }, + "settingsHero": { + "sponsoredBy": "Sponsor:", + "visit": "ziyaret et", + "whatsNew": "yenilikler", + "whatsNewTitle": "Size en son bildirilen güncellemenin sürüm notlarını göster", + "starOnGitHub": "GitHub'da yıldızla", + "reportProblem": "sorun bildir", + "fullChangelog": "tüm değişiklik günlüğü →", + "announcement": "Duyuru", + "proLaunch": "v0.5.0, Munder Difflin Pro ile birlikte geliyor.", + "proCommunityFree": "Community ücretsiz ve açık kalmaya, güncelleme almaya devam ediyor.", + "proParagraph": "Pro, yeni özellikler ve entegrasyonlarla geliyor; yıl boyunca daha fazlası eklenecek ve her zaman Community'nin önünde olacak. Kodlama ajanlarının ve ajan altyapılarının tüm potansiyelini isteyen ileri düzey kullanıcılar için. Pro yol haritasında bir mobil uygulama da var.", + "foundersWallTitle": "Kurucular Duvarı'nda mısınız?", + "foundersWallBody": "Bir ay ücretsiz Munder Difflin Pro, ardından yıllık planda %50 indirim. Duvardaki ilk 100 kişiye özel.", + "seeTheWall": "duvarı gör", + "joinDiscord": "Discord'a katıl" + }, + "officeTheme": { + "title": "Ofis Teması", + "tvShow": "Dizi temalı ofisler", + "experimental": "deneysel", + "desc": "Piksel ofisi bir diziye göre yeniden giydirin. Geçiş yapmak yeni bir kadro başlatır.", + "current": "mevcut", + "soon": "yakında", + "notBuiltYet": "{{label}} henüz hazır değil — şimdilik ofis gösteriliyor.", + "switchAborted": "Geçiş iptal edildi — bir terminal kapanmadı: {{error}}", + "confirmTitle": "OFİS \"{{label}}\" TEMASINA GEÇİRİLSİN Mİ?", + "startsFreshCast": "YENİ BİR KADRO BAŞLATIR", + "deleteCount": "Mevcut {{count}} ajanınız silinecek — terminalleri kapanır ve devam eden tüm işler durur.", + "deleteCountPlural": "Mevcut {{count}} ajanınız silinecek — terminalleri kapanır ve devam eden tüm işler durur.", + "onlyCarries": "Yalnızca {{god}} aktarılır.", + "stillWorking": "⚠ {{count}} ajan hâlâ çalışıyor.", + "stillWorkingPlural": "⚠ {{count}} ajan hâlâ çalışıyor.", + "cantUndo": "Bu işlem geri alınamaz.", + "switching": "geçiş yapılıyor…", + "deleteSwitch": "{{count}} ajanı sil ve geç" + }, + "settings": { + "title": "AYARLAR", + "changeHomeTitle": "ANA KLASÖRÜ DEĞİŞTİR", + "resetTitle": "HER ŞEY SIFIRLANSIN MI?", + "close": "kapat", + "change": "değiştir...", + "apply": "uygulanıyor...", + "moveAndRestart": "taşı ve yeniden başlat", + "switchAndRestart": "geç ve yeniden başlat", + "resetting": "sıfırlanıyor...", + "eraseEverything": "her şeyi sil ve yeniden başlat", + "nav": { + "general": "Genel", + "prerequisites": "Gereksinimler", + "agentsModels": "Ajanlar ve Modeller", + "autonomyBudgets": "Otonomi ve Bütçeler", + "connections": "Bağlantılar", + "voice": "Ses", + "memoryKnowledge": "Hafıza ve Bilgi" + }, + "changeHome": { + "newHome": "Yeni ana klasör", + "moveTitle": "Mevcut verileri taşı (önerilir)", + "moveDesc": "Bu altyapının kovanını (tüm ajanlar, hafıza, görevler) ve anlamsal hafıza sarayını yeni klasöre kopyalar. Eski klasöre dokunulmaz; daha sonra silebileceğiniz bir yedek olarak kalır.", + "freshTitle": "Sıfırdan başla", + "freshDesc": "Altyapıyı yeni (boş) klasöre yönlendirir. Mevcut verileriniz eski klasörde kalır, yalnızca kullanılmaz." + }, + "resetConfirm": { + "body": "Bu işlem {{godName}} ajanının tüm hafızasını ve kovanın tamamını kalıcı olarak siler ve geri alınamaz. Çalışan tüm oturumlar sonlandırılır ve uygulama ilk kurulum ekranıyla yeniden açılır. Emin misiniz?" + }, + "general": { + "homeFolder": "Ana klasör", + "environment": "Ortam", + "keepAwake": "Ajanlar çalışırken Mac'i uyanık tut", + "keepAwakeDesc": "Zamanlamalar ve terminaller vaktinde çalışsın diye ekranın uyumasını engeller. Pil tüketir — prize takılıyken en iyisi.", + "simpleMode": "Her şeyi basitçe anlat", + "simpleModeDesc": "Ajanlar size mühendislik kısaltmaları yerine sade bir dille bilgi verir.", + "notifications": "Bildirimler", + "desktopNotifications": "Masaüstü bildirimleri", + "desktopNotificationsDesc": "Bir ajan işini bitirdiğinde veya girdinize ihtiyaç duyduğunda sistem bildirimi gösterir.", + "maintenance": "Bakım", + "autoCompact": "Zamanlanmış otomatik sıkıştırma", + "autoCompactDesc": "Her ajan için /compact komutunu bir zamanlamayla kuyruğa ekler (varsayılan saatlik; aralık Tetikleyiciler sekmesinde). Varsayılan olarak kapalı — uzun süre çalışan ajanların bağlamı bu olmadan taşabilir.", + "autoUpdate": "Otomatik güncelleme", + "autoUpdateDesc": "GitHub sürümlerini denetler ve güncellemeleri arka planda indirir; ne zaman yeniden başlatılacağına siz karar verirsiniz. Asla kendiliğinden yeniden başlatmaz.", + "telemetry": "Anonim kullanım istatistikleri", + "telemetryDesc": "Birkaç anonim olay (uygulama açıldı, ajan başlatıldı, özellik kullanıldı) — asla istem, kod, dosya yolu veya ajan çıktısı içermez. Tam liste TELEMETRY.md dosyasında.", + "language": "Dil", + "languageDesc": "Uygulama arayüzünün dilini seçin. Varsayılan dil İngilizcedir.", + "dangerZone": "TEHLİKELİ BÖLGE", + "dangerDesc": "Sıfırlama; {{godName}} ajanının hafızasını, kovanın tamamını (tüm ajanlar, mesajlar, görevler ve pano), anlamsal hafıza sarayını ve tüm ayarları siler - ardından sizi ilk kurulum ekranına döndürür.", + "resetStartOver": "sıfırla ve baştan başla", + "arabicTerminal": "Terminallerde Arapça / RTL metin", + "arabicTerminalDesc": "Terminalleri tarayıcının metin motoruyla çizer; böylece Arapça harfler birleşir ve sağdan sola okunur (xterm'in kendi bidi desteği yoktur). Kapalıyken GPU çizici kullanılır: daha hızlıdır ama RTL'yi tanımaz. Açık ve yeni terminallerin hepsine uygulanır.", + "arabicTerminalFollowsLanguage": "Uygulama dilinizi izliyor. Her iki yönde de geçersiz kılmak için buradan değiştirin — dili yeniden değiştirseniz bile seçiminiz korunur." + }, + "agentsModels": { + "defaultModel": "Varsayılan ajan modeli", + "defaultModelDesc": "Yeni başlatılan her Claude ajanı ({{godName}} dahil), ajan bazında başka bir model seçilmedikçe bu modelle başlar. Model seçicilerde \"· varsayılan\" olarak işaretlenir.", + "savedNote": "kaydedildi — yeni başlatılan ajanlara uygulanır", + "saveFailed": "kaydedilemedi", + "advanced": "Gelişmiş", + "maxTurns": "Çalıştırma başına en fazla tur", + "unlimited": "sınırsız", + "blankUnlimited": "boş = sınırsız" + }, + "autonomy": { + "autonomy": "Otonomi", + "autoOn": "Otonom — ajanlar sormadan hareket eder", + "autoOff": "Önce sor — ajanlar araç onayı için duraklar", + "autoDesc": "Yeni başlatılan ajanlara uygulanır (her ajanın komutu yine de bunu geçersiz kılabilir).", + "autonomous": "otonom", + "askFirst": "önce sor", + "breaker": "Devre kesici", + "breakerDesc": "Kontrolden çıkan ajanlara ve harcamalara karşı koruma. Kesici, bu sınırları aşan bir ajanı önce yönlendirir, sonra kısıtlar, sonra durdurur.", + "floorBudget": "kat token bütçesi", + "budgetPlaceholder": "ör. 1000000", + "budgetEquals": "= {{value}} token", + "budgetTotal": "kat genelindeki toplam token", + "velocity": "token hızı (tok/dk)", + "velocityPlaceholder": "ör. 200000", + "repeatedLimit": "tekrarlanan araç limiti", + "errorStormLimit": "hata fırtınası limiti", + "defaultPlaceholder": "varsayılan", + "hardStop": "Kesin durdurma", + "hardStopDesc": "Tetiklendiğinde ajanı yalnızca kısıtlamak yerine SONLANDIRIR. Kapalı = önce yönlendir (önerilir).", + "killOnTrip": "tetiklenince sonlandır", + "steerFirst": "önce yönlendir", + "saved": "kaydedildi" + }, + "memory": { + "semanticMemory": "Anlamsal hafıza", + "crossSession": "Oturumlar arası hatırlama", + "crossSessionDesc": "Ajanların markdown hafızası anında arama için dizinlenir. Gömme modeli Hafıza panelinde yer alır.", + "kg": "Bilgi Grafiği", + "kgTitle": "Kurumsal bilgi tabanı", + "kgDesc": "Belgelerinizi, görsellerinizi ve PDF'lerinizi ekleyin; ajanlar kg aracıyla gerektiğinde bunları sorgular.", + "adding": "ekleniyor…", + "addFiles": "dosya ekle…", + "docCount": "{{count}} belge dizinlendi", + "docCountPlural": "{{count}} belge dizinlendi" + }, + "connections": { + "slack": "Slack", + "slackIntegration": "Slack entegrasyonu", + "showSlackHelp": "Slack bağlantı adımlarını göster", + "slackDesc": "Bir Slack kanalının mesajlarını doğrudan {{godName}} kuyruğuna aktarın.", + "connected": "● Bağlı", + "notConnected": "○ Bağlı değil", + "signingSecret": "İmzalama sırrı", + "signingSecretPlaceholder": "Slack uygulaması -> Basic Information -> Signing Secret", + "botToken": "Bot belirteci", + "channelId": "Kanal kimliği (isteğe bağlı)", + "channelPlaceholder": "C0123... veya tümü için boş", + "port": "Bağlantı noktası", + "proactivePosting": "Proaktif gönderim (uygulama başlatır) — varsayılan olarak kapalı", + "start": "başlat", + "connectedBtn": "bağlı", + "stop": "durdur", + "listening": "dinliyor", + "stopped": "durduruldu", + "requestUrl": "İstek URL'si - Slack Event Subscriptions alanına yapıştırın", + "lastRequestUrl": "son İstek URL'si - Durdur'a basana kadar Slack bunu kullanır", + "slackHint": "Slack uygulamanızda: Event Subscriptions'ı etkinleştirin, message.channels / message.groups bot olayını ekleyin, yukarıdaki İstek URL'sini ayarlayın ve uygulamayı çalışma alanınıza yeniden yükleyin. Tünel URL'si her yeniden başlatmada değişir; Başlat'a yeniden bastıktan sonra tekrar yapıştırın.", + "webhooks": "Webhook tetikleyicileri", + "showWebhookHelp": "Webhook API biçimini göster", + "webhooksDesc": "Her çağıran için kendi sırrı ve modu olan bir uç nokta. Hepsi tek bir sunucuyu paylaşır; yeni bir webhook ek maliyet getirmez.", + "listeningOn": "● Dinliyor", + "notListening": "○ Dinlemiyor", + "addWebhook": "webhook ekle", + "webhookWarning": "Açtığınız her webhook, sırrına sahip herkesin gönderi yapabileceği HERKESE AÇIK bir uç noktadır. Yeniler kapalı olarak gelir.", + "noWebhooks": "Henüz webhook yok. Bir araca iş devredebileceği bir URL vermek için ekleyin.", + "namePlaceholder": "bunu ne çağırıyor?", + "sure": "emin misiniz?", + "url": "URL", + "endpointPlaceholder": "webhook sunucusu dinlemeye başlayınca oluşur", + "secret": "Sır", + "rotate": "yenile", + "mode": "Mod", + "webhooksHint": "Çağıranlar, sırrı x-md-webhook-secret başlığında göndererek webhook URL'sine POST isteği yapar. Her webhook gövdeleri kendi JSON şemasına göre denetler — bunu {{godName}} Komuta Merkezi'nin Tetikleyiciler sekmesinden düzenleyin; gelen her şeyin geçmişi de orada.", + "organisation": "Kuruluş", + "orgKey": "Kuruluş anahtarı", + "orgKeyDesc": "Bir ekip arkadaşınızın kurulumunun sizinkine nasıl ulaştığı.", + "apiKey": "API anahtarı", + "orgKeyPlaceholder": "kuruluş anahtarınızı yapıştırın", + "orgConfigOnly": "Şimdilik yalnızca yapılandırma. Kuruluş mesajlaşma hizmeti henüz yok; bu yüzden buradaki anahtar bir aktarım başlatmaz — kaydedilir, Tetikleyiciler sekmesinde gösterilir ve bekler." + }, + "voice": { + "freeFlow": "Serbest Akış", + "freeFlowTitle": "Free Flow (sesli dikte)", + "freeFlowDesc": "Bas-konuş dikte: konuşun, Groq Whisper metni kuyruk düzenleyicisine bıraksın.", + "groqKey": "Groq API anahtarı", + "groqPlaceholder": "gsk_... (console.groq.com adresinden ücretsiz anahtar alın)", + "model": "Model", + "fast": "whisper-large-v3-turbo (hızlı)", + "accurate": "whisper-large-v3 (doğru)", + "freeFlowHint": "Dikte etmenin iki yolu var: kuyruk düzenleyicisinde Gönder'in üstündeki mikrofon düğmesine tıklayın (kaydetmek için tıklayın, metne dökmek için yeniden tıklayın) ya da herhangi bir ajanın terminalini görüntülerken konuşmak için Option (⌥) tuşunu basılı tutun, metne dökmek için bırakın. Her iki durumda da metin, göndermeden önce gözden geçirmeniz için düzenleyici taslağına düşer. İlk kayıtta macOS mikrofon izni isteyecektir.", + "realtime": "Gerçek zamanlı {{godName}}", + "voiceChat": "Sesli sohbet: {{godName}}", + "voiceChatDesc": "Yönetici ile gerçek zamanlı konuşun. {{godName}} sekmesinden açın; ses döngüsünün kullanacağı mikrofonu ve hoparlörü buradan seçin.", + "openaiKey": "OpenAI API anahtarı · ses", + "openaiKeyDesc1": "{{godName}} ile konuşma, OpenAI'ın Realtime API'si üzerinde çalışır — {{model}} ile canlı bir bağlantı üzerinden ses girer, ses çıkar. Bu, ajanlarınızın çalıştığı Claude aboneliğinden farklı bir hizmettir; bu yüzden ayrı bir OpenAI API anahtarı gerekir.", + "openaiKeyDesc2": "Aşağıya bir kez yapıştırın. Bu makinede şifrelenir ve bir daha gösterilmez — her sesli oturum ondan kendi kısa ömürlü token'ını üretir ve anahtarın kendisi bilgisayarınızdan asla çıkmaz. Ajanlar ve Modeller altında listelenen OpenAI anahtarıyla aynıdır; ikisinden birinde ayarlamak yeterlidir.", + "keyPlaceholderSaved": "anahtar kaydedildi — değiştirmek için yenisini yapıştırın", + "save": "Kaydet", + "keySaved": "Anahtar kaydedildi — Konuş hazır. {{godName}} kartından başlatın.", + "noKey": "Henüz anahtar yok — biri kaydedilene kadar Konuş devre dışı kalır.", + "keySavedNote": "Anahtar kaydedildi — Konuş hazır.", + "couldNotSave": "Anahtar kaydedilemedi.", + "idleDisconnect": "Boşta otomatik bağlantı kesme", + "30s": "30 saniye", + "1m": "1 dakika", + "2m": "2 dakika", + "3m": "3 dakika", + "5m": "5 dakika", + "10m": "10 dakika", + "never": "Kapalı (hiçbir zaman)", + "idleDisconnectDesc": "Sesli oturumun hiç konuşulmadan ne kadar açık kalacağı, sonra otomatik kapanır. Bu kapalı olsa bile harcama limiti kontrolden çıkan bir oturumu yine durdurur." + }, + "saved": "Kaydedildi", + "saving": "Kaydediliyor…", + "unsavedChanges": "kaydedilmemiş değişiklikler", + "unsavedWarning": "Kaydedilmemiş ayarlarınız var. Yine de kapatıp kaybetmek istiyor musunuz?" + }, + "commandCenter": { + "title": "KOMUTA MERKEZİ", + "runsTheFloor": "Katı yöneten: {{name}}", + "deliveryPaused": "duraklatıldı", + "deliveryAuto": "otomatik", + "deliveryPausedTitle": "Kuyruktaki mesajlar kattaki HER ajan için bekletiliyor. Hiçbir şey kaybolmaz; bunu tekrar açtığınızda teslim edilir.", + "deliveryOnTitle": "Kuyruktaki mesajlar her ajana otomatik olarak teslim edilir. Tüm katı bekletmek için tıklayın.", + "ideTitle": "IDE'yi açın: seçili ajanın çalışma alanındaki dosyalara göz atın, düzenleyin ve commit edilmemiş değişiklikleri diff olarak görün.", + "ide": "IDE", + "tabs": { + "terminal": "terminal", + "floor": "monitör", + "tasks": "görevler", + "human": "bana sor", + "triggers": "tetikleyiciler", + "history": "geçmiş", + "memory": "hafıza", + "graph": "grafik", + "activity": "etkinlik", + "skills": "beceriler", + "workers": "çalışanlar" + }, + "terminalFullscreen": "Terminal tam ekranda açık. Geri getirmek için Esc tuşuna basın.", + "noTerminal": "{{name}} için canlı terminal yok.", + "dispatchViaMichael": "GÖREV GÖNDER — {{godName}} ÜZERİNDEN", + "suggestedOwner": "ÖNERİLEN SORUMLU", + "michaelDecides": "Karar {{godName}} tarafından verilir", + "dispatchPlaceholder": "Görevi tanımlayın… ({{godName}} parçalara ayırır, kartı yazar ve atar)", + "dispatch": "gönder", + "sentToMichael": "gönderildi: {{godName}}", + "sentToWithSuggestion": "gönderildi: {{godName}} (öneri: {{name}})", + "dispatchFailed": "başarısız: {{error}}", + "dispatchSuggestion": "(Kullanıcı bu iş için {{name}} ({{id}}) ajanını öneriyor — yönetici olarak karar senin.)", + "taskFromHuman": "Kullanıcıdan gelen görev", + "agents": "AJANLAR", + "godTag": " (god)", + "toolCalls": "{{count}} araç çağrısı", + "rate": "hız", + "budget": "bütçe", + "meterTitle": "TOPLAM oturum kullanımı: {{used}} / {{limit}} token{{note}} — bağlam penceresi değil", + "agentLimit": " (ajan limiti — iş token'ları, önbellek okumaları hariç)", + "floorBudget": " (kat bütçesi)", + "ctx": "bağlam", + "contextTitle": "Bağlam penceresi: {{used}} / {{limit}} token (%{{pct}})", + "noStatusTick": "henüz durum güncellemesi yok", + "modelRestarts": "{{provider}} modeli (ajanı yeniden başlatır)", + "restartContinue": "yeniden başlat ve devam et", + "restartContinueTitle": "{{name}} ajanını sonlandırıp yeniden başlatır ve mevcut konuşmasını sürdürür — bağlamı kaybetmeden bozuk terminali düzeltir", + "engine": "motor:", + "apply": "uygula", + "confirmRestartEngine": "Bu işlem {{name}} ajanını yeniden başlatır; farklı bir motordaki konuşma sürdürülemez.", + "restartFailed": "Yeniden başlatma başarısız.", + "archived": "ARŞİVLENENLER ({{count}})", + "showClosed": "kapatılmış ajanları göster", + "hideClosed": "kapatılmış ajanları gizle", + "directories": "DİZİNLER", + "noRepos": "Kayıtlı depo yok.", + "openInTerminal": "Terminal.app'te aç", + "issues": "ISSUE'LAR", + "fetching": "getiriliyor…", + "fetchIssues": "Issue'ları getir", + "noRepoSelected": "Depo seçilmedi.", + "fetchFailed": "Issue'lar getirilemedi.", + "noIssues": "Henüz issue getirilmedi.", + "assign": "Ata", + "textSearch": "METİN ARAMA (pano, görevler, hafıza)", + "textSearchPlaceholder": "Hive dosyalarında birebir metin arayın…", + "nothingMatched": "Eşleşme yok.", + "searchNoMatch": "Henüz eşleşme yok.", + "semanticSearch": "ANLAMSAL ARAMA (MemPalace)", + "semanticPlaceholder": "Hive şu konuda ne biliyor…", + "memoryFile": "HAFIZA DOSYASI", + "noMemory": "Henüz hafıza kaydı yok.", + "activity": "ETKİNLİK", + "nothingYet": "Henüz bir şey yok.", + "board": "PANO", + "boardEmpty": "Pano boş.", + "logSpawn": "başlatıldı: {{name}}", + "logMessage": "{{from}} → {{to}}: {{subject}}", + "logDrain": "{{agent}}: {{count}} mesaj alındı", + "logEscalate": "kullanıcıya iletildi: {{subject}}", + "logApprovalGranted": "onay verildi", + "logApprovalDenied": "onay reddedildi", + "tokenLimitTitle": "Bu ajanın token limitini ayarlayın (iş token'ları: girdi + çıktı + önbellek yazmaları; önbellek okumaları sayılmaz)", + "tokenLimit": "limit: {{value}}", + "setLimit": "limit belirle", + "saveLimit": "Limiti kaydet", + "fleetTokens": "Σ {{value}} token", + "fleetInputs": "girdiler {{value}} (önbellek %{{pct}})", + "fleetRate": "{{value}} token/dk", + "telemetryNote": "her ajanın OpenTelemetry verisinden canlı · çubuklar kullanılan token'ı ajanın limitine, yoksa {{cap}} kat bütçesine göre gösterir", + "defaultBudgetNote": " (varsayılan — Ayarlar'dan bir kat token bütçesi belirleyin)", + "openIssue": "GitHub sorunu #{{num}}: {{title}}", + "deliveryResumeAria": "Tüm kat için otomatik teslimatı sürdür", + "deliveryHoldAria": "Tüm kat için otomatik teslimatı beklet", + "openIdeAria": "IDE'yi aç" + }, + "addAgent": { + "title": "AJAN EKLE", + "hireImported": "içe aktarılan eleman:", + "byAuthor": " · hazırlayan: {{author}}", + "reviewFields": "başlatmadan önce her alanı — özellikle komutu — gözden geçirin.", + "hireFlags": "⚠️ bu elemanın komuta eklediği bayraklar:", + "hireSkills": "bu elemanın etkinleştirdiği beceriler:", + "mcpSafe": "MCP sunucuları (güvenli, önceden etkin):", + "mcpConsent": "⚠️ MCP (onayınız gerekir — otomatik etkinleştirilMEZ):", + "mcpEnableInSettings": "— inceledikten sonra Ayarlar → MCP'den etkinleştirin", + "sections": { + "identity": { + "label": "Kimlik", + "hint": "ad · karakter · renk" + }, + "workspace": { + "label": "Çalışma alanı", + "hint": "klasör · izolasyon · sürdürme" + }, + "engine": { + "label": "Motor", + "hint": "sağlayıcı · model · komut" + }, + "briefing": { + "label": "Brifing", + "hint": "açıklama · hedef" + } + }, + "name": "Ad", + "namePlaceholder": "Ada", + "character": "Karakter", + "color": "Renk", + "project": "Proje", + "pickProject": "Bir proje seçin veya yeni bir tane ekleyin:", + "noProjects": "Henüz proje yok — başlamak için bir tane ekleyin:", + "addProject": "proje ekle", + "addProjectTitle": "Bir klasör seçin ve proje olarak kaydedin", + "projectPlaceholder": "/path/to/your/project", + "pick": "seç", + "saveAsProject": "proje olarak kaydet", + "saveAsProjectTitle": "Bu klasörü projelerinize kaydedin; bir dahaki sefere tek tıkla seçin", + "gitIsolation": "Git izolasyonu (ayrı worktree)", + "resumeSession": "Sürdürülecek oturum ID'si (isteğe bağlı)", + "resumePlaceholder": "konuşmasını sürdürmek için bir Claude oturum ID'si yapıştırın", + "folderFromSession": "klasör oturumdan ayarlandı: {{path}}", + "resumeNote": "Bu oturum seçilen klasörde sürdürülecek (git izolasyonu devre dışı).", + "provider": "Sağlayıcı", + "providerAntigravity": "Antigravity CLI'ı (agy) bir Gemini modeliyle başlatır", + "providerCodex": "Codex CLI'ı (codex) Claude'a özel bayraklar olmadan başlatır", + "providerCustom": "Herhangi bir komutu çalıştırır — Claude'a özel bayrak yok", + "model": "Model", + "cliDefaultModel": "CLI varsayılan modeli", + "fromHire": "{{model}} (elemandan)", + "ossModels": "Açık kaynak modeller", + "ossLocal": "Yerel · anahtarsız (Ollama / LM Studio)", + "ossByok": "Açık kaynak sağlayıcı ile · BYOK", + "ossLocalTitle": "{{slug}} · yaklaşık {{ram}} RAM gerekir — indirmek için: ollama pull {{tag}}", + "ossByokTitle": "{{slug}} · Ayarlar → AI Motorları'ndan {{keyEnv}} değerini ayarlayın", + "byokNote": "Bu motorun BYOK anahtarları ve yerel uç noktaları Ayarlar → AI Motorları'nda bulunur. Yerel modellerde yeni misiniz? Açık modellerle çalıştırma veya Mac Mini'de kurulum rehberini okuyun. Uçtan uca canlı doğrulama gerçek model çağrılarını bekliyor (cihazda doğrulayın).", + "runOnOpenModels": "açık modellerle çalıştırma", + "setUpMacMini": "Mac Mini'de kurulum", + "command": "Komut", + "commandAuto": "Komut (otomatik mod açık)", + "templates": "Şablonlar", + "templatesHint": { + "repoJanitor": { + "label": "Depo temizlikçisi" + }, + "docsWriter": { + "label": "Doküman yazarı" + }, + "bugTriager": { + "label": "Hata ayıklayıcı" + }, + "researchAssistant": { + "label": "Araştırma asistanı" + }, + "releaseManager": { + "label": "Sürüm yöneticisi" + } + }, + "description": "Açıklama", + "descriptionPlaceholder": "görev — bu ajanın ne için olduğu, anlık durumu değil", + "goal": "Hedef (isteğe bağlı)", + "goalPlaceholder": "her isteme eklenen uzun soluklu yönerge", + "importHire": "Eleman içe aktar", + "importHireDesc": "Eleman içe aktarma, bir .json manifestinden hazır bir ajan yükler — aşağıdaki tüm alanları incelemeniz için doldurur. Başlat'a basana kadar hiçbir şey başlamaz.", + "generateWithAI": "AI ile oluşturun…", + "hideAIPrompt": "AI istemini gizle", + "aiPromptHint": "Bunu Claude/ChatGPT/Gemini'ye kopyalayın, alttaki ayrıntıları doldurun, ardından JSON yanıtını .json dosyası olarak kaydedip buraya içe aktarın.", + "copied": "kopyalandı ✓", + "copyPrompt": "istemi kopyala", + "importHireBtn": "eleman içe aktar…", + "importHireBtnTitle": "Bir eleman manifesti (.json) içe aktarın", + "spawn": "başlat", + "spawning": "başlatılıyor...", + "errName": "Ad gerekli", + "errFolder": "Önce bir klasör seçin", + "errCommand": "Komut gerekli", + "hireProgress": "eleman {{current}} / {{total}}", + "skipHire": "elemanı atla" + }, + "onboarding": { + "titles": { + "persona": "MUNDER DIFFLIN'E HOŞ GELDİNİZ", + "welcome": "OFİSİNİZLE TANIŞIN", + "home": "ADIM 1 / 4 · HARNESS ANA DİZİNİ", + "homePlain": "ADIM 1 / 4 · UYGULAMA İÇİN BİR YUVA", + "orchestrator": "ADIM 2 / 4 · KLONUNUZUN MOTORU", + "orchestratorPlain": "ADIM 2 / 4 · KLONUNUZ", + "repos": "ADIM 3 / 4 · DEPOLARINIZ", + "reposPlain": "ADIM 3 / 4 · PROJELERİNİZ", + "permissions": "ADIM 4 / 4 · İZİNLER VE GÜVENİLİRLİK", + "done": "HER ŞEY HAZIR" + }, + "persona": { + "headline": "7/24 ÇALIŞAN BİR KLONUNUZ", + "body": "Munder Difflin, zaten kullandığınız CLI ajanını sizin bir klonunuza dönüştürür — uzun soluklu ajanlardan oluşan bir ofisi yöneten ve siz yokken de çalışmaya devam eden bir klon. Etraflarındaki her şeyi yönetir: bağlam, hafıza, görevler, tetikleyiciler, ortam, dosyalar ve entegrasyonlar.", + "bodyLocal": " Her şey bu makinede çalışır.", + "ask": "ÖNCE — SİZ KİMSİNİZ? (kurulumu size göre uyarlayalım)", + "technicalTitle": "TEKNİK BİRİYİM", + "technicalDesc": "Kod yazıyorum veya terminalde çalışıyorum. Bana CLI komutlarını, bayrakları ve model ID'lerini gösterin.", + "nonTechnicalTitle": "TEKNİK BİRİ DEĞİLİM", + "nonTechnicalDesc": "Pazarlama, satış ya da operasyonda çalışıyorum veya yeni başlıyorum. Her şeyi sade bir dille anlatın." + }, + "welcome": { + "headline": "KLONUNUZ VE YÖNETTİĞİ KAT", + "descPlain": "Klonunuz küçük bir AI çalışanları ofisini yönetir, siz de her şeyi tek ekrandan izlersiniz. İçinde neler var:", + "desc": "Klonunuz AI kodlama ajanlarından oluşan bir hive'ı koordine eder — kalıcı, izlenebilir, tamamen yerel. İçinde neler var:", + "features": { + "engines": { + "label": "ON BİR MOTOR, TEK OFİS", + "desc": "Claude Code, Codex, Grok, Kimi, Antigravity, Qwen, OpenCode, Crush, pi, Copilot ve Cursor — tek katta canlı ajanlar.", + "descPlain": "On bir AI asistanı — Claude, Codex, Cursor, Gemini, Grok ve daha fazlası — ortak bir ofiste yan yana çalışır." + }, + "clone": { + "label": "{{godName}} SİZİN KLONUNUZ", + "desc": "Katı klonunuz yönetir — istekleri ayıklar, görevleri dağıtır ve yalnızca size gereken konuları iletir.", + "descPlain": "Klonunuz {{godName}}, isteklerinizi alır, işi doğru ajana verir ve sizi yalnızca önemli olduğunda rahatsız eder." + }, + "memory": { + "label": "UZUN SÜRELİ HAFIZA", + "desc": "Her ajan notlar tutar; bunlar ortak, aranabilir bir MemPalace'a aktarılır.", + "descPlain": "Ajanlar yaptıklarını hatırlar, böylece her seferinde sıfırdan başlamazlar." + }, + "commandCenter": { + "label": "KOMUTA MERKEZİ", + "desc": "Terminal · Kat · Hafıza · Etkinlik · Görevler · Tetikleyiciler tek bir kontrol yüzeyinde.", + "descPlain": "İşi, ajanların hafızasını, görevleri ve tetikleyicileri izlemek için tek bir pano." + }, + "guardrails": { + "label": "KORUMA ÖNLEMLERİ", + "desc": "Ajan başına token bütçeleri, yönlendir→kısıtla→durdur devre kesicisi ve insan onayları.", + "descPlain": "Harcama limitleri ve güvenlik durdurmaları ajanları kontrol altında tutar — büyük işlemlerden önce size sorabilirler." + }, + "hires": { + "label": "HAZIR ELEMANLAR", + "desc": "Ajan Galerisi'nden önceden yapılandırılmış bir ajan seçin ve tek tıkla başlatın.", + "descPlain": "Galeriden hazır bir ajanı tek tıkla işe alın — kurulum gerekmez." + } + } + }, + "providerBlurb": { + "claude": "Claude Code — Anthropic", + "codex": "Codex — OpenAI", + "antigravity": "Antigravity — Google Gemini", + "qwen": "Qwen — makinenizde yerel bir Qwen modeli çalıştırır", + "gemini": "Gemini CLI - Google Gemini", + "cursor": "Cursor Agent CLI — Cursor kredilerinizi kullanır (Luna, Composer, …)" + }, + "home": { + "descPlain": "Uygulamanın yuvası olacak yeni, boş bir klasör oluşturun. Uygulamanın hatırladığı her şey — kendi ayarları ve ajanlarınızın hafızası — burada saklanır. ~/HarnessAgents gibi bir şey iyi olur. Yoksa sizin için oluştururuz.", + "desc": "Harness'ın kendi dosyalarını — ajan meta verileri, günlükler ve buradan oluşturduğunuz yeni depolar — tutacağı bir klasör seçin. ~/HarnessAgents iyi bir varsayılandır. Yoksa oluştururuz.", + "placeholder": "/path/to/HarnessAgents", + "createPick": "oluştur / seç", + "pick": "seç", + "notePlain": "Bu klasörü günlük olarak açmanız gerekmez — uygulama, yeniden başlattığınızda hiçbir şey kaybolmasın diye notlarını burada tutar.", + "note": "Burayı \"belediye binası\" gibi düşünün. Harness, oturumlar yeniden başlatmadan sonra kaldığı yerden devam edebilsin diye ajan durumunu burada saklar." + }, + "orchestrator": { + "descPlain": "{{godName}} sizin klonunuz — isteklerinizi okur, görevlere böler ve doğru ajana verir. Katın patronu o; onun patronu ise hâlâ sizsiniz. Ona güç verecek AI motorunu seçin.", + "desc": "{{godName}} sizin klonunuz — az önce tanıştığınız katın patronu. İsteklerinizi ayıklar, görevleri atar ve ekibi yönetir; gerçekten size gereken her şeyi size iletir. Ona güç verecek motoru ve modeli seçin; daha uzun bağlamlı, daha yetenekli bir model verin.", + "cliAgentPlain": "CLI ajanı, bilgisayarınızda çalışan bir AI kodlama asistanıdır — popüler olanlar Claude Code (Anthropic), Codex (OpenAI) ve Antigravity'dir (Google Gemini). Klonunuz, tüm ofisinizi yöneten ve sürekli açık olandır. Opus 4.8 (1M) ile Claude Code öneriyoruz. Diğerlerini daha sonra ekleyebilir veya değiştirebilirsiniz.", + "cliAgent": "Her seçenek bir CLI motorudur (Claude Code, Codex, Antigravity/Gemini veya Qwen gibi yerel bir proxy). KURULU olarak işaretlenen motorlar bu makinede zaten var; İLK ÇALIŞTIRMADA KURULUR, {{godName}} ilk başladığında uygulamanın onu kuracağı anlamına gelir. Klonunuz ({{godName}}), tüm hive'ı yöneten motordur. Önerilen: Claude Code · Opus 4.8 · 1M. Diğer sağlayıcılar daha sonra ajan bazında bağlanabilir.", + "recommended": "ÖNERİLEN", + "workersOnly": "YALNIZCA ÇALIŞANLAR", + "workersOnlyHint": "Henüz hive postasını işleyemediği için klonunuzu çalıştıramaz — çalışan işe alırken yine de kullanılabilir.", + "model": "Model", + "modelNote": "Bu yalnızca {{godName}} motorunu ayarlar. Diğer sağlayıcıları daha sonra ajan bazında çalıştırabilirsiniz." + }, + "repos": { + "descPlain": "Projelerinizi ekleyin. Proje basitçe bir klasördür — ajanlarınızın üzerinde çalışmasını istediğiniz kod, belge, not veya herhangi bir dosyayı içerebilir. Yepyeni bir klasör oluşturabilir veya mevcut birini seçebilir, istediğiniz zaman daha fazlasını ekleyebilirsiniz.", + "desc": "Ajanlarınızın çalışmasını istediğiniz depoları ekleyin. Her klasör bir proje (katta bir oda) olur — birden fazla ajan aynı projeyi paylaşabilir. Daha sonra başkalarını da ekleyebilirsiniz.", + "emptyPlain": "Henüz proje eklenmedi. İsteğe bağlı — daha sonra ekleyebilirsiniz.", + "empty": "Henüz depo eklenmedi. İsteğe bağlı ama önerilir.", + "addProject": "proje ekle", + "addRepo": "depo ekle" + }, + "permissions": { + "autonomyHead": "AJANLAR KENDİ BAŞLARINA NE KADAR İŞ YAPABİLİR?", + "autoLabelPlain": "AJANLAR KENDİ BAŞINA ÇALIŞSIN", + "autoLabel": "OTONOM ÇALIŞ (OTOMATİK MOD)", + "autoOnPlain": "Açık. Ajanlar sormak için durmadan görevleri yürütür — en akıcı deneyim.", + "autoOffPlain": "Kapalı. Ajanlar dosyaları değiştirmeden veya komut çalıştırmadan önce durup size sorar.", + "autoOn": "Açık. Ajanlar hiç durmaz — Claude bypassPermissions ile çalışır, Codex onayları + sandbox'ı atlar, vb.", + "autoOff": "Kapalı. Her ajan düzenlemelerden / kabuk komutlarından önce sorar (Claude varsayılanı, codex -a untrusted, …).", + "autoNotePlain": "Ajanlar kendi projelerinde çalışırken en iyisidir. Bunu daha sonra, tek tek ajanlar için de değiştirebilirsiniz.", + "autoNote": "\"Kontrol odası\" deneyimi için doğru varsayılan; üretim depolarında ise ayağınıza sıkmak gibi. Ajan Ekle penceresinden ajan bazında değiştirin.", + "reliabilityHead": "SİZ YOKKEN İŞLER YÜRÜSÜN", + "reliabilityDescPlain": "Ajanlarınız siz uzaklaştığınızda bile bir zamanlamaya göre ve canlı terminallerde çalışmaya devam eder. Bu ayarlar sizi haberdar eder ve işlerin yürümesini sağlar.", + "reliabilityDesc": "Ajanlarınız bir zamanlamaya göre ve canlı terminallerde çalışmaya devam eder. Bilgisayarınız tamamen uykuya geçerse bu zamanlayıcılar duraklar ve döndüğünüz anda telafi edilir — hiçbir şey kaybolmaz, yalnızca gecikebilir.", + "keepAwake": "SİZ YOKKEN DE ÇALIŞ", + "keepAwakeDesc": "Güçlü uyanık tutma: bir ajan canlıyken bilgisayarınızın uykuya geçmesini engeller, böylece siz uzaklaştığınızda bile zamanlamalar ve terminaller zamanında çalışır. Daha fazla pil tüketir — prize takılıyken en iyisi. Varsayılan olarak kapalı.", + "notifications": "MASAÜSTÜ BİLDİRİMLERİ", + "notificationsDesc": "Bir ajan size ihtiyaç duyduğunda veya bir terminalin canlandırılması gerektiğinde bildirim alın — siz uzaktayken bile. Sisteminiz ilk bildirimde izin isteyebilir.", + "openAtLogin": "GİRİŞTE AÇ", + "openAtLoginDesc": "Zamanlanmış görevler kendiliğinden sürsün diye yeniden başlatmadan sonra harness'ı tekrar açar. Onay istemez — hemen uygulanır.", + "shareStats": "ANONİM KULLANIM İSTATİSTİKLERİNİ PAYLAŞ", + "shareStatsDesc": "Munder Difflin'i geliştirmeye yardımcı olan birkaç anonim olay (uygulama açıldı, ajan başlatıldı, özellik kullanıldı) — asla istemler, kod, dosya yolları veya ajan çıktısı değil. Tam liste TELEMETRY.md içinde; istediğiniz zaman Ayarlar'dan değiştirin.", + "stayAwake": "PRİZDEYKEN UYANIK KAL (MANUEL)", + "stayAwakeDescMac": "macOS bunu yalnızca sizin ayarlamanıza izin verir. Pil → Seçenekler'de \"Ekran kapalıyken otomatik uykuyu engelle\" seçeneğini (güç adaptöründe) açın; böylece ekran uykudayken zamanlayıcılar çalışmaya devam eder. Uykuyu engelleyen bir ayar olmadan Mac yine gerçekten uyur — iş kaybolmaz ve uyanınca telafi edilir.", + "stayAwakeDescWindows": "Windows bunu yalnızca sizin ayarlamanıza izin verir. Ayarlar → Sistem → Güç ve pil → Ekran, boş ekran ve uyku bölümünde \"Pil gücündeyken cihazımı uyku moduna al\" ve \"Prize takılıyken\" seçeneklerini Hiçbir zaman olarak ayarlayın (veya süreyi artırın); böylece zamanlayıcılar çalışmaya devam eder. Uykuyu engelleyen bir ayar olmadan Windows yine gerçekten uyur — iş kaybolmaz ve uyanınca telafi edilir.", + "stayAwakeDescLinux": "Bunu yalnızca masaüstü ortamınızdan ayarlayabilirsiniz. Bir Güç Ayarları paneli arayın (ör. GNOME Ayarları → Güç veya KDE Sistem Ayarları → Güç Yönetimi) ve prizdeyken otomatik uyku/askıya almayı kapatın. Uykuyu engelleyen bir ayar olmadan makineniz yine gerçekten uyur — iş kaybolmaz ve uyanınca telafi edilir.", + "openBatteryMac": "Pil ayarlarını aç", + "openBatteryWindows": "Güç ayarlarını aç", + "setItUp": "ayarla", + "next": "ileri" + }, + "errPickHome": "Önce bir harness ana klasörü seçin.", + "errCreateHome": "harness ana klasörü oluşturulamadı", + "errEngineNotInstalled": "{{label}} kurulu değil. Kurup \"tekrar kontrol et\" düğmesine basın veya başka bir motor seçin." + }, + "office": { + "gpuError": "Ofis katı GPU bağlamını kaybetti.\n\nAynı anda çok fazla terminal GPU kullanıyor.\nGeri getirmek için birkaç ajan terminalini kapatın veya uygulamayı yeniden başlatın.", + "errand": { + "water": [ + "bitkileri suluyorum 🌿", + "bitkilere biraz su", + "ne çabuk büyüyorlar" + ], + "window": [ + "biraz hava alalım 🍃", + "biraz temiz hava", + "bugün güzel esinti var" + ], + "dispenser": [ + "su almaya gidiyorum 💧", + "su molası", + "dinç kalmak lazım" + ], + "fridge": [ + "buzdolabında güzel bir şey var mı?", + "yoğurdumu kim aldı?", + "sadece bakıyorum…" + ], + "shelf": [ + "rafa göz atıyorum 📚", + "burada yeni bir şey var mı?", + "ne çok güzel şey var" + ], + "bin": [ + "müsvedde kâğıtlar çöpe 🗑️", + "masa temizliği günü", + "biraz toparlanıyorum" + ], + "smoke": [ + "kat kendi kendine dönüyor 🚬", + "patron molası.", + "büyük düşünceler düşünüyorum 🚬", + "İLAN EDİYORUM… mola" + ] + }, + "suckUp": [ + "{{done}} görevi çoktan teslim ettim, {{godName}}. zam? 🥺", + "bu hafta {{done}} görev bitti, patron!", + "her zamanki gibi harika vizyon, patron!", + "TAM DA bunu yapmak üzereydim!", + "kravat bugün çok yakışmış, {{godName}}", + "sıkı çalışıyorum, patron! 💪", + "gelmiş geçmiş en iyi patron. cidden." + ], + "gossip": [ + "bu adam hiç gerçekten kod yazdı mı?", + "bir 'kısa toplantı' daha, bir saat sürdü…", + "'dünyanın en iyi patronu' — o kupayı kendi almış", + "BENİM görevimi kendi fikriymiş gibi sabitledi", + "o puro kokusu, gerçekten…", + "bitkiyi suladı. BİR bitki. kendi bitkisini.", + "duydun mu? 'İLAN EDİYORUM… mola'" + ], + "cheer": [ + "bitti! ✔", + "tam isabet", + "bu iş tamam", + "yayınla gitsin 🚀", + "bir tane daha bitti", + "ezip geçtim", + "kayıtlara geçti" + ], + "mugs": { + "empty": "temiz kupa kalmamış…", + "brewing": "tazesini demliyorum ☕", + "washing": "kupayı yıkıyorum" + }, + "activity": { + "waiting": "bekliyor", + "needsYou": "sizi bekliyor", + "compacting": "bağlam sıkıştırılıyor", + "looping": "döngüde — sigorta devrede", + "runningFloor": "katı yönetiyor", + "idle": "boşta" + } + }, + "setupPanel": { + "title": "ÖN KOŞULLAR", + "checking": "Nelerin kurulu olduğu kontrol ediliyor…", + "summary": "{{ready}}/{{total}} hazır{{missing}}", + "summaryMissing": " · {{count}} önerilen eksik", + "recheck": "yeniden kontrol et", + "checkingBtn": "kontrol ediliyor…", + "statusReady": "HAZIR", + "statusMissing": "EKSİK", + "statusNotSetUp": "KURULMADI", + "recommended": "önerilen", + "docs": "belgeler →", + "askDesc": "{{godName}}, eksik {{count}} önerilen aracı sizin için kurabilir. Bu yalnızca gönderim kutusunu doldurur — siz gönder'e basana kadar hiçbir şey çalışmaz.", + "askDescPlural": "{{godName}}, eksik {{count}} önerilen aracı sizin için kurabilir. Bu yalnızca gönderim kutusunu doldurur — siz gönder'e basana kadar hiçbir şey çalışmaz.", + "allReady": "Önerilen her şey kurulu. Yukarıdaki motorlar isteğe bağlıdır — yalnızca kullandıklarınızı kurun.", + "askMichael": "her şeyi {{godName}} kursun", + "sections": { + "prerequisites": { + "title": "Ön koşullar", + "blurb": "Diğer her şeyin üzerine kurulduğu temel." + }, + "memory": { + "title": "Hafıza katmanı", + "blurb": "Ajanlarınızın öğrendiği her şeyde anlam tabanlı hatırlama." + }, + "engine": { + "title": "Ajan motorları", + "blurb": "Ajanlarınızın üzerinde çalıştığı CLI'lar. Hepsine değil, yalnızca gerçekten kullandıklarınıza ihtiyacınız var." + } + } + }, + "aiEngines": { + "providers": "YAPAY ZEK MOTORU SAĞLAYICILARI (BYOK)", + "providersDesc": "OpenCode, Crush, pi.dev ve Qwen motorları için API anahtarları + yerel uç noktalar. Anahtarlar yalnızca yazılabilir olarak saklanır (diskte şifreli; bir daha gösterilmez) ve yalnızca bu motorlar başlatıldığında kullanılır. Claude Code ve Codex kendi oturum açma yöntemlerini kullanır.", + "apiKeys": "API ANAHTARLARI", + "setCheck": "ayarlı ✓", + "keyStoredPlaceholder": "•••••••• (kayıtlı — değiştirmek için yazın)", + "keyPlaceholder": "{{label}} anahtarını yapıştırın", + "saved": "kaydedildi", + "failed": "başarısız", + "cleared": "temizlendi", + "localEndpoint": "YEREL UÇ NOKTA · VARSAYILAN MODEL (MOTOR BAŞINA)", + "defaultModelPlaceholder": "varsayılan model (sağlayıcı/model)", + "runningOpenModels": "Açık modeller mi çalıştırıyorsunuz? Adım adım rehberler:", + "runOnOpenModels": "Munder Difflin'i açık modellerle çalıştırın", + "setUpMacMini": "bir Mac Mini üzerinde kurun", + "autoModeCaveat": "⚠ Otomatik modda bu motorlar tam dosya sistemi + kabuk erişimiyle (sandbox olmadan) çalışır — Claude'un bypass modu gibi. Önce sormalarını istiyorsanız otomatik modu kapatın (Genel). Gerçek model çağrılarıyla uçtan uca canlı doğrulama, anahtarlarınızı / yerel bir LLM'i bekliyor." + }, + "mcpDefaults": { + "title": "Varsayılan MCP sunucuları", + "desc": "Bu sunucular her yeni ajanın oturum ayarlarına eklenir. Güvenli sunucular varsayılan olarak açıktır; yazma/gizli anahtar gerektiren sunucular siz onay verene kadar kapalıdır. Değişiklikler bir sonraki ajan başlatıldığında geçerli olur — çalışan ajanlar etkilenmez.", + "toggleNote": "{{id}}: {{state}}", + "couldNotSave": "kaydedilemedi", + "tiers": { + "safeReadonly": "Güvenli ve Salt Okunur (varsayılan olarak açık)", + "write": "Yazma Erişimi (onay gerekir)", + "secret": "Gizli Anahtar / API Anahtarı Gerekir (onay gerekir)", + "safeReadonlyNote": "Bu sunucular yalnızca veri okur, gizli anahtar gerektirmez ve ajan çalışma alanıyla sınırlıdır. Her yeni ajan için etkindir.", + "writeNote": "Bu sunucular çalışma alanı dışındaki durumu değiştirebilir. Varsayılan olarak kapalı — yalnızca inceledikten sonra etkinleştirin.", + "secretNote": "Bu sunucular bir API anahtarı veya kimlik bilgisi gerektirir. Varsayılan olarak kapalı — kimlik bilgilerinizi ekleyin ve onay verdikten sonra etkinleştirin." + } + }, + "devicePicker": { + "microphone": "Mikrofon", + "speaker": "Hoparlör", + "systemDefault": "Sistem varsayılanı", + "namesHint": "Cihaz adları, ilk sesli oturumu başlatıp mikrofon izni verdikten sonra görünür. Mikrofon seçimi {{godName}} bir sonraki bağlandığında uygulanır; hoparlör anında değişir." + }, + "realtimeToggle": { + "talk": "konuş", + "connecting": "…", + "listening": "dinliyor", + "speaking": "konuşuyor", + "working": "çalışıyor", + "helpOff": "{{godName}} ile konuşun — sesli oturumu başlatın", + "helpConnecting": "Bağlanılıyor: {{godName}}…", + "helpListening": "Dinleniyor — {{godName}} sizi duyuyor (durdurmak için tıklayın)", + "helpSpeaking": "{{godName}} konuşuyor (durdurmak için tıklayın)", + "helpWorking": "{{godName}} bir araç çalıştırıyor — mikrofon kapalı (durdurmak için tıklayın)", + "noKeyTitle": "Konuşma için OpenAI API anahtarınız gerekir (Realtime ses API'si için kullanılır). Ayarlar → Ses bölümünden ekleyin.", + "whyDisabled": "Konuşma neden devre dışı?", + "popoverBody": "Bu özelliği kullanmak için bir OpenAI API anahtarı gerekir.", + "setItUpNow": "şimdi ayarla" + }, + "updatesSection": { + "title": "Güncellemeler", + "onVersion": "Kullandığınız sürüm: v{{v}}", + "checkingDetail": "Daha yeni bir sürüm aranıyor…", + "availableHeadline": "v{{version}} kullanılabilir", + "availableDetail": "Kullandığınız sürüm: v{{v}}. Şimdi indirin — hazır olduğunda yeniden başlatmanız istenecek.", + "downloadBtn": "v{{version}} indir", + "downloadingHeadline": "v{{version}} indiriliyor", + "downloadingDetail": "%{{percent}} tamamlandı. Çalışmaya devam edebilirsiniz; yeniden başlatma zamanı size kalmış.", + "downloadedHeadline": "v{{version}} kurulmaya hazır", + "downloadedDetail": "v{{v}} sürümünden güncellemeyi tamamlamak için Munder Difflin'i yeniden başlatın.", + "restartBtn": "Güncellemek için yeniden başlat", + "manualDetail": "Bu kurulum kendini güncelleyemiyor — sürüm sayfasından indirin.", + "manualDetailReason": "Bu kurulum kendini güncelleyemiyor ({{reason}}) — sürüm sayfasından indirin.", + "openReleaseBtn": "Sürüm sayfasını aç", + "errorHeadline": "Güncelleme kontrolü başarısız", + "errorDetail": "{{message}} (kullandığınız sürüm: v{{v}}).", + "retryBtn": "Tekrar dene", + "latestHeadline": "v{{v}} en son sürüm", + "latestDetail": "Zaten güncelsiniz — kurulacak bir şey yok.", + "checkAgainBtn": "Tekrar kontrol et", + "idleDetail": "Güncellemeler her 6 saatte bir otomatik olarak kontrol edilir. Emin olmak istiyorsanız şimdi kontrol edin.", + "checkBtn": "Güncellemeleri kontrol et", + "downloadManually": "elle indir", + "downloadManuallyTitle": "v{{version}} yükleyicisini indirin ve uygulamayı kendiniz değiştirin", + "manualDownloadingTitle": "v{{version}} tarayıcınızda indiriliyor.", + "manualDownloadingBody": "İndirme bitince bu uygulamadan çıkın, yeni sürümü mevcut sürümün üzerine kurun, açın ve aynı projeyi seçin. {{os}} için:" + }, + "triggersTab": { + "intro": "Siz yazmadan iş başlatabilen her şey.", + "schedules": "ZAMANLAMALAR", + "schedulesBlurb": "Bir istemi tekrarlanan bir saatle çalıştırın.", + "context": "BAĞLAM", + "contextBlurb": "Bağlamı doldukça bir ajanı sıkıştırın veya temizleyin.", + "webhooks": "WEBHOOK'LAR", + "webhooksBlurb": "Dış bir sistemin iş göndermesine izin verin.", + "organisation": "ORGANİZASYON", + "organisationBlurb": "Bir ekip arkadaşınızın Munder Difflin'inin sizinkine mesaj göndermesine izin verin." + }, + "orgSection": { + "acceptMessages": "Organizasyonunuzdan gelen mesajları kabul et", + "key": "ORGANİZASYON ANAHTARI", + "keyPlaceholder": "anahtarınızı yapıştırın", + "trust": "GÜVEN", + "settingsOnly": "Şimdilik yalnızca ayar. Organizasyon mesajlaşma hizmeti henüz yok; bu yüzden buradaki anahtar bağlantı başlatmaz, hiçbir şey gönderilmez veya alınmaz. Hizmet geldiğinde kullanılmak üzere saklanır.", + "noKeyWarning": "Bu, anahtar ayarlanmadan açık; bu yüzden henüz hiçbir ekip arkadaşı size ulaşamaz.", + "noKey": "anahtar yok" + }, + "contextSection": { + "loading": "Bir saniye…", + "intro": "Bir kural yalnızca iki koşul da sağlandığında çalışır: son çalışmasından bu yana belirlenen süre geçmiştir VE o ajanın bağlamı en az eşik kadar doludur. %0 eşik yalnızca süreye bakılması demektir.", + "compact": "Sıkıştır", + "compactBlurb": "Konu devam edebilsin diye bağlamı özetler.", + "clear": "Temizle", + "clearBlurb": "Bağlamı atar. Hiçbir şey özetlenmez.", + "clearCaution": "Temizlemek bağlamı çöpe atar — sıkıştırmanın daha küçük bir hali değildir. Görevin ortasındaki bir ajan ne yaptığını unutur. Bağlamı başka bir yolla korumuyorsanız bunu kapalı bırakın.", + "extraFocus": "EK ODAK", + "extraFocusHint": "Sağlayıcının sıkıştırma komutunun sonuna eklenir. Boş bırakılırsa yalın komut gönderilir.", + "extraFocusPlaceholder": "Özetin mutlaka koruması gerekenler…", + "command": "KOMUT", + "commandHint": "Olduğu gibi gönderilir. Boş bırakılırsa yalın temizleme komutu gönderilir.", + "bothOff": "ikisi de kapalı", + "off": "Kapalı.", + "hintEvery": "Bağlam %{{pct}} değerini geçtikten sonra her {{interval}}.", + "noSoonerThan": "EN SIK ŞU ARALIKLA", + "contextBar": "BAĞLAM EŞİĞİ", + "contextBarHint": "Bunun çalışabilmesi için pencerenin ne kadar dolu olması gerektiği. %0 = yalnızca süre.", + "bigWindows": "BÜYÜK PENCERELERDE EŞİK", + "bigWindowsHint": "~1M token'lık pencerelerde kullanılır; bu pencerelerde küçük bir dilim bile çok büyük miktarda metindir." + }, + "schedulesSection": { + "justNow": "az önce", + "ago": "{{unit}} önce", + "in": "{{unit}} sonra", + "summaryNone": "yok", + "summary": "{{on}}/{{total}} açık", + "nothingScheduled": "Henüz zamanlanmış bir şey yok.", + "addSchedule": "zamanlama ekle", + "newSchedule": "YENİ ZAMANLAMA", + "label": "ETİKET", + "labelPlaceholder": "Bu çalıştırma ne için", + "goesTo": "ALICI", + "everyone": "herkes", + "prompt": "İSTEM", + "promptPlaceholder": "Her çalıştırmada kelimesi kelimesine gönderilir.", + "fired": "çalıştı: {{time}}", + "notFired": "henüz çalışmadı", + "next": "sonraki: {{time}}", + "beat": "♥ nabız", + "noPrompt": "İstem ayarlanmadı.", + "saved": "kaydedildi", + "when": "NE ZAMAN", + "beatCeiling": "Nabız, katın ne kadar sakin olduğuna göre ayarlanır; bu yüzden bu tam aralık değil, üst sınırdır." + }, + "webhooksSection": { + "summaryNone": "yok", + "summary": "{{count}} · {{state}}", + "live": "canlı", + "offline": "çevrimdışı", + "intro": "Bir URL'ye ve onun gizli anahtarına sahip olan herkes iş gönderebilir. Her uç noktanın kendi gizli anahtarı vardır; böylece bir çağıranı iptal etmek diğerlerini etkilemez.", + "noEndpoints": "Henüz uç nokta yok.", + "minting": "oluşturuluyor…", + "addWebhook": "webhook ekle", + "newEndpointHint": "Yeni bir uç nokta kapalı başlar. URL'sini ve gizli anahtarını kopyalayın, sonra açın.", + "unnamed": "adsız", + "reachable": "erişilebilir", + "noUrlYet": "henüz URL yok", + "serverOffline": "sunucu çevrimdışı", + "name": "AD", + "namePlaceholder": "Bunu kim çağırıyor", + "postTo": "GÖNDERİM ADRESİ", + "noAddressYet": "Bu uç noktanın henüz genel bir adresi yok. Tünel onu algıladığında görünür.", + "serverNotListening": "Webhook sunucusu dinlemiyor; bu yüzden henüz verilecek bir adres yok.", + "secret": "GİZLİ ANAHTAR", + "secretHint": "Çağıranlar bunu x-md-webhook-secret başlığında gönderir.", + "trust": "GÜVEN", + "bodySchema": "GÖVDE ŞEMASI", + "editSchema": "şemayı düzenle", + "schemaDesc": "gelen bir gövdenin nasıl görünmesi gerektiği", + "notValidJson": "Geçerli JSON değil — {{error}}. Hiçbir şey kaydedilmedi.", + "saved": "kaydedildi", + "saveSchema": "şemayı kaydet", + "sure": "Emin misiniz?", + "deleteIt": "sil", + "keep": "kalsın" + }, + "triggersUi": { + "custom": "özel", + "customEllipsis": "özel…", + "min": "dk", + "every": "her…", + "onDays": "şu günlerde…", + "at": "saat", + "weekdays": "hafta içi", + "everyDay": "her gün", + "pickDayHint": "En az bir gün seçin, yoksa bu hiç çalışmaz." + }, + "triggerHistory": { + "justNow": "az önce", + "ago": "{{unit}} önce", + "in": "{{unit}} sonra", + "kindDirective": "talimat", + "kindCommunication": "iletişim", + "decisionPending": "sizi bekliyor", + "decisionApproved": "onaylandı", + "decisionRejected": "reddedildi", + "decisionAuto": "otomatik izin verildi", + "emptyMessage": "(boş mesaj)", + "showLess": "daha az göster", + "showAll": "{{count}} karakterin tümünü göster", + "tailRejected": "Bunu reddettiniz. Kovana hiçbir şey gönderilmedi.", + "tailNoReply": "Henüz yanıt yok. Bu iş {{godName}} üzerinde.", + "waitingForYou": "SİZİ BEKLİYOR", + "unnamedSource": "adsız kaynak", + "from": "kimden", + "to": "kime", + "unknown": "bilinmiyor", + "theySent": "GÖNDERDİKLERİ", + "weReplied": "YANITIMIZ", + "weSent": "GÖNDERDİĞİMİZ", + "pendingDirectiveDesc": "Onaylarsanız bu, kovanı bunun üzerinde çalıştıracak olan {{godName}} için iletilir. Reddederseniz atılır — hiçbir şey çalışmaz.", + "pendingDesc": "Onaylarsanız {{godName}} bunu okur. Reddederseniz atılır — hiçbir şey çalışmaz.", + "approveTitle": "Bu mesajı {{godName}} için ilet", + "oneSec": "bir saniye…", + "approve": "onayla", + "rejectTitle": "Bu mesajı at. Hiçbir şey gönderilmez", + "reject": "reddet", + "task": "GÖREV {{id}}", + "sectionWebhooks": "Webhook'lar", + "sectionWebhooksBlurb": "Webhook uç noktalarınıza gönderilen her şey, yanında {{godName}} tarafından verilen yanıtla.", + "sectionOrg": "Organizasyon", + "sectionOrgBlurb": "Ekip arkadaşlarınızın klon düğümlerinden gelen mesajlar, yanında {{godName}} tarafından verilen yanıtla.", + "heldOne": "Bir mesaj bekletiliyor, evet ya da hayır demenizi bekliyor.", + "heldMany": "{{count}} mesaj bekletiliyor, evet ya da hayır demenizi bekliyor.", + "decideFailed": "Bu işlem gerçekleşmedi. Tekrar deneyin.", + "clearFailed": "Temizlenemedi. Tekrar deneyin.", + "emptyOrgTitle": "Burada henüz bir şey yok ve hiçbir şey bozuk değil.", + "emptyOrgBody": "Ekip arkadaşı mesajlaşması henüz geliştirilmedi. Bugün bir organizasyon anahtarı ayarlayıp bir mod seçebilirsiniz, ancak aktarım katmanı yayınlanana kadar kimsenin klon düğümü sizinkine ulaşamaz. Yayınlandığında onların mesajları ve bizim yanıtlarımız buraya düşer.", + "emptyWebhookTitle": "Henüz webhook mesajı yok.", + "emptyWebhookBody": "Uç noktalarınızdan birine bir şey gönderildiğinde, altında {{godName}} tarafından verilen yanıtla birlikte buraya düşer. Şu ana kadar hiçbir çağrı gelmedi. Paylaşabileceğiniz bir URL almak için Webhook'lar altında bir uç nokta ekleyin.", + "clearConfirm": "{{count}} mesajın tümü silinsin mi? Kayıt kalıcı olarak gider.", + "deleteThem": "sil", + "keepThem": "kalsın", + "clearHistoryTitle": "Bu bölümün geçmişini sil", + "clearHistory": "geçmişi temizle" + }, + "fileTree": { + "loading": "yükleniyor…", + "copyPathTitle": "Yolu panoya kopyala" + }, + "fileEditor": { + "file": "DOSYA", + "edit": "düzenle", + "preview": "önizleme", + "editTitle": "Kaynağı düzenle", + "previewTitle": "İşlenmiş önizleme (kaydedilmiş dosyanın)", + "openInIde": "IDE'de aç", + "openInIdeTitle": "Bu dosyayı tam IDE'de aç", + "closeTitle": "Kapat (Esc)" + }, + "gitTab": { + "notARepo": "Git deposu değil.", + "notARepoHint": "Ajanın terminalinde git init çalıştırın.", + "detachedHead": "AYRIK HEAD", + "refresh": "yenile", + "sectionStatus": "durum", + "sectionBranches": "dallar", + "sectionLog": "günlük", + "staged": "hazırlanan", + "changes": "değişiklikler", + "untracked": "izlenmeyen", + "clean": "çalışma ağacı temiz", + "noCommits": "henüz commit yok", + "modified": "değiştirildi", + "added": "eklendi", + "deleted": "silindi", + "renamed": "yeniden adlandırıldı", + "unmerged": "birleştirilmedi", + "copyPath": "Yolu kopyala" + }, + "fullscreenTerminal": { + "showAgentList": "Ajan listesini göster", + "hideAgentList": "Ajan listesini gizle — tam genişlikte terminal", + "lightTheme": "Açık temaya geç", + "darkTheme": "Koyu temaya geç", + "toggleTheme": "Koyu modu aç/kapat", + "exitFullscreen": "Odak modundan çık (Esc)", + "addAgent": "Ajan ekle", + "respawnTitle": "Son oturumdan yeniden başlat: {{names}} — aynı kimlikler; hafıza ve gelen kutuları otomatik olarak yeniden bağlanır", + "contextTitle": "Bağlam: {{used}} / {{limit}} token (%{{pct}})", + "modelTitle": "Model: {{model}}", + "cliDefault": "CLI varsayılanı", + "closeAgent": "Kapat: {{name}} — süreci sonlandırır ve ajanı arşivler", + "ideTip": "IDE'yi açın: {{name}} adlı ajanın çalışma alanındaki dosyalara göz atıp düzenleyin ve commit edilmemiş değişiklikleri diff olarak görün.", + "openIdeAria": "IDE'yi aç", + "openTerminalTip": "Sistem terminal uygulamanızı {{cwd}} konumunda açın — bu ajanın klasöründe, ajanın kendi terminalinden ayrı normal bir kabuk.", + "openTerminalAria": "Bu ajanın klasöründe bir sistem terminali aç" + }, + "memoryPanel": { + "pill": "🧠 hafıza", + "pillActive": "🧠 hafıza", + "openTitle": "Ajanlarınızın oluşturduğu ortak hafızada arayın", + "title": "KOVAN HAFIZASI", + "intro": "Ajanlarınızın oturumlar boyunca hatırladıkları, aralarında paylaşılır. Yalnızca birebir kelimelerle değil, anlama göre arayın.", + "notSetUp": "Kurulmadı", + "onReady": "Açık · hazır", + "onGettingReady": "Açık · hazırlanıyor…", + "turnOff": "Kapat", + "turnOn": "Aç", + "notInstalled": "Anlam tabanlı arama henüz kurulmadı.", + "setUpInPrereqs": "Ön Koşullar bölümünden kurun →", + "plainNotesStill": "Ajanlar bu olmadan da düz notlar tutmaya devam eder.", + "searchLanguage": "Arama dili", + "modelFast": "Hızlı", + "modelFastDetail": "Yalnızca İngilizce · ~90 MB", + "modelMultilingual": "Çok dilli", + "modelMultilingualDetail": "tüm diller · ~300 MB", + "searchPlaceholder": "Anlama göre ara…", + "nothingMatched": "Henüz eşleşen bir şey yok.", + "searchFailed": "Arama yapılamadı" + }, + "threads": { + "noSubject": "(başlıksız)", + "empty": "Henüz konuşma yok. Bu ajanın aldığı mesajlar burada konu olarak görünecek.", + "less": "daha az", + "more": "daha fazla", + "replyPlaceholder": "Yanıt: {{name}}…", + "send": "Gönder" + }, + "skillsTab": { + "installed": "Yüklü", + "browse": "göz at", + "searchInstalled": "Yüklü becerilerde ara…", + "searchCatalog": "Beceri kataloğunda ara…", + "categoryTitle": "Kataloğun yayımladığı kategoriler", + "allCategories": "tüm kategoriler", + "allPublishers": "tüm yayıncılar", + "loading": "yükleniyor…", + "refresh": "yenile", + "scanning": "Taranıyor…", + "noSkillsInstalled": "Henüz yüklü beceri yok. Nelerin mevcut olduğunu görmek için Göz At'ı açın.", + "nothingMatches": "Bu aramayla eşleşen bir şey yok.", + "openFolder": "klasörü aç", + "shipsWithApp": "uygulamayla birlikte gelir", + "deleteConfirm": "{{name}} silinsin mi?", + "removing": "kaldırılıyor…", + "uninstall": "kaldır", + "loadingCatalog": "Katalog yükleniyor…", + "cachedCopy": "Önbellekteki kopya gösteriliyor — {{error}}.", + "matching": "{{count}} eşleşme", + "matchingFirst": "{{count}} eşleşme · ilk {{shown}} tanesi gösteriliyor", + "curatedBy": "derleyen: abubakarsiddik31/claude-skills-collection", + "installing": "yükleniyor…", + "install": "yükle", + "learnMore": "daha fazla bilgi", + "installFailed": "yükleme başarısız", + "removeFailed": "kaldırılamadı", + "uninstallFailed": "kaldırma başarısız", + "catalogUnreachable": "kataloğa ulaşılamadı" + }, + "workersTab": { + "stopping": "durduruluyor", + "working": "çalışıyor", + "liveWorkers": "Etkin çalışanlar", + "liveIntro": "{{godName}} tarafından Slack mesajlarını işlemek için başlatılan yalıtılmış çalışanlar — işi tamamlar, konu içinde yanıt verir, ardından kapanırlar.", + "noneRunning": "Şu anda çalışan yok.", + "repliesToSlack": "bir Slack konusuna yanıt verir", + "stoppingEllipsis": "durduruluyor…", + "stop": "durdur", + "workerIdTitle": "çalışan / PTY kimliği", + "baseBranchTitle": "worktree'nin ayrıldığı temel dal", + "base": "temel: {{branch}}", + "upSinceTitle": "başlatıldığından beri geçen süre", + "up": "çalışma süresi {{age}}", + "idleTitle": "son terminal çıktısından beri geçen süre", + "ptyGone": "pty yok", + "idle": "boşta {{age}}", + "tokensTitle": "toplam token (girdi+çıktı+önbellek)", + "tokens": "token {{value}}", + "uncapped": "limitsiz", + "preserved": "Korunan worktree'ler ({{count}})", + "preservedIntro": "Worktree'sinde entegre edilmemiş iş kalan, tamamlanmış çalışanlar — saklanır (asla otomatik silinmez) ve iş temel dala ulaştığında otomatik olarak geri alınır.", + "keptAgo": "{{age}} önce saklandı" + }, + "memoryGraph": { + "topics": "başlıklar", + "refresh": "yenile", + "readingMemory": "hafıza okunuyor…", + "topicsShown": "{{total}} başlıktan {{shown}} tanesi gösteriliyor", + "loadingMemory": "hafıza yükleniyor…", + "messageLinks": "{{count}} mesaj bağlantısı", + "knowsAbout": "{{a}}, “{{b}}” hakkında bilgi sahibi", + "messagesLast": "{{count}} mesaj · son: {{act}}", + "noMemory": "Henüz kaydedilmiş hafıza yok.", + "legendRequest": "istek", + "legendQuery": "sorgu", + "legendPropose": "öneri", + "legendAgreeDone": "kabul/bitti", + "legendRefuse": "ret", + "legendInformTopic": "bilgi/başlık" + }, + "integrations": { + "errLabel": "Bir etiket verin.", + "errId": "Etiketten geçerli bir kimlik türetilemedi.", + "errBaseUrl": "Temel URL gerekli.", + "errBaseUrlFormat": "Temel URL https:// olmalı (yerel bir hedef için http://127.0.0.1 / localhost).", + "errHeader": "Başlık adı 1–64 karakter olmalı ve yalnızca A–Z, 0–9 veya \"-\" içermeli.", + "couldNotSave": "Kaydedilemedi.", + "added": "Entegrasyon eklendi.", + "updated": "Entegrasyon güncellendi.", + "removed": "“{{label}}” kaldırıldı.", + "couldNotRemove": "Kaldırılamadı.", + "testFailed": "Test çalıştırılamadı.", + "connected": "✓ Bağlandı", + "connectedWith": "✓ Bağlandı ({{status}})", + "failed": "✕", + "backToList": "← Entegrasyonlar", + "pickTemplate": "Bir şablon seçin", + "galleryDesc": "Neyi bağladığınızı seçin. Varsayılanları şablon belirler. Listede olmayan her şey için Özel REST'i seçin.", + "anyHttpApi": "Herhangi bir HTTP API", + "continue": "devam", + "backToTemplates": "← Şablonlar", + "needsSecret": "Gerekli: {{label}}", + "publicApi": "Herkese açık API — gizli anahtar gerekmez", + "label": "Etiket", + "labelHint": "Listenizde gösterilir. Kimlik", + "fixed": "sabit", + "baseUrl": "Temel URL", + "baseUrlHint": "{{label}} şablonu tarafından belirlenir.", + "preset": "hazır ayar", + "authentication": "Kimlik doğrulama", + "setByTemplate": "şablon tarafından belirlenir", + "headerName": "Başlık adı", + "headerHint": "Gizli anahtar {{header}}: olarak gönderilir.", + "saved": "kaydedildi", + "replaceKey": "Anahtarı değiştir", + "pasteYour": "Şunu yapıştırın:", + "writeOnly": "Salt yazma", + "secretDesc": "Ana süreçte şifrelenir ve bir daha gösterilmez. Değiştirmek için yeni bir anahtar yapıştırın — eski anahtar geri okunamaz.", + "blankKeepsKey": "Kayıtlı anahtarı korumak için boş bırakın.", + "availability": "Kullanılabilirlik", + "enabled": "etkin", + "disabled": "devre dışı", + "availableToAll": "✓ Tüm çalışanlar kullanabilir", + "notAvailableYet": "Çalışanlar henüz kullanamaz", + "addSecretToEnable": "Kullanılabilir hale getirmek için gizli anahtar ekleyip etkinleştirin.", + "readyOnceSaved": "Kaydedildiğinde hazır.", + "disabledNoUse": "Devre dışı — hiçbir çalışan kullanamaz.", + "v1Note": "v1, etkin her entegrasyonu tüm çalışanlara açar. Çalışan bazında kapsam yakında geliyor.", + "testConnection": "Bağlantıyı test et", + "testing": "test ediliyor…", + "testAfterSave": "Önce entegrasyonu kaydedin, ardından canlı bağlantıyı test edin.", + "testLiveDesc": "Kayıtlı gizli anahtarla temel URL'ye karşı canlı, salt okunur bir yoklama çalıştırır.", + "saveIntegration": "Entegrasyonu kaydet", + "saveChanges": "Değişiklikleri kaydet", + "title": "Entegrasyonlar", + "titleDesc": "Ajanlarınızın okuyup üzerinde işlem yapabilmesi için dış araçları bağlayın. Gizli anahtarlar ana süreçte şifreli saklanır ve bir daha gösterilmez.", + "addIntegration": "entegrasyon ekle", + "empty": "Henüz entegrasyon yok. Ajanlarınızın kullanabilmesi için GitHub'ı veya özel bir REST API'yi bağlayın.", + "addFirst": "ilk entegrasyonunuzu ekleyin", + "count": "{{count}} entegrasyon · {{usable}} tanesi çalışanlara açık", + "needsSecretShort": "Gizli anahtar gerekli", + "test": "test et", + "edit": "düzenle" + }, + "kanban": { + "count": "{{count}} görev", + "newWorkHint": "yeni iş mi var? {{godName}} adlı yöneticiye iletin (izleme sekmesi)", + "colTodo": "YAPILACAK", + "colDoing": "YAPILIYOR", + "colBlocked": "ENGELLENDİ", + "colDone": "BİTTİ", + "openTaskDetails": "görev ayrıntılarını aç", + "needsYouTitle": "SİZİN yanıtınızı bekliyor — BANA SOR sekmesine bakın", + "dismissTitle": "bu görevi kapat (panodan kaldırır)", + "dismissAria": "görevi kapat", + "taskTitle": "GÖREV", + "unassigned": "atanmamış", + "noDescription": "(bu kartta açıklama yok)", + "humanQA": "İNSAN SORU-CEVAP", + "awaitingAnswer": "YANITINIZI BEKLİYOR — BANA SOR SEKMESİ", + "dependsOn": "BAĞLI OLDUĞU", + "assign": "ata", + "priority": "Öncelik {{level}}/5" + }, + "queueComposer": { + "recording": "● kaydediliyor — yazıya dökmek için durdur'a tıklayın", + "transcribing": "yazıya dökülüyor…", + "voice": "ses", + "busyQueued": "{{name}} meşgul — kuyrukta {{count}} mesaj", + "heldFloor": "bekletiliyor — teslimat kat genelinde duraklatıldı", + "heldDraft": "bekletiliyor — {{name}} terminalinin isteminde gönderilmemiş metin var", + "heldPicker": "bekletiliyor — {{name}} terminalinde bir eğik çizgi komutu seçicisi açık", + "heldExited": "bekletiliyor — {{name}} terminali kapandı", + "sendingOneByOne": "tek tek gönderiliyor: {{name}}…", + "pausedTitle": "Otomatik teslimat tüm kat için duraklatıldı. Komuta Merkezi'nden sürdürün veya aşağıdaki bir mesajda \"şimdi gönder\"i kullanın.", + "dropToAttach": "EKLEMEK İÇİN BIRAKIN", + "queue": "KUYRUK", + "closePicker": "seçiciyi kapat", + "recoverPrompt": "istemi geri yükle", + "clearAllTitle": "Kuyruktaki tüm mesajları temizle", + "clearAll": "tümünü temizle", + "removeAttachment": "Eki kaldır", + "messagePlaceholder": "Mesaj: {{name}}", + "busyPlaceholder": "{{name}} meşgul — bir mesajı kuyruğa ekleyin", + "files": "dosyalar", + "collapse": "Bu mesajı daralt", + "showFull": "Mesajın tamamını göster", + "seeLess": "daha az gör", + "seeMore": "daha fazla gör", + "sendNowTitle": "Otomatik teslimat duraklatılmış olsa da bu mesajı ilet. Kuyruğun başına geçer ve terminal boşalır boşalmaz yazılır.", + "sendNow": "şimdi gönder", + "sendingWhenFree": "boşalınca gönderilecek…", + "removeFromQueue": "Kuyruktan kaldır", + "ffNoKeyTitle": "Dikte için ücretsiz bir Groq API anahtarı gerekir. Adımlar için bilgi simgesine tıklayın.", + "ffStopTranscribe": "Durdur ve yazıya dök", + "ffTitle": "Free Flow — kuyruğa dikte edin. Tıklayın veya Option (⌥) tuşunu basılı tutun.", + "stop": "durdur", + "ffHowEnable": "Dikteyi nasıl etkinleştiririm?", + "ffSetupTitle": "Dikteyi kur", + "ffSetupIntro": "Yazmak yerine konuşun. Groq sesinizi yazıya döker ve ücretsiz katmanı bunu karşılar — kart yok, ücret yok.", + "ffCreateKey": "Ücretsiz bir anahtarı şurada oluşturun:", + "ffPasteKey": "Ayarlar → Ses → Groq API anahtarı alanına yapıştırın", + "ffClickOrHold": "Ses'e tıklayın veya konuşmak için sağ Option tuşunu basılı tutun", + "ffHoldHint": "Başlatmak için tuşu bir an TEK BAŞINA basılı tutun; bıraktığınızda metin, göndermeden önce düzenleyebileceğiniz yazma alanına aktarılır. İki Option tuşu da çalışır ve Option+tuş kombinasyonları terminale olduğu gibi ulaşmaya devam eder." + }, + "idePanel": { + "workspace": "Çalışma alanı: {{name}}", + "workspaceInferred": "IDE açılırken bir ajan belirtilmedi — gösterilen çalışma alanı: {{name}} (geçerli seçim)", + "assumed": "varsayıldı", + "noAgent": "ajan yok", + "noWorkspace": "çalışma alanı yok", + "closeIde": "IDE'yi kapat (Esc)", + "expandGit": "Git panelini genişlet", + "collapseGit": "Git panelini daralt — dosya ağacına daha fazla yer", + "rail": { + "changes": "değişiklikler", + "history": "geçmiş", + "compare": "karşılaştır" + }, + "refresh": "Yenile", + "files": "dosyalar", + "rev": "SÜRÜM", + "img": "GÖRSEL", + "diff": "FARK", + "closeTab": "Sekmeyi kapat", + "loadingDiff": "diff yükleniyor…", + "binaryDiff": "ikili dosya — metin diff'i yok", + "workingTree": "çalışma ağacı", + "refreshDiff": "Diff'i yenile", + "mdSourceOnly": "Yalnızca kaynak", + "mdSplit": "Kaynak + önizleme", + "mdPreview": "İşlenmiş önizleme", + "code": "kod", + "split": "bölünmüş", + "preview": "önizleme", + "viewImage": "görseli görüntüle", + "copyPath": "yolu kopyala", + "saveTitle": "Kaydet (Cmd/Ctrl+S)", + "saved": "kaydedildi", + "save": "kaydet" + }, + "gitPanes": { + "jumpConfirm": "Depo {{sha}} (\"{{subject}}\") commit'ine atlansın mı?\n\nBu işlem HEAD'i ayırır. Ağaç kirliyse veya bir ajan çalışıyorsa otomatik olarak engellenir.", + "nowAt": "şu an {{sha}} üzerinde (ayrık HEAD)", + "loadingHistory": "geçmiş yükleniyor…", + "loadOlder": "daha eskileri yükle…", + "checkoutTitle": "Bu commit'e geç (ayrık HEAD)", + "jumpHere": "buraya atla", + "loadingFiles": "dosyalar yükleniyor…", + "noFileChanges": "dosya değişikliği yok (birleştirme mi?)", + "comparing": "karşılaştırılıyor…", + "switchConfirm": "Bu depo '{{head}}' dalına geçirilsin mi?\n\nAğaç kirliyse veya bir ajan çalışıyorsa otomatik olarak engellenir.", + "switchedTo": "geçildi: {{head}}", + "baseTitle": "Temel — karşılaştırma yaptığınız dal", + "swapTitle": "Temel ↔ karşılaştırılanı değiştir", + "compareTitle": "Karşılaştırılan — değişikliklerini görüntülediğiniz dal", + "aheadBehind": "'{{head}}' dalı, '{{base}}' dalının {{ahead}} commit önünde ve {{behind}} commit gerisinde", + "modeThreeTitle": "Karşılaştırılan dalın ortak atadan bu yana EKLEDİKLERİ gösteriliyor (PR tarzı). Birebir iki noktalı fark için tıklayın.", + "modeTwoTitle": "İki dal durumu arasındaki birebir fark gösteriliyor. PR tarzı (karşılaştırılanın ekledikleri) için tıklayın.", + "sinceCommonAncestor": "ortak atadan bu yana", + "literalDifference": "birebir fark", + "switchToTitle": "'{{head}}' dalına geç", + "switchTo": "geç: {{branch}}", + "noDifferences": "fark yok" + }, + "imagePreview": { + "fitTitle": "Görseli panele sığacak şekilde küçült", + "oneToOneTitle": "Her pikseli 1:1 göster (kaydırmak için sürükleyin)", + "fit": "sığdır", + "viewSourceTitle": "SVG işaretlemesini düzenleyicide aç", + "viewSource": "kaynağı görüntüle", + "loading": "görsel yükleniyor…", + "decodeFailed": "bu görsel çözülemedi — dosya bozuk veya yanlış adlandırılmış olabilir" + }, + "demoFloor": { + "headingTo": { + "shelf": "rafa gidiyor", + "terminal": "terminale gidiyor", + "web": "web'e gidiyor", + "board": "panoya gidiyor", + "mailbox": "posta kutusuna gidiyor", + "mcp": "MCP'ye gidiyor", + "desk": "masaya gidiyor" + }, + "headingBackToDesk": "masaya dönüyor", + "awaiting": "bekliyor", + "doneWhatNext": "Bu iş bitti. Sırada ne var?", + "samples": { + "read": { + "what": "SPEC.md okunuyor", + "thought": "Uygulamaya dokunmadan önce durum makinesini doğrulamak için spesifikasyonu açıyorum." + }, + "edit": { + "what": "PixelPanel.tsx düzenleniyor", + "thought": "Panel kenarlığı hesabını düzeltiyorum — iç çizgi, içe gömülü modda bir piksel kaymıştı." + }, + "bash": { + "what": "testler çalışıyor", + "thought": "Devam etmeden önce bir şey bozulmadığından emin olmak için arayüz test takımını çalıştırıyorum." + }, + "webFetch": { + "what": "belgeler getiriliyor", + "thought": "PreToolUse yükünün yapısını kontrol etmek için hook belgesini alıyorum — alan adlarını tam hatırlamıyorum." + }, + "glob": { + "what": "skill dosyaları aranıyor", + "thought": "Eski betik yollarını bulmak için tüm skill dosyalarını tek tek listeliyorum." + }, + "todoWrite": { + "what": "yapılacaklar panosu güncelleniyor", + "thought": "Kalan işi takip edebilmek için dört ayrı göreve bölüyorum." + } + } + } +} diff --git a/src/renderer/src/i18n/locales/zh-CN.json b/src/renderer/src/i18n/locales/zh-CN.json index 0db2c7f25d..9263ce6aab 100644 --- a/src/renderer/src/i18n/locales/zh-CN.json +++ b/src/renderer/src/i18n/locales/zh-CN.json @@ -1405,5 +1405,45 @@ "viewSource": "查看源码", "loading": "正在加载图片…", "decodeFailed": "无法解码此图片——文件可能已损坏或扩展名有误" + }, + "demoFloor": { + "headingTo": { + "shelf": "前往书架", + "terminal": "前往终端", + "web": "前往网络", + "board": "前往看板", + "mailbox": "前往信箱", + "mcp": "前往 MCP", + "desk": "前往工位" + }, + "headingBackToDesk": "返回工位", + "awaiting": "等待中", + "doneWhatNext": "这件完成了。接下来做什么?", + "samples": { + "read": { + "what": "正在读取 SPEC.md", + "thought": "先调出规格说明,在动手实现之前确认一下状态机。" + }, + "edit": { + "what": "正在编辑 PixelPanel.tsx", + "thought": "修正面板边框的计算——内嵌模式下内描边偏了一个像素。" + }, + "bash": { + "what": "正在运行测试", + "thought": "运行渲染端测试套件,确认继续之前没有引入回归。" + }, + "webFetch": { + "what": "正在获取文档", + "thought": "拉取 hooks 文档,再核对一下 PreToolUse 负载的结构——字段名我记不太清了。" + }, + "glob": { + "what": "正在搜索技能文件", + "thought": "列出所有技能文件,逐个检查是否有过时的脚本路径。" + }, + "todoWrite": { + "what": "正在更新待办看板", + "thought": "把剩下的工作拆成四个独立任务,方便边做边跟踪。" + } + } } } diff --git a/src/renderer/src/store/mockEvents.ts b/src/renderer/src/store/mockEvents.ts index ce7c2d57a6..f62c2a23e4 100644 --- a/src/renderer/src/store/mockEvents.ts +++ b/src/renderer/src/store/mockEvents.ts @@ -1,5 +1,6 @@ // Synthetic event stream so the avatars actually move while we wait on real tmux/hook wiring. +import i18n from '@/i18n'; import { useStore, type Agent, type StationKind, type ToolKind } from './store'; const STATION_BY_TOOL: Record = { @@ -13,41 +14,41 @@ const STATION_BY_TOOL: Record = { interface ToolSample { tool: ToolKind; - what: string; // short — used as the action text + key: string; // demoFloor.samples..what / .thought in the locales lines: string[]; // terminal stream output - thought: string; // first-person assistant text, streamed in the sidebar } +/** Short action text for the thought cloud, in the UI language. Read when the + * agent is updated, so a language switch shows up on the next tick. */ +const what = (s: ToolSample) => i18n.t(`demoFloor.samples.${s.key}.what`); +/** First-person assistant text, streamed in the sidebar. */ +const thought = (s: ToolSample) => i18n.t(`demoFloor.samples.${s.key}.thought`); +const headingTo = (station: StationKind) => i18n.t(`demoFloor.headingTo.${station}`); + const TOOL_SAMPLES: ToolSample[] = [ { - tool: 'Read', what: 'reading SPEC.md', - lines: ['\x1b[36m● Read\x1b[0m SPEC.md', ' read 412 lines.'], - thought: "Pulling up the spec so I can confirm the state machine before touching the implementation." + tool: 'Read', key: 'read', + lines: ['\x1b[36m● Read\x1b[0m SPEC.md', ' read 412 lines.'] }, { - tool: 'Edit', what: 'editing PixelPanel.tsx', - lines: ['\x1b[36m● Edit\x1b[0m src/renderer/src/components/PixelPanel.tsx', ' +14 / -3'], - thought: "Tightening up the panel border math — the inner stroke was a pixel off in inset mode." + tool: 'Edit', key: 'edit', + lines: ['\x1b[36m● Edit\x1b[0m src/renderer/src/components/PixelPanel.tsx', ' +14 / -3'] }, { - tool: 'Bash', what: 'running tests', - lines: ['\x1b[36m● Bash\x1b[0m npm test', ' ✓ 24 passed'], - thought: "Running the renderer suite to make sure nothing regressed before I move on." + tool: 'Bash', key: 'bash', + lines: ['\x1b[36m● Bash\x1b[0m npm test', ' ✓ 24 passed'] }, { - tool: 'WebFetch', what: 'fetching docs', - lines: ['\x1b[36m● WebFetch\x1b[0m https://docs.example.com/hooks', ' ok 200 (1.2kb)'], - thought: "Grabbing the hooks doc to double-check the PreToolUse payload shape — my memory of the field names is hazy." + tool: 'WebFetch', key: 'webFetch', + lines: ['\x1b[36m● WebFetch\x1b[0m https://docs.example.com/hooks', ' ok 200 (1.2kb)'] }, { - tool: 'Glob', what: 'searching for skill files', - lines: ['\x1b[36m● Glob\x1b[0m **/*.skill.md', ' 23 matches'], - thought: "Enumerating all the skill files so I can walk each one and look for stale script paths." + tool: 'Glob', key: 'glob', + lines: ['\x1b[36m● Glob\x1b[0m **/*.skill.md', ' 23 matches'] }, { - tool: 'TodoWrite', what: 'updating the todo board', - lines: ['\x1b[36m● TodoWrite\x1b[0m 4 items'], - thought: "Splitting the remaining work into four discrete tasks so I can track them as I go." + tool: 'TodoWrite', key: 'todoWrite', + lines: ['\x1b[36m● TodoWrite\x1b[0m 4 items'] } ]; @@ -73,7 +74,7 @@ function stepAgent(agent: Agent) { const station = STATION_BY_TOOL[sample.tool]; updateAgent(agent.id, { status: 'thinking', - action: `heading to ${station}`, + action: headingTo(station), currentStation: station, progress: 1 }); @@ -93,10 +94,10 @@ function stepAgent(agent: Agent) { const sample = pickSample(); updateAgent(agent.id, { status: 'working', - action: sample.what, + action: what(sample), carrying: tool, progress: Math.min(agent.progress + 1, 8), - recentAssistantText: sample.thought, + recentAssistantText: thought(sample), recentTextTs: Date.now() }); sample.lines.forEach(l => pushFeed(agent.id, l)); @@ -108,7 +109,7 @@ function stepAgent(agent: Agent) { if (Math.random() < 0.5) { updateAgent(agent.id, { status: 'thinking', - action: 'heading back to desk', + action: i18n.t('demoFloor.headingBackToDesk'), currentStation: 'desk', progress: Math.min(agent.progress + 1, 8) }); @@ -118,7 +119,7 @@ function stepAgent(agent: Agent) { const station = STATION_BY_TOOL[sample.tool]; updateAgent(agent.id, { status: 'thinking', - action: `heading to ${station}`, + action: headingTo(station), currentStation: station, progress: Math.min(agent.progress + 1, 8) }); @@ -160,9 +161,9 @@ export function startMockLoop() { if (a.status === 'thinking' && a.currentStation === 'desk' && Math.random() < 0.4) { updateAgent(a.id, { status: 'idle', - action: 'awaiting', + action: i18n.t('demoFloor.awaiting'), carrying: undefined, - recentAssistantText: 'Done with that one. What next?', + recentAssistantText: i18n.t('demoFloor.doneWhatNext'), recentTextTs: Date.now() }); } diff --git a/test/bundled-fonts.test.cjs b/test/bundled-fonts.test.cjs index 1bd371a24b..1bb6efd475 100644 --- a/test/bundled-fonts.test.cjs +++ b/test/bundled-fonts.test.cjs @@ -118,3 +118,54 @@ test('the release-drop iframe also falls through to a system CJK face', () => { assert.match(stack, /Geeza Pro|Noto Naskh Arabic/); } }); + +// --- glyph coverage --------------------------------------------------------- + +/** Code points the woff2's cmap maps. cmap is never transformed in woff2, so it + * can be cut straight out of the brotli stream; only format 4 is read. */ +function woff2Codepoints(file) { + const zlib = require('node:zlib'); + const buf = fs.readFileSync(file); + const numTables = buf.readUInt16BE(12); + const base128 = () => { + let v = 0; + for (;;) { const b = buf[off++]; v = v * 128 + (b & 0x7f); if (!(b & 0x80)) return v; } + }; + const KNOWN = ['cmap', 'head', 'hhea', 'hmtx', 'maxp', 'name', 'OS/2', 'post', 'cvt ', 'fpgm', 'glyf', 'loca', 'prep']; + let off = 48, at = 0, cmap = null; + for (let i = 0; i < numTables; i++) { + const flags = buf[off++]; + const tag = (flags & 63) === 63 ? buf.toString('latin1', off, (off += 4)) : KNOWN[flags & 63]; + const length = base128(); + const version = flags >> 6; + const transformed = tag === 'glyf' || tag === 'loca' ? version !== 3 : version !== 0; + const stored = transformed ? base128() : length; + if (tag === 'cmap') cmap = [at, length]; + at += stored; + } + const data = zlib.brotliDecompressSync(buf.subarray(off)).subarray(cmap[0], cmap[0] + cmap[1]); + const out = new Set(); + for (let i = 0, n = data.readUInt16BE(2); i < n; i++) { + const sub = data.readUInt32BE(4 + i * 8 + 4); + if (data.readUInt16BE(sub) !== 4) continue; + const segs = data.readUInt16BE(sub + 6) / 2; + const ends = sub + 14, starts = ends + segs * 2 + 2, deltas = starts + segs * 2, ranges = deltas + segs * 2; + for (let s = 0; s < segs; s++) { + const end = data.readUInt16BE(ends + s * 2), start = data.readUInt16BE(starts + s * 2); + for (let c = start; c <= end && c !== 0xffff; c++) { + const ro = data.readUInt16BE(ranges + s * 2); + const g = ro ? data.readUInt16BE(ranges + s * 2 + ro + (c - start) * 2) : 1; + if (g) out.add(c); + } + } + } + return out; +} + +test('the pixel face carries every Turkish letter', () => { + // Press Start 2P sets the section headings. Without İ Ğ ğ Ş ş in the file the + // tr locale fell back per glyph to a CJK face: "DİL" read "D:L". + const cps = woff2Codepoints(path.join(root, FONT_DIR, 'press-start-2p-latin-400.woff2')); + for (const ch of 'İıĞğŞşÇçÖöÜü') assert.ok(cps.has(ch.codePointAt(0)), `Press Start 2P has no ${ch}`); + assert.ok(cps.has(0x41) && cps.has(0x7a), 'cmap parse looks wrong: no A or z'); +}); diff --git a/test/turkish-ui.test.cjs b/test/turkish-ui.test.cjs new file mode 100644 index 0000000000..9ba9fc24d2 --- /dev/null +++ b/test/turkish-ui.test.cjs @@ -0,0 +1,103 @@ +'use strict'; + +// The Turkish (tr) locale. Structural checks only, the same ones the Arabic +// locale is held to: tr is registered, left-to-right, carries exactly en's key +// tree, keeps every {{variable}} and inline tag, and leaves no English behind. +// +// Turkish CORRECTNESS is not what a green run here means. These tests are about +// coverage and shape, never about whether the Turkish reads well. + +const test = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); + +const root = path.join(__dirname, '..'); +const read = (p) => fs.readFileSync(path.join(root, p), 'utf8'); +const locale = (code) => + JSON.parse(read(`src/renderer/src/i18n/locales/${code}.json`)); + +/** Every leaf path in a locale tree, arrays included by index. */ +function leaves(node, prefix = '') { + if (Array.isArray(node)) return node.flatMap((v, i) => leaves(v, `${prefix}.${i}`)); + if (node && typeof node === 'object') { + return Object.entries(node).flatMap(([k, v]) => leaves(v, prefix ? `${prefix}.${k}` : k)); + } + return [[prefix, node]]; +} +const pathsOf = (o) => new Map(leaves(o)); + +const en = locale('en'); +const tr = locale('tr'); + +test('tr is registered everywhere a language has to be registered', () => { + const src = read('src/renderer/src/i18n/index.ts'); + assert.match(src, /import tr from '\.\/locales\/tr\.json'/, 'tr.json is not imported'); + assert.match(src, /tr: \{ translation: tr \}/, 'tr is missing from resources'); + assert.match(src, /supportedLngs: \[[^\]]*'tr'[^\]]*\]/, 'tr is missing from supportedLngs'); + assert.match(src, /code: 'tr'[^}]*dir: 'ltr'/, 'tr is not marked left-to-right'); +}); + +test('tr has exactly the same key tree as en', () => { + const e = pathsOf(en), t = pathsOf(tr); + const missing = [...e.keys()].filter((k) => !t.has(k)); + const extra = [...t.keys()].filter((k) => !e.has(k)); + assert.deepEqual(missing, [], 'tr is missing keys — they would silently fall back'); + assert.deepEqual(extra, [], 'tr has keys en does not — dead strings'); + assert.ok(e.size > 1000, `sanity: only ${e.size} keys found`); +}); + +test('no Turkish string is left as its English source', () => { + // Strings that are IDENTICAL ON PURPOSE: product names, literal paths, pure + // format strings. Translating them would make the UI wrong, not more Turkish. + const SAME_ON_PURPOSE = new Set([ + 'commandBar.skill', // "/skill" — a slash command + 'sidebar.terminal', // "terminal" is the Turkish word too + 'commandCenter.tabs.terminal', + 'settings.voice.model', // "Model" is the Turkish word too + 'addAgent.model', + 'onboarding.orchestrator.model', + 'fullscreenTerminal.modelTitle', // "Model: {{model}}" — same + 'settings.connections.slack', // product name + 'onboarding.providerBlurb.claude', // product names + 'onboarding.providerBlurb.codex', + 'onboarding.providerBlurb.antigravity', + 'onboarding.providerBlurb.gemini', + 'addAgent.projectPlaceholder', // filesystem paths + 'onboarding.home.placeholder', + 'commandCenter.logMessage', // pure interpolation + 'mcpDefaults.toggleNote', + 'webhooksSection.summary' + ]); + const e = pathsOf(en), t = pathsOf(tr); + const untranslated = []; + for (const [k, v] of e) { + if (typeof v !== 'string' || !/[A-Za-z]{4}/.test(v)) continue; // symbols, ids, brands + if (t.get(k) === v && !SAME_ON_PURPOSE.has(k)) untranslated.push(k); + } + assert.deepEqual(untranslated, [], `${untranslated.length} Turkish strings are still English`); + const stale = [...SAME_ON_PURPOSE].filter((k) => t.get(k) !== e.get(k)); + assert.deepEqual(stale, [], 'allowlisted keys that ARE translated — drop them from the list'); +}); + +test('every interpolation variable survives translation', () => { + const e = pathsOf(en), t = pathsOf(tr); + const vars = (s) => [...String(s).matchAll(/\{\{\s*([\w.]+)\s*\}\}/g)].map((m) => m[1]).sort().join(','); + const bad = []; + for (const [k, v] of e) { + if (vars(v) !== vars(t.get(k))) bad.push(`${k}: [${vars(v)}] -> [${vars(t.get(k))}]`); + } + assert.deepEqual(bad, []); +}); + +test('inline markup and array shapes are preserved', () => { + const e = pathsOf(en), t = pathsOf(tr); + const tags = (s) => [...String(s).matchAll(/<\/?([a-z]+)>/g)].map((m) => m[1]).sort().join(','); + for (const [k, v] of e) { + assert.equal(tags(t.get(k)), tags(v), `markup changed in ${k}`); + } + const at = (o, p) => p.split('.').reduce((n, s) => n?.[s], o); + for (const p of ['office.errand.smoke', 'office.suckUp', 'office.gossip', 'office.cheer']) { + assert.equal(at(tr, p).length, at(en, p).length, `${p} changed length`); + } +});