changeset 112:80f49f623d30

locale: allow switching locales without restarting
author Paper <mrpapersonic@gmail.com>
date Mon, 06 Nov 2023 13:41:30 -0500
parents fcae8bece0ec
children 32afe0e940bf
files CMakeLists.txt include/gui/widgets/sidebar.h include/gui/window.h rc/locale/en_GB.ts rc/locale/es.ts src/gui/dialog/settings/application.cc src/gui/pages/anime_list.cc src/gui/widgets/anime_info.cc src/gui/widgets/sidebar.cc src/gui/window.cc src/services/services.cc
diffstat 11 files changed, 286 insertions(+), 187 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Mon Nov 06 02:03:55 2023 -0500
+++ b/CMakeLists.txt	Mon Nov 06 13:41:30 2023 -0500
@@ -135,7 +135,7 @@
 	cmake_language(CALL qt${QT_VERSION_MAJOR}_create_translation ${SRC_FILES} ${TS_FILES} OPTIONS "-I${CMAKE_CURRENT_SOURCE_DIR}/include")
 endif()
 cmake_language(CALL qt${QT_VERSION_MAJOR}_add_translation QM_FILES ${TS_FILES})
-add_custom_target(translation SOURCES ${QM_FILES} DEPENDS ${TS_FILES})
+list(APPEND SRC_FILES ${QM_FILES})
 
 function(qt_create_resource_file outfile)
 	set(QRC "<!DOCTYPE rcc><RCC version=\"1.0\">\n\t<qresource>\n")
@@ -149,7 +149,7 @@
 endfunction()
 
 qt_create_resource_file("${CMAKE_CURRENT_BINARY_DIR}/rc/locale.qrc" ${QM_FILES})
-add_custom_target(resources DEPENDS translation SOURCES "${CMAKE_CURRENT_BINARY_DIR}/rc/locale.qrc")
+list(APPEND SRC_FILES "${CMAKE_CURRENT_BINARY_DIR}/rc/locale.qrc")
 
 # This is also used in the Win32 rc file
 set(RC_INFO_STRING "A lightweight anime tracker built with Qt.")
@@ -183,7 +183,6 @@
 endif()
 
 add_executable(minori WIN32 MACOSX_BUNDLE ${SRC_FILES})
-add_dependencies(minori resources)
 set_property(TARGET minori PROPERTY CXX_STANDARD 11)
 set_property(TARGET minori PROPERTY AUTOMOC ON)
 set_property(TARGET minori PROPERTY AUTORCC ON)
--- a/include/gui/widgets/sidebar.h	Mon Nov 06 02:03:55 2023 -0500
+++ b/include/gui/widgets/sidebar.h	Mon Nov 06 13:41:30 2023 -0500
@@ -13,6 +13,7 @@
 		SideBar(QWidget* parent = nullptr);
 		QListWidgetItem* AddItem(QString name, QIcon icon = QIcon());
 		QListWidgetItem* AddSeparator();
+		int GetCurrentItem();
 		bool IndexIsSeparator(QModelIndex index) const;
 		static QIcon CreateIcon(const char* file);
 		void SetBackgroundColor(QColor color);
--- a/include/gui/window.h	Mon Nov 06 02:03:55 2023 -0500
+++ b/include/gui/window.h	Mon Nov 06 13:41:30 2023 -0500
@@ -15,13 +15,17 @@
 		MainWindow(QWidget* parent = nullptr);
 		void SetActivePage(QWidget* page);
 		void CreateBars();
+		void AddMainWidgets();
+		void RetranslateUI();
+		void AsyncSynchronize(QStackedWidget* stack);
+		void changeEvent(QEvent* event) override;
 		void showEvent(QShowEvent* event) override;
 		void closeEvent(QCloseEvent* event) override;
 
 	private:
-		QWidget* main_widget;
-		QStackedWidget* stack;
-		SideBar* sidebar;
+		QWidget* main_widget = nullptr;
+		QStackedWidget* stack = nullptr;
+		SideBar* sidebar = nullptr;
 };
 
 #endif // __window_h
--- a/rc/locale/en_GB.ts	Mon Nov 06 02:03:55 2023 -0500
+++ b/rc/locale/en_GB.ts	Mon Nov 06 13:41:30 2023 -0500
@@ -185,252 +185,267 @@
 <context>
     <name>MainWindow</name>
     <message>
