feat: feat: add multilingual output support for commit, tag, and changelog commands
This commit is contained in:
@@ -3,9 +3,10 @@ use clap::Parser;
|
||||
use colored::Colorize;
|
||||
use dialoguer::{Confirm, Input, Select};
|
||||
|
||||
use crate::config::{GitProfile};
|
||||
use crate::config::{GitProfile, Language};
|
||||
use crate::config::manager::ConfigManager;
|
||||
use crate::config::profile::{GpgConfig, SshConfig};
|
||||
use crate::i18n::Messages;
|
||||
use crate::utils::validators::validate_email;
|
||||
|
||||
/// Initialize quicommit configuration
|
||||
@@ -22,7 +23,9 @@ pub struct InitCommand {
|
||||
|
||||
impl InitCommand {
|
||||
pub async fn execute(&self) -> Result<()> {
|
||||
println!("{}", "🚀 Initializing QuiCommit...".bold().cyan());
|
||||
// Start with English messages for initialization
|
||||
let messages = Messages::new(Language::English);
|
||||
println!("{}", messages.initializing().bold().cyan());
|
||||
|
||||
let config_path = crate::config::AppConfig::default_path()?;
|
||||
|
||||
@@ -57,9 +60,13 @@ impl InitCommand {
|
||||
|
||||
manager.save()?;
|
||||
|
||||
println!("{}", "✅ QuiCommit initialized successfully!".bold().green());
|
||||
println!("\nConfig file: {}", config_path.display());
|
||||
println!("\nNext steps:");
|
||||
// Get configured language for final messages
|
||||
let language = manager.get_language().unwrap_or(Language::English);
|
||||
let messages = Messages::new(language);
|
||||
|
||||
println!("{}", messages.init_success().bold().green());
|
||||
println!("\n{}: {}", messages.config_file(), config_path.display());
|
||||
println!("\n{}:", messages.next_steps());
|
||||
println!(" 1. Create a profile: {}", "quicommit profile add".cyan());
|
||||
println!(" 2. Configure LLM: {}", "quicommit config set-llm".cyan());
|
||||
println!(" 3. Start committing: {}", "quicommit commit".cyan());
|
||||
@@ -90,11 +97,35 @@ impl InitCommand {
|
||||
}
|
||||
|
||||
async fn interactive_setup(&self, manager: &mut ConfigManager) -> Result<()> {
|
||||
println!("\n{}", "Let's set up your first profile:".bold());
|
||||
let messages = Messages::new(Language::English);
|
||||
println!("\n{}", messages.setup_profile().bold());
|
||||
|
||||
// Language selection
|
||||
println!("\n{}", messages.select_output_language().bold());
|
||||
let languages = vec![
|
||||
Language::English,
|
||||
Language::Chinese,
|
||||
Language::Japanese,
|
||||
Language::Korean,
|
||||
Language::Spanish,
|
||||
Language::French,
|
||||
Language::German,
|
||||
];
|
||||
let language_names: Vec<String> = languages.iter().map(|l| l.display_name().to_string()).collect();
|
||||
let language_idx = Select::new()
|
||||
.items(&language_names)
|
||||
.default(0)
|
||||
.interact()?;
|
||||
|
||||
let selected_language = languages[language_idx];
|
||||
manager.set_output_language(selected_language.to_code().to_string());
|
||||
|
||||
// Update messages to selected language
|
||||
let messages = Messages::new(selected_language);
|
||||
|
||||
// Profile name
|
||||
let profile_name: String = Input::new()
|
||||
.with_prompt("Profile name")
|
||||
.with_prompt(messages.profile_name())
|
||||
.default("personal".to_string())
|
||||
.interact_text()?;
|
||||
|
||||
@@ -110,12 +141,12 @@ impl InitCommand {
|
||||
.unwrap_or_default();
|
||||
|
||||
let user_name: String = Input::new()
|
||||
.with_prompt("Git user name")
|
||||
.with_prompt(messages.git_user_name())
|
||||
.default(default_name)
|
||||
.interact_text()?;
|
||||
|
||||
let user_email: String = Input::new()
|
||||
.with_prompt("Git user email")
|
||||
.with_prompt(messages.git_user_email())
|
||||
.default(default_email)
|
||||
.validate_with(|input: &String| {
|
||||
validate_email(input).map_err(|e| e.to_string())
|
||||
@@ -123,18 +154,18 @@ impl InitCommand {
|
||||
.interact_text()?;
|
||||
|
||||
let description: String = Input::new()
|
||||
.with_prompt("Profile description (optional)")
|
||||
.with_prompt(messages.profile_description())
|
||||
.allow_empty(true)
|
||||
.interact_text()?;
|
||||
|
||||
let is_work = Confirm::new()
|
||||
.with_prompt("Is this a work profile?")
|
||||
.with_prompt(messages.is_work_profile())
|
||||
.default(false)
|
||||
.interact()?;
|
||||
|
||||
let organization = if is_work {
|
||||
Some(Input::new()
|
||||
.with_prompt("Organization/Company name")
|
||||
.with_prompt(messages.organization_name())
|
||||
.interact_text()?)
|
||||
} else {
|
||||
None
|
||||
@@ -142,24 +173,24 @@ impl InitCommand {
|
||||
|
||||
// SSH configuration
|
||||
let setup_ssh = Confirm::new()
|
||||
.with_prompt("Configure SSH key?")
|
||||
.with_prompt(messages.configure_ssh())
|
||||
.default(false)
|
||||
.interact()?;
|
||||
|
||||
let ssh_config = if setup_ssh {
|
||||
Some(self.setup_ssh_interactive().await?)
|
||||
Some(self.setup_ssh_interactive(&messages).await?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// GPG configuration
|
||||
let setup_gpg = Confirm::new()
|
||||
.with_prompt("Configure GPG signing?")
|
||||
.with_prompt(messages.configure_gpg())
|
||||
.default(false)
|
||||
.interact()?;
|
||||
|
||||
let gpg_config = if setup_gpg {
|
||||
Some(self.setup_gpg_interactive().await?)
|
||||
Some(self.setup_gpg_interactive(&messages).await?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -184,7 +215,7 @@ impl InitCommand {
|
||||
manager.set_default_profile(Some(profile_name))?;
|
||||
|
||||
// LLM provider selection
|
||||
println!("\n{}", "Select your preferred LLM provider:".bold());
|
||||
println!("\n{}", messages.select_llm_provider().bold());
|
||||
let providers = vec![
|
||||
"Ollama (local)",
|
||||
"OpenAI",
|
||||
@@ -213,27 +244,27 @@ impl InitCommand {
|
||||
// Configure API key if needed
|
||||
if provider == "openai" {
|
||||
let api_key: String = Input::new()
|
||||
.with_prompt("OpenAI API key")
|
||||
.with_prompt(messages.openai_api_key())
|
||||
.interact_text()?;
|
||||
manager.set_openai_api_key(api_key);
|
||||
} else if provider == "anthropic" {
|
||||
let api_key: String = Input::new()
|
||||
.with_prompt("Anthropic API key")
|
||||
.with_prompt(messages.anthropic_api_key())
|
||||
.interact_text()?;
|
||||
manager.set_anthropic_api_key(api_key);
|
||||
} else if provider == "kimi" {
|
||||
let api_key: String = Input::new()
|
||||
.with_prompt("Kimi API key")
|
||||
.with_prompt(messages.kimi_api_key())
|
||||
.interact_text()?;
|
||||
manager.set_kimi_api_key(api_key);
|
||||
} else if provider == "deepseek" {
|
||||
let api_key: String = Input::new()
|
||||
.with_prompt("DeepSeek API key")
|
||||
.with_prompt(messages.deepseek_api_key())
|
||||
.interact_text()?;
|
||||
manager.set_deepseek_api_key(api_key);
|
||||
} else if provider == "openrouter" {
|
||||
let api_key: String = Input::new()
|
||||
.with_prompt("OpenRouter API key")
|
||||
.with_prompt(messages.openrouter_api_key())
|
||||
.interact_text()?;
|
||||
manager.set_openrouter_api_key(api_key);
|
||||
}
|
||||
@@ -241,7 +272,7 @@ impl InitCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn setup_ssh_interactive(&self) -> Result<SshConfig> {
|
||||
async fn setup_ssh_interactive(&self, messages: &Messages) -> Result<SshConfig> {
|
||||
use std::path::PathBuf;
|
||||
|
||||
let ssh_dir = dirs::home_dir()
|
||||
@@ -249,17 +280,17 @@ impl InitCommand {
|
||||
.unwrap_or_else(|| PathBuf::from("~/.ssh"));
|
||||
|
||||
let key_path: String = Input::new()
|
||||
.with_prompt("SSH private key path")
|
||||
.with_prompt(messages.ssh_private_key_path())
|
||||
.default(ssh_dir.join("id_rsa").display().to_string())
|
||||
.interact_text()?;
|
||||
|
||||
let has_passphrase = Confirm::new()
|
||||
.with_prompt("Does this key have a passphrase?")
|
||||
.with_prompt(messages.has_passphrase())
|
||||
.default(false)
|
||||
.interact()?;
|
||||
|
||||
let passphrase = if has_passphrase {
|
||||
Some(crate::utils::password_input("SSH key passphrase")?)
|
||||
Some(crate::utils::password_input(messages.ssh_key_passphrase())?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -274,13 +305,13 @@ impl InitCommand {
|
||||
})
|
||||
}
|
||||
|
||||
async fn setup_gpg_interactive(&self) -> Result<GpgConfig> {
|
||||
async fn setup_gpg_interactive(&self, messages: &Messages) -> Result<GpgConfig> {
|
||||
let key_id: String = Input::new()
|
||||
.with_prompt("GPG key ID")
|
||||
.with_prompt(messages.gpg_key_id())
|
||||
.interact_text()?;
|
||||
|
||||
let use_agent = Confirm::new()
|
||||
.with_prompt("Use GPG agent?")
|
||||
.with_prompt(messages.use_gpg_agent())
|
||||
.default(true)
|
||||
.interact()?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user