Text-to-SQL / t2s /i18n.py
SevdanurGenc's picture
Upload 466 files
a72d1cf verified
Raw History Blame Contribute Delete
39 kB
"""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})."}