-        <location filename="../../src/gui/window.cc" line="65"/>
+        <location filename="../../src/gui/window.cc" line="99"/>
         <source>Now Playing</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="67"/>
+        <location filename="../../src/gui/window.cc" line="101"/>
         <source>Anime List</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="68"/>
+        <location filename="../../src/gui/window.cc" line="102"/>
         <source>History</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="69"/>
+        <location filename="../../src/gui/window.cc" line="103"/>
         <source>Statistics</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="71"/>
+        <location filename="../../src/gui/window.cc" line="105"/>
         <source>Search</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="72"/>
+        <location filename="../../src/gui/window.cc" line="106"/>
         <source>Seasons</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="73"/>
+        <location filename="../../src/gui/window.cc" line="107"/>
         <source>Torrents</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="117"/>
+        <location filename="../../src/gui/window.cc" line="133"/>
         <source>&amp;File</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="119"/>
+        <location filename="../../src/gui/window.cc" line="135"/>
         <source>&amp;Library folders</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="120"/>
+        <location filename="../../src/gui/window.cc" line="136"/>
         <source>&amp;Add new folder...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="122"/>
+        <location filename="../../src/gui/window.cc" line="138"/>
         <source>&amp;Scan available episodes</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="126"/>
+        <location filename="../../src/gui/window.cc" line="142"/>
         <source>Play &amp;next episode</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="128"/>
+        <location filename="../../src/gui/window.cc" line="144"/>
         <source>Play &amp;random episode</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="133"/>
+        <location filename="../../src/gui/window.cc" line="149"/>
         <source>E&amp;xit</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="135"/>
+        <location filename="../../src/gui/window.cc" line="151"/>
         <source>&amp;Services</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="136"/>
+        <location filename="../../src/gui/window.cc" line="152"/>
         <source>Synchronize &amp;list</source>
         <translation>Synchronise &amp;list</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="141"/>
+        <location filename="../../src/gui/window.cc" line="157"/>
         <source>&amp;AniList</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="142"/>
-        <location filename="../../src/gui/window.cc" line="148"/>
-        <location filename="../../src/gui/window.cc" line="152"/>
+        <location filename="../../src/gui/window.cc" line="158"/>
+        <location filename="../../src/gui/window.cc" line="164"/>
+        <location filename="../../src/gui/window.cc" line="168"/>
         <source>Go to my &amp;profile</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="143"/>
+        <location filename="../../src/gui/window.cc" line="159"/>
         <source>Go to my &amp;stats</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="145"/>
+        <location filename="../../src/gui/window.cc" line="161"/>
         <source>&amp;Kitsu</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="146"/>
+        <location filename="../../src/gui/window.cc" line="162"/>
         <source>Go to my &amp;feed</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="147"/>
+        <location filename="../../src/gui/window.cc" line="163"/>
         <source>Go to my &amp;library</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="150"/>
+        <location filename="../../src/gui/window.cc" line="166"/>
         <source>&amp;MyAnimeList</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="151"/>
+        <location filename="../../src/gui/window.cc" line="167"/>
         <source>Go to my p&amp;anel</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="153"/>
+        <location filename="../../src/gui/window.cc" line="169"/>
         <source>Go to my &amp;history</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="155"/>
+        <location filename="../../src/gui/window.cc" line="171"/>
         <source>&amp;Tools</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="156"/>
+        <location filename="../../src/gui/window.cc" line="172"/>
         <source>&amp;Export anime list</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="157"/>
+        <location filename="../../src/gui/window.cc" line="173"/>
         <source>Export as &amp;Markdown...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="158"/>
+        <location filename="../../src/gui/window.cc" line="174"/>
         <source>Export as MyAnimeList &amp;XML...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="162"/>
+        <location filename="../../src/gui/window.cc" line="178"/>
         <source>Enable anime &amp;recognition</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="164"/>
+        <location filename="../../src/gui/window.cc" line="180"/>
         <source>Enable auto &amp;sharing</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="166"/>
+        <location filename="../../src/gui/window.cc" line="182"/>
         <source>Enable &amp;auto synchronization</source>
         <translation>Enable &amp;auto synchronisation</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="171"/>
