"""Arayüz dil desteği (Türkçe / English). Kullanım: t("anahtar", lang, **biçim_parametreleri) Eksik çeviri varsa Türkçe metne, o da yoksa anahtarın kendisine düşer (tests/test_i18n.py eksikleri yakalar). """ from __future__ import annotations import re LANGS = {"tr": "Türkçe", "en": "English"} S: dict[str, dict[str, str]] = { # ------------------------------------------------------------------ genel "app_title": {"tr": "Tablo2SQL · Türkçe belge tablolarını sorgula", "en": "Tablo2SQL · Query tables in Turkish documents"}, "app_sub": {"tr": "PDF / HTML raporlardaki tabloları çıkar → yapılandırılmış veritabanına aktar → doğal dille soru sor. " "Sistem SQL'i kendisi düzeltir; cevap tablolarda yoksa bunu açıkça söyler.", "en": "Extract tables from PDF / HTML reports → load them into a structured database → ask in natural language. " "The system repairs its own SQL and says so plainly when the answer is not in the tables."}, "tab_docs": {"tr": "① Belgeler & çıkarım", "en": "① Documents & extraction"}, "tab_kb": {"tr": "② Bilgi tabanı", "en": "② Knowledge base"}, "tab_ask": {"tr": "③ Soru sor", "en": "③ Ask"}, "tab_err": {"tr": "④ Hata kataloğu", "en": "④ Error catalog"}, "tab_eval": {"tr": "⑤ Değerlendirme", "en": "⑤ Evaluation"}, # ------------------------------------------------------------------ model bağlantıları "conn_button": {"tr": "🔌 Model bağlantıları", "en": "🔌 Model connections"}, "conn_title": {"tr": "Model bağlantıları", "en": "Model connections"}, "conn_intro": {"tr": "Testleri yerel Ollama modelleriyle ya da OpenAI ve Claude bulut modelleriyle çalıştırın. " "Bağlandıktan sonra model listesi kendiliğinden senkronize olur ve modeller her sekmede seçilebilir.", "en": "Run tests with local Ollama models or with OpenAI and Claude cloud models. After connecting, the " "model list syncs automatically and the models can be selected in every tab."}, "badge_local": {"tr": "Yerel", "en": "Local"}, "badge_cloud": {"tr": "Bulut", "en": "Cloud"}, "st_connected": {"tr": "Bağlı · {n} model", "en": "Connected · {n} models"}, "st_not_connected": {"tr": "Bağlı değil", "en": "Not connected"}, "st_unreachable": {"tr": "Ulaşılamıyor", "en": "Unreachable"}, "st_unknown": {"tr": "Denetlenmedi", "en": "Not checked"}, "syncing": {"tr": "{p} modelleri senkronize ediliyor…", "en": "Syncing {p} models…"}, "ollama_change_url": {"tr": "Sunucu adresini değiştir", "en": "Change server address"}, "save_and_sync": {"tr": "Kaydet ve senkronize et", "en": "Save and sync"}, "sync_models": {"tr": "Modelleri senkronize et", "en": "Sync models"}, "disconnect": {"tr": "Bağlantıyı kes", "en": "Disconnect"}, "get_key": {"tr": "Anahtar al", "en": "Get a key"}, "saved_key": {"tr": "Kayıtlı anahtar", "en": "Saved key"}, "key_from_env": {"tr": " (ortam değişkeni)", "en": " (environment variable)"}, "env_key_note": {"tr": "Anahtar .env dosyasından ya da ortam değişkeninden okunuyor; ayar dosyasına yazılmadı.", "en": "The key is read from the .env file or an environment variable; it is not in the settings file."}, "last_synced": {"tr": "son senkron", "en": "last synced"}, "key_placeholder": {"tr": "API anahtarını yapıştırın", "en": "Paste the API key"}, "key_placeholder_new": {"tr": "Yeni anahtar (değiştirmek için)", "en": "New key (to replace)"}, "server_url_opt": {"tr": "Sunucu adresi (isteğe bağlı)", "en": "Server URL (optional)"}, "server_url_help": {"tr": "Boş bırakılırsa api.openai.com kullanılır. OpenAI uyumlu sunucular (vLLM, LM Studio, " "OpenRouter) için adres girin.", "en": "Leave empty to use api.openai.com. Enter an address for OpenAI-compatible servers " "(vLLM, LM Studio, OpenRouter)."}, "server_url_note": {"tr": "Adres değişince 'Modelleri senkronize et' ile listeyi yenileyin.", "en": "After changing the address, refresh the list with 'Sync models'."}, "show_models": {"tr": "Modelleri göster ({n})", "en": "Show models ({n})"}, "col_name": {"tr": "Ad", "en": "Name"}, "col_size": {"tr": "Boyut", "en": "Size"}, "col_detail": {"tr": "Ayrıntı", "en": "Details"}, "col_mem": {"tr": "Bellek", "en": "Memory"}, "col_note": {"tr": "Not", "en": "Note"}, "col_installed": {"tr": "Kurulu", "en": "Installed"}, "device_title": {"tr": "Hesaplama aygıtı (Ollama)", "en": "Compute device (Ollama)"}, "dev_auto": {"tr": "Otomatik", "en": "Auto"}, "dev_gpu": {"tr": "GPU", "en": "GPU"}, "dev_cpu": {"tr": "CPU", "en": "CPU"}, "dev_help_auto": {"tr": "Ollama karar verir; ekran kartına sığmayan kısım CPU'da çalışır (önerilen).", "en": "Ollama decides; whatever does not fit on the graphics card runs on the CPU (recommended)."}, "dev_help_gpu": {"tr": "Modelin tüm katmanları ekran kartına yüklenmeye çalışılır. Bellek yetmezse model açılmayabilir.", "en": "All model layers are loaded onto the graphics card. If memory is short the model may fail to load."}, "dev_help_cpu": {"tr": "Ekran kartı kullanılmaz; yavaştır ama her bilgisayarda çalışır.", "en": "The graphics card is not used; slow, but works on any computer."}, "dev_note": {"tr": "Varsayılan aygıttır; Değerlendirme sekmesinde her çalıştırma için ayrıca değiştirilebilir. " "Bulut modellerini etkilemez.", "en": "Default device; can also be changed per run in the Evaluation tab. Does not affect cloud models."}, "ollama_ver": {"tr": "Ollama sürümü {v}", "en": "Ollama version {v}"}, "ollama_pick_title": {"tr": "Hangi Ollama modeli? · önerilenler ve indirme", "en": "Which Ollama model? · recommendations and download"}, "ollama_pick_help": {"tr": "Text-to-SQL için önerilen yerel modeller. Boyut ve bellek değerleri yaklaşıktır " "(4-bit sürümler). Bellek, modelin ekran kartına ya da RAM'e rahat sığması için gereken miktardır.", "en": "Recommended local models for Text-to-SQL. Sizes and memory are approximate (4-bit builds). " "Memory is what the model needs to fit comfortably on the graphics card or in RAM."}, "cloud_notice": {"tr": "Bir bulut modeli seçtiğinizde tablo şemaları, sorular ve örnek satırlar o sağlayıcıya " "gönderilir ve kullanım sağlayıcı hesabınıza faturalanır. Anahtarlar yalnızca uygulama " "klasöründeki ayar dosyasında tutulur ve arayüze hiçbir zaman tam olarak geri gönderilmez.", "en": "When you pick a cloud model, table schemas, questions and sample rows are sent to that " "provider and usage is billed to your provider account. Keys are stored only in the settings " "file in the app folder and are never sent back to the interface in full."}, "settings_file": {"tr": "Ayar dosyası", "en": "Settings file"}, "settings_file_help": {"tr": "Tüm ayarlar (API anahtarları, aygıt, dil, tema, model ve sekme seçimleri) uygulama " "klasöründeki {p} dosyasında tutulur. Başka bir bilgisayara taşımak için dosyayı oradaki " "uygulama klasöründe aynı yere kopyalayın ya da aşağıdan indirip orada yükleyin.", "en": "All settings (API keys, device, language, theme, model and tab choices) are stored in " "{p} in the app folder. To move them to another computer, copy the file to the same " "place in the app folder there, or download it below and load it there."}, "dl_settings": {"tr": "Ayar dosyasını indir", "en": "Download settings file"}, "load_settings": {"tr": "Ayar dosyası yükle…", "en": "Load settings file…"}, "load_apply": {"tr": "Yükle ve uygula", "en": "Load and apply"}, "settings_loaded": {"tr": "Ayarlar yüklendi.", "en": "Settings loaded."}, "settings_plain_warn": {"tr": "Dosya API anahtarlarınızı düz metin olarak içerir; paylaşmayın.", "en": "The file contains your API keys in plain text; do not share it."}, "close_apply": {"tr": "Kapat", "en": "Close"}, "default_model": {"tr": "Varsayılan model", "en": "Default model"}, "default_model_help": {"tr": "Sekmelerde ayrıca model seçilmemişse bu model kullanılır.", "en": "Used in every tab unless a tab picks its own model."}, "no_models_yet": {"tr": "Yapay zekâ modeli eklemek için Model bağlantıları'nı açın.", "en": "Open Model connections to add AI models."}, "tab_model": {"tr": "Bu sekmedeki model", "en": "Model for this tab"}, "use_default": {"tr": "Varsayılan ({m})", "en": "Default ({m})"}, # ------------------------------------------------------------------ model karşılaştırma "cmp_title": {"tr": "Model karşılaştırma (cevap düzeyinde)", "en": "Model comparison (answer level)"}, "cmp_help": {"tr": "Bir test kümesini seçtiğiniz modellerle çalıştırır. Doğruluk, altın SQL yerine beklenen cevapla " "ölçülür. Sonuçlar kaydedilir; aynı kümedeki önceki çalıştırmalar tabloda yan yana görünür.", "en": "Runs a test set with the models you pick. Accuracy is measured against the expected answer rather " "than a gold SQL. Results are saved; earlier runs on the same set appear side by side."}, "cmp_no_sets": {"tr": "Test kümesi bulunamadı. 'python agir_kume/uret.py' ile üretin.", "en": "No test set found. Generate one with 'python agir_kume/uret.py'."}, "cmp_set": {"tr": "Test kümesi", "en": "Test set"}, "set_agir_hizli": {"tr": "Ağır küme · hızlı alt küme ({n} soru)", "en": "Heavy set · quick subset ({n} questions)"}, "set_agir": {"tr": "Ağır küme · tamamı ({n} soru, tek veritabanı)", "en": "Heavy set · full ({n} questions, one database)"}, "set_stres": {"tr": "Stres kümesi ({n} soru, belge başına)", "en": "Stress set ({n} questions, per document)"}, "set_pilot": {"tr": "Pilot ({n} soru)", "en": "Pilot ({n} questions)"}, "cmp_models": {"tr": "Karşılaştırılacak modeller", "en": "Models to compare"}, "cmp_limit": {"tr": "Soru sınırı (0 = tümü)", "en": "Question limit (0 = all)"}, "cmp_limit_help": {"tr": "Maliyeti denetlemek için ilk N soruyu çalıştırır.", "en": "Runs only the first N questions to control cost."}, "cmp_cost": {"tr": "Tahmini kullanım: {n} soru × {m} model; model başına yaklaşık {tok} bin girdi belirteci " "(şema boyutuna ve düzeltme denemelerine göre değişir).", "en": "Estimated usage: {n} questions × {m} models; roughly {tok} thousand input tokens per model " "(varies with schema size and repair attempts)."}, "cmp_run": {"tr": "▶ Karşılaştırmayı çalıştır", "en": "▶ Run comparison"}, "cmp_building": {"tr": "Veritabanı hazırlanıyor ve sorular çalıştırılıyor…", "en": "Preparing the database and running questions…"}, "cmp_none": {"tr": "Bu küme için henüz sonuç yok.", "en": "No results for this set yet."}, "cmp_col_model": {"tr": "Model", "en": "Model"}, "cmp_col_n": {"tr": "Soru", "en": "Questions"}, "cmp_col_acc": {"tr": "Doğruluk %", "en": "Accuracy %"}, "cmp_col_abst": {"tr": "Cevapsız→red %", "en": "Unanswerable→abstain %"}, "cmp_col_silent": {"tr": "Sessiz yanlış %", "en": "Silent wrong %"}, "cmp_col_tok": {"tr": "Belirteç", "en": "Tokens"}, "cmp_col_time": {"tr": "Süre (sn)", "en": "Time (s)"}, "cmp_col_when": {"tr": "Zaman", "en": "When"}, "cmp_by_level": {"tr": "Seviyeye göre doğruluk (%)", "en": "Accuracy by level (%)"}, "cmp_levels": {"tr": "L1 değer okuma · L2 toplama/filtre/sıralama · L3 çok adımlı hesap · L4 belgeler arası · " "L5 tuzak ve cevapsız sorular", "en": "L1 lookup · L2 aggregation/filter/ranking · L3 multi-step computation · L4 cross-document · " "L5 traps and unanswerable questions"}, "cmp_level_filter": {"tr": "Seviye", "en": "Level"}, "cmp_dl": {"tr": "⬇️ Sonuçları indir (JSON)", "en": "⬇️ Download results (JSON)"}, # ------------------------------------------------------------------ kenar çubuğu "settings": {"tr": "⚙️ Ayarlar", "en": "⚙️ Settings"}, "language": {"tr": "Dil", "en": "Language"}, "theme": {"tr": "Tema", "en": "Theme"}, "theme_light": {"tr": "☀️ Aydınlık", "en": "☀️ Light"}, "theme_dark": {"tr": "🌙 Karanlık", "en": "🌙 Dark"}, "ai_engine": {"tr": "🤖 Yapay zekâ", "en": "🤖 AI engine"}, "provider": {"tr": "Sağlayıcı", "en": "Provider"}, "prov_rule": {"tr": "Kural tabanlı (AI kapalı)", "en": "Rule-based (AI off)"}, "prov_claude": {"tr": "Claude (Anthropic)", "en": "Claude (Anthropic)"}, "prov_openai": {"tr": "OpenAI / uyumlu", "en": "OpenAI / compatible"}, "prov_ollama": {"tr": "Ollama (yerel)", "en": "Ollama (local)"}, "provider_help": {"tr": "Kural tabanlı arka uç anahtar gerektirmez. Bir AI sağlayıcısı seçildiğinde yapay zekâ " "uygulamanın her adımında kullanılır.", "en": "The rule-based backend needs no key. When an AI provider is selected, AI is used in every " "step of the app."}, "api_key": {"tr": "API anahtarı", "en": "API key"}, "api_key_help": {"tr": "Yalnızca bu oturumda tutulur, diske yazılmaz. Kalıcı kullanım için proje klasöründeki .env " "dosyasına ekleyebilirsiniz.", "en": "Kept only for this session and never written to disk. For permanent use add it to the .env " "file in the project folder."}, "base_url": {"tr": "Uç nokta (Base URL)", "en": "Endpoint (base URL)"}, "ollama_host": {"tr": "Ollama adresi", "en": "Ollama address"}, "model": {"tr": "Model", "en": "Model"}, "refresh_models": {"tr": "🔄 Modelleri senkronize et", "en": "🔄 Sync models"}, "models_synced": {"tr": "{n} model bulundu · {t}", "en": "{n} models found · {t}"}, "models_none": {"tr": "Sağlayıcıda kullanılabilir model bulunamadı.", "en": "No usable models found at the provider."}, "models_need_key": {"tr": "Modelleri listelemek için API anahtarını girin.", "en": "Enter the API key to list models."}, "models_error": {"tr": "Model listesi alınamadı: {e}", "en": "Could not fetch the model list: {e}"}, "ollama_unreachable": {"tr": "Ollama'ya ulaşılamadı. Ollama uygulamasını açın veya 'ollama serve' çalıştırın. " "Kurulum: https://ollama.com/download", "en": "Cannot reach Ollama. Open the Ollama app or run 'ollama serve'. " "Install: https://ollama.com/download"}, "ollama_pull": {"tr": "⬇️ Model indir", "en": "⬇️ Download model"}, "ollama_pull_pick": {"tr": "Önerilen modeller", "en": "Recommended models"}, "ollama_pulling": {"tr": "{m} indiriliyor…", "en": "Downloading {m}…"}, "ollama_pulled": {"tr": "{m} indirildi.", "en": "{m} downloaded."}, "test_conn": {"tr": "🔌 Bağlantıyı test et", "en": "🔌 Test connection"}, "ping_wait": {"tr": "Model yanıtı bekleniyor…", "en": "Waiting for the model…"}, "ping_wait_ollama": {"tr": "Ollama modeli belleğe yükleniyor… Büyük modellerde (ör. 32B) ilk çağrı 1–3 dakika " "sürebilir; bu sırada uygulama donmuş gibi görünür, bekleyin.", "en": "Loading the Ollama model into memory… For large models (e.g. 32B) the first call can " "take 1–3 minutes and the app looks frozen meanwhile; please wait."}, "conn_ok": {"tr": "Bağlantı başarılı ({d})", "en": "Connection OK ({d})"}, "conn_fail": {"tr": "Bağlantı başarısız: {e}", "en": "Connection failed: {e}"}, "ai_status_on": {"tr": "AI aktif", "en": "AI active"}, "ai_status_off": {"tr": "AI kapalı · kural tabanlı", "en": "AI off · rule-based"}, "ai_usage": {"tr": "{c} çağrı · {i} girdi / {o} çıktı belirteci", "en": "{c} calls · {i} input / {o} output tokens"}, "ai_where": {"tr": "AI kullanılan yerler", "en": "Where AI is used"}, "ai_where_list": {"tr": "SQL üretimi ve kendini düzeltme · tablo adı/sütun açıklaması/özet · örnek soru önerisi · " "cevabı cümleleştirme · hata açıklaması · değerlendirme analizi · çok tabloda şema seçimi", "en": "SQL generation and self-repair · table name/column descriptions/summary · suggested " "questions · answer phrasing · error explanations · evaluation analysis · schema selection " "for many tables"}, "agent_opts": {"tr": "Ajan", "en": "Agent"}, "self_correct": {"tr": "Kendini düzeltme döngüsü", "en": "Self-correction loop"}, "max_attempts": {"tr": "En fazla deneme", "en": "Max attempts"}, "verbalize": {"tr": "Cevabı AI ile cümleleştir", "en": "Phrase the answer with AI"}, "hybrid": {"tr": "AI hata verirse kural tabanlıya geç", "en": "Fall back to rule-based if AI fails"}, "kb": {"tr": "🗄️ Bilgi tabanı", "en": "🗄️ Knowledge base"}, "kb_count": {"tr": "{n} tablo", "en": "{n} tables"}, "reset_samples": {"tr": "Örneklerle sıfırla", "en": "Reset with samples"}, "empty_db": {"tr": "Boşalt", "en": "Empty"}, "backend_err": {"tr": "{e} Kural tabanlı arka uç kullanılacak.", "en": "{e} The rule-based backend will be used."}, # ------------------------------------------------------------------ ① belgeler "pick_doc": {"tr": "Belge seç", "en": "Choose documents"}, "upload": {"tr": "PDF, HTML, CSV veya XLSX yükle", "en": "Upload PDF, HTML, CSV or XLSX"}, "samples": {"tr": "…veya örnek belgeler (sentetik)", "en": "…or sample documents (synthetic)"}, "pdf_extractor": {"tr": "PDF çıkarıcı", "en": "PDF extractor"}, "pdf_extractor_help": {"tr": "auto: pdfplumber (çizgili tablolar, birleşik hücre çözümleme) → bulamazsa Camelot-stream", "en": "auto: pdfplumber (ruled tables, merged-cell resolution) → Camelot-stream if none found"}, "num_mode": {"tr": "Sayı ayrıştırma", "en": "Number parsing"}, "num_mode_help": {"tr": "tr: '1.234,56' = 1234,56 (doğru) · en: naif İngilizce yerel ayar · text: ayrıştırma yok. " "Naif kipler karşılaştırma içindir.", "en": "tr: '1.234,56' = 1234.56 (correct) · en: naive English locale · text: no parsing. " "The naive modes exist for comparison."}, "ai_enrich": {"tr": "AI ile zenginleştir (tablo adı, açıklamalar, özet)", "en": "Enrich with AI (table name, descriptions, summary)"}, "extract": {"tr": "🔍 Tabloları çıkar", "en": "🔍 Extract tables"}, "extracting": {"tr": "Tablolar çıkarılıyor…", "en": "Extracting tables…"}, "enriching": {"tr": "AI tabloları inceliyor ({i}/{n})…", "en": "AI is reviewing tables ({i}/{n})…"}, "no_tables": {"tr": "Tablo bulunamadı. Taranmış (görüntü) PDF'ler için önce OCR gerekir; çizgisiz tablolarda " "'camelot-stream' deneyin.", "en": "No tables found. Scanned (image) PDFs need OCR first; for borderless tables try 'camelot-stream'."}, "extract_hint": {"tr": "Soldan bir belge seçip **Tabloları çıkar**'a basın. Her tablo için ham ızgara (birleşik hücreler " "vurgulu), çözümlenmiş başlıklar, tip/birim çıkarımı ve şema önizlemesi gösterilir.", "en": "Pick a document on the left and press **Extract tables**. For each table you will see the raw " "grid (merged cells highlighted), resolved headers, type/unit inference and a schema preview."}, "n_tables_found": {"tr": "{n} tablo bulundu", "en": "{n} tables found"}, "import_all": {"tr": "⬇️ Tümünü veritabanına aktar", "en": "⬇️ Import all into the database"}, "imported": {"tr": "Aktarıldı: {x}", "en": "Imported: {x}"}, "imported_dl": {"tr": "Veritabanı güncellendi — hemen indirebilirsiniz:", "en": "Database updated — download it now:"}, "untitled": {"tr": "(başlıksız)", "en": "(untitled)"}, "pill_header_rows": {"tr": "{n} başlık satırı", "en": "{n} header rows"}, "pill_merged": {"tr": "{n} birleşik hücre", "en": "{n} merged cells"}, "pill_shape": {"tr": "{r} satır × {c} sütun", "en": "{r} rows × {c} columns"}, "pill_total": {"tr": "toplam satırı işaretlendi", "en": "total row flagged"}, "raw_grid": {"tr": "Ham ızgara", "en": "Raw grid"}, "resolved": {"tr": "Çözümlenmiş tablo", "en": "Resolved table"}, "schema": {"tr": "Şema", "en": "Schema"}, "ai_tab": {"tr": "🤖 AI önerileri", "en": "🤖 AI suggestions"}, "grid_note": {"tr": "Mavi hücreler birleşik (rowspan/colspan). Gri satırlar başlık olarak algılandı.", "en": "Blue cells are merged (rowspan/colspan). Grey rows were detected as headers."}, "col_column": {"tr": "sütun", "en": "column"}, "col_orig": {"tr": "orijinal başlık", "en": "original header"}, "col_type": {"tr": "SQL tipi", "en": "SQL type"}, "col_sem": {"tr": "anlam", "en": "meaning"}, "col_unit": {"tr": "birim", "en": "unit"}, "col_unparsed": {"tr": "ayrıştırılamayan", "en": "unparsed"}, "col_sample": {"tr": "örnek", "en": "sample"}, "col_desc": {"tr": "açıklama", "en": "description"}, "table_name": {"tr": "Tablo adı", "en": "Table name"}, "import_one": {"tr": "Bu tabloyu aktar", "en": "Import this table"}, "imported_one": {"tr": "'{x}' aktarıldı.", "en": "'{x}' imported."}, "ai_summary": {"tr": "AI özeti", "en": "AI summary"}, "ai_name": {"tr": "Önerilen tablo adı", "en": "Suggested table name"}, "ai_warnings": {"tr": "AI uyarıları", "en": "AI warnings"}, "ai_apply": {"tr": "AI önerilerini aktarırken uygula", "en": "Apply AI suggestions on import"}, "ai_badge": {"tr": "AI tarafından üretildi — kontrol edin", "en": "Generated by AI — please review"}, "ai_failed": {"tr": "AI yanıt veremedi: {e}", "en": "AI did not respond: {e}"}, # ------------------------------------------------------------------ ② bilgi tabanı "kb_empty": {"tr": "Bilgi tabanı boş. ① sekmesinden tablo aktarın veya kenar çubuğundan örneklerle sıfırlayın.", "en": "The knowledge base is empty. Import tables in tab ① or reset with samples in the sidebar."}, "meta_table": {"tr": "tablo", "en": "table"}, "meta_caption": {"tr": "belgedeki başlık", "en": "caption in document"}, "meta_source": {"tr": "kaynak", "en": "source"}, "meta_page": {"tr": "sayfa", "en": "page"}, "meta_unit": {"tr": "birim", "en": "unit"}, "meta_rows": {"tr": "satır", "en": "rows"}, "meta_cols": {"tr": "sütun", "en": "columns"}, "meta_merged": {"tr": "birleşik hücre", "en": "merged cells"}, "meta_extractor": {"tr": "çıkarıcı", "en": "extractor"}, "meta_mode": {"tr": "sayı kipi", "en": "number mode"}, "meta_summary": {"tr": "özet", "en": "summary"}, "table": {"tr": "Tablo", "en": "Table"}, "delete_table": {"tr": "🗑️ Tabloyu sil", "en": "🗑️ Delete table"}, "ai_describe": {"tr": "🤖 AI ile açıkla", "en": "🤖 Describe with AI"}, "export_title": {"tr": "⬇️ Veritabanını indir", "en": "⬇️ Download the database"}, "export_help": {"tr": "Çıkarılan tabloların tamamı, meta verileriyle (orijinal başlık, birim, kaynak sayfa) birlikte.", "en": "All extracted tables together with their metadata (original header, unit, source page)."}, "dl_sqlite": {"tr": "SQLite (.db)", "en": "SQLite (.db)"}, "dl_xlsx": {"tr": "Excel (.xlsx)", "en": "Excel (.xlsx)"}, "dl_csv": {"tr": "CSV (.zip)", "en": "CSV (.zip)"}, "dl_sql": {"tr": "SQL dökümü (.sql)", "en": "SQL dump (.sql)"}, "dl_table": {"tr": "Yalnızca bu tablo", "en": "This table only"}, "sql_console": {"tr": "SQL konsolu (salt okunur)", "en": "SQL console (read-only)"}, "sql_help": {"tr": "TR_NORM(x) ve TR_LOWER(x) Türkçe duyarlı yardımcı fonksiyonlardır.", "en": "TR_NORM(x) and TR_LOWER(x) are Turkish-aware helper functions."}, "run": {"tr": "Çalıştır", "en": "Run"}, "select_only": {"tr": "Yalnızca SELECT/WITH sorgularına izin verilir.", "en": "Only SELECT/WITH queries are allowed."}, # ------------------------------------------------------------------ ③ soru sor "examples": {"tr": "Örnek sorular", "en": "Example questions"}, "ai_examples": {"tr": "🤖 AI'nın bu veritabanı için önerdiği sorular", "en": "🤖 Questions AI suggests for this database"}, "regen_examples": {"tr": "🔄 Yeni öneriler", "en": "🔄 New suggestions"}, "ask_placeholder": {"tr": "Sorunuzu yazın…", "en": "Type your question…"}, "ask_rule_note": {"tr": "Kural tabanlı arka uç yalnızca Türkçe soruları anlar; İngilizce soru için bir AI sağlayıcısı seçin.", "en": "The rule-based backend only understands Turkish questions; select an AI provider to ask in English."}, "thinking": {"tr": "Şema bağlanıyor, SQL üretiliyor ve doğrulanıyor…", "en": "Linking schema, generating and validating SQL…"}, "clear_chat": {"tr": "Sohbeti temizle", "en": "Clear chat"}, "st_answer": {"tr": "cevaplandı", "en": "answered"}, "st_abstain": {"tr": "cevap tablolarda yok", "en": "not in the tables"}, "st_notfound": {"tr": "kayıt bulunamadı", "en": "no matching rows"}, "st_error": {"tr": "sorgu üretilemedi", "en": "no query produced"}, "attempts": {"tr": "{n} deneme", "en": "{n} attempt(s)"}, "seconds": {"tr": "{s} sn", "en": "{s} s"}, "agent_steps": {"tr": "Ajan adımları", "en": "Agent steps"}, "model_schema": {"tr": "Modele verilen şema", "en": "Schema given to the model"}, "fallback_used": {"tr": "AI'ya ulaşılamadı, kural tabanlı üreticiye geçildi", "en": "AI unreachable, switched to the rule-based generator"}, "step_sema": {"tr": "Şema bağlama", "en": "Schema linking"}, "step_analiz": {"tr": "Soru çözümleme (kural tabanlı)", "en": "Question analysis (rule-based)"}, "step_uretim": {"tr": "Deneme {k}: aday SQL", "en": "Attempt {k}: candidate SQL"}, "step_uyari_statik": {"tr": "Statik denetim: {tip}", "en": "Static check: {tip}"}, "step_uyari_sonuc": {"tr": "Sonuç denetimi: {tip}", "en": "Result check: {tip}"}, "step_hata_yurutme": {"tr": "Yürütme hatası: {tip}", "en": "Execution error: {tip}"}, "step_hata_model": {"tr": "Model hatası", "en": "Model error"}, "step_geribildirim": {"tr": "Geri besleme gönderildi", "en": "Feedback sent"}, "step_sonuc": {"tr": "Yürütme: {n} satır", "en": "Execution: {n} row(s)"}, "step_cevap": {"tr": "Sonuç", "en": "Result"}, "step_cevapsiz": {"tr": "Cevaplanamaz", "en": "Not answerable"}, "step_ai": {"tr": "AI ile cümleleştirildi", "en": "Phrased by AI"}, "step_fallback": {"tr": "Kural tabanlıya geri düşüldü", "en": "Fell back to rule-based"}, "schema_linked": {"tr": "{n} tablo bağlama alındı: {x}", "en": "{n} table(s) put in context: {x}"}, "feedback_note": {"tr": "Hata tipi ve öneriler bir sonraki denemeye aktarıldı.", "en": "Error type and suggestions passed to the next attempt."}, # ------------------------------------------------------------------ ④ hata kataloğu "err_types": {"tr": "Hata tipleri", "en": "Error types"}, "example": {"tr": "Örnek", "en": "Example"}, "remedy": {"tr": "Önlem", "en": "Remedy"}, "logged_errors": {"tr": "Kaydedilen hatalar", "en": "Logged errors"}, "source": {"tr": "Kaynak", "en": "Source"}, "src_ui": {"tr": "Arayüz oturumları", "en": "UI sessions"}, "src_eval": {"tr": "Değerlendirme çalıştırmaları", "en": "Evaluation runs"}, "no_records": {"tr": "Henüz kayıt yok.", "en": "No records yet."}, "filter_type": {"tr": "Tipe göre süz", "en": "Filter by type"}, "count": {"tr": "adet", "en": "count"}, "explain_pick": {"tr": "AI ile açıklanacak kayıt", "en": "Record to explain with AI"}, "explain_btn": {"tr": "🤖 Bu hatayı AI ile açıkla", "en": "🤖 Explain this error with AI"}, "explain_off": {"tr": "Hataları AI ile açıklamak için kenar çubuğundan bir AI sağlayıcısı seçin.", "en": "Select an AI provider in the sidebar to explain errors with AI."}, # ------------------------------------------------------------------ ⑤ değerlendirme "bench_title": {"tr": "TR-TabloSQL test kümesi", "en": "TR-TabloSQL benchmark"}, "m_questions": {"tr": "Soru", "en": "Questions"}, "m_heldout": {"tr": "Ayrılmış test", "en": "Held-out test"}, "m_unans": {"tr": "Cevapsız soru", "en": "Unanswerable"}, "m_cats": {"tr": "Kategori", "en": "Categories"}, "show_q": {"tr": "Soruları göster", "en": "Show questions"}, "run_eval": {"tr": "Değerlendirmeyi çalıştır", "en": "Run the evaluation"}, "modes": {"tr": "Sayı kipleri", "en": "Number modes"}, "split": {"tr": "Bölüm", "en": "Split"}, "split_all": {"tr": "tümü", "en": "all"}, "run_with": {"tr": "▶️ Seçili arka uçla çalıştır", "en": "▶️ Run with the selected backend"}, "starting": {"tr": "Başlıyor…", "en": "Starting…"}, "detail": {"tr": "Ayrıntı", "en": "Details"}, "only_wrong": {"tr": "Yalnızca yanlışlar", "en": "Wrong answers only"}, "ai_eval": {"tr": "🤖 Hataları AI ile analiz et", "en": "🤖 Analyse failures with AI"}, "last_full": {"tr": "Son tam çalıştırma (`python scripts/run_all.py`)", "en": "Last full run (`python scripts/run_all.py`)"}, "sys_ex": {"tr": "Sistem EX (%)", "en": "System EX (%)"}, "gold_by_mode": {"tr": "**Altın SQL, sayı kipine göre (%)** — doğru sorgu, naif ayrıştırma", "en": "**Gold SQL by number mode (%)** — correct query, naive parsing"}, "dl_report": {"tr": "📄 Başarım raporunu indir (HTML)", "en": "📄 Download the performance report (HTML)"}, "no_full": {"tr": "Henüz tam çalıştırma yok: `python scripts/run_all.py`", "en": "No full run yet: `python scripts/run_all.py`"}, } # Hata kataloğunun İngilizcesi (Türkçesi t2s/errors.py içindedir) CATALOG_EN = { "SEMA_ESLEME": {"ad": "Schema linking error", "tanim": "The question was bound to a wrong or non-existent table/column.", "ornek": "no such column: gerceklesme2024", "cozum": "Suggest similar column names; show original headers and units in the schema."}, "DEGER_ESLEME": {"ad": "Value matching error", "tanim": "A text value did not match the table exactly: Turkish İ/ı-I/i casing, suffixed names, abbreviations.", "ornek": "WHERE il = 'Istanbul' (table has 'İstanbul')", "cozum": "Folded comparison with TR_NORM(); feed back the closest real values."}, "BIRIM": {"ad": "Unit error", "tanim": "Scale/unit conversion missing or wrong (thousand TL ↔ TL, thousand MWh ↔ MWh, m³ ↔ litre, % ↔ ratio).", "ornek": "The question asks for TL but a 'thousand TL' column was returned (1000× off).", "cozum": "Store column units as metadata, show them in the schema; label result units."}, "TARIH_BICIMI": {"ad": "Date format error", "tanim": "Turkish date spelling ('15.03.2025', 'Ocak 2024') did not match the ISO form in the database.", "ornek": "WHERE yururluk_tarihi = '15.03.2025'", "cozum": "Convert dates to ISO on import; catch Turkish date literals in SQL and suggest the conversion."}, "SAYI_BICIMI": {"ad": "Turkish number format error", "tanim": "'1.234,56' was misread: the number stayed text, the dot was taken as decimal (1000× off) " "or the comma as thousands separator; or a Turkish number literal was written into SQL.", "ornek": "SUM('1.234,56') = 1.234 | '4,5' -> 45", "cozum": "Parse with the Turkish locale on import; check SQL literals."}, "SAYISAL_AKIL": {"ad": "Numerical reasoning error", "tanim": "Wrong sum/average/percentage formula; the document's own Total row counted twice; sign " "(negative expense) or integer division errors.", "ornek": "SUM(...) also included the total row (2× result)", "cozum": "toplam_satiri flag; formula evidence; plausibility checks."}, "SOZDIZIMI": {"ad": "SQL syntax error", "tanim": "The generated query could not be parsed or is not valid SQLite.", "ornek": "near \"TOP\": syntax error", "cozum": "Feed back the error message; require SQLite syntax only."}, "BOS_SONUC": {"ad": "Empty result", "tanim": "The query ran but returned no rows; usually a value/date matching problem.", "ornek": "WHERE donem = 'Mart 2025' -> 0 rows", "cozum": "Compare WHERE literals with real table values and suggest the closest ones."}, "CEVAPSIZLIK": {"ad": "Answerability error", "tanim": "A made-up answer to a question the tables cannot answer, or an answerable question refused.", "ornek": "A question about 'Mersin' returned another province's value.", "cozum": "Coverage checks for years/entities; say 'no answer found' when unsure."}, "YURUTME": {"ad": "Other execution error", "tanim": "Unknown function, type mismatch, timeout, etc.", "ornek": "no such function: YEAR", "cozum": "Use SQLite functions (strftime, substr)."}, "YANLIS_SONUC": {"ad": "Wrong result (unclassified)", "tanim": "The query ran but did not match the gold result and could not be assigned a specific subtype.", "ornek": "-", "cozum": "Manual inspection."}, } def t(key: str, lang: str = "tr", **kw) -> str: d = S.get(key) if d is None: return key s = d.get(lang) or d.get("tr") or key return s.format(**kw) if kw else s def catalog(lang: str): from .errors import CATALOG return CATALOG if lang == "tr" else {k: CATALOG_EN.get(k, v) for k, v in CATALOG.items()} # ------------------------------------------------------------------ sayı biçimi def format_num(x, lang: str = "tr", dec: int | None = None) -> str: from .trnum import format_tr if lang == "tr": return format_tr(x, dec) if x is None: return "—" if isinstance(x, bool): return str(x) if isinstance(x, int) or (isinstance(x, float) and x.is_integer() and dec is None): return f"{int(x):,}" if isinstance(x, float): return f"{x:,.{2 if dec is None else dec}f}" return str(x) # ------------------------------------------------------------------ ajan / kural mesajları _ABSTAIN = {"tr": "Bu soruya yüklenen belgelerdeki tablolardan güvenilir bir cevap veremiyorum", "en": "I can't give a reliable answer to this question from the tables in the uploaded documents"} _REASONS_EN = [ (r"^Soru yüklenen tabloların hiçbiriyle eşleşmedi\.$", "The question did not match any of the loaded tables."), (r"^'(.+)' tablosunda (.+) yılına ait veri yok; bu soru mevcut tablolardan cevaplanamaz\.$", r"The table '\1' has no data for \2; this question cannot be answered from the available tables."), (r"^Tabloda (.+) dönemine ait kayıt bulunmuyor; veri bu dönemi kapsamıyor\.$", r"The table has no record for the period \1; the data does not cover it."), (r"^Soruda geçen varlık .*eşleşmedi; bu bilgi belgelerde yer almıyor olabilir\.$", "The entity in the question (e.g. province, item, service name) did not match any table value; " "this information may not be in the documents."), (r"^Soruda tabloya ait bir ölçü \(sütun\) bulunamadı\.$", "No measure (column) of the table was found in the question."), (r"^Değişim hesaplamak için iki dönem/sütun belirlenemedi\.$", "Could not determine two periods/columns to compute a change."), (r"^Uygun sorgu kurulamadı\.$", "No suitable query could be built."), (r"^Model soruyu tablolarla cevaplanamaz buldu\.$", "The model found the question unanswerable from the tables."), ] def abstain_prefix(lang: str) -> str: return _ABSTAIN.get(lang, _ABSTAIN["tr"]) def translate_reason(text: str, lang: str) -> str: if lang == "tr" or not text: return text for pat, rep in _REASONS_EN: if re.match(pat, text): return re.sub(pat, rep, text) return text def answer_texts(lang: str) -> dict: if lang == "en": return {"answer": "Answer", "n_results": "{n} results", "table_below": "{n}-row result table below.", "no_rows": "The query returned no rows.", "notfound": "the query ran but no row matched the condition. The value or period in the question may " "not be in the tables.", "failed": "no working query could be produced in {k} attempts (last error type: {tip}).", "llm_down": "could not reach the language model ({e})."} return {"answer": "Cevap", "n_results": "{n} sonuç", "table_below": "{n} satırlık sonuç tablosu aşağıda.", "no_rows": "Sorgu sonuç döndürmedi.", "notfound": "sorgu çalıştı ancak koşulu sağlayan kayıt bulunamadı. Soruda geçen değer veya dönem tablolarda " "yer almıyor olabilir.", "failed": "{k} denemede çalışan bir sorgu üretilemedi (son hata tipi: {tip}).", "llm_down": "dil modeline erişilemedi ({e})."}