@echo off
goto :main

:plugin_task_config
rem ===== 插件开发者配置区：任务菜单和提示词 =====
rem 插件开发者通常只需要改这个区域；下面的运行逻辑会自动读取菜单项和对应提示词。
rem 格式：@@TASK 序号 | 菜单显示名称
rem 从 @@TASK 下一行开始，到下一个 @@TASK 或 @@END_TASKS 之前，都是这个选项发送给 CodePanel 的提示词。
rem 提示词可以直接粘贴多行内容；正文里不要单独使用以 @@TASK 或 @@END_TASKS 开头的行。
rem 如果需要新增第 4 项，复制一个任务块并把序号改成 4。
@@TASK 1 | 在当前项目接入 translate.js
你的角色是一个资深的编程研发。
我需要在当前项目中接入 translate.js 这个开源项目，目的是使当前的项目具备多语言切换能力。 使多个页面都可以显示多语言切换的select 标签。 再开始之前，你需要先进行详细了解 translate.js 的所有知识，你需要到网站 http://translate.zvo.cn/ 去阅读有关 translate.js 的所有说明，其中，[快速使用 - 让你最快看到效果，了解它翻译的原理](https://translate.zvo.cn/532777.html) 你应该优先看看， 另外，它的 微调指令包含了可以有开发者自己进行设置自定义的方式，你更应该非常详细的去阅读，微调指令包括：   
- [切换语言select选择框的自定义设置](https://translate.zvo.cn/4056.html)
- [只翻译指定的元素](https://translate.zvo.cn/4063.html)
- [主动进行语言切换](https://translate.zvo.cn/4064.html)
- [设置本地语种（当前网页的语种）](https://translate.zvo.cn/4066.html)
- [手动调用接口进行翻译操作](https://translate.zvo.cn/4077.html)
- [对网页中图片进行翻译](https://translate.zvo.cn/4055.html)
- [设置默认翻译为的语种](https://translate.zvo.cn/4071.html)
- [自定义翻译术语](https://translate.zvo.cn/4070.html)
- [翻译完后自动触发执行](https://translate.zvo.cn/4069.html)
- [指定翻译服务接口域名](https://translate.zvo.cn/4068.html)
- [监控页面动态渲染的文本进行自动翻译](https://translate.zvo.cn/4067.html)
- [自动切换为用户所使用的语种](https://translate.zvo.cn/4065.html)
- [翻译时忽略指定的文字不翻译](https://translate.zvo.cn/283381.html)
- [翻译时忽略指定的id](https://translate.zvo.cn/4062.html)
- [翻译时忽略指定的class属性](https://translate.zvo.cn/4061.html)
- [翻译时忽略指定的tag标签](https://translate.zvo.cn/4060.html)
- [设置只对指定语种进行翻译](https://translate.zvo.cn/4085.html)
- [识别字符串语种及分析](https://translate.zvo.cn/4083.html)
- [重写一级缓存·浏览器缓存](https://translate.zvo.cn/4082.html)
- [设置使用的翻译服务 translate.service.use](https://translate.zvo.cn/4081.html)
- [清除历史翻译语种的缓存](https://translate.zvo.cn/4080.html)
- [翻译接口响应捕获处理](https://translate.zvo.cn/4079.html)
- [元素的内容整体翻译能力配置](https://translate.zvo.cn/4078.html)
- [离线翻译及自动生成配置](https://translate.zvo.cn/4076.html)
- [根据URL传参控制以何种语种显示](https://translate.zvo.cn/4075.html)
- [获取当前显示的是什么语种](https://translate.zvo.cn/4074.html)
- [获取本地语种](https://translate.zvo.cn/4073.html)
- [鼠标划词翻译](https://translate.zvo.cn/4072.html)
- [翻译后再手动对某些元素节点翻译](https://translate.zvo.cn/4088.html)
- [网页ajax请求触发自动翻译](https://translate.zvo.cn/4086.html)
- [增加对指定标签的属性进行翻译](https://translate.zvo.cn/231504.html)
- [本地语种也进行强制翻译](https://translate.zvo.cn/289574.html)
- [自定义通过翻译API进行时的监听事件](https://translate.zvo.cn/379207.html)
- [对某个句子中的某个单词进行翻译替换-文本处理](https://translate.zvo.cn/396191.html)
- [启用翻译中的遮罩层](https://translate.zvo.cn/407105.html)
- [对JS对象及代码进行翻译](https://translate.zvo.cn/452991.html)
- [网络请求自定义附加参数](https://translate.zvo.cn/471711.html)
- [网络请求数据拦截并翻译](https://translate.zvo.cn/479724.html)
- [翻译排队执行](https://translate.zvo.cn/479742.html)
- [获取翻译区域显示的原始文本](https://translate.zvo.cn/513197.html)
- [重写语种识别策略](https://translate.zvo.cn/513538.html)
- [默认网络请求的自定义控制](https://translate.zvo.cn/521713.html)
- [进行翻译的生命周期监控及触发](https://translate.zvo.cn/540189.html)
- [网页打开时自动隐藏文字，翻译完成后显示译文](https://translate.zvo.cn/549731.html)
- [将翻译后的页面进行还原回翻译前的](https://translate.zvo.cn/549732.html)
- [启用翻译性能监控](https://translate.zvo.cn/549733.html)
- [对iframe中的页面自动翻译](https://translate.zvo.cn/549764.html)
- [私有部署翻译服务后调试自检](https://translate.zvo.cn/549786.html)
- [当前是否已进行了翻译处理](https://translate.zvo.cn/549790.html)
- [对翻译服务接口启用 SSE 能力](https://translate.zvo.cn/549861.html)

另外，这个 translate.js 的源码，它的网址是： https://gitee.com/mail_osc/translate/raw/master/translate.js/translate.js  或者 https://raw.githubusercontent.com/xnx3/translate/refs/heads/master/translate.js/translate.js  或者 http://res.zvo.cn/translate/translate.js 这几个都是一样的，你可以按顺序自行下载到当前项目中，放到当前项目放置javascript静态资源的目录下。 同样，你也可以阅读一下这个 translate.js 的代码，如果有什么在微调指令中无法实现的，你可以阅读这个 translate.js 的源码，看是否有相关方法可以直接拿来使用实现功能需求。

另外，如果你基本不需要对 translate.js 进行修改，如果特殊情况一定要时，一定切记不要直接改 translate.js 这个文件，否则你改了它，那它将无法再进行升级了。不然它升级时，你的改动将会全部给覆盖掉。

你在进行任务，在改动时一定要追根溯源一直追踪根源，从根源下手进行改动，尽量改动更少的地方打成目标，避免硬堆、造成臃肿，后续维护困难，出异常也不好检测！而且你的目的是解决问题的根源，而不是仅仅解决当前发现的问题，不然这个问题解决了，那下次依然还可能会出现问题，所以一定要从根源杜绝，从理论上要绝对保证没有任何问题。
如果有你觉得不是非常确定的更改方式，一定要吧相关的选项列出来给我让我做选择，而不是你替我做选择。
尽量是从问题的根源去以最简单的方式改动解决，而不是在做一些新的功能来解决出现的bug。
你要记得，你每做一个改动后，都要提交一次commit，记得要写中文，尽量写详细一些。
另外你写的代码中注释一定要写全面，这样方便别人看。直接提交git并推送。 尽量将它细化提交，而不是好几个任务合并到一次改动里，说明一大堆。 比如你可以改动了一个文件，做了什么操作，你就直接进行一次提交，并推送。这样会非常明确，其他人看提交时也会非常顺畅。
如果你进行的过程中发现有异常需要进行优化时，如果有多个调整方向，你应该先吧可选项列出来，给我选择。

最后，你要看一下用户当前是否已经介入过 translate.js ，如果已经接入过了，那么你应该提醒用户，您已经接入过 translate.js 了，请问你是想让我帮你做什么呢？    这样给用户一个提醒，让用户告诉你具体怎么做，你不要代替用户做决定！



@@END_TASKS

:developer_notes
编码提醒：本文件使用 GBK/ANSI 编码保存；如果编辑器按 UTF-8 打开会看到乱码，请切换为 GBK/ANSI 后再编辑。
中文开发者说明：
1. 这个文件是 CodePanel 第三方 bat 插件示例。
2. 开发者通常只需要修改上方 plugin_task_config 区域。
3. 其他部分已经封装 CodePanel.exe 查找、项目目录校验和启动参数拼接。
4. 选中任务的提示词会在启动前按 UTF-8 转成 Base64，并作为第一条提示词发给 CodePanel，不要放密钥、token、cookie 或账号密码。
5. 脚本不要打印明文提示词，也不要打印 Base64 提示词。
6. 这个说明区由 goto main 跳过，不会被 cmd.exe 执行；这样既保留中文说明，也避免某些 Windows 环境把中文 rem 注释解析错。

:main
setlocal EnableExtensions DisableDelayedExpansion
rem Do not call chcp before set /p; some cmd.exe sessions then read interactive input as empty.

set "SCRIPT_DIR=%~dp0"
set "SCRIPT_PATH=%~f0"
set "LOG_PATH=%TEMP%\codepanel-translate-last.log"
> "%LOG_PATH%" echo [%date% %time%] translate.js.bat started.
call :log "Script path: %SCRIPT_PATH%"

rem 复制到任意项目根目录后，直接把脚本所在目录作为 CodePanel 的项目目录。
for %%I in ("%SCRIPT_DIR%.") do set "PROJECT_PATH=%%~fI"
set "PROJECT_PATH=%PROJECT_PATH:"=%"

rem CodePanel.exe 查找顺序：
rem 1. CODEPANEL_EXE 环境变量显式指定的路径。
rem 2. bat 同级 CodePanel 目录下的 CodePanel.exe，适配 bat 与 CodePanel 文件夹一起复制到项目根目录的结构。
rem 3. bat 同级目录下的 CodePanel.exe，兼容只复制单个 exe 到脚本旁边的结构。
rem 4. bat 上一级目录下的 CodePanel.exe，兼容插件脚本放在子目录中的结构。
rem 5. 开发仓库内的 Windows 交付包路径。
if defined CODEPANEL_EXE (
    set "CODEPANEL_EXE_PATH=%CODEPANEL_EXE%"
    goto after_codepanel_exe_candidates
)

set "CODEPANEL_EXE_PATH=%SCRIPT_DIR%CodePanel\CodePanel.exe"
if exist "%CODEPANEL_EXE_PATH%" goto after_codepanel_exe_candidates

set "CODEPANEL_EXE_PATH=%SCRIPT_DIR%CodePanel.exe"
if exist "%CODEPANEL_EXE_PATH%" goto after_codepanel_exe_candidates

set "CODEPANEL_EXE_PATH=%SCRIPT_DIR%..\CodePanel.exe"
if exist "%CODEPANEL_EXE_PATH%" goto after_codepanel_exe_candidates

set "CODEPANEL_EXE_PATH=%SCRIPT_DIR%..\delivery\packages\windows\CodePanel\CodePanel.exe"

:after_codepanel_exe_candidates
set "CODEPANEL_EXE_PATH=%CODEPANEL_EXE_PATH:"=%"
call :log "CodePanel candidate: %CODEPANEL_EXE_PATH%"
if not exist "%CODEPANEL_EXE_PATH%" (
    call :log "CodePanel.exe was not found."
    echo.
    echo 未找到 CodePanel.exe。
    echo.
    echo 你可以把 CodePanel.exe 放到当前脚本同级目录，或者先设置环境变量：
    echo set CODEPANEL_EXE=D:\CodePanel\CodePanel.exe
    echo.
    pause
    exit /b 1
)

for %%I in ("%CODEPANEL_EXE_PATH%") do set "CODEPANEL_EXE_PATH=%%~fI"
if /I not "%CODEPANEL_EXE_PATH:~-4%"==".exe" (
    call :log "CODEPANEL_EXE does not point to an exe file: %CODEPANEL_EXE_PATH%"
    echo.
    echo CODEPANEL_EXE 必须指向 CodePanel.exe，当前值不是 exe 文件：
    echo %CODEPANEL_EXE_PATH%
    echo.
    pause
    exit /b 1
)
if /I "%CODEPANEL_EXE_PATH%"=="%SCRIPT_PATH%" (
    call :log "CODEPANEL_EXE points to translate.js.bat itself."
    echo.
    echo CODEPANEL_EXE 不能指向 translate.js.bat 自己，否则会递归启动。
    echo %CODEPANEL_EXE_PATH%
    echo.
    pause
    exit /b 1
)


rem translate.js.bat 只有一个接入任务，直接固定使用任务 1，双击后无需再次选择。
set "TASK_ID=1"

set "TASK_NAME="
set "PROMPT_FILE="

call :read_task_config "%TASK_ID%"
if errorlevel 1 (
    call :log "Failed to read task 1 from plugin config."
    echo.
    echo 任务配置读取失败，请检查 translate.js.bat 顶部的插件开发者配置区。
    echo.
    echo 诊断日志：%LOG_PATH%
    pause
    exit /b 1
)
echo 即将打开 CodePanel：
echo 项目目录：%PROJECT_PATH%
echo 任务：%TASK_NAME%
echo.

for %%I in ("%CODEPANEL_EXE_PATH%") do set "CODEPANEL_EXE_DIR=%%~dpI"
call :log "Launching CodePanel.exe: %CODEPANEL_EXE_PATH%"
call :log "Working directory: %CODEPANEL_EXE_DIR%"
call :log "Project path: %PROJECT_PATH%"
call :log "Task id: %TASK_ID%"

rem Store the selected prompt in a UTF-8 temp file instead of passing a large
rem Base64 value through cmd.exe. The translate.js task prompt is long enough
rem to exceed cmd.exe's practical command line limit when encoded inline.
if not exist "%PROMPT_FILE%" (
    call :log "Prompt file was not created: %PROMPT_FILE%"
    echo.
    echo Prompt temp file was not created.
    echo.
    echo Diagnostic log: %LOG_PATH%
    pause
    exit /b 1
)

rem Keep CodePanel.exe as the working directory when this bat is opened by double-click.
start "" /D "%CODEPANEL_EXE_DIR%" "%CODEPANEL_EXE_PATH%" --focus --new-session-path "%PROJECT_PATH%" --prompt-file "%PROMPT_FILE%" --prompt-file-delete-after-read
call :log "start command returned errorlevel %ERRORLEVEL%."

if errorlevel 1 (
    call :log "CodePanel start command failed."
    if exist "%PROMPT_FILE%" del /q "%PROMPT_FILE%" >nul 2>nul
    echo.
    echo CodePanel 启动失败。
    echo.
    echo 诊断日志：%LOG_PATH%
    pause
    exit /b 1
)

exit /b 0

:read_task_config
rem 用法：
rem   call :read_task_config ""        从 plugin_task_config 打印任务菜单。
rem   call :read_task_config "1"       读取所选任务，并设置 TASK_NAME 和 PROMPT_FILE。
rem 这里让 PowerShell 直接读取 bat 文件，避免多行中文提示词再被 cmd.exe 重新解析。
set "CODEPANEL_PLUGIN_SCRIPT_PATH=%SCRIPT_PATH%"
set "CODEPANEL_PLUGIN_TASK_ID=%~1"
set "CODEPANEL_PLUGIN_READ_STATUS=1"
for /f "tokens=1,* delims==" %%A in ('powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command ^
    "$ErrorActionPreference='Stop'; [Console]::OutputEncoding=[Text.Encoding]::Default;" ^
    "$path=$env:CODEPANEL_PLUGIN_SCRIPT_PATH; $selectedId=$env:CODEPANEL_PLUGIN_TASK_ID;" ^
    "$lines=[IO.File]::ReadAllLines($path,[Text.Encoding]::Default);" ^
    "$tasks=New-Object System.Collections.Generic.List[object];" ^
    "$taskId=$null; $taskName=$null; $prompt=New-Object System.Collections.Generic.List[string];" ^
    "$addTask={ if($script:taskId -ne $null){ while($script:prompt.Count -gt 0 -and $script:prompt[$script:prompt.Count-1].Length -eq 0){ $script:prompt.RemoveAt($script:prompt.Count-1) }; [void]$script:tasks.Add([pscustomobject]@{Id=$script:taskId;Name=$script:taskName;Prompt=($script:prompt -join [char]10)}) } };" ^
    "foreach($line in $lines){" ^
    "if($line -match '^@@TASK\s+([^|]+?)\s*\|\s*(.+?)\s*$'){ & $addTask; $taskId=$matches[1].Trim(); $taskName=$matches[2].Trim(); $prompt=New-Object System.Collections.Generic.List[string]; continue };" ^
    "if($line -match '^@@END_TASKS\s*$'){ & $addTask; break };" ^
    "if($taskId -ne $null){ [void]$prompt.Add($line) }" ^
    "};" ^
    "if($tasks.Count -lt 1){ exit 1 };" ^
    "if([string]::IsNullOrEmpty($selectedId)){ foreach($task in $tasks){ Write-Output ('MENU=' + $task.Id + '. ' + $task.Name) }; Write-Output 'STATUS=0'; exit 0 };" ^
    "$selected=$tasks | Where-Object { $_.Id -eq $selectedId } | Select-Object -First 1;" ^
    "if($null -eq $selected -or [string]::IsNullOrWhiteSpace($selected.Prompt)){ exit 1 };" ^
    "Write-Output ('TASK_NAME=' + $selected.Name);" ^
    "$safeTaskId=($selected.Id -replace '[^A-Za-z0-9_.-]','_'); $promptPath=[IO.Path]::Combine([IO.Path]::GetTempPath(),('codepanel-translate-prompt-' + [Guid]::NewGuid().ToString('N') + '-' + $safeTaskId + '.txt')); [IO.File]::WriteAllText($promptPath,$selected.Prompt,(New-Object Text.UTF8Encoding $false));" ^
    "Write-Output ('PROMPT_FILE=' + $promptPath);" ^
    "Write-Output 'STATUS=0'" ^<nul') do (
    if /I "%%A"=="MENU" echo(%%B
    if /I "%%A"=="TASK_NAME" set "TASK_NAME=%%B"
    if /I "%%A"=="PROMPT_FILE" set "PROMPT_FILE=%%B"
    if /I "%%A"=="STATUS" set "CODEPANEL_PLUGIN_READ_STATUS=%%B"
)
set "CODEPANEL_PLUGIN_SCRIPT_PATH="
set "CODEPANEL_PLUGIN_TASK_ID="
exit /b %CODEPANEL_PLUGIN_READ_STATUS%
:log
rem Keep the log payload in one argument so cmd.exe does not split it.
>> "%LOG_PATH%" echo [%date% %time%] %~1
exit /b 0
