Core: Remove markdown skip/original fallback and enforce fail-fast (#334)

This commit is contained in:
Minseok Song
2026-01-08 19:33:58 +09:00
committed by GitHub
parent 1f379392b5
commit a0c9266cd7
5 changed files with 38 additions and 18 deletions
@@ -207,17 +207,18 @@ class MarkdownTranslator(ABC):
f"Request exceeded {self.TRANSLATION_TIMEOUT_SECONDS} seconds. "
f"Check your network connection and API response time."
)
results.append(
f"Translation for chunk {index + 1} of '{md_file_path.name}' skipped due to timeout."
raise RuntimeError(
f"Markdown translation timed out for chunk {index + 1} of '{md_file_path.name}'"
)
except Exception as e:
logger.error(
f"Translation failed for chunk {index + 1} of file '{md_file_path.name}': {str(e)}. "
f"Check your API configuration and network connection."
)
results.append(
f"Error translating chunk {index + 1} of '{md_file_path.name}': {str(e)}"
f"Check your API configuration and network connection.",
exc_info=True,
)
raise RuntimeError(
f"Markdown translation failed for chunk {index + 1} of '{md_file_path.name}': {e}"
) from e
return results
@abstractmethod
@@ -257,7 +258,15 @@ class MarkdownTranslator(ABC):
user_text = template_text
disclaimer_prompt = system_text + SPLIT_DELIMITER + user_text
disclaimer = await self._run_prompt(disclaimer_prompt, "disclaimer prompt", 1)
try:
disclaimer = await self._run_prompt(
disclaimer_prompt, "disclaimer prompt", 1
)
except Exception as e:
logger.warning(
f"Failed to generate disclaimer for language '{output_lang}': {e}"
)
return ""
return disclaimer
@@ -117,7 +117,7 @@ class AzureMarkdownTranslator(MarkdownTranslator):
return await self._run_prompt_once(prompt, index, total)
except Exception as e:
logger.error(f"Error in prompt {index}/{total} - {prompt}: {e}")
return ""
raise
async def _call_once():
return await self._run_prompt_once(prompt, index, total)
@@ -138,4 +138,4 @@ class AzureMarkdownTranslator(MarkdownTranslator):
)
except Exception as e:
logger.error(f"Error in prompt {index}/{total} - {prompt}: {e}")
return ""
raise
@@ -117,7 +117,7 @@ class OpenAIMarkdownTranslator(MarkdownTranslator):
return await self._run_prompt_once(prompt, index, total)
except Exception as e:
logger.error(f"Error in prompt {index}/{total} - {prompt}: {e}")
return ""
raise
async def _call_once():
return await self._run_prompt_once(prompt, index, total)
@@ -138,4 +138,4 @@ class OpenAIMarkdownTranslator(MarkdownTranslator):
)
except Exception as e:
logger.error(f"Error in prompt {index}/{total} - {prompt}: {e}")
return ""
raise
@@ -172,7 +172,9 @@ class TranslationManager:
logger.error(
f"Translation failed for {file_path}: Empty translation result"
)
return ""
raise RuntimeError(
f"Markdown translation returned empty content for {file_path}"
)
# Validate translation format and line break consistency
if compare_line_breaks(document, translated_content):
@@ -189,7 +191,9 @@ class TranslationManager:
logger.error(
f"Retry translation failed for {file_path}: Empty translation result"
)
return ""
raise RuntimeError(
f"Markdown translation retry returned empty content for {file_path}"
)
relative_path = file_path.relative_to(self.root_dir)
translated_path = self.translations_dir / language_code / relative_path
@@ -204,11 +208,11 @@ class TranslationManager:
return str(translated_path)
except Exception as e:
logger.error(f"Failed to write translation to {translated_path}: {e}")
return ""
raise
except Exception as e:
logger.error(f"Failed to translate {file_path}: {e}")
return ""
raise
async def translate_notebook(self, file_path: Path, language_code: str) -> str:
"""Translate a Jupyter notebook file to the specified language.
@@ -746,7 +750,8 @@ class TranslationManager:
except Exception as e:
logger.error(f"Error during translation: {e}")
all_errors.append(str(e))
# Fail fast: propagate to CLI so the process exits
raise
logger.info(f"Translation completed. Modified {total_modified} files.")
if all_errors:
@@ -237,8 +237,14 @@ async def test_translate_project_async_with_outdated(
return_value=[(test_md, temp_project_dir / "translations" / "ko" / "test.md")]
)
mock_translation_manager.retranslate_outdated_files = AsyncMock()
mock_translation_manager.translate_all_markdown_files = AsyncMock()
mock_translation_manager.translate_all_image_files = AsyncMock()
# Ensure translate_* methods return the expected (modified_count, errors) tuple
mock_translation_manager.translate_all_markdown_files = AsyncMock(
return_value=(0, [])
)
mock_translation_manager.translate_all_notebook_files = AsyncMock(
return_value=(0, [])
)
mock_translation_manager.translate_all_image_files = AsyncMock(return_value=(0, []))
mock_translation_manager.directory_manager = MagicMock()
mock_translation_manager.directory_manager.sync_directory_structure = MagicMock(
return_value=(0, 0, [])