Class: LlmTranslate::TranslatorEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/llm_translate/translator_engine.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, logger, ai_client) ⇒ TranslatorEngine

Returns a new instance of TranslatorEngine.



12
13
14
15
16
17
18
# File 'lib/llm_translate/translator_engine.rb', line 12

def initialize(config, logger, ai_client)
  @config = config
  @logger = logger
  @ai_client = ai_client
  @file_finder = FileFinder.new(config, logger)
  @document_splitter = DocumentSplitter.new(config, logger)
end

Instance Attribute Details

#ai_clientObject (readonly)

Returns the value of attribute ai_client.



10
11
12
# File 'lib/llm_translate/translator_engine.rb', line 10

def ai_client
  @ai_client
end

#configObject (readonly)

Returns the value of attribute config.



10
11
12
# File 'lib/llm_translate/translator_engine.rb', line 10

def config
  @config
end

#document_splitterObject (readonly)

Returns the value of attribute document_splitter.



10
11
12
# File 'lib/llm_translate/translator_engine.rb', line 10

def document_splitter
  @document_splitter
end

#file_finderObject (readonly)

Returns the value of attribute file_finder.



10
11
12
# File 'lib/llm_translate/translator_engine.rb', line 10

def file_finder
  @file_finder
end

#loggerObject (readonly)

Returns the value of attribute logger.



10
11
12
# File 'lib/llm_translate/translator_engine.rb', line 10

def logger
  @logger
end

Instance Method Details

#translate_content(content, file_path = nil) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/llm_translate/translator_engine.rb', line 119

def translate_content(content, file_path = nil)
  # 检查是否需要启用文档拆分
  if config.enable_document_splitting? && content.length > config.max_chars_for_splitting
    translate_with_document_splitting(content, file_path)
  elsif config.preserve_formatting?
    translate_with_format_preservation(content)
  else
    ai_client.translate(content)
  end
rescue StandardError => e
  raise TranslationError, "Failed to translate content#{file_path ? " from #{file_path}" : ''}: #{e.message}"
end

#translate_file(input_path) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/llm_translate/translator_engine.rb', line 20

def translate_file(input_path)
  logger.log_translation_start(input_path)

  # Read file content
  content = read_file_content(input_path)

  # Determine output path
  if config.single_file_mode?
    output_path = config.output_file
  else
    output_path = file_finder.output_path_for(input_path).to_s

    # Check if we should skip this file
    if file_finder.should_skip_file?(input_path, output_path)
      logger.info "Skipping file: #{input_path}"
      return
    end
  end

  # Ensure output directory exists
  if config.single_file_mode?
    output_dir = File.dirname(output_path)
    FileUtils.mkdir_p(output_dir) unless Dir.exist?(output_dir)
  else
    file_finder.ensure_output_directory(output_path)
  end

  # Translate content
  translated_content = translate_content(content, input_path)

  # Write translated content
  write_translated_file(output_path, translated_content)

  logger.log_translation_complete(input_path, output_path)

  # Add rate limiting delay if configured
  sleep(config.request_interval) if config.request_interval.positive?
end

#translate_files_concurrently(file_paths) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/llm_translate/translator_engine.rb', line 59

def translate_files_concurrently(file_paths)
  return translate_files_sequentially(file_paths) if config.concurrent_files <= 1

  results = { success: [], error: [] }

  # Use Async to run concurrent translation tasks
  Async do |task|
    # Process files in batches to limit concurrency
    file_paths.each_slice(config.concurrent_files) do |batch|
      # Create async tasks for the current batch
      batch_tasks = batch.map.with_index do |file_path, _batch_index|
        # Calculate overall index
        overall_index = file_paths.index(file_path) + 1

        task.async do
          logger.info "[#{overall_index}/#{file_paths.length}] Processing: #{file_path}"

          # Translate the file
          translate_file(file_path)

          # Collect successful result
          results[:success] << file_path

          logger.info "✓ Successfully processed: #{file_path}"
          { status: :success, file: file_path }
        rescue StandardError => e
          # Collect error result
          results[:error] << { file: file_path, error: e.message }

          logger.error "✗ Failed to process #{file_path}: #{e.message}"
          { status: :error, file: file_path, error: e.message }
        end
      end

      # Wait for all tasks in this batch to complete before starting the next batch
      batch_tasks.each(&:wait)
    end
  end

  results
end

#translate_files_sequentially(file_paths) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/llm_translate/translator_engine.rb', line 101

def translate_files_sequentially(file_paths)
  results = { success: [], error: [] }

  file_paths.each_with_index do |file_path, index|
    logger.info "[#{index + 1}/#{file_paths.length}] Processing: #{file_path}"

    translate_file(file_path)

    results[:success] << file_path
    logger.info "✓ Successfully processed: #{file_path}"
  rescue StandardError => e
    results[:error] << { file: file_path, error: e.message }
    logger.error "✗ Failed to process #{file_path}: #{e.message}"
  end

  results
end