AutoTranslateAI / app.py
Brian045's picture
Update app.py
1aa73ec verified
Raw History Blame Contribute Delete
7.23 kB
import gradio as gr
import pandas as pd
import os
from translator_utils import process_rows, revert_rows, download_dataset, LOCAL_FILENAME, ENV_HF_TOKEN, read_csv_robust
def load_data():
"""Load the dataset safely using robust reader."""
if not os.path.exists(LOCAL_FILENAME):
try:
download_dataset()
except:
return pd.DataFrame()
df = read_csv_robust(LOCAL_FILENAME)
if df.empty:
return df
try:
if 'Judul_Inggris' not in df.columns:
df['Judul_Inggris'] = ""
if 'Isi_Inggris' not in df.columns:
df['Isi_Inggris'] = ""
df = df.fillna("")
return df
except:
return pd.DataFrame()
def force_refresh_data():
"""Forces a re-download and reload of the data."""
try:
download_dataset(force=True)
return load_data(), "Data refreshed successfully."
except Exception as e:
return pd.DataFrame(), f"Failed to refresh data: {e}"
def get_pending_data(full_df):
"""Filter for rows that are NOT fully translated."""
if full_df.empty:
return full_df
mask = (full_df['Judul_Inggris'].str.strip() == "") | (full_df['Isi_Inggris'].str.strip() == "")
df_view = full_df[mask].copy()
df_view.reset_index(inplace=True)
df_view.rename(columns={'index': 'ID'}, inplace=True)
df_view.insert(0, "Select", False)
return df_view
def get_history_data(full_df, date_filter=""):
"""Filter for rows that ARE fully translated."""
if full_df.empty:
return full_df
mask = (full_df['Judul_Inggris'].str.strip() != "") & (full_df['Isi_Inggris'].str.strip() != "")
df_view = full_df[mask].copy()
df_view.reset_index(inplace=True)
df_view.rename(columns={'index': 'ID'}, inplace=True)
if date_filter:
df_view = df_view[df_view['Tanggal'].str.contains(date_filter, case=False, na=False)]
# Add 'Select' column for Revert functionality
df_view.insert(0, "Select", False)
return df_view
def on_translate_selected(df_data, token, progress=gr.Progress()):
"""Callback when user clicks 'Translate Selected'."""
selected_rows = df_data[df_data["Select"] == True]
if selected_rows.empty:
return gr.DataFrame(), gr.DataFrame(), "No rows selected!"
try:
indices = selected_rows['ID'].tolist()
indices = [int(i) for i in indices]
except KeyError:
return gr.DataFrame(), gr.DataFrame(), "Error: ID column missing."
updated_df, msg = process_rows(indices, token=token, progress=progress)
pending = get_pending_data(updated_df)
history = get_history_data(updated_df)
return pending, history, msg
def on_revert_selected(df_data, token, progress=gr.Progress()):
"""Callback when user clicks 'Revert Selected'."""
selected_rows = df_data[df_data["Select"] == True]
if selected_rows.empty:
return gr.DataFrame(), gr.DataFrame(), "No rows selected!"
try:
indices = selected_rows['ID'].tolist()
indices = [int(i) for i in indices]
except KeyError:
return gr.DataFrame(), gr.DataFrame(), "Error: ID column missing."
# Call revert
updated_df, msg = revert_rows(indices, token=token, progress=progress)
# Refresh views
pending = get_pending_data(updated_df)
history = get_history_data(updated_df)
return pending, history, msg
def filter_history(date_input):
df = load_data()
return get_history_data(df, date_input)
def refresh_views():
df, msg = force_refresh_data()
pending = get_pending_data(df)
history = get_history_data(df)
return pending, history, msg
def auto_select_pending(df_view):
"""Automatically selects the first 10 rows in the pending view."""
if df_view.empty:
return df_view, "No rows to select."
# Set 'Select' to True for the first 10 rows
limit = min(10, len(df_view))
df_view.loc[:limit-1, "Select"] = True
return df_view, f"Auto-selected top {limit} rows."
# CSS to ensure columns are readable
custom_css = """
/* Fix minimum width for content columns */
table td:nth-child(5), table td:nth-child(6), table td:nth-child(7), table td:nth-child(8) {
min-width: 300px !important;
white-space: pre-wrap !important;
}
/* Ensure row ID is small */
table td:nth-child(2) {
width: 50px !important;
}
"""
with gr.Blocks(title="Auto AI News Translator") as app:
gr.Markdown("# Auto AI News Translator")
gr.Markdown("Translate news from Indonesian to English (with Chunking). Select rows to translate.")
# Inject default value from Env Var
hf_token = gr.Textbox(
label="HF Token (Optional for Persistence)",
placeholder="hf_... (Leave empty if set in ENV)",
type="password",
value=ENV_HF_TOKEN
)
with gr.Row():
status_output = gr.Textbox(label="Status", value="Ready", interactive=False, scale=4)
refresh_btn = gr.Button("🔄 Refresh Data (Force Redownload)", scale=1)
with gr.Tabs():
with gr.TabItem("Translate Pending"):
gr.Markdown("Select rows to translate and click Submit.")
with gr.Row():
auto_select_btn = gr.Button("Auto-Select Next 10", size="sm")
translate_btn = gr.Button("Translate Selected Rows", variant="primary")
pending_df_comp = gr.DataFrame(
value=get_pending_data(load_data()),
label="Pending Translations",
interactive=True,
wrap=True,
datatype=["bool", "number"] + ["str"] * 6
)
auto_select_btn.click(
fn=auto_select_pending,
inputs=[pending_df_comp],
outputs=[pending_df_comp, status_output]
)
with gr.TabItem("History (Revert Supported)"):
gr.Markdown("Select rows to delete translation and move back to Pending.")
date_filter = gr.Textbox(label="Filter by Date (YYYY-MM-DD)")
# History now has checkbox
history_df_comp = gr.DataFrame(
value=get_history_data(load_data()),
label="Translation History",
interactive=True,
wrap=True,
datatype=["bool", "number"] + ["str"] * 6
)
with gr.Row():
date_filter.change(fn=filter_history, inputs=[date_filter], outputs=[history_df_comp])
revert_btn = gr.Button("Revert Selected (Delete & Move to Pending)", variant="stop")
translate_btn.click(
fn=on_translate_selected,
inputs=[pending_df_comp, hf_token],
outputs=[pending_df_comp, history_df_comp, status_output]
)
revert_btn.click(
fn=on_revert_selected,
inputs=[history_df_comp, hf_token],
outputs=[pending_df_comp, history_df_comp, status_output]
)
refresh_btn.click(
fn=refresh_views,
outputs=[pending_df_comp, history_df_comp, status_output]
)
if __name__ == "__main__":
app.launch(css=custom_css)