feat: add i18n framework with Indonesian translation support (#124)

* feat: add i18n support with separate translation files

- Extract translations from store.js to separate files for easier management
- Add translation files for English (en.js), Indonesian (id.js), Turkish (tr.js), and Chinese (zh.js)
- Load translations via window.translations object before Alpine store initialization
- Add Bahasa Indonesia option to language selector

* feat: translate remaining hardcoded UI strings

- Update index.html to use t() for Menu and GitHub labels
- Update views to translate Tier, Quota, Live, tier badges, and close button
- Update components to use translated error messages and confirmation dialogs
- Update utils to use translated validation and error messages
- Update app-init.js to use translated OAuth success/error messages
This commit is contained in:
Irvan Fauziansyah
2026-01-15 22:33:38 +07:00
committed by GitHub
parent 9ffb83ab74
commit e2d03f9b25
17 changed files with 1413 additions and 890 deletions

View File

@@ -0,0 +1,316 @@
/**
* Turkish (Türkçe) Translations
*/
window.translations = window.translations || {};
window.translations.tr = {
dashboard: "Panel",
models: "Modeller",
accounts: "Hesaplar",
logs: "Günlükler",
settings: "Ayarlar",
online: "ÇEVRİMİÇİ",
offline: "ÇEVRİMDIŞI",
totalAccounts: "TOPLAM HESAP",
active: "AKTİF",
operational: "Çalışıyor",
rateLimited: "HIZ SINIRLANDI",
quotasDepleted: "{count}/{total} Kota Tükendi",
quotasDepletedTitle: "KOTA TÜKENDİ",
outOfTracked: "{total} Takip Edilen İçinden",
cooldown: "Soğuma",
searchPlaceholder: "Modelleri ara...",
allAccounts: "Tüm Hesaplar",
stat: "DURUM",
modelIdentity: "MODEL KİMLİĞİ",
globalQuota: "GENEL KOTA",
nextReset: "SONRAKİ SIFIRLAMA",
distribution: "HESAP DAĞILIMI",
systemConfig: "Sistem Yapılandırması",
language: "Dil",
pollingInterval: "Veri Güncelleme Aralığı",
maxDisplayLogs: "Maksimum Görüntülenen Günlük",
showExhausted: "Tükenmiş Modelleri Göster",
showExhaustedDesc: "%0 kotası kalan modelleri de göster.",
compactMode: "Kompakt Mod",
compactModeDesc: "Daha fazla bilgi göstermek için tablo boşluklarını azalt.",
saveChanges: "Değişiklikleri Kaydet",
autoScroll: "Otomatik Kaydır",
clearLogs: "Günlükleri Temizle",
accountManagement: "Hesap Yönetimi",
manageTokens: "Google Hesap jetonlarını ve yetkilendirme durumlarını yönet",
addAccount: "Hesap Ekle",
status: "DURUM",
enabled: "ETKİN",
health: "SAĞLIK",
accountEmail: "HESAP (E-POSTA)",
source: "KAYNAK",
projectId: "PROJE ID",
sessionState: "OTURUM DURUMU",
operations: "İŞLEMLER",
delete: "Sil",
confirmDelete: "Bu hesabı kaldırmak istediğinizden emin misiniz?",
cannotDeleteDatabase: "Silinemez: Bu hesap Antigravity veritabanından (salt okunur)",
connectGoogle: "Google Hesabı Bağla",
reauthenticated: "yeniden doğrulandı",
added: "eklendi",
successfully: "başarıyla",
accountAddedSuccess: "Hesap başarıyla eklendi",
accountReauthSuccess: "Hesap başarıyla yeniden doğrulandı",
failedToGetAuthUrl: "Yetkilendirme URL'si alınamadı",
failedToStartOAuth: "OAuth akışı başlatılamadı",
oauthInProgress: "OAuth devam ediyor. Lütfen açılır pencerede kimlik doğrulamayı tamamlayın...",
family: "Aile",
model: "Model",
activeSuffix: "Aktif",
manualReload: "Yapılandırmayı Yeniden Yükle",
// Tabs
tabInterface: "Arayüz",
tabClaude: "Claude CLI",
tabModels: "Modeller",
tabServer: "Sunucu Ayarları",
// Dashboard
linkedAccounts: "Bağlı Hesaplar",
noSignal: "SİNYAL YOK",
establishingUplink: "BAĞLANTI KURULUYOR...",
goToAccounts: "Hesaplara Git",
// Settings - Models
modelsDesc: "Model görünürlüğünü, sabitlemeyi ve istek yönlendirmeyi yapılandırın.",
modelsPageDesc: "Tüm mevcut modeller için gerçek zamanlı kota ve durum.",
showHidden: "Gizli Modelleri Göster",
hideHidden: "Gizli Modelleri Gizle",
hiddenOn: "Gizli: AÇIK",
hiddenOff: "Gizli: KAPALI",
modelId: "Model ID",
actions: "İşlemler",
pinToTop: "En Üste Sabitle",
toggleVisibility: "Görünürlüğü Değiştir",
noModels: "MODEL ALGILANMADI",
modelMappingHint: "Sunucu tarafı model yönlendirme. Claude Code kullanıcıları: istemci tarafı kurulumu için 'Claude CLI' sekmesine bakın.",
modelMapping: "Eşleştirme (Hedef Model ID)",
// Settings - Claude
proxyConnection: "Proxy Bağlantısı",
modelSelection: "Model Seçimi",
defaultModelAliases: "VARSAYILAN MODEL TAKMA ADLARI",
opusAlias: "Opus Takma Adı",
sonnetAlias: "Sonnet Takma Adı",
haikuAlias: "Haiku Takma Adı",
claudeSettingsAlertPrefix: "Aşağıdaki ayarlar doğrudan değiştirir",
claudeSettingsAlertSuffix: "Uygulamak için Claude CLI'yı yeniden başlatın.",
applyToClaude: "Claude CLI'ya Uygula",
// Settings - Server
port: "Port",
uiVersion: "Arayüz Sürümü",
debugMode: "Hata Ayıklama Modu",
environment: "Ortam",
serverReadOnly: "Ayarlar config.json üzerinden yönetilir. Değişiklikleri uygulamak için sunucuyu yeniden başlatın.",
advancedSettings: "Gelişmiş Ayarlar",
reloadConfigTitle: "Hesap Yapılandırmasını Yeniden Yükle",
reloadConfigDesc: "accounts.json dosyasını diskten yeniden yüklemeye zorla",
reload: "Yeniden Yükle",
// Config Specific
primaryModel: "Birincil Model",
subAgentModel: "Alt Ajan Modeli",
advancedOverrides: "Varsayılan Model Geçersiz Kılmaları",
opusModel: "Opus Modeli",
sonnetModel: "Sonnet Modeli",
haikuModel: "Haiku Modeli",
authToken: "Yetkilendirme Jetonu",
saveConfig: "Claude CLI ayarlarına kaydet",
envVar: "Ortam Değişkeni",
// New Keys
systemName: "ANTIGRAVITY",
systemDesc: "CLAUDE PROXY SİSTEMİ",
connectGoogleDesc: "API kota limitinizi artırmak için bir Google Workspace hesabı bağlayın. Bu hesap, Claude isteklerini Antigravity üzerinden vekil sunucu olarak kullanmak için kullanılacaktır.",
useCliCommand: "CLI Komutunu Kullan",
close: "Kapat",
requestVolume: "İstek Hacmi",
filter: "Filtrele",
all: "Tümü",
none: "Hiçbiri",
noDataTracked: "Henüz veri izlenmedi",
selectFamilies: "Görüntülenecek aileleri seçin",
selectModels: "Görüntülenecek modelleri seçin",
noLogsMatch: "Filtreyle eşleşen günlük yok",
connecting: "BAĞLANILIYOR",
main: "Ana",
system: "Sistem",
refreshData: "Verileri Yenile",
connectionLost: "Bağlantı Kaybedildi",
lastUpdated: "Son Güncelleme",
grepLogs: "günlükleri ara...",
noMatchingModels: "Eşleşen model yok",
typeToSearch: "Aramak veya seçmek için yazın...",
or: "VEYA",
refreshingAccount: "{email} yenileniyor...",
refreshedAccount: "{email} yenilendi",
refreshFailed: "Yenileme başarısız",
accountToggled: "Hesap {email} {status}",
toggleFailed: "Değiştirme başarısız",
reauthenticating: "{email} yeniden doğrulanıyor...",
authUrlFailed: "Yetkilendirme URL'si alınamadı",
deletedAccount: "{email} silindi",
deleteFailed: "Silme başarısız",
accountsReloaded: "Hesaplar yeniden yüklendi",
reloadFailed: "Yeniden yükleme başarısız",
claudeConfigSaved: "Claude yapılandırması kaydedildi",
claudeConfigRestored: "Claude CLI varsayılanlara geri yüklendi",
saveConfigFailed: "Yapılandırma kaydedilemedi",
restoreConfigFailed: "Yapılandırma geri yüklenemedi",
restoreDefault: "Varsayılana Dön",
confirmRestoreTitle: "Geri Yüklemeyi Onayla",
confirmRestoreMessage: "Claude CLI'yı varsayılan ayarlara geri yüklemek istediğinizden emin misiniz? Bu işlem proxy yapılandırmasını kaldıracaktır.",
confirmRestore: "Geri Yüklemeyi Onayla",
claudeActive: "Claude Aktif",
claudeEmpty: "Claude Boş",
geminiActive: "Gemini Aktif",
geminiEmpty: "Gemini Boş",
synced: "EŞİTLENDİ",
syncing: "EŞİTLENİYOR...",
// Time range labels
last1Hour: "Son 1S",
last6Hours: "Son 6S",
last24Hours: "Son 24S",
last7Days: "Son 7G",
allTime: "Tüm Zamanlar",
groupBy: "Gruplama Ölçütü",
// Additional
reloading: "Yeniden yükleniyor...",
reloaded: "Yeniden yüklendi",
lines: "satır",
enabledSeeLogs: "Etkin (Günlüklere Bak)",
production: "Üretim",
configSaved: "Yapılandırma Kaydedildi",
enterPassword: "Web UI Parolasını Girin:",
ready: "HAZIR",
depleted: "Tükendi",
timeH: "S",
timeM: "D",
familyClaude: "Claude",
familyGemini: "Gemini",
familyOther: "Diğer",
enabledStatus: "etkin",
disabledStatus: "devre dışı",
logLevelInfo: "BİLGİ",
logLevelSuccess: "BAŞARILI",
logLevelWarn: "UYARI",
logLevelError: "HATA",
totalColon: "Toplam:",
todayColon: "Bugün:",
hour1Colon: "1S:",
frequentModels: "Sık Kullanılan",
smartTitle: "En çok kullanılan 5 modeli otomatik seç (24s)",
activeCount: "{count} Aktif",
allCaps: "TÜMÜ",
claudeCaps: "CLAUDE",
geminiCaps: "GEMINI",
modelMapping: "Eşleştirme (Hedef Model ID)",
systemInfo: "Sistem Bilgisi",
refresh: "Yenile",
runtimeConfig: "Çalışma Zamanı Yapılandırması",
debugDesc: "Ayrıntılı günlük kaydını etkinleştir (Günlükler sekmesine bakın)",
networkRetry: "Ağ Yeniden Deneme Ayarları",
maxRetries: "Maksimum Deneme",
retryBaseDelay: "Yeniden Deneme Temel Gecikmesi (ms)",
retryMaxDelay: "Yeniden Deneme Maksimum Gecikmesi (ms)",
persistentSessions: "Kalıcı Oturumlar",
persistTokenDesc: "Daha hızlı yeniden başlatmalar için OAuth oturumlarını diske kaydet",
rateLimiting: "Hesap Hız Sınırlama ve Zaman Aşımları",
defaultCooldown: "Varsayılan Soğuma Süresi",
maxWaitThreshold: "Maksimum Bekleme Eşiği (Yapışkan)",
maxWaitDesc: "Yapışkan bir hesabın değiştirmeden önce sıfırlanması için beklenecek maksimum süre.",
saveConfigServer: "Yapılandırmayı Kaydet",
serverRestartAlert: "Değişiklikler {path} konumuna kaydedildi. Bazı ayarları uygulamak için sunucuyu yeniden başlatın.",
changePassword: "WebUI Parolasını Değiştir",
changePasswordDesc: "Bu panoya erişim parolasını güncelle",
currentPassword: "Mevcut Parola",
newPassword: "Yeni Parola",
confirmNewPassword: "Yeni Parolayı Onayla",
passwordEmptyDesc: "Parola ayarlanmamışsa boş bırakın",
passwordLengthDesc: "En az 6 karakter",
passwordConfirmDesc: "Yeni parolayı tekrar girin",
cancel: "İptal",
passwordsNotMatch: "Parolalar eşleşmiyor",
passwordTooShort: "Parola en az 6 karakter olmalıdır",
// Dashboard drill-down
clickToViewAllAccounts: "Tüm hesapları görüntülemek için tıklayın",
clickToViewModels: "Modeller sayfasını görüntülemek için tıklayın",
clickToViewLimitedAccounts: "Hız sınırı olan hesapları görüntülemek için tıklayın",
clickToFilterClaude: "Claude modellerini filtrelemek için tıklayın",
clickToFilterGemini: "Gemini modellerini filtrelemek için tıklayın",
// Accounts page
searchAccounts: "Hesap ara...",
noAccountsYet: "Henüz Hesap Yok",
noAccountsDesc: "OAuth üzerinden bir Google hesabı ekleyerek veya kimlik bilgilerini içe aktarmak için CLI komutunu kullanarak başlayın.",
addFirstAccount: "İlk Hesabınızı Ekleyin",
noSearchResults: "Aramanızla eşleşen hesap yok",
clearSearch: "Aramayı Temizle",
disabledAccountsNote: "<strong>Devre dışı bırakılan hesaplar</strong> istek yönlendirmesi için kullanılmayacak ancak yapılandırmada kalacaktır. Pano istatistikleri yalnızca etkin hesapları içerir.",
dangerousOperation: "⚠️ Tehlikeli İşlem",
confirmDeletePrompt: "Hesabı silmek istediğinizden emin misiniz",
deleteWarning: "⚠️ Bu işlem geri alınamaz. Tüm yapılandırma ve geçmiş kayıtları kalıcı olarak silinecektir.",
// OAuth progress
oauthWaiting: "OAuth yetkilendirmesi bekleniyor...",
oauthWaitingDesc: "Lütfen açılır pencerede kimlik doğrulamasını tamamlayın. Bu işlem 2 dakikaya kadar sürebilir.",
oauthCancelled: "OAuth yetkilendirmesi iptal edildi",
oauthTimeout: "⏱️ OAuth yetkilendirmesi zaman aşımına uğradı. Lütfen tekrar deneyin.",
oauthWindowClosed: "OAuth penceresi kapatıldı. Yetkilendirme tamamlanmamış olabilir.",
cancelOAuth: "İptal",
// MCP CLI & Gemini 1M
mcpCliExperimental: "Deneysel MCP CLI",
mcpCliDesc: "Daha az bağlam tüketimi ile güvenilir araç kullanımı için deneysel MCP entegrasyonunu etkinleştirir.",
gemini1mMode: "Gemini 1M Bağlam Modu",
gemini1mDesc: "1M bağlam penceresi desteği için Gemini modellerine [1m] son eki ekler.",
gemini1mWarning: "⚠ Büyük bağlam, Gemini-3-Pro performansını düşürebilir.",
clickToSet: "Yapılandırmak için tıklayın...",
none: "Hiçbiri",
// Quota Distribution
quotaDistribution: "Kota Dağılımı",
resetsIn: "{time} içinde sıfırlanır",
noQuotaData: "Bu hesap için henüz kota verisi yok.",
// TODO: Missing translations - Hardcoded strings from HTML
// pageTitle: "Antigravity Console",
// live: "Live",
// tier: "Tier",
// quota: "Quota",
// tierUltra: "Ultra",
// tierPro: "Pro",
// tierFree: "Free",
// menu: "Menu",
// github: "GitHub",
// noData: "No data",
// fix: "Fix",
// TODO: Missing translations - Hardcoded strings from JS (Error Messages)
// operationFailed: "Operation failed",
// unknownError: "Unknown error",
// presetNameRequired: "Preset name is required",
// saveFailed: "Save failed",
// failedToSavePreset: "Failed to save preset",
// noPresetSelected: "No preset selected",
// deletePresetConfirm: "Delete preset \"{name}\"?",
// deleteFailed: "Delete failed",
// failedToDeletePreset: "Failed to delete preset",
// failedToChangePassword: "Failed to change password",
// passwordChangedSuccess: "Password changed successfully",
// debugModeToggled: "Debug mode {status}",
// tokenCacheToggled: "Token cache {status}",
// failedToUpdateTokenCache: "Failed to update token cache",
// failedToUpdateDebugMode: "Failed to update debug mode",
// failedToRefreshAccount: "Failed to refresh account",
// failedToDeleteAccount: "Failed to delete account",
// failedToReloadAccounts: "Failed to reload accounts",
// failedToUpdateModelConfig: "Failed to update model config",
// fieldUpdated: "{displayName} updated to {value}",
// failedToUpdateField: "Failed to update {displayName}",
// TODO: Missing translations - Validation messages from validators.js
// mustBeValidNumber: "{fieldName} must be a valid number",
// mustBeAtLeast: "{fieldName} must be at least {min}",
// mustBeAtMost: "{fieldName} must be at most {max}",
// cannotBeEmpty: "{fieldName} cannot be empty",
// mustBeTrueOrFalse: "Value must be true or false",
// TODO: Missing translation - Server config (exists in EN but missing here)
// defaultCooldownDesc: "Fallback cooldown when API doesn't provide a reset time.",
};