diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5018379..ac96dba 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,4 +15,4 @@ repos: rev: 3.9.0 hooks: - id: flake8 - args: ["--ignore=E203,W503,FI10,FI11,FI12,FI13,FI14,FI15,FI16,FI17,FI58,E501"] + args: ["--ignore=E203,W503,FI10,FI11,FI12,FI13,FI14,FI15,FI16,FI17,FI58,E501", "--builtins=_"] diff --git a/README.md b/README.md index e886902..3045be1 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,16 @@ ## Как запустить проект ### Frontend +Интерфейс на русском языке ```bash python3 todo_tk.py ``` +Интерфейс на английском языке +```bash +LANG=eng python3 todo_tk.py +``` + ### backend ```bash docker-compose up diff --git a/frontend/login.py b/frontend/login.py index 5b03aeb..f471fff 100644 --- a/frontend/login.py +++ b/frontend/login.py @@ -1,7 +1,11 @@ +import gettext +import os import tkinter as tk from .user import User from . import message +gettext.install("todo", os.path.join(os.path.dirname(__file__), "po")) + class LoginFrame(tk.Frame): @@ -57,21 +61,22 @@ class LoginFrame(tk.Frame): tk.Grid.columnconfigure(self, columns, weight=1) # Подпись и поле ввода для логина - login_label = tk.Label(self, text="Введите логин") + t = _("Введите логин") + login_label = tk.Label(self, text=t) login_label.grid(row=9, column=12, columnspan=3, rowspan=1, sticky="nsew") self.login = tk.Entry(self) self.login.grid(row=10, column=12, columnspan=3, rowspan=1, sticky="nsew") # Подпись и поле ввода для пароля - password_label = tk.Label(self, text="Введите пароль") + password_label = tk.Label(self, text=_("Введите пароль")) password_label.grid(row=11, column=12, columnspan=3, rowspan=1, sticky="nsew") self.password = tk.Entry(self, show="*") self.password.grid(row=12, column=12, columnspan=3, rowspan=1, sticky="nsew") # Кнопка авториазции - btn = tk.Button(self, text="Войти", command=self.login_clicked) + btn = tk.Button(self, text=_("Войти"), command=self.login_clicked) btn.grid(row=14, column=12, columnspan=3, rowspan=1, sticky="nsew") # Если захочется реализовать в логине diff --git a/frontend/message.py b/frontend/message.py index 824d07b..c088893 100644 --- a/frontend/message.py +++ b/frontend/message.py @@ -1,8 +1,12 @@ +import gettext +import os from tkinter import messagebox as mb -TITLE_INFO_BOX = "Сообщение!" -MESSAGE_INVALID_LOGIN = "Неправильный логин или пароль" -MESSAGE_EMPTY = "Сдесь могло быть ваше сообщение" +gettext.install("todo", os.path.join(os.path.dirname(__file__), "po")) + +TITLE_INFO_BOX = _("Сообщение!") +MESSAGE_INVALID_LOGIN = _("Неправильный логин или пароль") +MESSAGE_EMPTY = _("Сдесь могло быть ваше сообщение") def infobox(msg: str = None) -> None: diff --git a/frontend/po/eng/LC_MESSAGES/todo.po b/frontend/po/eng/LC_MESSAGES/todo.po new file mode 100644 index 0000000..427bd92 --- /dev/null +++ b/frontend/po/eng/LC_MESSAGES/todo.po @@ -0,0 +1,83 @@ +# English (United States) translations for PROJECT. +# Copyright (C) 2021 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2021. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2021-06-06 23:42+0300\n" +"PO-Revision-Date: 2021-06-07 00:24+0300\n" +"Last-Translator: FULL NAME \n" +"Language: en_US\n" +"Language-Team: en_US \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.1\n" + +#: todo_tk.py:20 +msgid "Приложение для планирования" +msgstr "ToDo Application" + +#: message.py:6 +msgid "Сообщение!" +msgstr "Message!" + +#: message.py:7 +msgid "Неправильный логин или пароль" +msgstr "Wrong login or password" + +#: message.py:8 +msgid "Сдесь могло быть ваше сообщение" +msgstr "This could have been your message" + +#: login.py:63 +msgid "Введите логин" +msgstr "Enter your username" + +#: login.py:71 +msgid "Введите пароль" +msgstr "Enter your password" + +#: login.py:78 +msgid "Войти" +msgstr "Enter" + +#: workspace.py:17 +msgid "Не реализовано" +msgstr "Not implemented" + +#: workspace.py:25 +msgid "Текст" +msgstr "Text" + +#: workspace.py:28 +msgid "Выполнено" +msgstr "Done" + +#: workspace.py:31 +msgid "Создано" +msgstr "Created" + +#: workspace.py:60 +msgid "Удалить" +msgstr "Delete" + +#: workspace.py:88 +msgid "Добавить заметку" +msgstr "Add note" + +#: workspace.py:91 +msgid "Удалить лист" +msgstr "Delete list" + +#: workspace.py:149 +msgid "Запомнить меня" +msgstr "Remember me" + +#: workspace.py:158 +msgid "Добавить лист" +msgstr "Add list" diff --git a/frontend/todo_tk.py b/frontend/todo_tk.py index c7123e9..e80154b 100644 --- a/frontend/todo_tk.py +++ b/frontend/todo_tk.py @@ -1,20 +1,24 @@ #!/usr/bin/env python3 +import gettext +import os import sys import tkinter as tk from .login import LoginFrame from .workspace import WorkSpaceFrame from .user import User +gettext.install("todo", os.path.join(os.path.dirname(__file__), "po")) + if "win" in sys.platform.lower(): DEFAULT_URL = "http://localhost:8000" else: DEFAULT_URL = "http://0.0.0.0:8000" -BASE_W = 600 +BASE_W = 900 BASE_H = 400 -TITLE_APP = "ToDo Application" +TITLE_APP = _("Приложение для планирования") class Application(tk.Tk): @@ -50,7 +54,6 @@ class Application(tk.Tk): def center_window(self, width: str = BASE_W, heigh: str = BASE_H) -> None: """ Центрирует приложение по центру экрана - :param width: ширина окна :param heigh: высота окна """ diff --git a/frontend/workspace.py b/frontend/workspace.py index 73875e7..fe4ba2f 100644 --- a/frontend/workspace.py +++ b/frontend/workspace.py @@ -1,60 +1,65 @@ +import gettext +import os import tkinter as tk +gettext.install("todo", os.path.join(os.path.dirname(__file__), "po")) + def str_time(time): return time.strftime("%Y-%m-%d %H:%M:%S") -TODO_ITEM_TABLE_TEXT_WIDTH = 15 -TODO_ITEM_TABLE_FINISHED_WIDTH = 8 -TODO_ITEM_TABLE_CREATED_AT_WIDTH = 15 +TODO_ITEM_TABLE_TEXT_WIDTH = 25 +TODO_ITEM_TABLE_FINISHED_WIDTH = 20 + +TODO_ITEM_TABLE_CREATED_AT_WIDTH = 25 def placeholder(): - print("Не реализовано") + print(_("Не реализовано")) class ToDoItemWidget(tk.Frame): - @staticmethod - def header(parent): - body = tk.Frame(parent) - - text = tk.Label(body, text="Текст", width=TODO_ITEM_TABLE_TEXT_WIDTH) - text.pack(side="left") - - text = tk.Label(body, text="Выполнено", width=TODO_ITEM_TABLE_FINISHED_WIDTH) - text.pack(side="left") - - text = tk.Label(body, text="Создано", width=TODO_ITEM_TABLE_CREATED_AT_WIDTH) - text.pack(side="left") - - return body - - def __init__(self, *args, item, **argv): + def __init__(self, *args, row_number, item, table, **argv): super().__init__(*args, **argv) self.parent = self.master self.item = item - self.noteLabel = tk.Label(self, text=item.text, width=TODO_ITEM_TABLE_TEXT_WIDTH) - self.noteLabel.pack(side="left") + self.noteLabel = tk.Label( + table, + text=item.text, + width=TODO_ITEM_TABLE_TEXT_WIDTH, + justify="center", + font=("Arial", 8), + ) + self.noteLabel.grid(row=row_number, column=0) self.finished = tk.IntVar(value=int(item.finished)) self.finishedButton = tk.Checkbutton( - self, + table, variable=self.finished, command=self.finishedButton_command, width=TODO_ITEM_TABLE_FINISHED_WIDTH, + justify="center", ) - self.finishedButton.pack(side="left") + self.finishedButton.grid(row=row_number, column=1) self.createdAt = tk.Label( - self, text=str_time(item.created_at), width=TODO_ITEM_TABLE_CREATED_AT_WIDTH + table, + text=str_time(item.created_at), + width=TODO_ITEM_TABLE_CREATED_AT_WIDTH, + justify="center", ) - self.createdAt.pack(side="left") + self.createdAt.grid(row=row_number, column=2) - self.remove = tk.Button(self, text="Удалить", command=lambda: self.parent.remove(self.item)) - self.remove.pack(side="left") + self.remove = tk.Button( + table, + text=_("Удалить"), + command=lambda: self.parent.remove(self.item), + justify="center", + ) + self.remove.grid(row=row_number, column=3) def finishedButton_command(self): self.item.modify(finished=self.finished.get() > 0) @@ -65,26 +70,69 @@ class ToDoListWidget(tk.Frame): super().__init__(*args, **argv) self.delete_list = delete_list - def fill(self, itemList): + def create_table_header(self, body): - header = ToDoItemWidget.header(self) - header.pack(side="left") - header.pack(side="top", fill="y") + header_font = ("Arial", "10", "bold") + text = tk.Label( + body, + text=_("Текст"), + width=TODO_ITEM_TABLE_TEXT_WIDTH, + justify="center", + font=header_font, + ) + text.grid(row=0, column=0) + + done = tk.Label( + body, + text=_("Выполнено"), + width=TODO_ITEM_TABLE_FINISHED_WIDTH, + justify="center", + font=header_font, + ) + done.grid(row=0, column=1) + + created = tk.Label( + body, + text=_("Создано"), + width=TODO_ITEM_TABLE_CREATED_AT_WIDTH, + justify="center", + font=header_font, + ) + created.grid(row=0, column=2) + + def create_table(self, itemList): + table = tk.LabelFrame(self, relief=tk.GROOVE) + table.grid() + self.create_table_header(table) self.itemList = itemList - + row_number = 1 for item in itemList: - item = ToDoItemWidget(self, item=item) - item.pack(side="top", fill="y") + item = ToDoItemWidget(self, row_number=row_number, item=item, table=table) + row_number += 1 + return table - self.itemToAdd = tk.Text(self, width=15, height=1) - self.itemToAdd.pack(side="top") + def create_new_item(self): + table = tk.LabelFrame(self, relief=tk.GROOVE) + table.grid() + self.itemToAdd = tk.Text(table, width=15, height=1) + self.itemToAdd.grid(row=0, column=0) - add = tk.Button(self, text="Добавить заметку", command=self.add_command) - add.pack(side="top") + add = tk.Button(table, text=_("Добавить заметку"), command=self.add_command) + add.grid(row=0, column=1) + return table - delete = tk.Button(self, text="Удалить лист", command=self.delete_list) - delete.pack(side="top") + def fill(self, itemList): + self.frame = tk.LabelFrame(self, relief=tk.GROOVE) + self.frame.grid(sticky="NEWS") + table = self.create_table(itemList) + table.grid(row=0, column=0) + + new = self.create_new_item() + new.grid(row=2, column=0) + + delete = tk.Button(self, text=_("Удалить лист"), command=self.delete_list) + delete.grid(row=4, column=0) def update(self, itemList=None): self.clear() @@ -141,7 +189,7 @@ class WorkSpaceFrame(tk.Frame): # Запомнить пользователя self.rbtn_var = tk.IntVar(value=1) - rbtn = tk.Checkbutton(self, text="Запомнить меня", variable=self.rbtn_var, command=None) + rbtn = tk.Checkbutton(self, text=_("Запомнить меня"), variable=self.rbtn_var, command=None) rbtn.pack(anchor="n") # data @@ -150,7 +198,7 @@ class WorkSpaceFrame(tk.Frame): self.add_list_text = tk.Text(self, width=15, height=1) self.add_list_text.pack(anchor="sw") - add = tk.Button(self, text="Добавить лист", command=self.add_list) + add = tk.Button(self, text=_("Добавить лист"), command=self.add_list) add.pack(anchor="sw") # select list box