fix(i18n): correct double-escaped ellipsis in Turkish locale

Replace \\u2026 with \u2026 (and fix \\u2192/\\u2713) in the tr block
so ellipsis renders as U+2026 instead of literal backslash-u text.
Add a regression test guarding against double-escaped unicode sequences.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Uğur Murat AltıntasandCursor authored and nesquena-hermes committed 2026-05-24 17:13:34 +00:00
1 parent 6c811dcef5
commit d4603b096d
2 files changed
+41 -31

No files matched your search

+33 -31
View File
@@ -13116,18 +13116,19 @@ const LOCALES = {
offline_title: 'Bağlantı kesildi',
offline_browser_detail: 'Tarayıcınız bu cihazın çevrimdışı olduğunu bildiriyor.',
offline_network_detail: 'Hermes\'e şu anda bu tarayıcıdan ulaşılamıyor.',
offline_autorefresh: 'Hermes\'e tekrar ulaşılabilir olduğunda bu sayfayı otomatik olarak yenileyeceğim.',
offline_check_now: 'Şimdi kontrol et',
offline_checking: 'Kontrol ediliyor\\u2026',
offline_stream_waiting: 'Bağlantı kesildi. Yenilenmesi bekleniyor\\u2026',
offline_checking: 'Kontrol ediliyor\u2026',
offline_stream_waiting: 'Bağlantı kesildi. Yenilenmesi bekleniyor\u2026',
_lang: 'tr',
_label: 'Türkçe',
_speech: 'tr-TR',
// boot.js
cancelling: 'İptal ediliyor\\u2026',
cancelling: 'İptal ediliyor\u2026',
cancel_failed: 'İptal başarısız oldu:',
mic_denied: 'Mikrofon erişimi reddedildi. Tarayıcı izinlerini kontrol edin.',
mic_no_speech: 'Konuşma algılanmadı. Tekrar deneyin.',
@@ -13137,9 +13138,9 @@ const LOCALES = {
voice_dictate_active: 'Dikteyi durdur',
voice_mode_toggle: 'Ses modu',
voice_mode_toggle_active: 'Ses modundan çık',
voice_listening: 'Dinleniyor\\u2026',
voice_speaking: 'Konuşuyor\\u2026',
voice_thinking: 'Düşünüyor\\u2026',
voice_listening: 'Dinleniyor\u2026',
voice_speaking: 'Konuşuyor\u2026',
voice_thinking: 'Düşünüyor\u2026',
voice_error: 'Ses bu tarayıcıda desteklenmiyor',
voice_mode_active: 'Ses modu açık',
voice_mode_off: 'Ses modu kapalı',
@@ -13198,7 +13199,7 @@ const LOCALES = {
mcp_enabled_no: 'Engelli',
mcp_tools_title: 'MCP Araçları',
mcp_tools_desc: 'Aktif MCP sunucularında bilinen araçları arayın.',
mcp_tools_search_placeholder: 'Araçlarda ada, sunucuya veya açıklamaya göre arama yapın\\u2026',
mcp_tools_search_placeholder: 'Araçlarda ada, sunucuya veya açıklamaya göre arama yapın\u2026',
mcp_tools_no_tools: 'Etkin çalışma zamanı envanterinde hiçbir MCP aracı mevcut değil.',
mcp_tools_no_matches: 'Aramanızla eşleşen MCP aracı yok.',
mcp_tools_load_failed: 'MCP araçları yüklenemedi.',
@@ -13236,13 +13237,13 @@ const LOCALES = {
approval_btn_always_title: 'Bu komut düzenine her zaman izin ver',
approval_btn_deny: 'Reddetmek',
approval_btn_deny_title: 'Reddet — bu komutu çalıştırma',
approval_responding: 'Yanıt veriliyor\\u2026',
approval_responding: 'Yanıt veriliyor\u2026',
clarify_heading: 'Açıklama gerekli',
clarify_hint: 'Bir seçim yapın veya kendi cevabınızı aşağıya yazın.',
clarify_other: 'Diğer',
clarify_send: 'Göndermek',
clarify_input_placeholder: 'Yanıtınızı yazın\\u2026',
clarify_responding: 'Yanıt veriliyor\\u2026',
clarify_input_placeholder: 'Yanıtınızı yazın\u2026',
clarify_responding: 'Yanıt veriliyor\u2026',
untitled: 'İsimsiz',
n_messages: (n) => `${n}개 메시지`,
load_older_messages: '↑ Eski mesajları yüklemek için yukarı kaydırın veya tıklayın',
@@ -13262,7 +13263,7 @@ const LOCALES = {
model_not_found_label: 'Model bulunamadı',
model_custom_label: 'Özel model kimliği',
model_custom_placeholder: 'örneğin openai/gpt-5.4',
model_search_placeholder: 'Modelleri ara\\u2026',
model_search_placeholder: 'Modelleri ara\u2026',
session_toolsets: 'Oturum araç setleri',
session_toolsets_desc: 'Bu oturum için kullanılabilir araçları kısıtlayın (boş = genel yapılandırma)',
session_toolsets_global: 'Genel (varsayılan)',
@@ -13275,7 +13276,7 @@ const LOCALES = {
session_toolsets_failed: 'Araç setleri güncellenemedi: ',
model_search_no_results: 'Hiçbir model bulunamadı',
model_group_configured: 'Yapılandırılmış',
ws_search_placeholder: 'Çalışma alanlarını arayın\\u2026',
ws_search_placeholder: 'Çalışma alanlarını arayın\u2026',
ws_no_results: 'Çalışma alanı bulunamadı',
workspace_new_worktree_conversation: 'Worktree\'de yeni konuşma',
workspace_new_worktree_conversation_meta: 'Bu çalışma alanı için yalıtılmış bir git çalışma ağacı oluşturun.',
@@ -13315,7 +13316,7 @@ const LOCALES = {
switched_workspace: 'Çalışma alanına geçildi:',
workspace_switch_failed: 'Çalışma alanı anahtarı başarısız oldu:',
new_session: 'Yeni oturum oluşturuldu',
new_session_creating: 'Yeni görüşme oluşturuluyor\\u2026',
new_session_creating: 'Yeni görüşme oluşturuluyor\u2026',
compressing: 'Bağlam sıkıştırması isteniyor...',
compress_running_label: 'Sıkıştırma',
compress_complete_label: 'Sıkıştırma tamamlandı',
@@ -13331,9 +13332,9 @@ const LOCALES = {
no_active_session: 'Aktif oturum yok',
cmd_queue: 'Bir sonraki dönüş için bir mesajı sıraya koy',
cmd_goal: 'Kalıcı bir hedef belirleyin veya inceleyin',
goal_evaluating_progress: 'Hedef ilerlemesi değerlendiriliyor\\u2026',
goal_working_toward: 'Hedefe doğru çalışmak\\u2026',
goal_continuing_toast: 'Hedefe doğru devam\\u2026',
goal_evaluating_progress: 'Hedef ilerlemesi değerlendiriliyor\u2026',
goal_working_toward: 'Hedefe doğru çalışmak\u2026',
goal_continuing_toast: 'Hedefe doğru devam\u2026',
goal_status_none: 'Aktif hedef yok. /goal <text> ile bir tane ayarlayın.',
goal_status_active: (turns, max_turns, goal) => `⊙ Hedef (aktif, ${turns}/${max_turns} tur): ${goal}`,
goal_status_paused: (turns, max_turns, reason, goal) => `⏸ Hedef (duraklatıldı, ${turns}/${max_turns}${reason ? `, ${reason}` : ''}): ${goal}`,
@@ -13455,7 +13456,7 @@ const LOCALES = {
terminal_input_failed: 'Terminal girişi başarısız oldu:',
terminal_copy_failed: 'Kopyalama başarısız oldu:',
terminal_error: 'Terminal hatası',
workspace_empty_no_path: 'Çalışma alanı seçilmedi. Dosyalara göz atmak için Ayarlar \\u2192 Çalışma Alanı\'nda bir çalışma alanı ayarlayın.',
workspace_empty_no_path: 'Çalışma alanı seçilmedi. Dosyalara göz atmak için Ayarlar \u2192 Çalışma Alanı\'nda bir çalışma alanı ayarlayın.',
workspace_empty_dir: 'Bu çalışma alanı boş.',
workspace_show_hidden_files: 'Gizli dosyaları göster',
workspace_show_hidden_files_desc: 'Dosya ağacına .DS_Store, .git, node_modules ve diğer gizli / sistem dosyalarını ekleyin.',
@@ -13586,8 +13587,8 @@ const LOCALES = {
settings_section_system_title: 'Sistem',
settings_section_system_meta: 'Örnek sürümü ve erişim kontrolleri.',
settings_check_now: 'Şimdi kontrol et',
settings_checking: 'Kontrol ediliyor\\u2026',
settings_up_to_date: 'Güncel \\u2713',
settings_checking: 'Kontrol ediliyor\u2026',
settings_up_to_date: 'Güncel \u2713',
settings_updates_available: '{count} güncelleme mevcut',
settings_updates_disabled: 'Güncelleme kontrolleri devre dışı bırakıldı',
settings_update_check_failed: 'Güncelleme kontrolü başarısız oldu',
@@ -13637,7 +13638,7 @@ const LOCALES = {
font_size_default: 'Varsayılan',
font_size_large: 'Büyük',
font_size_xlarge: 'Ekstra Büyük',
settings_autosave_saving: 'Kaydediliyor\\u2026',
settings_autosave_saving: 'Kaydediliyor\u2026',
settings_autosave_saved: 'Kaydedildi',
settings_autosave_failed: 'Kaydetme başarısız oldu',
settings_autosave_retry: 'Yeniden dene',
@@ -13746,9 +13747,9 @@ const LOCALES = {
kanban_unblock: 'Engellemeyi kaldır',
kanban_back_to_board: 'Panoya geri dön',
kanban_lanes_by_profile: 'Profile göre şeritler',
kanban_new_board: 'Yeni yönetim kurulu\\u2026',
kanban_rename_board: 'Mevcut panoyu yeniden adlandır\\u2026',
kanban_archive_board: 'Mevcut panoyu arşivle\\u2026',
kanban_new_board: 'Yeni yönetim kurulu\u2026',
kanban_rename_board: 'Mevcut panoyu yeniden adlandır\u2026',
kanban_archive_board: 'Mevcut panoyu arşivle\u2026',
kanban_archive_board_confirm: 'Arşiv panosu "{name}"? Görevler diskte kalır ve pano kanban/boards/_archived/ adresinden geri yüklenebilir.',
kanban_board_archived: 'Pano arşivlendi',
kanban_board_name: 'İsim',
@@ -13844,7 +13845,7 @@ const LOCALES = {
settings_desc_whats_new_summary: "Changes the What's New action from opening the raw diff first to generating a short, human-readable summary. The regular diff comparison stays available after the summary.",
settings_desc_bot_name: 'Yalnızca varsayılan profil için kullanılır. Diğer profiller kendi profil adlarını kullanır.',
settings_desc_password: 'Ayarlamak veya değiştirmek için yeni bir şifre girin. Geçerli ayarı korumak için boş bırakın.',
password_placeholder: 'Yeni şifreyi girin\\u2026',
password_placeholder: 'Yeni şifreyi girin\u2026',
password_env_var_locked: 'HERMES_WEBUI_PASSWORD ortam değişkeni şu anda ayarlıdır ve önceliklidir. Şifreyi buradan yönetmek için ayarı kaldırın ve sunucuyu yeniden başlatın.',
password_env_var_locked_placeholder: 'Kilitli: HERMES_WEBUI_PASSWORD ortam değişkeni ayarlandı',
disable_auth: 'Kimlik Doğrulamasını Devre Dışı Bırak',
@@ -13863,14 +13864,14 @@ const LOCALES = {
providers_oauth_not_configured_hint: 'Kimliği doğrulanmadı. Bu sağlayıcıyı yapılandırmak için terminalde Hermes Auth komutunu çalıştırın.',
providers_save: 'Kaydetmek',
providers_remove: 'Kaldırmak',
providers_saving: 'Kaydediliyor\\u2026',
providers_removing: 'Kaldırılıyor\\u2026',
providers_saving: 'Kaydediliyor\u2026',
providers_removing: 'Kaldırılıyor\u2026',
providers_enter_key: 'Lütfen bir API anahtarı girin',
providers_empty: 'Yapılandırılabilir sağlayıcı bulunamadı.',
providers_key_updated: 'API anahtarı kaydedildi',
providers_key_removed: 'API anahtarı kaldırıldı',
providers_key_placeholder_new: 'sk-...',
providers_key_placeholder_replace: 'Değiştirilecek yeni anahtarı girin\\u2026',
providers_key_placeholder_replace: 'Değiştirilecek yeni anahtarı girin\u2026',
provider_quota_title: 'Etkin sağlayıcı kotası',
provider_quota_active_provider: 'Aktif sağlayıcı',
provider_quota_last_checked_after_refresh: 'Yenilemeden sonra son kontrol edildi',
@@ -14041,7 +14042,7 @@ const LOCALES = {
cron_status_paused: 'duraklatıldı',
cron_status_error: 'hata',
cron_status_active: 'aktif',
cron_status_running: 'koşuyor\\u2026',
cron_status_running: 'koşuyor\u2026',
cron_status_needs_attention: 'dikkat edilmesi gerekiyor',
cron_attention_desc: 'Bu yinelenen işin bir sonraki çalışma süresi yoktur. Zamanlayıcı bir sonraki çalıştırmayı hesaplamada başarısız olmuş olabilir.',
cron_attention_croniter_hint: 'Ağ Geçidi çalışma zamanında croniter paketi eksik olabilir. Ağ Geçidini cron desteğiyle yeniden başlatın, ardından bu işe devam edin.',
@@ -14206,7 +14207,7 @@ const LOCALES = {
cron_toast_notifications_enabled: 'Etkinleştirilmiş',
cron_toast_notifications_disabled: 'Engelli',
cron_skills_label: 'Yetenekler',
cron_skills_placeholder: 'Beceri ekleyin (isteğe bağlı)\\u2026',
cron_skills_placeholder: 'Beceri ekleyin (isteğe bağlı)\u2026',
cron_skills_edit_hint: 'Beceri listesi oluşturulduktan sonra düzenlenemez.',
// workspace form
workspace_name_label: 'İsim',
@@ -14247,12 +14248,12 @@ const LOCALES = {
composer_mobile_reasoning: 'muhakeme',
composer_mobile_context: 'Bağlam',
pdf_loading: 'PDF {0} yükleniyor\\u2026',
pdf_loading: 'PDF {0} yükleniyor\u2026',
pdf_too_large: 'PDF satır içi önizleme için çok büyük',
pdf_no_pages: 'PDF\'de sayfa yok',
pdf_error: 'PDF önizlemesi oluşturulamadı',
pdf_download: 'PDF\'yi indir',
html_loading: 'HTML önizlemesi yükleniyor\\u2026',
html_loading: 'HTML önizlemesi yükleniyor\u2026',
html_too_large: 'HTML satır içi önizleme için çok büyük',
html_error: 'HTML önizlemesi oluşturulamadı',
html_open_full: 'Tam sayfayı aç',
@@ -14330,6 +14331,7 @@ const LOCALES = {
subagent_children: 'Alt agent oturumları',
}
};
+8
View File
@@ -145,3 +145,11 @@ def test_turkish_locale_keys_use_standard_indentation():
if re.match(r"^\s{1,3}[a-zA-Z0-9_]+\s*:", line)
]
assert badly_indented == []
def test_turkish_locale_has_no_double_escaped_unicode_sequences():
"""JSON-style double escapes (\\\\u2026) render literal backslash-u in the UI."""
src = read(REPO / "static" / "i18n.js")
tr_block = extract_locale_block(src, "tr")
for bad in ("\\\\u2026", "\\\\u2192", "\\\\u2713"):
assert bad not in tr_block, f"Turkish locale must not contain {bad!r}"