Skip to content
This repository has been archived by the owner on Sep 26, 2023. It is now read-only.

Commit

Permalink
Add translations. (read README.md in /translations)
Browse files Browse the repository at this point in the history
  • Loading branch information
ramon-victor committed Jul 26, 2023
2 parents 8f48800 + 25cd3f2 commit 970895f
Show file tree
Hide file tree
Showing 44 changed files with 2,585 additions and 55 deletions.
2 changes: 2 additions & 0 deletions babel.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[python: **/server/.py]
[jinja2: **/client/html/**.html]
6 changes: 1 addition & 5 deletions client/css/checkbox.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

.checkbox span {
font-size: 0.875rem;
color: var(--colour-3);
color: var(--colour-2);
margin-left: 4px;
}

Expand Down Expand Up @@ -38,10 +38,6 @@
}

@media screen and (max-width: 990px) {
.checkbox span {
font-size: 0.75rem;
}

.checkbox label {
width: 25px;
height: 15px;
Expand Down
15 changes: 15 additions & 0 deletions client/css/select.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,18 @@ select {

appearance: none;
}

/* scrollbar */
select.dropdown::-webkit-scrollbar {
width: 4px;
padding: 8px 0px;
}

select.dropdown::-webkit-scrollbar-track {
background-color: #ffffff00;
}

select.dropdown::-webkit-scrollbar-thumb {
background-color: #555555;
border-radius: 10px;
}
44 changes: 44 additions & 0 deletions client/css/settings.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
.settings-container {
margin: 24px 0px 8px 0px;
justify-content: center;
}

.settings-container span {
font-size: 0.875rem;
margin: 0;
}

.settings-container label {
width: 24px;
height: 16px;
}

.settings-container .field {
justify-content: space-between;
}

.settings-container .checkbox input + label,
.settings-container .checkbox input:checked + label:after {
background: var(--colour-1);
}

.settings-container .checkbox input + label:after,
.settings-container .checkbox input:checked + label {
background: var(--colour-3);
}

.settings-container .checkbox label:after {
left: 2px;
width: 10px;
height: 10px;
}

.settings-container .checkbox input:checked + label:after {
left: calc(100% - 2px - 10px);
}

.settings-container .dropdown {
padding: 4px 8px;
font-size: 0.75rem;
}

2 changes: 1 addition & 1 deletion client/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
@import "./field.css";
@import "./select.css";
@import "./options.css";
@import "./theme-toggler.css";
@import "./settings.css";
@import "./message-input.css";
33 changes: 0 additions & 33 deletions client/css/theme-toggler.css

This file was deleted.

36 changes: 23 additions & 13 deletions client/html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,38 +39,47 @@
<div class="top">
<button class="button" onclick="new_conversation()">
<i class="fa-regular fa-plus"></i>
<span>New Conversation</span>
<span>{{_('New Conversation')}}</span>
</button>
<div class="spinner"></div>
</div>
<div class="sidebar-footer">
<button class="button" onclick="delete_conversations()">
<i class="fa-regular fa-trash"></i>
<span>Clear Conversations</span>
<span>{{_('Clear Conversations')}}</span>
</button>
<div class="field checkbox theme-toggler-container">
<input type="checkbox" id="theme-toggler" />
<label for="theme-toggler"></label>
<span>Dark Mode</span>
<div class="settings-container">
<div class="checkbox field">
<span>{{_('Dark Mode')}}</span>
<input type="checkbox" id="theme-toggler" />
<label for="theme-toggler"></label>
</div>
<div class="field">
<span>{{_('Language')}}</span>
<select
class="dropdown"
id="language"
onchange="changeLanguage(this.value)"></select>
</div>
</div>
<a class="info" href="https://github.com/ramonvc/gptfree-jailbreak-webui" target="_blank">
<i class="fa-brands fa-github"></i>
<span class="conversation-title"> Version: 0.0.10-Alpha </span>
<span class="conversation-title"> {{_('Version')}}: 0.1.0 </span>
</a>
</div>
</div>
<div class="conversation">
<div class="stop-generating stop-generating-hidden">
<button class="button" id="cancelButton">
<span>Stop Generating</span>
<span>{{_('Stop Generating')}}</span>
</button>
</div>
<div class="box" id="messages"></div>
<div class="user-input">
<div class="box input-box">
<textarea
id="message-input"
placeholder="Ask a question"
placeholder="{{_('Ask a question')}}"
cols="30"
rows="10"
style="white-space: pre-wrap"></textarea>
Expand All @@ -91,16 +100,16 @@
</div>
<div class="field">
<select class="dropdown" name="jailbreak" id="jailbreak">
<option value="default" selected>Default</option>
<option value="gpt-dan-11.0">DAN</option>
<option value="gpt-evil">Evil</option>
<option value="default" selected>{{_('Default')}}</option>
<option value="gpt-dan-11.0">{{_('DAN')}}</option>
<option value="gpt-evil">{{_('Evil')}}</option>
</select>
</div>
</div>
<div class="field checkbox">
<input type="checkbox" id="switch" />
<label for="switch"></label>
<span>Web Access</span>
<span>{{_('Web Access')}}</span>
</div>
</div>
</div>
Expand All @@ -121,5 +130,6 @@
<script src="{{ url_for('bp.static', filename='js/highlightjs-copy.min.js') }}"></script>
<script src="{{ url_for('bp.static', filename='js/theme-toggler.js') }}"></script>
<script src="{{ url_for('bp.static', filename='js/sidebar-toggler.js') }}"></script>
<script src="{{ url_for('bp.static', filename='js/change-language.js') }}"></script>
</body>
</html>
47 changes: 47 additions & 0 deletions client/js/change-language.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
document.addEventListener('DOMContentLoaded', fetchLanguages);

async function fetchLanguages() {
try {
const [languagesResponse, currentLanguageResponse] = await Promise.all([
fetch('/get-languages'),
fetch('/get-locale')
]);

const languages = await languagesResponse.json();
const currentLanguage = await currentLanguageResponse.text();

const languageSelect = document.getElementById('language');
languages.forEach(lang => {
const option = document.createElement('option');
option.value = lang;
option.textContent = lang;
languageSelect.appendChild(option);
});

const savedLanguage = localStorage.getItem("language") || currentLanguage;
setLanguageOnPageLoad(savedLanguage);
} catch (error) {
console.error("Failed to fetch languages or current language");
}
}

function setLanguageOnPageLoad(language) {
document.getElementById("language").value = language;
}

function changeLanguage(lang) {
fetch("/change-language", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ language: lang }),
}).then((response) => {
if (response.ok) {
localStorage.setItem("language", lang);
location.reload();
} else {
console.error("Failed to change language");
}
});
}
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ curl_cffi
aiohttp
flask
flask_cors
flask-babel
streamlit
selenium
fake-useragent
Expand Down
13 changes: 11 additions & 2 deletions run.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import secrets