+        <location filename="../../src/gui/window.cc" line="187"/>
         <source>&amp;Settings</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="177"/>
-        <source>&amp;View</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../../src/gui/window.cc" line="184"/>
-        <source>&amp;Now Playing</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../../src/gui/window.cc" line="188"/>
-        <source>&amp;Anime List</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
         <location filename="../../src/gui/window.cc" line="193"/>
+        <source>&amp;View</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/gui/window.cc" line="200"/>
+        <source>&amp;Now Playing</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/gui/window.cc" line="204"/>
+        <source>&amp;Anime List</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/gui/window.cc" line="209"/>
         <source>&amp;History</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="197"/>
+        <location filename="../../src/gui/window.cc" line="213"/>
         <source>&amp;Statistics</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="201"/>
+        <location filename="../../src/gui/window.cc" line="217"/>
         <source>S&amp;earch</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="205"/>
+        <location filename="../../src/gui/window.cc" line="221"/>
         <source>Se&amp;asons</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="209"/>
+        <location filename="../../src/gui/window.cc" line="225"/>
         <source>&amp;Torrents</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="220"/>
+        <location filename="../../src/gui/window.cc" line="236"/>
         <source>Show sidebar</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="222"/>
+        <location filename="../../src/gui/window.cc" line="238"/>
         <source>&amp;Help</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="223"/>
-        <source>&amp;About Minori</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../../src/gui/window.cc" line="227"/>
-        <source>About &amp;Qt</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
         <location filename="../../src/gui/window.cc" line="239"/>
+        <source>&amp;About Minori</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/gui/window.cc" line="243"/>
+        <source>About &amp;Qt</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/gui/window.cc" line="259"/>
         <source>&amp;Synchronize</source>
         <translation>&amp;Synchronise</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="246"/>
+        <location filename="../../src/gui/window.cc" line="266"/>
         <source>Add new folder...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="256"/>
+        <location filename="../../src/gui/window.cc" line="276"/>
         <source>Placeholder</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="264"/>
+        <location filename="../../src/gui/window.cc" line="284"/>
         <source>S&amp;ettings</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="../../src/gui/window.cc" line="298"/>
+        <source>Error synchronizing with service!</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/gui/window.cc" line="299"/>
+        <source>It seems you haven&apos;t yet selected a service to use.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../src/gui/window.cc" line="300"/>
+        <source>Would you like to select one now?</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>NowPlayingPages::Default</name>
@@ -716,6 +731,11 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
+        <location filename="../../src/gui/dialog/settings/application.cc" line="110"/>
+        <source>Set application locale:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
         <location filename="../../src/gui/dialog/settings/application.cc" line="142"/>
         <source>Highlight anime if next episode is available in library folders</source>
         <translation type="unfinished"></translation>
@@ -726,11 +746,6 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/dialog/settings/application.cc" line="110"/>
-        <source>Set application locale (requires restart):</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
         <location filename="../../src/gui/dialog/settings/application.cc" line="161"/>
         <source>Progress</source>
         <translation type="unfinished"></translation>
--- a/rc/locale/es.ts	Mon Nov 06 02:03:55 2023 -0500
+++ b/rc/locale/es.ts	Mon Nov 06 13:41:30 2023 -0500
@@ -190,252 +190,267 @@
 <context>
     <name>MainWindow</name>
     <message>
-        <location filename="../../src/gui/window.cc" line="65"/>
+        <location filename="../../src/gui/window.cc" line="99"/>
         <source>Now Playing</source>
         <translation>Jugando ahora</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="67"/>
+        <location filename="../../src/gui/window.cc" line="101"/>
         <source>Anime List</source>
         <translation>Lista de anime</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="68"/>
+        <location filename="../../src/gui/window.cc" line="102"/>
         <source>History</source>
         <translation>Historia</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="69"/>
+        <location filename="../../src/gui/window.cc" line="103"/>
         <source>Statistics</source>
         <translation>Estadísticas</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="71"/>
+        <location filename="../../src/gui/window.cc" line="105"/>
         <source>Search</source>
         <translation>Buscar</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="72"/>
+        <location filename="../../src/gui/window.cc" line="106"/>
         <source>Seasons</source>
         <translation>Temporadas</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="73"/>
