diff --git a/ocs-url.pro b/ocs-url.pro
index 304f58312d14899c2ebb61db8a5e42a184492c6f..4f7a1ded53a11157a65c0da55680ab19915d8533 100644
--- a/ocs-url.pro
+++ b/ocs-url.pro
@@ -6,7 +6,9 @@ CONFIG += c++11
 
 DEFINES += QT_DEPRECATED_WARNINGS
 
-RESOURCES += src/desktop/desktop.qrc
+RESOURCES += \
+    src/desktop/desktop.qrc \
+    src/i18n/i18n.qrc
 
 DISTFILES += \
     README.md \
diff --git a/src/app/handlers/ocsurlhandler.cpp b/src/app/handlers/ocsurlhandler.cpp
index 52edf33322b60e796774c52281a2836ea854d9b8..3527d7b7387b715d1fe92f04bd30356f1c26ff7a 100644
--- a/src/app/handlers/ocsurlhandler.cpp
+++ b/src/app/handlers/ocsurlhandler.cpp
@@ -34,7 +34,7 @@ void OcsUrlHandler::process()
     if (!isValid()) {
         QJsonObject result;
         result["status"] = QString("error_validation");
-        result["message"] = QString("Invalid OCS-URL " + ocsUrl_);
+        result["message"] = tr("Invalid OCS-URL");
         emit finishedWithError(result);
         return;
     }
@@ -138,14 +138,14 @@ void OcsUrlHandler::saveDownloadedFile(qtlib::NetworkResource *resource)
 
     if (!resource->saveData(destFile.path())) {
         result["status"] = QString("error_save");
-        result["message"] = QString("Failed to save data as " + destFile.path());
+        result["message"] = tr("Failed to save data");
         emit finishedWithError(result);
         resource->deleteLater();
         return;
     }
 
     result["status"] = QString("success_download");
-    result["message"] = QString("The file has been stored into " + destDir.path());
+    result["message"] = tr("The file has been downloaded");
     emit finishedWithSuccess(result);
 
     resource->deleteLater();
