GET HTTP リクエストが機能しない問題を修正し、iCIBA および LibreTranslate エンジンを再追加し、マニュアル ページを作成し、Docker に関連するものを削除しました。
Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja> git-svn-id: file:///srv/svn/repo/mai/trunk@60 e410bdd4-646f-c54f-a7ce-fffcc4f439ae
This commit is contained in:
parent
0c83958125
commit
21388e220d
@ -1,7 +0,0 @@
|
||||
FROM golang:1.20-alpine
|
||||
|
||||
COPY . .
|
||||
RUN go mod download
|
||||
RUN go build -o mai
|
||||
EXPOSE 5000
|
||||
CMD [ "./mai" ]
|
@ -32,12 +32,12 @@ location / {
|
||||
```
|
||||
|
||||
### Legal notice
|
||||
Mai does not host any content. All content shown on any Mai/Mozhi/SimplyTranslate instances is from [Google Translate](https://translate.google.com) and [Reverso](https://www.reverso.net/).
|
||||
Mai does not host any content. All content shown on any Mai instances is from [Google Translate](https://translate.google.com), [Reverso](https://www.reverso.net/), [iCIBA](https://www.iciba.net) and [LibreTranslate](https://libretranslate.com)
|
||||
|
||||
Mai is not affiliated with Google Translate nor Reverso, which this program relays.
|
||||
Mai is not affiliated with none of the above, which this program relays.
|
||||
|
||||
Trademarks belong to their respective owners.
|
||||
Google Translate is a trademark of [Google LLC](https://www.google.com). Reverso is a trademark of Reverso.
|
||||
Google Translate is a trademark of [Google LLC](https://www.google.com). Reverso is a trademark of Reverso, et cetera.
|
||||
|
||||
The creators and maintainers of this repository assume no liability for the accuracy and timeliness of any information provided above. Trademark owner information was researched to the best of the author's knowledge at the time of curation and may be outdated or incorrect.
|
||||
|
||||
|
@ -38,8 +38,6 @@ func main() {
|
||||
Views: engine,
|
||||
})
|
||||
|
||||
api := app.Group("/api")
|
||||
|
||||
app.All("/", func(c *fiber.Ctx) error {
|
||||
engine := c.Cookies("engine")
|
||||
if c.Query("engine") != "" {
|
||||
@ -139,7 +137,7 @@ func main() {
|
||||
})
|
||||
})
|
||||
|
||||
api.All("/api/translate", func(c *fiber.Ctx) error {
|
||||
app.All("/api/translate", func(c *fiber.Ctx) error {
|
||||
from := ""
|
||||
to := ""
|
||||
engine := ""
|
||||
@ -170,7 +168,7 @@ func main() {
|
||||
}
|
||||
})
|
||||
|
||||
api.Get("/api/source_languages", func(c *fiber.Ctx) error {
|
||||
app.Get("/api/source_languages", func(c *fiber.Ctx) error {
|
||||
engine := c.Query("engine")
|
||||
if _, ok := engines.Engines[engine]; !ok || engine == "" {
|
||||
engine = "google"
|
||||
@ -182,7 +180,7 @@ func main() {
|
||||
}
|
||||
})
|
||||
|
||||
api.Get("/api/target_languages", func(c *fiber.Ctx) error {
|
||||
app.Get("/api/target_languages", func(c *fiber.Ctx) error {
|
||||
engine := c.Query("engine")
|
||||
if _, ok := engines.Engines[engine]; !ok || engine == "" {
|
||||
engine = "google"
|
||||
@ -194,7 +192,7 @@ func main() {
|
||||
}
|
||||
})
|
||||
|
||||
api.Get("/api/tts", func(c *fiber.Ctx) error {
|
||||
app.Get("/api/tts", func(c *fiber.Ctx) error {
|
||||
engine := c.Query("engine")
|
||||
if _, ok := engines.Engines[engine]; !ok || engine == "" {
|
||||
engine = "google"
|
||||
@ -221,7 +219,7 @@ func main() {
|
||||
}
|
||||
}
|
||||
})
|
||||
api.Get("/version", func(c *fiber.Ctx) error {
|
||||
app.Get("/version", func(c *fiber.Ctx) error {
|
||||
return c.JSON(fiber.Map{
|
||||
"fiberversion": fiber.Version,
|
||||
"goversion": runtime.Version(),
|
||||
|
@ -1,11 +0,0 @@
|
||||
version: "3.6"
|
||||
|
||||
services:
|
||||
mai:
|
||||
container_name: mai
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 5000:5000
|
@ -1,5 +1,9 @@
|
||||
package engines
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
type TranslationResult struct {
|
||||
SourceLanguage string `json:"source_language"`
|
||||
Definitions interface{} `json:"definitions"`
|
||||
@ -20,4 +24,9 @@ type Language map[string]string
|
||||
var Engines = map[string]Engine{
|
||||
"google": &GoogleTranslate{},
|
||||
"reverso": &Reverso{},
|
||||
"iciba": &ICIBA{},
|
||||
"libretranslate": &LibreTranslate{
|
||||
InstanceURL: os.Getenv("MAI_LIBRETRANSLATE_INSTANCE"),
|
||||
APIKey: os.Getenv("MAI_LIBRETRANSLATE_API"),
|
||||
},
|
||||
}
|
||||
|
283
engines/iciba.go
Normal file
283
engines/iciba.go
Normal file
@ -0,0 +1,283 @@
|
||||
package engines
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// iCIBA is an engine that fetches data from https://www.iciba.com.
|
||||
type ICIBA struct{}
|
||||
|
||||
func (_ *ICIBA) DisplayName() string { return "iCIBA" }
|
||||
|
||||
var icibaLanguages = Language{
|
||||
// ICIBA does have an API, but they return Chinese names.
|
||||
// For languages already present in Google translate, the English
|
||||
// names in that engine file are used; Otherwise official names
|
||||
// as researched on Wikipedia are used. They're validated against
|
||||
// the Chinese names to the best of my ability.
|
||||
// Missing "cni", "kbh", "tmh"
|
||||
// due to conflict between ISO-639 table and Chinese label
|
||||
// one "//" means on iciba but not on google
|
||||
"ace": "Achinese", //
|
||||
"acu": "Achuar-Shiwiar", //
|
||||
"af": "Afrikaans",
|
||||
"agr": "Aguaruna", //
|
||||
"ake": "Akawaio", //
|
||||
"sq": "Albanian",
|
||||
"am": "Amharic",
|
||||
"ar": "Arabic",
|
||||
"hy": "Armenian",
|
||||
"az": "Azerbaijani",
|
||||
"bsn": "Barasana-Eduria", //
|
||||
"ba": "Bashkir", //
|
||||
"eu": "Basque",
|
||||
"be": "Belarusian",
|
||||
"bem": "Bemba", //
|
||||
"bn": "Bengali",
|
||||
"ber": "Berber", //
|
||||
"bi": "Bislama", //
|
||||
"bs": "Bosnian",
|
||||
"br": "Breton", //
|
||||
"bg": "Bulgarian",
|
||||
"cjp": "Cabécar", //
|
||||
"yue": "Cantonese",
|
||||
"ca": "Catalan",
|
||||
"ceb": "Cebuano",
|
||||
"cha": "Chamorro", //
|
||||
"chr": "Cherokee", //
|
||||
"ny": "Chichewa",
|
||||
"zh": "Chinese (Simplified)", // "zh-cn" on Google
|
||||
"cht": "Chinese (Traditional)", // "zh-tw" on Google
|
||||
"cv": "Chuvash",
|
||||
"cop": "Coptic", //
|
||||
"co": "Corsican",
|
||||
"hr": "Croatian",
|
||||
"cs": "Czech",
|
||||
"da": "Danish",
|
||||
"dv": "Dhivehi", //
|
||||
"dik": "Dinka", //
|
||||
"nl": "Dutch",
|
||||
"dz": "Dzongkha", //
|
||||
"en": "English",
|
||||
"eo": "Esperanto",
|
||||
"et": "Estonian",
|
||||
"ee": "Ewe", //
|
||||
"fo": "Faroese", //
|
||||
"fj": "Fijian", //
|
||||
"fil": "Filipino", // "tl" on Google
|
||||
"fi": "Finnish",
|
||||
"fr": "French",
|
||||
"fy": "Frisian",
|
||||
"gbi": "Galela", //
|
||||
"gl": "Galician",
|
||||
"lg": "Ganda", //
|
||||
"jy": "Georgian", // "ka" on Google
|
||||
"de": "German",
|
||||
"el": "Greek",
|
||||
"amu": "Guerrero Amuzgo", //
|
||||
"gu": "Gujarati",
|
||||
"ht": "Haitian Creole",
|
||||
"ha": "Hausa",
|
||||
"haw": "Hawaiian",
|
||||
"he": "Hebrew", // "iw" on Google
|
||||
"hi": "Hindi",
|
||||
"mww": "Hmong Daw", //
|
||||
"hmn": "Hmong", // not in iciba
|
||||
"hu": "Hungarian",
|
||||
"is": "Icelandic",
|
||||
"ig": "Igbo",
|
||||
"id": "Indonesian",
|
||||
"ga": "Irish",
|
||||
"it": "Italian",
|
||||
"jac": "Jacalteco", //
|
||||
"ja": "Japanese",
|
||||
"jv": "Javanese", // "jw" on Google
|
||||
"kab": "Kabyle", //
|
||||
"kn": "Kannada",
|
||||
"cak": "Kaqchikel", //
|
||||
"ka": "Kazakh", // Google only has "kk"
|
||||
"kk": "Kazakh (Cyrillic)", // Google has it as just "Kazakh"
|
||||
"kek": "Kekchí", //
|
||||
"km": "Khmer",
|
||||
"rw": "Kinyarwanda",
|
||||
"kg": "Kongo", //
|
||||
"ko": "Korean",
|
||||
"ku": "Kurdish (Kurmanji)",
|
||||
"ky": "Kyrgyz",
|
||||
"lo": "Lao",
|
||||
"la": "Latin",
|
||||
"lv": "Latvian",
|
||||
"ln": "Lingala", //
|
||||
"lt": "Lithuanian",
|
||||
"dop": "Lukpa", //
|
||||
"lb": "Luxembourgish",
|
||||
"mk": "Macedonian",
|
||||
"mg": "Malagasy",
|
||||
"ms": "Malay",
|
||||
"ml": "Malayalam",
|
||||
"mt": "Maltese",
|
||||
"mam": "Mam", //
|
||||
"gv": "Manx", //
|
||||
"mi": "Maori",
|
||||
"mr": "Marathi",
|
||||
"mhr": "Mari (Eastern)", //
|
||||
"mrj": "Mari (Western)", //
|
||||
"mn": "Mongolian",
|
||||
"me": "Montenegrin", //
|
||||
"my": "Myanmar (Burmese)",
|
||||
"nhg": "Nahuatl", //
|
||||
"djk": "Ndyuka", //
|
||||
"ne": "Nepali",
|
||||
"no": "Norwegian",
|
||||
"or": "Odia (Oriya)",
|
||||
"ojb": "Ojibwa",
|
||||
"om": "Oromo", //
|
||||
"os": "Ossetian", //
|
||||
"pck": "Paite", //
|
||||
"pap": "Papiamento", //
|
||||
"ps": "Pashto",
|
||||
"fa": "Persian",
|
||||
"pl": "Polish",
|
||||
"pt": "Portuguese",
|
||||
"pot": "Potawatomi", //
|
||||
"pa": "Punjabi",
|
||||
"otq": "Querétaro Otomi", //
|
||||
"quc": "Quiché", //
|
||||
"quw": "Quichua", //
|
||||
"chq": "Quiotepec Chinantec", //
|
||||
"rmn": "Romani", //
|
||||
"ro": "Romanian",
|
||||
"rn": "Rundi", //
|
||||
"ru": "Russian",
|
||||
"sm": "Samoan",
|
||||
"sg": "Sango", //
|
||||
"gd": "Scots Gaelic",
|
||||
"sr": "Serbian",
|
||||
"crs": "Seselwa Creole French", //
|
||||
"st": "Sesotho",
|
||||
"sn": "Shona",
|
||||
"jiv": "Shuar", //
|
||||
"sd": "Sindhi",
|
||||
"si": "Sinhala",
|
||||
"sk": "Slovak",
|
||||
"sl": "Slovenian",
|
||||
"so": "Somali",
|
||||
"es": "Spanish",
|
||||
"su": "Sundanese",
|
||||
"sw": "Swahili",
|
||||
"sv": "Swedish",
|
||||
"syc": "Syriac", // considered "extinct" but is somehow supported
|
||||
"shi": "Tachelhit", //
|
||||
"ty": "Tahitian", //
|
||||
"tg": "Tajik",
|
||||
"ta": "Tamil",
|
||||
"tt": "Tatar",
|
||||
"te": "Telugu",
|
||||
"tet": "Tetum", //
|
||||
"th": "Thai",
|
||||
"ti": "Tigre", //
|
||||
"tw": "Tiwi", //
|
||||
"tpi": "Tok Pisin", //
|
||||
"to": "Tonga", //
|
||||
"ts": "Tsonga",
|
||||
"tn": "Tswana", //
|
||||
"tr": "Turkish",
|
||||
"tk": "Turkmen",
|
||||
"udm": "Udmurt", //
|
||||
"uk": "Ukrainian",
|
||||
"ppk": "Uma", //
|
||||
"ur": "Urdu",
|
||||
"usp": "Uspanteco", //
|
||||
"uy": "Uyghur", // "ug" on Google
|
||||
"uz": "Uzbek",
|
||||
"ve": "Venda", //
|
||||
"vi": "Vietnamese",
|
||||
"war": "Waray", //
|
||||
"cy": "Welsh",
|
||||
"wal": "Wolaitta", //
|
||||
"wol": "Wolof",
|
||||
"xh": "Xhosa",
|
||||
"yi": "Yiddish",
|
||||
"yo": "Yoruba",
|
||||
"yua": "Yucatán Maya", //
|
||||
"dje": "Zarma", //
|
||||
"zu": "Zulu",
|
||||
}
|
||||
|
||||
func (_ *ICIBA) SourceLanguages() (Language, error) {
|
||||
icibaLanguagesCopy := make(Language)
|
||||
for k, v := range icibaLanguages {
|
||||
icibaLanguagesCopy[k] = v
|
||||
}
|
||||
|
||||
icibaLanguagesCopy["auto"] = "Detect Language"
|
||||
return icibaLanguagesCopy, nil
|
||||
}
|
||||
|
||||
func (_ *ICIBA) TargetLanguages() (Language, error) { return icibaLanguages, nil }
|
||||
|
||||
func (_ *ICIBA) Translate(text string, from, to string) (TranslationResult, error) {
|
||||
requestURL, _ := url.Parse("https://ifanyi.iciba.com/index.php")
|
||||
|
||||
query := url.Values{}
|
||||
query.Add("c", "trans")
|
||||
query.Add("m", "fy")
|
||||
query.Add("client", "6")
|
||||
query.Add("auth_user", "key_web_fanyi")
|
||||
|
||||
sum := md5.Sum([]byte(("6key_web_fanyiifanyiweb8hc9s98e" + text)))
|
||||
query.Add("sign", hex.EncodeToString(sum[:])[:16])
|
||||
|
||||
requestURL.RawQuery = query.Encode()
|
||||
|
||||
formData := url.Values{}
|
||||
formData.Add("from", from)
|
||||
formData.Add("to", to)
|
||||
formData.Add("q", text)
|
||||
|
||||
response, err := http.PostForm(requestURL.String(), formData)
|
||||
if err != nil {
|
||||
return TranslationResult{}, err
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
|
||||
if response.StatusCode != 200 {
|
||||
return TranslationResult{}, fmt.Errorf("got status code %d from iCIBA", response.StatusCode)
|
||||
}
|
||||
|
||||
var responseJSON struct {
|
||||
Content struct {
|
||||
From string `json:"from"`
|
||||
Out string `json:"out"`
|
||||
} `json:"content"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(response.Body).Decode(&responseJSON); err != nil {
|
||||
return TranslationResult{}, err
|
||||
}
|
||||
|
||||
for code := range icibaLanguages {
|
||||
if code == responseJSON.Content.From {
|
||||
from = code
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if from == "" {
|
||||
return TranslationResult{TranslatedText: responseJSON.Content.Out},
|
||||
fmt.Errorf("language code \"%s\" is not in iCIBA's language list", responseJSON.Content.From)
|
||||
}
|
||||
|
||||
return TranslationResult{
|
||||
SourceLanguage: from,
|
||||
TranslatedText: responseJSON.Content.Out,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (_ *ICIBA) Tts(text, lang string) (string, error) { return "", nil }
|
169
engines/libretranslate.go
Normal file
169
engines/libretranslate.go
Normal file
@ -0,0 +1,169 @@
|
||||
package engines
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// LibreTranslate is an engine that interfaces with any
|
||||
// [LibreTranslate](https://github.com/LibreTranslate/LibreTranslate) instance.
|
||||
type LibreTranslate struct {
|
||||
// InstanceURL is the URL to a LibreTranslate instance, for example
|
||||
// "https://libretranslate.com".
|
||||
InstanceURL string
|
||||
// APIKey is the API key for the given instance. If empty, then no API
|
||||
// key will be sent along with requests to the instance.
|
||||
//
|
||||
// Some instances issue API keys to users so that they can have a
|
||||
// higher rate limit. See
|
||||
// https://github.com/LibreTranslate/LibreTranslate#manage-api-keys for
|
||||
// more information.
|
||||
APIKey string
|
||||
}
|
||||
|
||||
func (_ *LibreTranslate) DisplayName() string { return "LibreTranslate" }
|
||||
|
||||
func (e *LibreTranslate) getLangs() (Language, error) {
|
||||
response, err := http.Get(e.InstanceURL + "/languages")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
|
||||
if response.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("got status code %d from LibreTranslate API", response.StatusCode)
|
||||
}
|
||||
|
||||
var langsResponse []struct {
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(response.Body).Decode(&langsResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
langs := Language{}
|
||||
|
||||
for _, lang := range langsResponse {
|
||||
langs[lang.Code] = lang.Name
|
||||
}
|
||||
|
||||
return langs, nil
|
||||
}
|
||||
|
||||
func (e *LibreTranslate) SourceLanguages() (Language, error) { return e.getLangs() }
|
||||
|
||||
func (e *LibreTranslate) TargetLanguages() (Language, error) { return e.getLangs() }
|
||||
|
||||
func (e *LibreTranslate) Tts(text, lang string) (string, error) { return "", nil }
|
||||
|
||||
type libreDetectResponse []struct {
|
||||
Confidence float64 `json:"confidence"`
|
||||
LanguageCode string `json:"language"`
|
||||
}
|
||||
|
||||
func (e *LibreTranslate) detectLanguage(text string) (string, error) {
|
||||
formData := map[string]string{"q": text}
|
||||
|
||||
if e.APIKey != "" {
|
||||
formData["api_key"] = e.APIKey
|
||||
}
|
||||
|
||||
formDataJSON, err := json.Marshal(formData)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
response, err := http.Post(e.InstanceURL+"/detect", "application/json", bytes.NewBuffer(formDataJSON))
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
|
||||
if response.StatusCode != 200 {
|
||||
return "", fmt.Errorf("got status code %d from LibreTranslate API", response.StatusCode)
|
||||
}
|
||||
|
||||
var langs libreDetectResponse
|
||||
|
||||
if err := json.NewDecoder(response.Body).Decode(&langs); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
maxConfidenceLang := langs[0]
|
||||
|
||||
for _, lang := range langs[1:] {
|
||||
if lang.Confidence > maxConfidenceLang.Confidence {
|
||||
maxConfidenceLang = lang
|
||||
}
|
||||
}
|
||||
|
||||
engineLangs, err := e.getLangs()
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for code := range engineLangs {
|
||||
if code == maxConfidenceLang.LanguageCode {
|
||||
return code, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("language code \"%s\" is not in the instance's language list", maxConfidenceLang.LanguageCode)
|
||||
}
|
||||
|
||||
func (e *LibreTranslate) Translate(text string, from, to string) (TranslationResult, error) {
|
||||
formData := map[string]string{
|
||||
"q": text,
|
||||
"source": from,
|
||||
"target": to,
|
||||
}
|
||||
|
||||
if e.APIKey != "" {
|
||||
formData["api_key"] = e.APIKey
|
||||
}
|
||||
|
||||
formDataJSON, err := json.Marshal(formData)
|
||||
|
||||
if err != nil {
|
||||
return TranslationResult{}, err
|
||||
}
|
||||
|
||||
response, err := http.Post(e.InstanceURL+"/translate", "application/json", bytes.NewBuffer(formDataJSON))
|
||||
|
||||
if err != nil {
|
||||
return TranslationResult{}, err
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
|
||||
if response.StatusCode != 200 {
|
||||
return TranslationResult{}, fmt.Errorf("got status code %d from LibreTranslate API", response.StatusCode)
|
||||
}
|
||||
|
||||
var responseJSON struct {
|
||||
TranslatedText string `json:"translatedText"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(response.Body).Decode(&responseJSON); err != nil {
|
||||
return TranslationResult{}, err
|
||||
}
|
||||
|
||||
if r, err := e.detectLanguage(text); err == nil {
|
||||
from = r
|
||||
}
|
||||
|
||||
return TranslationResult{
|
||||
TranslatedText: responseJSON.TranslatedText,
|
||||
SourceLanguage: from,
|
||||
}, nil
|
||||
}
|
22
mai.1
Normal file
22
mai.1
Normal file
@ -0,0 +1,22 @@
|
||||
.Dd $Mdocdate$
|
||||
.Dt MAI 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mai
|
||||
.Nd An usable frontend for popular translation engines
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl f Ar config-file
|
||||
.Sh DESCRIPTION
|
||||
This project has been forked from the remains of the
|
||||
rewrite of the SimplyTranslate project, which is currently
|
||||
maintained by ManeraKai, but as time passed, this fork
|
||||
diverged wildly, and was renamed.
|
||||
Much to anyone's dismay, this was named after
|
||||
.Lk https://en.touhouwiki.net/wiki/Mai Mai from Mystic Square
|
||||
.Sh AUTHORS
|
||||
.An fattalion
|
||||
.An metalune
|
||||
.An ManeraKai
|
||||
.Sh MAINTAINERS
|
||||
.An Izuru Yakumo Aq Mt yakumo.izuru@chaotic.ninja
|
37
mai.ini.5
Normal file
37
mai.ini.5
Normal file
@ -0,0 +1,37 @@
|
||||
.Dd $Mdocdate$
|
||||
.Dt MAI.INI 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mai.ini
|
||||
.Nd Configuration file for Mai
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width 11n
|
||||
.It listen
|
||||
HTTP port for the server to listen.
|
||||
Default is "localhost:5000"
|
||||
.It rootdir
|
||||
Directory where the static resources are located.
|
||||
Default is "./static"
|
||||
.It tmplpath
|
||||
Directory where the templates are located.
|
||||
Default is "./views"
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width 11n
|
||||
.It Ev MAI_LIBRETRANSLATE_INSTANCE
|
||||
LibreTranslate instance to use.
|
||||
Default is ""
|
||||
.It Ev MAI_LIBRETRANSLATE_API
|
||||
LibreTranslate API key for the above setting.
|
||||
Default is ""
|
||||
.El
|
||||
.Sh FILES
|
||||
.Pa /usr/local/etc/mai/mai.ini
|
||||
.Sh SEE ALSO
|
||||
.Xr mai 1
|
||||
.Sh AUTHORS
|
||||
.An fattalion
|
||||
.An metalune
|
||||
.An ManeraKai
|
||||
.Sh MAINTAINERS
|
||||
.An Izuru Yakumo Aq Mt yakumo.izuru@chaotic.ninja
|
Loading…
x
Reference in New Issue
Block a user