diff --git a/README.md b/README.md index ba77b87..2319ff3 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/TODO.md b/TODO.md index d28b6d2..21f2004 100644 --- a/TODO.md +++ b/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 diff --git a/go.mod b/go.mod index df538a8..c69aadc 100644 --- a/go.mod +++ b/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 diff --git a/go.sum b/go.sum index 8e9a2c2..b03a421 100644 --- a/go.sum +++ b/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= diff --git a/pages/index.go b/pages/index.go index ba4cc45..4fd7ffe 100644 --- a/pages/index.go +++ b/pages/index.go @@ -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, }) } diff --git a/public/css/global.css b/public/css/global.css deleted file mode 100644 index f89f031..0000000 --- a/public/css/global.css +++ /dev/null @@ -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; -} diff --git a/public/css/style.css b/public/css/style.css new file mode 100644 index 0000000..a23a858 --- /dev/null +++ b/public/css/style.css @@ -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; +} diff --git a/serve/serve.go b/serve/serve.go index 639974a..fcc5ef0 100644 --- a/serve/serve.go +++ b/serve/serve.go @@ -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") diff --git a/views/error.html b/views/error.html deleted file mode 100644 index 7797974..0000000 --- a/views/error.html +++ /dev/null @@ -1,18 +0,0 @@ -{{ template "header" .}} -
-
-

Error

-

- Someone pushed to production. Just kidding, that's probably not what - happened. Here's the error: -

-
{{.error}}
-

- Think this is a bug? - Create an issue on Codeberg. -

-
-
-{{ template "footer" .}} diff --git a/views/footer.html b/views/footer.html index 2e94034..6181882 100644 --- a/views/footer.html +++ b/views/footer.html @@ -1,5 +1,14 @@ - - +
+ + diff --git a/views/header.html b/views/header.html index c67cd77..2977ce3 100644 --- a/views/header.html +++ b/views/header.html @@ -2,12 +2,27 @@ {{ if .title }} - {{ .title }} - Mozhi - {{ else }} + {{.title}} - Mozhi + {{else}} Mozhi - {{ end }} - - - + {{end}} + + + + + + + +
+ + +
+
diff --git a/views/index.html b/views/index.html index 232816c..d7a1479 100644 --- a/views/index.html +++ b/views/index.html @@ -1,28 +1,95 @@ {{template "header" .}} -
-

Mozhi

-

Translate

- -
- - - -
- -
- -

- -
-

Info

- {{ if eq .version "unknown, please build with Go 1.13+ or use Git"}} Mozhi - version: unknown {{ else }} Mozhi version: - {{ .version}} - {{ end }} -
- Fiber version: {{ .fiberversion}}, running on {{ .goversion}} + +
+ Translate with: {{.Engine}} + +
+ +

+
+ + + +
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+
+ + {{if .TtsFrom}} + + {{end}} +
+ +
+ + {{if .Translation.AutoDetect}} +

+ Detected Language: {{.Translation.AutoDetect}}{{end}} {{if .TtsTo}} + + {{end}} +

+
+
+
+ +
+
{{ template "footer" .}}