+        <location filename="../../src/gui/window.cc" line="107"/>
         <source>Torrents</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="117"/>
+        <location filename="../../src/gui/window.cc" line="133"/>
         <source>&amp;File</source>
         <translation>&amp;Fichero</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="119"/>
+        <location filename="../../src/gui/window.cc" line="135"/>
         <source>&amp;Library folders</source>
         <translation>Directorios de la biblioteca (&amp;L)</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="120"/>
+        <location filename="../../src/gui/window.cc" line="136"/>
         <source>&amp;Add new folder...</source>
         <translation>&amp;Añadir una nueva directorios...</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="122"/>
+        <location filename="../../src/gui/window.cc" line="138"/>
         <source>&amp;Scan available episodes</source>
         <translation>E&amp;scanear episodios disponibles</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="126"/>
+        <location filename="../../src/gui/window.cc" line="142"/>
         <source>Play &amp;next episode</source>
         <translation>Ver el próximo episodio (&amp;N)</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="128"/>
+        <location filename="../../src/gui/window.cc" line="144"/>
         <source>Play &amp;random episode</source>
         <translation>Ver episodio aleato&amp;rio</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="133"/>
+        <location filename="../../src/gui/window.cc" line="149"/>
         <source>E&amp;xit</source>
         <translation>Salida (&amp;X)</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="135"/>
+        <location filename="../../src/gui/window.cc" line="151"/>
         <source>&amp;Services</source>
         <translation>&amp;Servicios</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="136"/>
+        <location filename="../../src/gui/window.cc" line="152"/>
         <source>Synchronize &amp;list</source>
         <translation>Sincronizar &amp;lista</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="141"/>
+        <location filename="../../src/gui/window.cc" line="157"/>
         <source>&amp;AniList</source>
         <translation>&amp;AniList</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="142"/>
-        <location filename="../../src/gui/window.cc" line="148"/>
-        <location filename="../../src/gui/window.cc" line="152"/>
+        <location filename="../../src/gui/window.cc" line="158"/>
+        <location filename="../../src/gui/window.cc" line="164"/>
+        <location filename="../../src/gui/window.cc" line="168"/>
         <source>Go to my &amp;profile</source>
         <translation>Ir a mi &amp;perfil</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="143"/>
+        <location filename="../../src/gui/window.cc" line="159"/>
         <source>Go to my &amp;stats</source>
         <translation>Ir a mis e&amp;stadísticas</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="145"/>
+        <location filename="../../src/gui/window.cc" line="161"/>
         <source>&amp;Kitsu</source>
         <translation>&amp;Kitsu</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="146"/>
+        <location filename="../../src/gui/window.cc" line="162"/>
         <source>Go to my &amp;feed</source>
         <translation>Ir a mi &amp;feed</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="147"/>
+        <location filename="../../src/gui/window.cc" line="163"/>
         <source>Go to my &amp;library</source>
         <translation>Ir a mi biblioteca (&amp;L)</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="150"/>
+        <location filename="../../src/gui/window.cc" line="166"/>
         <source>&amp;MyAnimeList</source>
         <translation>&amp;MyAnimeList</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="151"/>
+        <location filename="../../src/gui/window.cc" line="167"/>
         <source>Go to my p&amp;anel</source>
         <translation>Ir a mi p&amp;anel</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="153"/>
+        <location filename="../../src/gui/window.cc" line="169"/>
         <source>Go to my &amp;history</source>
         <translation>Ir a mi &amp;historia</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="155"/>
+        <location filename="../../src/gui/window.cc" line="171"/>
         <source>&amp;Tools</source>
         <translation>Ins&amp;trumentos</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="156"/>
+        <location filename="../../src/gui/window.cc" line="172"/>
         <source>&amp;Export anime list</source>
         <translation>&amp;Exportar lista de anime</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="157"/>
+        <location filename="../../src/gui/window.cc" line="173"/>
         <source>Export as &amp;Markdown...</source>
         <translation>Exportar como &amp;Markdown...</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="158"/>
+        <location filename="../../src/gui/window.cc" line="174"/>
         <source>Export as MyAnimeList &amp;XML...</source>
         <translation>Exportar como &amp;XML de MyAnimeList</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="162"/>
