Spaces:
Sleeping
Sleeping
Upload 15 files
Browse files- README.en.md +6 -0
- __init__.py +0 -0
- adibideak.py +7 -0
- app.py +123 -0
- gr_app.py +106 -0
- gr_requirements.txt +9 -0
- helsinki_models.py +26 -0
- images/banner.jpg +0 -0
- iso639_wrapper.py +60 -0
- language_detection.py +13 -0
- language_directions.py +71 -0
- requirements.txt +9 -0
- styles/style.css +30 -0
- styles/w3.css +250 -0
- utils.py +18 -0
README.en.md
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Scope of project
|
2 |
+
1. Enable multiple languages translate based on helsinki models.✅
|
3 |
+
2. Enable auto detect langauge ✅
|
4 |
+
3. Show error message instead of gradio error ✅
|
5 |
+
4. Add examples ✅
|
6 |
+
5. Auto detect on text change ✅
|
__init__.py
ADDED
File without changes
|
adibideak.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
adibide_esaldiak = [
|
2 |
+
"Zer da benetakoa? galdetu zion Untxiak egun batean.",
|
3 |
+
"¿Qué es real? preguntó el Conejo un día.",
|
4 |
+
"Что реально? спросил кролик однажды.",
|
5 |
+
"Was ist real? fragte das Kaninchen eines Tages.",
|
6 |
+
"What is real? asked the Rabbit one day."
|
7 |
+
]
|
app.py
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
@author: idoia lerchundi
|
3 |
+
"""
|
4 |
+
import streamlit as st
|
5 |
+
from language_directions import *
|
6 |
+
from transformers import pipeline
|
7 |
+
from adibideak import adibide_esaldiak
|
8 |
+
from PIL import Image
|
9 |
+
|
10 |
+
|
11 |
+
def local_css(file_name):
|
12 |
+
with open(file_name) as f:
|
13 |
+
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
|
14 |
+
|
15 |
+
st.set_page_config(
|
16 |
+
page_title="Streamlit iCodeIdoia",
|
17 |
+
)
|
18 |
+
|
19 |
+
st.image("images/banner.jpg")
|
20 |
+
|
21 |
+
# ---- LOAD
|
22 |
+
local_css("styles/style.css")
|
23 |
+
|
24 |
+
source_lang_dict = get_all_source_languages()
|
25 |
+
target_lang_dict = {}
|
26 |
+
source_languages = source_lang_dict.keys()
|
27 |
+
|
28 |
+
def get_auto_detect_source_dropdown(input_text):
|
29 |
+
source, _ = auto_detect_language_code(input_text)
|
30 |
+
language_name = get_name_from_iso_code(source)
|
31 |
+
source_dropdown_text = "Detected - " + language_name
|
32 |
+
update_source_languages_dict(source_lang_dict, source_dropdown_text)
|
33 |
+
source_language_dropdown = st.selectbox(choices=source_languages,
|
34 |
+
value=source_dropdown_text,
|
35 |
+
label="Input Language")
|
36 |
+
|
37 |
+
########################
|
38 |
+
return source_language_dropdown, language_name
|
39 |
+
|
40 |
+
def get_target_dropdown(source_language_name, input_text):
|
41 |
+
global target_lang_dict
|
42 |
+
target_lang_dict, source_language = get_target_languages(source_lang_dict[source_language_name], input_text)
|
43 |
+
target_languages = list(target_lang_dict.keys())
|
44 |
+
default_target_value = None
|
45 |
+
if "English" in target_languages or "english" in target_languages:
|
46 |
+
default_target_value = "English"
|
47 |
+
else:
|
48 |
+
default_target_value = target_languages[0]
|
49 |
+
target_dropdown = st.selectbox(choices=target_languages,
|
50 |
+
value=default_target_value,
|
51 |
+
label="Output Language")
|
52 |
+
return target_dropdown
|
53 |
+
|
54 |
+
def get_dropdown_value(dropdown):
|
55 |
+
if isinstance(dropdown, st.selectbox):
|
56 |
+
dropdown_value = dropdown.constructor_args.get('value')
|
57 |
+
elif isinstance(dropdown, str):
|
58 |
+
dropdown_value = dropdown
|
59 |
+
return dropdown_value
|
60 |
+
|
61 |
+
def get_dropdowns(source_dropdown, input_text):
|
62 |
+
source_language_name = get_dropdown_value(source_dropdown)
|
63 |
+
if input_text and source_language_name == "Detect" or source_language_name.startswith("Detected"):
|
64 |
+
source_dropdown, source_language_name = get_auto_detect_source_dropdown(input_text)
|
65 |
+
target_dropdown = get_target_dropdown(source_language_name=source_language_name,
|
66 |
+
input_text=input_text)
|
67 |
+
return source_dropdown, target_dropdown
|
68 |
+
|
69 |
+
def input_changed(source_language_dropdown, input_text=""):
|
70 |
+
return get_dropdowns(source_dropdown=source_language_dropdown,
|
71 |
+
input_text=input_text)
|
72 |
+
|
73 |
+
def translate(input_text, source, target):
|
74 |
+
source_readable = source
|
75 |
+
if source == "Detect" or source.startswith("Detected"):
|
76 |
+
source, _ = auto_detect_language_code(input_text)
|
77 |
+
if source in source_lang_dict.keys():
|
78 |
+
source = source_lang_dict[source]
|
79 |
+
target_lang_dict, _ = get_target_languages(source)
|
80 |
+
try:
|
81 |
+
target = target_lang_dict[target]
|
82 |
+
model = f"Helsinki-NLP/opus-mt-{source}-{target}"
|
83 |
+
pipe = pipeline("translation", model=model)
|
84 |
+
translation = pipe(input_text)
|
85 |
+
return translation[0]['translation_text']
|
86 |
+
except KeyError:
|
87 |
+
return f"Error: Translation from {source_readable} to {target} is not supported by Translation Models"
|
88 |
+
|
89 |
+
with st.container():
|
90 |
+
st.header("Euskera-EU Basque translator - itzultzailea")
|
91 |
+
st.caption("This is a trained AI translator - Hau AI itzultzaile bat da.")
|
92 |
+
coffee = """
|
93 |
+
<div style="margin: 0.75em 0;"><a href="https://www.buymeacoffee.com/Artgen" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"></a></div>
|
94 |
+
"""
|
95 |
+
col1, col2 = st.columns([1,1], gap="small")
|
96 |
+
|
97 |
+
with col1:
|
98 |
+
#source_language_dropdown.change
|
99 |
+
slang = ("Detect", "Basque") # Example list of languages
|
100 |
+
source_language_dropdown = st.selectbox("Language - Hizkuntza", slang, key='source_languages')
|
101 |
+
|
102 |
+
# Create a text area widget
|
103 |
+
input_textbox = st.text_area("Enter text - Idatzi textua", value="", key='input_text')
|
104 |
+
|
105 |
+
with col2:
|
106 |
+
tlang=("","English","German","Russian","Spanish")
|
107 |
+
target_language_dropdown = st.selectbox("Translation - Itzulpena", tlang, key='target_languages')
|
108 |
+
#translated_textbox = st.text_area("Translation - Itzulpena", value="", disabled=False)
|
109 |
+
|
110 |
+
if st.button('Translate - Itzuli') and len(input_textbox)> 0:
|
111 |
+
translated_output = translate(input_textbox,source_language_dropdown,target_language_dropdown)
|
112 |
+
st.text_area("Translation - Itzulpena", value=translated_output, disabled=True)
|
113 |
+
|
114 |
+
@st.cache_data
|
115 |
+
def load_data(inputt,inputl,targetl):
|
116 |
+
data = translate(inputt,inputl,targetl)
|
117 |
+
return data
|
118 |
+
|
119 |
+
if len(target_language_dropdown)>1 and len(source_language_dropdown)>0 and target_language_dropdown!= "" and source_language_dropdown!="Detect" and len(input_textbox)>0:
|
120 |
+
data_load_state = st.text("Translating - Itzultzen..")
|
121 |
+
#data = load_data(input_textbox,source_language_dropdown,target_language_dropdown)
|
122 |
+
data_load_state.text("Translation...completed - Itzulpena amaituta.")
|
123 |
+
st.markdown(coffee, unsafe_allow_html=True)
|
gr_app.py
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from language_directions import get_all_source_languages,update_source_languages_dict,get_target_languages,auto_detect_language_code
|
3 |
+
from transformers import pipeline
|
4 |
+
from adibideak import adibide_esaldiak
|
5 |
+
from iso639_wrapper import get_name_from_iso_code
|
6 |
+
|
7 |
+
source_lang_dict = get_all_source_languages()
|
8 |
+
target_lang_dict = {}
|
9 |
+
source_languages = source_lang_dict.keys()
|
10 |
+
|
11 |
+
def get_auto_detect_source_dropdown(input_text):
|
12 |
+
source, _ = auto_detect_language_code(input_text)
|
13 |
+
language_name = get_name_from_iso_code(source)
|
14 |
+
source_dropdown_text = "Detected - " + language_name
|
15 |
+
update_source_languages_dict(source_lang_dict, source_dropdown_text)
|
16 |
+
source_language_dropdown = gr.Dropdown(choices=source_languages,
|
17 |
+
value=source_dropdown_text,
|
18 |
+
label="Input Language")
|
19 |
+
return source_language_dropdown, language_name
|
20 |
+
|
21 |
+
def get_target_dropdown(source_language_name, input_text):
|
22 |
+
global target_lang_dict
|
23 |
+
target_lang_dict, source_language = get_target_languages(source_lang_dict[source_language_name], input_text)
|
24 |
+
target_languages = list(target_lang_dict.keys())
|
25 |
+
default_target_value = None
|
26 |
+
if "English" in target_languages or "english" in target_languages:
|
27 |
+
default_target_value = "English"
|
28 |
+
else:
|
29 |
+
default_target_value = target_languages[0]
|
30 |
+
target_dropdown = gr.Dropdown(choices=target_languages,
|
31 |
+
value=default_target_value,
|
32 |
+
label="Output Language")
|
33 |
+
return target_dropdown
|
34 |
+
|
35 |
+
def get_dropdown_value(dropdown):
|
36 |
+
if isinstance(dropdown, gr.Dropdown):
|
37 |
+
dropdown_value = dropdown.constructor_args.get('value')
|
38 |
+
elif isinstance(dropdown, str):
|
39 |
+
dropdown_value = dropdown
|
40 |
+
return dropdown_value
|
41 |
+
|
42 |
+
def get_dropdowns(source_dropdown, input_text):
|
43 |
+
source_language_name = get_dropdown_value(source_dropdown)
|
44 |
+
if input_text and source_language_name == "Detect" or source_language_name.startswith("Detected"):
|
45 |
+
source_dropdown, source_language_name = get_auto_detect_source_dropdown(input_text)
|
46 |
+
target_dropdown = get_target_dropdown(source_language_name=source_language_name,
|
47 |
+
input_text=input_text)
|
48 |
+
return source_dropdown, target_dropdown
|
49 |
+
|
50 |
+
def input_changed(source_language_dropdown, input_text=""):
|
51 |
+
return get_dropdowns(source_dropdown=source_language_dropdown,
|
52 |
+
input_text=input_text)
|
53 |
+
|
54 |
+
def translate(input_text, source, target):
|
55 |
+
source_readable = source
|
56 |
+
if source == "Detect" or source.startswith("Detected"):
|
57 |
+
source, _ = auto_detect_language_code(input_text)
|
58 |
+
if source in source_lang_dict.keys():
|
59 |
+
source = source_lang_dict[source]
|
60 |
+
target_lang_dict, _ = get_target_languages(source)
|
61 |
+
try:
|
62 |
+
target = target_lang_dict[target]
|
63 |
+
model = f"Helsinki-NLP/opus-mt-{source}-{target}"
|
64 |
+
pipe = pipeline("translation", model=model)
|
65 |
+
translation = pipe(input_text)
|
66 |
+
return translation[0]['translation_text'], ""
|
67 |
+
except KeyError:
|
68 |
+
return "", f"Error: Translation from {source_readable} to {target} is not supported by Translation Models"
|
69 |
+
|
70 |
+
|
71 |
+
with gr.Blocks() as demo:
|
72 |
+
gr.HTML("""<html>
|
73 |
+
<head>
|
74 |
+
<style>
|
75 |
+
h2 {
|
76 |
+
text-align: center;
|
77 |
+
}
|
78 |
+
</style>
|
79 |
+
</head>
|
80 |
+
<body>
|
81 |
+
<h2>Euskera-EU Basque translator - itzultzailea</h2>
|
82 |
+
</body>
|
83 |
+
</html>""")
|
84 |
+
with gr.Row():
|
85 |
+
with gr.Column():
|
86 |
+
source_language_dropdown = gr.Dropdown(choices=source_languages,
|
87 |
+
value="Detect",
|
88 |
+
label="Input Language - Input Hizkuntza")
|
89 |
+
input_textbox = gr.Textbox(lines=5, placeholder="Enter text to translate", label="Input Text")
|
90 |
+
with gr.Column():
|
91 |
+
target_language_dropdown = gr.Dropdown(choices=["Basque", "English", "French", "Spanish"],
|
92 |
+
value="Basque",
|
93 |
+
label="Output Language - Output Hizkuntza")
|
94 |
+
translated_textbox = gr.Textbox(lines=5, placeholder="", label="Translated Text")
|
95 |
+
info_label = gr.HTML("")
|
96 |
+
btn = gr.Button("Translate - Itzuli")
|
97 |
+
source_language_dropdown.change(input_changed, inputs=[source_language_dropdown, input_textbox], outputs=[source_language_dropdown, target_language_dropdown])
|
98 |
+
input_textbox.change(input_changed, inputs=[source_language_dropdown, input_textbox], outputs=[source_language_dropdown, target_language_dropdown])
|
99 |
+
btn.click(translate, inputs=[input_textbox,
|
100 |
+
source_language_dropdown,
|
101 |
+
target_language_dropdown],
|
102 |
+
outputs=[translated_textbox, info_label])
|
103 |
+
gr.Examples(adibide_esaldiak, inputs=[input_textbox])
|
104 |
+
|
105 |
+
if __name__ == "__main__":
|
106 |
+
demo.launch()
|
gr_requirements.txt
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-i https://pypi.python.org/simple
|
2 |
+
gradio==3.*
|
3 |
+
iso639-lang
|
4 |
+
pycld2 # In future, maybe use lingua-language-detector
|
5 |
+
torch
|
6 |
+
transformers
|
7 |
+
sentencepiece
|
8 |
+
langdetect
|
9 |
+
sacremoses
|
helsinki_models.py
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
helsinki_models = [
|
2 |
+
"Helsinki-NLP/opus-mt-tc-big-itc-eu",
|
3 |
+
"Helsinki-NLP/opus-mt-tc-big-eu-itc",
|
4 |
+
"Helsinki-NLP/opus-mt-euq-en",
|
5 |
+
"Helsinki-NLP/opus-mt-eu-ru",
|
6 |
+
"Helsinki-NLP/opus-mt-eu-es",
|
7 |
+
"Helsinki-NLP/opus-mt-eu-en",
|
8 |
+
"Helsinki-NLP/opus-mt-eu-de",
|
9 |
+
"Helsinki-NLP/opus-mt-en-euq",
|
10 |
+
"Helsinki-NLP/opus-mt-en-euq",
|
11 |
+
"Helsinki-NLP/opus-mt-en-eu",
|
12 |
+
"Helsinki-NLP/opus-mt-de-eu",
|
13 |
+
"Helsinki-NLP/opus-mt-ru-eu",
|
14 |
+
"Helsinki-NLP/opus-mt-es-eu",
|
15 |
+
]
|
16 |
+
|
17 |
+
def get_clearly_formatted_language_directions():
|
18 |
+
# Clearly formatted language directions only
|
19 |
+
# Helsinki-NLP/opus-mt-tc-base-bat-zle is ignored
|
20 |
+
# Helsinki-NLP/opus-mt-tc-fr-en is accepted due to clarity of source language being fr and target language being en
|
21 |
+
language_directions = [model.split("Helsinki-NLP/opus-mt-")[1] for model in helsinki_models
|
22 |
+
if (len(model.split("-"))<6 and
|
23 |
+
"opus-mt" in model and
|
24 |
+
len(model.split("_")) == 1)
|
25 |
+
and len(model) < len("Helsinki-NLP/opus-mt-src-trg")]
|
26 |
+
return language_directions
|
images/banner.jpg
ADDED
![]() |
iso639_wrapper.py
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#from iso639 import Lang, iter_langs
|
2 |
+
from iso639 import iter_langs
|
3 |
+
from regex import R
|
4 |
+
|
5 |
+
langs = [lang for lang in iter_langs()]
|
6 |
+
|
7 |
+
# iso 1
|
8 |
+
iso1_code_to_name = {lg.pt1: lg.name for lg in langs}
|
9 |
+
iso1_name_to_code = {lg.name: lg.pt1 for lg in langs}
|
10 |
+
|
11 |
+
# iso 2
|
12 |
+
iso2b_code_to_name = {lg.pt2b: lg.name for lg in langs}
|
13 |
+
iso2b_name_to_code = {lg.name: lg.pt2b for lg in langs}
|
14 |
+
iso2t_code_to_name = {lg.pt2t: lg.name for lg in langs}
|
15 |
+
iso2t_name_to_code = {lg.name: lg.pt2t for lg in langs}
|
16 |
+
|
17 |
+
# iso 3
|
18 |
+
iso3_code_to_name = {lg.pt3: lg.name for lg in langs}
|
19 |
+
iso3_name_to_code = {lg.name: lg.pt3 for lg in langs}
|
20 |
+
|
21 |
+
# iso 5
|
22 |
+
iso5_code_to_name = {lg.pt5: lg.name for lg in langs}
|
23 |
+
iso5_name_to_code = {lg.name: lg.pt5 for lg in langs}
|
24 |
+
|
25 |
+
# https://github.com/Helsinki-NLP/Tatoeba-Challenge/blob/master/README.md#in-more-detail
|
26 |
+
helsinki_precendence = ["iso3", "iso5", "iso1", "iso2t", "iso2b"]
|
27 |
+
|
28 |
+
rename_dict = {"Panjabi": "Punjabi"}
|
29 |
+
|
30 |
+
def rename_languages(language):
|
31 |
+
if language in rename_dict:
|
32 |
+
return rename_dict[language]
|
33 |
+
return language
|
34 |
+
|
35 |
+
def rename_return_value(func):
|
36 |
+
def wrapper(*args, **kwargs):
|
37 |
+
result = func(*args, **kwargs)
|
38 |
+
if isinstance(result, str):
|
39 |
+
return rename_languages(result)
|
40 |
+
elif isinstance(result, list):
|
41 |
+
return [rename_languages(item) for item in result]
|
42 |
+
elif isinstance(result, dict):
|
43 |
+
return {key: rename_languages(value) for key, value in result.items()}
|
44 |
+
else:
|
45 |
+
return result
|
46 |
+
return wrapper
|
47 |
+
|
48 |
+
@rename_return_value
|
49 |
+
def get_name_from_iso_code(iso_code, precedence=helsinki_precendence):
|
50 |
+
for code_type in precedence:
|
51 |
+
if code_type == "iso1" and iso_code in iso1_code_to_name.keys():
|
52 |
+
return iso1_code_to_name[iso_code]
|
53 |
+
elif code_type == "iso2b" and iso_code in iso2b_code_to_name.keys():
|
54 |
+
return iso2b_code_to_name[iso_code]
|
55 |
+
elif code_type == "iso2t" and iso_code in iso2t_code_to_name.keys():
|
56 |
+
return iso2t_code_to_name[iso_code]
|
57 |
+
elif code_type == "iso3" and iso_code in iso3_code_to_name.keys():
|
58 |
+
return iso3_code_to_name[iso_code]
|
59 |
+
elif code_type == "iso5" and iso_code in iso5_code_to_name.keys():
|
60 |
+
return iso5_code_to_name[iso_code]
|
language_detection.py
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pycld2 as cld2
|
2 |
+
from langdetect import detect
|
3 |
+
|
4 |
+
def detect_language(input_text):
|
5 |
+
if not input_text:
|
6 |
+
return "unknown"
|
7 |
+
_, _, details = cld2.detect(input_text)
|
8 |
+
detected_language = details[0][0].lower()
|
9 |
+
if detected_language == "unknown":
|
10 |
+
language_code = detect(input_text)
|
11 |
+
return language_code
|
12 |
+
else:
|
13 |
+
return detected_language
|
language_directions.py
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from helsinki_models import helsinki_models, get_clearly_formatted_language_directions
|
2 |
+
from iso639_wrapper import get_name_from_iso_code
|
3 |
+
from language_detection import detect_language
|
4 |
+
from collections import OrderedDict
|
5 |
+
from utils import convert_keys_to_lowercase, match_in_keys, match_in_values
|
6 |
+
|
7 |
+
def get_all_source_languages():
|
8 |
+
"""
|
9 |
+
Returns a human-readable `dict source_languages_names:codes`
|
10 |
+
based on the available models.
|
11 |
+
"""
|
12 |
+
source_languages = {}
|
13 |
+
language_directions = get_clearly_formatted_language_directions()
|
14 |
+
|
15 |
+
for direction in language_directions:
|
16 |
+
source_lang_code = direction.split('-')[0]
|
17 |
+
source_language_name = get_name_from_iso_code(source_lang_code)
|
18 |
+
if source_language_name:
|
19 |
+
source_languages[source_language_name] = source_lang_code
|
20 |
+
source_languages = OrderedDict(sorted(source_languages.items()))
|
21 |
+
all_source_langs_including_auto_detect = \
|
22 |
+
{ **{'Detect' : 'Detect'}, **source_languages}
|
23 |
+
return all_source_langs_including_auto_detect
|
24 |
+
|
25 |
+
def update_source_languages_dict(source_languages_dict, auto_detected_language):
|
26 |
+
source_languages_dict[auto_detected_language] = "Detect"
|
27 |
+
|
28 |
+
def get_target_languages(source_language_code, input_text=None):
|
29 |
+
"""
|
30 |
+
Returns a human-readable `dict of target languages names to codes`
|
31 |
+
based on the available models and the source language passed.
|
32 |
+
"""
|
33 |
+
include_all_languages = False
|
34 |
+
if source_language_code == "Detect":
|
35 |
+
source_language_code, include_all_languages = auto_detect_language_code(input_text)
|
36 |
+
|
37 |
+
target_languages = {}
|
38 |
+
language_directions = get_clearly_formatted_language_directions()
|
39 |
+
for direction in language_directions:
|
40 |
+
if direction.startswith(f"{source_language_code}-") or include_all_languages:
|
41 |
+
target_language = direction.split('-')[1] # Extracting the last part as the target language
|
42 |
+
target_language_name = get_name_from_iso_code(target_language)
|
43 |
+
if target_language_name:
|
44 |
+
target_languages[target_language_name] = target_language
|
45 |
+
return OrderedDict(sorted(target_languages.items())), source_language_code
|
46 |
+
|
47 |
+
def auto_detect_language_code(input_text):
|
48 |
+
DEFAULT_SOURCE_LANGUAGE = "eu"
|
49 |
+
detected_language_string = DEFAULT_SOURCE_LANGUAGE
|
50 |
+
if not input_text:
|
51 |
+
return DEFAULT_SOURCE_LANGUAGE, True
|
52 |
+
language_or_code = detect_language(input_text)
|
53 |
+
if language_or_code == "unknown":
|
54 |
+
return DEFAULT_SOURCE_LANGUAGE, True
|
55 |
+
else:
|
56 |
+
detected_language_string = match_in_keys(get_all_source_languages(), language_or_code)
|
57 |
+
if not detected_language_string:
|
58 |
+
detected_language_string = match_in_values(get_all_source_languages(), language_or_code)
|
59 |
+
if detected_language_string:
|
60 |
+
return detected_language_string, False
|
61 |
+
else:
|
62 |
+
return DEFAULT_SOURCE_LANGUAGE, True
|
63 |
+
|
64 |
+
|
65 |
+
# Example usage:
|
66 |
+
# all_source_languages = get_all_source_languages()
|
67 |
+
# print("All Source Languages:", all_source_languages)
|
68 |
+
|
69 |
+
# source_language_code = "pa" # Replace with your desired source language
|
70 |
+
# target_languages = get_target_languages(source_language_code)
|
71 |
+
# print(f"Target Languages for {source_language_code}:", target_languages)
|
requirements.txt
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-i https://pypi.python.org/simple
|
2 |
+
streamlit
|
3 |
+
iso639-lang
|
4 |
+
pycld2 # In future, maybe use lingua-language-detector
|
5 |
+
torch
|
6 |
+
transformers
|
7 |
+
sentencepiece
|
8 |
+
langdetect
|
9 |
+
sacremoses
|
styles/style.css
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
@author: idoia lerchundi
|
3 |
+
*/
|
4 |
+
input[type=message], input[type=email], input[type=text], textarea {
|
5 |
+
width: 100%;
|
6 |
+
padding: 12px;
|
7 |
+
border: 1px solid #ccc;
|
8 |
+
border-radius: 4px;
|
9 |
+
box-sizing: border-box;
|
10 |
+
margin-top: 6px;
|
11 |
+
margin-bottom: 16px;
|
12 |
+
resize: vertical;
|
13 |
+
}
|
14 |
+
button[type=submit] {
|
15 |
+
background-color: #04AA6D;
|
16 |
+
color: white;
|
17 |
+
padding: 12px 20px;
|
18 |
+
border: none;
|
19 |
+
border-radius: 4px;
|
20 |
+
cursor: pointer;
|
21 |
+
}
|
22 |
+
button[type=submit]:hover {
|
23 |
+
background-color: #45a049;
|
24 |
+
}
|
25 |
+
/* Hide Streamlit Branding */
|
26 |
+
#MainMenu {visibility: hidden;}
|
27 |
+
footer {visibility: hidden;}
|
28 |
+
header {visibility: hidden;}
|
29 |
+
|
30 |
+
.block-container{padding:0 20px 20px 20px}
|
styles/w3.css
ADDED
@@ -0,0 +1,250 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}
|
2 |
+
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
|
3 |
+
.w3-menubar{
|
4 |
+
width:100%;
|
5 |
+
overflow:auto;
|
6 |
+
position:absolute;
|
7 |
+
top:10px;
|
8 |
+
color:rgba(0, 0, 0, 1);
|
9 |
+
font-family:Hind;
|
10 |
+
text-align:left;
|
11 |
+
font-size:16px;
|
12 |
+
letter-spacing:0;
|
13 |
+
}
|
14 |
+
.w3-center .w3-menubar{display:inline-block;width:auto}
|
15 |
+
.w3-menubar .w3-menubar-item{padding:10px auto 10px auto;float:left;width:auto;border:none;display:block;outline:0;}
|
16 |
+
.w3-menubar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left}
|
17 |
+
.w3-menubar .w3-button{white-space:normal}
|
18 |
+
.w3-menubar-block .w3-menubar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0}
|
19 |
+
.w3-menubar-block.w3-center .w3-menubar-item{text-align:center}.w3-block{display:block;width:100%}
|
20 |
+
.w3-top,.w3-bottom{position:relative;width:100%;z-index:1}.w3-top{left:330px;top:0px;}.w3-bottom{bottom:0}
|
21 |
+
article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item}
|
22 |
+
audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline}
|
23 |
+
audio:not([controls]){display:none;height:0}[hidden],template{display:none}
|
24 |
+
a{background-color:transparent}a:active,a:hover{outline-width:0}
|
25 |
+
abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}
|
26 |
+
b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000}
|
27 |
+
small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
28 |
+
sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none}
|
29 |
+
code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible}
|
30 |
+
button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold}
|
31 |
+
button,input{overflow:visible}button,select{text-transform:none}
|
32 |
+
button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}
|
33 |
+
button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}
|
34 |
+
button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}
|
35 |
+
fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}
|
36 |
+
legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}
|
37 |
+
[type=checkbox],[type=radio]{padding:0}
|
38 |
+
[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}
|
39 |
+
[type=search]{-webkit-appearance:textfield;outline-offset:-2px}
|
40 |
+
[type=search]::-webkit-search-decoration{-webkit-appearance:none}
|
41 |
+
::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}
|
42 |
+
html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden}
|
43 |
+
h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px}
|
44 |
+
.w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace}
|
45 |
+
h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px}
|
46 |
+
hr{border:0;border-top:1px solid #eee;margin:20px 0}
|
47 |
+
.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit}
|
48 |
+
.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc}
|
49 |
+
.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1}
|
50 |
+
.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1}
|
51 |
+
.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center}
|
52 |
+
.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top}
|
53 |
+
.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px}
|
54 |
+
.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap}
|
55 |
+
.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
|
56 |
+
.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
57 |
+
.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none}
|
58 |
+
.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none}
|
59 |
+
.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%}
|
60 |
+
.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none}
|
61 |
+
.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block}
|
62 |
+
.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s}
|
63 |
+
.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%}
|
64 |
+
.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc}
|
65 |
+
.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer}
|
66 |
+
.w3-dropdown-hover:hover .w3-dropdown-content{display:block}
|
67 |
+
.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000}
|
68 |
+
.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000}
|
69 |
+
.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1}
|
70 |
+
.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px}
|
71 |
+
.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto}
|
72 |
+
.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%}
|
73 |
+
.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%}
|
74 |
+
.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px}
|
75 |
+
.w3-main,#main{transition:margin-left .4s}
|
76 |
+
.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)}
|
77 |
+
.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px}
|
78 |
+
.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto}
|
79 |
+
.w3-bar .w3-bar-item{padding:8px 8px 8px 8px;float:right;width:auto;border:none;display:block;outline:0;}
|
80 |
+
.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left}
|
81 |
+
.w3-bar .w3-button{white-space:normal}
|
82 |
+
.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0}
|
83 |
+
.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%}
|
84 |
+
.w3-responsive{display:block;overflow-x:auto}
|
85 |
+
.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before,
|
86 |
+
.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both}
|
87 |
+
.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%}
|
88 |
+
.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%}
|
89 |
+
.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%}
|
90 |
+
.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%}
|
91 |
+
@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%}
|
92 |
+
.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%}
|
93 |
+
.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}}
|
94 |
+
@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%}
|
95 |
+
.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%}
|
96 |
+
.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}}
|
97 |
+
.w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px}
|
98 |
+
.w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px}
|
99 |
+
.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell}
|
100 |
+
.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom}
|
101 |
+
.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important}
|
102 |
+
@media (max-width:1205px){.w3-auto{max-width:95%}}
|
103 |
+
@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px}
|
104 |
+
.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative}
|
105 |
+
.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center}
|
106 |
+
.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}}
|
107 |
+
@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}}
|
108 |
+
@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}}
|
109 |
+
@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}}
|
110 |
+
@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}}
|
111 |
+
/*w3-top was here */
|
112 |
+
.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2}
|
113 |
+
.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0}
|
114 |
+
.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0}
|
115 |
+
.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)}
|
116 |
+
.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)}
|
117 |
+
.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)}
|
118 |
+
.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
|
119 |
+
.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
|
120 |
+
.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none}
|
121 |
+
.w3-display-position{position:absolute}
|
122 |
+
.w3-circle{border-radius:50%}
|
123 |
+
.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px}
|
124 |
+
.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px}
|
125 |
+
.w3-container,.w3-panel{padding:0.0em 0px}.w3-panel{margin-top:16px;margin-bottom:16px}
|
126 |
+
.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px}
|
127 |
+
.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word}
|
128 |
+
.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%}
|
129 |
+
.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)}
|
130 |
+
.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)}
|
131 |
+
.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}
|
132 |
+
.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}}
|
133 |
+
.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}}
|
134 |
+
.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}}
|
135 |
+
.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}}
|
136 |
+
.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}}
|
137 |
+
.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}}
|
138 |
+
.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}}
|
139 |
+
.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important}
|
140 |
+
.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1}
|
141 |
+
.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75}
|
142 |
+
.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)}
|
143 |
+
.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)}
|
144 |
+
.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)}
|
145 |
+
.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important}
|
146 |
+
.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important}
|
147 |
+
.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important}
|
148 |
+
.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important}
|
149 |
+
.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important}
|
150 |
+
.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important}
|
151 |
+
.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important}
|
152 |
+
.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important}
|
153 |
+
.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important}
|
154 |
+
.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important}
|
155 |
+
.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important}
|
156 |
+
.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important}
|
157 |
+
.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important}
|
158 |
+
.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important}
|
159 |
+
.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important}
|
160 |
+
.w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important}
|
161 |
+
.w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important}
|
162 |
+
.w3-left{float:left!important}.w3-right{float:right!important}
|
163 |
+
.w3-button:hover{color:#000!important;background-color:#ccc!important}
|
164 |
+
.w3-transparent,.w3-hover-none:hover{background-color:transparent!important}
|
165 |
+
.w3-hover-none:hover{box-shadow:none!important}
|
166 |
+
/* Colors */
|
167 |
+
.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important}
|
168 |
+
.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important}
|
169 |
+
.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important}
|
170 |
+
.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important}
|
171 |
+
.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important}
|
172 |
+
.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important}
|
173 |
+
.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important}
|
174 |
+
.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}
|
175 |
+
.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important}
|
176 |
+
.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important}
|
177 |
+
.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important}
|
178 |
+
.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important}
|
179 |
+
.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important}
|
180 |
+
.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important}
|
181 |
+
.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important}
|
182 |
+
.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important}
|
183 |
+
.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important}
|
184 |
+
.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important}
|
185 |
+
.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important}
|
186 |
+
.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important}
|
187 |
+
.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important}
|
188 |
+
.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important}
|
189 |
+
.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important}
|
190 |
+
.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important}
|
191 |
+
.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important}
|
192 |
+
.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important}
|
193 |
+
.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important}
|
194 |
+
.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important}
|
195 |
+
.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important}
|
196 |
+
.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important}
|
197 |
+
.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important}
|
198 |
+
.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important}
|
199 |
+
.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important}
|
200 |
+
.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important}
|
201 |
+
.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important}
|
202 |
+
.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important}
|
203 |
+
.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important}
|
204 |
+
.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important}
|
205 |
+
.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important}
|
206 |
+
.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important}
|
207 |
+
.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important}
|
208 |
+
.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important}
|
209 |
+
.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important}
|
210 |
+
.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important}
|
211 |
+
.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important}
|
212 |
+
.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important}
|
213 |
+
.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important}
|
214 |
+
.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important}
|
215 |
+
.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important}
|
216 |
+
.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important}
|
217 |
+
.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important}
|
218 |
+
.w3-text-white,.w3-hover-text-white:hover{color:#fff!important}
|
219 |
+
.w3-text-black,.w3-hover-text-black:hover{color:#000!important}
|
220 |
+
.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important}
|
221 |
+
.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important}
|
222 |
+
.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important}
|
223 |
+
.w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important}
|
224 |
+
.w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important}
|
225 |
+
.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important}
|
226 |
+
.w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important}
|
227 |
+
.w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important}
|
228 |
+
.w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important}
|
229 |
+
.w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important}
|
230 |
+
.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important}
|
231 |
+
.w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important}
|
232 |
+
.w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important}
|
233 |
+
.w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important}
|
234 |
+
.w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important}
|
235 |
+
.w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important}
|
236 |
+
.w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important}
|
237 |
+
.w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important}
|
238 |
+
.w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important}
|
239 |
+
.w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important}
|
240 |
+
.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important}
|
241 |
+
.w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important}
|
242 |
+
.w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important}
|
243 |
+
.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important}
|
244 |
+
.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important}
|
245 |
+
.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important}
|
246 |
+
.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important}
|
247 |
+
.w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important}
|
248 |
+
.w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important}
|
249 |
+
.w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important}
|
250 |
+
.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important}
|
utils.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from functools import cache
|
2 |
+
|
3 |
+
|
4 |
+
def convert_keys_to_lowercase(input_dict):
|
5 |
+
return {key.lower(): value for key, value in input_dict.items()}
|
6 |
+
|
7 |
+
def match_in_keys(dictionary, search_string):
|
8 |
+
lowercase_dict = convert_keys_to_lowercase(dictionary)
|
9 |
+
if search_string.lower() in list(lowercase_dict.keys()):
|
10 |
+
return lowercase_dict.get(search_string.lower())
|
11 |
+
for l_key in lowercase_dict.keys():
|
12 |
+
if l_key.startswith(search_string.lower()):
|
13 |
+
return lowercase_dict.get(l_key)
|
14 |
+
|
15 |
+
def match_in_values(dictionary, search_string):
|
16 |
+
lowercase_dict = convert_keys_to_lowercase(dictionary)
|
17 |
+
if search_string.lower() in list(lowercase_dict.values()):
|
18 |
+
return search_string
|