From 005546b58867fb5872c9eafa93295d139f3b6888 Mon Sep 17 00:00:00 2001 From: yingying Date: Fri, 15 Nov 2024 16:24:26 +0800 Subject: [PATCH] feat: add the i18n middleware for the server --- server/agent/tools/bot_builder.py | 57 +++++++++++++++++++------------ server/bot/builder.py | 18 ++-------- server/bot/router.py | 19 +++++++++-- server/i18n/en.json | 6 ++++ server/i18n/ja.json | 6 ++++ server/i18n/ko.json | 6 ++++ server/i18n/translations.py | 49 ++++++++++++++++++++++++++ server/i18n/zh-CN.json | 6 ++++ server/i18n/zh-TW.json | 6 ++++ server/main.py | 11 +++--- 10 files changed, 142 insertions(+), 42 deletions(-) create mode 100644 server/i18n/en.json create mode 100644 server/i18n/ja.json create mode 100644 server/i18n/ko.json create mode 100644 server/i18n/translations.py create mode 100644 server/i18n/zh-CN.json create mode 100644 server/i18n/zh-TW.json diff --git a/server/agent/tools/bot_builder.py b/server/agent/tools/bot_builder.py index 9f39079f..e0a60cdf 100644 --- a/server/agent/tools/bot_builder.py +++ b/server/agent/tools/bot_builder.py @@ -8,6 +8,7 @@ g = Github() + @tool async def create_bot( repo_name: str, @@ -25,20 +26,23 @@ async def create_bot( """ res = await bot_builder(uid, repo_name, starters, hello_message) if not res: - return JSONResponse(content={"success": False, "errorMessage": "仓库不存在,生成失败"}) + return JSONResponse( + content={"success": False, "errorMessage": "Failed to create bot."} + ) return res.json() + @tool def edit_bot( - id: str, - uid: str, - avatar: Optional[str] = None, - name: Optional[str] = None, - description : Optional[str] = None, - prompt: Optional[str] = None, - starters: Optional[list[str]] = None, - hello_message: Optional[str] = None - ): + id: str, + uid: str, + avatar: Optional[str] = None, + name: Optional[str] = None, + description: Optional[str] = None, + prompt: Optional[str] = None, + starters: Optional[list[str]] = None, + hello_message: Optional[str] = None, +): """ Modify Bot Configuration based on the given parameters. @@ -54,30 +58,41 @@ def edit_bot( try: # Step1: Get the bot object supabase = get_client() - bot = supabase.table("bots").select("*").eq("id", id).eq("uid", uid).execute().data[0] + bot = ( + supabase.table("bots") + .select("*") + .eq("id", id) + .eq("uid", uid) + .execute() + .data[0] + ) if not bot: raise ValueError(f"Bot with ID {id} not found.") # Step2: Update the bot data bot_data = { - "name": name if name else bot["name"], + "name": name if name else bot["name"], "description": description if description else bot["description"], "avatar": avatar if avatar else bot["avatar"], "prompt": prompt if prompt else bot["prompt"], - "uid": bot["uid"], + "uid": bot["uid"], "label": "Assistant", - "starters": starters if isinstance(starters, list) and starters else bot["starters"], + "starters": ( + starters if isinstance(starters, list) and starters else bot["starters"] + ), "public": bot["public"], - "hello_message": hello_message if hello_message else bot["hello_message"] + "hello_message": hello_message if hello_message else bot["hello_message"], } - - + # Step3: Save the changes to the database - response = supabase.table("bots").update(bot_data).eq("id", id).eq("uid", uid).execute() + response = ( + supabase.table("bots") + .update(bot_data) + .eq("id", id) + .eq("uid", uid) + .execute() + ) return response.json() except Exception as e: print(f"An error occurred: {e}") return e - - - diff --git a/server/bot/builder.py b/server/bot/builder.py index 57a6352b..d853f579 100644 --- a/server/bot/builder.py +++ b/server/bot/builder.py @@ -31,24 +31,12 @@ async def bot_info_generator( "prompt": prompt, "uid": uid, "label": "Assistant", - "starters": ( - starters - if starters - else [ - f"介绍一下 {repo.name} 这个项目", - f"查看 {repo_name} 的贡献指南", - "我该怎样快速上手", - ] - ), + "starters": starters, "public": False, - "hello_message": ( - hello_message - if hello_message - else "我是你专属的答疑机器人,你可以问我关于当前项目的任何问题~" - ), + "hello_message": hello_message, "repo_name": repo_name, "llm": "openai", - "token_id": "" + "token_id": "", } return bot_data diff --git a/server/bot/router.py b/server/bot/router.py index e9ab81c6..2ebcc021 100644 --- a/server/bot/router.py +++ b/server/bot/router.py @@ -1,5 +1,5 @@ from datetime import datetime -from fastapi import APIRouter, Depends, status, Query, Path +from fastapi import APIRouter, Request, Depends, status, Query, Path from fastapi.responses import JSONResponse from github import Github, Auth from auth.get_user_info import get_user, get_user_id @@ -134,11 +134,26 @@ async def create_bot( @router.post("/config/generator", status_code=200) async def bot_generator( + request: Request, bot_data: BotCreateRequest, user_id: Annotated[str | None, Depends(get_user_id)] = None, + lang: str = Query("en", description="Language of the bot"), ): + default_starters = [ + request.state.i18n.get_text("starter0", lang), + request.state.i18n.get_text("starter1", lang), + request.state.i18n.get_text("starter2", lang), + ] + default_hello_message = request.state.i18n.get_text("hello_message", lang) + print(bot_data.starters) + starters = bot_data.starters if bot_data.starters else default_starters + hello_message = ( + bot_data.hello_message if bot_data.hello_message else default_hello_message + ) try: - res = await bot_info_generator(user_id, **bot_data.model_dump()) + res = await bot_info_generator( + user_id, bot_data.repo_name, starters, hello_message + ) if not res: return JSONResponse( content={ diff --git a/server/i18n/en.json b/server/i18n/en.json new file mode 100644 index 00000000..e4c49a7b --- /dev/null +++ b/server/i18n/en.json @@ -0,0 +1,6 @@ +{ + "starter0": "Introduce the project", + "starter1": "Review the contribution guidelines", + "starter2": "How can I quickly get started?", + "hello_message": "I'm your dedicated Q&A bot. Feel free to ask me anything about the current project~" +} diff --git a/server/i18n/ja.json b/server/i18n/ja.json new file mode 100644 index 00000000..d361f853 --- /dev/null +++ b/server/i18n/ja.json @@ -0,0 +1,6 @@ +{ + "starter0": "このプロジェクトを紹介します", + "starter1": "コントリビューションガイドラインを確認する", + "starter2": "どうやって素早く始められますか?", + "hello_message": "私はあなた専用のQ&Aボットです。現在のプロジェクトについて何でも聞いてくださいね~" +} diff --git a/server/i18n/ko.json b/server/i18n/ko.json new file mode 100644 index 00000000..8f8dd6f1 --- /dev/null +++ b/server/i18n/ko.json @@ -0,0 +1,6 @@ +{ + "starter0": "이 프로젝트를 소개합니다", + "starter1": "기여 가이드라인 보기", + "starter2": "어떻게 빠르게 시작할 수 있나요?", + "hello_message": "저는 여러분의 전용 Q&A 봇입니다. 현재 프로젝트에 대해 무엇이든 물어보세요~" +} diff --git a/server/i18n/translations.py b/server/i18n/translations.py new file mode 100644 index 00000000..6d29e8f0 --- /dev/null +++ b/server/i18n/translations.py @@ -0,0 +1,49 @@ +from typing import Dict +from fastapi import FastAPI, Request +from starlette.middleware.base import BaseHTTPMiddleware +import json +from pathlib import Path + + +class I18nConfig: + def __init__( + self, default_language: str = "en", translations_dir: str = "translations" + ): + self.default_language = default_language + self.translations_dir = Path(translations_dir) + self.translations: Dict[str, Dict] = {} + self._load_translations() + + def _load_translations(self): + """load translations from the translations directory""" + if not self.translations_dir.exists(): + raise FileNotFoundError( + f"Translations directory {self.translations_dir} not found" + ) + + for lang_file in self.translations_dir.glob("*.json"): + lang_code = lang_file.stem + with open(lang_file, "r", encoding="utf-8") as f: + self.translations[lang_code] = json.load(f) + + def get_text(self, key: str, lang: str) -> str: + if lang not in self.translations: + lang = self.default_language + return self.translations[lang].get(key, key) + + +class I18nMiddleware(BaseHTTPMiddleware): + def __init__(self, app: FastAPI, i18n_config: I18nConfig): + super().__init__(app) + self.i18n_config = i18n_config + + async def dispatch(self, request: Request, call_next): + lang = request.query_params.get( + "lang", self.i18n_config.default_language + ) or request.query_params.get("lang", self.i18n_config.default_language) + + request.state.i18n = self.i18n_config + request.state.lang = lang + + response = await call_next(request) + return response diff --git a/server/i18n/zh-CN.json b/server/i18n/zh-CN.json new file mode 100644 index 00000000..eec4ae7a --- /dev/null +++ b/server/i18n/zh-CN.json @@ -0,0 +1,6 @@ +{ + "starter0": "介绍一下这个项目", + "starter1": "查看贡献指南", + "starter2": "我该怎样快速上手", + "hello_message": "我是你专属的答疑机器人,你可以问我关于当前项目的任何问题~" +} diff --git a/server/i18n/zh-TW.json b/server/i18n/zh-TW.json new file mode 100644 index 00000000..e4c49a7b --- /dev/null +++ b/server/i18n/zh-TW.json @@ -0,0 +1,6 @@ +{ + "starter0": "Introduce the project", + "starter1": "Review the contribution guidelines", + "starter2": "How can I quickly get started?", + "hello_message": "I'm your dedicated Q&A bot. Feel free to ask me anything about the current project~" +} diff --git a/server/main.py b/server/main.py index 51327eb7..a5d747d6 100644 --- a/server/main.py +++ b/server/main.py @@ -7,6 +7,7 @@ from starlette.middleware.sessions import SessionMiddleware from fastapi.middleware.cors import CORSMiddleware from auth.cors_middleware import AuthCORSMiddleWare +from i18n.translations import I18nConfig, I18nMiddleware from auth.middleware import AuthMiddleWare from petercat_utils import get_env_variable @@ -36,12 +37,11 @@ app = FastAPI(title="Petercat Server", version="1.0", description="Petercat.ai APIs") +i18n_config = I18nConfig(default_language="en", translations_dir="i18n") + app.add_middleware(AuthMiddleWare) -app.add_middleware( - SessionMiddleware, - secret_key=session_secret_key -) +app.add_middleware(SessionMiddleware, secret_key=session_secret_key) cors_origins = ( ["*"] if cors_origins_whitelist is None else cors_origins_whitelist.split(",") @@ -57,6 +57,8 @@ app.add_middleware(AuthCORSMiddleWare) +app.add_middleware(I18nMiddleware, i18n_config=i18n_config) + app.include_router(rag_router.router) app.include_router(bot_router.router) app.include_router(auth_router.router) @@ -71,6 +73,7 @@ def home_page(): return RedirectResponse(url=WEB_URL) + @app.get("/api/health_checker") def health_checker(): return {