+        <location filename="../../src/gui/window.cc" line="178"/>
         <source>Enable anime &amp;recognition</source>
         <translation>Activar el &amp;reconocimiento de anime</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="164"/>
+        <location filename="../../src/gui/window.cc" line="180"/>
         <source>Enable auto &amp;sharing</source>
         <translation>Activar el uso compartido automático (&amp;S)</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="166"/>
+        <location filename="../../src/gui/window.cc" line="182"/>
         <source>Enable &amp;auto synchronization</source>
         <translation>Activar la sincronización &amp;automática</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="171"/>
+        <location filename="../../src/gui/window.cc" line="187"/>
         <source>&amp;Settings</source>
         <translation>Configuración (&amp;S)</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="177"/>
+        <location filename="../../src/gui/window.cc" line="193"/>
         <source>&amp;View</source>
         <translation>&amp;Ver</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="184"/>
+        <location filename="../../src/gui/window.cc" line="200"/>
         <source>&amp;Now Playing</source>
         <translation>Jugando ahora (&amp;N)</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="188"/>
+        <location filename="../../src/gui/window.cc" line="204"/>
         <source>&amp;Anime List</source>
         <translation>Lista de &amp;anime</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="193"/>
+        <location filename="../../src/gui/window.cc" line="209"/>
         <source>&amp;History</source>
         <translation>&amp;Historia</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="197"/>
+        <location filename="../../src/gui/window.cc" line="213"/>
         <source>&amp;Statistics</source>
         <translation>E&amp;stadísticas</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="201"/>
+        <location filename="../../src/gui/window.cc" line="217"/>
         <source>S&amp;earch</source>
         <translation>Buscar (&amp;S)</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="205"/>
+        <location filename="../../src/gui/window.cc" line="221"/>
         <source>Se&amp;asons</source>
         <translation>Tempor&amp;adas</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="209"/>
+        <location filename="../../src/gui/window.cc" line="225"/>
         <source>&amp;Torrents</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="220"/>
+        <location filename="../../src/gui/window.cc" line="236"/>
         <source>Show sidebar</source>
         <translation>Mostrar barra lateral</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="222"/>
+        <location filename="../../src/gui/window.cc" line="238"/>
         <source>&amp;Help</source>
         <translation>Ayuda (&amp;H)</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="223"/>
+        <location filename="../../src/gui/window.cc" line="239"/>
         <source>&amp;About Minori</source>
         <translation>&amp;Acerca de Minori</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="227"/>
+        <location filename="../../src/gui/window.cc" line="243"/>
         <source>About &amp;Qt</source>
         <translation>Acerca de &amp;Qt</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="239"/>
+        <location filename="../../src/gui/window.cc" line="259"/>
         <source>&amp;Synchronize</source>
         <translation>&amp;Sincronice</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="246"/>
+        <location filename="../../src/gui/window.cc" line="266"/>
         <source>Add new folder...</source>
         <translation>Añadir una nueva carpeta...</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="256"/>
+        <location filename="../../src/gui/window.cc" line="276"/>
         <source>Placeholder</source>
         <translation>Marcador de posición</translation>
     </message>
     <message>
-        <location filename="../../src/gui/window.cc" line="264"/>
+        <location filename="../../src/gui/window.cc" line="284"/>
         <source>S&amp;ettings</source>
         <translation>Configuración (&amp;S)</translation>
     </message>
+    <message>
+        <location filename="../../src/gui/window.cc" line="298"/>
+        <source>Error synchronizing with service!</source>
+        <translation>Error al sincronizar con el servicio!</translation>
+    </message>
+    <message>
+        <location filename="../../src/gui/window.cc" line="299"/>
+        <source>It seems you haven&apos;t yet selected a service to use.</source>
+        <translation>Parece que aún no has seleccionado un servicio para usar.</translation>
+    </message>
+    <message>
+        <location filename="../../src/gui/window.cc" line="300"/>
+        <source>Would you like to select one now?</source>
+        <translation>¿Quieres seleccionar uno ahora?</translation>
+    </message>
 </context>
 <context>
     <name>NowPlayingPages::Default</name>
@@ -722,8 +737,8 @@
     </message>
     <message>
         <location filename="../../src/gui/dialog/settings/application.cc" line="110"/>
