mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 15:15:44 -03:00
feat(i18n): Implement server-side internationalization support
- Added ServerI18nManager to handle translations and locale settings on the server. - Integrated server-side translations into templates, reducing language flashing on initial load. - Created API endpoints for setting and getting user language preferences. - Enhanced client-side i18n handling to work seamlessly with server-rendered content. - Updated various templates to utilize the new translation system. - Added mixed i18n handler to coordinate server and client translations, improving user experience. - Expanded translation files to include initialization messages for various components.
This commit is contained in:
@@ -11,6 +11,7 @@ import jinja2
|
||||
from ..utils.routes_common import ModelRouteUtils
|
||||
from ..services.websocket_manager import ws_manager
|
||||
from ..services.settings_manager import settings
|
||||
from ..services.server_i18n import server_i18n
|
||||
from ..utils.utils import calculate_relative_path_for_model
|
||||
from ..utils.constants import AUTO_ORGANIZE_BATCH_SIZE
|
||||
from ..config import config
|
||||
@@ -116,13 +117,31 @@ class BaseModelRoutes(ABC):
|
||||
# 获取用户语言设置
|
||||
user_language = settings.get('language', 'en')
|
||||
|
||||
# 设置服务端i18n语言
|
||||
server_i18n.set_locale(user_language)
|
||||
|
||||
# 为模板环境添加i18n过滤器
|
||||
if not hasattr(self.template_env, '_i18n_filter_added'):
|
||||
self.template_env.filters['t'] = server_i18n.create_template_filter()
|
||||
self.template_env._i18n_filter_added = True
|
||||
|
||||
# 准备模板上下文
|
||||
template_context = {
|
||||
'is_initializing': is_initializing,
|
||||
'settings': settings,
|
||||
'request': request,
|
||||
'user_language': user_language, # 传递语言设置到模板
|
||||
'folders': []
|
||||
'folders': [],
|
||||
# 添加服务端翻译函数
|
||||
't': server_i18n.get_translation,
|
||||
'server_i18n': server_i18n,
|
||||
# 添加一些常用的翻译到上下文,避免在模板中频繁调用
|
||||
'common_translations': {
|
||||
'loading': server_i18n.get_translation('common.status.loading'),
|
||||
'error': server_i18n.get_translation('common.status.error'),
|
||||
'refresh': server_i18n.get_translation('common.actions.refresh'),
|
||||
'search': server_i18n.get_translation('common.actions.search'),
|
||||
}
|
||||
}
|
||||
|
||||
if not is_initializing:
|
||||
|
||||
@@ -112,6 +112,10 @@ class MiscRoutes:
|
||||
|
||||
# Add new route for checking if a model exists in the library
|
||||
app.router.add_get('/api/check-model-exists', MiscRoutes.check_model_exists)
|
||||
|
||||
# Language settings endpoints
|
||||
app.router.add_post('/api/set-language', MiscRoutes.set_language)
|
||||
app.router.add_get('/api/get-language', MiscRoutes.get_language)
|
||||
|
||||
@staticmethod
|
||||
async def clear_cache(request):
|
||||
@@ -697,3 +701,69 @@ class MiscRoutes:
|
||||
'success': False,
|
||||
'error': str(e)
|
||||
}, status=500)
|
||||
|
||||
@staticmethod
|
||||
async def set_language(request):
|
||||
"""
|
||||
Set user language preference
|
||||
|
||||
Expects a JSON body with:
|
||||
{
|
||||
"language": "en" | "zh-CN" | "zh-TW" | "ru" | "de" | "ja" | "ko" | "fr" | "es"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
data = await request.json()
|
||||
language = data.get('language')
|
||||
|
||||
if not language:
|
||||
return web.json_response({
|
||||
'success': False,
|
||||
'error': 'Missing language parameter'
|
||||
}, status=400)
|
||||
|
||||
# Validate language code
|
||||
supported_languages = ['en', 'zh-CN', 'zh-TW', 'ru', 'de', 'ja', 'ko', 'fr', 'es']
|
||||
if language not in supported_languages:
|
||||
return web.json_response({
|
||||
'success': False,
|
||||
'error': f'Unsupported language: {language}. Supported languages: {", ".join(supported_languages)}'
|
||||
}, status=400)
|
||||
|
||||
# Save language setting
|
||||
settings.set('language', language)
|
||||
|
||||
return web.json_response({
|
||||
'success': True,
|
||||
'message': f'Language set to {language}',
|
||||
'language': language
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to set language: {e}", exc_info=True)
|
||||
return web.json_response({
|
||||
'success': False,
|
||||
'error': str(e)
|
||||
}, status=500)
|
||||
|
||||
@staticmethod
|
||||
async def get_language(request):
|
||||
"""
|
||||
Get current user language preference
|
||||
|
||||
Returns the current language setting from settings
|
||||
"""
|
||||
try:
|
||||
current_language = settings.get('language', 'en')
|
||||
|
||||
return web.json_response({
|
||||
'success': True,
|
||||
'language': current_language
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get language: {e}", exc_info=True)
|
||||
return web.json_response({
|
||||
'success': False,
|
||||
'error': str(e)
|
||||
}, status=500)
|
||||
|
||||
@@ -17,6 +17,7 @@ from ..recipes import RecipeParserFactory
|
||||
from ..utils.constants import CARD_PREVIEW_WIDTH
|
||||
|
||||
from ..services.settings_manager import settings
|
||||
from ..services.server_i18n import server_i18n
|
||||
from ..config import config
|
||||
|
||||
# Check if running in standalone mode
|
||||
@@ -127,6 +128,17 @@ class RecipeRoutes:
|
||||
# Ensure services are initialized
|
||||
await self.init_services()
|
||||
|
||||
# 获取用户语言设置
|
||||
user_language = settings.get('language', 'en')
|
||||
|
||||
# 设置服务端i18n语言
|
||||
server_i18n.set_locale(user_language)
|
||||
|
||||
# 为模板环境添加i18n过滤器
|
||||
if not hasattr(self.template_env, '_i18n_filter_added'):
|
||||
self.template_env.filters['t'] = server_i18n.create_template_filter()
|
||||
self.template_env._i18n_filter_added = True
|
||||
|
||||
# Skip initialization check and directly try to get cached data
|
||||
try:
|
||||
# Recipe scanner will initialize cache if needed
|
||||
@@ -136,7 +148,18 @@ class RecipeRoutes:
|
||||
recipes=[], # Frontend will load recipes via API
|
||||
is_initializing=False,
|
||||
settings=settings,
|
||||
request=request
|
||||
request=request,
|
||||
user_language=user_language,
|
||||
# 添加服务端翻译函数
|
||||
t=server_i18n.get_translation,
|
||||
server_i18n=server_i18n,
|
||||
# 添加一些常用的翻译到上下文
|
||||
common_translations={
|
||||
'loading': server_i18n.get_translation('common.status.loading'),
|
||||
'error': server_i18n.get_translation('common.status.error'),
|
||||
'refresh': server_i18n.get_translation('common.actions.refresh'),
|
||||
'search': server_i18n.get_translation('common.actions.search'),
|
||||
}
|
||||
)
|
||||
except Exception as cache_error:
|
||||
logger.error(f"Error loading recipe cache data: {cache_error}")
|
||||
@@ -145,7 +168,16 @@ class RecipeRoutes:
|
||||
rendered = template.render(
|
||||
is_initializing=True,
|
||||
settings=settings,
|
||||
request=request
|
||||
request=request,
|
||||
user_language=user_language,
|
||||
# 添加服务端翻译函数
|
||||
t=server_i18n.get_translation,
|
||||
server_i18n=server_i18n,
|
||||
# 添加一些常用的翻译到上下文
|
||||
common_translations={
|
||||
'loading': server_i18n.get_translation('common.status.loading'),
|
||||
'error': server_i18n.get_translation('common.status.error'),
|
||||
}
|
||||
)
|
||||
logger.info("Recipe cache error, returning initialization page")
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from typing import Dict, List, Any
|
||||
|
||||
from ..config import config
|
||||
from ..services.settings_manager import settings
|
||||
from ..services.server_i18n import server_i18n
|
||||
from ..services.service_registry import ServiceRegistry
|
||||
from ..utils.usage_stats import UsageStats
|
||||
|
||||
@@ -58,11 +59,32 @@ class StatsRoutes:
|
||||
|
||||
is_initializing = lora_initializing or checkpoint_initializing or embedding_initializing
|
||||
|
||||
# 获取用户语言设置
|
||||
user_language = settings.get('language', 'en')
|
||||
|
||||
# 设置服务端i18n语言
|
||||
server_i18n.set_locale(user_language)
|
||||
|
||||
# 为模板环境添加i18n过滤器
|
||||
if not hasattr(self.template_env, '_i18n_filter_added'):
|
||||
self.template_env.filters['t'] = server_i18n.create_template_filter()
|
||||
self.template_env._i18n_filter_added = True
|
||||
|
||||
template = self.template_env.get_template('statistics.html')
|
||||
rendered = template.render(
|
||||
is_initializing=is_initializing,
|
||||
settings=settings,
|
||||
request=request
|
||||
request=request,
|
||||
user_language=user_language,
|
||||
# 添加服务端翻译函数
|
||||
t=server_i18n.get_translation,
|
||||
server_i18n=server_i18n,
|
||||
# 添加一些常用的翻译到上下文
|
||||
common_translations={
|
||||
'loading': server_i18n.get_translation('common.status.loading'),
|
||||
'error': server_i18n.get_translation('common.status.error'),
|
||||
'refresh': server_i18n.get_translation('common.actions.refresh'),
|
||||
}
|
||||
)
|
||||
|
||||
return web.Response(
|
||||
|
||||
Reference in New Issue
Block a user