diff --git a/backend/app/api/graph.py b/backend/app/api/graph.py index bcd6c5f..759ff48 100644 --- a/backend/app/api/graph.py +++ b/backend/app/api/graph.py @@ -15,7 +15,7 @@ from ..services.graph_builder import GraphBuilderService from ..services.text_processor import TextProcessor from ..utils.file_parser import FileParser from ..utils.logger import get_logger -from ..utils.locale import t +from ..utils.locale import t, get_locale, set_locale from ..models.task import TaskManager, TaskStatus from ..models.project import ProjectManager, ProjectStatus @@ -371,8 +371,12 @@ def build_graph(): project.graph_build_task_id = task_id ProjectManager.save_project(project) + # Capture locale before spawning background thread + current_locale = get_locale() + # 启动后台任务 def build_task(): + set_locale(current_locale) build_logger = get_logger('mirofish.build') try: build_logger.info(f"[{task_id}] 开始构建图谱...") diff --git a/backend/app/api/report.py b/backend/app/api/report.py index f803f1f..d7f2a4d 100644 --- a/backend/app/api/report.py +++ b/backend/app/api/report.py @@ -15,7 +15,7 @@ from ..services.simulation_manager import SimulationManager from ..models.project import ProjectManager from ..models.task import TaskManager, TaskStatus from ..utils.logger import get_logger -from ..utils.locale import t +from ..utils.locale import t, get_locale, set_locale logger = get_logger('mirofish.api.report') @@ -121,8 +121,12 @@ def generate_report(): } ) + # Capture locale before spawning background thread + current_locale = get_locale() + # 定义后台任务 def run_generate(): + set_locale(current_locale) try: task_manager.update_task( task_id, diff --git a/backend/app/api/simulation.py b/backend/app/api/simulation.py index 2535f13..2c1b6b1 100644 --- a/backend/app/api/simulation.py +++ b/backend/app/api/simulation.py @@ -14,7 +14,7 @@ from ..services.oasis_profile_generator import OasisProfileGenerator from ..services.simulation_manager import SimulationManager, SimulationStatus from ..services.simulation_runner import SimulationRunner, RunnerStatus from ..utils.logger import get_logger -from ..utils.locale import t +from ..utils.locale import t, get_locale, set_locale from ..models.project import ProjectManager logger = get_logger('mirofish.api.simulation') @@ -501,8 +501,12 @@ def prepare_simulation(): state.status = SimulationStatus.PREPARING manager._save_simulation_state(state) + # Capture locale before spawning background thread + current_locale = get_locale() + # 定义后台任务 def run_prepare(): + set_locale(current_locale) try: task_manager.update_task( task_id, diff --git a/backend/app/services/graph_builder.py b/backend/app/services/graph_builder.py index d642451..37c9969 100644 --- a/backend/app/services/graph_builder.py +++ b/backend/app/services/graph_builder.py @@ -17,7 +17,7 @@ from ..config import Config from ..models.task import TaskManager, TaskStatus from ..utils.zep_paging import fetch_all_nodes, fetch_all_edges from .text_processor import TextProcessor -from ..utils.locale import t +from ..utils.locale import t, get_locale, set_locale @dataclass @@ -84,10 +84,13 @@ class GraphBuilderService: } ) + # Capture locale before spawning background thread + current_locale = get_locale() + # 在后台线程中执行构建 thread = threading.Thread( target=self._build_graph_worker, - args=(task_id, text, ontology, graph_name, chunk_size, chunk_overlap, batch_size) + args=(task_id, text, ontology, graph_name, chunk_size, chunk_overlap, batch_size, current_locale) ) thread.daemon = True thread.start() @@ -102,9 +105,11 @@ class GraphBuilderService: graph_name: str, chunk_size: int, chunk_overlap: int, - batch_size: int + batch_size: int, + locale: str = 'zh' ): """图谱构建工作线程""" + set_locale(locale) try: self.task_manager.update_task( task_id, diff --git a/backend/app/services/oasis_profile_generator.py b/backend/app/services/oasis_profile_generator.py index 83f49cb..0c1d6ec 100644 --- a/backend/app/services/oasis_profile_generator.py +++ b/backend/app/services/oasis_profile_generator.py @@ -20,7 +20,7 @@ from zep_cloud.client import Zep from ..config import Config from ..utils.logger import get_logger -from ..utils.locale import get_language_instruction, t +from ..utils.locale import get_language_instruction, get_locale, set_locale, t from .zep_entity_reader import EntityNode, ZepEntityReader logger = get_logger('mirofish.oasis_profile') @@ -916,8 +916,12 @@ class OasisProfileGenerator: except Exception as e: logger.warning(f"实时保存 profiles 失败: {e}") + # Capture locale before spawning thread pool workers + current_locale = get_locale() + def generate_single_profile(idx: int, entity: EntityNode) -> tuple: """生成单个profile的工作函数""" + set_locale(current_locale) entity_type = entity.get_entity_type() or "Entity" try: diff --git a/backend/app/services/simulation_runner.py b/backend/app/services/simulation_runner.py index 8c35380..e86021f 100644 --- a/backend/app/services/simulation_runner.py +++ b/backend/app/services/simulation_runner.py @@ -20,6 +20,7 @@ from queue import Queue from ..config import Config from ..utils.logger import get_logger +from ..utils.locale import get_locale, set_locale from .zep_graph_memory_updater import ZepGraphMemoryManager from .simulation_ipc import SimulationIPCClient, CommandType, IPCResponse @@ -455,10 +456,13 @@ class SimulationRunner: cls._processes[simulation_id] = process cls._save_run_state(state) + # Capture locale before spawning monitor thread + current_locale = get_locale() + # 启动监控线程 monitor_thread = threading.Thread( target=cls._monitor_simulation, - args=(simulation_id,), + args=(simulation_id, current_locale), daemon=True ) monitor_thread.start() @@ -475,8 +479,9 @@ class SimulationRunner: return state @classmethod - def _monitor_simulation(cls, simulation_id: str): + def _monitor_simulation(cls, simulation_id: str, locale: str = 'zh'): """监控模拟进程,解析动作日志""" + set_locale(locale) sim_dir = os.path.join(cls.RUN_STATE_DIR, simulation_id) # 新的日志结构:分平台的动作日志 diff --git a/backend/app/services/zep_graph_memory_updater.py b/backend/app/services/zep_graph_memory_updater.py index a8f3cec..e034fee 100644 --- a/backend/app/services/zep_graph_memory_updater.py +++ b/backend/app/services/zep_graph_memory_updater.py @@ -16,6 +16,7 @@ from zep_cloud.client import Zep from ..config import Config from ..utils.logger import get_logger +from ..utils.locale import get_locale, set_locale logger = get_logger('mirofish.zep_graph_memory_updater') @@ -275,10 +276,14 @@ class ZepGraphMemoryUpdater: """启动后台工作线程""" if self._running: return - + + # Capture locale before spawning background thread + current_locale = get_locale() + self._running = True self._worker_thread = threading.Thread( target=self._worker_loop, + args=(current_locale,), daemon=True, name=f"ZepMemoryUpdater-{self.graph_id[:8]}" ) @@ -356,8 +361,9 @@ class ZepGraphMemoryUpdater: self.add_activity(activity) - def _worker_loop(self): + def _worker_loop(self, locale: str = 'zh'): """后台工作循环 - 按平台批量发送活动到Zep""" + set_locale(locale) while self._running or not self._activity_queue.empty(): try: # 尝试从队列获取活动(超时1秒) diff --git a/backend/app/utils/__init__.py b/backend/app/utils/__init__.py index e022abb..e70161a 100644 --- a/backend/app/utils/__init__.py +++ b/backend/app/utils/__init__.py @@ -4,7 +4,7 @@ from .file_parser import FileParser from .llm_client import LLMClient -from .locale import t, get_locale, get_language_instruction +from .locale import t, get_locale, set_locale, get_language_instruction -__all__ = ['FileParser', 'LLMClient', 't', 'get_locale', 'get_language_instruction'] +__all__ = ['FileParser', 'LLMClient', 't', 'get_locale', 'set_locale', 'get_language_instruction'] diff --git a/backend/app/utils/locale.py b/backend/app/utils/locale.py index 8da76c7..868c4f0 100644 --- a/backend/app/utils/locale.py +++ b/backend/app/utils/locale.py @@ -1,7 +1,10 @@ import json import os +import threading from flask import request, has_request_context +_thread_local = threading.local() + _locales_dir = os.path.join(os.path.dirname(__file__), '..', '..', '..', 'locales') # Load language registry @@ -17,10 +20,15 @@ for filename in os.listdir(_locales_dir): _translations[locale_name] = json.load(f) +def set_locale(locale: str): + """Set locale for current thread. Call at the start of background threads.""" + _thread_local.locale = locale + + def get_locale() -> str: if has_request_context(): return request.headers.get('Accept-Language', 'zh') - return 'zh' + return getattr(_thread_local, 'locale', 'zh') def t(key: str, **kwargs) -> str: