XUnity.AutoTranslator-Gemini——调用Google的Gemini API, 实现Unity游戏中日文文本的自动翻译

XunityAutoTranslator-Gemini-API

本项目是一个使用 Flask 框架和 Google Gemini GenAI 模型构建的 Web API 服务,用于将日文unity游戏文本翻译成简体中文。

日文游戏文本AI翻译API (基于Google Gemini)

本项目是一个使用 Flask 框架和 Google Gemini GenAI 模型构建的 Web API 服务,用于将日文游戏文本翻译成简体中文。

功能特点

  • AI 驱动翻译: 使用 Google Gemini GenAI 模型 gemini-2.0-flash-001 进行高质量的日文到简体中文翻译。
  • 游戏文本优化: 针对游戏文本特点进行了优化,例如保留格式标签、处理特殊符号、保留原文风格等。
  • 质量检测与重试: 自动检测译文质量,当检测到译文包含日文或重复内容时,会自动重试翻译。
  • 高并发处理: 使用 Flask 框架和 gevent WSGI 服务器,支持高并发请求处理。
  • 异步请求处理: 使用队列和线程池异步处理翻译请求,避免阻塞主线程,提高服务器响应速度。
  • 简单易用: 提供简洁的 HTTP GET API 接口 /translate,方便集成到各种游戏或工具中。

快速开始

1. 前置条件

  • Python 3.6+
  • 已安装必要的 Python 库 (见(###2-依赖库))
  • Google Gemini API 密钥

2. 依赖库

请确保已安装以下 Python 库:

import os
import re
import json
import time
from flask import Flask, request
from gevent.pywsgi import WSGIServer
from urllib.parse import unquote
from threading import Thread
from queue import Queue
import concurrent.futures
from google import genai  # 导入 Google GenAI 库

配置说明

API 配置

Model_Type = "gemini-2.0-flash-001" # 使用的模型类型, 请根据Google的文档自行修改
client = genai.Client(api_key="YOUR_API_KEY") # 替换为你的 API 密钥

3. 配置 API 密钥

请修改代码,打开 脚本文件名.py 文件,找到以下代码行:

client = genai.Client(api_key=“YOUR_API_KEY”) # 使用 genai.Client 初始化客户端,并配置 API 密钥 请替换为您的 API 密钥

将 “YOUR_API_KEY” 替换为您自己的 Google Gemini API 密钥。 注意:请务必替换为您自己的 API 密钥,否则API将无法正常工作。

4. 运行 API 服务 在代码所在目录下,打开终端并执行以下命令:

   python 脚本文件名.py

配置XUnity.AutoTranslator看我上一篇文章:

XUnity.AutoTranslator-deepseek——调用腾讯的DeepSeek V3 API,实现Unity游戏中日文文本的自动翻译

代码配置

以下参数在代码中直接定义,您可以根据需要修改代码进行调整:

  • Model_Type: 使用的 Google Gemini GenAI 模型类型,默认为 “gemini-2.0-flash-001”。您可以根据 Google GenAI API 的支持情况选择其他模型。
  • repeat_count: 重复内容检测阈值,默认为 5。用于检测译文中是否存在重复内容,数值越大,对重复内容检测的容忍度越高。
  • prompt: 基础提示词 (Prompt),用于指导 AI 模型进行翻译。您可以根据需要修改提示词,以优化翻译效果。
  • prompt_list: 提示词列表,默认为包含单个基础提示词的列表。您可以配置多个提示词,程序会在翻译失败时自动尝试使用列表中的下一个提示词进行重试翻译。
  • MAX_WORKERS: 线程池最大工作线程数,默认为 2。您可以根据服务器性能和并发需求调整线程池大小。

代码如下:

import os
import re
import json
import time
from flask import Flask, request
from gevent.pywsgi import WSGIServer
from urllib.parse import unquote
from threading import Thread
from queue import Queue
import concurrent.futures
from google import genai  # 导入 Google GenAI 库

# 启用虚拟终端序列,支持 ANSI 转义代码,允许在终端显示彩色文本
os.system('')

# dict_path='用户替换字典.json' # 替换字典路径。如果不需要使用替换字典,请将此变量留空(设为 None 或空字符串 "")
dict_path=None # 替换字典路径。如果不需要使用替换字典,请将此变量留空(设为 None 或空字符串 "")
# API 配置参数
Model_Type =  "gemini-2.0-flash-001"    # 使用的模型类型,选择 GenAI 支持的模型,例如 "gemini-2.0-flash"

# 创建 Google GenAI 客户端实例
# 使用 genai.Client 进行客户端初始化,并配置 API 密钥
# 注意:请将 "YOUR_API_KEY" 替换为您自己的 Google GenAI API 密钥
client = genai.Client(api_key="YOUR_API_KEY") # 使用 genai.Client 初始化客户端,并配置 API 密钥  **请替换为您的 API 密钥**

# 译文重复内容检测参数
repeat_count=5 # 重复内容阈值。如果译文中有任意单字或单词连续重复出现次数大于等于 repeat_count,则认为译文质量不佳,会触发重试翻译逻辑

# 提示词 (Prompt) 配置
prompt= '''
你是资深本地化专家,负责将游戏日文文本译为简体中文。
**你的任务是精确翻译日文文本,仅输出译文,请勿添加任何与原文无关的解释、说明、补充信息或其他任何文字。** 接收文本后,请严格按照以下要求翻译:
翻译范围:翻译普通日文文本,保留原文叙述风格。
保留格式:保留转义字符、格式标签等非日文文本内容。
翻译原则:忠实准确,确保语义无误;对露骨性描写,可直白粗俗表述,不删减篡改;对双关语等特殊表达,找目标语言等效表达,保原作意图风格。
文本类型:游戏文本含角色对话、旁白、武器及物品名称、技能描述、格式标签、特殊符号等。
以下是待翻译的游戏文本:''' # 基础提示词,用于指导模型进行翻译,定义了翻译的角色、范围、格式、原则和文本类型
prompt_list=[prompt] # 提示词列表。可以配置多个提示词,程序会依次尝试使用列表中的提示词进行翻译,直到获得满意的结果
# l=len(prompt_list) # 获取提示词列表的长度 (此变量目前未被直接使用,移除)

# 提示字典相关的提示词配置
dprompt0='\n在翻译中使用以下字典,字典的格式为{\'原文\':\'译文\'}\n' # 提示模型在翻译时使用提供的字典。字典格式为 JSON 格式的字符串,键为原文,值为译文
dprompt1='\nDuring the translation, use a dictionary in {\'Japanese text \':\'translated text \'} format\n' # 英文版的字典提示词,可能用于多语言支持或模型偏好
# dprompt_list 字典提示词列表,与 prompt_list 提示词列表一一对应。当使用 prompt_list 中的第 i 个提示词时,会同时使用 dprompt_list 中的第 i 个字典提示词
dprompt_list=[dprompt0,dprompt1,dprompt1]
MAX_WORKERS = 2 # 线程池最大工作线程数 (直接在代码中定义)

app = Flask(__name__) # 创建 Flask 应用实例

# 读取提示字典
prompt_dict= {} # 初始化提示字典为空字典
if dict_path: # 检查是否配置了字典路径
    try:
        with open(dict_path, 'r', encoding='utf8') as f: # 尝试打开字典文件
            tempdict = json.load(f) # 加载 JSON 字典数据
            # 按照字典 key 的长度从长到短排序,确保优先匹配长 key,避免短 key 干扰长 key 的匹配
            sortedkey = sorted(tempdict.keys(), key=lambda x: len(x), reverse=True)
            for i in sortedkey:
                prompt_dict[i] = tempdict[i] # 将排序后的字典数据存入 prompt_dict
        print(f"\033[32m字典文件 {dict_path} 加载成功,共加载 {len(prompt_dict)} 个词条。\033[0m") # 打印字典加载成功的消息
    except FileNotFoundError:
        print(f"\033[33m警告:字典文件 {dict_path} 未找到。\033[0m") # 警告用户字典文件未找到
    except json.JSONDecodeError:
        print(f"\033[31m错误:字典文件 {dict_path} JSON 格式错误,请检查字典文件。\033[0m") # 错误提示 JSON 格式错误
    except Exception as e:
        print(f"\033[31m读取字典文件时发生未知错误: {e}\033[0m") # 捕获其他可能的文件读取或 JSON 解析错误

def contains_japanese(text):
    """
    检测文本中是否包含日文字符。
    """
    pattern = re.compile(r'[\u3040-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FE]') # 日文字符的 Unicode 范围正则表达式
    return pattern.search(text) is not None # 使用正则表达式搜索文本中是否包含日文字符


def has_repeated_sequence(string, count):
    """
    检测字符串中是否存在连续重复的字符或子串。
    """
    # 检查单个字符的重复
    for char in set(string):
        if string.count(char) >= count:
            return True

    # 检查字符串片段(子串)的重复
    for size in range(2, len(string) // count + 1):
        for start in range(0, len(string) - size + 1):
            substring = string[start:start + size]
            matches = re.findall(re.escape(substring), string)
            if len(matches) >= count:
                return True

    return False


# 获得文本中包含的字典词汇 (优化后)
def get_dict(text, dictionary):
    """
    从文本中提取出在提示字典 (dictionary) 中存在的词汇及其翻译 (优化版本,不修改原文).

    Args:
        text (str): 待处理的文本.
        dictionary (dict): 提示字典.

    Returns:
        dict:  一个字典,key 为在文本中找到的字典原文,value 为对应的译文.
               如果文本中没有找到任何字典词汇,则返回空字典.
    """
    res = {}
    for key in dictionary:
        if key in text:
            res[key] = dictionary[key]
    return res


request_queue = Queue()  # 创建请求队列
def handle_translation(text, translation_queue):
    """
    处理翻译请求的核心函数.
    """
    text = unquote(text) # URL 解码

    max_retries = 3  # 最大 API 请求重试次数
    retries = 0  # 重试计数器

    special_chars = [',', '。', '?','...'] # 句末特殊字符
    text_end_special_char = None
    if text and text[-1] in special_chars: # 避免空字符串索引错误
        text_end_special_char = text[-1]

    special_char_start = "「"
    special_char_end = "」"
    has_special_start = text.startswith(special_char_start)
    has_special_end = text.endswith(special_char_end)

    if has_special_start and has_special_end:
        text = text[len(special_char_start):-len(special_char_end)]

    try: # 捕获 API 异常
        dict_inuse = get_dict(text, prompt_dict) # 获取字典词汇 (优化: 仅调用一次)
        for i in range(len(prompt_list)): # 遍历提示词列表
            prompt = prompt_list[i]
            if dict_inuse: # 如果有字典词汇,则添加字典提示
                prompt += dprompt_list[i] + str(dict_inuse)

            content_to_translate = prompt + text # 构建完整的翻译内容

            response_test = client.models.generate_content( # API 调用
                model=Model_Type, contents=content_to_translate
            )
            translations = response_test.text
            print(f"【API 原始输出 (未经处理):】\n{repr(translations)}")  # 打印原始值
            if translations.endswith("\n"): # 移除尾部换行符
                translations = translations[:-1]

            print(f"【API 翻译结果 (经处理):】\n{repr(translations)}") # 打印处理后的值,用于调试或日志记录
            # print(f'{prompt}\n{translations}')  # 打印提示词和翻译结果, 调试用


            if has_special_start and has_special_end: # 特殊字符处理
                if not translations.startswith(special_char_start):
                    translations = special_char_start + translations
                if not translations.endswith(special_char_end):
                    translations = translations + special_char_end

            translation_end_special_char = None
            if translations and translations[-1] in special_chars: # 避免空字符串索引错误
                translation_end_special_char = translations[-1]

            if text_end_special_char and translation_end_special_char:
                if text_end_special_char != translation_end_special_char:
                    translations = translations[:-1] + text_end_special_char
            elif text_end_special_char and not translation_end_special_char:
                translations += text_end_special_char
            elif not text_end_special_char and translation_end_special_char:
                translations = translations[:-1]

            contains_japanese_characters = contains_japanese(translations) # 检测日文
            repeat_check = has_repeated_sequence(translations, repeat_count) # 重复检测

            if not contains_japanese_characters and not repeat_check: # 质量检测通过则跳出循环
                break
            elif contains_japanese_characters:
                print("\033[31m检测到译文中包含日文字符,尝试使用下一个提示词进行翻译。\033[0m")
                continue
            elif repeat_check:
                print("\033[31m检测到译文中存在重复短语。\033[0m")
                # 可以在此处添加更复杂的重试策略,例如更换提示词组合,调整模型参数等 (当前版本暂未实现)
                break

        if not contains_japanese_characters and not repeat_check: # 最终质量检测
            pass # 翻译成功
        print(f"\033[36m[译文]\033[0m:\033[31m {translations}\033[0m")
        print("-------------------------------------------------------------------------------------------------------")
        translation_queue.put(translations) # 放入结果队列

    except Exception as e: # API 异常处理
        retries += 1
        print(f"\033[31mAPI请求超时或发生错误 (第 {retries} 次重试): {e}\033[0m") # 打印错误信息
        if retries == max_retries:
            print(f"\033[31m达到最大重试次数,翻译失败。\033[0m")
            translation_queue.put(False) # 放入失败标志
            return # 达到最大重试次数,返回
        time.sleep(1) # 等待重试
        handle_translation(text, translation_queue) # 递归重试
        return # 重试后返回


@app.route('/translate', methods=['GET'])
def translate():
    """
    Flask 路由函数,处理 "/translate" GET 请求.
    """
    text = request.args.get('text')  # 获取待翻译文本
    print(f"\033[36m[原文]\033[0m \033[35m{text}\033[0m") # 打印原文

    translation_queue = Queue() # 创建结果队列

    request_queue.put_nowait(text) # 放入请求队列

    with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor: # 使用配置的线程池大小 (直接使用硬编码值)
        future = executor.submit(handle_translation, text, translation_queue) # 提交翻译任务

        try: # 超时处理
            translation_result = future.result(timeout=30) # 获取结果,设置超时时间
        except concurrent.futures.TimeoutError:
            print("\033[31m翻译请求超时。\033[0m") # 打印超时信息
            return "[请求超时] " + text, 500 # 返回超时错误

    translation = translation_queue.get() # 获取翻译结果
    request_queue.get_nowait() # 从请求队列移除已处理请求

    if isinstance(translation, str): # 翻译成功
        return translation # 返回翻译结果
    else: # 翻译失败
        return "[翻译失败] " , 500 # 返回失败状态码


def main():
    """
    主函数,启动 Flask 应用和 gevent 服务器.
    """
    print("\033[31m服务器在 http://127.0.0.1:4000 上启动\033[0m") # 启动信息
    http_server = WSGIServer(('127.0.0.1', 4000), app, log=None, error_log=None) # 创建 gevent WSGIServer 实例
    http_server.serve_forever() # 启动服务器

if __name__ == '__main__':
    main() # 运行主函数

我的上一篇帖子:XUnity.AutoTranslator-deepseek——调用腾讯的DeepSeek V3 API,实现Unity游戏中日文文本的自动翻译
本项目地址:项目地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/975938.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Grok 3.0 Beta 版大语言模型评测

2025年2月17日至18日,全球首富埃隆马斯克(Elon Musk)携手其人工智能公司xAI,在美国重磅发布了Grok 3.0 Beta版。这款被誉为“迄今为止世界上最智能的语言模型”的AI,不仅集成了先进的“DeepSearch”搜索功能&#xff0…

【R语言】绘图

一、散点图 散点图也叫X-Y图,它将所有的数据以点的形式展现在坐标系上,用来显示变量之间的相互影响程度。 ggplot2包中用来绘制散点图的函数是geom_point(),但在绘制前需要先用ggplot()函数指定数据集和变量。 下面用mtcars数据集做演示&a…

php session数据存储位置选择

PHP session 数据的存储位置可以通过配置文件或者代码来进行设置。默认情况下,session 数据是存储在服务器的文件系统中的。你可以将 session 数据存储在其他地方,例如数据库、缓存等。 基础概念 PHP session默认情况下将数据存储在服务器端的临时文件中…

保姆级! 本地部署DeepSeek-R1大模型 安装Ollama Api 后,Postman本地调用 deepseek

要在Postman中访问Ollama API并调用DeepSeek模型,你需要遵循以下步骤。首先,确保你有一个有效的Ollama服务器实例运行中,并且DeepSeek模型已经被加载。 可以参考我的这篇博客 保姆级!使用Ollama本地部署DeepSeek-R1大模型 并java…

Windows桌面系统管理5:Windows 10操作系统注册表

Windows桌面系统管理0:总目录-CSDN博客 Windows桌面系统管理1:计算机硬件组成及组装-CSDN博客 Windows桌面系统管理2:VMware Workstation使用和管理-CSDN博客 Windows桌面系统管理3:Windows 10操作系统部署与使用-CSDN博客 Wi…

臻识相机,华夏相机,芊熠车牌识别相机加密解密

臻识,华夏,芊熠这三种车牌识别相机解密我都试过了,可以正常解密成功,其它品牌我暂时没有测试。超级简单,免费的,白嫖无敌! 流程: ①:先导出配置文件,例如我以…

RK Android11 WiFi模组 AIC8800 驱动移植流程

RK Android WiFi模组 AIC8800 驱动移植流程 作者:Witheart更新时间:20250220 概要:本文介绍了基于 AIC8800D40 芯片的 WiFi6 模组 BL-M8800DS2-40 在 RK3568 平台上的驱动移植流程。主要涉及环境搭建、驱动代码分析、设备树修改、驱动编译配…

Unity Shader Graph 2D - Procedural程序化图形循环加载进度效果

前言 在游戏中进度加载的效果是一种常见的效果,可以告诉玩家当前游戏处于一个资源加载的状态,这样玩家就能理解游戏不是卡住了或者是出现Bug了,而是正在进行一些数据的处理准备进入下一个场景。 创建一个LineLoading的Shader Graph文件,对应创建一个材质球,然后在…

蓝桥杯备考:贪心算法之矩阵消除游戏

这道题是牛客上的一道题,它呢和我们之前的排座位游戏非常之相似,但是,排座位问题选择行和列是不会改变元素的值的,这道题呢每每选一行都会把这行或者这列清零,所以我们的策略就是先用二进制把选择所有行的情况全部枚举…

Java网络编程封装

系列文章目录 Java知识点 文章目录 系列文章目录👉前言👉一、封装的目标👉二、套接字层封装👉壁纸分享👉总结 👉前言 Java 网络编程封装原理主要围绕着将底层的网络通信细节隐藏起来,提供简洁…

百度首页上线 DeepSeek 入口,免费使用

大家好,我是小悟。 百度首页正式上线了 DeepSeek 入口,这一重磅消息瞬间在技术圈掀起了惊涛骇浪,各大平台都被刷爆了屏。 百度这次可太给力了,PC 端开放仅 1 小时,就有超千万人涌入体验。这速度,简直比火…

边缘安全加速(Edge Security Acceleration)

边缘安全加速(Edge Security Acceleration,简称ESA)是一种通过将安全功能与网络边缘紧密结合来提升安全性和加速网络流量的技术。ESA的目标是将安全措施部署到接近用户或设备的地方,通常是在网络的边缘,而不是将所有流…

SpringBoot+Mybatis-Plus实现动态数据源

目录 一、前言二、代码实现1)工程结构2)相关依赖3)数据源拦截切面4)动态数据源切换5)核心配置类6)使用 三、原理分析1)mapper接口注入流程2)动态数据源切换执行流程 四、声明式事务导…

进程概念、PCB及进程查看

文章目录 一.进程的概念进程控制块(PCB) 二.进程查看通过指令查看进程通过proc目录查看进程的cwd和exe获取进程pid和ppid通过fork()创建子进程 一.进程的概念 进程是一个运行起来的程序,而程序是存放在磁盘的,cpu要想执行程序的指…

字节火山引擎 DeepSeek 接入本地使用

文章目录 1. 火山引擎 DeepSeek 初体验2. 本地接入 火山引擎 DeepSeek API3. 新建 API KEY4. 直接使用 1. 火山引擎 DeepSeek 初体验 火山引擎官网 : https://www.volcengine.com/product/ark 火山云默认给每个模型赠送 50 万 tokens 推理免费额度 进来就会看到模型广场&#…

基于javaweb的SpringBoot个人博客系统设计和实现(源码+文档+部署讲解)

技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…

《操作系统 - 清华大学》8 -4:进程管理:进程控制结构

深度剖析进程控制块:操作系统进程管理的核心关键 在操作系统的复杂体系中,进程控制块(PCB)是实现高效进程管理的关键所在。接下来,将从多个维度深入剖析进程控制块,帮助更好地理解其在操作系统中的重要作用…

Jupyter里面的manim编程学习

1.Jupyterlab的使用 因为我之前一直都是使用的vscode进行manim编程的,但是今天看的这个教程使用的是Jupyter,我也很是好奇这个manim在Jupyter这样的交互式下面会生成怎么样的效果,所以今天尝试了jupyter,并且对于两个进行比较和说…

孜然单授权系统V2.0PHP授权系统

孜然单授权V1.0系统,延续了2022年开发的孜然多应用授权系统V2.0 变更:多应用变单系统,去除没用的垃圾代码,从0开发,去除了一些没用的功能 完善了开发文档,之前那套是我写着玩的屎山代码,V1.0将展…

输入菜单关键字,遍历匹配到 menuIds,展开 匹配节点 的所有父节点以及 匹配节点 本身,高亮 匹配节点

菜单检索,名称、地址、权限标志 等 关键字匹配、展开、高亮(全程借助 DeepSeek ) 便捷简洁的企业官网 的后台菜单管理,图示: 改造点: (1)修改 bootstrapTreeTable 的节点class命名方式为:treeg…