anhuiqiang 1 тиждень тому
батько
коміт
fdef15aeaf
3 змінених файлів з 44 додано та 39 видалено
  1. 3 0
      .gitignore
  2. 38 37
      libreoffice-server/main.py
  3. 3 2
      server/src/i18n/i18n.service.ts

+ 3 - 0
.gitignore

@@ -54,3 +54,6 @@ server/check_models.js
 server/aurak.sqlite
 server/models_list.json
 server/models_status.json
+libreoffice-server/__pycache__/main.cpython-312.pyc
+nul
+.sisyphus/

+ 38 - 37
libreoffice-server/main.py

@@ -1,14 +1,15 @@
-from fastapi import FastAPI, File, UploadFile, HTTPException
-from fastapi.responses import RedirectResponse, FileResponse
-from pydantic import BaseModel
-from typing import Optional
-import subprocess
+import io
 import os
+import subprocess
 import time
-from PIL import Image  # Pillowライブラリを追加
-import io
+from typing import Optional
+
+from fastapi import FastAPI, File, HTTPException, UploadFile
+from fastapi.responses import FileResponse, RedirectResponse
+from PIL import Image  # Pillow library for image processing
+from pydantic import BaseModel
 
-# レスポンスモデル
+# Response models
 class ConvertResponse(BaseModel):
     pdf_path: str
     converted: bool
@@ -22,10 +23,10 @@ class HealthResponse(BaseModel):
     version: str
     uptime: float
 