@@ -159,7 +159,7 @@ void OcsUrlHandler::installDownloadedFile(qtlib::NetworkResource *resource)
 
     if (!resource->saveData(tempFile.path())) {
         result["status"] = QString("error_save");
-        result["message"] = QString("Failed to save data as " + tempFile.path());
+        result["message"] = tr("Failed to save data");
         emit finishedWithError(result);
         resource->deleteLater();
         return;
@@ -173,41 +173,41 @@ void OcsUrlHandler::installDownloadedFile(qtlib::NetworkResource *resource)
 
     if (type == "bin"
             && package.installAsProgram(destFile.path())) {
-        result["message"] = QString("The file has been installed into " + destDir.path());
+        result["message"] = tr("The file has been installed as program");
     }
     else if ((type == "plasma_plasmoids" || type == "plasma4_plasmoids" || type == "plasma5_plasmoids")
              && package.installAsPlasmapkg("plasmoid")) {
-        result["message"] = QString("The plasmoid has been installed");
+        result["message"] = tr("The plasmoid has been installed");
     }
     else if ((type == "plasma_look_and_feel" || type == "plasma5_look_and_feel")
              && package.installAsPlasmapkg("lookandfeel")) {
-        result["message"] = QString("The plasma look and feel has been installed");
+        result["message"] = tr("The plasma look and feel has been installed");
     }
     else if ((type == "plasma_desktopthemes" || type == "plasma5_desktopthemes")
              && package.installAsPlasmapkg("theme")) {
-        result["message"] = QString("The plasma desktop theme has been installed");
+        result["message"] = tr("The plasma desktop theme has been installed");
     }
     else if (type == "kwin_effects"
              && package.installAsPlasmapkg("kwineffect")) {
-        result["message"] = QString("The KWin effect has been installed");
+        result["message"] = tr("The KWin effect has been installed");
     }
     else if (type == "kwin_scripts"
              && package.installAsPlasmapkg("kwinscript")) {
-        result["message"] = QString("The KWin script has been installed");
+        result["message"] = tr("The KWin script has been installed");
     }
     else if (type == "kwin_tabbox"
              && package.installAsPlasmapkg("windowswitcher")) {
-        result["message"] = QString("The KWin window switcher has been installed");
+        result["message"] = tr("The KWin window switcher has been installed");
     }
     else if (package.installAsArchive(destDir.path())) {
-        result["message"] = QString("The archive file has been extracted into " + destDir.path());
+        result["message"] = tr("The archive file has been extracted");
     }
     else if (package.installAsFile(destFile.path())) {
-        result["message"] = QString("The file has been installed into " + destDir.path());
+        result["message"] = tr("The file has been installed");
     }
     else {
         result["status"] = QString("error_install");
-        result["message"] = QString("Failed to installation");
+        result["message"] = tr("Failed to installation");
         emit finishedWithError(result);
         tempFile.remove();
         return;
diff --git a/src/app/main.cpp b/src/app/main.cpp
index 1d84cb4cf09b3d173345339561a5039fc9a01290..1cbaeb3ce4124b1dfbf369397197f3e1630e63c4 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -2,6 +2,8 @@
 #include <QStringList>
 #include <QUrl>
 #include <QJsonObject>
+#include <QTranslator>
+#include <QLocale>
 #include <QCommandLineParser>
 #include <QGuiApplication>
 #include <QIcon>
@@ -25,12 +27,18 @@ int main(int argc, char *argv[])
     app.setOrganizationDomain(appConfigApplication["domain"].toString());
     app.setWindowIcon(QIcon::fromTheme(appConfigApplication["id"].toString(), QIcon(appConfigApplication["icon"].toString())));
 
+    // Setup translator
+    QTranslator translator;
+    if (translator.load(QLocale(), "messages", ".", ":/i18n")) {
+        app.installTranslator(&translator);
+    }
+
     // Setup CLI
     QCommandLineParser clParser;
     clParser.setApplicationDescription(appConfigApplication["description"].toString());
     clParser.addHelpOption();
     clParser.addVersionOption();
-    clParser.addPositionalArgument("ocsurl", "OCS-URL");
+    clParser.addPositionalArgument("OCS-URL", "OCS-URL that starts with ocs://");
     clParser.process(app);
 
     QStringList args = clParser.positionalArguments();
diff --git a/src/app/qml/main.qml b/src/app/qml/main.qml
index 4e367f78c1898f618df70593574ebc8e672b4fa5..810065b1cb15ec99185155581907f6ac7a5399ea 100644
--- a/src/app/qml/main.qml
+++ b/src/app/qml/main.qml
@@ -153,7 +153,7 @@ Window {
         }
         else {
             errorDialog.text = qsTr("Validation error");
-            errorDialog.detailedText = qsTr("Invalid OCS-URL") + " " + ocsUrlHandler.ocsUrl();
+            errorDialog.detailedText = qsTr("Invalid OCS-URL");
             errorDialog.open();
         }
     }
diff --git a/src/i18n/i18n.pro b/src/i18n/i18n.pro
new file mode 100644
index 0000000000000000000000000000000000000000..a2f872dfd3a55711181e0ce2255b4aff69445048
--- /dev/null
+++ b/src/i18n/i18n.pro
@@ -0,0 +1,7 @@
+SOURCES += $$system(find ../app -type f -name "*.cpp" -or -name "*.qml" -or -name "*.js")
+
+TRANSLATIONS += \
+    messages.ts \
+    messages.en_US.ts
+
+RESOURCES += i18n.qrc
diff --git a/src/i18n/i18n.qrc b/src/i18n/i18n.qrc
new file mode 100644
index 0000000000000000000000000000000000000000..52757b9d77907783ab458abe337799f345695a3b
--- /dev/null
+++ b/src/i18n/i18n.qrc
@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/i18n">
+        <file>messages.en_US.qm</file>
+    </qresource>
+</RCC>