From 9d50b863c8630362d71ea29ae9017bd3694bb713 Mon Sep 17 00:00:00 2001 From: zvon Date: Thu, 12 Mar 2020 20:52:23 +0100 Subject: [PATCH] Internationalization: first steps --- cs.po | 360 +++++++++++++++++++++++++++++++++++++++++++++ databasewindow.cpp | 36 +++-- en_US.po | 360 +++++++++++++++++++++++++++++++++++++++++++++ functions.cpp | 196 ++++++++++++------------ functions.hpp | 11 +- gtkfunctions.cpp | 7 +- gui.cpp | 14 ++ main.cpp | 45 +++--- mainwindow.cpp | 99 +++++++------ progress.cpp | 6 +- progresswindow.cpp | 3 +- resources_linux.h | 132 +++++++++++++++++ searchwindow.cpp | 10 +- seasonwindow.cpp | 13 +- tv_rename.cpp | 32 ++-- 15 files changed, 1116 insertions(+), 208 deletions(-) create mode 100644 cs.po create mode 100644 en_US.po create mode 100644 resources_linux.h diff --git a/cs.po b/cs.po new file mode 100644 index 0000000..ffb0bd5 --- /dev/null +++ b/cs.po @@ -0,0 +1,360 @@ +# Czech translations for tv_rename program. +# Copyright (C) 2020 Zv0n +# This file is distributed under the same license as the tv_rename program +# , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: tv_rename\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-03-03 21:29+0200\n" +"PO-Revision-Date: 2020-03-03 21:29+0200\n" +"Last-Translator: \n" +"Language-Team: Czech\n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +msgid "Invalid language choice" +msgstr "Neplatná volba jazyka" + +msgid "Specified file does not conform to filename pattern, cannot rename." +msgstr "Zadaný soubor nesplňuje potřebný vzor jména souboru, nelze přejmenovat." + +msgid "You can't remove and add at the same time" +msgstr "Nelze přidat a odebrat z databáze zároveň" + +msgid "Added to database" +msgstr "Přidáno do databáze" + +msgid "Refreshed database" +msgstr "Databáze obnovena" + +msgid "Updated database" +msgstr "Databáze aktualizována" + +msgid "Database cleaned" +msgstr "Databáze vyčištěna" + +msgid "This directory doesn't exist, please insert a correct path:" +msgstr "Tento adresář neexistuje, zadejte prosím správnou cestu:" + +msgid "Is this the right directory?" +msgstr "Je toto správný adresář?" + +msgid "Insert correct path:" +msgstr "Zadejte správnou cestu:" + +msgid "Is this the right show name?" +msgstr "Je toto správný název seriálu?" + +msgid "Insert the correct show name:" +msgstr "Zadejte správný název seriálu:" + +msgid "Database" +msgstr "Databáze" + +msgid "Progress" +msgstr "Průběh" + +msgid "Select show" +msgstr "Zvolte seriál" + +msgid "Choose seasons" +msgstr "Zvolte série" + +msgid "Save" +msgstr "Uložit" + +msgid "Delete" +msgstr "Smazat" + +msgid "Quit" +msgstr "Ukončit" + +msgid "Show" +msgstr "Seriál" + +msgid "Path" +msgstr "Cesta" + +msgid "Language" +msgstr "Jazyk" + +msgid "DVD" +msgstr "DVD" + +msgid "Select a directory" +msgstr "Zvolte adresář" + +msgid "Cancel" +msgstr "Zrušit" + +msgid "Select" +msgstr "Zvolit" + +msgid "Search" +msgstr "Vyhledat" + +msgid "Invalid path" +msgstr "Neplatná cesta" + +msgid "Directory '%s' doesn't exist" +msgstr "Adresář '%s' neexistuje" + +msgid "Usage:" +msgstr "Použití:" + +msgid "options" +msgstr "volby" + +msgid "path" +msgstr "cesta" + +msgid "show this help message and exit" +msgstr "ukázat tuto nápovědu a skončit" + +msgid " path can be either a file or a directory, if it's a directory\n" + " all files in it and its subdirectories will be renamed" +msgstr " cesta může být buď soubor nebo adresář, pokud je to adresář\n" + " veškeré soubory v něm a v jeho podadresářích budou přejmenovány" + +msgid "OPTIONS" +msgstr "VOLBY" + +msgid "TV show from which you want the episode names" +msgstr "Seriál, jehož názvy epizod chcete" + +msgid "Season number/s (if multiple seasons,\n" + " must be seperated by one space) or 'all'\n" + " for all seasons in selected directory" +msgstr "Číslo/čísla sérií (pokud je sérií více,\n" + " musí být odděleny jednou mezero) nebo 'all'\n" + " pro přejmenování všech sérií ve zvoleném adresáři" + +msgid "use dvd ordering instead of aired ordering" +msgstr "použít řazení podle DVD" + +msgid "Pattern to which change the file name." +msgstr "Vzor podle kterého přejmenovat soubor." + +msgid "This is the correct path, stop asking me!" +msgstr "Nacházím se ve správném adresáři" + +msgid "Don't ask whether the names are correct" +msgstr "Nepotvrzovat správnost nových názvů" + +msgid "Don't replace characters characters that are\n" + " illegal in Windows" +msgstr "Nenahrazovat znaky, které nejsou povoleny\n" + " na systému Windows" + +msgid "Select which language the episode names shoud be in" +msgstr "Zvolte jazyk, ve kterém budou názvy epizod" + +msgid "Print available languages" +msgstr "Vypsat možné jazyky" + +msgid "DATABASE OPTIONS" +msgstr "VOLBY PRO DATABÁZI" + +msgid "Add path to the database" +msgstr "Přidat cestu do databáze" + +msgid "Refresh episode names for all paths in the database" +msgstr "Obnovit názvy epizod v databázi" + +msgid "Check all paths in the database,\n" + " if they contain new files, rename them" +msgstr "Zkontrolovat všechny adresáře v databázi,\n" + " pokud v některém jsou nové soubory, přejmenovat je" + +msgid "Change name pattern used for files\n" + " managed by database" +msgstr "Změnit vzor používaný pro přejmenování\n" + " souborů v databázi" + +msgid "Remove deleted files from the database" +msgstr "Odstranit smazané soubory z databáze" + +msgid "Remove path from the database" +msgstr "Odstranit cestu z databáze" + +msgid "Possible pattern sequences are:" +msgstr "Možné součásti vzoru:" + +msgid "original filename (without filetype extension)" +msgstr "původní název (vyjma souborového typu)" + +msgid "show name from thetvdb" +msgstr "název seriálu z thetvdb" + +msgid "episode name from thetvdb" +msgstr "název epizody z thetvdb" + +msgid "season number" +msgstr "číslo série" + +msgid "episode number" +msgstr "číslo epizody" + +msgid "it's possible to specify leading 0 like this:" +msgstr "je možné nastavit počáteční nuly:" + +msgid "(number means how many zeros)" +msgstr "(číslo určuje délku čísla)" + +msgid "Default pattern is" +msgstr "Výchozí vzor je" + +msgid "You might want to change this to" +msgstr "Možná jej budete chtít změnit na" + +msgid "User with uid %u doesn't exist!" +msgstr "Uživatel s uid %u neexistuje!" + +msgid "Couldn't create database, make sure you have write permission for" +msgstr "Databáze nemohla být vytvořena, ujistěte se, že máte právo pro zápis pro" + +msgid "Insert name pattern for database:" +msgstr "Zadejte vzor, který bude databáze používat:" + +msgid "Can't open database, make sure it exists" +msgstr "Databázi nelze otevřít, ujistěte se, že existuje" + +msgid "Renaming" +msgstr "Přejmenovávám" + +msgid "Adding to database" +msgstr "Přidávám do databáze" + +msgid "Refreshing database" +msgstr "Obnovuji v databázi" + +msgid "Refreshing" +msgstr "Obnovuji" + +msgid "Updating %s in database" +msgstr "Aktualizuji %s v databázi" + +msgid "Updating database" +msgstr "Aktualizuji databázi" + +msgid "Updating" +msgstr "Aktualizuji" + +msgid "Show field is empty" +msgstr "Pole pro seriál je prázdné" + +msgid "No results found for given show name" +msgstr "Pro zadaný seriál nebyly nalezeny žádné výsledky" + +msgid "Select seasons:" +msgstr "Zvolte série:" + +msgid "Select All" +msgstr "Zvolit Vše" + +msgid "Select None" +msgstr "Nezvolit Nic" + +msgid "Which TV Show is the right one?" +msgstr "Který seriál je správný?" + +msgid "Couldn't find episode names for season %s of show %s" +msgstr "Nepodařilo se najít názvy epizod pro sérii %s seriálu %s" + +msgid "Couldn't find episodes with season" +msgstr "Nepodařilo se najít epizody se sérií" + +msgid "Does this seem ok?" +msgstr "Vypadá toto správně?" + +msgid "y" +msgstr "a" + +msgid "Y" +msgstr "A" + +msgid "n" +msgstr "n" + +msgid "N" +msgstr "N" + +msgid "Yes" +msgstr "Ano" + +msgid "No" +msgstr "Ne" + +msgid "Pattern escape sequences" +msgstr "Únikové sekvence pro vzor" + +msgid "Directory field is empty" +msgstr "Pole pro adresář je prázdné" + +msgid "Rename confirmation" +msgstr "Potvrzení přejmenování" + +msgid "File" +msgstr "Soubor" + +msgid "Exit" +msgstr "Ukončit" + +msgid "Update database" +msgstr "Aktualizovat databázi" + +msgid "Refresh database" +msgstr "Obnovit databázi" + +msgid "Clean database" +msgstr "Vyčistit databázi" + +msgid "Manage database" +msgstr "Spravovat databázi" + +msgid "Change pattern" +msgstr "Změnit vzor" + +msgid "Process" +msgstr "Zpracovat" + +msgid "Choose directory" +msgstr "Zvolit adresář" + +msgid "Pattern help" +msgstr "Nápověda pro vzor" + +msgid "Rename" +msgstr "Přejmenovat" + +msgid "Add to database" +msgstr "Přidat do databáze" + +msgid "Replace windows-illegal characters" +msgstr "Nahradit znaky neplatné ve Windows" + +msgid "Don't ask for rename confirmation" +msgstr "Nevyžadovat potvrzení přejmenování" + +msgid "Use DVD ordering" +msgstr "Použít řazení podle DVD" + +msgid "Directory" +msgstr "Adresář" + +msgid "Pattern" +msgstr "Vzor" + +msgid "Possible shows" +msgstr "Možné seriály" + +msgid "OK" +msgstr "OK" + +msgid "or" +msgstr "nebo" diff --git a/databasewindow.cpp b/databasewindow.cpp index b268cfd..cee6d8d 100644 --- a/databasewindow.cpp +++ b/databasewindow.cpp @@ -12,6 +12,7 @@ #include "functions.hpp" #include "gtkfunctions.hpp" #include "progresswindow.hpp" +#include "resources_linux.h" #include "tv_rename.hpp" DatabaseWindow::~DatabaseWindow() { @@ -23,7 +24,7 @@ DatabaseWindow::DatabaseWindow( bool _linux, std::map< std::string, std::string > &_language_map, Glib::RefPtr< Gtk::Application > _app ) : linux( _linux ), language_map( _language_map ), app( _app ) { - set_title( "Database" ); + set_title( _( DATABASE ) ); property_modal().set_value( true ); set_default_size( 550, 350 ); @@ -60,9 +61,9 @@ DatabaseWindow::DatabaseWindow( button_save->set_margin_right( 5 ); // set button texts - button_save->set_label( "Save" ); - button_remove->set_label( "Delete" ); - button_quit->set_label( "Quit" ); + button_save->set_label( _( SAVE ) ); + button_remove->set_label( _( DELETE ) ); + button_quit->set_label( _( QUIT ) ); // set dimensions button_save->set_size_request( 80, 30 ); @@ -86,17 +87,20 @@ DatabaseWindow::DatabaseWindow( row[m_columns_database.m_col_dvd] = x["DVD"] == "1"; } - m_tree_database->append_column( "Show", m_columns_database.m_col_show ); - m_tree_database->append_column( "Path", m_columns_database.m_col_path ); - m_tree_database->append_column( "Language", m_combo_language ); - m_tree_database->append_column_editable( "DVD", + m_tree_database->append_column( _( SHOW ), m_columns_database.m_col_show ); + m_tree_database->append_column( _( PATH ), m_columns_database.m_col_path ); + m_tree_database->append_column( _( LANGUAGE ), m_combo_language ); + m_tree_database->append_column_editable( _( DVD ), m_columns_database.m_col_dvd ); m_tree_database->signal_button_press_event().connect( sigc::mem_fun( *this, &DatabaseWindow::treeViewClick ) ); + // create language combobox for treeview auto model = Gtk::ListStore::create( m_columns_language ); m_combo_language.property_model().set_value( model ); m_combo_language.property_editable().set_value( true ); + // the combobox should show value with index 1 in its model + // (meaning the full language name) m_combo_language.property_text_column().set_value( 1 ); m_combo_language.property_has_entry().set_value( false ); @@ -128,6 +132,7 @@ DatabaseWindow::DatabaseWindow( void DatabaseWindow::languageChange( const Glib::ustring &str, const Gtk::TreeIter &it ) { + // set new language and language code in database auto lang_row = *it; auto database_row = *( m_model->get_iter( str ) ); database_row[m_columns_database.m_col_lang] = @@ -143,7 +148,7 @@ bool DatabaseWindow::treeViewClick( GdkEventButton *event ) { int x_column, y_column; m_tree_database->get_path_at_pos( event->x, event->y, path, column, x_column, y_column ); - if ( column->get_title() == "Show" ) { + if ( column->get_title() == _( SHOW ) ) { // set default values id_search = "_"; show_search = "_"; @@ -155,12 +160,12 @@ bool DatabaseWindow::treeViewClick( GdkEventButton *event ) { app->add_window( *sw ); sw->show(); - } else if ( column->get_title() == "Path" ) { - Gtk::FileChooserDialog dialog( "Select a directory", + } else if ( column->get_title() == _( PATH ) ) { + Gtk::FileChooserDialog dialog( _( SELECT_DIR ), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); dialog.set_transient_for( *this ); - dialog.add_button( "_Cancel", Gtk::RESPONSE_CANCEL ); - dialog.add_button( "Select", Gtk::RESPONSE_OK ); + dialog.add_button( "_" + _( CANCEL ), Gtk::RESPONSE_CANCEL ); + dialog.add_button( _( SELECT ), Gtk::RESPONSE_OK ); auto result = dialog.run(); if ( result == Gtk::RESPONSE_OK ) { auto selection = m_tree_database->get_selection(); @@ -176,6 +181,7 @@ void DatabaseWindow::finishedSearch() { sw.reset(); if ( id_search == "_" || show_search == "_" || lang_search == "_" ) return; + // set new show name/id/language auto selection = m_tree_database->get_selection(); auto row = *( selection->get_selected() ); ( *row )[m_columns_database.m_col_show] = show_search; @@ -238,8 +244,8 @@ void DatabaseWindow::changed( const Gtk::TreeModel::Path & /*UNUSED*/, } void DatabaseWindow::errorPath( const std::string &path ) { - Gtk::MessageDialog d( *this, "Invalid path", false, Gtk::MESSAGE_ERROR ); - d.set_secondary_text( "Directory '" + path + "' doesn't exist" ); + Gtk::MessageDialog d( *this, _( INVALID_PATH ), false, Gtk::MESSAGE_ERROR ); + d.set_secondary_text( _( DIR_NOT_EXIST, path.c_str() ) ); d.run(); } diff --git a/en_US.po b/en_US.po new file mode 100644 index 0000000..b70b457 --- /dev/null +++ b/en_US.po @@ -0,0 +1,360 @@ +# English translations for tv_rename program. +# Copyright (C) 2020 Zv0n +# This file is distributed under the same license as the tv_rename program +# , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: tv_rename\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-03-03 21:29+0200\n" +"PO-Revision-Date: 2020-03-03 21:29+0200\n" +"Last-Translator: \n" +"Language-Team: English\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Invalid language choice" +msgstr "Invalid language choice" + +msgid "Specified file does not conform to filename pattern, cannot rename." +msgstr "Specified file does not conform to filename pattern, cannot rename." + +msgid "You can't remove and add at the same time" +msgstr "You can't remove and add at the same time" + +msgid "Added to database" +msgstr "Added to database" + +msgid "Refreshed database" +msgstr "Refreshed database" + +msgid "Updated database" +msgstr "Updated database" + +msgid "Database cleaned" +msgstr "Database cleaned" + +msgid "This directory doesn't exist, please insert a correct path:" +msgstr "This directory doesn't exist, please insert a correct path:" + +msgid "Is this the right directory?" +msgstr "Is this the right directory?" + +msgid "Insert correct path:" +msgstr "Insert correct path:" + +msgid "Is this the right show name?" +msgstr "Is this the right show name?" + +msgid "Insert the correct show name:" +msgstr "Insert the correct show name:" + +msgid "Database" +msgstr "Database" + +msgid "Progress" +msgstr "Progress" + +msgid "Select show" +msgstr "Select show" + +msgid "Choose seasons" +msgstr "Choose seasons" + +msgid "Save" +msgstr "Save" + +msgid "Delete" +msgstr "Delete" + +msgid "Quit" +msgstr "Quit" + +msgid "Show" +msgstr "Show" + +msgid "Path" +msgstr "Path" + +msgid "Language" +msgstr "Language" + +msgid "DVD" +msgstr "DVD" + +msgid "Select a directory" +msgstr "Select a directory" + +msgid "Cancel" +msgstr "Cancel" + +msgid "Select" +msgstr "Select" + +msgid "Search" +msgstr "Search" + +msgid "Invalid path" +msgstr "Invalid path" + +msgid "Directory '%s' doesn't exist" +msgstr "Directory '%s' doesn't exist" + +msgid "Usage:" +msgstr "Usage:" + +msgid "options" +msgstr "options" + +msgid "path" +msgstr "path" + +msgid "show this help message and exit" +msgstr "show this help message and exit" + +msgid " path can be either a file or a directory, if it's a directory\n" + " all files in it and its subdirectories will be renamed" +msgstr " path can be either a file or a directory, if it's a directory\n" + " all files in it and its subdirectories will be renamed" + +msgid "OPTIONS" +msgstr "OPTIONS" + +msgid "TV show from which you want the episode names" +msgstr "TV show from which you want the episode names" + +msgid "Season number/s (if multiple seasons,\n" + " must be seperated by one space) or 'all'\n" + " for all seasons in selected directory" +msgstr "Season number/s (if multiple seasons,\n" + " must be seperated by one space) or 'all'\n" + " for all seasons in selected directory" + +msgid "use dvd ordering instead of aired ordering" +msgstr "use dvd ordering instead of aired ordering" + +msgid "Pattern to which change the file name." +msgstr "Pattern to which change the file name." + +msgid "This is the correct path, stop asking me!" +msgstr "This is the correct path, stop asking me!" + +msgid "Don't ask whether the names are correct" +msgstr "Don't ask whether the names are correct" + +msgid "Don't replace characters characters that are\n" + " illegal in Windows" +msgstr "Don't replace characters characters that are\n" + " illegal in Windows" + +msgid "Select which language the episode names shoud be in" +msgstr "Select which language the episode names shoud be in" + +msgid "Print available languages" +msgstr "Print available languages" + +msgid "DATABASE OPTIONS" +msgstr "DATABASE OPTIONS" + +msgid "Add path to the database" +msgstr "Add path to the database" + +msgid "Refresh episode names for all paths in the database" +msgstr "Refresh episode names for all paths in the database" + +msgid "Check all paths in the database,\n" + " if they contain new files, rename them" +msgstr "Check all paths in the database,\n" + " if they contain new files, rename them" + +msgid "Change name pattern used for files\n" + " managed by database" +msgstr "Change name pattern used for files\n" + " managed by database" + +msgid "Remove deleted files from the database" +msgstr "Remove deleted files from the database" + +msgid "Remove path from the database" +msgstr "Remove path from the database" + +msgid "Possible pattern sequences are:" +msgstr "Possible pattern sequences are:" + +msgid "original filename (without filetype extension)" +msgstr "original filename (without filetype extension)" + +msgid "show name from thetvdb" +msgstr "show name from thetvdb" + +msgid "episode name from thetvdb" +msgstr "episode name from thetvdb" + +msgid "season number" +msgstr "season number" + +msgid "episode number" +msgstr "episode number" + +msgid "it's possible to specify leading 0 like this:" +msgstr "it's possible to specify leading 0 like this:" + +msgid "(number means how many zeros)" +msgstr "(number means how many zeros)" + +msgid "Default pattern is" +msgstr "Default pattern is" + +msgid "You might want to change this to" +msgstr "You might want to change this to" + +msgid "User with uid %u doesn't exist!" +msgstr "User with uid %u doesn't exist!" + +msgid "Couldn't create database, make sure you have write permission for" +msgstr "Couldn't create database, make sure you have write permission for" + +msgid "Insert name pattern for database:" +msgstr "Insert name pattern for database:" + +msgid "Can't open database, make sure it exists" +msgstr "Can't open database, make sure it exists" + +msgid "Renaming" +msgstr "Renaming" + +msgid "Adding to database" +msgstr "Adding to database" + +msgid "Refreshing database" +msgstr "Refreshing database" + +msgid "Refreshing" +msgstr "Refreshing" + +msgid "Updating %s in database" +msgstr "Updating %s in database" + +msgid "Updating database" +msgstr "Updating database" + +msgid "Updating" +msgstr "Updating" + +msgid "Show field is empty" +msgstr "Show field is empty" + +msgid "No results found for given show name" +msgstr "No results found for given show name" + +msgid "Select seasons:" +msgstr "Select seasons:" + +msgid "Select All" +msgstr "Select All" + +msgid "Select None" +msgstr "Select None" + +msgid "Which TV Show is the right one?" +msgstr "Which TV Show is the right one?" + +msgid "Couldn't find episode names for season %s of show %s" +msgstr "Couldn't find episode names for season %s of show %s" + +msgid "Couldn't find episodes with season" +msgstr "Couldn't find episodes with season" + +msgid "Does this seem ok?" +msgstr "Does this seem ok?" + +msgid "y" +msgstr "y" + +msgid "Y" +msgstr "Y" + +msgid "n" +msgstr "n" + +msgid "N" +msgstr "N" + +msgid "Yes" +msgstr "Yes" + +msgid "No" +msgstr "No" + +msgid "Pattern escape sequences" +msgstr "Pattern escape sequences" + +msgid "Directory field is empty" +msgstr "Directory field is empty" + +msgid "Rename confirmation" +msgstr "Rename confirmation" + +msgid "File" +msgstr "File" + +msgid "Exit" +msgstr "Exit" + +msgid "Update database" +msgstr "Update database" + +msgid "Refresh database" +msgstr "Refresh database" + +msgid "Clean database" +msgstr "Clean database" + +msgid "Manage database" +msgstr "Manage database" + +msgid "Change pattern" +msgstr "Change pattern" + +msgid "Process" +msgstr "Process" + +msgid "Choose directory" +msgstr "Choose directory" + +msgid "Pattern help" +msgstr "Pattern help" + +msgid "Rename" +msgstr "Rename" + +msgid "Add to database" +msgstr "Add to database" + +msgid "Replace windows-illegal characters" +msgstr "Replace windows-illegal characters" + +msgid "Don't ask for rename confirmation" +msgstr "Don't ask for rename confirmation" + +msgid "Use DVD ordering" +msgstr "Use DVD ordering" + +msgid "Directory" +msgstr "Directory" + +msgid "Pattern" +msgstr "Pattern" + +msgid "Possible shows" +msgstr "Possible shows" + +msgid "OK" +msgstr "OK" + +msgid "or" +msgstr "or" diff --git a/functions.cpp b/functions.cpp index 5382fcf..9e05759 100644 --- a/functions.cpp +++ b/functions.cpp @@ -27,6 +27,7 @@ constexpr const char_t *dir_divider = L"\\"; #include #include #include +#include "resources_linux.h" #define cout std::cout #define cerr std::cerr @@ -50,6 +51,42 @@ std::wstring utf8_to_wstring( const std::string &utf8 ) { return wconv.from_bytes( utf8 ); } +wchar_t *LMsg( int ID ) { + // TODO better max value perhaps? + static wchar_t local[MAX_PATH]; + auto hInstance = GetModuleHandle( NULL ); + LoadString( hInstance, ID, local, MAX_PATH ); + // TODO add vargs + + return local; +} + +#else + +std::string getlocalized( const char *id, ... ) { + const char *local = gettext( id ); + va_list args; + va_start( args, id ); + int count = 0; + const char *p; + while ( ( p = va_arg( args, const char * ) ) != NULL ) + count++; + va_end( args ); + + if ( count == 0 ) + return local; + + va_start( args, id ); + int len = vsnprintf( nullptr, 0, local, args ); + va_end( args ); + char *text = new char[len + 1]; + va_start( args, id ); + vsnprintf( text, len + 1, local, args ); + std::string ret = text; + delete[] text; + return ret; +} + #endif // _WIN32 // encode url so it's valid even with UTF-8 characters @@ -77,8 +114,8 @@ string encodeUrl( const string &url ) { return encoded.str(); } -// return true if file contains S[0-9]+E[0-9]+ and set -// season_pos to start of season number +// return true if file contains S[0-9]+E[0-9]+, set +// season_pos to start of season number and ep_pos to start of episode number bool searchSeason( const char_t *const path, size_t &season_pos, size_t &ep_pos ) { size_t cur_pos{}; @@ -131,80 +168,51 @@ void iterateFS( std::map< int, std::map< int, string > > &seasons, // following functions are only needed for CLI version void printHelp() { - cout << "Usage:" << std::endl; - cout << " tv_rename [options] [path]" << std::endl << std::endl; - cout << " -h, --help show this help message and exit" - << std::endl + cout << _( HELP_USAGE ) << std::endl; + cout << " tv_rename [" << _( HELP_OPTIONS_SMALL ) << "] [" + << _( HELP_PATH_SMALL ) << "]" << std::endl << std::endl; - cout << " path can be either a file or a directory, if it's a directory" + cout << " -h, --help " << _( HELP_HELP ) << std::endl << std::endl; - cout << " all files in it and its subdirectories will be renamed" - << std::endl + cout << _( HELP_PATH_INFO ) << std::endl << std::endl; + cout << _( HELP_OPTIONS ) << std::endl; + cout << " -s, --show " << _( HELP_SHOW ) << std::endl; + cout << " -n, --season " << _( HELP_SEASON ) << std::endl; + cout << "" << std::endl; + cout << " -d, --dvd " << _( HELP_DVD ) << std::endl; + cout << " --name-pattern " << _( HELP_PATTERN ) << std::endl; + cout << " --pattern-help " << _( HELP_PATTERN_HELP ) << std::endl; - cout << "OPTIONS" << std::endl; - cout << " -s, --show TV show from which you want the"; - cout << " episode names" << std::endl; - cout << " -n, --season Season number/s (if multiple seasons," + cout << " -c, --correct-path " << _( HELP_CORRECT_PATH ) << std::endl; - cout << " must be seperated by one space)" - << " or 'all'" << std::endl; - cout << " for all seasons in selected directory" - << std::endl; - cout << " -d, --dvd use dvd ordering instead of aired " - "ordering" - << std::endl; - cout << " --name-pattern Pattern to which change the file name." - << std::endl; - cout << " Possible sequences are:" << std::endl; - cout << " %filename - original filename" - << std::endl; - cout << " (without filetype" - << " extension)" << std::endl; - cout << " %show - show name from thetvdb" - << std::endl; - cout << " %epname - episode name from thetvdb" - << std::endl; - cout << " %season - season number" - << std::endl; - cout << " it's possible to specify leading" - << " 0 like this:" << std::endl; - cout << " %2season (number means how many" - << " zeros)" << std::endl; - cout << " %episode - episode number" - << std::endl; - cout << " it's possible to specify leading" - << " 0 like this:" << std::endl; - cout << " %2episode (number means how many" - << " zeros)" << std::endl; - cout << " Default pattern is \"$filename -" - << " $epname\"" << std::endl; - cout << " -c, --correct-path This is the correct path," - << " stop asking me!" << std::endl; - cout << " -t, --trust Don't ask whether the names are correct" - << std::endl; - cout << " -x, --linux Don't replace characters characters" - << " that are" << std::endl; - cout << " illegal in Windows" << std::endl; - cout << " -l, --lang Select which language the episode" - << " names shoud be in" << std::endl; - cout << " --print-langs Pring available languages" << std::endl; + cout << " -t, --trust " << _( HELP_TRUST ) << std::endl; + cout << " -x, --linux " << _( HELP_LINUX ) << std::endl; + cout << " -l, --lang " << _( HELP_LANG ) << std::endl; + cout << " --print-langs " << _( HELP_LANGS ) << std::endl; cout << std::endl; - cout << "DATABASE OPTIONS" << std::endl; - cout << " --db-add Add path to the database" + cout << _( HELP_DATABASE_OPTS ) << std::endl; + cout << " --db-add " << _( HELP_ADD_DB ) << std::endl; + cout << " --db-refresh " << _( HELP_REFRESH_DB ) << std::endl; - cout << " --db-refresh Refresh episode names for all paths" - << " in the database" << std::endl; - cout << " --db-update Check all paths in the database," - << std::endl; - cout << " if they contain new files," - << " rename them" << std::endl; - cout << " --db-name-pattern Change name pattern used for files" - << std::endl - << " managed by database" << std::endl; - cout << " --db-clean Remove deleted files from the" - << " database" << std::endl; - cout << " --db-remove Remove path from the database" + cout << " --db-update " << _( HELP_UPDATE_DB ) << std::endl; + cout << " --db-name-pattern " << _( HELP_DB_PATTERN ) << std::endl; + cout << " --db-clean " << _( HELP_CLEAN_DB ) << std::endl; + cout << " --db-remove " << _( HELP_REMOVE_DB ) << std::endl; +} + +void printPatternHelp() { + cout << _( PATTERN_POSSIBLE ) << std::endl; + cout << " %filename - " << _( PATTERN_FILENAME ) << std::endl; + cout << " %show - " << _( PATTERN_SHOW ) << std::endl; + cout << " %epname - " << _( PATTERN_EPNAME ) << std::endl; + cout << " %season - " << _( PATTERN_SEASON ) << std::endl; + cout << " " << _( PATTERN_LEADING_ZERO ) << std::endl; + cout << " %2season " << _( PATTERN_LEADING_NUM ) << std::endl; + cout << " %episode - " << _( PATTERN_EPISODE ) << std::endl; + cout << " " << _( PATTERN_LEADING_ZERO ) << std::endl; + cout << " %2episode " << _( PATTERN_LEADING_NUM ) << std::endl; + cout << _( PATTERN_DEFAULT ) << " \"%filename - %epname\"" << std::endl; } // parse command line argument --seasons (e.g. '1 2 3 4 5') @@ -248,7 +256,7 @@ string userHome() { return dir_s; } CoTaskMemFree( dir ); - throw std::runtime_error( "Couldn't find user's %%APPDATA%%!" ); + throw std::runtime_error( _( APPDATA_NOT_FOUND ) ); } #else // UNIX @@ -264,9 +272,9 @@ string userHome() { // password file entry auto user_passwd = getpwuid( user_uid ); - if ( user_passwd == nullptr ) - throw std::runtime_error( - "User with uid " + std::to_string( user_uid ) + " doesn't exist!" ); + if ( user_passwd == nullptr ) { + throw std::runtime_error( _( USER_NOT_EXIST, user_uid ) ); + } return user_passwd->pw_dir; } @@ -402,8 +410,7 @@ void prepareDB( const string &_pattern ) { try { db.open( getDBName(), SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE ); } catch ( std::exception &e ) { - cerr << "Couldn't create database, make sure you have" - << " write permission for " << getDBName() << std::endl; + cerr << _( DB_NOT_CREATE ) << " " << getDBName() << std::endl; throw e; } db.exec( @@ -416,7 +423,7 @@ void prepareDB( const string &_pattern ) { "REFERENCES SHOWS(ID));" ); const string *pattern; if ( _pattern.empty() ) { - cout << "Insert name pattern for database:" << std::endl; + cout << _( DB_INSERT_PATTERN ) << std::endl; auto *p = new string; std::getline( cin, *p ); pattern = p; @@ -446,7 +453,7 @@ void addToDB( const string &show, const string &path, const string &language, try { db.open( getDBName(), SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE ); } catch ( std::exception &e ) { - cerr << "Can't open database, make sure it exists" << std::endl; + cerr << _( DB_CANT_OPEN ) << std::endl; throw e; } #ifndef GUI @@ -481,7 +488,7 @@ void addToDB( const string &show, const string &path, const string &language, ProgressBar p( progress_ptr ); #endif - p.print( TEXT( "Renaming" ) ); + p.print( _( RENAMING ) ); p.print( 0 ); size_t i = 0; @@ -496,7 +503,7 @@ void addToDB( const string &show, const string &path, const string &language, cout << std::endl; #endif - p.print( TEXT( "Adding to database" ) ); + p.print( _( ADDING_TO_DB ) ); p.print( 0 ); i = 0; @@ -557,7 +564,7 @@ void refreshDB( bool linux, void *progress_ptr ) { try { db.open( getDBName(), SQLite::OPEN_READWRITE ); } catch ( std::exception &e ) { - cerr << "Can't open database, make sure it exists" << std::endl; + cerr << _( DB_CANT_OPEN ) << std::endl; throw e; } @@ -574,7 +581,7 @@ void refreshDB( bool linux, void *progress_ptr ) { #ifndef GUI ProgressBar p; - p.print( TEXT( "Refreshing database" ) ); + p.print( _( REFRESHING_DB ) ); cout << std::endl << std::endl; #else // GUI ProgressBar p( progress_ptr ); @@ -585,7 +592,7 @@ void refreshDB( bool linux, void *progress_ptr ) { #ifndef GUI cleanUpLine(); #endif - p.print( TEXT( "Refreshing " ) + show[TEXT( "SHOW" )] ); + p.print( _( REFRESHING ) + string( " " ) + show[TEXT( "SHOW" )] ); p.print( 0 ); std::map< int, std::map< int, string > > seasons; @@ -606,8 +613,7 @@ void refreshDB( bool linux, void *progress_ptr ) { cout << std::endl; cleanUpLine(); #endif - p.print( TEXT( "Updating " ) + show[TEXT( "SHOW" )] + - TEXT( " in database" ) ); + p.print( _( UPDATING_IN_DB, show[TEXT( "SHOW" )].c_str() ) ); p.print( 0 ); i = 0; size_t j{}; @@ -646,7 +652,7 @@ void updateDB( bool linux, void *progress_ptr ) { try { db.open( getDBName(), SQLite::OPEN_READWRITE ); } catch ( std::exception &e ) { - cerr << "Can't open database, make sure it exists" << std::endl; + cerr << _( DB_CANT_OPEN ) << std::endl; throw e; } db.exec( @@ -663,7 +669,7 @@ void updateDB( bool linux, void *progress_ptr ) { #else // GUI ProgressBar p( progress_ptr ); #endif - p.print( TEXT( "Updating database" ) ); + p.print( _( UPDATING_DB ) ); #ifndef GUI cout << std::endl << std::endl; #endif @@ -674,7 +680,7 @@ void updateDB( bool linux, void *progress_ptr ) { #ifndef GUI cleanUpLine(); #endif - p.print( TEXT( "Updating " ) + show[TEXT( "SHOW" )] ); + p.print( _( UPDATING ) + string( ' ', 1 ) + show[TEXT( "SHOW" )] ); std::unordered_set< string > episodes; db.exec( TEXT( "SELECT PATH FROM EPISODES WHERE SHOWID == " ) + @@ -727,7 +733,7 @@ void changeDBPattern( const string &pattern ) { try { db.open( getDBName(), SQLite::OPEN_READWRITE ); } catch ( std::exception &e ) { - cerr << "Can't open database, make sure it exists" << std::endl; + cerr << _( DB_CANT_OPEN ) << std::endl; throw e; } db.exec( TEXT( "UPDATE SHOWS SET PATH = '" ) + pattern + @@ -742,7 +748,7 @@ void cleanDB() { try { db.open( getDBName(), SQLite::OPEN_READWRITE ); } catch ( std::exception &e ) { - cerr << "Can't open database, make sure it exists" << std::endl; + cerr << _( DB_CANT_OPEN ) << std::endl; throw e; } db.exec( TEXT( "SELECT ID, PATH FROM SHOWS WHERE TVID" @@ -779,7 +785,7 @@ void removeFromDB( const string &path ) { try { db.open( getDBName(), SQLite::OPEN_READWRITE ); } catch ( std::exception &e ) { - cerr << "Can't open database, make sure it exists" << std::endl; + cerr << _( DB_CANT_OPEN ) << std::endl; throw e; } string show_id{}; @@ -799,7 +805,7 @@ std::vector< std::unordered_map< string, string > > dbGetShows() { try { db.open( getDBName(), SQLite::OPEN_READWRITE ); } catch ( std::exception &e ) { - cerr << "Can't open database, make sure it exists" << std::endl; + cerr << _( DB_CANT_OPEN ) << std::endl; throw e; } std::vector< std::unordered_map< string, string > > ret; @@ -816,7 +822,7 @@ void changeDB( size_t index, const string &path, const string &language, try { db.open( getDBName(), SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE ); } catch ( std::exception &e ) { - cerr << "Can't open database, make sure it exists" << std::endl; + cerr << _( DB_CANT_OPEN ) << std::endl; throw e; } #ifndef _WIN32 @@ -852,7 +858,7 @@ void refreshSelectDB( std::unordered_set< size_t > indexes, bool linux, try { db.open( getDBName(), SQLite::OPEN_READWRITE ); } catch ( std::exception &e ) { - cerr << "Can't open database, make sure it exists" << std::endl; + cerr << _( DB_CANT_OPEN ) << std::endl; throw e; } db.exec( TEXT( "DELETE FROM EPISODES WHERE SHOWID IN " ) + index_list + @@ -869,7 +875,7 @@ void refreshSelectDB( std::unordered_set< size_t > indexes, bool linux, ProgressBar p( progress_ptr ); for ( auto &show : shows ) { - p.print( TEXT( "Refreshing " ) + show[TEXT( "SHOW" )] ); + p.print( _( REFRESHING ) + string( ' ', 1 ) + show[TEXT( "SHOW" )] ); if ( FSLib::exists( show[TEXT( "PATH" )] ) ) { p.print( 0 ); std::map< int, std::map< int, string > > seasons; @@ -907,7 +913,7 @@ string getDBPattern() { try { db.open( getDBName(), SQLite::OPEN_READONLY ); } catch ( std::exception &e ) { - cerr << "Can't open database, make sure it exists" << std::endl; + cerr << _( DB_CANT_OPEN ) << std::endl; throw e; } string pattern{}; diff --git a/functions.hpp b/functions.hpp index c2f7ac3..4d8bea0 100644 --- a/functions.hpp +++ b/functions.hpp @@ -16,19 +16,28 @@ using string = std::wstring; using char_t = wchar_t; std::wstring utf8_to_wstring( const std::string &utf8 ); +wchar_t *LMsg( int ID ); + +#define _( x, ... ) LMsg( ID, ##__VA_ARGS__ ) #else +#include + using string = std::string; using char_t = char; -#define TEXT( a ) a +std::string getlocalized( const char *id, ... ); + +#define TEXT( x ) x +#define _( x, ... ) getlocalized( x, ##__VA_ARGS__ ) #endif #ifndef GUI // CLI functions void printHelp(); +void printPatternHelp(); bool searchSeason( const char_t *const path, size_t &season_pos ); bool searchSeason( const char_t *const path, size_t &season_pos, diff --git a/gtkfunctions.cpp b/gtkfunctions.cpp index 0aa7f03..9d5a9ec 100644 --- a/gtkfunctions.cpp +++ b/gtkfunctions.cpp @@ -3,6 +3,8 @@ #include #include +#include "functions.hpp" +#include "resources_linux.h" #include "tv_rename.hpp" void searchShow( Gtk::Entry *entry_show, Gtk::ComboBox *combo_possible, @@ -11,7 +13,7 @@ void searchShow( Gtk::Entry *entry_show, Gtk::ComboBox *combo_possible, const std::string &language_code, Gtk::Window *parent ) { // check required field is filled out if ( entry_show->get_text().empty() ) { - Gtk::MessageDialog dialog( *parent, "Show field is empty" ); + Gtk::MessageDialog dialog( *parent, _( SHOW_FIELD_EMPTY ) ); dialog.run(); return; } @@ -22,8 +24,7 @@ void searchShow( Gtk::Entry *entry_show, Gtk::ComboBox *combo_possible, // if no possible shows were found, tell the user if ( possible_shows.size() == 0 ) { - Gtk::MessageDialog dialog( *parent, - "No results found for given show name" ); + Gtk::MessageDialog dialog( *parent, _( NO_RESULTS ) ); dialog.run(); return; } diff --git a/gui.cpp b/gui.cpp index ab6af9b..40ecab4 100644 --- a/gui.cpp +++ b/gui.cpp @@ -1,14 +1,28 @@ +#include "functions.hpp" +#include +#include #include +#include +#include #include "mainwindow.hpp" +#include "resources_linux.h" #include "tv_rename.hpp" #define API_KEY "42B66F5E-C6BF-423F-ADF9-CC97163472F6" +#define DOMAIN "tv_rename" int main( int argc, char **argv ) { auto app = Gtk::Application::create( argc, argv, "org.idonthaveanorganization.tvrename" ); + if ( setlocale( LC_ALL, "" ) == NULL ) + error( 1, errno, _( INVALID_LOCALE ).c_str() ); + if ( bindtextdomain( DOMAIN, "./locale" ) == NULL ) + error( 1, errno, _( MEM_ALLOC_FAILED ).c_str() ); + if ( textdomain( DOMAIN ) == NULL ) + error( 1, errno, _( MEM_ALLOC_FAILED ).c_str() ); + authenticate( API_KEY ); MainWindow mw( app ); diff --git a/main.cpp b/main.cpp index 39763dd..6518637 100644 --- a/main.cpp +++ b/main.cpp @@ -1,8 +1,12 @@ +#include +#include #include +#include #include #ifdef _WIN32 +#include "resources.h" #include #include #include @@ -16,6 +20,7 @@ using string = std::wstring; #else +#include "resources_linux.h" #include using char_t = char; @@ -24,8 +29,7 @@ using string = std::string; #define cerr std::cerr #define cout std::cout #define cin std::cin - -#define TEXT( a ) a +#define DOMAIN "tv_rename" #endif @@ -109,6 +113,9 @@ int handleArgument( char_t c, string &show, std::set< int > &seasons_num, db_flags |= DB_PATTERN; i++; break; + case '5': + printPatternHelp(); + return 1; default: return -1; } @@ -154,6 +161,8 @@ string getOptions( const char_t *option ) { return L"3"; else if ( !wcscmp( option, L"--db-name-pattern" ) ) return L"4"; + else if ( !wcscmp( option, L"--pattern-help" ) ) + return L"5"; return L""; } @@ -207,6 +216,7 @@ int parseCommandLine( string &show, std::set< int > &seasons_num, string &path, { "db-clean", no_argument, 0, '2' }, { "db-remove", no_argument, 0, '3' }, { "db-name-pattern", required_argument, 0, '4' }, + { "pattern-help", no_argument, 0, '5' }, { 0, 0, 0, 0 } }; @@ -246,6 +256,10 @@ int main #ifdef _WIN32 // set console to unicode _setmode( _fileno( stdout ), _O_U16TEXT ); +#else + setlocale( LC_ALL, "" ); + bindtextdomain( DOMAIN, "./locale" ); + textdomain( DOMAIN ); #endif string show{}; std::set< int > seasons_num{}; @@ -271,7 +285,7 @@ int main } if ( !findLanguage( language.c_str() ) ) { - cerr << "Invalid language choice" << std::endl; + cerr << _( INVALID_CHOICE ) << std::endl; printLangs(); return -1; } @@ -281,8 +295,7 @@ int main std::map< int, string > file_set{}; size_t season_pos{}, ep_pos{}; if ( !searchSeason( path.c_str(), season_pos, ep_pos ) ) { - cerr << "Specified file does not conform to filename pattern, " - << "cannot rename." << std::endl; + cerr << _( PATTERN_ERROR ) << std::endl; return 1; } else { file_set[std::stoi( path.c_str() + ep_pos )] = path; @@ -300,7 +313,7 @@ int main } if ( db_flags & DB_REMOVE && db_flags & DB_ADD ) { - cerr << "You can't remove and add at the same time" << std::endl; + cerr << _( ADD_REMOVE_FLAG_ERROR ) << std::endl; return 1; } @@ -309,19 +322,19 @@ int main } if ( db_flags & DB_ADD ) { addToDB( show, path, language, tv_flags & TV_LINUX, tv_flags & TV_DVD ); - cout << "Added to database" << std::endl; + cout << _( ADDED_TO_DB ) << std::endl; } if ( db_flags & DB_REFRESH ) { refreshDB( tv_flags & TV_LINUX ); - cout << "Refreshed database" << std::endl; + cout << _( REFRESHED_DB ) << std::endl; } if ( db_flags & DB_UPDATE ) { updateDB( tv_flags & TV_LINUX ); - cout << "Updated database" << std::endl; + cout << _( UPDATED_DB ) << std::endl; } if ( db_flags & DB_CLEAN ) { cleanDB(); - cout << "Database cleaned" << std::endl; + cout << _( CLEANED_DB ) << std::endl; } // if db operations happened don't continue @@ -330,13 +343,11 @@ int main while ( tv_flags & TV_CHDIR ) { if ( !FSLib::isDirectory( path ) ) { - cout << "This directory doesn't exist, please insert a correct " - "path: " - << std::endl; + cout << _( DIR_FAIL_REENTER ) << std::endl; std::getline( cin, path ); continue; } - cout << "Is this the right directory? " << FSLib::canonical( path ) + cout << _( DIR_CONFIRM ) << ' ' << FSLib::canonical( path ) << std::endl; string response; cin >> response; @@ -345,7 +356,7 @@ int main if ( response[0] == 'y' || response[0] == 'Y' ) { tv_flags &= ~TV_CHDIR; } else { - cout << "Insert correct path:" << std::endl; + cout << _( DIR_REENTER ) << std::endl; std::getline( cin, path ); } } @@ -355,13 +366,13 @@ int main auto pos = show.find_last_of( '/' ); if ( pos != string::npos ) show = show.substr( ++pos ); - cout << "Is this the right show name? " << show << std::endl; + cout << _( SHOW_CONFIRM ) << ' ' << show << std::endl; string response; cin >> response; cin.ignore( 1, '\n' ); cin.clear(); if ( response[0] != 'y' && response[0] != 'Y' ) { - cout << "Insert the correct show name: " << std::endl; + cout << _( SHOW_REENTER ) << std::endl; std::getline( cin, show ); } } diff --git a/mainwindow.cpp b/mainwindow.cpp index f75168b..fec291c 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -14,16 +14,17 @@ #include "gtkfunctions.hpp" #include "mainwindow.hpp" #include "progresswindow.hpp" +#include "resources_linux.h" #include "tv_rename.hpp" void MainWindow::chooseFile() { // create a dialog for choosing directory - Gtk::FileChooserDialog dialog( "Select a directory", + Gtk::FileChooserDialog dialog( _( SELECT_DIR ), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); dialog.set_transient_for( *this ); // add cancel and select buttons - dialog.add_button( "_Cancel", Gtk::RESPONSE_CANCEL ); - dialog.add_button( "Select", Gtk::RESPONSE_OK ); + dialog.add_button( "_" + _( CANCEL ), Gtk::RESPONSE_CANCEL ); + dialog.add_button( _( SELECT ), Gtk::RESPONSE_OK ); auto result = dialog.run(); @@ -42,21 +43,20 @@ void MainWindow::quit() { hide(); } +// TODO maybe fix help to not force translators to make 2 versions void MainWindow::patternHelp() { - Gtk::MessageDialog dialog( *this, "Pattern escape sequences" ); - dialog.set_secondary_text( - "%filename - original filename (without type extension)\n" - "%show - show name from thetvdb\n" - "%epname - episode name from thetvdb\n" - "%season - season number\n" - "%episode - episode number\n" - "Both season number and episode number can be padded with zeros, just " - "add width of padding" - " right after %, like this: %2season.\n" - "Default pattern is \"%filename - %epname\", you might want to change " - "this to" - " \"S%2seasonE%2episode - %epname\" or \"%show - S%2seasonE%2episode - " - "%epname\"" ); + Gtk::MessageDialog dialog( *this, _( PATTERN_ESC_SEQ ) ); + std::string help = "%filename - " + _( PATTERN_FILENAME ) + "\n"; + help += "%show - " + _( PATTERN_SHOW ) + "\n"; + help += "%epname - " + _( PATTERN_EPNAME ) + "\n"; + help += "%season - " + _( PATTERN_SEASON ) + "\n"; + help += "%episode - " + _( PATTERN_EPNAME ) + "\n"; + help += _( PATTERN_LEADING_ZERO ) + "\n"; + help += " %2season, %2episode - " + _( PATTERN_LEADING_NUM ) + "\n"; + help += _( PATTERN_DEFAULT ) + " \"%filename - %epname\"\n"; + help += _( PATTERN_CHANGE ) + "\"S%2seasonE%2episode - %epname\" " + + _( OR ) + "\"%show - S%2seasonE%2episode - %epname\""; + dialog.set_secondary_text( help ); dialog.run(); } @@ -73,13 +73,14 @@ void MainWindow::process() { void MainWindow::getNames() { // check required field is filled out if ( m_entry_dir->get_text().empty() ) { - Gtk::MessageDialog dialog( *this, "Directory field is empty" ); + Gtk::MessageDialog dialog( *this, _( DIR_EMPTY ) ); dialog.run(); return; } // check directory exists if ( !FSLib::isDirectory( m_entry_dir->get_text() ) ) { - Gtk::MessageDialog dialog( *this, "Directory doesn't exist" ); + Gtk::MessageDialog dialog( + *this, _( DIR_NOT_EXIST, m_entry_dir->get_text().c_str() ) ); dialog.run(); return; } @@ -152,7 +153,7 @@ void MainWindow::finishedSelection() { // create a custom dialog box with textview of new episode names std::unique_ptr< Gtk::Dialog > dialog( - new Gtk::Dialog( "Rename confirmation", *this ) ); + new Gtk::Dialog( _( RENAME_CONFIRM ), *this ) ); dialog->set_default_size( 550, 350 ); dialog->set_resizable( false ); auto content = dialog->get_content_area(); @@ -164,8 +165,8 @@ void MainWindow::finishedSelection() { tx->set_editable( false ); tx->set_cursor_visible( false ); - dialog->add_button( "_No", Gtk::RESPONSE_CANCEL ); - dialog->add_button( "_Yes", Gtk::RESPONSE_OK ); + dialog->add_button( "_" + _( NO ), Gtk::RESPONSE_CANCEL ); + dialog->add_button( "_" + _( YES ), Gtk::RESPONSE_OK ); sc_w->show(); tx->show(); @@ -249,13 +250,13 @@ MainWindow::MainWindow( const Glib::RefPtr< Gtk::Application > &ptr ) menu->append( *item ); // File menu - item->set_label( "File" ); + item->set_label( _( FILE ) ); item->set_submenu( *submenu ); // Exit item for File menu item = new Gtk::MenuItem(); - item->set_label( "Exit" ); + item->set_label( _( EXIT ) ); item->signal_activate().connect( sigc::mem_fun( *this, &MainWindow::quit ) ); @@ -265,13 +266,13 @@ MainWindow::MainWindow( const Glib::RefPtr< Gtk::Application > &ptr ) item = new Gtk::MenuItem(); submenu = new Gtk::Menu(); - item->set_label( "Database" ); + item->set_label( _( DATABASE ) ); item->set_submenu( *submenu ); menu->append( *item ); // Update database item = new Gtk::MenuItem(); - item->set_label( "Update database" ); + item->set_label( _( UPDATE_DB ) ); item->signal_activate().connect( sigc::mem_fun( *this, &MainWindow::dbUpdate ) ); @@ -279,7 +280,7 @@ MainWindow::MainWindow( const Glib::RefPtr< Gtk::Application > &ptr ) // Refresh database item = new Gtk::MenuItem(); - item->set_label( "Refresh database" ); + item->set_label( _( REFRESH_DB ) ); item->signal_activate().connect( sigc::mem_fun( *this, &MainWindow::dbRefresh ) ); @@ -287,7 +288,7 @@ MainWindow::MainWindow( const Glib::RefPtr< Gtk::Application > &ptr ) // Clean database item = new Gtk::MenuItem(); - item->set_label( "Clean database" ); + item->set_label( _( CLEAN_DB ) ); item->signal_activate().connect( sigc::mem_fun( *this, &MainWindow::dbClean ) ); @@ -295,14 +296,14 @@ MainWindow::MainWindow( const Glib::RefPtr< Gtk::Application > &ptr ) // Manage database item = new Gtk::MenuItem(); - item->set_label( "Manage database" ); + item->set_label( _( MANAGE_DB ) ); item->signal_activate().connect( sigc::mem_fun( *this, &MainWindow::dbManage ) ); submenu->append( *item ); item = new Gtk::MenuItem(); - item->set_label( "Change pattern" ); + item->set_label( _( CHANGE_DB_PATTERN ) ); item->signal_activate().connect( sigc::mem_fun( *this, &MainWindow::dbPattern ) ); @@ -356,22 +357,22 @@ MainWindow::MainWindow( const Glib::RefPtr< Gtk::Application > &ptr ) button_quit->set_margin_bottom( 5 ); // set button texts - button_process->set_label( "Process" ); - button_quit->set_label( "Quit" ); - button_dir->set_label( "Choose directory" ); - button_pattern->set_label( "Pattern help" ); - m_button_rename->set_label( "Rename" ); - m_button_db_add->set_label( "Add to database" ); - m_check_linux->set_label( "Replace windows-illegal characters" ); - m_check_trust->set_label( "Don't ask for rename confirmation" ); - m_check_dvd->set_label( "Use DVD ordering" ); + button_process->set_label( _( PROCESS ) ); + button_quit->set_label( _( QUIT ) ); + button_dir->set_label( _( CHOOSE_DIR ) ); + button_pattern->set_label( _( PATTERN_HELP ) ); + m_button_rename->set_label( _( RENAME ) ); + m_button_db_add->set_label( _( ADD_TO_DB ) ); + m_check_linux->set_label( _( REPLACE_WIN ) ); + m_check_trust->set_label( _( DONT_RENAME_CONFIRM ) ); + m_check_dvd->set_label( _( USE_DVD ) ); // set label texts - label_show->set_label( "Show:" ); - label_language->set_label( "Language:" ); - label_dir->set_label( "Directory:" ); - label_pattern->set_label( "Pattern:" ); - m_label_possible->set_label( "Possible shows:" ); + label_show->set_label( _( SHOW ) + ":" ); + label_language->set_label( _( LANGUAGE ) + ":" ); + label_dir->set_label( _( DIRECTORY ) + ":" ); + label_pattern->set_label( _( PATTERN ) + ":" ); + m_label_possible->set_label( _( POSSIBLE_SHOWS ) + ":" ); m_entry_show->set_size_request( 170, 30 ); m_entry_dir->set_size_request( 170, 30 ); @@ -476,13 +477,13 @@ void MainWindow::dbRefresh() { void MainWindow::dbAdd() { // check required field is filled out if ( m_entry_dir->get_text().empty() ) { - Gtk::MessageDialog dialog( *this, "Directory field is empty" ); + Gtk::MessageDialog dialog( *this, _( DIR_EMPTY ) ); dialog.run(); return; } // check directory exists if ( !FSLib::isDirectory( m_entry_dir->get_text() ) ) { - Gtk::MessageDialog dialog( *this, "Directory doesn't exist" ); + Gtk::MessageDialog dialog( *this, _( DIR_EMPTY ) ); dialog.run(); return; } @@ -530,7 +531,7 @@ void MainWindow::dbManage() { void MainWindow::dbPattern() { // Create a custom dialog box for pattern change std::unique_ptr< Gtk::Dialog > dialog( - new Gtk::Dialog( "Change pattern", *this ) ); + new Gtk::Dialog( _( CHANGE_DB_PATTERN ), *this ) ); dialog->set_default_size( 350, 0 ); auto content = dialog->get_content_area(); @@ -539,8 +540,8 @@ void MainWindow::dbPattern() { std::unique_ptr< Gtk::Entry > pattern_entry( new Gtk::Entry ); content->pack_start( *pattern_entry ); - dialog->add_button( "_Cancel", Gtk::RESPONSE_CANCEL ); - dialog->add_button( "_OK", Gtk::RESPONSE_OK ); + dialog->add_button( "_" + _( CANCEL ), Gtk::RESPONSE_CANCEL ); + dialog->add_button( "_" + _( OK ), Gtk::RESPONSE_OK ); dialog->show_all_children(); dialog->signal_response().connect( diff --git a/progress.cpp b/progress.cpp index 3fb6cb1..e84e9f2 100644 --- a/progress.cpp +++ b/progress.cpp @@ -100,7 +100,7 @@ void ProgressBar::print( int perc ) { #ifndef _WIN32 static_cast< ProgressWindow * >( ptr )->setPerc( perc ); #else - SendMessage( (HWND)ptr, WM_APP, PROGRESS_PERC, perc ); + SendMessage( ( HWND )ptr, WM_APP, PROGRESS_PERC, perc ); #endif } @@ -108,7 +108,7 @@ void ProgressBar::print( const string &t ) { #ifndef _WIN32 static_cast< ProgressWindow * >( ptr )->setLabel( t ); #else - SendMessage( (HWND)ptr, WM_APP, PROGRESS_STRING, ( LPARAM )t.c_str() ); + SendMessage( ( HWND )ptr, WM_APP, PROGRESS_STRING, ( LPARAM )t.c_str() ); #endif } @@ -116,7 +116,7 @@ ProgressBar::~ProgressBar() { #ifndef _WIN32 static_cast< ProgressWindow * >( ptr )->hide(); #else - SendMessage( (HWND)ptr, WM_CLOSE, 0, 0 ); + SendMessage( ( HWND )ptr, WM_CLOSE, 0, 0 ); #endif } diff --git a/progresswindow.cpp b/progresswindow.cpp index 17e00bc..7b8fdaa 100644 --- a/progresswindow.cpp +++ b/progresswindow.cpp @@ -3,9 +3,10 @@ #include "functions.hpp" #include "progresswindow.hpp" +#include "resources_linux.h" ProgressWindow::ProgressWindow() { - set_title( "Progress" ); + set_title( _( GUI_WINDOW_PROGRESS ) ); set_default_size( 500, 55 ); diff --git a/resources_linux.h b/resources_linux.h new file mode 100644 index 0000000..ba2acf0 --- /dev/null +++ b/resources_linux.h @@ -0,0 +1,132 @@ +#define INVALID_CHOICE "Invalid language choice" +#define PATTERN_ERROR "Specified file does not conform to filename pattern, cannot rename." +#define ADD_REMOVE_FLAG_ERROR "You can't remove and add at the same time" +#define ADDED_TO_DB "Added to database" +#define REFRESHED_DB "Refreshed database" +#define UPDATED_DB "Updated database" +#define CLEANED_DB "Database cleaned" +#define DIR_FAIL_REENTER "This directory doesn't exist, please insert a correct path:" +#define DIR_CONFIRM "Is this the right directory?" +#define DIR_REENTER "Insert correct path:" +#define SHOW_CONFIRM "Is this the right show name?" +#define SHOW_REENTER "Insert the correct show name:" + +#define DATABASE "Database" +#define GUI_WINDOW_PROGRESS "Progress" +#define GUI_WINDOW_SEARCH "Select show" +#define GUI_WINDOW_SEASON "Choose seasons" + +#define SAVE "Save" +#define DELETE "Delete" +#define QUIT "Quit" +#define SHOW "Show" +#define PATH "Path" +#define LANGUAGE "Language" +#define DVD "DVD" +#define SELECT_DIR "Select a directory" +#define CANCEL "Cancel" +#define SELECT "Select" +#define SEARCH "Search" +#define INVALID_PATH "Invalid path" +#define DIR_NOT_EXIST "Directory '%s' doesn't exist" + +#define HELP_USAGE "Usage:" +#define HELP_OPTIONS_SMALL "options" +#define HELP_PATH_SMALL "path" +#define HELP_HELP "show this help message and exit" +#define HELP_PATH_INFO " path can be either a file or a directory, "\ + "if it's a directory\n all files in it and its "\ + "subdirectories will be renamed" +#define HELP_OPTIONS "OPTIONS" +#define HELP_SHOW "TV show from which you want the episode names" +#define HELP_SEASON "Season number/s (if multiple seasons,\n "\ + " must be seperated by one"\ + " space) or 'all'\n "\ + "for all seasons in selected directory" +#define HELP_DVD "use dvd ordering instead of aired ordering" +#define HELP_PATTERN "Pattern to which change the file name." +#define HELP_PATTERN_HELP "Print pattern help" +#define HELP_CORRECT_PATH "This is the correct path, stop asking me!" +#define HELP_TRUST "Don't ask whether the names are correct" +#define HELP_LINUX "Don't replace characters characters that are\n"\ + " illegal in Windows" +#define HELP_LANG "Select which language the episode names shoud be in" +#define HELP_LANGS "Print available languages" +#define HELP_DATABASE_OPTS "DATABASE OPTIONS" +#define HELP_ADD_DB "Add path to the database" +#define HELP_REFRESH_DB "Refresh episode names for all paths in the database" +#define HELP_UPDATE_DB "Check all paths in the database,\n "\ + " if they contain new files, rename them" +#define HELP_DB_PATTERN "Change name pattern used for files\n "\ + " managed by database" +#define HELP_CLEAN_DB "Remove deleted files from the database" +#define HELP_REMOVE_DB "Remove path from the database" + +#define PATTERN_POSSIBLE "Possible pattern sequences are:" +#define PATTERN_FILENAME "original filename (without filetype extension)" +#define PATTERN_SHOW "show name from thetvdb" +#define PATTERN_EPNAME "episode name from thetvdb" +#define PATTERN_SEASON "season number" +#define PATTERN_EPISODE "episode number" +#define PATTERN_LEADING_ZERO "it's possible to specify leading 0 like this:" +#define PATTERN_LEADING_NUM "(number means how many zeros)" +#define PATTERN_DEFAULT "Default pattern is" +#define PATTERN_CHANGE "You might want to change this to" + +#define USER_NOT_EXIST "User with uid %u doesn't exist!" +#define DB_NOT_CREATE "Couldn't create database, make sure you have "\ + "write permission for" +#define DB_INSERT_PATTERN "Insert name pattern for database:" +#define DB_CANT_OPEN "Can't open database, make sure it exists" +#define RENAMING "Renaming" +#define ADDING_TO_DB "Adding to database" +#define REFRESHING_DB "Refreshing database" +#define REFRESHING "Refreshing" +#define UPDATING_IN_DB "Updating %s in database" +#define UPDATING_DB "Updating database" +#define UPDATING "Updating" + +#define SHOW_FIELD_EMPTY "Show field is empty" +#define NO_RESULTS "No results found for given show name" + +#define SELECT_SEASONS "Select seasons:" +#define SELECT_ALL "Select All" +#define SELECT_NONE "Select None" + +#define WHICH_SHOW "Which TV Show is the right one?" +#define NOT_FOUND_SHOW_SEASON "Couldn't find episode names for season %s of show %s" +#define NOT_FOUND_FOR_SEASON "Couldn't find episodes with season" +#define CONFIRMATION "Does this seem ok?" +#define YES_1 "y" +#define YES_2 "Y" +#define NO_1 "n" +#define NO_2 "N" +#define YES "Yes" +#define NO "No" + +#define PATTERN_ESC_SEQ "Pattern escape sequences" +#define DIR_EMPTY "Directory field is empty" +#define RENAME_CONFIRM "Rename confirmation" +#define FILE "File" +#define EXIT "Exit" +#define UPDATE_DB "Update database" +#define REFRESH_DB "Refresh database" +#define CLEAN_DB "Clean database" +#define MANAGE_DB "Manage database" +#define CHANGE_DB_PATTERN "Change pattern" +#define PROCESS "Process" +#define CHOOSE_DIR "Choose directory" +#define PATTERN_HELP "Pattern help" +#define RENAME "Rename" +#define ADD_TO_DB "Add to database" +#define REPLACE_WIN "Replace windows-illegal characters" +#define DONT_RENAME_CONFIRM "Don't ask for rename confirmation" +#define USE_DVD "Use DVD ordering" +#define DIRECTORY "Directory" +#define PATTERN "Pattern" +#define POSSIBLE_SHOWS "Possible shows" +#define OK "OK" +#define OR "or" + +#define INVALID_LOCALE "invalid locale" +#define MEM_ALLOC_FAILED "memory allocation failed" diff --git a/searchwindow.cpp b/searchwindow.cpp index f2b8c70..8f5127c 100644 --- a/searchwindow.cpp +++ b/searchwindow.cpp @@ -4,7 +4,9 @@ #include #include +#include "functions.hpp" #include "gtkfunctions.hpp" +#include "resources_linux.h" #include "searchwindow.hpp" #include "tv_rename.hpp" @@ -37,7 +39,7 @@ SearchWindow::SearchWindow( std::string &_show, std::string &_id, std::map< std::string, std::string > &_languages ) : search_show( _show ), search_id( _id ), language_code( _lang ), language_map( _languages ) { - set_title( "Select show" ); + set_title( _( GUI_WINDOW_SEARCH ) ); property_modal().set_value( true ); set_resizable( false ); @@ -50,10 +52,10 @@ SearchWindow::SearchWindow( std::string &_show, std::string &_id, box->pack_start( *buttons, Gtk::PACK_EXPAND_WIDGET ); hbox->pack_start( *m_entry_show, Gtk::PACK_EXPAND_WIDGET ); hbox->pack_start( *m_combo_language, Gtk::PACK_EXPAND_WIDGET ); - auto *search_button = new Gtk::Button( "Search" ); + auto *search_button = new Gtk::Button( _( SEARCH ) ); hbox->pack_start( *search_button, Gtk::PACK_SHRINK ); - auto *select_button = new Gtk::Button( "Select" ); - auto *cancel_button = new Gtk::Button( "Cancel" ); + auto *select_button = new Gtk::Button( _( SELECT ) ); + auto *cancel_button = new Gtk::Button( _( CANCEL ) ); buttons->pack_end( *cancel_button, Gtk::PACK_SHRINK ); buttons->pack_end( *select_button, Gtk::PACK_SHRINK ); diff --git a/seasonwindow.cpp b/seasonwindow.cpp index 8872283..26c105c 100644 --- a/seasonwindow.cpp +++ b/seasonwindow.cpp @@ -1,6 +1,9 @@ #include "seasonwindow.hpp" #include +#include "functions.hpp" +#include "resources_linux.h" + void SeasonWindow::confirm() { // go through all checkbuttons and save numbers // of checked boxes into returned vector @@ -30,7 +33,7 @@ void SeasonWindow::select_none() { SeasonWindow::SeasonWindow( const std::vector< int > &seasons, std::vector< int > &_returned ) : returned( _returned ) { - set_title( "Choose seasons" ); + set_title( _( GUI_WINDOW_SEASON ) ); set_default_size( 250, 250 ); set_resizable( false ); @@ -53,7 +56,7 @@ SeasonWindow::SeasonWindow( const std::vector< int > &seasons, } m_layout.put( m_label, 5, 5 ); - m_label.set_label( "Select seasons:" ); + m_label.set_label( _( SELECT_SEASONS ) ); m_layout.put( m_confirm, 165, 215 ); m_layout.put( m_all, 130, 175 ); @@ -63,9 +66,9 @@ SeasonWindow::SeasonWindow( const std::vector< int > &seasons, m_all.set_size_request( 80, 30 ); m_none.set_size_request( 80, 30 ); - m_confirm.set_label( "Select" ); - m_all.set_label( "Select All" ); - m_none.set_label( "Unselect All" ); + m_confirm.set_label( _( SELECT ) ); + m_all.set_label( _( SELECT_ALL ) ); + m_none.set_label( _( SELECT_NONE ) ); m_confirm.signal_clicked().connect( sigc::mem_fun( *this, &SeasonWindow::confirm ) ); diff --git a/tv_rename.cpp b/tv_rename.cpp index 7b6c90f..5ea12e9 100644 --- a/tv_rename.cpp +++ b/tv_rename.cpp @@ -4,6 +4,7 @@ #include "filesystem.hpp" #include "functions.hpp" +#include "resources_linux.h" #include "tv_rename.hpp" #include "rapidjson/document.h" @@ -39,7 +40,6 @@ constexpr const char_t *_tv_rename_dir_divider = "/"; #define cerr std::cerr #define cin std::cin -#define TEXT( a ) a #define toString( a ) a #endif @@ -88,7 +88,7 @@ string getShowId( const string &show, const string &language ) { for ( const auto &x : search_results ) { cout << ++order << ". " << x.first << std::endl; } - cout << "Which TV Show is the right one? " << std::flush; + cout << _( WHICH_SHOW ) << " " << std::flush; cin >> pos; cin.clear(); cin.ignore( 1, '\n' ); @@ -168,8 +168,9 @@ std::vector< string > getEpisodeNames( const string &id, const string &season, } } } else { - cerr << "Couldn't find episode names for season " << season - << " of show " << showNameFromId( id, language ) << std::endl; + cerr << _( NOT_FOUND_SHOW_SEASON, season.c_str(), + showNameFromId( id, language ).c_str() ) + << std::endl; } if ( json["links"]["next"].IsNull() ) break; @@ -235,17 +236,17 @@ getRenamedFiles( const string &show, int season, const string id, if ( name[i] == '|' ) { name[i] = '-'; } else if ( name[i] == '<' ) { - name[i] = 'i'; - name.insert( i + 1, TEXT( "s less than" ) ); - max += 11; + name.erase( i, 1 ); + name.insert( i, TEXT( "<" ) ); + max = name.size(); } else if ( name[i] == '>' ) { - name[i] = 'i'; - name.insert( i + 1, TEXT( "s more than" ) ); - max += 11; + name.erase( i, 1 ); + name.insert( i, TEXT( ">" ) ); + max = name.size(); } else if ( name[i] == ':' ) { name[i] = ' '; - name.insert( i + 1, 1, '-' ); - max++; + name.insert( i + 1, TEXT( "- " ) ); + max = name.size(); } } for ( size_t i = 0; i < max; i++ ) { @@ -331,7 +332,7 @@ void singleSeason( const string &path, const string &show, int season, } if ( files_ptr == nullptr ) { - cerr << "Couldn't find episodes with season " << season << std::endl; + cerr << _( NOT_FOUND_FOR_SEASON ) << " " << season << std::endl; return; } @@ -348,12 +349,13 @@ void singleSeason( const string &path, const string &show, int season, } if ( !trust ) { - cout << "Does this seem ok? (y/n) "; + cout << _( CONFIRMATION ) << " (" << _( YES_1 ) << "/" << _( NO_1 ) + << ") " << std::flush; string response; cin >> response; cin.clear(); cin.ignore( 1, '\n' ); - if ( response[0] != 'y' && response[0] != 'Y' ) + if ( response[0] != _( YES_1 )[0] && response[0] != _( YES_2 )[0] ) return; } }