diff --git a/app/app.py b/app/app.py index 659409f..e1a7681 100644 --- a/app/app.py +++ b/app/app.py @@ -1,6 +1,7 @@ import os from functools import wraps +import pkg_resources from flask import Flask, abort, jsonify, render_template, request from flask_swagger import swagger from flask_swagger_ui import get_swaggerui_blueprint @@ -176,6 +177,7 @@ def create_app(args): frontendTimeout=args.frontend_timeout, api_keys=args.api_keys, web_version=os.environ.get("LT_WEB") is not None, + version=pkg_resources.require("LibreTranslate")[0].version ) @app.route("/javascript-licenses", methods=["GET"]) diff --git a/app/static/js/app.js b/app/static/js/app.js new file mode 100644 index 0000000..b957b08 --- /dev/null +++ b/app/static/js/app.js @@ -0,0 +1,325 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0 +// API host/endpoint +var BaseUrl = window.location.protocol + "//" + window.location.host; +var htmlRegex = /<(.*)>.*?|<(.*)\/>/; +document.addEventListener('DOMContentLoaded', function(){ + var sidenavElems = document.querySelectorAll('.sidenav'); + var sidenavInstances = M.Sidenav.init(sidenavElems); + + var app = new Vue({ + el: '#app', + delimiters: ['[[',']]'], + data: { + BaseUrl: BaseUrl, + loading: true, + error: "", + langs: [], + settings: {}, + sourceLang: "", + targetLang: "", + + loadingTranslation: false, + inputText: "", + inputTextareaHeight: 250, + savedTanslatedText: "", + translatedText: "", + output: "", + charactersLimit: -1, + + copyTextLabel: "Copy text", + + suggestions: false, + isSuggesting: false, + }, + mounted: function(){ + var self = this; + var requestSettings = new XMLHttpRequest(); + requestSettings.open('GET', BaseUrl + '/frontend/settings', true); + + requestSettings.onload = function() { + if (this.status >= 200 && this.status < 400) { + // Success! + self.settings = JSON.parse(this.response); + self.sourceLang = self.settings.language.source.code; + self.targetLang = self.settings.language.target.code; + self.charactersLimit = self.settings.charLimit; + self.suggestions = self.settings.suggestions; + }else { + self.error = "Cannot load /frontend/settings"; + self.loading = false; + } + }; + + requestSettings.onerror = function() { + self.error = "Error while calling /frontend/settings"; + self.loading = false; + }; + + requestSettings.send(); + + var requestLanguages = new XMLHttpRequest(); + requestLanguages.open('GET', BaseUrl + '/languages', true); + + requestLanguages.onload = function() { + if (this.status >= 200 && this.status < 400) { + // Success! + self.langs = JSON.parse(this.response); + self.langs.push({ name: 'Auto Detect (Experimental)', code: 'auto' }) + if (self.langs.length === 0){ + self.loading = false; + self.error = "No languages available. Did you install the models correctly?" + return; + } + + self.loading = false; + } else { + self.error = "Cannot load /languages"; + self.loading = false; + } + }; + + requestLanguages.onerror = function() { + self.error = "Error while calling /languages"; + self.loading = false; + }; + + requestLanguages.send(); + }, + updated: function(){ + M.FormSelect.init(this.$refs.sourceLangDropdown); + M.FormSelect.init(this.$refs.targetLangDropdown); + if (this.inputText === ""){ + this.$refs.inputTextarea.style.height = this.inputTextareaHeight + "px"; + this.$refs.translatedTextarea.style.height = this.inputTextareaHeight + "px"; + }else{ + this.$refs.inputTextarea.style.height = this.$refs.translatedTextarea.style.height = "1px"; + this.$refs.inputTextarea.style.height = Math.max(this.inputTextareaHeight, this.$refs.inputTextarea.scrollHeight + 32) + "px"; + this.$refs.translatedTextarea.style.height = Math.max(this.inputTextareaHeight, this.$refs.translatedTextarea.scrollHeight + 32) + "px"; + } + + if (this.charactersLimit !== -1 && this.inputText.length >= this.charactersLimit){ + this.inputText = this.inputText.substring(0, this.charactersLimit); + } + + // Update "selected" attribute (to overcome a vue.js limitation) + // but properly display checkmarks on supported browsers. + // Also change the