-        <source>Set application locale (requires restart):</source>
-        <translation>Establecer la configuración regional de la aplicación (requiere reinicio):</translation>
+        <source>Set application locale:</source>
+        <translation>Establecer la configuración regional de la aplicación:</translation>
     </message>
     <message>
         <location filename="../../src/gui/dialog/settings/application.cc" line="132"/>
--- a/src/gui/dialog/settings/application.cc	Mon Nov 06 02:03:55 2023 -0500
+++ b/src/gui/dialog/settings/application.cc	Mon Nov 06 13:41:30 2023 -0500
@@ -107,7 +107,7 @@
 		{
 			/* Application locale */
 			{
-				QLabel* locale_combo_box_label = new QLabel(tr("Set application locale (requires restart):"), appearance_group_box);
+				QLabel* locale_combo_box_label = new QLabel(tr("Set application locale:"), appearance_group_box);
 				appearance_layout->addWidget(locale_combo_box_label);
 			}
 
--- a/src/gui/pages/anime_list.cc	Mon Nov 06 02:03:55 2023 -0500
+++ b/src/gui/pages/anime_list.cc	Mon Nov 06 13:41:30 2023 -0500
@@ -434,6 +434,8 @@
 	SetColumnDefaults();
 	setFocusPolicy(Qt::TabFocus);
 	setFocusProxy(tab_bar);
+
+	Refresh();
 }
 
 void AnimeListPage::RefreshList() {
--- a/src/gui/widgets/anime_info.cc	Mon Nov 06 02:03:55 2023 -0500
+++ b/src/gui/widgets/anime_info.cc	Mon Nov 06 13:41:30 2023 -0500
@@ -31,11 +31,15 @@
 	/* details */
 	QString details_data;
 	QTextStream details_data_s(&details_data);
-	details_data_s << Translate::ToString(anime.GetFormat()).c_str() << "\n"
+	/* we have to convert ALL of these strings to
+	   QString because QTextStream sucks and assumes
+	   Latin1 (on Windows?) */
+	details_data_s << Strings::ToQString(Translate::ToString(anime.GetFormat())) << "\n"
 	               << anime.GetEpisodes() << "\n"
-	               << Translate::ToString(anime.GetUserStatus()).c_str() << "\n"
-	               << Translate::ToString(anime.GetSeason()).c_str() << " " << anime.GetAirDate().GetYear() << "\n"
-	               << Strings::Implode(anime.GetGenres(), ", ").c_str() << "\n"
+	               << Strings::ToQString(Translate::ToString(anime.GetUserStatus())) << "\n"
+	               << Strings::ToQString(Translate::ToString(anime.GetSeason())) << " "
+	                   << anime.GetAirDate().GetYear() << "\n"
+	               << Strings::ToQString(Strings::Implode(anime.GetGenres(), ", ")) << "\n"
 	               << anime.GetAudienceScore() << "%";
 	_details->GetParagraph()->SetText(details_data);
 
--- a/src/gui/widgets/sidebar.cc	Mon Nov 06 02:03:55 2023 -0500
+++ b/src/gui/widgets/sidebar.cc	Mon Nov 06 13:41:30 2023 -0500
@@ -24,6 +24,10 @@
 	setCurrentRow(AddSeparatorsToIndex(index));
 }
 
+int SideBar::GetCurrentItem() {
+	return RemoveSeparatorsFromIndex(currentRow());
+}
+
 void SideBar::SetBackgroundColor(QColor color) {
 	viewport()->setAutoFillBackground(color != Qt::transparent);
 	QPalette pal(palette());
--- a/src/gui/window.cc	Mon Nov 06 02:03:55 2023 -0500
+++ b/src/gui/window.cc	Mon Nov 06 13:41:30 2023 -0500
@@ -31,6 +31,7 @@
 #include <QTimer>
 #include <QToolBar>
 #include <QToolButton>
+#include <iostream>
 #ifdef MACOSX
 #	include "sys/osx/dark_theme.h"
 #elif defined(WIN32)
@@ -49,46 +50,14 @@
 	TORRENTS
 };
 