from server.bp import bp
from server.website import Website
from server.backend import Backend_Api
from server.babel import create_babel
from json import load
from flask import Flask

Expand All @@ -11,6 +14,13 @@
site_config = config['site_config']
url_prefix = config.pop('url_prefix')

# Create the app
app = Flask(__name__)
app.secret_key = secrets.token_hex(16)

# Set up Babel
create_babel(app)

# Set up the website routes
site = Website(bp, url_prefix)
for route in site.routes:
Expand All @@ -29,8 +39,7 @@
methods=backend_api.routes[route]['methods'],
)

# Create the app and register the blueprint
app = Flask(__name__)
# Register the blueprint
app.register_blueprint(bp, url_prefix=url_prefix)

# Run the Flask server
Expand Down
48 changes: 48 additions & 0 deletions server/babel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os
import subprocess
from flask import request, session, jsonify
from flask_babel import Babel


def get_languages_from_dir(directory):
"""Return a list of directory names in the given directory."""
return [name for name in os.listdir(directory)
if os.path.isdir(os.path.join(directory, name))]


BABEL_DEFAULT_LOCALE = 'en_US'
BABEL_LANGUAGES = get_languages_from_dir('translations')


def create_babel(app):
"""Create and initialize a Babel instance with the given Flask app."""
babel = Babel(app)
app.config['BABEL_DEFAULT_LOCALE'] = BABEL_DEFAULT_LOCALE
app.config['BABEL_LANGUAGES'] = BABEL_LANGUAGES

babel.init_app(app, locale_selector=get_locale)
compile_translations()


def get_locale():
"""Get the user's locale from the session or the request's accepted languages."""
return session.get('language') or request.accept_languages.best_match(BABEL_LANGUAGES)


def get_languages():
"""Return a list of available languages in JSON format."""
return jsonify(BABEL_LANGUAGES)


def compile_translations():
"""Compile the translation files."""
result = subprocess.run(
['pybabel', 'compile', '-d', 'translations'],
stdout=subprocess.PIPE,
)

if result.returncode != 0:
raise Exception(
f'Compiling translations failed:\n{result.stdout.decode()}')

print('Translations compiled successfully')
28 changes: 27 additions & 1 deletion server/website.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from flask import render_template, redirect, url_for
from flask import render_template, redirect, url_for, request, session
from flask_babel import refresh
from time import time
from os import urandom
from server.babel import get_locale, get_languages


class Website:
Expand All @@ -19,6 +21,18 @@ def __init__(self, bp, url_prefix) -> None:
'/chat/<conversation_id>': {
'function': self._chat,
'methods': ['GET', 'POST']
},
'/change-language': {
'function': self.change_language,
'methods': ['POST']
},
'/get-locale': {
'function': self.get_locale,
'methods': ['GET']
},
'/get-languages': {
'function': self.get_languages,
'methods': ['GET']
}
}

Expand All @@ -30,3 +44,15 @@ def _chat(self, conversation_id):

def _index(self):
return render_template('index.html', chat_id=f'{urandom(4).hex()}-{urandom(2).hex()}-{urandom(2).hex()}-{urandom(2).hex()}-{hex(int(time() * 1000))[2:]}', url_prefix=self.url_prefix)

def change_language(self):
data = request.get_json()
session['language'] = data.get('language')
refresh()
return '', 204

def get_locale(self):
return get_locale()

def get_languages(self):
return get_languages()
Loading

0 comments on commit 970895f

Please sign in to comment.