国际化 (i18n) SillyTavern 支持多种语言。本指南解释如何添加和管理翻译。
您可能来到这里是因为某些文本在您的语言中未翻译,这让您感到困扰。首先,我将向您展示我是如何修复繁体中文语言环境中的一些缺失翻译的。每个翻译缺失的原因都不同,这样您就能很好地了解如何修复自己的缺失翻译。
在第二部分,我们将探讨
如果您正在开发扩展或修改核心代码,请在编写 HTML 和 JavaScript 时考虑 i18n。这样,其他人就可以将您的工作翻译成他们的语言。
没有人能自己掌握 15 种语言。我们一起努力让 SillyTavern 对每个人都可访问。
世界上的每个人都应该能够在手机和电脑上使用自己的语言。
让我们修复一些缺失的翻译!
这 3 个问题都需要代码更改才能修复。如果您要添加新翻译,可能根本不需要修改代码。只需将翻译添加到 JSON 文件中即可。恰好最近有人向繁体中文 JSON 文件添加了大量缺失的翻译,所以剩下的问题都在代码中。在其他语言环境中,有很多缺失的翻译可以在不修改代码的情况下修复。
Generate Image
"Generate Image"(生成图像)在繁体中文语言环境中未翻译。为什么?
generate-image-pre.png
右键点击元素并检查它。您会看到 HTML:
< div class = " list-group-item flex-container flexGap5 interactable" id = " sd_gen" tabindex = " 0" >
< div data-i18n = " [title]Trigger Stable Diffusion" title = " 觸發 Stable Diffusion"
class = " fa-solid fa-paintbrush extensionsMenuExtensionButton" > </ div>
< span> Generate Image</ span>
</ div>
它的 data-i18n
属性在哪里?它缺失了!让我们添加它。我们在源代码中找到它:
< div id = " sd_gen" class = " list-group-item flex-container flexGap5" >
< div class = " fa-solid fa-paintbrush extensionsMenuExtensionButton" title = " Trigger Stable Diffusion"
data-i18n = " [title]Trigger Stable Diffusion" > </ div>
< span> Generate Image</ span>
</ div>
< div id = " sd_stop_gen" class = " list-group-item flex-container flexGap5" >
< div class = " fa-solid fa-circle-stop extensionsMenuExtensionButton" title = " Abort current image generation task"
data-i18n = " [title]Abort current image generation task" > </ div>
< span> Stop Image Generation</ span>
</ div>
我们很幸运,字符串 Generate Image
在许多语言文件中都有,包括繁体中文。
generate-image-lang.png
{
"Generate Image" : "生成图片"
}
为什么它没有显示出来?我们必须正确连接元素:
< div id = " sd_gen" class = " list-group-item flex-container flexGap5" >
< div class = " fa-solid fa-paintbrush extensionsMenuExtensionButton" title = " Trigger Stable Diffusion"
data-i18n = " [title]Trigger Stable Diffusion" > </ div>
< span data-i18n = " Generate Image" > Generate Image</ span>
</ div>
< div id = " sd_stop_gen" class = " list-group-item flex-container flexGap5" >
< div class = " fa-solid fa-circle-stop extensionsMenuExtensionButton" title = " Abort current image generation task"
data-i18n = " [title]Abort current image generation task" > </ div>
< span> Stop Image Generation</ span>
</ div>
现在它可以工作了!重新加载页面看看。
generate-image-post.png
但是当我们打开 HTML 时,下面的 Stop Image Generation
是怎么回事?HTML 看起来不对。
如果我们生成图像,然后在生成时打开魔杖菜单,我们会看到未翻译的文本。
stop-generating-image-pre.png
首先修复 HTML:
< div id = " sd_gen" class = " list-group-item flex-container flexGap5" >
< div class = " fa-solid fa-paintbrush extensionsMenuExtensionButton" title = " Trigger Stable Diffusion"
data-i18n = " [title]Trigger Stable Diffusion" > </ div>
< span data-i18n = " Generate Image" > Generate Image</ span>
</ div>
< div id = " sd_stop_gen" class = " list-group-item flex-container flexGap5" >
< div class = " fa-solid fa-circle-stop extensionsMenuExtensionButton" title = " Abort current image generation task"
data-i18n = " [title]Abort current image generation task" > </ div>
< span data-i18n = " Stop Image Generation" > Stop Image Generation</ span>
</ div>
这还不足以解决问题。繁体中文文件中没有"Stop Image Generation"的翻译。我们可以添加它!这是一个可能的翻译:
{
"Stop Image Generation" : "停止生成图片"
}
...我们可以将其添加到 JSON 文件中的"Generate Image"翻译之后。
{
"Generate Image" : "生成图片" ,
"Stop Image Generation" : "停止生成图片"
}
经过与 Claude 的讨论,我们实际上将使用以下翻译:
繁体中文:"Stop Image Generation": "終止圖片生成" 简体中文:"Stop Image Generation": "中止图像生成" 日语:"Stop Image Generation": "画像生成を停止"
stop-generating-post-2.png
Generate Caption
"Generate Caption"(生成说明)在繁体中文语言环境中未翻译。让我们修复它!
generate-image-post.png
它在哪里?检查元素。
< div id = " send_picture" class = " list-group-item flex-container flexGap5 interactable" tabindex = " 0" >
< div class = " fa-solid fa-image extensionsMenuExtensionButton" > </ div>
Generate Caption
</ div>
原来这个 HTML 是由 JavaScript 生成的。让我们找到源代码。
const sendButton = $ ( `
<div id="send_picture" class="list-group-item flex-container flexGap5">
<div class="fa-solid fa-image extensionsMenuExtensionButton"></div>
Generate Caption
</div> ` ) ;
我们首先要修复代码:
const sendButton = $ ( `
<div id="send_picture" class="list-group-item flex-container flexGap5">
<div class="fa-solid fa-image extensionsMenuExtensionButton"></div>
<span data-i18n="Generate Caption">Generate Caption</span>
</div> ` ) ;
繁体中文文件中也没有"Generate Caption"的翻译。让我们添加它!
{
"Generate Caption" : "生成圖片說明"
}
我们将使用以下翻译:
繁体中文:"Generate Caption": "生成圖片說明" 简体中文:"Generate Caption": "生成图片说明" 日语:"Generate Caption": "画像説明を生成"
generate-caption-post.png
Inspect Prompts
"Inspect Prompts"(检查提示词)在繁体中文语言环境中未翻译。为什么? 这个有点复杂。文本是由 JavaScript 生成的,而且翻译缺失。
const enabledText = 'Stop Inspecting' ;
const disabledText = 'Inspect Prompts' ;
好吧,您知道吗...这两个短语都不在 i18n 文件中。让我们添加它们。
{
"Stop Inspecting" : "停止檢查" ,
"Inspect Prompts" : "檢查提示詞"
}
现在我们必须修复 JavaScript 代码。它必须使用 t
函数来获取翻译。
import { t} from '../../../i18n.js' ;
const enabledText = t` Stop Inspecting ` ;
const disabledText = t` Inspect Prompts ` ;
我们从 Claude 那里得到了这些建议。保留字符串,忽略代码。它们必须添加到 JSON 文件中。
const enabledText = t` 停止检查 ` ;
const disabledText = t` 检查提示词 ` ;
const enabledText = t` 停止檢查 ` ;
const disabledText = t` 檢查提示詞 ` ;
const enabledText = t` 検査を停止 ` ;
const disabledText = t` プロンプトを検査 ` ;
我们将把这些合并到 JSON 文件中。
{
"Stop Inspecting" : "停止检查" ,
"Inspect Prompts" : "检查提示词"
}
{
"Stop Inspecting" : "停止檢查" ,
"Inspect Prompts" : "檢查提示詞"
}
{
"Stop Inspecting" : "検査を停止" ,
"Inspect Prompts" : "プロンプトを検査"
}
toggle-prompt-inspection-post-tt.png
关于那个工具提示很遗憾。问题在于代码没有使用 t
函数。
launchButton. title = 'Toggle prompt inspection' ;
我们必须在扩展代码中修复这个问题。
launchButton. title = t` Toggle prompt inspection ` ;
我们还需要将翻译添加到 JSON 文件中。
{
"Toggle prompt inspection" : "切换提示检查"
}
{
"Toggle prompt inspection" : "切换提示词检查"
}
{
"Toggle prompt inspection" : "プロンプト検査の切り替え"
}
提示检查器是一个独立的扩展,所以我们会向该仓库提交代码修复:https://github.com/SillyTavern/Extension-PromptInspector/pull/1
翻译将添加到主 SillyTavern 仓库。https://github.com/SillyTavern/SillyTavern/pull/3198
start-inspecting-post.png
语言文件 每种语言在 public/locales/
目录下都有一个以其语言代码命名的 JSON 文件(例如,ru-ru.json
)。
该文件包含键值对,其中:
示例:
{
"Save" : "Сохранить" ,
"Cancel" : "Отмена" ,
"Could not find proxy with name '${0}'" : "Не удалось найти прокси с названием '${0}'"
}
翻译的工作原理 应用程序中有两种使用翻译的方式:
HTML 元素 :使用 data-i18n
属性
< div data-i18n = " some_key" > 默认文本</ div>
如果有可用的翻译,HTML 中的默认文本将被替换为翻译后的文本。
模板字符串 :在 JavaScript 代码中使用 t
函数
t` Some text with ${ variable} `
这些字符串应该在保持 ${0}
、${1}
等占位符不变的情况下进行翻译。
SillyTavern 使用带有 data-i18n
属性的 HTML 元素来标记可翻译的内容。使用这个属性有几种方式:
1. 翻译元素文本 对于简单的文本内容:
< span data-i18n = " Role:" > Role:</ span>
这会将元素的文本内容替换为"Role:"的翻译。
2. 翻译属性 要翻译标题或占位符等属性:
< a class = " menu_button fa-chain fa-solid fa-fw"
title = " Insert prompt"
data-i18n = " [title]Insert prompt" > </ a>
{
"Insert prompt" : "Вставить промпт"
}
[title]
前缀指示要翻译哪个属性。属性值的其余部分是将用作 JSON 文件中查找键的文本。程序员通常使用英文文本作为键,但这不是必需的。键可以是任何唯一标识符。
不过,原始英文文本必须存在于相应的属性中(title="Insert prompt"
)。如果缺少翻译,它将用作后备。最值得注意的是,英语没有翻译文件。
这里是一个使用唯一标识符 no_items_text
作为键而不是英文文本的示例:
< div class = " openai_logit_bias_list" no_items_text = " No items"
data-i18n = " [no_items_text]openai_logit_bias_no_items" > </ div>
{
"openai_logit_bias_no_items" : "没有相关产品"
}
3. 每个元素的多个翻译 某些元素需要同时翻译内容和属性,用分号分隔。最常见的模式是同时翻译元素的文本内容和其标题属性:
< div data-source = " openrouter" class = " menu_button menu_button_icon openrouter_authorize"
title = " Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai"
data-i18n = " Authorize;[title]Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai" >
Authorize
</ div>
{
"Authorize" : "Авторизоваться" ,
"Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai" : "Получите свой OpenRouter API токен используя OAuth. У вас будет открыта вкладка openrouter.ai"
}
这会翻译:
使用键"Authorize"翻译元素的文本内容 使用键"Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai"翻译标题属性 注意,title
属性和元素的文本内容都以英语提供作为后备。
您也可以翻译多个属性:
< textarea id = " send_textarea" name = " text" class = " mdHotkeys"
data-i18n = " [no_connection_text]Not connected to API!;[connected_text]Type a message, or /? for help"
placeholder = " Not connected to API!"
no_connection_text = " Not connected to API!"
connected_text = " Type a message, or /? for help" > </ textarea>
您的语言文件中相应的翻译看起来像这样:
{
"Not connected to API!" : "Нет соединения с API!" ,
"Type a message, or /? for help" : "Введите сообщение или /? для помощи"
}
当页面加载时,系统会:
查找所有带有 data-i18n
属性的元素 解析任何属性前缀,如 [title]
或 [placeholder]
在您的语言的 JSON 文件中查找每个键 用翻译后的文本替换元素的内容或属性
动态文本 对于 JavaScript 代码中的动态文本,翻译使用以下方式之一:
带有 t
函数的模板字面量: toastr. warn ( t` Tag ${ tagName} not found. ` ) ;
直接翻译函数: translate ( "Some text" , "optional_key" )
变量占位符 某些字符串包含使用 ${0}
、${1}
等的动态值占位符:
toastr. error ( t` Could not find proxy with name ' ${ presetName} ' ` ) ;
{
"Could not find proxy with name '${0}'" : "Не удалось найти прокси с названием '${0}'"
}
在键和翻译中保持占位符相同。系统将用 presetName
的值替换 ${0}
等。
查找缺失的翻译 如果您不仅想修复某个特定的翻译问题,而是希望全面查找并修复所有缺失的翻译,这无疑是一个更具挑战性的任务。
虽然修复单个翻译已经很有价值,但若您希望系统性地解决所有翻译缺失问题,您将需要借助专门的工具来完成这项工作。
SillyTavern-i18n https://github.com/SillyTavern/SillyTavern-i18n
用于处理前端本地化文件的工具。
功能:
自动从 HTML 文件添加新的待翻译项。 从本地化文件中删除缺失的项。 使用自动 Google 翻译来自动填充缺失的值。 按键对 JSON 文件进行排序。
Inbuilt debug functions 这些工具位于 用户设置 > 调试菜单 下。
获取缺失的翻译 检测当前语言环境中缺失的本地化数据,并将数据输出到浏览器控制台。如果当前语言环境是英语,则搜索所有其他语言环境。
控制台将显示一个缺失翻译的表格,包含:
key:需要翻译的文本或标识符 language:您当前的语言代码 value:需要翻译的英文文本
应用语言环境 重新应用当前选择的语言环境到页面
这两个工具都不是完美的 它们无法捕获 JavaScript 代码中缺失的翻译 它们无法捕获 HTML 中缺失的 data-i18n 属性,它们只能捕获未翻译的键 getMissingTranslations
的代码中存在错误:键不应该带有 [title]
或 [placeholder]
前缀
Adding a new language 要添加对新语言的支持:
将您的语言添加到 public/locales/lang.json
:
{
"lang" : "xx-xx" ,
"display" : "语言名称(英文名称)"
}
创建 public/locales/xx-xx.json
并添加您的翻译
Contributing 当您的翻译准备就绪时:
验证您的 JSON 文件是否有效 在应用程序中进行彻底测试 通过 GitHub 拉取请求提交