feat(ui): localize commit AI and git error messages to English
Translate commit AI prompts, model labels, and git/keychain errors to English so the app and generated messages are consistent. Also add a discard confirmation dialog and update the UI text/styles to match the new flow. - src-tauri/crates/commit_ai/src/cloud.rs - Translate HTTP and API error messages to English. - Keep request timeout and token sizing behavior unchanged. - src-tauri/crates/commit_ai/src/lib.rs - Translate model labels, prompt text, and validation errors. - Keep diff truncation and message sanitization logic intact. - src-tauri/src/git.rs - Translate git, credential, merge, and history errors. - Update AI provider validation messages to English. - src/lib/components/* - Update AI settings, commit panel, credential, and loading UI text. - Add discard confirmation dialog for destructive actions. - src/App.svelte, src/app.css - Adjust app layout and styling for the new dialog and text changes.
This commit is contained in:
@@ -4,16 +4,16 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{build_messages, sanitize_message};
|
||||
|
||||
// Großzügig bemessen, damit ein ausführlicher Body mit Stichpunkten nicht abgeschnitten wird.
|
||||
// Generous sizing so a detailed body with bullet points isn't cut off.
|
||||
const DEFAULT_MAX_TOKENS: u32 = 1500;
|
||||
// Ohne Timeout würde ein hängender Endpoint den "AI"-Button dauerhaft blockieren.
|
||||
// Without a timeout, a hanging endpoint would permanently block the "AI" button.
|
||||
const REQUEST_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
|
||||
fn http_client() -> Result<reqwest::Client, String> {
|
||||
reqwest::Client::builder()
|
||||
.timeout(REQUEST_TIMEOUT)
|
||||
.build()
|
||||
.map_err(|err| format!("HTTP-Client konnte nicht erstellt werden: {err}"))
|
||||
.map_err(|err| format!("Could not create HTTP client: {err}"))
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -71,19 +71,19 @@ async fn openai_compatible_request(
|
||||
let response = request
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("Anfrage an das KI-Modell fehlgeschlagen: {err}"))?;
|
||||
.map_err(|err| format!("Request to the AI model failed: {err}"))?;
|
||||
let status = response.status();
|
||||
let text = response
|
||||
.text()
|
||||
.await
|
||||
.map_err(|err| format!("Antwort konnte nicht gelesen werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not read response: {err}"))?;
|
||||
|
||||
if !status.is_success() {
|
||||
return Err(format!("API-Fehler ({status}): {text}"));
|
||||
return Err(format!("API error ({status}): {text}"));
|
||||
}
|
||||
|
||||
let parsed: OpenAiResponse = serde_json::from_str(&text)
|
||||
.map_err(|err| format!("Antwort konnte nicht verarbeitet werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not process response: {err}"))?;
|
||||
|
||||
parsed
|
||||
.choices
|
||||
@@ -92,7 +92,7 @@ async fn openai_compatible_request(
|
||||
.and_then(|choice| choice.message.content)
|
||||
.map(|content| sanitize_message(&content))
|
||||
.filter(|content| !content.is_empty())
|
||||
.ok_or_else(|| "Das Modell hat keine Antwort geliefert.".to_string())
|
||||
.ok_or_else(|| "The model did not return a response.".to_string())
|
||||
}
|
||||
|
||||
pub async fn generate_openai(
|
||||
@@ -102,7 +102,7 @@ pub async fn generate_openai(
|
||||
notes: Option<&str>,
|
||||
) -> Result<String, String> {
|
||||
if api_key.trim().is_empty() {
|
||||
return Err("OpenAI-API-Key fehlt.".to_string());
|
||||
return Err("OpenAI API key is missing.".to_string());
|
||||
}
|
||||
openai_compatible_request(
|
||||
"https://api.openai.com/v1/chat/completions".to_string(),
|
||||
@@ -122,7 +122,7 @@ pub async fn generate_custom(
|
||||
notes: Option<&str>,
|
||||
) -> Result<String, String> {
|
||||
if base_url.trim().is_empty() {
|
||||
return Err("Endpoint-URL fehlt.".to_string());
|
||||
return Err("Endpoint URL is missing.".to_string());
|
||||
}
|
||||
let url = format!("{}/chat/completions", base_url.trim_end_matches('/'));
|
||||
openai_compatible_request(url, api_key, model, diff, notes).await
|
||||
@@ -161,7 +161,7 @@ pub async fn generate_anthropic(
|
||||
notes: Option<&str>,
|
||||
) -> Result<String, String> {
|
||||
if api_key.trim().is_empty() {
|
||||
return Err("Anthropic-API-Key fehlt.".to_string());
|
||||
return Err("Anthropic API key is missing.".to_string());
|
||||
}
|
||||
let (system, user) = build_messages(diff, notes)?;
|
||||
let body = AnthropicRequest {
|
||||
@@ -179,19 +179,19 @@ pub async fn generate_anthropic(
|
||||
.json(&body)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("Anfrage an Anthropic fehlgeschlagen: {err}"))?;
|
||||
.map_err(|err| format!("Request to Anthropic failed: {err}"))?;
|
||||
let status = response.status();
|
||||
let text = response
|
||||
.text()
|
||||
.await
|
||||
.map_err(|err| format!("Antwort konnte nicht gelesen werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not read response: {err}"))?;
|
||||
|
||||
if !status.is_success() {
|
||||
return Err(format!("API-Fehler ({status}): {text}"));
|
||||
return Err(format!("API error ({status}): {text}"));
|
||||
}
|
||||
|
||||
let parsed: AnthropicResponse = serde_json::from_str(&text)
|
||||
.map_err(|err| format!("Antwort konnte nicht verarbeitet werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not process response: {err}"))?;
|
||||
|
||||
parsed
|
||||
.content
|
||||
@@ -199,5 +199,5 @@ pub async fn generate_anthropic(
|
||||
.find_map(|block| block.text)
|
||||
.map(|text| sanitize_message(&text))
|
||||
.filter(|text| !text.is_empty())
|
||||
.ok_or_else(|| "Das Modell hat keine Antwort geliefert.".to_string())
|
||||
.ok_or_else(|| "The model did not return a response.".to_string())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user