-static void AsyncSynchronize(QStackedWidget* stack) {
-	QThreadPool::globalInstance()->start([stack] {
-		Services::Synchronize();
-		reinterpret_cast<AnimeListPage*>(stack->widget(static_cast<int>(Pages::ANIME_LIST)))->Refresh();
-	});
-}
-
 MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) {
 	setWindowIcon(QIcon(":/favicon.png"));
 
-	main_widget = new QWidget(parent);
-
-	sidebar = new SideBar(main_widget);
-	sidebar->AddItem(tr("Now Playing"), SideBar::CreateIcon(":/icons/16x16/film.png"));
-	sidebar->AddSeparator();
-	sidebar->AddItem(tr("Anime List"), SideBar::CreateIcon(":/icons/16x16/document-list.png"));
-	sidebar->AddItem(tr("History"), SideBar::CreateIcon(":/icons/16x16/clock-history-frame.png"));
-	sidebar->AddItem(tr("Statistics"), SideBar::CreateIcon(":/icons/16x16/chart.png"));
-	sidebar->AddSeparator();
-	sidebar->AddItem(tr("Search"), SideBar::CreateIcon(":/icons/16x16/magnifier.png"));
-	sidebar->AddItem(tr("Seasons"), SideBar::CreateIcon(":/icons/16x16/calendar.png"));
-	sidebar->AddItem(tr("Torrents"), SideBar::CreateIcon(":/icons/16x16/feed.png"));
-	sidebar->setFixedWidth(128);
-	sidebar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
+	main_widget = new QWidget(this);
+	/*QHBoxLayout* layout = */new QHBoxLayout(main_widget);
 
-	stack = new QStackedWidget(main_widget);
-	stack->addWidget(new NowPlayingPage(main_widget));
-	stack->addWidget(new AnimeListPage(main_widget));
-	stack->addWidget(new HistoryPage(main_widget));
-	stack->addWidget(new StatisticsPage(main_widget));
-	stack->addWidget(new SearchPage(main_widget));
-	stack->addWidget(new SeasonsPage(main_widget));
-	stack->addWidget(new TorrentsPage(main_widget));
+	AddMainWidgets();
 
-	connect(sidebar, &SideBar::CurrentItemChanged, stack, &QStackedWidget::setCurrentIndex);
-	sidebar->SetCurrentItem(static_cast<int>(Pages::ANIME_LIST));
-
-	QHBoxLayout* layout = new QHBoxLayout(main_widget);
-	layout->addWidget(sidebar);
-	layout->addWidget(stack);
 	setCentralWidget(main_widget);
 
 	CreateBars();
@@ -110,6 +79,53 @@
 	timer->start(5000);
 }
 
