diff --git a/CMakeLists.txt b/CMakeLists.txt
index d83fb8d163b20e05919d84f0a995f09d46bb391b..4b36ad1162529ffb52436c0248504c0e7d4b14db 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,6 +6,7 @@ option(BUILD_TESTS "Build all tests" OFF)
 
 find_package(Qt5Widgets REQUIRED)
 find_package(Qt5Network REQUIRED)
+find_package(Qt5LinguistTools REQUIRED)
 
 set(CMAKE_C_COMPILER gcc)
 
@@ -191,6 +192,21 @@ qt5_wrap_cpp(MOC_HEADERS
     include/ui/ThemeManager.h
 )
 
+FILE(GLOB LANG_TS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/resources/langs/*.ts")
+
+qt5_add_translation(QM_SRC ${LANG_TS_SRC})
+add_custom_target(LANG_QRC ALL DEPENDS ${QM_SRC})
+
+# Generate a qrc file for the translations
+set(_qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc)
+file(WRITE ${_qrc} "<RCC> <qresource prefix=\"/translations\">")
+foreach(_lang ${QM_SRC})
+    get_filename_component(_filename ${_lang} NAME)
+    file(APPEND ${_qrc} "<file>${_filename}</file>")
+endforeach(_lang)
+file(APPEND ${_qrc} "</qresource> </RCC>")
+
+qt5_add_resources(LANG_QRC ${_qrc})
 qt5_add_resources(QRC resources/res.qrc)
 
 add_library(matrix_events ${MATRIX_EVENTS} src/Deserializable.cc)
@@ -215,7 +231,7 @@ if (BUILD_TESTS)
     add_test(MatrixEventCollection event_collection_test)
     add_test(MatrixMessageEvents message_events)
 else()
-    add_executable (nheko ${OS_BUNDLE} ${SRC_FILES} ${UI_HEADERS} ${MOC_HEADERS} ${QRC})
+    add_executable (nheko ${OS_BUNDLE} ${SRC_FILES} ${UI_HEADERS} ${MOC_HEADERS} ${QRC} ${LANG_QRC} ${QM_SRC})
     target_link_libraries (nheko matrix_events Qt5::Widgets Qt5::Network)
 
     if(WIN32)
diff --git a/resources/langs/nheko_de.ts b/resources/langs/nheko_de.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0b17ab44cc5867bfeef6bddd2f239169babf58de
--- /dev/null
+++ b/resources/langs/nheko_de.ts
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1">
+<context>
+    <name>EmojiPanel</name>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="120"/>
+        <source>Smileys &amp; People</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="123"/>
+        <source>Animals &amp; Nature</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="126"/>
+        <source>Food &amp; Drink</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="129"/>
+        <source>Activity</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="132"/>
+        <source>Travel &amp; Places</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="135"/>
+        <source>Objects</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="138"/>
+        <source>Symbols</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="141"/>
+        <source>Flags</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>LoginPage</name>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="85"/>
+        <source>Matrix ID</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="88"/>
+        <source>e.g @joe:matrix.org</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="92"/>
+        <source>Password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="104"/>
+        <source>LOGIN</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="150"/>
+        <source>Invalid Matrix ID</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="152"/>
+        <source>Empty password</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>MatrixClient</name>
+    <message>
+        <location filename="../../src/MatrixClient.cc" line="75"/>
+        <source>Wrong username or password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/MatrixClient.cc" line="80"/>
+        <source>Login endpoint was not found on the server</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/MatrixClient.cc" line="86"/>
+        <source>An unknown error occured. Please try again.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/MatrixClient.cc" line="100"/>
+        <source>Malformed response. Possibly not a Matrix server</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>RegisterPage</name>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="72"/>
+        <source>Username</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="78"/>
+        <source>Password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="85"/>
+        <source>Password confirmation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="92"/>
+        <source>Home Server</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="108"/>
+        <source>REGISTER</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="159"/>
+        <source>Invalid username</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="161"/>
+        <source>Password is not long enough (min 8 chars)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="163"/>
+        <source>Passwords don&apos;t match</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="165"/>
+        <source>Invalid server name</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>TextInputWidget</name>
+    <message>
+        <location filename="../../src/TextInputWidget.cc" line="62"/>
+        <source>Write a message...</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>TrayIcon</name>
+    <message>
+        <location filename="../../src/TrayIcon.cc" line="73"/>
+        <source>Show</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/TrayIcon.cc" line="74"/>
+        <source>Quit</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>WelcomePage</name>
+    <message>
+        <location filename="../../src/WelcomePage.cc" line="38"/>
+        <source>Welcome to nheko! The desktop client for the Matrix protocol.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/WelcomePage.cc" line="39"/>
+        <source>Enjoy your stay!</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/WelcomePage.cc" line="60"/>
+        <source>REGISTER</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/WelcomePage.cc" line="68"/>
+        <source>LOGIN</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+</TS>
diff --git a/resources/langs/nheko_el.ts b/resources/langs/nheko_el.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0cc9aa13381ac13b6cefc9c27d5097f55e2303fc
--- /dev/null
+++ b/resources/langs/nheko_el.ts
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="el_GR">
+<context>
+    <name>EmojiPanel</name>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="120"/>
+        <source>Smileys &amp; People</source>
+        <translation>Πρόσωπα</translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="123"/>
+        <source>Animals &amp; Nature</source>
+        <translation>Ζώα &amp; Φύση</translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="126"/>
+        <source>Food &amp; Drink</source>
+        <translation>Φαγητά &amp; Ποτά</translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="129"/>
+        <source>Activity</source>
+        <translation>Δραστηριότητες</translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="132"/>
+        <source>Travel &amp; Places</source>
+        <translation>Ταξίδια &amp; Τοποθεσίες</translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="135"/>
+        <source>Objects</source>
+        <translation>Αντικείμενα</translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="138"/>
+        <source>Symbols</source>
+        <translation>Σύμβολα</translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="141"/>
+        <source>Flags</source>
+        <translation>Σημαίες</translation>
+    </message>
+</context>
+<context>
+    <name>LoginPage</name>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="85"/>
+        <source>Matrix ID</source>
+        <translation>Matrix ID</translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="88"/>
+        <source>e.g @joe:matrix.org</source>
+        <translation>π.χ @john:matrix.org</translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="92"/>
+        <source>Password</source>
+        <translation>Κωδικός</translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="104"/>
+        <source>LOGIN</source>
+        <translation>ΕΙΣΟΔΟΣ</translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="150"/>
+        <source>Invalid Matrix ID</source>
+        <translation>Μη έγκυρο Matrix ID</translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="152"/>
+        <source>Empty password</source>
+        <translation>Κενός κωδικός</translation>
+    </message>
+</context>
+<context>
+    <name>MatrixClient</name>
+    <message>
+        <location filename="../../src/MatrixClient.cc" line="75"/>
+        <source>Wrong username or password</source>
+        <translation>Λάθος ψευδώνυμο ή κωδικός.</translation>
+    </message>
+    <message>
+        <location filename="../../src/MatrixClient.cc" line="80"/>
+        <source>Login endpoint was not found on the server</source>
+        <translation>Δεν παρέχεται δυνατότητα εισόδου από το διακομιστή.</translation>
+    </message>
+    <message>
+        <location filename="../../src/MatrixClient.cc" line="86"/>
+        <source>An unknown error occured. Please try again.</source>
+        <translation>Σφάλμα άγνωστης προεύλευσης. Παρακαλώ προσπαθήστε ξανά.</translation>
+    </message>
+    <message>
+        <location filename="../../src/MatrixClient.cc" line="100"/>
+        <source>Malformed response. Possibly not a Matrix server</source>
+        <translation>Ο διακόμιστής δεν χρησιμοποιεί το πρωτόκολλο Matrix.</translation>
+    </message>
+</context>
+<context>
+    <name>RegisterPage</name>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="72"/>
+        <source>Username</source>
+        <translation>Ψευδώνυμο</translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="78"/>
+        <source>Password</source>
+        <translation>Κωδικός</translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="85"/>
+        <source>Password confirmation</source>
+        <translation>Επαλήθευση κωδικού</translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="92"/>
+        <source>Home Server</source>
+        <translation>Διακομιστής</translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="108"/>
+        <source>REGISTER</source>
+        <translation>ΕΓΓΡΑΦΗ</translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="159"/>
+        <source>Invalid username</source>
+        <translation>Μη έγκυρο ψευδώνυμο</translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="161"/>
+        <source>Password is not long enough (min 8 chars)</source>
+        <translation>Ο κωδικός δεν αποτελείται από αρκετούς χαρακτήρες (τουλάχιστον 8)</translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="163"/>
+        <source>Passwords don&apos;t match</source>
+        <translation>Οι κωδικοί δεν ταιριάζουν</translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="165"/>
+        <source>Invalid server name</source>
+        <translation>Μη έγκυρος διακομιστής</translation>
+    </message>
+</context>
+<context>
+    <name>TextInputWidget</name>
+    <message>
+        <location filename="../../src/TextInputWidget.cc" line="62"/>
+        <source>Write a message...</source>
+        <translation>Γράψε κάτι...</translation>
+    </message>
+</context>
+<context>
+    <name>TrayIcon</name>
+    <message>
+        <location filename="../../src/TrayIcon.cc" line="73"/>
+        <source>Show</source>
+        <translation>Εμφάνιση</translation>
+    </message>
+    <message>
+        <location filename="../../src/TrayIcon.cc" line="74"/>
+        <source>Quit</source>
+        <translation>Έξοδος</translation>
+    </message>
+</context>
+<context>
+    <name>WelcomePage</name>
+    <message>
+        <location filename="../../src/WelcomePage.cc" line="38"/>
+        <source>Welcome to nheko! The desktop client for the Matrix protocol.</source>
+        <translation>Καλώς ήρθες στο nheko! </translation>
+    </message>
+    <message>
+        <location filename="../../src/WelcomePage.cc" line="39"/>
+        <source>Enjoy your stay!</source>
+        <translation>Τη desktop εφαρμογή για το πρωτόκολλο επικοινωνίας Matrix.</translation>
+    </message>
+    <message>
+        <location filename="../../src/WelcomePage.cc" line="60"/>
+        <source>REGISTER</source>
+        <translation>ΕΓΓΡΑΦΗ</translation>
+    </message>
+    <message>
+        <location filename="../../src/WelcomePage.cc" line="68"/>
+        <source>LOGIN</source>
+        <translation>ΕΙΣΟΔΟΣ</translation>
+    </message>
+</context>
+</TS>
diff --git a/resources/langs/nheko_nl.ts b/resources/langs/nheko_nl.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0b17ab44cc5867bfeef6bddd2f239169babf58de
--- /dev/null
+++ b/resources/langs/nheko_nl.ts
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1">
+<context>
+    <name>EmojiPanel</name>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="120"/>
+        <source>Smileys &amp; People</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="123"/>
+        <source>Animals &amp; Nature</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="126"/>
+        <source>Food &amp; Drink</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="129"/>
+        <source>Activity</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="132"/>
+        <source>Travel &amp; Places</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="135"/>
+        <source>Objects</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="138"/>
+        <source>Symbols</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/EmojiPanel.cc" line="141"/>
+        <source>Flags</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>LoginPage</name>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="85"/>
+        <source>Matrix ID</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="88"/>
+        <source>e.g @joe:matrix.org</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="92"/>
+        <source>Password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="104"/>
+        <source>LOGIN</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="150"/>
+        <source>Invalid Matrix ID</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/LoginPage.cc" line="152"/>
+        <source>Empty password</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>MatrixClient</name>
+    <message>
+        <location filename="../../src/MatrixClient.cc" line="75"/>
+        <source>Wrong username or password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/MatrixClient.cc" line="80"/>
+        <source>Login endpoint was not found on the server</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/MatrixClient.cc" line="86"/>
+        <source>An unknown error occured. Please try again.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/MatrixClient.cc" line="100"/>
+        <source>Malformed response. Possibly not a Matrix server</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>RegisterPage</name>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="72"/>
+        <source>Username</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="78"/>
+        <source>Password</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="85"/>
+        <source>Password confirmation</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="92"/>
+        <source>Home Server</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="108"/>
+        <source>REGISTER</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="159"/>
+        <source>Invalid username</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="161"/>
+        <source>Password is not long enough (min 8 chars)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="163"/>
+        <source>Passwords don&apos;t match</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/RegisterPage.cc" line="165"/>
+        <source>Invalid server name</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>TextInputWidget</name>
+    <message>
+        <location filename="../../src/TextInputWidget.cc" line="62"/>
+        <source>Write a message...</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>TrayIcon</name>
+    <message>
+        <location filename="../../src/TrayIcon.cc" line="73"/>
+        <source>Show</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/TrayIcon.cc" line="74"/>
+        <source>Quit</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>WelcomePage</name>
+    <message>
+        <location filename="../../src/WelcomePage.cc" line="38"/>
+        <source>Welcome to nheko! The desktop client for the Matrix protocol.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/WelcomePage.cc" line="39"/>
+        <source>Enjoy your stay!</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/WelcomePage.cc" line="60"/>
+        <source>REGISTER</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/WelcomePage.cc" line="68"/>
+        <source>LOGIN</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+</TS>
diff --git a/src/EmojiPanel.cc b/src/EmojiPanel.cc
index 02fe2f141091b8d63768c6c132671762162f1f44..63b408c00e9f9e1a852f0d79f97659f45a21892a 100644
--- a/src/EmojiPanel.cc
+++ b/src/EmojiPanel.cc
@@ -117,28 +117,28 @@ EmojiPanel::EmojiPanel(QWidget *parent)
 	scroll_layout_->setMargin(0);
 	scroll_area_->setWidget(scroll_widget_);
 
-	auto people_emoji = new EmojiCategory("Smileys & People", emoji_provider_.people, scroll_widget_);
+	auto people_emoji = new EmojiCategory(tr("Smileys & People"), emoji_provider_.people, scroll_widget_);
 	scroll_layout_->addWidget(people_emoji);
 
-	auto nature_emoji = new EmojiCategory("Animals & Nature", emoji_provider_.nature, scroll_widget_);
+	auto nature_emoji = new EmojiCategory(tr("Animals & Nature"), emoji_provider_.nature, scroll_widget_);
 	scroll_layout_->addWidget(nature_emoji);
 
-	auto food_emoji = new EmojiCategory("Food & Drink", emoji_provider_.food, scroll_widget_);
+	auto food_emoji = new EmojiCategory(tr("Food & Drink"), emoji_provider_.food, scroll_widget_);
 	scroll_layout_->addWidget(food_emoji);
 
-	auto activity_emoji = new EmojiCategory("Activity", emoji_provider_.activity, scroll_widget_);
+	auto activity_emoji = new EmojiCategory(tr("Activity"), emoji_provider_.activity, scroll_widget_);
 	scroll_layout_->addWidget(activity_emoji);
 
-	auto travel_emoji = new EmojiCategory("Travel & Places", emoji_provider_.travel, scroll_widget_);
+	auto travel_emoji = new EmojiCategory(tr("Travel & Places"), emoji_provider_.travel, scroll_widget_);
 	scroll_layout_->addWidget(travel_emoji);
 
-	auto objects_emoji = new EmojiCategory("Objects", emoji_provider_.objects, scroll_widget_);
+	auto objects_emoji = new EmojiCategory(tr("Objects"), emoji_provider_.objects, scroll_widget_);
 	scroll_layout_->addWidget(objects_emoji);
 
-	auto symbols_emoji = new EmojiCategory("Symbols", emoji_provider_.symbols, scroll_widget_);
+	auto symbols_emoji = new EmojiCategory(tr("Symbols"), emoji_provider_.symbols, scroll_widget_);
 	scroll_layout_->addWidget(symbols_emoji);
 
-	auto flags_emoji = new EmojiCategory("Flags", emoji_provider_.flags, scroll_widget_);
+	auto flags_emoji = new EmojiCategory(tr("Flags"), emoji_provider_.flags, scroll_widget_);
 	scroll_layout_->addWidget(flags_emoji);
 
 	content_layout->addStretch(1);
diff --git a/src/LoginPage.cc b/src/LoginPage.cc
index 02ab92c6258e6e20ea41a412e74302453fbd2f31..4514b6076550287ebe311bea9d0f66e4bb2bc12f 100644
--- a/src/LoginPage.cc
+++ b/src/LoginPage.cc
@@ -82,14 +82,14 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
 
 	matrixid_input_ = new TextField(this);
 	matrixid_input_->setTextColor("#333333");
-	matrixid_input_->setLabel("Matrix ID");
+	matrixid_input_->setLabel(tr("Matrix ID"));
 	matrixid_input_->setInkColor("#555459");
 	matrixid_input_->setBackgroundColor("#f9f9f9");
-	matrixid_input_->setPlaceholderText("e.g @joe:matrix.org");
+	matrixid_input_->setPlaceholderText(tr("e.g @joe:matrix.org"));
 
 	password_input_ = new TextField(this);
 	password_input_->setTextColor("#333333");
-	password_input_->setLabel("Password");
+	password_input_->setLabel(tr("Password"));
 	password_input_->setInkColor("#555459");
 	password_input_->setBackgroundColor("#f9f9f9");
 	password_input_->setEchoMode(QLineEdit::Password);
@@ -101,7 +101,7 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
 	button_layout_->setSpacing(0);
 	button_layout_->setContentsMargins(0, 0, 0, 30);
 
-	login_button_ = new RaisedButton("LOGIN", this);
+	login_button_ = new RaisedButton(tr("LOGIN"), this);
 	login_button_->setBackgroundColor(QColor("#333333"));
 	login_button_->setForegroundColor(QColor("white"));
 	login_button_->setMinimumSize(350, 65);
@@ -147,9 +147,9 @@ void LoginPage::onLoginButtonClicked()
 	error_label_->setText("");
 
 	if (!matrixid_input_->hasAcceptableInput()) {
-		loginError("Invalid Matrix ID");
+		loginError(tr("Invalid Matrix ID"));
 	} else if (password_input_->text().isEmpty()) {
-		loginError("Empty password");
+		loginError(tr("Empty password"));
 	} else {
 		QString user = matrixid_input_->text().split(":").at(0).split("@").at(1);
 		QString password = password_input_->text();
diff --git a/src/MatrixClient.cc b/src/MatrixClient.cc
index 23cbbb5e4520d838c2eff2fb7900c340868e8f32..a605623f8cd0c7b324fa1070e9eb39dd85fd5d33 100644
--- a/src/MatrixClient.cc
+++ b/src/MatrixClient.cc
@@ -72,18 +72,18 @@ void MatrixClient::onLoginResponse(QNetworkReply *reply)
 	int status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
 
 	if (status_code == 403) {
-		emit loginError("Wrong username or password");
+		emit loginError(tr("Wrong username or password"));
 		return;
 	}
 
 	if (status_code == 404) {
-		emit loginError("Login endpoint was not found on the server");
+		emit loginError(tr("Login endpoint was not found on the server"));
 		return;
 	}
 
 	if (status_code >= 400) {
 		qWarning() << "Login error: " << reply->errorString();
-		emit loginError("An unknown error occured. Please try again.");
+		emit loginError(tr("An unknown error occured. Please try again."));
 		return;
 	}
 
@@ -97,7 +97,7 @@ void MatrixClient::onLoginResponse(QNetworkReply *reply)
 		emit loginSuccess(response.getUserId(), server_.host(), response.getAccessToken());
 	} catch (DeserializationException &e) {
 		qWarning() << "Malformed JSON response" << e.what();
-		emit loginError("Malformed response. Possibly not a Matrix server");
+		emit loginError(tr("Malformed response. Possibly not a Matrix server"));
 	}
 }
 
diff --git a/src/RegisterPage.cc b/src/RegisterPage.cc
index d5c6091805e3a4130f559a2f09ca7f775c96e8d1..33df0b62ef964000df50fbf0d564efdc4c41cc20 100644
--- a/src/RegisterPage.cc
+++ b/src/RegisterPage.cc
@@ -69,27 +69,27 @@ RegisterPage::RegisterPage(QSharedPointer<MatrixClient> client, QWidget *parent)
 
 	username_input_ = new TextField();
 	username_input_->setTextColor("#333333");
-	username_input_->setLabel("Username");
+	username_input_->setLabel(tr("Username"));
 	username_input_->setInkColor("#555459");
 	username_input_->setBackgroundColor("#f9f9f9");
 
 	password_input_ = new TextField();
 	password_input_->setTextColor("#333333");
-	password_input_->setLabel("Password");
+	password_input_->setLabel(tr("Password"));
 	password_input_->setInkColor("#555459");
 	password_input_->setBackgroundColor("#f9f9f9");
 	password_input_->setEchoMode(QLineEdit::Password);
 
 	password_confirmation_ = new TextField();
 	password_confirmation_->setTextColor("#333333");
-	password_confirmation_->setLabel("Password confirmation");
+	password_confirmation_->setLabel(tr("Password confirmation"));
 	password_confirmation_->setInkColor("#555459");
 	password_confirmation_->setBackgroundColor("#f9f9f9");
 	password_confirmation_->setEchoMode(QLineEdit::Password);
 
 	server_input_ = new TextField();
 	server_input_->setTextColor("#333333");
-	server_input_->setLabel("Home Server");
+	server_input_->setLabel(tr("Home Server"));
 	server_input_->setInkColor("#555459");
 	server_input_->setBackgroundColor("#f9f9f9");
 
@@ -105,7 +105,7 @@ RegisterPage::RegisterPage(QSharedPointer<MatrixClient> client, QWidget *parent)
 	error_label_ = new QLabel(this);
 	error_label_->setStyleSheet("margin-bottom: 10px; color: #E22826; font-size: 11pt;");
 
-	register_button_ = new RaisedButton("REGISTER", this);
+	register_button_ = new RaisedButton(tr("REGISTER"), this);
 	register_button_->setBackgroundColor(QColor("#333333"));
 	register_button_->setForegroundColor(QColor("white"));
 	register_button_->setMinimumSize(350, 65);
@@ -156,13 +156,13 @@ void RegisterPage::onRegisterButtonClicked()
 	error_label_->setText("");
 
 	if (!username_input_->hasAcceptableInput()) {
-		registerError("Invalid username");
+		registerError(tr("Invalid username"));
 	} else if (!password_input_->hasAcceptableInput()) {
-		registerError("Password is not long enough (min 8 chars)");
+		registerError(tr("Password is not long enough (min 8 chars)"));
 	} else if (password_input_->text() != password_confirmation_->text()) {
-		registerError("Passwords don't match");
+		registerError(tr("Passwords don't match"));
 	} else if (!server_input_->hasAcceptableInput()) {
-		registerError("Invalid server name");
+		registerError(tr("Invalid server name"));
 	} else {
 		QString username = username_input_->text();
 		QString password = password_input_->text();
diff --git a/src/TextInputWidget.cc b/src/TextInputWidget.cc
index ab73a98f3e69c10341f7388aa3cf0508a27da0c6..cda00c2c18b556b35d3f879f1971aa0c4943ddac 100644
--- a/src/TextInputWidget.cc
+++ b/src/TextInputWidget.cc
@@ -59,7 +59,7 @@ TextInputWidget::TextInputWidget(QWidget *parent)
 
 	input_ = new FilteredTextEdit(this);
 	input_->setFixedHeight(45);
-	input_->setPlaceholderText("Write a message...");
+	input_->setPlaceholderText(tr("Write a message..."));
 	input_->setStyleSheet("color: #333333; font-size: 13px; border-radius: 0; padding-top: 10px;");
 
 	send_message_button_ = new FlatButton(this);
diff --git a/src/TrayIcon.cc b/src/TrayIcon.cc
index 3a227087c05def4b5ee6be75a4b6d70e28e7149b..beaf00dfbd4648a531e9b7fff45fff64263e4226 100644
--- a/src/TrayIcon.cc
+++ b/src/TrayIcon.cc
@@ -70,8 +70,8 @@ TrayIcon::TrayIcon(const QString &filename, QWidget *parent)
 	setIcon(QIcon(icon_));
 
 	QMenu *menu = new QMenu(parent);
-	viewAction_ = new QAction("Show", parent);
-	quitAction_ = new QAction("Quit", parent);
+	viewAction_ = new QAction(tr("Show"), parent);
+	quitAction_ = new QAction(tr("Quit"), parent);
 
 	connect(viewAction_, SIGNAL(triggered()), parent, SLOT(show()));
 	connect(quitAction_, &QAction::triggered, this, [=]() {
diff --git a/src/WelcomePage.cc b/src/WelcomePage.cc
index d6668e7b67f2182e1e6fbf1b6d1786309da397c8..b88c4db124fc4dec9635b01678892a1471abeb2f 100644
--- a/src/WelcomePage.cc
+++ b/src/WelcomePage.cc
@@ -34,21 +34,18 @@ WelcomePage::WelcomePage(QWidget *parent)
 	intro_banner_->setAlignment(Qt::AlignCenter);
 
 	intro_text_ = new QLabel(this);
-	intro_text_->setText(QApplication::translate("WelcomePage",
-						     "<html>"
-						     "<head/>"
-						     "<body>"
-						     "    <p align=\"center\" style=\"margin: 0; line-height: 2pt\">"
-						     "      <span style=\" font-size:18px; color:#515151;\"> "
-						     "		Welcome to nheko! The desktop client for the Matrix protocol."
-						     "	    </span>"
-						     "    </p>\n"
-						     "    <p align=\"center\" style=\"margin: 1pt; line-height: 2pt;\">"
-						     "        <span style=\" font-size:18px; color:#515151;\">Enjoy your stay!</span>"
-						     "    </p>"
-						     "</body>"
-						     "</html>",
-						     Q_NULLPTR));
+
+	QString heading(tr("Welcome to nheko! The desktop client for the Matrix protocol."));
+	QString main(tr("Enjoy your stay!"));
+
+	intro_text_->setText(QString("<p align=\"center\" style=\"margin: 0; line-height: 2pt\">"
+				     "  <span style=\" font-size:18px; color:#515151;\"> %1 </span>"
+				     "</p>"
+				     "<p align=\"center\" style=\"margin: 1pt; line-height: 2pt;\">"
+				     "  <span style=\" font-size:18px; color:#515151;\"> %2 </span>"
+				     "</p>")
+				     .arg(heading)
+				     .arg(main));
 
 	top_layout_->addStretch(1);
 	top_layout_->addWidget(intro_banner_);
@@ -60,7 +57,7 @@ WelcomePage::WelcomePage(QWidget *parent)
 	button_layout_->setSpacing(0);
 	button_layout_->setContentsMargins(0, 20, 0, 80);
 
-	register_button_ = new RaisedButton("REGISTER", this);
+	register_button_ = new RaisedButton(tr("REGISTER"), this);
 	register_button_->setBackgroundColor(QColor("#333333"));
 	register_button_->setForegroundColor(QColor("white"));
 	register_button_->setMinimumSize(240, 60);
@@ -68,7 +65,7 @@ WelcomePage::WelcomePage(QWidget *parent)
 	register_button_->setFontSize(14);
 	register_button_->setCornerRadius(3);
 
-	login_button_ = new RaisedButton("LOGIN", this);
+	login_button_ = new RaisedButton(tr("LOGIN"), this);
 	login_button_->setBackgroundColor(QColor("#333333"));
 	login_button_->setForegroundColor(QColor("white"));
 	login_button_->setMinimumSize(240, 60);
diff --git a/src/main.cc b/src/main.cc
index 993eea82743d37908065cd7b3493173562bdd12b..e6d4c4e76ee727c56d32aedb78297fda106cd692 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -18,6 +18,8 @@
 #include <QApplication>
 #include <QDesktopWidget>
 #include <QFontDatabase>
+#include <QLibraryInfo>
+#include <QTranslator>
 
 #include "MainWindow.h"
 
@@ -44,6 +46,16 @@ int main(int argc, char *argv[])
 	QFont font("Open Sans");
 	app.setFont(font);
 
+	QString lang = QLocale::system().name();
+
+	QTranslator qtTranslator;
+	qtTranslator.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
+	app.installTranslator(&qtTranslator);
+
+	QTranslator appTranslator;
+	appTranslator.load("nheko_" + lang, ":/translations");
+	app.installTranslator(&appTranslator);
+
 	MainWindow w;
 
 	// Move the MainWindow to the center