webui finally
This commit is contained in:
parent
566eb69743
commit
8403dfe227
12 changed files with 371 additions and 448 deletions
|
@ -76,3 +76,9 @@ These envvars turn off/on engines. By default all of them are enabled.
|
|||
|
||||
## Etymology
|
||||
Mozhi is the word in Tamil for language. Simple as that :P
|
||||
|
||||
## Credits
|
||||
- [Arya](https://aryak.me): creator
|
||||
- [Midou36o](https://midou.dev): made the logo
|
||||
- [Missuo](https://github.com/missuo): making gDeepLX that does the hard part of making DeepL work
|
||||
- [SimplyTranslate](https://codeberg.org/simpleweb/simplytranslate): Inspiration and base code for the webui
|
||||
|
|
5
TODO.md
5
TODO.md
|
@ -1,5 +1,8 @@
|
|||
# TODO
|
||||
- Create a web interface
|
||||
- Support disabling engines with Web interface
|
||||
- Make LibreTranslate work with web interface
|
||||
- Write an about page for web
|
||||
- Make detectlanguage swap the text as well
|
||||
- Interactive/Step-by-step CLI
|
||||
- Ability for user to choose engines they want to use
|
||||
- Proper Error handling for requests.go
|
||||
|
|
2
go.mod
2
go.mod
|
@ -5,7 +5,7 @@ go 1.21.0
|
|||
replace github.com/OwO-Network/gdeeplx => github.com/gi-yt/gdeeplx v0.0.0-20230817133036-0eb71706cd51
|
||||
|
||||
require (
|
||||
codeberg.org/aryak/libmozhi v0.0.0-20230909133311-5b21e2215c4c
|
||||
codeberg.org/aryak/libmozhi v0.0.0-20230909142818-70619214b1ea
|
||||
github.com/gofiber/fiber/v2 v2.49.1
|
||||
github.com/gofiber/swagger v0.1.13
|
||||
github.com/gofiber/template v1.8.0
|
||||
|
|
2
go.sum
2
go.sum
|
@ -47,6 +47,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
|
|||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
codeberg.org/aryak/libmozhi v0.0.0-20230909133311-5b21e2215c4c h1:lnG0+NunYw4x6TUl00MQvucNTypqK6skms9MsKx0P2E=
|
||||
codeberg.org/aryak/libmozhi v0.0.0-20230909133311-5b21e2215c4c/go.mod h1:DOxFxtSCKbs3sfKLxDwho9RFqkZy1opa67/c9v+/G+I=
|
||||
codeberg.org/aryak/libmozhi v0.0.0-20230909142818-70619214b1ea h1:WqElyz20JDxXiQveo2TkNP2q0zyEK3i9VP5P6p7Dh7o=
|
||||
codeberg.org/aryak/libmozhi v0.0.0-20230909142818-70619214b1ea/go.mod h1:DOxFxtSCKbs3sfKLxDwho9RFqkZy1opa67/c9v+/G+I=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
|
|
|
@ -1,26 +1,66 @@
|
|||
package pages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"codeberg.org/aryak/libmozhi"
|
||||
)
|
||||
|
||||
func HandleIndex(c *fiber.Ctx) error {
|
||||
// Check if all required queries are present
|
||||
m := c.Queries()
|
||||
sl, _ := m["sl"]
|
||||
tl, _ := m["tl"]
|
||||
engine, _ := m["engine"]
|
||||
text, _ := m["text"]
|
||||
if sl != "" && tl != "" && engine != "" && text != "" {
|
||||
fmt.Println("Work")
|
||||
engines := []string{"google", "deepl", "duckduckgo", "libretranslate", "mymemory", "reverso", "watson", "yandex"}
|
||||
var engine string
|
||||
var originalText string
|
||||
if c.Query("engine") == "" {
|
||||
engine = "google"
|
||||
}
|
||||
if c.Query("engine") != "" {
|
||||
for _, name := range engines {
|
||||
if c.Query("engine") == name {
|
||||
engine = c.Query("engine")
|
||||
}
|
||||
}
|
||||
if engine == "" {
|
||||
engine = "google"
|
||||
}
|
||||
}
|
||||
|
||||
sourceLanguages, err1 := libmozhi.LangList(engine, "sl")
|
||||
targetLanguages, err2 := libmozhi.LangList(engine, "tl")
|
||||
if err1 != nil || err2 != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err1.Error()+err2.Error())
|
||||
}
|
||||
|
||||
originalText = c.Query("text")
|
||||
to := c.Query("to")
|
||||
from := c.Query("from")
|
||||
var translation libmozhi.LangOut
|
||||
var tlerr error
|
||||
var ttsFrom string
|
||||
var ttsTo string
|
||||
if engine != "" && originalText != "" && from != "" && to != "" {
|
||||
translation, tlerr = libmozhi.Translate(engine, to, from, originalText)
|
||||
if tlerr != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, tlerr.Error())
|
||||
}
|
||||
if engine == "google" || engine == "reverso" {
|
||||
if from == "auto" {
|
||||
//ttsFrom = "/api/tts?lang="+translation.AutoDetect+"&engine="+engine+"&text="+originalText
|
||||
ttsFrom = ""
|
||||
} else {
|
||||
ttsFrom = "/api/tts?lang="+from+"&engine="+engine+"&text="+originalText
|
||||
}
|
||||
ttsTo = "/api/tts?lang="+to+"&engine="+engine+"&text="+translation.OutputText
|
||||
}
|
||||
}
|
||||
return c.Render("index", fiber.Map{
|
||||
"host": c.Hostname(),
|
||||
"fiberversion": fiber.Version,
|
||||
"goversion": runtime.Version(),
|
||||
"Engine": engine,
|
||||
"enginesNames": engines,
|
||||
"SourceLanguages": sourceLanguages,
|
||||
"TargetLanguages": targetLanguages,
|
||||
"OriginalText": originalText,
|
||||
"Translation": translation,
|
||||
"From": from,
|
||||
"To": to,
|
||||
"TtsFrom": ttsFrom,
|
||||
"TtsTo": ttsTo,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,380 +0,0 @@
|
|||
/* god bless you */
|
||||
|
||||
:root {
|
||||
--text: #fff;
|
||||
--background: #252525;
|
||||
--secondary-background: #353535;
|
||||
--background-darker: #151515;
|
||||
--accent: #00b7c3;
|
||||
--yellow: #8b8000;
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui,
|
||||
helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial,
|
||||
sans-serif;
|
||||
color: var(--text);
|
||||
background-color: var(--background-darker);
|
||||
transition: ease-in-out 0.25s;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 8px;
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
main {
|
||||
margin: 0 24vw;
|
||||
}
|
||||
|
||||
.margin-ow {
|
||||
margin: 0 12vw;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow: scroll;
|
||||
background: var(--secondary-background);
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
#wrap {
|
||||
display: flex;
|
||||
}
|
||||
.navbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
padding: 8px;
|
||||
|
||||
margin-bottom: 8px;
|
||||
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
.index-gh {
|
||||
background: var(--background);
|
||||
color: var(--text);
|
||||
padding: 4px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
transition: ease-in-out 0.25s;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.navbar-slogan:hover {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 5px;
|
||||
}
|
||||
|
||||
.brand:hover {
|
||||
color: var(--text);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: var(--background);
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui,
|
||||
helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial,
|
||||
sans-serif;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--text);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 5px;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.setup-notice {
|
||||
background-color: var(--yellow);
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui,
|
||||
helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial,
|
||||
sans-serif;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.setup-notice > a {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 5px;
|
||||
}
|
||||
|
||||
.setup-notice > a:hover {
|
||||
color: var(--text);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* URI: /explore */
|
||||
|
||||
.explore-card,
|
||||
.user-repo-card {
|
||||
background-color: var(--background);
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
margin: 8px 0 8px 0;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
white-space: wrap;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
|
||||
transition: ease-in-out 0.25s;
|
||||
}
|
||||
|
||||
.explore-card:hover,
|
||||
.user-repo-card:hover {
|
||||
background-color: var(--secondary-background);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
/* URI: /:user */
|
||||
|
||||
.user-profile {
|
||||
background-color: var(--background);
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
margin: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-profile h1 {
|
||||
color: var(--accent);
|
||||
margin: 4px;
|
||||
word-wrap: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.user-profile h2 {
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.user-profile p {
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.user-profile img {
|
||||
border: 4px solid var(--accent);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.user-bio,
|
||||
.user-readme {
|
||||
background-color: var(--background);
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.user-bio-text,
|
||||
.user-readme-text {
|
||||
background-color: var(--background-darker);
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.user-readme-text {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.social-links {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.user-repo-card {
|
||||
background-color: var(--background-darker);
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
margin: 8px 0 8px 0;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
white-space: wrap;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
transition: ease-in-out 0.25s;
|
||||
}
|
||||
|
||||
.user-repo-card > p {
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.user-repo-card:hover {
|
||||
background-color: var(--secondary-background);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.lang-bar:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.lang-bar {
|
||||
width: 100%;
|
||||
display: inherit;
|
||||
height: 10px;
|
||||
border-radius:4px;
|
||||
overflow: hidden; /* To force the corners to be round. */
|
||||
user-select: none; /* Prevent the selection */
|
||||
-webkit-user-select: none; /* Safari specific fix. */
|
||||
}
|
||||
|
||||
/* URI: /:user/:repo */
|
||||
.button {
|
||||
background-color: var(--background);
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
margin: 8px;
|
||||
color: var(--text);
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background-color: var(--secondary-background);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.button-parent {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.file-list {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.file-u-list {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
/* URI: /file/:user/:repo/:file */
|
||||
.user-readme pre {
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
/*white-space: pre-wrap;*/
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.user-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.secondary {
|
||||
background-color: var(--secondary-background);
|
||||
}
|
||||
|
||||
/* Overwrite */
|
||||
|
||||
.no-margin {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.no-padding {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: right;
|
||||
display: grid;
|
||||
flex: none;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
@media screen and (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--text: #000;
|
||||
--background: #ececec;
|
||||
--secondary-background: #f5f5f5;
|
||||
--background-darker: #dddddd;
|
||||
--accent: #005ec3;
|
||||
--yellow: #f5f5a5;
|
||||
color-scheme: light;
|
||||
}
|
||||
a {
|
||||
color: black;
|
||||
}
|
||||
a:hover {
|
||||
color: #005ec3;
|
||||
}
|
||||
.explore-card {
|
||||
background-color: var(--background);
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
main {
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
#wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: none;
|
||||
display: inline-grid;
|
||||
}
|
||||
|
||||
.navbar-slogan {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navbarImg {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.explore-card {
|
||||
margin-left: 0;
|
||||
margin-bottom: 8px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.social-links {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
.cl {
|
||||
padding-left: 8px;
|
||||
}
|
171
public/css/style.css
Normal file
171
public/css/style.css
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*General theming*/
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
margin: 20px auto;
|
||||
max-width: 1100px;
|
||||
line-height: 1.5em;
|
||||
font-size: 1.1em;
|
||||
background-color: #222;
|
||||
color: #f8f9fa;
|
||||
padding: 0 10px;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
flex-wrap: wrap;
|
||||
|
||||
border-bottom: 1px solid #b2b2b2;
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 95%;
|
||||
border-top: 1px solid #b2b2b2;
|
||||
}
|
||||
footer p {
|
||||
margin: 0.2em 0 0.2em 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3c67ff;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
nav {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
gap: 1rem;
|
||||
}
|
||||
nav li {
|
||||
display: inline-block no;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.navlogo {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
/* Theming for buttons and text areas*/
|
||||
textarea {
|
||||
width: 100%;
|
||||
font-size: 1rem;
|
||||
padding: 4px;
|
||||
border: 2px solid #888888;
|
||||
background-color: #222;
|
||||
border-color: #9d9d9d;
|
||||
color: #f8f9fa;
|
||||
}
|
||||
textarea:focus {
|
||||
border-color: #e5ebff;
|
||||
outline: 1px solid #e5ebff;
|
||||
}
|
||||
|
||||
select {
|
||||
display: flex;
|
||||
padding: 4px 8px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex: 1 0 0;
|
||||
border-right: none;
|
||||
border-bottom: none;
|
||||
border-top: none;
|
||||
border-radius: 4px;
|
||||
border-left: 2px solid #3c67ff;
|
||||
/* Accent shadow */
|
||||
box-shadow: 2px 2px 0px 0px rgba(60, 103, 255, 0.25);
|
||||
color: #b2b2b2;
|
||||
background-color: #2f2f2f;
|
||||
}
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
padding: 4px 8px;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
background: #3c67ff;
|
||||
}
|
||||
button:hover {
|
||||
box-shadow: 5px 5px 0px 0px rgba(60, 103, 255, 0.25);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Spacing stuff */
|
||||
.wrap {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
.wrap.languages {
|
||||
flex-wrap: nowrap;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.language {
|
||||
margin: 0px 10px;
|
||||
}
|
||||
.item {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
}
|
||||
.item-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
width: 450px;
|
||||
margin: 5px 10px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
/* CSS for the custom engine selector */
|
||||
.custom-select {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.selected-option {
|
||||
display: block;
|
||||
padding: 7px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
color: #f8f9fa;
|
||||
}
|
||||
|
||||
.options {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #222;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.options li {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.options li:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.custom-select:hover .options {
|
||||
display: block;
|
||||
}
|
|
@ -85,10 +85,18 @@ func Serve(port string) {
|
|||
})
|
||||
|
||||
app.Get("/", pages.HandleIndex)
|
||||
app.Get("/switchlanguages", func(c *fiber.Ctx) error {
|
||||
engine := c.Query("engine")
|
||||
from := c.Query("from")
|
||||
to := c.Query("to")
|
||||
text := c.Query("text")
|
||||
return c.Redirect("/?engine="+engine+"&from="+to+"&to="+from+"&text="+text+"&redirected=true", 301)
|
||||
})
|
||||
app.Static("/css", "./public/css", staticConfig)
|
||||
app.Static("/robots.txt", "./public/robots.txt", staticConfig)
|
||||
app.Static("/favicon.ico", "./public/assets/favicon.ico", staticConfig)
|
||||
app.Static("/mozhi.svg", "./public/assets/mozhi.svg", staticConfig)
|
||||
app.Static("/mozhi.png", "./public/assets/mozhi.png", staticConfig)
|
||||
// app.Get("/about", pages.HandleAbout)
|
||||
|
||||
api := app.Group("/api")
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
{{ template "header" .}}
|
||||
<main>
|
||||
<div class="center">
|
||||
<h1 style="color: red">Error</h1>
|
||||
<h2>
|
||||
Someone pushed to production. Just kidding, that's probably not what
|
||||
happened. Here's the error:
|
||||
</h2>
|
||||
<pre class="error">{{.error}}</pre>
|
||||
<h3>
|
||||
Think this is a bug?
|
||||
<a href="https://codeberg.org/aryak/mozhi/issues" target="_blank"
|
||||
>Create an issue on Codeberg.</a
|
||||
>
|
||||
</h3>
|
||||
</div>
|
||||
</main>
|
||||
{{ template "footer" .}}
|
|
@ -1,5 +1,14 @@
|
|||
<footer class="center">
|
||||
<a href="https://codeberg.org/aryak/mozhi">Codeberg</a> | <a href="/instance">About Instance</a>
|
||||
</footer>
|
||||
</body>
|
||||
<br />
|
||||
<footer style="text-align: center">
|
||||
<br />
|
||||
<p>
|
||||
Copyright 2023 <a href="https://aryak.me">Arya Kiran</a> and other
|
||||
contributors
|
||||
</p>
|
||||
<p>
|
||||
View Source Code on
|
||||
<a href="https://codeberg.org/aryak/mozhi">Codeberg</a>
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -2,12 +2,27 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
{{ if .title }}
|
||||
<title>{{ .title }} - Mozhi</title>
|
||||
{{ else }}
|
||||
<title>{{.title}} - Mozhi</title>
|
||||
{{else}}
|
||||
<title>Mozhi</title>
|
||||
{{ end }}
|
||||
<link rel="stylesheet" href="/css/global.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||||
{{end}}
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Mozhi is an alternative-frontend for many translation engines."
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="referrer" content="no-referrer" />
|
||||
<link rel="stylesheet" href="/css/style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<a href="/"><img src="/mozhi.png" alt="Mozhi Logo" class="navlogo" /></a>
|
||||
<nav>
|
||||
<a href="/about">About</a>
|
||||
<a href="/api/swagger">API</a>
|
||||
</nav>
|
||||
</header>
|
||||
<br />
|
||||
|
|
115
views/index.html
115
views/index.html
|
@ -1,28 +1,95 @@
|
|||
{{template "header" .}}
|
||||
|
||||
<main>
|
||||
<h2>Mozhi</h2>
|
||||
<h3>Translate</h3>
|
||||
|
||||
<form action="/" method="get">
|
||||
<label for="textin">Text To Translate:</label>
|
||||
<textarea id="textin" name="textin" rows="4" cols="50"></textarea>
|
||||
<input type="checkbox" name="vehicle1" value="Bike">
|
||||
<label for="vehicle1"> I have a bike</label><br>
|
||||
<input type="checkbox" name="vehicle2" value="Car">
|
||||
<label for="vehicle2"> I have a car</label><br>
|
||||
<input type="checkbox" name="vehicle3" value="Boat" checked>
|
||||
<label for="vehicle3"> I have a boat</label><br><br>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
<h3>Info</h3>
|
||||
{{ if eq .version "unknown, please build with Go 1.13+ or use Git"}} Mozhi
|
||||
version: <code>unknown</code> {{ else }} Mozhi version:
|
||||
<a href="https://codeberg.org/aryak/mozhi/commit/{{ .version}}"
|
||||
><code>{{ .version}}</code></a
|
||||
>
|
||||
{{ end }}
|
||||
<br />
|
||||
Fiber version: {{ .fiberversion}}, running on {{ .goversion}}
|
||||
<!-- Need to do this custom selector thingy since <select> cant submit on click -->
|
||||
<div class="custom-select">
|
||||
Translate with: <a href="#" class="selected-option">{{.Engine}}</a>
|
||||
<ul class="options">
|
||||
{{range .enginesNames}}
|
||||
<a href="/?engine={{.}}"><li>{{.}}</li></a>
|
||||
{{end}}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<br /><br />
|
||||
<form action="/" method="GET" id="translation-form">
|
||||
<!-- This hidden input is so that the engine gets sent in the GET request even though its not declared here -->
|
||||
<input name="engine" value="{{.Engine}}" type="hidden" />
|
||||
|
||||
<div class="wrap languages">
|
||||
<div class="language">
|
||||
<select name="from" aria-label="Source language">
|
||||
{{range $key, $value := .SourceLanguages}}
|
||||
<option value="{{ .Id }}" {{if eq $.From .Id}}selected{{end}}>
|
||||
{{ .Name }}
|
||||
</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="switch_languages">
|
||||
<button
|
||||
id="switchbutton"
|
||||
aria-label="Switch languages"
|
||||
formaction="/switchlanguages?engine={{ .Engine }}"
|
||||
type="submit"
|
||||
>
|
||||
<->
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="language">
|
||||
<select name="to" aria-label="Target language">
|
||||
{{range $key, $value := .TargetLanguages}}
|
||||
<option value="{{ .Id }}" {{if eq $.To .Id}}selected{{end}}>
|
||||
{{ .Name }}
|
||||
</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wrap">
|
||||
<div class="item-wrapper">
|
||||
<textarea
|
||||
autofocus
|
||||
class="item"
|
||||
id="input"
|
||||
name="text"
|
||||
dir="auto"
|
||||
placeholder="Enter Text Here"
|
||||
>
|
||||
{{ .OriginalText }}</textarea
|
||||
>
|
||||
{{if .TtsFrom}}
|
||||
<audio controls>
|
||||
<source type="audio/mpeg" src="{{ .TtsFrom }}" />
|
||||
</audio>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<div class="item-wrapper">
|
||||
<textarea
|
||||
id="output"
|
||||
class="translation item"
|
||||
dir="auto"
|
||||
placeholder="Translation"
|
||||
readonly
|
||||
>
|
||||
{{.Translation.OutputText}}</textarea
|
||||
>
|
||||
{{if .Translation.AutoDetect}}
|
||||
<p>
|
||||
Detected Language: {{.Translation.AutoDetect}}{{end}} {{if .TtsTo}}
|
||||
<audio controls>
|
||||
<source type="audio/mpeg" src="{{ .TtsTo }}" />
|
||||
</audio>
|
||||
{{end}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: center">
|
||||
<button type="submit">Translate with {{ .Engine }}!</button>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
{{ template "footer" .}}
|
||||
|
|
Loading…
Reference in a new issue