This repository contains the official plugins for Koodo Reader, including translation plugins, dictionary plugins, and text-to-speech (TTS) voice plugins.
├── code/
│ ├── translation/ # Translation plugin source code
│ ├── dictionary/ # Dictionary plugin source code
│ └── voice/ # Voice (TTS) plugin source code
├── plugins/
│ ├── translation/ # Compiled translation plugin JSON files
│ ├── dictionary/ # Compiled dictionary plugin JSON files
│ └── voice/ # Compiled voice (TTS) plugin JSON files
├── utils/ # Utility scripts (e.g., SHA256 hash generation)
├── index.js # Entry point / helper runtime
└── package.json # Node.js project manifest
Each plugin is defined as a JSON file with the following structure:
Translation plugins:
{
"identifier": "plugin-identifier",
"type": "translation",
"displayName": "Display Name",
"icon": "icon-name",
"version": "1.0.0",
"autoValue": "auto",
"config": {},
"langList": { "en": "English", "...": "..." },
"scriptSHA256": "<sha256 of the script field>",
"script": "<minified JavaScript function>"
}Dictionary plugins:
{
"identifier": "plugin-identifier",
"type": "dictionary",
"displayName": "Display Name",
"icon": "icon-name",
"version": "1.0.0",
"config": {},
"langList": [{ "lang": "English", "code": "en", "nativeLang": "English" }],
"scriptSHA256": "<sha256 of the script field>",
"script": "<minified JavaScript function>"
}Voice plugins:
{
"identifier": "plugin-identifier",
"type": "voice",
"displayName": "Display Name",
"icon": "speaker",
"version": "1.0.0",
"config": {},
"voiceList": [
{
"name": "voice-id",
"gender": "female | male",
"locale": "zh-CN",
"displayName": "Voice Display Name",
"plugin": "plugin-identifier",
"config": {}
}
],
"scriptSHA256": "<sha256 of the script field>",
"script": "<minified JavaScript function>"
}The script field must expose a translate function:
async function translate(text, from, to, axios, config) {
// text - the text to translate
// from - source language code
// to - target language code
// axios - axios instance for HTTP requests
// config - user-provided configuration object
return "translated text"; // or a URL string for embed-type plugins
}
window.translate = translate;The script field must expose a getDictText function:
async function getDictText(text, from, to, axios, t, config) {
// text - the word or phrase to look up
// from - source language code
// to - target language code
// axios - axios instance for HTTP requests
// t - i18n translation function (e.g. t("Learn more"))
// config - user-provided configuration object
return "<p>HTML content</p>"; // or a URL string for embed-type plugins
}
window.getDictText = getDictText;The script field must expose a getAudioPath function:
const getAudioPath = async (text, speed, dirPath, config) => {
// text - text to synthesize
// speed - playback speed
// dirPath - directory path to save the audio file
// config - user-provided configuration object
return "?url=https%3A%2F%2Fgithub.com%2Fpath%2Fto%2Faudio.wav"; // absolute path to the generated audio file
};
global.getAudioPath = getAudioPath;Optionally, the script field can also expose a getTTSVoice function. This function is used to dynamically fetch the voice list and is only called when the voiceList field in the plugin template is an empty array ([]):
const getTTSVoice = async (axios, config) => {
// axios - axios instance for HTTP requests
// config - user-provided configuration object
return [
{
name: "voice-id",
gender: "female | male",
locale: "zh-CN",
displayName: "Voice Display Name",
config: {},
},
];
};
global.getTTSVoice = getTTSVoice;A helper script that computes the SHA-256 hash of the script field in a plugin JSON file. This hash is stored in the scriptSHA256 field and is used by Koodo Reader to verify plugin integrity.
node utils/getCodeSHA256.js- Node.js >= 16
- npm
npm install- Write the plugin source code in
code/<plugin-type>/<plugin-name>.js. - Write the plugin template in
plugins/<plugin-type>/<plugin-name>.json. - Minify and escape the plugin source code. Recommended tools: Online JavaScript Minifier Tool and Compressor, JSON Escape / Unescape
- Write the processed script into the
scriptfield of script template. - Update the file path in
utils/getCodeSHA256.jsand run it. Fill the output hash value into thescriptSHA256field.
This project is licensed under the AGPL v3 license.