diff --git a/src/main/java/cz/muni/fi/pv168/project/data/category/Category.java b/src/main/java/cz/muni/fi/pv168/project/data/category/Category.java
index 525daa8e5028a317f8aea6957bc287b699c8178e..62935b668b564872bf9a4943d0511030fd27f702 100644
--- a/src/main/java/cz/muni/fi/pv168/project/data/category/Category.java
+++ b/src/main/java/cz/muni/fi/pv168/project/data/category/Category.java
@@ -79,6 +79,7 @@ public class Category implements Identifiable {
         timeSpents.removeIf(categoryTime -> categoryTime.getTaskId().equals(taskId));
     }
 
+    //TODO: add support for language structures in localization
     private PeriodFormatter createFormatter() {
         return new PeriodFormatterBuilder()
                 .appendDays()
diff --git a/src/main/java/cz/muni/fi/pv168/project/data/task/TaskStatus.java b/src/main/java/cz/muni/fi/pv168/project/data/task/TaskStatus.java
index 31afb954cabcf9ae9ed09ef8a09b364c99e9093e..9e3b0fcf2ceef326daf2985ff45bcb9b17d6b87c 100644
--- a/src/main/java/cz/muni/fi/pv168/project/data/task/TaskStatus.java
+++ b/src/main/java/cz/muni/fi/pv168/project/data/task/TaskStatus.java
@@ -11,6 +11,7 @@ public enum TaskStatus {
     @Override
     public String toString() {
         String value = this.name().replace("_", " ");
+        //TODO: solve hardcoded locale of root
         return value.charAt(0) + value.substring(1).toLowerCase(Locale.ROOT);
     }
 
diff --git a/src/main/java/cz/muni/fi/pv168/project/model/CategoryStatisticsTableModel.java b/src/main/java/cz/muni/fi/pv168/project/model/CategoryStatisticsTableModel.java
index 12f87f0810dfb5cc76eef7c01282773cf738f4ac..3c325bad78f5347cdaa83edbef704ad6950e1e25 100644
--- a/src/main/java/cz/muni/fi/pv168/project/model/CategoryStatisticsTableModel.java
+++ b/src/main/java/cz/muni/fi/pv168/project/model/CategoryStatisticsTableModel.java
@@ -1,6 +1,7 @@
 package cz.muni.fi.pv168.project.model;
 
 import cz.muni.fi.pv168.project.data.category.Category;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 
 import javax.swing.ListModel;
 import javax.swing.event.ListDataEvent;
@@ -13,6 +14,8 @@ public class CategoryStatisticsTableModel extends AbstractTableModel implements
     private LocalDate fromDate;
     private LocalDate toDate;
 
+    private static final I18N I18N = new I18N(CategoryStatisticsTableModel.class);
+
     public CategoryStatisticsTableModel(ListModel<Category> model) {
         fromDate = LocalDate.now();
         toDate = LocalDate.now();
@@ -48,9 +51,9 @@ public class CategoryStatisticsTableModel extends AbstractTableModel implements
     public String getColumnName(int columnIndex) {
         switch (columnIndex) {
             case 0:
-                return "Category name";
+                return I18N.getString("columnNameTitle");
             case 1:
-                return "Time spent";
+                return I18N.getString("columnTimeTitle");
             default:
                 throw new IndexOutOfBoundsException("Invalid column index: " + columnIndex);
         }
diff --git a/src/main/java/cz/muni/fi/pv168/project/model/db/AbstractDataModel.java b/src/main/java/cz/muni/fi/pv168/project/model/db/AbstractDataModel.java
index fc8e0fd0dc5a2b3648b450e564e530b913c81778..36aeaabc0d1cdc9bf4830529909452c6850d569f 100644
--- a/src/main/java/cz/muni/fi/pv168/project/model/db/AbstractDataModel.java
+++ b/src/main/java/cz/muni/fi/pv168/project/model/db/AbstractDataModel.java
@@ -2,18 +2,21 @@ package cz.muni.fi.pv168.project.model.db;
 
 import cz.muni.fi.pv168.project.model.EditableModel;
 import cz.muni.fi.pv168.project.ui.dialog.error.ErrorDialog;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 
 import javax.swing.DefaultListModel;
 
 public abstract class AbstractDataModel<E> extends DefaultListModel<E> implements EditableModel<E> {
 
+    private static final I18N I18N = new I18N(AbstractDataModel.class);
+
     @Override
     public void setElementAt(E element, int index) {
         try {
             update(element);
         } catch (Exception e) {
             e.printStackTrace();
-            ErrorDialog.show("Error when editing " + element, e);
+            ErrorDialog.show(I18N.getString("editingEntError") + " " + element, e);
         }
         super.setElementAt(element, index);
     }
@@ -24,7 +27,7 @@ public abstract class AbstractDataModel<E> extends DefaultListModel<E> implement
             add(element);
         } catch (Exception e) {
             e.printStackTrace();
-            ErrorDialog.show("Error when adding " + element, e);
+            ErrorDialog.show(I18N.getString("addingEntError") + " " + element, e);
         }
 
         super.addElement(element);
@@ -37,7 +40,7 @@ public abstract class AbstractDataModel<E> extends DefaultListModel<E> implement
             delete((E) obj);
         } catch (Exception e) {
             e.printStackTrace();
-            ErrorDialog.show("Error when removing " + obj, e);
+            ErrorDialog.show(I18N.getString("deletingEntError") + " " + obj, e);
         }
         return super.removeElement(obj);
     }
diff --git a/src/main/java/cz/muni/fi/pv168/project/model/db/TaskModel.java b/src/main/java/cz/muni/fi/pv168/project/model/db/TaskModel.java
index 13a8842d4906660f8e8b13cfa84d4366415cad3f..8e6ed12e88c60b820a729f88ee2e6cff1e9519c5 100644
--- a/src/main/java/cz/muni/fi/pv168/project/model/db/TaskModel.java
+++ b/src/main/java/cz/muni/fi/pv168/project/model/db/TaskModel.java
@@ -4,12 +4,15 @@ import cz.muni.fi.pv168.project.data.task.Task;
 import cz.muni.fi.pv168.project.db.DataAccessException;
 import cz.muni.fi.pv168.project.db.interfaces.DataAccessObject;
 import cz.muni.fi.pv168.project.ui.dialog.error.ErrorDialog;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 
 import java.util.ArrayList;
 import java.util.function.Predicate;
 
 public class TaskModel extends UpdatableDataModel<Task> {
 
+    private static final I18N I18N = new I18N(TaskModel.class);
+
     public TaskModel(DataAccessObject<Task> dao) {
         super(dao);
     }
@@ -26,7 +29,7 @@ public class TaskModel extends UpdatableDataModel<Task> {
             addAll(tasks);
         } catch (DataAccessException e) {
             e.printStackTrace();
-            ErrorDialog.show("Error when querying all elements.", e);
+            ErrorDialog.show(I18N.getString("queryAllError"), e);
         }
     }
 }
diff --git a/src/main/java/cz/muni/fi/pv168/project/model/db/UpdatableDataModel.java b/src/main/java/cz/muni/fi/pv168/project/model/db/UpdatableDataModel.java
index 781a685a7baf3e7af6fd57850810117d08b046c8..3757454228f6fea066e9717b39fbc63170bb7dae 100644
--- a/src/main/java/cz/muni/fi/pv168/project/model/db/UpdatableDataModel.java
+++ b/src/main/java/cz/muni/fi/pv168/project/model/db/UpdatableDataModel.java
@@ -2,11 +2,14 @@ package cz.muni.fi.pv168.project.model.db;
 
 import cz.muni.fi.pv168.project.db.interfaces.DataAccessObject;
 import cz.muni.fi.pv168.project.ui.dialog.error.ErrorDialog;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 
 public class UpdatableDataModel<E> extends AbstractDataModel<E> {
 
     protected final DataAccessObject<E> dataAccessObject;
 
+    private static final I18N I18N = new I18N(UpdatableDataModel.class);
+
     public UpdatableDataModel(DataAccessObject<E> dao) {
         this.dataAccessObject = dao;
         updateAll();
@@ -33,7 +36,7 @@ public class UpdatableDataModel<E> extends AbstractDataModel<E> {
             addAll(dataAccessObject.getAll());
         } catch (Exception e) {
             e.printStackTrace();
-            ErrorDialog.show("Error when querying all elements.", e);
+            ErrorDialog.show(I18N.getString("queryAllError"), e);
         }
     }
 }
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/action/AddAction.java b/src/main/java/cz/muni/fi/pv168/project/ui/action/AddAction.java
index b0920eb28a5d9471566fa842dc283f9bcfad6cc3..65839010d2cf48b5faa462276def18954086d633 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/action/AddAction.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/action/AddAction.java
@@ -1,5 +1,6 @@
 package cz.muni.fi.pv168.project.ui.action;
 
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import cz.muni.fi.pv168.project.ui.main.tab.ListHolder;
 
 import javax.swing.Icon;
@@ -9,10 +10,12 @@ import java.awt.event.KeyEvent;
 
 public final class AddAction<T> extends AbstractAction<T> {
 
+    private static final I18N I18N = new I18N(AddAction.class);
+
     public AddAction(ListHolder<T> listHolder, Icon icon, String description) {
         super(listHolder, selectedRowsCount -> true);
 
-        putValue(NAME, "Add");
+        putValue(NAME, I18N.getString("addAction"));
         putValue(SMALL_ICON, icon);
         putValue(SHORT_DESCRIPTION, description);
         putValue(MNEMONIC_KEY, KeyEvent.VK_A);
@@ -23,7 +26,7 @@ public final class AddAction<T> extends AbstractAction<T> {
     public void actionPerformed(ActionEvent e) {
         var maybeResult = getDialogFactory()
                 .newAddDialog()
-                .show("Add");
+                .show(I18N.getString("addAction"));
 
         maybeResult.ifPresent(t -> {
             listHolder.getModel().addElement(t);
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/action/DeleteAction.java b/src/main/java/cz/muni/fi/pv168/project/ui/action/DeleteAction.java
index 7a398f96a3d6714bdcece44fe4a2cfcc8ff618cf..2f99853f07f6facd83ee8d9aa3efc7ec0907da0c 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/action/DeleteAction.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/action/DeleteAction.java
@@ -1,5 +1,6 @@
 package cz.muni.fi.pv168.project.ui.action;
 
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import cz.muni.fi.pv168.project.ui.main.tab.ListHolder;
 
 import javax.swing.Icon;
@@ -12,10 +13,12 @@ import java.util.List;
 
 public final class DeleteAction<T> extends AbstractAction<T> {
 
+    private static final I18N I18N = new I18N(DeleteAction.class);
+
     public DeleteAction(ListHolder<T> listHolder, Icon icon, String description) {
         super(listHolder, selectedRowsCount -> selectedRowsCount >= 1);
 
-        putValue(NAME, "Delete");
+        putValue(NAME, I18N.getString("deleteAction"));
         putValue(SMALL_ICON, icon);
         putValue(SHORT_DESCRIPTION, description);
         putValue(MNEMONIC_KEY, KeyEvent.VK_D);
@@ -24,7 +27,7 @@ public final class DeleteAction<T> extends AbstractAction<T> {
 
     @Override
     public void actionPerformed(ActionEvent e) {
-        int result = JOptionPane.showConfirmDialog(listHolder.getList(), "Are you sure you want to delete?");
+        int result = JOptionPane.showConfirmDialog(listHolder.getList(), I18N.getString("confirmation"));
         if (result != JOptionPane.OK_OPTION) {
             return;
         }
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/action/EditAction.java b/src/main/java/cz/muni/fi/pv168/project/ui/action/EditAction.java
index f58f080d38acd6d1654153ea389d6cec6eb48d84..f4c83818c798f4b5b261ec4df4d7f280d7a763d4 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/action/EditAction.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/action/EditAction.java
@@ -1,6 +1,7 @@
 package cz.muni.fi.pv168.project.ui.action;
 
 import cz.muni.fi.pv168.project.data.task.Task;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import cz.muni.fi.pv168.project.ui.main.tab.ListHolder;
 import org.jetbrains.annotations.Nullable;
 
@@ -13,10 +14,11 @@ import java.util.function.Supplier;
 
 public final class EditAction<T> extends AbstractAction<T> {
 
+    private static final cz.muni.fi.pv168.project.ui.i18n.I18N I18N = new I18N(EditAction.class);
     public EditAction(ListHolder<T> listHolder, Icon icon, String description, @Nullable Supplier<Task> taskSupplier) {
         super(listHolder, selectedRowsCount -> selectedRowsCount == 1, taskSupplier);
 
-        putValue(NAME, "Edit");
+        putValue(NAME, I18N.getString("editAction"));
         putValue(SMALL_ICON, icon);
         putValue(SHORT_DESCRIPTION, description);
         putValue(MNEMONIC_KEY, KeyEvent.VK_E);
@@ -38,7 +40,7 @@ public final class EditAction<T> extends AbstractAction<T> {
 
         var maybeResult = getDialogFactory()
                 .newEditDialog(list.getSelectedValue())
-                .show("Edit");
+                .show(I18N.getString("editAction"));
 
         maybeResult.ifPresent(t -> {
             listHolder.getModel().setElementAt(t, listHolder.getModel().indexOf(t));
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/action/task/GoToAction.java b/src/main/java/cz/muni/fi/pv168/project/ui/action/task/GoToAction.java
index 38779db5cb04d30db1cd2223ef696ba78c5a5e4f..5d76b37f834041db83b0cbec3106f2a2c6b27a25 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/action/task/GoToAction.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/action/task/GoToAction.java
@@ -2,6 +2,7 @@ package cz.muni.fi.pv168.project.ui.action.task;
 
 import cz.muni.fi.pv168.project.data.task.Task;
 import cz.muni.fi.pv168.project.ui.action.AbstractAction;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import cz.muni.fi.pv168.project.ui.main.tab.ListHolder;
 
 import javax.swing.JList;
@@ -13,12 +14,13 @@ import java.util.List;
 public final class GoToAction extends AbstractAction<Task> {
 
     private final JList<Task> destinationList;
+    private static final I18N I18N = new I18N(GoToAction.class);
 
     public GoToAction(ListHolder<Task> sourceListHolder, JList<Task> destinationList, String description) {
         super(sourceListHolder, selectedRowsCount -> selectedRowsCount == 1);
         this.destinationList = destinationList;
 
-        putValue(NAME, "Go to task");
+        putValue(NAME, I18N.getString("goTo"));
         putValue(SHORT_DESCRIPTION, description);
         putValue(MNEMONIC_KEY, KeyEvent.VK_G);
         putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl G"));
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/action/task/ToggleCompletionAction.java b/src/main/java/cz/muni/fi/pv168/project/ui/action/task/ToggleCompletionAction.java
index 0a6fe08bbcacea94e1fab975d44735a893a5c3b4..22ebb3fc7ba56ca4d0eaf94f7d148e703ff00a09 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/action/task/ToggleCompletionAction.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/action/task/ToggleCompletionAction.java
@@ -3,6 +3,7 @@ package cz.muni.fi.pv168.project.ui.action.task;
 import cz.muni.fi.pv168.project.data.task.ITask;
 import cz.muni.fi.pv168.project.data.task.Task;
 import cz.muni.fi.pv168.project.ui.action.AbstractAction;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import cz.muni.fi.pv168.project.ui.main.tab.ListHolder;
 import org.jetbrains.annotations.Nullable;
 
@@ -14,10 +15,12 @@ import java.util.function.Supplier;
 
 public class ToggleCompletionAction<T extends ITask> extends AbstractAction<T> {
 
+    private static final I18N I18N = new I18N(ToggleCompletionAction.class);
+
     public ToggleCompletionAction(ListHolder<T> listHolder, String description, @Nullable Supplier<Task> taskSupplier) {
         super(listHolder, selectedRowsCount -> selectedRowsCount == 1, taskSupplier);
 
-        putValue(NAME, "Toggle completion");
+        putValue(NAME, I18N.getString("toggleAction"));
         putValue(SHORT_DESCRIPTION, description);
         putValue(MNEMONIC_KEY, KeyEvent.VK_T);
         putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl T"));
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/dialog/AbstractEntityDialog.java b/src/main/java/cz/muni/fi/pv168/project/ui/dialog/AbstractEntityDialog.java
index 418bafb056f596b1ca8ba07a8774049bf18088b9..1e4cb007381f59bc92892eb2d334e8b7cd7b4766 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/dialog/AbstractEntityDialog.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/dialog/AbstractEntityDialog.java
@@ -1,6 +1,7 @@
 package cz.muni.fi.pv168.project.ui.dialog;
 
 import cz.muni.fi.pv168.project.ui.centering.WindowCenterer;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import cz.muni.fi.pv168.project.ui.resources.Icons;
 
 import javax.swing.BorderFactory;
@@ -23,6 +24,8 @@ abstract class AbstractEntityDialog<E> extends JDialog {
     private final JPanel panel;
     private final JButton okButton;
 
+    private static final I18N I18N = new I18N(AbstractEntityDialog.class);
+
     private boolean wasOk;
 
     AbstractEntityDialog() {
@@ -30,12 +33,12 @@ abstract class AbstractEntityDialog<E> extends JDialog {
         panel.setLayout(new GridBagLayout());
 
         wasOk = false;
-        okButton = new JButton("OK");
+        okButton = new JButton(I18N.getString("buttonConfirm"));
         okButton.addActionListener(e -> {
             wasOk = true;
             this.dispose();
         });
-        JButton cancelButton = new JButton("Cancel");
+        JButton cancelButton = new JButton(I18N.getString("buttonDismiss"));
         cancelButton.addActionListener(e -> this.dispose());
 
         GridBagConstraints gbc = new GridBagConstraints();
@@ -54,7 +57,7 @@ abstract class AbstractEntityDialog<E> extends JDialog {
         gbc.gridx = 2;
         okCancelPanel.add(cancelButton, gbc);
 
-        this.setTitle("New filesystem VM");
+        this.setTitle(I18N.getString("vmTitle"));
         this.setMinimumSize(new Dimension(300, 100));
         this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
         this.setModalityType(ModalityType.APPLICATION_MODAL);
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/dialog/CategoryDialog.java b/src/main/java/cz/muni/fi/pv168/project/ui/dialog/CategoryDialog.java
index a084b31dcd55c78b37547df4eb0e5d1f942a62ef..2e3d3a0b675096c5ccef1abbb658db43afd90bf6 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/dialog/CategoryDialog.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/dialog/CategoryDialog.java
@@ -3,6 +3,7 @@ package cz.muni.fi.pv168.project.ui.dialog;
 import cz.muni.fi.pv168.project.color.AppColors;
 import cz.muni.fi.pv168.project.data.category.Category;
 import cz.muni.fi.pv168.project.ui.component.SimpleColorChooser;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 
 import javax.swing.JLabel;
 import javax.swing.JTextField;
@@ -16,6 +17,8 @@ public class CategoryDialog extends AbstractLaidOutDialog<Category> {
     private final SimpleColorChooser colorField = new SimpleColorChooser();
     private final JLabel colorCodeField = new JLabel();
 
+    private static final I18N I18N = new I18N(CategoryDialog.class);
+
     public CategoryDialog() {
         colorCodeField.setText("#FFFFFF");
         colorField.getSelectionModel().addChangeListener(
@@ -34,8 +37,8 @@ public class CategoryDialog extends AbstractLaidOutDialog<Category> {
     }
 
     private void addFields() {
-        addLabeledField("Name:", nameField, labelGbc, componentGbc, getRowThenIncrement());
-        addLabeledField("Color:", colorField, labelGbc, componentGbc, getRowThenIncrement());
+        addLabeledField(I18N.getString("fieldLabelName"), nameField, labelGbc, componentGbc, getRowThenIncrement());
+        addLabeledField(I18N.getString("fieldLabelColor"), colorField, labelGbc, componentGbc, getRowThenIncrement());
 
         var colorCodeGbc = (GridBagConstraints) labelGbc.clone();
         colorCodeGbc.fill = GridBagConstraints.CENTER;
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/dialog/ComboBoxDialog.java b/src/main/java/cz/muni/fi/pv168/project/ui/dialog/ComboBoxDialog.java
index 5eab0d5d5c89c74629fd279b694e54c806131abe..1ebbeea5b489c8d95b0df780ff1c1e92ca2b4516 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/dialog/ComboBoxDialog.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/dialog/ComboBoxDialog.java
@@ -1,6 +1,7 @@
 package cz.muni.fi.pv168.project.ui.dialog;
 
 import cz.muni.fi.pv168.project.model.ComboBoxModelAdapter;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 
 import javax.swing.JComboBox;
 import java.util.Collection;
@@ -8,10 +9,11 @@ import java.util.Collection;
 public class ComboBoxDialog<T> extends AbstractLaidOutDialog<T> {
 
     private final JComboBox<T> comboBox;
+    private static final I18N I18N = new I18N(ComboBoxDialog.class);
 
     public ComboBoxDialog(Collection<T> entities) {
         comboBox = new JComboBox<>(ComboBoxModelAdapter.fromCollection(entities));
-        addLabeledField("Select :", comboBox, labelGbc, middleComponent, getRow());
+        addLabeledField(I18N.getString("fieldLabelSelect"), comboBox, labelGbc, middleComponent, getRow());
 
         // gray out button when nothing is initially selected
         getOkButton().setEnabled(false);
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/dialog/SubTaskDialog.java b/src/main/java/cz/muni/fi/pv168/project/ui/dialog/SubTaskDialog.java
index 788fbe778099ba52f935146d9e1d3b52329e20b3..f7bb0d55bfb1f9a47c3a893c91b42532160d08fd 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/dialog/SubTaskDialog.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/dialog/SubTaskDialog.java
@@ -1,6 +1,7 @@
 package cz.muni.fi.pv168.project.ui.dialog;
 
 import cz.muni.fi.pv168.project.data.task.SubTask;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 
 import javax.swing.JTextField;
 
@@ -9,6 +10,8 @@ public class SubTaskDialog extends AbstractLaidOutDialog<SubTask> {
     protected SubTask entity;
     protected final JTextField titleField = new JTextField();
 
+    private static final I18N I18N = new I18N(SubTaskDialog.class);
+
     public SubTaskDialog() {
         entity = new SubTask("");
         this.addTitle();
@@ -23,7 +26,7 @@ public class SubTaskDialog extends AbstractLaidOutDialog<SubTask> {
     }
 
     protected void addTitle() {
-        addLabeledField("Title:", titleField, labelGbc, componentGbc, getRowThenIncrement());
+        addLabeledField(I18N.getString("fieldLabelTitle"), titleField, labelGbc, componentGbc, getRowThenIncrement());
     }
 
     @Override
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/dialog/TaskDialog.java b/src/main/java/cz/muni/fi/pv168/project/ui/dialog/TaskDialog.java
index 45d59ea52dab6812b891532129a0812d9a9b40e1..31c99faba15eacc3fbf1137ab93b1a1077c24df0 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/dialog/TaskDialog.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/dialog/TaskDialog.java
@@ -2,6 +2,7 @@ package cz.muni.fi.pv168.project.ui.dialog;
 
 import cz.muni.fi.pv168.project.data.task.Task;
 import cz.muni.fi.pv168.project.model.LocalDateModel;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import org.jdatepicker.DateModel;
 import org.jdatepicker.JDatePicker;
 import org.joda.time.Duration;
@@ -31,6 +32,8 @@ public class TaskDialog extends AbstractLaidOutDialog<Task> {
     private final JTextField estimatedTimeField = new IntegerTextField(0);
     private final JDatePicker datePicker = new JDatePicker(dueTimeModel);
 
+    private static final I18N I18N = new I18N(TaskDialog.class);
+
     public TaskDialog() {
         descriptionField.setLineWrap(true);
         descriptionField.setFont(descriptionField.getFont().deriveFont(11f));
@@ -45,17 +48,17 @@ public class TaskDialog extends AbstractLaidOutDialog<Task> {
     }
 
     protected void addFields() {
-        addLabeledField("Title:", titleField, labelGbc, componentGbc, getRowThenIncrement());
-        addLabeledField("Description:", new JScrollPane(descriptionField), labelGbc, componentGbc, getRowThenIncrement());
-        addLabeledField("Estimated time:", createEstimatedTimePanel(), labelGbc, componentGbc, getRowThenIncrement());
-        addLabeledField("Due time:", datePicker, labelGbc, componentGbc, getRowThenIncrement());
+        addLabeledField(I18N.getString("labelTitle"), titleField, labelGbc, componentGbc, getRowThenIncrement());
+        addLabeledField(I18N.getString("labelDescription"), new JScrollPane(descriptionField), labelGbc, componentGbc, getRowThenIncrement());
+        addLabeledField(I18N.getString("labelEstTime"), createEstimatedTimePanel(), labelGbc, componentGbc, getRowThenIncrement());
+        addLabeledField(I18N.getString("labelDueTime"), datePicker, labelGbc, componentGbc, getRowThenIncrement());
     }
 
     private JPanel createEstimatedTimePanel() {
         JPanel estimatePanel = new JPanel(new BorderLayout());
 
         estimatePanel.add(estimatedTimeField, BorderLayout.CENTER);
-        estimatePanel.add(new JLabel(" hours"), BorderLayout.EAST);
+        estimatePanel.add(new JLabel(" " + I18N.getString("estimatedTimeUnit")), BorderLayout.EAST);
 
         return estimatePanel;
     }
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/dialog/error/ErrorDialog.java b/src/main/java/cz/muni/fi/pv168/project/ui/dialog/error/ErrorDialog.java
index 84b02d525ce0c5505f87db958db9bf81ef3bd676..7b9592e314f219c9b70a49e1c93607393b5a0509 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/dialog/error/ErrorDialog.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/dialog/error/ErrorDialog.java
@@ -1,5 +1,6 @@
 package cz.muni.fi.pv168.project.ui.dialog.error;
 
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
@@ -15,6 +16,7 @@ import java.io.StringWriter;
 public final class ErrorDialog {
 
     private final JPanel panel = new JPanel();
+    private static final I18N I18N = new I18N(ErrorDialog.class);
 
     private ErrorDialog(String message, Throwable throwable) {
         panel.setLayout(new GridBagLayout());
@@ -39,7 +41,7 @@ public final class ErrorDialog {
     private void show(Component parentComponent) {
         JOptionPane.showMessageDialog(parentComponent,
                 panel,
-                "Error occurred",
+                I18N.getString("error"),
                 JOptionPane.ERROR_MESSAGE);
     }
 
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/WelcomePanel.java b/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/WelcomePanel.java
index 9a67f20b9a95909be2714592de7a8bb750d75ba1..51e7f77bf0dc4478bcd5432453ceaf92f608e714 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/WelcomePanel.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/WelcomePanel.java
@@ -1,5 +1,7 @@
 package cz.muni.fi.pv168.project.ui.main.panel;
 
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
+
 import javax.swing.BorderFactory;
 import javax.swing.JPanel;
 import javax.swing.JTextArea;
@@ -13,11 +15,9 @@ import java.awt.Font;
 public class WelcomePanel {
 
     private final JPanel panel;
-    private static final String WELCOME_MESSAGE =
-            "Welcome to to:do, your daily task reminder.\n" + "\n" +
-            "You can use the toolbar buttons above to add, edit, or delete tasks and categories.\n" +
-            "Switch between tasks and categories using the tabs.\n" +
-            "Click on a task in the list on the left to see details.";
+
+    private static final I18N I18N = new I18N(WelcomePanel.class);
+    private static final String WELCOME_MESSAGE = I18N.getString("welcomeMessage");
 
     public WelcomePanel() {
         var welcomeTextArea = new JTextArea(WELCOME_MESSAGE);
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/listholder/CategoryHolderPanel.java b/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/listholder/CategoryHolderPanel.java
index e8f921ef86f9b5d8f4abb649ce830f13750de758..19cf68449baaf03d7ede4a49b74637f68693ee93 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/listholder/CategoryHolderPanel.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/listholder/CategoryHolderPanel.java
@@ -9,6 +9,7 @@ import cz.muni.fi.pv168.project.ui.action.DeleteAction;
 import cz.muni.fi.pv168.project.ui.action.EditAction;
 import cz.muni.fi.pv168.project.ui.dialog.factory.DialogFactory;
 import cz.muni.fi.pv168.project.ui.dialog.factory.ExistingCategoryDialogFactory;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import cz.muni.fi.pv168.project.ui.popup.PopupMenuFactory;
 import cz.muni.fi.pv168.project.ui.renderer.list.InnerColoredListRenderer;
 import cz.muni.fi.pv168.project.ui.resources.Icons;
@@ -20,17 +21,19 @@ public class CategoryHolderPanel extends AbstractHolderPanel<Category> {
 
     private final ExistingCategoryDialogFactory factory;
 
+    private static final I18N I18N = new I18N(CategoryHolderPanel.class);
+
     public CategoryHolderPanel(TaskCategoryDao categoryDao, CategoryDao parentDao) {
         super(
-                new TaskCategoryModel(categoryDao, parentDao), "Categories",
+                new TaskCategoryModel(categoryDao, parentDao), I18N.getString("panelName"),
                 new InnerColoredListRenderer<>(Category::getName, Category::getColor, Font.BOLD | Font.ITALIC),
                 Optional.empty());
 
         factory = new ExistingCategoryDialogFactory(parentDao);
         PopupMenuFactory.builder()
-                .addMenuItem(new AddAction<>(this, Icons.ADD_CATEGORY_ICON, "Add category").addUpdatable(this))
-                .addMenuItem(new EditAction<>(this, Icons.EDIT_CATEGORY_ICON, "Edit category").addUpdatable(this))
-                .addMenuItem(new DeleteAction<>(this, Icons.REMOVE_CATEGORY_BIN_ICON, "Remove category").addUpdatable(this))
+                .addMenuItem(new AddAction<>(this, Icons.ADD_CATEGORY_ICON, I18N.getString("addCategoryOption")).addUpdatable(this))
+                .addMenuItem(new EditAction<>(this, Icons.EDIT_CATEGORY_ICON, I18N.getString("editCategoryOption")).addUpdatable(this))
+                .addMenuItem(new DeleteAction<>(this, Icons.REMOVE_CATEGORY_BIN_ICON, I18N.getString("removeCategoryOption")).addUpdatable(this))
                 .buildFor(this.getList());
     }
 
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/listholder/DependencyHolderPanel.java b/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/listholder/DependencyHolderPanel.java
index 3ce31ffcc0abfb358a110203ae3a63ba96bd0064..dadb40d6e348542f5fc8b0321566ec8fb9f4919e 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/listholder/DependencyHolderPanel.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/listholder/DependencyHolderPanel.java
@@ -9,6 +9,7 @@ import cz.muni.fi.pv168.project.ui.action.DeleteAction;
 import cz.muni.fi.pv168.project.ui.action.task.GoToAction;
 import cz.muni.fi.pv168.project.ui.dialog.factory.DependencyTaskDialogFactory;
 import cz.muni.fi.pv168.project.ui.dialog.factory.DialogFactory;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import cz.muni.fi.pv168.project.ui.popup.PopupMenuFactory;
 import cz.muni.fi.pv168.project.ui.renderer.list.TaskStatusListRenderer;
 import cz.muni.fi.pv168.project.ui.resources.Icons;
@@ -21,19 +22,21 @@ public class DependencyHolderPanel extends AbstractHolderPanel<Task> {
 
     private final DependencyTaskDialogFactory factory;
 
+    private static final I18N I18N = new I18N(DependencyHolderPanel.class);
+
     public DependencyHolderPanel(JList<Task> superiorTaskList, DependencyDao dependencyDao, TaskDao taskDao) {
         super(
-                new TaskDependencyModel(dependencyDao), "Dependencies",
+                new TaskDependencyModel(dependencyDao), I18N.getString("panelName"),
                 new TaskStatusListRenderer<>(Task::getTitle, Task::getTaskStatus, Task::isUrgent, Font.PLAIN),
                 Optional.of(Task::isCompleted)
         );
 
         factory = new DependencyTaskDialogFactory(dependencyDao, taskDao);
         PopupMenuFactory.builder()
-                .addMenuItem(new GoToAction(this, superiorTaskList, "Go to dependency"))
+                .addMenuItem(new GoToAction(this, superiorTaskList, I18N.getString("goToAction")))
                 .addSeparator()
-                .addMenuItem(new AddAction<>(this, Icons.ADD_TASK_ICON, "Add dependency").addUpdatable(this))
-                .addMenuItem(new DeleteAction<>(this, Icons.REMOVE_TASK_BIN_ICON, "Remove dependency").addUpdatable(this))
+                .addMenuItem(new AddAction<>(this, Icons.ADD_TASK_ICON, I18N.getString("addAction")).addUpdatable(this))
+                .addMenuItem(new DeleteAction<>(this, Icons.REMOVE_TASK_BIN_ICON, I18N.getString("removeAction")).addUpdatable(this))
                 .buildFor(this.getList());
     }
 
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/listholder/SubTaskHolderPanel.java b/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/listholder/SubTaskHolderPanel.java
index 159a637eb1073fd63d865dd7378f3b94cdba54f0..6662ce493f2d0840a4f84188c737818cdbe8c292 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/listholder/SubTaskHolderPanel.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/main/panel/listholder/SubTaskHolderPanel.java
@@ -10,6 +10,7 @@ import cz.muni.fi.pv168.project.ui.action.EditAction;
 import cz.muni.fi.pv168.project.ui.action.task.ToggleCompletionAction;
 import cz.muni.fi.pv168.project.ui.dialog.factory.DialogFactory;
 import cz.muni.fi.pv168.project.ui.dialog.factory.SubTaskDialogFactory;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import cz.muni.fi.pv168.project.ui.popup.PopupMenuFactory;
 import cz.muni.fi.pv168.project.ui.renderer.list.TaskStatusListRenderer;
 import cz.muni.fi.pv168.project.ui.resources.Icons;
@@ -19,20 +20,22 @@ import java.util.Optional;
 
 public class SubTaskHolderPanel extends AbstractHolderPanel<SubTask> {
 
+    private static final I18N I18N = new I18N(SubTaskHolderPanel.class);
+
     public SubTaskHolderPanel(SubTaskDao subTaskDao) {
         super(
-                new SubTaskModel(subTaskDao), "Sub tasks",
+                new SubTaskModel(subTaskDao), I18N.getString("panelName"),
                 new TaskStatusListRenderer<>(SubTask::getTitle,
                         task -> task.isCompleted() ? TaskStatus.FINISHED : TaskStatus.PLANNED, task -> false, Font.PLAIN),
                 Optional.of(SubTask::isCompleted)
         );
 
         PopupMenuFactory.builder()
-                .addMenuItem(new ToggleCompletionAction<>(this, "Toggle completion").addUpdatable(this))
+                .addMenuItem(new ToggleCompletionAction<>(this, I18N.getString("completionToggle")).addUpdatable(this))
                 .addSeparator()
-                .addMenuItem(new AddAction<>(this, Icons.ADD_TASK_ICON, "Add subtask").addUpdatable(this))
-                .addMenuItem(new EditAction<>(this, Icons.EDIT_TASK_ICON, "Edit subtask").addUpdatable(this))
-                .addMenuItem(new DeleteAction<>(this, Icons.REMOVE_TASK_BIN_ICON, "Remove subtask").addUpdatable(this))
+                .addMenuItem(new AddAction<>(this, Icons.ADD_TASK_ICON, I18N.getString("addAction")).addUpdatable(this))
+                .addMenuItem(new EditAction<>(this, Icons.EDIT_TASK_ICON, I18N.getString("editAction")).addUpdatable(this))
+                .addMenuItem(new DeleteAction<>(this, Icons.REMOVE_TASK_BIN_ICON, I18N.getString("removeAction")).addUpdatable(this))
                 .buildFor(this.getList());
     }
 
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/main/toolbar/CategoriesStatisticsToolBar.java b/src/main/java/cz/muni/fi/pv168/project/ui/main/toolbar/CategoriesStatisticsToolBar.java
index 15376a32d75d1bcfd6349cf89665e266ac59ab24..8fab7c67656b3a52fc48d1404ecefbf2f0db4f00 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/main/toolbar/CategoriesStatisticsToolBar.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/main/toolbar/CategoriesStatisticsToolBar.java
@@ -2,6 +2,7 @@ package cz.muni.fi.pv168.project.ui.main.toolbar;
 
 import cz.muni.fi.pv168.project.model.LocalDateModel;
 import cz.muni.fi.pv168.project.ui.action.TabActions;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import org.jdatepicker.JDatePicker;
 
 import javax.swing.Action;
@@ -19,6 +20,8 @@ public class CategoriesStatisticsToolBar {
     private final JDatePicker showStatisticsFrom;
     private final JDatePicker showStatisticsTo;
 
+    private static final I18N I18N = new I18N(CategoriesStatisticsToolBar.class);
+
     public CategoriesStatisticsToolBar(TabActions tabActions) {
         toolbar = new JToolBar(JToolBar.HORIZONTAL);
         toolbar.setFloatable(false);
@@ -26,10 +29,10 @@ public class CategoriesStatisticsToolBar {
         showStatisticsFrom = new JDatePicker(new LocalDateModel());
         showStatisticsTo = new JDatePicker(new LocalDateModel());
 
-        JLabel fromText = new JLabel("From");
+        JLabel fromText = new JLabel(I18N.getString("from"));
         fromText.setFont(fromText.getFont().deriveFont(Font.BOLD));
 
-        JLabel toText = new JLabel("To");
+        JLabel toText = new JLabel(I18N.getString("to"));
         toText.setFont(toText.getFont().deriveFont(Font.BOLD));
 
         for (Action action : tabActions.getLeftSideActions()) {
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/main/toolbar/TasksToolBar.java b/src/main/java/cz/muni/fi/pv168/project/ui/main/toolbar/TasksToolBar.java
index 6d12551aa2206199491d108a0b518ebf567da1c9..2b879d2d15dd20f0e1523eb7f15ab77cff1d1740 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/main/toolbar/TasksToolBar.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/main/toolbar/TasksToolBar.java
@@ -2,6 +2,7 @@ package cz.muni.fi.pv168.project.ui.main.toolbar;
 
 import cz.muni.fi.pv168.project.data.task.TaskStatus;
 import cz.muni.fi.pv168.project.ui.action.TabActions;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 
 import javax.swing.Action;
 import javax.swing.Box;
@@ -17,12 +18,14 @@ public class TasksToolBar {
     private final JCheckBox isJustToday;
     private final JComboBox<TaskStatus> taskTypes;
 
+    private static final I18N I18N = new I18N(TasksToolBar.class);
+
     public TasksToolBar(TabActions tabActions) {
         toolBar = new JToolBar(JToolBar.HORIZONTAL);
         toolBar.setFloatable(false);
 
-        isJustToday = new JCheckBox("Only urgent tasks", false);
-        isJustToday.setToolTipText("Show only tasks that are overdue or due today");
+        isJustToday = new JCheckBox(I18N.getString("filter"), false);
+        isJustToday.setToolTipText(I18N.getString("filterTooltip"));
         taskTypes = new JComboBox<>(TaskStatus.values());
         taskTypes.setSelectedItem(TaskStatus.ALL);
 
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/main/view/CategoryAndStatisticsView.java b/src/main/java/cz/muni/fi/pv168/project/ui/main/view/CategoryAndStatisticsView.java
index 3b552b0ccfe1284b40e6194bd7a94bf8f67c150d..cba592b5b397bab52c8a8ae1ae4df1e271db37a2 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/main/view/CategoryAndStatisticsView.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/main/view/CategoryAndStatisticsView.java
@@ -9,6 +9,7 @@ import cz.muni.fi.pv168.project.ui.action.EditAction;
 import cz.muni.fi.pv168.project.ui.action.TabActions;
 import cz.muni.fi.pv168.project.ui.dialog.factory.CategoryDialogFactory;
 import cz.muni.fi.pv168.project.ui.dialog.factory.DialogFactory;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import cz.muni.fi.pv168.project.ui.main.tab.Tab;
 import cz.muni.fi.pv168.project.ui.main.toolbar.CategoriesStatisticsToolBar;
 import cz.muni.fi.pv168.project.ui.popup.PopupMenuFactory;
@@ -30,6 +31,8 @@ public class CategoryAndStatisticsView implements Tab<Category> {
     private final CategoryView categoryView;
     private final StatisticsView statisticsView;
 
+    private static final I18N I18N = new I18N(CategoryAndStatisticsView.class);
+
     public CategoryAndStatisticsView(DaoHolder daoHolder) {
         categoryModel = new UpdatableDataModel<>(daoHolder.getCategoryDao());
         splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
@@ -38,9 +41,10 @@ public class CategoryAndStatisticsView implements Tab<Category> {
         this.statisticsView = new StatisticsView(categoryModel);
 
         TabActions tabActions = TabActions.builder()
-                .addLeftSideAction(new AddAction<>(this, Icons.ADD_CATEGORY_ICON, "Add a new category"))
-                .addLeftSideAction(new EditAction<>(this, Icons.EDIT_CATEGORY_ICON, "Edit a selected category"))
-                .addLeftSideAction(new DeleteAction<>(this, Icons.REMOVE_CATEGORY_BIN_ICON, "Delete a selected category")
+                .addLeftSideAction(new AddAction<>(this, Icons.ADD_CATEGORY_ICON, I18N.getString("addActionDesc")))
+                .addLeftSideAction(new EditAction<>(this, Icons.EDIT_CATEGORY_ICON, I18N.getString("editActionDesc")))
+                //TODO: edit locale accroding to count
+                .addLeftSideAction(new DeleteAction<>(this, Icons.REMOVE_CATEGORY_BIN_ICON, I18N.getString("deleteActionDesc"))
                         .addEnabledCondition(selectedCount -> daoHolder
                                 .getTaskDao()
                                 .getAll()
@@ -65,7 +69,7 @@ public class CategoryAndStatisticsView implements Tab<Category> {
 
     @Override
     public String getLabel() {
-        return "Categories";
+        return I18N.getString("label");
     }
 
     @Override
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/main/view/TaskView.java b/src/main/java/cz/muni/fi/pv168/project/ui/main/view/TaskView.java
index a9428731cdcf295047ce61d0e2f85360338f098a..fccb731c6f33812e90de5ebeb7568d6c59fe31eb 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/main/view/TaskView.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/main/view/TaskView.java
@@ -13,6 +13,7 @@ import cz.muni.fi.pv168.project.ui.action.Updatable;
 import cz.muni.fi.pv168.project.ui.action.task.ToggleCompletionAction;
 import cz.muni.fi.pv168.project.ui.dialog.factory.DialogFactory;
 import cz.muni.fi.pv168.project.ui.dialog.factory.TaskDialogFactory;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import cz.muni.fi.pv168.project.ui.main.panel.CardPanel;
 import cz.muni.fi.pv168.project.ui.main.panel.TaskPanel;
 import cz.muni.fi.pv168.project.ui.main.panel.WelcomePanel;
@@ -51,8 +52,10 @@ public class TaskView implements Tab<Task> {
     private final TaskPanel taskPanel;
     private final CardPanel cardPanel;
 
-    public static final String WELCOME_CARD = "Welcome";
-    public static final String TASK_CARD = "Task";
+    private static final I18N I18N = new I18N(TaskView.class);
+
+    public static final String WELCOME_CARD = I18N.getString("welcomeCard");
+    public static final String TASK_CARD = I18N.getString("taskCard");
 
     public TaskView(DaoHolder daoHolder) {
         taskModel = new TaskModel(daoHolder.getTaskDao());
@@ -74,10 +77,11 @@ public class TaskView implements Tab<Task> {
                 .addComponent(taskPanel, TASK_CARD);
 
         tabActions = TabActions.builder()
-                .addLeftSideAction(new AddAction<>(this, Icons.ADD_TASK_ICON, "Add a new task"))
-                .addLeftSideAction(new EditAction<>(this, Icons.EDIT_TASK_ICON, "Edit a selected task", headerList::getSelectedValue)
+                .addLeftSideAction(new AddAction<>(this, Icons.ADD_TASK_ICON, I18N.getString("addActionDesc")))
+                .addLeftSideAction(new EditAction<>(this, Icons.EDIT_TASK_ICON, I18N.getString("editActionDesc"), headerList::getSelectedValue)
                         .addUpdatable(taskPanel))
-                .addLeftSideAction(new DeleteAction<>(this, Icons.REMOVE_TASK_BIN_ICON, "Delete a selected task")
+                //TODO: edit locale accroding to count
+                .addLeftSideAction(new DeleteAction<>(this, Icons.REMOVE_TASK_BIN_ICON, I18N.getString("deleteActionDesc"))
                         .addEnabledCondition(selectedCount -> daoHolder
                                 .getTaskDao()
                                 .getAll()
@@ -133,7 +137,7 @@ public class TaskView implements Tab<Task> {
     private void createPopupMenu(CategoryDao categoryDao) {
         PopupMenuFactory.builder()
                 .addMenuItems(tabActions.getLeftSideActions())
-                .addMenuItem(new ToggleCompletionAction<>(this, "Toggle task completion", headerList::getSelectedValue)
+                .addMenuItem(new ToggleCompletionAction<>(this, I18N.getString("actionToggle"), headerList::getSelectedValue)
                         .addUpdatable(new Updatable() {
                             @Override
                             public void updateFrom(Task task) {
@@ -155,7 +159,7 @@ public class TaskView implements Tab<Task> {
 
     @Override
     public String getLabel() {
-        return "Tasks";
+        return I18N.getString("label");
     }
 
     @Override
diff --git a/src/main/java/cz/muni/fi/pv168/project/ui/renderer/list/TaskListRenderer.java b/src/main/java/cz/muni/fi/pv168/project/ui/renderer/list/TaskListRenderer.java
index cfeab2179f16ecf84f893703376fa3dd5c7be753..3dd79dc829662c583f51bddcb939a697a0e01b48 100644
--- a/src/main/java/cz/muni/fi/pv168/project/ui/renderer/list/TaskListRenderer.java
+++ b/src/main/java/cz/muni/fi/pv168/project/ui/renderer/list/TaskListRenderer.java
@@ -2,6 +2,8 @@ package cz.muni.fi.pv168.project.ui.renderer.list;
 
 import cz.muni.fi.pv168.project.data.task.Task;
 import cz.muni.fi.pv168.project.data.task.TaskStatus;
+import cz.muni.fi.pv168.project.ui.dialog.TaskDialog;
+import cz.muni.fi.pv168.project.ui.i18n.I18N;
 import cz.muni.fi.pv168.project.ui.main.panel.TaskStatusPanel;
 
 import javax.swing.BorderFactory;
@@ -28,8 +30,11 @@ public class TaskListRenderer implements ListCellRenderer<Task> {
     private final TaskStatusPanel completionPanel;
     private final JPanel panel;
 
-    public static final String TITLE_DATE_DELIMITER = "- due";
-    public static final String TIME_FORMAT = "Estimated %d hours";
+    private static final I18N I18N = new I18N(TaskListRenderer.class);
+
+    public static final String TITLE_DATE_DELIMITER = I18N.getString("delimiter");
+    //TODO localization depending on count
+    public static final String TIME_FORMAT = I18N.getString("timeFormat");
 
     public TaskListRenderer() {
         panel = new JPanel(new GridBagLayout());
diff --git a/src/main/resources/cz/muni/fi/pv168/project/model/db/i18n.properties b/src/main/resources/cz/muni/fi/pv168/project/model/db/i18n.properties
new file mode 100644
index 0000000000000000000000000000000000000000..10adbcd6d341b319c4a72fee5a4b7025645e978c
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/model/db/i18n.properties
@@ -0,0 +1,7 @@
+AbstractDataModel.editingEntError=Error when editing
+AbstractDataModel.addingEntError=Error when adding
+AbstractDataModel.deletingEntError=Error when removing
+
+UpdatableDataModel.queryAllError=Error when querying all elements.
+
+TaskModel.queryAllError=Error when querying all elements.
diff --git a/src/main/resources/cz/muni/fi/pv168/project/model/db/i18n_cs.properties b/src/main/resources/cz/muni/fi/pv168/project/model/db/i18n_cs.properties
new file mode 100644
index 0000000000000000000000000000000000000000..68508870fbf3750f6e42823864266c69bf1ddca8
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/model/db/i18n_cs.properties
@@ -0,0 +1,7 @@
+AbstractDataModel.editingEntError=Chyba p\u0159i editaci
+AbstractDataModel.addingEntError=Chyba p\u0159i p\u0159id\u00E1v\u00E1n\u00ED
+AbstractDataModel.deletingEntError=Chyba p\u0159i maz\u00E1n\u00ED
+
+UpdatableDataModel.queryAllError=Chyba p\u0159i na\u010D\u00EDt\u00E1n\u00ED v\u0161ech polo\u017Eek.
+
+TaskModel.queryAllError=Chyba p\u0159i na\u010D\u00EDt\u00E1n\u00ED v\u0161ech polo\u017Eek.
diff --git a/src/main/resources/cz/muni/fi/pv168/project/model/i18n.properties b/src/main/resources/cz/muni/fi/pv168/project/model/i18n.properties
new file mode 100644
index 0000000000000000000000000000000000000000..047e78c411f0659ade8031e871df0708331c5ff6
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/model/i18n.properties
@@ -0,0 +1,2 @@
+CategoryStatisticsTableModel.columnNameTitle=Category name
+CategoryStatisticsTableModel.columnTimeTitle=Time spent
\ No newline at end of file
diff --git a/src/main/resources/cz/muni/fi/pv168/project/model/i18n_cs.properties b/src/main/resources/cz/muni/fi/pv168/project/model/i18n_cs.properties
new file mode 100644
index 0000000000000000000000000000000000000000..4062662d9bed417ad594774c55b0b8f6e07a6ca1
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/model/i18n_cs.properties
@@ -0,0 +1,2 @@
+CategoryStatisticsTableModel.columnNameTitle=Jm\u00E9no kategorie
+CategoryStatisticsTableModel.columnTimeTitle=Str\u00E1ven\u00FD \u010Das
\ No newline at end of file
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/action/i18n.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/action/i18n.properties
new file mode 100644
index 0000000000000000000000000000000000000000..cd425203c5ad7a57f0c39c01f19834d68adf9232
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/action/i18n.properties
@@ -0,0 +1,6 @@
+AddAction.addAction=Add
+
+DeleteAction.deleteAction=Delete
+DeleteAction.confirmation=Are you sure you want to delete?
+
+EditAction.editAction=Edit
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/action/i18n_cs.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/action/i18n_cs.properties
new file mode 100644
index 0000000000000000000000000000000000000000..175d2253b52ddf02b2086f6dc530a419870e3b83
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/action/i18n_cs.properties
@@ -0,0 +1,6 @@
+AddAction.addAction=P\u0159idat
+
+DeleteAction.deleteAction=Smazat
+DeleteAction.confirmation=Jste si jisti, \u017Ee chcete v\u00FDb\u011Br smazat?
+
+EditAction.editAction=Upravit
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/action/task/i18n.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/action/task/i18n.properties
new file mode 100644
index 0000000000000000000000000000000000000000..c825f94723af61f8f2ce3806778ae0ec19591bee
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/action/task/i18n.properties
@@ -0,0 +1,3 @@
+GoToAction.goTo=Go to task
+
+ToggleCompletionAction.toggleAction=Toggle completion
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/action/task/i18n_cs.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/action/task/i18n_cs.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1b2c7cdefcce948b92db21be4eac5327ebbec1c6
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/action/task/i18n_cs.properties
@@ -0,0 +1,3 @@
+GoToAction.goTo=P\u0159ej\u00EDt na \u00FAlohu
+
+ToggleCompletionAction.toggleAction=P\u0159epnout spln\u011Bn\u00ED
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/dialog/error/i18n.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/dialog/error/i18n.properties
new file mode 100644
index 0000000000000000000000000000000000000000..9853a874006a74469762715d2ccc46712ba97788
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/dialog/error/i18n.properties
@@ -0,0 +1 @@
+error=Nastala chyba
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/dialog/error/i18n_cs.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/dialog/error/i18n_cs.properties
new file mode 100644
index 0000000000000000000000000000000000000000..fb36abc64457bf64e03586573a9226d8e7893425
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/dialog/error/i18n_cs.properties
@@ -0,0 +1 @@
+error=Error occurred
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/dialog/i18n.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/dialog/i18n.properties
new file mode 100644
index 0000000000000000000000000000000000000000..ebbb22d25fdf00a69c8122f985f83b1effeb2ad4
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/dialog/i18n.properties
@@ -0,0 +1,16 @@
+AbstractEntityDialog.buttonConfirm=OK
+AbstractEntityDialog.buttonDismiss=Cancel
+AbstractEntityDialog.vmTitle=New filesystem VM
+
+CategoryDialog.fieldLabelName=Name:
+CategoryDialog.fieldLabelColor=Color:
+
+ComboBoxDialog.fieldLabelSelect=Select:
+
+SubTaskDialog.fieldLabelTitle=Title:
+
+TaskDialog.labelTitle=Title:
+TaskDialog.labelDescription=Description:
+TaskDialog.labelEstTime=Estimated time:
+TaskDialog.labelDueTime=Due time:
+TaskDialog.estimatedTimeUnit=hours
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/dialog/i18n_cs.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/dialog/i18n_cs.properties
new file mode 100644
index 0000000000000000000000000000000000000000..dbbfe4b50a9a3bd79c68c7c6b4523b5f1f98cdc9
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/dialog/i18n_cs.properties
@@ -0,0 +1,16 @@
+AbstractEntityDialog.buttonConfirm=OK
+AbstractEntityDialog.buttonDismiss=Zru\u0161it
+AbstractEntityDialog.vmTitle=Nov\u00FD filesystem VM
+
+CategoryDialog.fieldLabelName=Jm\u00E9no:
+CategoryDialog.fieldLabelColor=Barva:
+
+ComboBoxDialog.fieldLabelSelect=Vybrat:
+
+SubTaskDialog.fieldLabelTitle=N\u00E1zev:
+
+TaskDialog.labelTitle=N\u00E1zev:
+TaskDialog.labelDescription=Popis:
+TaskDialog.labelEstTime=Odhadovan\u00FD \u010Das:
+TaskDialog.labelDueTime=Deadline:
+TaskDialog.estimatedTimeUnit=hodin
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/main/panel/i18n.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/main/panel/i18n.properties
new file mode 100644
index 0000000000000000000000000000000000000000..d2b790f0927446474a8aa127ef252dbc9e4baf0a
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/main/panel/i18n.properties
@@ -0,0 +1,4 @@
+WelcomePanel.welcomeMessage=Welcome to to:do, your daily task reminder.\n\n\
+  You can use the toolbar buttons above to add, edit, or delete tasks and categories.\n\
+  Switch between tasks and categories using the tabs.\n\
+  Click on a task in the list on the left to see details.
\ No newline at end of file
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/main/panel/i18n_cs.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/main/panel/i18n_cs.properties
new file mode 100644
index 0000000000000000000000000000000000000000..0b9d2838ebe46f237410a9e68aac5584a786961e
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/main/panel/i18n_cs.properties
@@ -0,0 +1,4 @@
+WelcomePanel.welcomeMessage=V\u00EDtejte v to:do, va\u0161em denn\u00EDm pl\u00E1nova\u010Di \u00FAloh.\n\n\
+  M\u016F\u017Eete pou\u017E\u00EDt horn\u00ED tla\u010D\u00EDtka pro p\u0159id\u00E1n\u00ED, editaci, nebo odstran\u011Bn\u00ED \u00FAloh a kategori\u00ED.\n\
+  P\u0159ep\u00EDnat mezi plohami a kategoriemi m\u016F\u017Eete pomoc\u00ED z\u00E1lo\u017Eek.\n\
+  Klikn\u011Bte na \u00FAlohu nalevo pro zobrazen\u00ED jej\u00EDch detail\u016F.
\ No newline at end of file
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/main/panel/listholder/i18n.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/main/panel/listholder/i18n.properties
new file mode 100644
index 0000000000000000000000000000000000000000..62fd6d5284824213d30b314619f6d0ef2a8777b7
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/main/panel/listholder/i18n.properties
@@ -0,0 +1,15 @@
+CategoryHolderPanel.panelName=Categories
+CategoryHolderPanel.addCategoryOption=Add category
+CategoryHolderPanel.editCategoryOption=Edit category
+CategoryHolderPanel.removeCategoryOption=Remove category
+
+DependencyHolderPanel.panelName=Dependencies
+DependencyHolderPanel.goToAction=Go to dependency
+DependencyHolderPanel.addAction=Add dependency
+DependencyHolderPanel.removeAction=Remove dependency
+
+SubTaskHolderPanel.panelName=Sub tasks
+SubTaskHolderPanel.completionToggle=Toggle completion
+SubTaskHolderPanel.addAction=Add subtask
+SubTaskHolderPanel.editAction=Edit subtask
+SubTaskHolderPanel.removeAction=Remove subtask
\ No newline at end of file
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/main/panel/listholder/i18n_cs.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/main/panel/listholder/i18n_cs.properties
new file mode 100644
index 0000000000000000000000000000000000000000..733a5132c02aa22ecd1f43ab452b6d00aafcc816
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/main/panel/listholder/i18n_cs.properties
@@ -0,0 +1,15 @@
+CategoryHolderPanel.panelName=Kategorie
+CategoryHolderPanel.addCategoryOption=P\u0159idat kategorii
+CategoryHolderPanel.editCategoryOption=Upravit kategorii
+CategoryHolderPanel.removeCategoryOption=Smazat kategorii
+
+DependencyHolderPanel.panelName=Dependence
+DependencyHolderPanel.goToAction=P\u0159ej\u00EDt na dependenci
+DependencyHolderPanel.addAction=P\u0159idat dependenci
+DependencyHolderPanel.deleteAction=Smazat dependenci
+
+SubTaskHolderPanel.panelName=Pod\u00FAlohy
+SubTaskHolderPanel.completionToggle=P\u0159epnout spln\u011Bn\u00ED
+SubTaskHolderPanel.addAction=P\u0159idat pod\u00FAlohu
+SubTaskHolderPanel.editAction=Upravit pod\u00FAlohu
+SubTaskHolderPanel.removeAction=Smazat pod\u00FAlohu
\ No newline at end of file
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/main/toolbar/i18n.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/main/toolbar/i18n.properties
new file mode 100644
index 0000000000000000000000000000000000000000..7f0558ce49616bb051e309eb04e23b1b83cc330e
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/main/toolbar/i18n.properties
@@ -0,0 +1,5 @@
+CategoriesStatisticsToolBar.from=From
+CategoriesStatisticsToolBar.to=To
+
+TasksToolBar.filter=Only urgent tasks
+TasksToolBar.filterTooltip=Show only tasks that are overdue or due today
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/main/toolbar/i18n_cs.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/main/toolbar/i18n_cs.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1a297249223c16b3dc20a3911883b23dd9475af5
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/main/toolbar/i18n_cs.properties
@@ -0,0 +1,5 @@
+CategoriesStatisticsToolBar.from=Od
+CategoriesStatisticsToolBar.to=Do
+
+TasksToolBar.filter=Jen urgentn\u00ED \u00FAlohy
+TasksToolBar.filterTooltip=Zobraz\u00ED pouze ty \u00FAlohy, je\u017E maj\u00ED b\u00FDt hotov\u00E9 do dnes
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/main/view/i18n.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/main/view/i18n.properties
new file mode 100644
index 0000000000000000000000000000000000000000..6e771cf323e492a67541ff81b4a132d17949799d
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/main/view/i18n.properties
@@ -0,0 +1,14 @@
+CategoryAndStatisticsView.addActionDesc=Add a new category
+CategoryAndStatisticsView.editActionDesc=Edit a selected category
+CategoryAndStatisticsView.deleteActionDesc=Delete a selected category
+CategoryAndStatisticsView.label=Categories
+
+TaskView.welcomeCard=Welcome
+TaskView.taskCard=Task
+
+TaskView.addActionDesc=Add a new task
+TaskView.editActionDesc=Edit a selected task
+TaskView.deleteActionDesc=Delete a selected task
+
+TaskView.actionToggle=Toggle task completion
+TaskView.label=Tasks
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/main/view/i18n_cs.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/main/view/i18n_cs.properties
new file mode 100644
index 0000000000000000000000000000000000000000..a5c3b810c186cd9b237d8b1ff25b53db5beefd6e
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/main/view/i18n_cs.properties
@@ -0,0 +1,13 @@
+CategoryAndStatisticsView.addActionDesc=P\u0159idat novou kategorii
+CategoryAndStatisticsView.editActionDesc=Upravit vybranou kategorii
+CategoryAndStatisticsView.deleteActionDesc=Smazat vybranou kategorii
+CategoryAndStatisticsView.label=Kategorie
+
+TaskView.welcomeCard=V\u00EDtejte
+TaskView.taskCard=\u00DAloha
+TaskView.addActionDesc=P\u0159idat novou \u00FAlohu
+TaskView.editActionDesc=Upravit vybranou \u00FAlohu
+TaskView.deleteActionDesc=Smazat vybranou \u00FAlohu
+
+TaskView.actionToggle=P\u0159epnout spln\u011Bn\u00ED \u00FAlohy
+TaskView.label=\u00DAlohy
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/renderer/list/i18n.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/renderer/list/i18n.properties
new file mode 100644
index 0000000000000000000000000000000000000000..39ec632a20de7e0eaffb3d23cdf831f129d7a2ae
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/renderer/list/i18n.properties
@@ -0,0 +1,2 @@
+TaskListRenderer.delimiter=\u2013 due
+TaskListRenderer.timeFormat=Estimated %d hours
diff --git a/src/main/resources/cz/muni/fi/pv168/project/ui/renderer/list/i18n_cs.properties b/src/main/resources/cz/muni/fi/pv168/project/ui/renderer/list/i18n_cs.properties
new file mode 100644
index 0000000000000000000000000000000000000000..cf885516ccd03f71cbb1e8a0e3f718b71584a039
--- /dev/null
+++ b/src/main/resources/cz/muni/fi/pv168/project/ui/renderer/list/i18n_cs.properties
@@ -0,0 +1,2 @@
+TaskListRenderer.delimiter=\u2013 do
+TaskListRenderer.timeFormat=Odhadov\u00E1no %d hodin