+void MainWindow::AddMainWidgets() {
+	int page = static_cast<int>(Pages::ANIME_LIST);
+	if (sidebar) {
+		main_widget->layout()->removeWidget(sidebar);
+		delete sidebar;
+	}
+
+	if (stack) {
+		page = stack->currentIndex();
+		main_widget->layout()->removeWidget(stack);
+		delete stack;
+	}
+
+	sidebar = new SideBar(main_widget);
+	sidebar->setFixedWidth(128);
+	sidebar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
+
+	sidebar->AddItem(tr("Now Playing"), SideBar::CreateIcon(":/icons/16x16/film.png"));
+	sidebar->AddSeparator();
+	sidebar->AddItem(tr("Anime List"), SideBar::CreateIcon(":/icons/16x16/document-list.png"));
+	sidebar->AddItem(tr("History"), SideBar::CreateIcon(":/icons/16x16/clock-history-frame.png"));
+	sidebar->AddItem(tr("Statistics"), SideBar::CreateIcon(":/icons/16x16/chart.png"));
+	sidebar->AddSeparator();
+	sidebar->AddItem(tr("Search"), SideBar::CreateIcon(":/icons/16x16/magnifier.png"));
+	sidebar->AddItem(tr("Seasons"), SideBar::CreateIcon(":/icons/16x16/calendar.png"));
+	sidebar->AddItem(tr("Torrents"), SideBar::CreateIcon(":/icons/16x16/feed.png"));
+
+	stack = new QStackedWidget(main_widget);
+	stack->addWidget(new NowPlayingPage(main_widget));
+	stack->addWidget(new AnimeListPage(main_widget));
+	stack->addWidget(new HistoryPage(main_widget));
+	stack->addWidget(new StatisticsPage(main_widget));
+	stack->addWidget(new SearchPage(main_widget));
+	stack->addWidget(new SeasonsPage(main_widget));
+	stack->addWidget(new TorrentsPage(main_widget));
+
+	connect(sidebar, &SideBar::CurrentItemChanged, this, [](int index){
+		std::cout << index << std::endl;
+	});
+
+	connect(sidebar, &SideBar::CurrentItemChanged, stack, &QStackedWidget::setCurrentIndex);
+	sidebar->SetCurrentItem(page);
+
+	main_widget->layout()->addWidget(sidebar);
+	main_widget->layout()->addWidget(stack);
+}
+
 void MainWindow::CreateBars() {
 	/* Menu Bar */
 	QAction* action;
@@ -227,13 +243,17 @@
 	action = menu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
 	action->setMenuRole(QAction::AboutQtRole);
 
+	/* QMainWindow will delete the old one for us,
+	   according to the docs */
 	setMenuBar(menubar);
 
 	/* Toolbar */
 	/* remove old toolbar(s) */
 	QList<QToolBar*> toolbars = findChildren<QToolBar*>();
-	for (auto& t : toolbars)
+	for (auto& t : toolbars) {
 		removeToolBar(t);
+		delete t;
+	}
 
 	QToolBar* toolbar = new QToolBar(this);
 	toolbar->addAction(QIcon(":/icons/24x24/arrow-circle-double-135.png"), tr("&Synchronize"),
@@ -272,9 +292,56 @@
 	this->setCentralWidget(page);
 }
 
+void MainWindow::AsyncSynchronize(QStackedWidget* stack) {
+	if (session.config.service == Anime::Services::NONE) {
+		QMessageBox msg;
+		msg.setWindowTitle(tr("Error synchronizing with service!"));
+		msg.setText(tr("It seems you haven't yet selected a service to use."));
+		msg.setInformativeText(tr("Would you like to select one now?"));
+		msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+		msg.setDefaultButton(QMessageBox::Yes);
+		int ret = msg.exec();
+		if (ret == QMessageBox::Yes) {
+			SettingsDialog dialog;
+			dialog.exec();
+		}
+	}
+	QThreadPool::globalInstance()->start([stack] {
+		Services::Synchronize();
+		reinterpret_cast<AnimeListPage*>(stack->widget(static_cast<int>(Pages::ANIME_LIST)))->Refresh();
+	});
+}
+
+void MainWindow::RetranslateUI() {
+	/* Temporarily disable UI updates so we don't flash the screen */
+	setUpdatesEnabled(false);
+	AddMainWidgets();
+	CreateBars();
+	setUpdatesEnabled(true);
+}
+
+void MainWindow::changeEvent(QEvent* event) {
+	if (event) { /* is this really necessary */
+		switch (event->type()) {
+			// this event is send if a translator is loaded
+			case QEvent::LanguageChange:
+				RetranslateUI();
+				break;
+
+			default:
+				break;
+		}
+	}
+	QMainWindow::changeEvent(event);
+}
+
 void MainWindow::showEvent(QShowEvent* event) {
 	QMainWindow::showEvent(event);
 #ifdef WIN32
+	/* Technically this *should* be
+	   session.config.theme.IsInDarkTheme() && win32::IsInDarkTheme()
+	   but I prefer the title bar being black even when light mode
+	   is enabled :/ */
 	win32::SetTitleBarsToBlack(session.config.theme.IsInDarkTheme());
 #endif
 }
--- a/src/services/services.cc	Mon Nov 06 02:03:55 2023 -0500
+++ b/src/services/services.cc	Mon Nov 06 13:41:30 2023 -0500
@@ -9,19 +9,7 @@
 void Synchronize() {
 	switch (session.config.service) {
 		case Anime::Services::ANILIST: AniList::GetAnimeList(); break;
-		default: {
-			QMessageBox msg;
-			msg.setInformativeText("It seems you haven't yet selected a service to use.");
-			msg.setText("Would you like to select one now?");
-			msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
-			msg.setDefaultButton(QMessageBox::Yes);
-			int ret = msg.exec();
-			if (ret == QMessageBox::Yes) {
-				SettingsDialog dialog;
-				dialog.exec();
-			}
-			break;
-		}
+		default: break;
 	}
 }