# Translator for SillyTavern Cards
This is a pure front-end web app to translate (e.g. from English to
Chinese) SillyTavern character cards.
## Tech stack
- Use preact.js. The app should be written in a way that doesn’t
require a build process. The user should be able to simply host the
files as static files in an HTTP server and use it.
- No style-related external libraries (e.g. bootstrap).
## The translation process
A SillyTavern character card is basically just a piece of JSON code.
The process of tranlate such a character card is the following:
1. Parse the JSON into JavaScript object
2. Iterate over all the “leaf” values in this object. If the value is
a string, it should be translated.
3. For each “leaf” string value, the app should use an
OpenAI-compatible LLM API to translate it, and replace the value
with the translated value. These requests should be managed by a
task queue to handle concurrency and prevent overloading the API
or the browser.
4. After all “leaf” string values are translated, provide the JSON as
a string to the user.
## Details
- The app should have an option dialog.
- The options should include the LLM prompt.
- The endpoint URL of the LLM API, the model name, and the API key are
also configurable in the option dialog.
- There should be a list of “ignored keys”, which is a list of regular
expressions. In the process of iterating over the “leaf” values, if
the any of patterns in the ignored keys is found in the key, all the
values under the key should not be translated. Note that the key
does not have to be the key of the “leaf” value; it could be a key
in an intermediate layer. The ignored keys should be configurable in
the option dialog.
- The number of concurrent translations in the task queue should also
be configurable in the option dialog.
- The options are saved in the browser’s local storage.
- After the translation is done. There should be an interface that
layout the JSON as a tree on the UI. Each string value will be
accompanied by three buttons: translate, revert, or retry. This
interface will allow the user to finetune the translation result.
* If the user clicks the “translate” button, and the value was not
translated at that point (maybe because it was ignored by an
ignored key), the app should translate the value. If the value is
already translated, the “translate” button does nothing.
* If the user clicks the “revert” button, and the value was
translated, it should revert the value to the original value. If
that value was not translated, this button does nothing.
* If the user clicks the “retry” button, and the value was
translated, the app should redo the translation on that value. If
the value was not translated, this button does nothing.
- Because of this interface, it is recommended to create an
intermediate type (maybe a JavaScript class), which stores both the
original value, and the translated value. In the beginning of the
translation process, the string values in the JSON should be
replaced by an object of this type.