Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
b4ccdf2
feat: full English UI translation
K1skakas Mar 21, 2026
6f176e3
feat(i18n): add English base locale JSON
K1skakas Mar 22, 2026
7fa6ed5
feat(i18n): add LLM-powered locale generator service
K1skakas Mar 22, 2026
71db103
fix(i18n): validate language code to prevent prompt injection
K1skakas Mar 22, 2026
c33fee4
feat(i18n): add GET /api/locale/<lang> endpoint
K1skakas Mar 22, 2026
9f08633
feat(i18n): add language parameter to LLMClient.chat() and chat_json()
K1skakas Mar 22, 2026
48a6cdd
feat(i18n): add locale middleware, capture language before thread spawn
K1skakas Mar 22, 2026
e9aee39
feat(i18n): inject user language into all LLM service calls
K1skakas Mar 22, 2026
38ad71a
feat(i18n): install vue-i18n, auto-detect language, send Accept-Langu…
K1skakas Mar 22, 2026
287a8f6
feat(i18n): replace hardcoded strings in Home.vue with $t() keys
K1skakas Mar 22, 2026
895b554
feat(i18n): replace hardcoded strings in view components with $t() keys
K1skakas Mar 22, 2026
1bd5ca8
fix(i18n): translate Step counter and Chinese log messages in view co…
K1skakas Mar 22, 2026
29c7e1e
feat(i18n): replace hardcoded strings in all component files with $t(…
K1skakas Mar 22, 2026
b46f377
fix(i18n): translate remaining hardcoded strings in HistoryDatabase a…
K1skakas Mar 22, 2026
5d05c23
fix: use chat() directly in locale generator, fix JSON injection from…
K1skakas Mar 22, 2026
3c9a769
feat: add cached Hungarian (hu) locale translation
K1skakas Mar 22, 2026
4ebcf04
docs: add infinite i18n implementation plan
K1skakas Mar 22, 2026
60c7fd0
chore: exclude generated locale cache files from git
K1skakas Mar 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# i18n generated locale cache (auto-generated, not en.json base)
backend/app/i18n/[!e]*.json
backend/app/i18n/e[!n]*.json

# OS
.DS_Store
Thumbs.db
Expand Down
12 changes: 10 additions & 2 deletions backend/app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# 需要在所有其他导入之前设置
warnings.filterwarnings("ignore", message=".*resource_tracker.*")

from flask import Flask, request
from flask import Flask, request, g
from flask_cors import CORS

from .config import Config
Expand Down Expand Up @@ -48,6 +48,13 @@ def create_app(config_class=Config):
if should_log_startup:
logger.info("已注册模拟进程清理函数")

# Locale middleware — normalize Accept-Language header to a 2-letter code
@app.before_request
def set_locale():
# Normalize 'hu-HU,hu;q=0.9,en;q=0.8' -> 'hu'
accept_lang = request.headers.get("Accept-Language", "en")
g.locale = accept_lang.split(",")[0].split("-")[0].lower()

# 请求日志中间件
@app.before_request
def log_request():
Expand All @@ -63,10 +70,11 @@ def log_response(response):
return response

# 注册蓝图
from .api import graph_bp, simulation_bp, report_bp
from .api import graph_bp, simulation_bp, report_bp, locale_bp
app.register_blueprint(graph_bp, url_prefix='/api/graph')
app.register_blueprint(simulation_bp, url_prefix='/api/simulation')
app.register_blueprint(report_bp, url_prefix='/api/report')
app.register_blueprint(locale_bp, url_prefix='/api/locale')

# 健康检查
@app.route('/health')
Expand Down
2 changes: 2 additions & 0 deletions backend/app/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
graph_bp = Blueprint('graph', __name__)
simulation_bp = Blueprint('simulation', __name__)
report_bp = Blueprint('report', __name__)
locale_bp = Blueprint('locale', __name__)

from . import graph # noqa: E402, F401
from . import simulation # noqa: E402, F401
from . import report # noqa: E402, F401
from . import locale # noqa: E402, F401

9 changes: 7 additions & 2 deletions backend/app/api/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import os
import traceback
import threading
from flask import request, jsonify
from flask import request, jsonify, g

from . import graph_bp
from ..config import Config
Expand Down Expand Up @@ -213,11 +213,13 @@ def generate_ontology():

# 生成本体
logger.info("调用 LLM 生成本体定义...")
locale = getattr(g, 'locale', 'en')
generator = OntologyGenerator()
ontology = generator.generate(
document_texts=document_texts,
simulation_requirement=simulation_requirement,
additional_context=additional_context if additional_context else None
additional_context=additional_context if additional_context else None,
language=locale
)

# 保存本体到项目
Expand Down Expand Up @@ -370,6 +372,9 @@ def build_graph():
project.graph_build_task_id = task_id
ProjectManager.save_project(project)

# Capture locale before spawning thread — g is not accessible inside threads
locale = getattr(g, 'locale', 'en')

# 启动后台任务
def build_task():
build_logger = get_logger('mirofish.build')
Expand Down
24 changes: 24 additions & 0 deletions backend/app/api/locale.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
Locale API endpoint.
GET /api/locale/<lang> — returns locale JSON for given language tag.
"""

from flask import jsonify

from . import locale_bp
from ..services.locale_generator import get_locale
from ..utils.logger import get_logger

logger = get_logger(__name__)


@locale_bp.route("/<lang>", methods=["GET"])
def get_locale_route(lang: str):
try:
data = get_locale(lang)
return jsonify({"success": True, "data": data})
except ValueError as e:
return jsonify({"success": False, "error": str(e)}), 400
except Exception as e:
logger.error(f"Failed to get locale '{lang}': {e}")
return jsonify({"success": False, "error": str(e)}), 500
19 changes: 12 additions & 7 deletions backend/app/api/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import os
import traceback
import threading
from flask import request, jsonify, send_file
from flask import request, jsonify, send_file, g

from . import report_bp
from ..config import Config
Expand Down Expand Up @@ -120,6 +120,9 @@ def generate_report():
}
)

# Capture locale before spawning thread — g is not accessible inside threads
locale = getattr(g, 'locale', 'en')

# 定义后台任务
def run_generate():
try:
Expand All @@ -129,26 +132,27 @@ def run_generate():
progress=0,
message="初始化Report Agent..."
)

# 创建Report Agent
agent = ReportAgent(
graph_id=graph_id,
simulation_id=simulation_id,
simulation_requirement=simulation_requirement
)

# 进度回调
def progress_callback(stage, progress, message):
task_manager.update_task(
task_id,
progress=progress,
message=f"[{stage}] {message}"
)

# 生成报告(传入预先生成的 report_id)
report = agent.generate_report(
progress_callback=progress_callback,
report_id=report_id
report_id=report_id,
language=locale
)

# 保存报告
Expand Down Expand Up @@ -542,8 +546,9 @@ def chat_with_report_agent():
simulation_id=simulation_id,
simulation_requirement=simulation_requirement
)

result = agent.chat(message=message, chat_history=chat_history)

locale = getattr(g, 'locale', 'en')
result = agent.chat(message=message, chat_history=chat_history, language=locale)

return jsonify({
"success": True,
Expand Down
8 changes: 6 additions & 2 deletions backend/app/api/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import os
import traceback
from flask import request, jsonify, send_file
from flask import request, jsonify, send_file, g

from . import simulation_bp
from ..config import Config
Expand Down Expand Up @@ -500,6 +500,9 @@ def prepare_simulation():
state.status = SimulationStatus.PREPARING
manager._save_simulation_state(state)

# Capture locale before spawning thread — g is not accessible inside threads
locale = getattr(g, 'locale', 'en')

# 定义后台任务
def run_prepare():
try:
Expand Down Expand Up @@ -582,7 +585,8 @@ def progress_callback(stage, progress, message, **kwargs):
defined_entity_types=entity_types_list,
use_llm_for_profiles=use_llm_for_profiles,
progress_callback=progress_callback,
parallel_profile_count=parallel_profile_count
parallel_profile_count=parallel_profile_count,
language=locale
)

# 任务完成
Expand Down
Loading