Add save+open to notebook, allow multiple windows, add translations, add welcome window
diff --git a/REFAL.pro b/REFAL.pro
index b4fa9c5..6ff0562 100644
--- a/REFAL.pro
+++ b/REFAL.pro
@@ -39,3 +39,6 @@
 !isEmpty(target.path): INSTALLS += target
 
 LIBS += -lreadline
+
+TRANSLATIONS += $$files(ts/*.ts)
+RESOURCES += translations.qrc
diff --git a/edit-translations.sh b/edit-translations.sh
new file mode 100755
index 0000000..fed1076
--- /dev/null
+++ b/edit-translations.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+linguist-qt5 ts/refal_*.ts
+lrelease-pro REFAL.pro
diff --git a/ide/Cell.cpp b/ide/Cell.cpp
index d00a219..85d20a3 100644
--- a/ide/Cell.cpp
+++ b/ide/Cell.cpp
@@ -90,6 +90,14 @@
         return nullptr;
 }
 
+void Cell::fromJson(QJsonObject json)
+{
+    setCode(json["code"].toString());
+    setResult(json["result"].toString());
+    setStatus(json["status"].toInt());
+    setResultType(json["resultType"].toInt());
+}
+
 QJsonObject Cell::toJson() const
 {
     QJsonObject object;
diff --git a/ide/Cell.h b/ide/Cell.h
index 55da010..350874c 100644
--- a/ide/Cell.h
+++ b/ide/Cell.h
@@ -38,6 +38,7 @@
 
     Q_INVOKABLE static Cell *cellFromUuid(QUuid uuid);
 
+    Q_INVOKABLE void fromJson(QJsonObject json);
     Q_INVOKABLE QJsonObject toJson() const;
 
     enum Status
diff --git a/ide/IdeMain.cpp b/ide/IdeMain.cpp
index caa0c85..ff8025f 100644
--- a/ide/IdeMain.cpp
+++ b/ide/IdeMain.cpp
@@ -2,15 +2,12 @@
 
 #include <QQmlApplicationEngine>
 #include <QQuickStyle>
+#include <QTranslator>
 
 #include "CellModel.h"
 
 int ideMain(Application *app)
 {
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
-#endif
-
     QQmlApplicationEngine engine;
 
     QQuickStyle::setStyle("Material");
@@ -18,6 +15,10 @@
     qRegisterMetaType<CellModel>();
     qRegisterMetaType<CellModel *>();
 
+    QTranslator translator;
+    qInfo() << "loading translations" << translator.load(QLocale(), "refal", "_", ":/ts/", ".qm");
+    app->installTranslator(&translator);
+
     const QUrl url(QStringLiteral("qrc:/qml/main.qml"));
     QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                      app, [url](QObject *obj, const QUrl &objUrl)
diff --git a/ide/Notebook.cpp b/ide/Notebook.cpp
index 8d0e8ee..36cc0a3 100644
--- a/ide/Notebook.cpp
+++ b/ide/Notebook.cpp
@@ -5,6 +5,7 @@
 #include <QJsonObject>
 #include <QJsonArray>
 #include <QFileDialog>
+#include <QDebug>
 
 // TODO: avoid potential race condition if Cell is deleted, pass by value with same UUID instead
 
@@ -57,6 +58,47 @@
     _rt->unqueueCell(Cell::cellFromUuid(uuid));
 }
 
+void Notebook::fromJson(QJsonDocument doc)
+{
+    QJsonObject nb = doc.object();
+    QJsonArray cellArray = nb["cells"].toArray();
+
+    for (const QJsonValueRef &cell : cellArray)
+    {
+        cellModel()->insertCellBefore(cellModel()->rowCount());
+        _cells.last()->fromJson(cell.toObject());
+    }
+}
+
+void Notebook::open(QString path)
+{
+    QFile file(path);
+
+    if (file.exists())
+    {
+        file.open(QFile::ReadOnly);
+
+        QJsonParseError error;
+        QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
+
+        if (error.error == QJsonParseError::NoError)
+        {
+            fromJson(doc);
+        }
+        else
+        {
+            qWarning() << error.errorString();
+        }
+
+        file.close();
+        setSavePath(path);
+    }
+    else
+    {
+        qWarning() << "File does not exist" << path;
+    }
+}
+
 QJsonDocument Notebook::toJson() const
 {
     QJsonObject nb;
diff --git a/ide/Notebook.h b/ide/Notebook.h
index dda07bc..6a6541d 100644
--- a/ide/Notebook.h
+++ b/ide/Notebook.h
@@ -26,6 +26,9 @@
     Q_INVOKABLE void runCell(QUuid uuid);
     Q_INVOKABLE void quitCell(QUuid uuid);
 
+    Q_INVOKABLE void fromJson(QJsonDocument doc);
+    Q_INVOKABLE void open(QString path);
+
     Q_INVOKABLE QJsonDocument toJson() const;
     Q_INVOKABLE void save();
 
diff --git a/ide/icons/book.svg b/ide/icons/book.svg
new file mode 100644
index 0000000..24d24e2
--- /dev/null
+++ b/ide/icons/book.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M18.125 1.875C15.484 1.88633 13.5207 2.25 12.1 2.87852C11.0398 3.34727 10.625 3.70195 10.625 4.90352V17.5C12.2488 16.0352 13.6898 15.625 19.375 15.625V1.875H18.125ZM1.875 1.875C4.51602 1.88633 6.4793 2.25 7.9 2.87852C8.96016 3.34727 9.375 3.70195 9.375 4.90352V17.5C7.75117 16.0352 6.31016 15.625 0.625 15.625V1.875H1.875Z" fill="#C8C8C8"/>
+</svg>
diff --git a/ide/icons/document.svg b/ide/icons/document.svg
new file mode 100644
index 0000000..918c5ad
--- /dev/null
+++ b/ide/icons/document.svg
@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9.375 8.4375V1.25H3.59375C3.46943 1.25 3.3502 1.29939 3.26229 1.38729C3.17439 1.4752 3.125 1.59443 3.125 1.71875V18.2812C3.125 18.4056 3.17439 18.5248 3.26229 18.6127C3.3502 18.7006 3.46943 18.75 3.59375 18.75H16.4062C16.5306 18.75 16.6498 18.7006 16.7377 18.6127C16.8256 18.5248 16.875 18.4056 16.875 18.2812V8.75H9.6875C9.60462 8.75 9.52513 8.71708 9.46653 8.65847C9.40792 8.59987 9.375 8.52038 9.375 8.4375Z" fill="#C8C8C8"/>
+<path d="M10.625 1.62852V7.34375C10.625 7.38519 10.6415 7.42493 10.6708 7.45423C10.7001 7.48354 10.7398 7.5 10.7813 7.5H16.4965C16.5119 7.50001 16.527 7.49545 16.5399 7.48689C16.5527 7.47833 16.5627 7.46616 16.5687 7.45191C16.5746 7.43766 16.5762 7.42197 16.5732 7.40682C16.5702 7.39167 16.5629 7.37774 16.552 7.3668L10.7582 1.57305C10.7473 1.56217 10.7333 1.55477 10.7182 1.5518C10.703 1.54882 10.6873 1.5504 10.6731 1.55633C10.6588 1.56227 10.6467 1.57229 10.6381 1.58514C10.6295 1.59799 10.625 1.61308 10.625 1.62852V1.62852Z" fill="#C8C8C8"/>
+</svg>
diff --git a/ide/qml/NbWindow.qml b/ide/qml/NbWindow.qml
new file mode 100644
index 0000000..5710c9e
--- /dev/null
+++ b/ide/qml/NbWindow.qml
@@ -0,0 +1,213 @@
+import QtQuick 2.5
+import QtQuick.Controls 2.15
+import QtQuick.Controls.Material 2.0
+import QtQuick.Layouts 1.3
+
+import sh.swisschili.REFAL 1.0
+
+ApplicationWindow {
+    id: root
+    width: 800
+    height: 800
+    title: "Refal Notebook — " + notebook.savePath
+    visible: true
+
+    Material.theme: Material.Light
+    Material.accent: Material.Orange
+
+    minimumWidth: column.implicitWidth
+
+    required property ApplicationWindow welcomeWindow
+
+    function openNotebook(path) {
+        notebook.open(path);
+    }
+
+    menuBar: MenuBar {
+        Menu {
+            title: qsTr("&File")
+
+            Action {
+                text: qsTr("&New")
+
+                onTriggered: {
+                    welcomeWindow.openNotebook();
+                }
+            }
+
+            Action {
+                text: qsTr("&Save")
+                shortcut: "Ctrl+s"
+
+                onTriggered: {
+                    notebook.save()
+                }
+            }
+
+            Action {
+                text: qsTr("&Open")
+                shortcut: "Ctrl+o"
+
+                onTriggered: {
+                    notebook.open();
+                }
+            }
+        }
+
+        Menu {
+            title: qsTr("&View")
+
+            Action {
+                text: qsTr("&Welcome Window")
+                checkable: true
+
+                checked: welcomeWindow.visible
+
+                onTriggered: {
+                    welcomeWindow.toggleVisible()
+                }
+            }
+
+            Action {
+                id: varInspector
+                text: qsTr("&Variable Inspector")
+
+                checkable: true
+            }
+        }
+
+        Menu {
+            title: qsTr("&Runtime")
+
+            Action {
+                text: qsTr("Run &Selected Cell")
+                shortcut: "Ctrl+Return"
+
+                onTriggered: {
+                    if (codeEditor.currentItem !== null) {
+                        notebook.runCell(codeEditor.currentItem.uuid)
+                    }
+                }
+            }
+
+            Action {
+                text: qsTr("Run &All")
+            }
+
+            Action {
+                text: qsTr("&Reset Runtime State")
+            }
+        }
+    }
+
+    Notebook {
+        id: notebook
+
+        onSaveError: (message) =>
+        {
+            console.error(message)
+        }
+    }
+
+    ColumnLayout {
+        id: column
+        anchors.fill: parent
+
+        SplitView {
+            id: split
+            Layout.fillHeight: true
+            Layout.fillWidth: true
+            orientation: Qt.Horizontal
+
+            ListView {
+                id: codeEditor
+                SplitView.fillWidth: true
+                SplitView.minimumWidth: 400
+                model: notebook.cellModel
+                clip: true
+
+                spacing: 5
+
+                header: ColumnLayout {
+                    width: codeEditor.width
+
+                    Pane {
+                        Layout.bottomMargin: 0
+
+                        ColumnLayout {
+                            Label {
+                                font.pointSize: 18
+                                text: qsTr("Notebook")
+                            }
+
+                            Label {
+                                visible: codeEditor.count === 0
+
+                                text: qsTr("Looks like you haven't created any cells yet. Click the + button below to create one.")
+                            }
+                        }
+                    }
+
+                    InsertRow {
+                        onInsertClicked: notebook.cellModel.insertCellBefore(0)
+                    }
+
+                    Item {
+                        height: 5 // JANK!
+                    }
+                }
+
+                delegate: NotebookCell {
+                    id: notebookCell
+
+                    required property var model
+                    required property var index
+                    required property var uuid
+
+                    width: codeEditor.width
+
+                    code: model.code
+                    result: model.result.trim()
+                    status: model.status
+                    resultType: model.resultType
+                    cellActive: codeEditor.currentIndex === index
+
+                    onCodeEditingFinished: code => model.code = code
+
+                    onInsertBelowClicked: {
+                        console.info(index);
+                        notebook.cellModel.insertCellBefore(index + 1);
+                    }
+
+                    onRunClicked: {
+                        notebook.runCell(uuid)
+                    }
+
+                    onCellFocused: {
+                        codeEditor.currentIndex = index
+                    }
+
+                    onDeleteClicked: {
+                        notebook.cellModel.deleteCellAt(index)
+                    }
+
+                    onCellUnfocused: {
+                        codeEditor.currentIndex = -1
+                    }
+                }
+            }
+
+            Item {
+                id: variables
+                SplitView.minimumWidth: 240
+
+                visible: varInspector.checked
+
+                Label {
+                    anchors.centerIn: parent
+                    text: qsTr("Variables")
+                }
+            }
+        }
+    }
+}
diff --git a/ide/qml/NotebookCell.qml b/ide/qml/NotebookCell.qml
index 24eaf17..7653dd7 100644
--- a/ide/qml/NotebookCell.qml
+++ b/ide/qml/NotebookCell.qml
@@ -90,7 +90,7 @@
                         selectByMouse: true
                         wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
 
-                        placeholderText: "Write some code..."
+                        placeholderText: qsTr("Write some code...")
 
                         Keys.onTabPressed: {
                             var pos = cursorPosition + 4
@@ -134,7 +134,7 @@
                         MenuItem {
                             icon.source: "qrc:///icons/trash.svg"
                             icon.color: Material.color(Material.Red)
-                            text: "Delete"
+                            text: qsTr("Delete")
 
                             onClicked: root.deleteClicked()
                         }
diff --git a/ide/qml/RecentNotebook.qml b/ide/qml/RecentNotebook.qml
new file mode 100644
index 0000000..d0b1120
--- /dev/null
+++ b/ide/qml/RecentNotebook.qml
@@ -0,0 +1,39 @@
+import QtQuick 2.0
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.0
+
+RowLayout {
+    id: root
+
+    property string name: "Hello.refnb"
+    property alias containsMouse: mouseArea.containsMouse
+    signal clicked()
+
+    Image {
+        id: nbIcon
+        width: 100
+        height: 100
+        source: "qrc:///icons/document.svg"
+        fillMode: Image.PreserveAspectFit
+    }
+
+    Label {
+        text: name
+        Layout.fillWidth: true
+
+        MouseArea {
+            id: mouseArea
+
+            anchors.fill: parent
+            hoverEnabled: true
+
+            onClicked: root.clicked()
+        }
+    }
+}
+
+/*##^##
+Designer {
+    D{i:0;autoSize:true;height:24;width:300}
+}
+##^##*/
diff --git a/ide/qml/Tip.qml b/ide/qml/Tip.qml
new file mode 100644
index 0000000..ba6084b
--- /dev/null
+++ b/ide/qml/Tip.qml
@@ -0,0 +1,33 @@
+import QtQuick 2.0
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.0
+
+RowLayout {
+    id: root
+
+    property string title: "title"
+    property string url: "https://swisschili.sh"
+    property alias containsMouse: mouseArea.containsMouse
+
+    Image {
+        id: nbIcon
+        width: 100
+        height: 100
+        source: "qrc:///icons/book.svg"
+        fillMode: Image.PreserveAspectFit
+    }
+
+    Label {
+        text: title
+        Layout.fillWidth: true
+
+        MouseArea {
+            id: mouseArea
+
+            anchors.fill: parent
+            hoverEnabled: true
+
+            onClicked: Qt.openUrlExternally(url)
+        }
+    }
+}
diff --git a/ide/qml/main.qml b/ide/qml/main.qml
index ab86efd..23f8926 100644
--- a/ide/qml/main.qml
+++ b/ide/qml/main.qml
@@ -1,178 +1,186 @@
-import QtQuick 2.5
+import QtQuick 2.0
 import QtQuick.Controls 2.15
 import QtQuick.Controls.Material 2.0
-import QtQuick.Layouts 1.3
-
-import sh.swisschili.REFAL 1.0
+import QtQuick.Layouts 1.11
 
 ApplicationWindow {
     id: root
-    width: 1080
-    height: 720
-    title: "Refal Notebook -- " + notebook.savePath
-    visible: true
+
+    title: "REFAL Studio"
+
+    width: 680
+    height: 360
+
+    minimumWidth: 680
+    minimumHeight: 360
 
     Material.theme: Material.Light
     Material.accent: Material.Orange
 
-    menuBar: MenuBar {
-        Menu {
-            title: qsTr("&File")
+    visible: true
 
-            Action {
-                text: "&Save"
-                shortcut: "Ctrl+s"
+    function openNotebook(path=null) {
+        let NbWindow = Qt.createComponent("qrc:///qml/NbWindow.qml");
+        let window = NbWindow.createObject(null, {welcomeWindow: root});
 
-                onTriggered: {
-                    notebook.save()
-                }
-            }
-        }
-
-        Menu {
-            title: qsTr("&Runtime")
-
-            Action {
-                text: qsTr("Run &Selected Cell")
-                shortcut: "Ctrl+Return"
-
-                onTriggered: {
-                    if (codeEditor.currentItem !== null) {
-                        notebook.runCell(codeEditor.currentItem.uuid)
-                    }
-                }
-            }
-        }
-    }
-
-    Notebook {
-        id: notebook
-
-        onSaveError: (message) =>
+        if (path !== null)
         {
-            console.error(message)
+            window.openNotebook(path)
         }
     }
 
-    ColumnLayout {
-        id: column
-        anchors.fill: parent
+    function toggleVisible() {
+        if (visible)
+            hide();
+        else
+            show();
+    }
 
-        TabBar {
-            id: bar
+    Label {
+        id: textRefal
+        text: qsTr("REFAL")
+        anchors.left: parent.left
+        anchors.top: parent.top
+        font.pixelSize: 36
+        anchors.leftMargin: 36
+        anchors.topMargin: 29
+        font.weight: Font.Black
+        font.bold: true
+        font.italic: false
+    }
 
-            Layout.fillWidth: true
+    Label {
+        id: textStudio
+        y: 29
+        text: qsTr("Studio")
+        anchors.verticalCenter: textRefal.verticalCenter
+        anchors.left: textRefal.right
+        font.pixelSize: 36
+        anchors.leftMargin: 6
+        font.bold: false
+        font.italic: false
+        font.weight: Font.Medium
+        color: Material.color(Material.Orange)
+    }
 
-            TabButton {
-                text: "Notebook"
-                width: implicitWidth
+    Rectangle {
+        id: sepRect
+        x: 364
+        width: 1
+        color: "#cecece"
+        anchors.top: parent.top
+        anchors.bottom: parent.bottom
+        anchors.bottomMargin: 14
+        anchors.topMargin: 78
+        anchors.horizontalCenter: parent.horizontalCenter
+    }
+
+    Flickable {
+        id: notebooksFlick
+        anchors.left: textRefal.left
+        anchors.right: sepRect.left
+        anchors.top: textRefal.bottom
+        anchors.bottom: parent.bottom
+        anchors.leftMargin: -8
+        anchors.rightMargin: 16
+        anchors.bottomMargin: 16
+        anchors.topMargin: 6
+        clip: true
+        flickableDirection: Flickable.VerticalFlick
+
+        ColumnLayout {
+            id: notebooksCol
+            spacing: 12
+
+            RowLayout {
+                id: nbBtnsRow
+                spacing: 12
+                Layout.alignment: Qt.AlignLeft | Qt.AlignTop
+                Layout.fillWidth: true
+                Layout.fillHeight: false
+                Layout.leftMargin: 8
+                Layout.rightMargin: 8
+
+                Button {
+                    id: newNotebookBtn
+                    text: qsTr("New Notebook")
+                    font.bold: true
+                    highlighted: true
+
+                    onClicked: {
+                        root.openNotebook();
+                    }
+                }
+
+                Button {
+                    id: openNotebookBtn
+                    text: qsTr("Open Existing")
+                }
             }
 
-            TabButton {
-                text: "Another Notebook"
-                width: implicitWidth
+            Repeater {
+                id: notebooksList
+
+                Layout.alignment: Qt.AlignLeft | Qt.AlignTop
+                Layout.fillWidth: true
+                Layout.fillHeight: false
+
+                model: [
+                    // "~/Documents/Hello.refnb", "~/Downloads/stuff/Goodbye.refnb", "/home/ch/dev/REFAL/build/test.refnb"
+                ]
+
+                delegate: RecentNotebook {
+                    Layout.leftMargin: 8
+                    Layout.rightMargin: 8
+
+                    name: modelData.split("/").pop()
+
+                    ToolTip.text: modelData
+                    ToolTip.visible: containsMouse
+                    ToolTip.delay: 1000
+
+                    onClicked: root.openNotebook(modelData)
+                }
             }
 
-            TabButton {
-                text: "Testing"
-                width: implicitWidth
+            Label {
+                Layout.leftMargin: 8
+                Layout.rightMargin: 8
+
+                visible: notebooksList.count == 0
+                text: qsTr("Your recent notebooks will appear here")
             }
         }
+    }
 
-        SplitView {
-            id: split
-            Layout.fillHeight: true
+    ListView {
+        id: tipsList
+        anchors.left: sepRect.right
+        anchors.right: parent.right
+        anchors.top: textRefal.bottom
+        anchors.bottom: parent.bottom
+        anchors.bottomMargin: 16
+        anchors.topMargin: 6
+        anchors.leftMargin: 16
+        anchors.rightMargin: 36
+        spacing: 12
+
+        model: [
+            {url: "https://wiki.swisschili.sh/wiki/REFAL", title: "REFAL Studio Wiki"},
+            {url: "https://wiki.swisschili.sh/wiki/REFAL/Cookbook", title: "REFAL Cookbook"},
+            {url: "http://refal.botik.ru/book/html/", title: "REFAL-5 Programming Guide (en)"},
+            {url: "http://refal.net/rf5_frm.htm", title: "REFAL-5 Programming Guide (ru)"}
+        ]
+
+        delegate: Tip {
             Layout.fillWidth: true
-            orientation: Qt.Horizontal
 
-            ListView {
-                id: codeEditor
-                SplitView.fillWidth: true
-                SplitView.minimumWidth: 400
-                model: notebook.cellModel
-                clip: true
+            url: modelData.url
+            title: modelData.title
 
-                spacing: 5
-
-                header: ColumnLayout {
-                    width: codeEditor.width
-
-                    Pane {
-                        Layout.bottomMargin: 0
-
-                        ColumnLayout {
-                            Label {
-                                font.pointSize: 18
-                                text: "Notebook"
-                            }
-
-                            Label {
-                                visible: codeEditor.count === 0
-
-                                text: "Looks like you haven't created any cells yet. Click the + button below to create one."
-                            }
-                        }
-                    }
-
-                    InsertRow {
-                        onInsertClicked: notebook.cellModel.insertCellBefore(0)
-                    }
-
-                    Item {
-                        height: 5 // JANK!
-                    }
-                }
-
-                delegate: NotebookCell {
-                    id: notebookCell
-
-                    required property var model
-                    required property var index
-                    required property var uuid
-
-                    width: codeEditor.width
-
-                    code: model.code
-                    result: model.result.trim()
-                    status: model.status
-                    resultType: model.resultType
-                    cellActive: codeEditor.currentIndex === index
-
-                    onCodeEditingFinished: code => model.code = code
-
-                    onInsertBelowClicked: {
-                        console.info(index);
-                        notebook.cellModel.insertCellBefore(index + 1);
-                    }
-
-                    onRunClicked: {
-                        console.info("Cell run clicked")
-                        notebook.runCell(uuid)
-                    }
-
-                    onCellFocused: {
-                        codeEditor.currentIndex = index
-                    }
-
-                    onDeleteClicked: {
-                        notebook.cellModel.deleteCellAt(index)
-                    }
-
-                    onCellUnfocused: {
-                        codeEditor.currentIndex = -1
-                    }
-                }
-            }
-
-            Item {
-                id: variables
-                SplitView.minimumWidth: 240
-
-                Label {
-                    anchors.centerIn: parent
-                    text: "Vars"
-                }
-            }
+            ToolTip.text: modelData.url
+            ToolTip.visible: containsMouse
+            ToolTip.delay: 1000
         }
     }
 }
diff --git a/ide/resources.qrc b/ide/resources.qrc
index c4b120e..f76afd3 100644
--- a/ide/resources.qrc
+++ b/ide/resources.qrc
@@ -1,6 +1,6 @@
 <RCC>
     <qresource prefix="/">
-        <file>qml/main.qml</file>
+        <file>qml/NbWindow.qml</file>
         <file>qml/NotebookCell.qml</file>
         <file>icons/play-circle.svg</file>
         <file>icons/add.svg</file>
@@ -10,5 +10,10 @@
         <file>icons/menu.svg</file>
         <file>qml/Constants.qml</file>
         <file>qml/qmldir</file>
+        <file>qml/main.qml</file>
+        <file>icons/book.svg</file>
+        <file>icons/document.svg</file>
+        <file>qml/RecentNotebook.qml</file>
+        <file>qml/Tip.qml</file>
     </qresource>
 </RCC>
diff --git a/main.cpp b/main.cpp
index 278f1d0..42cc0a4 100644
--- a/main.cpp
+++ b/main.cpp
@@ -268,6 +268,9 @@
 int main(int argc, char *argv[])
 {
     QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
 
     Application a(argc, argv);
     a.setApplicationName("REFAL");
diff --git a/translations.qrc b/translations.qrc
new file mode 100644
index 0000000..a79f88e
--- /dev/null
+++ b/translations.qrc
@@ -0,0 +1,8 @@
+<RCC>
+    <qresource prefix="/">
+        <file>ts/refal_en_US.qm</file>
+        <file>ts/refal_en_US.ts</file>
+        <file>ts/refal_ru_RU.qm</file>
+        <file>ts/refal_ru_RU.ts</file>
+    </qresource>
+</RCC>
diff --git a/ts/refal_en_US.qm b/ts/refal_en_US.qm
new file mode 100644
index 0000000..71c6570
--- /dev/null
+++ b/ts/refal_en_US.qm
Binary files differ
diff --git a/ts/refal_en_US.ts b/ts/refal_en_US.ts
new file mode 100644
index 0000000..cf241b8
--- /dev/null
+++ b/ts/refal_en_US.ts
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="en_US">
+<context>
+    <name></name>
+    <message>
+        <source>REFAL</source>
+        <translation type="obsolete">REFAL</translation>
+    </message>
+</context>
+<context>
+    <name>NbWindow</name>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="28"/>
+        <source>&amp;File</source>
+        <translation>&amp;File</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="31"/>
+        <source>&amp;New</source>
+        <translation>&amp;New</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="35"/>
+        <source>&amp;Save</source>
+        <translation>&amp;Save</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="44"/>
+        <source>&amp;Open</source>
+        <translation>&amp;Open</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="54"/>
+        <source>&amp;View</source>
+        <translation>&amp;View</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="57"/>
+        <source>&amp;Welcome Window</source>
+        <translation>&amp;Welcome Window</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="69"/>
+        <source>&amp;Variable Inspector</source>
+        <translation>&amp;Variable Inspector</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="80"/>
+        <source>&amp;Runtime</source>
+        <translation>&amp;Runtime</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="83"/>
+        <source>Run &amp;Selected Cell</source>
+        <translation>Run &amp;Selected Cell</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="94"/>
+        <source>Run &amp;All</source>
+        <translation>Run &amp;All</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="98"/>
+        <source>&amp;Reset Runtime State</source>
+        <translation>&amp;Reset Runtime State</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="140"/>
+        <source>Notebook</source>
+        <translation>Notebook</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="146"/>
+        <source>Looks like you haven&apos;t created any cells yet. Click the + button below to create one.</source>
+        <translation>Looks like you haven&apos;t created any cells yet. Click the + button below to create one.</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="208"/>
+        <source>Variables</source>
+        <translation>Variables</translation>
+    </message>
+</context>
+<context>
+    <name>NotebookCell</name>
+    <message>
+        <location filename="../ide/qml/NotebookCell.qml" line="93"/>
+        <source>Write some code...</source>
+        <translation>Write some code...</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NotebookCell.qml" line="137"/>
+        <source>Delete</source>
+        <translation>Delete</translation>
+    </message>
+</context>
+<context>
+    <name>main</name>
+    <message>
+        <location filename="../ide/qml/main.qml" line="41"/>
+        <source>REFAL</source>
+        <translation>REFAL</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/main.qml" line="55"/>
+        <source>Studio</source>
+        <translation>Studio</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/main.qml" line="106"/>
+        <source>New Notebook</source>
+        <translation>New Notebook</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/main.qml" line="117"/>
+        <source>Open Existing</source>
+        <translation>Open Existing</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/main.qml" line="151"/>
+        <source>Your recent notebooks will appear here</source>
+        <translation>Your recent notebooks will appear here</translation>
+    </message>
+</context>
+</TS>
diff --git a/ts/refal_ru_RU.qm b/ts/refal_ru_RU.qm
new file mode 100644
index 0000000..ca42b3a
--- /dev/null
+++ b/ts/refal_ru_RU.qm
Binary files differ
diff --git a/ts/refal_ru_RU.ts b/ts/refal_ru_RU.ts
new file mode 100644
index 0000000..fbf55af
--- /dev/null
+++ b/ts/refal_ru_RU.ts
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ru_RU">
+<context>
+    <name></name>
+    <message>
+        <source>REFAL</source>
+        <translation type="obsolete">РЕФАЛ</translation>
+    </message>
+</context>
+<context>
+    <name>NbWindow</name>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="28"/>
+        <source>&amp;File</source>
+        <translation>&amp;Файл</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="31"/>
+        <source>&amp;New</source>
+        <translation>Создать &amp;Новую Тетрадь</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="35"/>
+        <source>&amp;Save</source>
+        <translation>&amp;Сохранить</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="44"/>
+        <source>&amp;Open</source>
+        <translation>&amp;Открыть</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="54"/>
+        <source>&amp;View</source>
+        <translation>&amp;Видеть</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="57"/>
+        <source>&amp;Welcome Window</source>
+        <translation>&amp;Стартовая Страниця</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="69"/>
+        <source>&amp;Variable Inspector</source>
+        <translation>Инспектор &amp;Переменных</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="80"/>
+        <source>&amp;Runtime</source>
+        <translation>&amp;Выполнение</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="83"/>
+        <source>Run &amp;Selected Cell</source>
+        <translation>Запутстить Выбранную &amp;Ячейку</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="94"/>
+        <source>Run &amp;All</source>
+        <translation>Запустить &amp;Все Ячейки</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="98"/>
+        <source>&amp;Reset Runtime State</source>
+        <translation>Востоновить &amp;Исходное Состояние</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="140"/>
+        <source>Notebook</source>
+        <translation>Тетрадь</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="146"/>
+        <source>Looks like you haven&apos;t created any cells yet. Click the + button below to create one.</source>
+        <translation>Вы еще не создали ячейку, нажмите кнопку + снизы что бы её создать.</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NbWindow.qml" line="208"/>
+        <source>Variables</source>
+        <translation>Переменные</translation>
+    </message>
+</context>
+<context>
+    <name>NotebookCell</name>
+    <message>
+        <location filename="../ide/qml/NotebookCell.qml" line="93"/>
+        <source>Write some code...</source>
+        <translation>Напишите какой-нибудь код...</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/NotebookCell.qml" line="137"/>
+        <source>Delete</source>
+        <translation>Стереть</translation>
+    </message>
+</context>
+<context>
+    <name>main</name>
+    <message>
+        <location filename="../ide/qml/main.qml" line="41"/>
+        <source>REFAL</source>
+        <translation>РЕФАЛ</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/main.qml" line="55"/>
+        <source>Studio</source>
+        <translation>Студия</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/main.qml" line="106"/>
+        <source>New Notebook</source>
+        <translation>Создать Тетрадь</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/main.qml" line="117"/>
+        <source>Open Existing</source>
+        <translation>Открыть</translation>
+    </message>
+    <message>
+        <location filename="../ide/qml/main.qml" line="151"/>
+        <source>Your recent notebooks will appear here</source>
+        <translation>Ваши недавние тетради появится здесь</translation>
+    </message>
+</context>
+</TS>
diff --git a/update-translations.sh b/update-translations.sh
new file mode 100755
index 0000000..0e44d35
--- /dev/null
+++ b/update-translations.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+lupdate-pro REFAL.pro -verbose