feat: feat: add multilingual output support for commit, tag, and changelog commands
This commit is contained in:
@@ -5,10 +5,11 @@ use colored::Colorize;
|
||||
use dialoguer::{Confirm, Input};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::config::manager::ConfigManager;
|
||||
use crate::config::{Language, manager::ConfigManager};
|
||||
use crate::generator::ContentGenerator;
|
||||
use crate::git::find_repo;
|
||||
use crate::git::{changelog::*, CommitInfo, GitRepo};
|
||||
use crate::i18n::{Messages, translate_changelog_category};
|
||||
|
||||
/// Generate changelog
|
||||
#[derive(Parser)]
|
||||
@@ -67,6 +68,8 @@ impl ChangelogCommand {
|
||||
let repo = find_repo(std::env::current_dir()?.as_path())?;
|
||||
let manager = ConfigManager::new()?;
|
||||
let config = manager.config();
|
||||
let language = manager.get_language().unwrap_or(Language::English);
|
||||
let messages = Messages::new(language);
|
||||
|
||||
// Initialize changelog if requested
|
||||
if self.init {
|
||||
@@ -75,7 +78,7 @@ impl ChangelogCommand {
|
||||
.unwrap_or_else(|| PathBuf::from(&config.changelog.path));
|
||||
|
||||
init_changelog(&path)?;
|
||||
println!("{} Initialized changelog at {:?}", "✓".green(), path);
|
||||
println!("{}", messages.initialized_changelog(&format!("{:?}", path)));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -98,28 +101,28 @@ impl ChangelogCommand {
|
||||
v.clone()
|
||||
} else if !self.yes {
|
||||
Input::new()
|
||||
.with_prompt("Version")
|
||||
.default("Unreleased".to_string())
|
||||
.with_prompt(messages.version())
|
||||
.default(messages.unreleased().to_string())
|
||||
.interact_text()?
|
||||
} else {
|
||||
"Unreleased".to_string()
|
||||
messages.unreleased().to_string()
|
||||
};
|
||||
|
||||
// Get commits
|
||||
println!("{} Fetching commits...", "→".blue());
|
||||
println!("{}", messages.fetching_commits());
|
||||
let commits = generate_from_history(&repo, self.from.as_deref(), Some(&self.to))?;
|
||||
|
||||
if commits.is_empty() {
|
||||
bail!("No commits found in the specified range");
|
||||
bail!("{}", messages.no_commits_found());
|
||||
}
|
||||
|
||||
println!("{} Found {} commits", "✓".green(), commits.len());
|
||||
println!("{}", messages.found_commits(commits.len()));
|
||||
|
||||
// Generate changelog
|
||||
let changelog = if self.generate || (config.changelog.auto_generate && !self.yes) {
|
||||
self.generate_with_ai(&repo, &version, &commits).await?
|
||||
self.generate_with_ai(&repo, &version, &commits, &messages).await?
|
||||
} else {
|
||||
self.generate_with_template(format, &version, &commits)?
|
||||
self.generate_with_template(format, &version, &commits, language)?
|
||||
};
|
||||
|
||||
// Output or write
|
||||
@@ -133,7 +136,7 @@ impl ChangelogCommand {
|
||||
// Preview
|
||||
if !self.yes {
|
||||
println!("\n{}", "─".repeat(60));
|
||||
println!("{}", "Changelog preview:".bold());
|
||||
println!("{}", messages.changelog_preview().bold());
|
||||
println!("{}", "─".repeat(60));
|
||||
// Show first 20 lines
|
||||
let preview: String = changelog.lines().take(20).collect::<Vec<_>>().join("\n");
|
||||
@@ -144,12 +147,12 @@ impl ChangelogCommand {
|
||||
println!("{}", "─".repeat(60));
|
||||
|
||||
let confirm = Confirm::new()
|
||||
.with_prompt(&format!("Write to {:?}?", output_path))
|
||||
.with_prompt(&messages.write_to_file(&format!("{:?}", output_path)))
|
||||
.default(true)
|
||||
.interact()?;
|
||||
|
||||
if !confirm {
|
||||
println!("{}", "Cancelled.".yellow());
|
||||
println!("{}", messages.cancelled().yellow());
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@@ -163,7 +166,7 @@ impl ChangelogCommand {
|
||||
std::fs::write(&output_path, changelog)?;
|
||||
}
|
||||
|
||||
println!("{} Changelog written to {:?}", "✓".green(), output_path);
|
||||
println!("{} {:?}", messages.changelog_written(), output_path);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -173,11 +176,12 @@ impl ChangelogCommand {
|
||||
repo: &GitRepo,
|
||||
version: &str,
|
||||
commits: &[CommitInfo],
|
||||
messages: &Messages,
|
||||
) -> Result<String> {
|
||||
let manager = ConfigManager::new()?;
|
||||
let config = manager.config();
|
||||
|
||||
println!("{} AI is generating changelog...", "🤖");
|
||||
println!("{}", messages.ai_generating_changelog());
|
||||
|
||||
let generator = ContentGenerator::new(&config.llm).await?;
|
||||
generator.generate_changelog_entry(version, commits).await
|
||||
@@ -188,12 +192,43 @@ impl ChangelogCommand {
|
||||
format: ChangelogFormat,
|
||||
version: &str,
|
||||
commits: &[CommitInfo],
|
||||
language: Language,
|
||||
) -> Result<String> {
|
||||
let manager = ConfigManager::new()?;
|
||||
|
||||
let generator = ChangelogGenerator::new()
|
||||
.format(format)
|
||||
.include_hashes(self.include_hashes)
|
||||
.include_authors(self.include_authors);
|
||||
|
||||
generator.generate(version, Utc::now(), commits)
|
||||
let changelog = generator.generate(version, Utc::now(), commits)?;
|
||||
|
||||
// Translate changelog categories if configured
|
||||
if !manager.keep_changelog_types_english() {
|
||||
Ok(self.translate_changelog_categories(&changelog, language))
|
||||
} else {
|
||||
Ok(changelog)
|
||||
}
|
||||
}
|
||||
|
||||
fn translate_changelog_categories(&self, changelog: &str, language: Language) -> String {
|
||||
let translated = changelog
|
||||
.lines()
|
||||
.map(|line| {
|
||||
if line.starts_with("## ") || line.starts_with("### ") {
|
||||
let category = line.trim_start_matches("## ").trim_start_matches("### ");
|
||||
let translated_category = translate_changelog_category(category, language, false);
|
||||
if line.starts_with("## ") {
|
||||
format!("## {}", translated_category)
|
||||
} else {
|
||||
format!("### {}", translated_category)
|
||||
}
|
||||
} else {
|
||||
line.to_string()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
translated
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user