80f9e01
use axum::extract::State;
use export::rest::AppResponseData;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
use crate::errors::ApiError;
use crate::service::GitService;
/// 一门可选的输出语言。
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct LanguageOptionDto {
/// BCP-47 代码(小写、`-` 分隔),如 `zh-cn`、`en`、`ja`。
pub code: String,
/// 本语名称,如「简体中文」。
pub native_name: String,
/// 英文名称,如 "Simplified Chinese"。
pub english_name: String,
/// 是否为「沿用内容语言」模式。
pub auto: bool,
/// 是否为部署时的缺省语言。
pub default: bool,
}
#[utoipa::path(
get,
path = "/ai/languages",
tag = "ai",
description = "AI 输出语言清单;前端据此渲染语言选择器。`auto` 表示沿用代码注释的语言。",
responses(
(status = 200, description = "supported languages", body = AppResponseData<Vec<LanguageOptionDto>>)
)
)]
pub async fn list_ai_languages(
State(service): State<GitService>,
) -> Result<AppResponseData<Vec<LanguageOptionDto>>, ApiError> {
let configured = ci_protocol::ai_languages::normalize(&service.state.config.ai.output_language);
let options = ci_protocol::ai_languages::supported_codes()
.into_iter()
.map(|code| {
let auto = ci_protocol::ai_languages::is_auto(code);
let (native, english) = if auto {
("沿用内容语言".to_string(), "Match content".to_string())
} else {
let display = ci_protocol::ai_languages::display_name(code);
// display_name 形如「简体中文 (Simplified Chinese)」;拆回两段。
match display.split_once(" (") {
Some((native, english)) => (
native.to_string(),
english.trim_end_matches(')').to_string(),
),
None => (display.clone(), display),
}
};
LanguageOptionDto {
code: code.to_string(),
native_name: native,
english_name: english,
auto,
default: code == configured,
}
})
.collect();
Ok(AppResponseData::ok(options))
}