Files
yoyo/internal/config/config.go
Z.To 6807371c5e feat: add content filter and code processing module (v0.3.0)
- Add content filter module (internal/content/)
- Implement basic character filtering (control chars, line breaks, symbols)
- Implement code block and inline code detection
- Implement comment detection for 30+ languages (JS/Python/Go/HTML/etc)
- Add go-enry dependency for intelligent language detection
- Add SkipKeywords config option (default: TODO/FIXME/HACK/XXX/etc)
- Integrate content processing into Translator
- Update config.yaml with skip_keywords
2026-03-29 18:41:25 +08:00

226 lines
5.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package config
import (
"fmt"
"os"
"path/filepath"
"strings"
"gopkg.in/yaml.v3"
)
// Config 全局配置结构
type Config struct {
// 全局设置
DefaultProvider string `yaml:"default_provider"`
DefaultModel string `yaml:"default_model"`
Timeout int `yaml:"timeout"` // 秒
DefaultSourceLang string `yaml:"default_source_lang"` // 默认源语言auto为自动检测
DefaultTargetLang string `yaml:"default_target_lang"` // 默认目标语言
// 厂商配置
Providers map[string]ProviderConfig `yaml:"providers"`
// Prompt配置
Prompts map[string]string `yaml:"prompts"`
// 内容过滤配置
SkipKeywords []string `yaml:"skip_keywords"` // 不翻译的关键词
}
// ProviderConfig 厂商配置
type ProviderConfig struct {
APIHost string `yaml:"api_host"`
APIKey string `yaml:"api_key"`
Model string `yaml:"model"`
Enabled bool `yaml:"enabled"`
}
// ConfigLoader 配置加载器接口
type ConfigLoader interface {
Load(path string) (*Config, error)
Save(config *Config, path string) error
}
// YAMLConfigLoader YAML配置加载器实现
type YAMLConfigLoader struct{}
// Load 加载YAML配置文件
func (l *YAMLConfigLoader) Load(path string) (*Config, error) {
// 读取文件
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("读取配置文件失败: %w", err)
}
// 替换环境变量
content := string(data)
content = os.ExpandEnv(content)
// 解析YAML
config := &Config{}
if err := yaml.Unmarshal([]byte(content), config); err != nil {
return nil, fmt.Errorf("解析配置文件失败: %w", err)
}
// 设置默认值
config.setDefaults()
return config, nil
}
// Save 保存配置到文件
func (l *YAMLConfigLoader) Save(config *Config, path string) error {
// 确保目录存在
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("创建配置目录失败: %w", err)
}
// 序列化为YAML
data, err := yaml.Marshal(config)
if err != nil {
return fmt.Errorf("序列化配置失败: %w", err)
}
// 写入文件
if err := os.WriteFile(path, data, 0644); err != nil {
return fmt.Errorf("写入配置文件失败: %w", err)
}
return nil
}
// setDefaults 设置默认值
func (c *Config) setDefaults() {
if c.DefaultProvider == "" {
c.DefaultProvider = "siliconflow"
}
if c.Timeout <= 0 {
c.Timeout = 30
}
if c.DefaultModel == "" {
c.DefaultModel = "gpt-3.5-turbo"
}
if c.DefaultSourceLang == "" {
c.DefaultSourceLang = "auto" // 自动检测
}
if c.DefaultTargetLang == "" {
c.DefaultTargetLang = "zh-CN" // 默认翻译为简体中文
}
// 为每个厂商设置默认值
for name, provider := range c.Providers {
if provider.Model == "" {
provider.Model = c.DefaultModel
c.Providers[name] = provider
}
// 替换环境变量
provider.APIKey = os.ExpandEnv(provider.APIKey)
c.Providers[name] = provider
}
// 确保Prompts映射存在
if c.Prompts == nil {
c.Prompts = make(map[string]string)
}
// 设置默认关键词
if c.SkipKeywords == nil {
c.SkipKeywords = []string{
"TODO", "FIXME", "HACK", "XXX", "NOTE",
"BUG", "WARN", "IMPORTANT", "TODO:",
"FIXME:", "HACK:", "XXX:", "NOTE:",
"BUG:", "WARN:", "IMPORTANT:",
}
}
}
// GetProviderConfig 获取指定厂商的配置
func (c *Config) GetProviderConfig(name string) (ProviderConfig, error) {
config, exists := c.Providers[name]
if !exists {
return ProviderConfig{}, fmt.Errorf("未找到厂商配置: %s", name)
}
if !config.Enabled {
return ProviderConfig{}, fmt.Errorf("厂商未启用: %s", name)
}
return config, nil
}
// GetPrompt 获取指定名称的Prompt
func (c *Config) GetPrompt(name string) (string, bool) {
prompt, exists := c.Prompts[name]
return prompt, exists
}
// ExpandEnv 扩展环境变量(辅助函数)
func ExpandEnv(s string) string {
return os.ExpandEnv(s)
}
// Validate 验证配置是否有效
func (c *Config) Validate() error {
if c.DefaultProvider == "" {
return fmt.Errorf("默认厂商不能为空")
}
// 检查默认厂商是否在配置中
if _, exists := c.Providers[c.DefaultProvider]; !exists {
return fmt.Errorf("默认厂商 '%s' 未在配置中定义", c.DefaultProvider)
}
// 检查每个厂商配置
for name, provider := range c.Providers {
if provider.APIKey == "" {
return fmt.Errorf("厂商 '%s' 的API密钥不能为空", name)
}
if provider.APIHost == "" {
return fmt.Errorf("厂商 '%s' 的API主机不能为空", name)
}
}
return nil
}
// GetDefaultProvider 获取默认厂商配置
func (c *Config) GetDefaultProvider() (ProviderConfig, error) {
return c.GetProviderConfig(c.DefaultProvider)
}
// IsProviderEnabled 检查厂商是否启用
func (c *Config) IsProviderEnabled(name string) bool {
config, exists := c.Providers[name]
return exists && config.Enabled
}
// GetEnabledProviders 获取所有启用的厂商
func (c *Config) GetEnabledProviders() []string {
var enabled []string
for name, config := range c.Providers {
if config.Enabled {
enabled = append(enabled, name)
}
}
return enabled
}
// String 返回配置的字符串表示(隐藏敏感信息)
func (c *Config) String() string {
var builder strings.Builder
builder.WriteString(fmt.Sprintf("DefaultProvider: %s\n", c.DefaultProvider))
builder.WriteString(fmt.Sprintf("DefaultModel: %s\n", c.DefaultModel))
builder.WriteString(fmt.Sprintf("Timeout: %d seconds\n", c.Timeout))
builder.WriteString(fmt.Sprintf("DefaultSourceLang: %s\n", c.DefaultSourceLang))
builder.WriteString(fmt.Sprintf("DefaultTargetLang: %s\n", c.DefaultTargetLang))
builder.WriteString("Providers:\n")
for name, provider := range c.Providers {
builder.WriteString(fmt.Sprintf(" %s: enabled=%v, model=%s\n", name, provider.Enabled, provider.Model))
}
builder.WriteString("Prompts:\n")
for name := range c.Prompts {
builder.WriteString(fmt.Sprintf(" %s\n", name))
}
return builder.String()
}