-# FastAPI アプリケーション
+# FastAPI Application
 app = FastAPI(
-    title="LibreOffice ドキュメント変換サービス",
-    description="Word/PPT/Excel/PDF を PDF に変換し、混合内容のドキュメント処理をサポートします",
+    title="LibreOffice Document Conversion Service",
+    description="Convert Word/PPT/Excel/PDF to PDF and support mixed content document processing",
     version="1.0.0",
     docs_url="/docs",
     redoc_url="/redoc"
@@ -35,12 +36,12 @@ start_time = time.time()
 
 @app.get("/", include_in_schema=False)
 async def root():
-    """ドキュメントページへリダイレクト"""
+    """Redirect to documentation page"""
     return RedirectResponse(url="/docs")
 
 @app.get("/health", response_model=HealthResponse)
 async def health():
-    """ヘルスチェックインターフェース"""
+    """Health check interface"""
     return HealthResponse(
         status="healthy",
         service="libreoffice-converter",
@@ -51,11 +52,11 @@ async def health():
 @app.post("/convert")
 async def convert(file: UploadFile = File(...)):
     """
-    ドキュメント変換インターフェース
-    戻り値: PDF ファイルストリーム
+    Document conversion interface
+    Returns: PDF file stream
     """
     try:
-        # ファイル形式の検証
+        # File format validation
         allowed_extensions = [
             '.pdf', '.doc', '.docx', '.ppt', '.pptx', '.xls', '.xlsx',
             '.md', '.txt', '.rtf', '.odt', '.ods', '.odp',
@@ -66,25 +67,25 @@ async def convert(file: UploadFile = File(...)):
         if file_ext not in allowed_extensions:
             raise HTTPException(
                 status_code=400,
-                detail=f"サポートされていないファイル形式です: {file_ext}。サポート対象: {', '.join(allowed_extensions)}"
+                detail=f"Unsupported file format: {file_ext}. Supported formats: {', '.join(allowed_extensions)}"
             )
 
-        # uploads ディレクトリの存在を確認
+        # Check uploads directory existence
         upload_dir = "/app/uploads" if os.path.exists("/app/uploads") else "./uploads"
         os.makedirs(upload_dir, exist_ok=True)
 
-        # アップロードファイルの保存
+        # Save uploaded file
         filepath = os.path.join(upload_dir, file.filename)
         with open(filepath, "wb") as buffer:
             content = await file.read()
             buffer.write(content)
 
-        # PDF の場合はそのまま返却
+        # For PDF files, return directly without conversion
         if file_ext == '.pdf':
             return FileResponse(filepath, filename=file.filename, media_type='application/pdf')
 
         if file_ext == '.md':
-            # Node.js スクリプトを使用して Markdown を PDF にレンダリング
+            # Use Node.js script to render Markdown to PDF
             expected_pdf = filepath.rsplit('.', 1)[0] + '.pdf'
             cmd = [
                 'node',
@@ -93,14 +94,14 @@ async def convert(file: UploadFile = File(...)):
                 expected_pdf
             ]
         elif file_ext in ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff', '.webp']:
-            # 画像ファイルの場合は Pillow を使用して PDF に変換
+            # For image files, use Pillow to convert to PDF
             expected_pdf = filepath.rsplit('.', 1)[0] + '.pdf'
 
-            # 画像を開いてPDFとして保存
+            # Open image and save as PDF
             with Image.open(filepath) as img:
-                # RGBAモードの場合はRGBに変換(透明度がある画像対応)
+                # Convert RGBA mode to RGB (support for transparent images)
                 if img.mode in ('RGBA', 'LA', 'P'):
-                    # 白い背景に変換
+                    # Convert to white background
                     background = Image.new('RGB', img.size, (255, 255, 255))
                     if img.mode == 'P':
                         img = img.convert('RGBA')
@@ -109,21 +110,21 @@ async def convert(file: UploadFile = File(...)):
                 elif img.mode != 'RGB':
                     img = img.convert('RGB')
 
-                # PDFとして保存
+                # Save as PDF
                 img.save(expected_pdf, 'PDF', resolution=100.0, save_all=False)
 
-            # PDF生成が完了したことを確認
+            # Verify PDF generation completed
             if not os.path.exists(expected_pdf):
                 raise HTTPException(
                     status_code=500,
-                    detail="画像からPDFへの変換は成功しましたが、出力ファイルが見つかりません"
+                    detail="Image to PDF conversion succeeded but output file not found"
                 )
             
-            # 画像変換完了、PDFファイルを返却
+            # Image conversion completed, return PDF file
             filename_base = os.path.splitext(file.filename)[0]
             return FileResponse(expected_pdf, filename=f"{filename_base}.pdf", media_type='application/pdf')
         else:
-            # LibreOffice による変換
+            # Conversion using LibreOffice
             cmd = [
                 'soffice',
                 '--headless',
@@ -136,7 +137,7 @@ async def convert(file: UploadFile = File(...)):
             cmd,
             capture_output=True,
             text=True,
-            timeout=600,  # 複雑なMarkdown変換をサポートするために10分に延長
+            timeout=600,  # Extended to 10 minutes to support complex Markdown conversion
         )
 
         # Combine stdout and stderr for error reporting since capture_output uses PIPE
@@ -144,7 +145,7 @@ async def convert(file: UploadFile = File(...)):
         if result.stderr:
             combined_output += "\n" + result.stderr
 
-        # Node.jsスクリプトの実際の出力を表示して、デバッグ
+        # Display Node.js script output for debugging
         print(f"Node.js script output: {combined_output}")
 
         if result.returncode != 0:
@@ -158,15 +159,15 @@ async def convert(file: UploadFile = File(...)):
             print(f"Subprocess output: {combined_output}")
             raise HTTPException(
                 status_code=500,
-                detail=f"変換に失敗しました: {combined_output}"
+                detail=f"Conversion failed: {combined_output}"
             )
 
-        # 出力ファイルの確認
+        # Verify output file
         expected_pdf = filepath.rsplit('.', 1)[0] + '.pdf'
         if not os.path.exists(expected_pdf):
             raise HTTPException(
                 status_code=500,
-                detail="変換は成功しましたが、出力ファイルが見つかりません"
+                detail="Conversion succeeded but output file not found"
             )
 
         filename_base = os.path.splitext(file.filename)[0]
@@ -175,13 +176,13 @@ async def convert(file: UploadFile = File(...)):
     except HTTPException:
         raise
     except subprocess.TimeoutExpired:
-        raise HTTPException(status_code=504, detail="変換タイムアウト (300秒)")
+        raise HTTPException(status_code=504, detail="Conversion timeout (300 seconds)")
     except Exception as e:
         raise HTTPException(status_code=500, detail=str(e))
 
 @app.get("/version")
 async def version():
-    """バージョン情報"""
+    """Version information"""
     return {
         "service": "libreoffice-converter",
         "version": "1.0.0",

+ 3 - 2
server/src/i18n/i18n.service.ts

@@ -1,10 +1,11 @@
 import { Injectable } from '@nestjs/common';
 import { errorMessages, logMessages, statusMessages } from './messages';
 import { i18nStore } from './i18n.store';
+import { DEFAULT_LANGUAGE } from '../common/constants'; // 使用常量定义的默认语言
 
 @Injectable()
 export class I18nService {
-  private readonly defaultLanguage = 'ja'; // プロジェクト要件に従い、日本語をデフォルトとして使用
+  private readonly defaultLanguage = DEFAULT_LANGUAGE; // 使用常量定义的默认语言
 
   private getLanguage(lang?: string): string {
     if (lang) return lang;
@@ -62,7 +63,7 @@ export class I18nService {
   // システムプロンプトを取得
   getPrompt(lang: string = this.defaultLanguage, type: 'withContext' | 'withoutContext' = 'withContext', hasKnowledgeGroup: boolean = false): string {
     const language = this.getLanguage(lang);
-    const noMatchMsg = statusMessages[language]?.noMatchInKnowledgeGroup || statusMessages['ja'].noMatchInKnowledgeGroup;
+    const noMatchMsg = statusMessages[language]?.noMatchInKnowledgeGroup || statusMessages[this.defaultLanguage].noMatchInKnowledgeGroup;
 
     if (language === 'zh') {
       return type === 'withContext' ? `