mirror of
https://github.com/LibreTranslate/LibreTranslate.git
synced 2025-05-24 01:12:56 -04:00
Improvement to under attack mode
This commit is contained in:
parent
fd0119bf70
commit
411b50178e
@ -365,7 +365,11 @@ def create_app(args):
|
|||||||
need_key = True
|
need_key = True
|
||||||
|
|
||||||
if args.under_attack and key_missing:
|
if args.under_attack and key_missing:
|
||||||
need_key = True
|
abort(make_response(jsonify({
|
||||||
|
'translatedText': secret.get_emoji(),
|
||||||
|
'alternatives': [],
|
||||||
|
'detectedLanguage': { 'confidence': 100, 'language': 'en' }
|
||||||
|
}), 200))
|
||||||
|
|
||||||
if need_key:
|
if need_key:
|
||||||
description = _("Please contact the server operator to get an API key")
|
description = _("Please contact the server operator to get an API key")
|
||||||
@ -473,7 +477,8 @@ def create_app(args):
|
|||||||
url_prefix=args.url_prefix,
|
url_prefix=args.url_prefix,
|
||||||
get_api_key_link=args.get_api_key_link,
|
get_api_key_link=args.get_api_key_link,
|
||||||
api_secret=api_secret,
|
api_secret=api_secret,
|
||||||
bogus_api_secret=bogus_api_secret), content_type='application/javascript; charset=utf-8')
|
bogus_api_secret=bogus_api_secret,
|
||||||
|
under_attack=args.under_attack), content_type='application/javascript; charset=utf-8')
|
||||||
|
|
||||||
if args.require_api_key_secret:
|
if args.require_api_key_secret:
|
||||||
response.headers['Last-Modified'] = http_date(datetime.now())
|
response.headers['Last-Modified'] = http_date(datetime.now())
|
||||||
|
@ -457,6 +457,10 @@ code[class*="language-"], pre[class*="language-"] {
|
|||||||
background-color: var(--sec-bg-color)
|
background-color: var(--sec-bg-color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea:disabled{
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 280px) {
|
@media (min-width: 280px) {
|
||||||
.btn-text {
|
.btn-text {
|
||||||
display: inline;
|
display: inline;
|
||||||
|
@ -60,7 +60,7 @@ class MemoryStorage(Storage):
|
|||||||
def set_str(self, key, value, ex=None):
|
def set_str(self, key, value, ex=None):
|
||||||
self.store[key] = {
|
self.store[key] = {
|
||||||
'value': value,
|
'value': value,
|
||||||
'ex': time.time() + ex
|
'ex': None if ex is None else time.time() + ex
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_str(self, key):
|
def get_str(self, key):
|
||||||
|
@ -17,6 +17,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
settings: {},
|
settings: {},
|
||||||
sourceLang: "",
|
sourceLang: "",
|
||||||
targetLang: "",
|
targetLang: "",
|
||||||
|
apiKey: localStorage.getItem("api_key") || "",
|
||||||
|
|
||||||
loadingTranslation: false,
|
loadingTranslation: false,
|
||||||
inputText: "",
|
inputText: "",
|
||||||
@ -45,6 +46,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
},
|
},
|
||||||
mounted: function() {
|
mounted: function() {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
window._vueApp = self;
|
||||||
self.$el.classList.add("loaded");
|
self.$el.classList.add("loaded");
|
||||||
|
|
||||||
const settingsRequest = new XMLHttpRequest();
|
const settingsRequest = new XMLHttpRequest();
|
||||||
@ -137,7 +139,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
' target: ' + this.$options.filters.escape(this.targetLang) + ',',
|
' target: ' + this.$options.filters.escape(this.targetLang) + ',',
|
||||||
' format: "' + (this.isHtml ? "html" : "text") + '",',
|
' format: "' + (this.isHtml ? "html" : "text") + '",',
|
||||||
' alternatives: 3,',
|
' alternatives: 3,',
|
||||||
' api_key: "' + (localStorage.getItem("api_key") || "") + '"',
|
' api_key: "' + this.apiKey + '"',
|
||||||
' }),',
|
' }),',
|
||||||
' headers: { "Content-Type": "application/json" }',
|
' headers: { "Content-Type": "application/json" }',
|
||||||
'});',
|
'});',
|
||||||
@ -164,6 +166,9 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
});
|
});
|
||||||
return tgtLangs;
|
return tgtLangs;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
disableInput: function(){
|
||||||
|
return {% if under_attack %}true{% else %}false{% endif %} && this.apiKey === "";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
@ -211,6 +216,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
history.pushState(null, '', newRelativePathQuery);
|
history.pushState(null, '', newRelativePathQuery);
|
||||||
},
|
},
|
||||||
handleInput: function(e){
|
handleInput: function(e){
|
||||||
|
if (this.disableInput) return;
|
||||||
this.closeSuggestTranslation(e)
|
this.closeSuggestTranslation(e)
|
||||||
|
|
||||||
this.updateQueryParam('source', this.sourceLang)
|
this.updateQueryParam('source', this.sourceLang)
|
||||||
@ -245,7 +251,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
data.append("target", self.targetLang);
|
data.append("target", self.targetLang);
|
||||||
data.append("format", self.isHtml ? "html" : "text");
|
data.append("format", self.isHtml ? "html" : "text");
|
||||||
data.append("alternatives", 3);
|
data.append("alternatives", 3);
|
||||||
data.append("api_key", localStorage.getItem("api_key") || "");
|
data.append("api_key", self.apiKey);
|
||||||
if (self.apiSecret) data.append("secret", atob(self.apiSecret));
|
if (self.apiSecret) data.append("secret", atob(self.apiSecret));
|
||||||
|
|
||||||
request.open('POST', BaseUrl + '/translate', true);
|
request.open('POST', BaseUrl + '/translate', true);
|
||||||
@ -329,7 +335,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
data.append("s", self.translatedText);
|
data.append("s", self.translatedText);
|
||||||
data.append("source", self.sourceLang);
|
data.append("source", self.sourceLang);
|
||||||
data.append("target", self.targetLang);
|
data.append("target", self.targetLang);
|
||||||
data.append("api_key", localStorage.getItem("api_key") || "");
|
data.append("api_key", self.apiKey);
|
||||||
|
|
||||||
request.open('POST', BaseUrl + '/suggest', true);
|
request.open('POST', BaseUrl + '/suggest', true);
|
||||||
request.onload = function() {
|
request.onload = function() {
|
||||||
@ -382,6 +388,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
},
|
},
|
||||||
translateFile: function(e) {
|
translateFile: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
if (this.disableInput) return;
|
||||||
|
|
||||||
let self = this;
|
let self = this;
|
||||||
let translateFileRequest = new XMLHttpRequest();
|
let translateFileRequest = new XMLHttpRequest();
|
||||||
@ -392,7 +399,7 @@ document.addEventListener('DOMContentLoaded', function(){
|
|||||||
data.append("file", this.inputFile);
|
data.append("file", this.inputFile);
|
||||||
data.append("source", this.sourceLang);
|
data.append("source", this.sourceLang);
|
||||||
data.append("target", this.targetLang);
|
data.append("target", this.targetLang);
|
||||||
data.append("api_key", localStorage.getItem("api_key") || "");
|
data.append("api_key", this.apiKey);
|
||||||
if (self.apiSecret) data.append("secret", self.apiSecret);
|
if (self.apiSecret) data.append("secret", self.apiSecret);
|
||||||
|
|
||||||
this.loadingFileTranslation = true
|
this.loadingFileTranslation = true
|
||||||
@ -537,6 +544,9 @@ function setApiKey(){
|
|||||||
if (newKey === null) newKey = "";
|
if (newKey === null) newKey = "";
|
||||||
|
|
||||||
localStorage.setItem("api_key", newKey);
|
localStorage.setItem("api_key", newKey);
|
||||||
|
if (window._vueApp){
|
||||||
|
window._vueApp.apiKey = newKey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color scheme handling
|
// Color scheme handling
|
||||||
|
@ -181,11 +181,11 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<h3 class="header center">{{ _h("Translation API") }}</h3>
|
<h3 class="header center">{{ _h("Translation API") }}</h3>
|
||||||
<div id="translation-type-btns" class="s12 center" v-if="filesTranslation === true">
|
<div id="translation-type-btns" class="s12 center" v-if="filesTranslation === true">
|
||||||
<button type="button" class="btn btn-switch-type" @click="switchType('text')" :class="{'active': translationType === 'text'}">
|
<button type="button" class="btn btn-switch-type" @click="switchType('text')" :class="{'active': translationType === 'text'}" :disabled="disableInput">
|
||||||
<i aria-hidden="true" class="material-icons">title</i>
|
<i aria-hidden="true" class="material-icons">title</i>
|
||||||
<span class="btn-text">{{ _h("Translate Text") }}</span>
|
<span class="btn-text">{{ _h("Translate Text") }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-switch-type" @click="switchType('files')" :class="{'active': translationType === 'files'}">
|
<button type="button" class="btn btn-switch-type" @click="switchType('files')" :class="{'active': translationType === 'files'}" :disabled="disableInput">
|
||||||
<i aria-hidden="true" class="material-icons">description</i>
|
<i aria-hidden="true" class="material-icons">description</i>
|
||||||
<span class="btn-text">{{ _h("Translate Files") }}</span>
|
<span class="btn-text">{{ _h("Translate Files") }}</span>
|
||||||
</button>
|
</button>
|
||||||
@ -220,7 +220,7 @@
|
|||||||
<label for="textarea1" class="sr-only">
|
<label for="textarea1" class="sr-only">
|
||||||
{{ _h("Text to translate") }}
|
{{ _h("Text to translate") }}
|
||||||
</label>
|
</label>
|
||||||
<textarea id="textarea1" :maxLength="charactersLimit" v-model="inputText" @input="handleInput" ref="inputTextarea" dir="auto"></textarea>
|
<textarea id="textarea1" :maxLength="charactersLimit" v-model="inputText" @input="handleInput" ref="inputTextarea" dir="auto" :disabled="disableInput"></textarea>
|
||||||
<button class="btn-delete-text" title="{{ _h('Delete text') }}" aria-label="{{ _h('Delete text') }}" @click="deleteText">
|
<button class="btn-delete-text" title="{{ _h('Delete text') }}" aria-label="{{ _h('Delete text') }}" @click="deleteText">
|
||||||
<i class="material-icons">close</i>
|
<i class="material-icons">close</i>
|
||||||
</button>
|
</button>
|
||||||
@ -232,7 +232,7 @@
|
|||||||
<label for="textarea2" class="sr-only">
|
<label for="textarea2" class="sr-only">
|
||||||
{{ _h("Translated text") }}
|
{{ _h("Translated text") }}
|
||||||
</label>
|
</label>
|
||||||
<textarea id="textarea2" v-model="translatedText" ref="translatedTextarea" dir="auto" v-bind:readonly="suggestions && !isSuggesting"></textarea>
|
<textarea id="textarea2" v-model="translatedText" ref="translatedTextarea" dir="auto" v-bind:readonly="suggestions && !isSuggesting" :disabled="disableInput"></textarea>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button v-if="suggestions && !loadingTranslation && inputText.length && !isSuggesting" class="btn-action" @click="suggestTranslation" aria-label="{{ _h('Suggest translation') }}">
|
<button v-if="suggestions && !loadingTranslation && inputText.length && !isSuggesting" class="btn-action" @click="suggestTranslation" aria-label="{{ _h('Suggest translation') }}">
|
||||||
<i class="material-icons">edit</i>
|
<i class="material-icons">edit</i>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user