mirror of
https://github.com/c9moser/sgbackup.git
synced 2026-01-19 11:30:13 +00:00
added gettext support
This commit is contained in:
parent
e6a5bd67b7
commit
f16c7c987a
3
.gitignore
vendored
3
.gitignore
vendored
@ -185,3 +185,6 @@ cython_debug/
|
||||
*.temp
|
||||
|
||||
apidoc/
|
||||
|
||||
sgbackup/locale/*/*.po
|
||||
sgbackup/locale/*/*.mo
|
||||
|
||||
11
Makefile
Normal file
11
Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
PO/messages.pot:
|
||||
scripts/extract_loclestrings.sh
|
||||
|
||||
pot:
|
||||
scripts/extract_localestrings.sh
|
||||
|
||||
update-po: PO/messages.pot
|
||||
scripts/update_po.sh
|
||||
|
||||
translations:
|
||||
scripts/make_translations.sh
|
||||
1
PO/LINGUAS
Normal file
1
PO/LINGUAS
Normal file
@ -0,0 +1 @@
|
||||
de
|
||||
30
PO/SOURCES
Normal file
30
PO/SOURCES
Normal file
@ -0,0 +1,30 @@
|
||||
sgbackup/archiver/tarfilearchiver.py
|
||||
sgbackup/archiver/zipfilearchiver.py
|
||||
sgbackup/archiver/_archiver.py
|
||||
sgbackup/archiver/__init__.py
|
||||
sgbackup/command.py
|
||||
sgbackup/commands/help.py
|
||||
sgbackup/commands/__init__.py
|
||||
sgbackup/curses/__init__.py
|
||||
sgbackup/curses/__main__.py
|
||||
sgbackup/game.py
|
||||
sgbackup/gui/_app.py
|
||||
sgbackup/gui/_backupdialog.py
|
||||
sgbackup/gui/_dialogs.py
|
||||
sgbackup/gui/_gamedialog.py
|
||||
sgbackup/gui/_settingsdialog.py
|
||||
sgbackup/gui/_steam.py
|
||||
sgbackup/gui/__init__.py
|
||||
sgbackup/gui/__main__.py
|
||||
sgbackup/help/__init__.py
|
||||
sgbackup/i18n.py
|
||||
sgbackup/locale/__init__.py
|
||||
sgbackup/main.py
|
||||
sgbackup/settings.py
|
||||
sgbackup/steam.py
|
||||
sgbackup/utility.py
|
||||
sgbackup/version.py
|
||||
sgbackup/_import_gtk.py
|
||||
sgbackup/_logging.py
|
||||
sgbackup/__init__.py
|
||||
sgbackup/__main__.py
|
||||
1
PO/UI.SOURCES
Normal file
1
PO/UI.SOURCES
Normal file
@ -0,0 +1 @@
|
||||
sgbackup/gui/appmenu.ui
|
||||
199
PO/de.po
Normal file
199
PO/de.po
Normal file
@ -0,0 +1,199 @@
|
||||
# sgbackup - The SaveGameBackup tool
|
||||
# Copyright (C) 2024,2025
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Christian Moser <christian@cmoser.eu>, 2025.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-03-05 10:15+0100\n"
|
||||
"PO-Revision-Date: 2025-03-05 10:19+0100\n"
|
||||
"Last-Translator: Christian Moser <christian@cmoser.eu>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 3.5\n"
|
||||
|
||||
#: sgbackup/gui/_app.py:224
|
||||
msgid "Add a new game."
|
||||
msgstr "Neues Spiel hinzufügen."
|
||||
|
||||
#: sgbackup/gui/_app.py:232
|
||||
msgid "Manage new Steam-Apps."
|
||||
msgstr "Neue Steam-Apps verwalten."
|
||||
|
||||
#: sgbackup/gui/_app.py:242
|
||||
msgid "Backup all <i>active</i> and <i>live</i> Games."
|
||||
msgstr "Alle <i>aktiven</i> und <i>live</i> Spiele sichern."
|
||||
|
||||
#: sgbackup/gui/_app.py:276
|
||||
msgid "Key"
|
||||
msgstr "Schlüssel"
|
||||
|
||||
#: sgbackup/gui/_app.py:282
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: sgbackup/gui/_app.py:290
|
||||
msgid "Active"
|
||||
msgstr "Aktiv"
|
||||
|
||||
#: sgbackup/gui/_app.py:296 sgbackup/gui/_app.py:864
|
||||
msgid "Live"
|
||||
msgstr "Live"
|
||||
|
||||
#: sgbackup/gui/_app.py:455
|
||||
msgid "No icon-name for sgtype {}"
|
||||
msgstr "Kein Icon-Name für sgtype {}"
|
||||
|
||||
#: sgbackup/gui/_app.py:543
|
||||
#, python-brace-format
|
||||
msgid "Do you want to create a new savegame for <i>{game}</i>?"
|
||||
msgstr "Willst du ein neues SaveGame für <i>{game}</i> erstellen?"
|
||||
|
||||
#: sgbackup/gui/_app.py:545
|
||||
msgid "The new savegame is added to the finsihed savegames for the game."
|
||||
msgstr ""
|
||||
"Das Neue SaveGame wird zu den beendeten Speicherständen für dieses Spiel "
|
||||
"hinzugefügt."
|
||||
|
||||
#: sgbackup/gui/_app.py:557
|
||||
msgid "Backup the SaveGames for this game."
|
||||
msgstr "Sichere das SaveGame für dieses Spiel."
|
||||
|
||||
#: sgbackup/gui/_app.py:569
|
||||
msgid ""
|
||||
"Remove this game.\n"
|
||||
"<span weight='ultrabold'>This also deletes the game configuration file!!!</"
|
||||
"span>"
|
||||
msgstr ""
|
||||
"Lösche dieses Spiel!\n"
|
||||
"<span weight='ultrabold'>Dies wird auch die Konfigurationsdatei des Spiels "
|
||||
"löschen!!!</span>"
|
||||
|
||||
#: sgbackup/gui/_app.py:663
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Do you really want to remove the game <span weight='bold'>{game}</span>?"
|
||||
msgstr "Wills du wirklich das Spiel <span weight='bold'>{game}</span> löschen?"
|
||||
|
||||
#: sgbackup/gui/_app.py:666
|
||||
msgid "Removing games cannot be undone!!!"
|
||||
msgstr "Das Löschen von Spielen kann nicht Rückgängig gemacht werden!!!"
|
||||
|
||||
#: sgbackup/gui/_app.py:859
|
||||
msgid "OS"
|
||||
msgstr "OS"
|
||||
|
||||
#: sgbackup/gui/_app.py:869
|
||||
msgid "Savegame name"
|
||||
msgstr "Speicherstandname"
|
||||
|
||||
#: sgbackup/gui/_app.py:875
|
||||
msgid "Timestamp"
|
||||
msgstr "Zeitstempel"
|
||||
|
||||
#: sgbackup/gui/_app.py:880
|
||||
msgid "Size"
|
||||
msgstr "Größe"
|
||||
|
||||
#: sgbackup/gui/_app.py:1066
|
||||
msgid "%m.%d.%Y %H:%M:%S"
|
||||
msgstr "%d.%m.%Y %H:%M:%S"
|
||||
|
||||
#: sgbackup/gui/_app.py:1099
|
||||
msgid "Restore the SaveGameBackup."
|
||||
msgstr "Stelle das Speicherstandbackup wieder her."
|
||||
|
||||
#: sgbackup/gui/_app.py:1104
|
||||
msgid "Convert to another SaveGameBackup."
|
||||
msgstr "Konvertiere zu anderen Speicherstandbackup"
|
||||
|
||||
#: sgbackup/gui/_app.py:1113
|
||||
msgid "Delete this SaveGameBackup."
|
||||
msgstr "Lösche dieses Speicherstandbackup."
|
||||
|
||||
#: sgbackup/gui/_app.py:1170
|
||||
msgid "SGBackup"
|
||||
msgstr "SGBackup"
|
||||
|
||||
#: sgbackup/gui/_app.py:1232 sgbackup/gui/_app.py:1300
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{games} Games -- {active} Games active -- {live} Games live -- {finished} "
|
||||
"Games finished"
|
||||
msgstr ""
|
||||
"{games} Spile -- {active} Spiele aktiv -- {live} Spiele live -- {finished} "
|
||||
"Spiele beendet"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:6
|
||||
msgid "_Game"
|
||||
msgstr "_Spiel"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:9
|
||||
msgid "_Add Game"
|
||||
msgstr "Spiel _hinzufügen"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:14
|
||||
msgid "_Steam"
|
||||
msgstr "_Steam"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:17
|
||||
msgid "New Steam Apps"
|
||||
msgstr "Neue Steam-App"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:21
|
||||
msgid "Manage Steam Libraries"
|
||||
msgstr "Steam Bibliotheken verwalten"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:27
|
||||
msgid "_Epic"
|
||||
msgstr "_Epic"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:30
|
||||
msgid "_GoG"
|
||||
msgstr "_GoG"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:35
|
||||
msgid "_Settings"
|
||||
msgstr "_Einstellungen"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:42
|
||||
msgid "_Help"
|
||||
msgstr "_Hilfe"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:47
|
||||
msgid "_About SGBackup"
|
||||
msgstr "_Über SGBackup"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:56
|
||||
msgid "_Quit"
|
||||
msgstr "_Beenden"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:65
|
||||
msgid "Convert to _Windows"
|
||||
msgstr "Nach _Windows konvertieren"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:69
|
||||
msgid "Convert to _Linux"
|
||||
msgstr "Nach _Linux konvertieren"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:73
|
||||
msgid "Convert to _Mac OS"
|
||||
msgstr "Nach _MacOS konvertieren"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:77
|
||||
msgid "Convert to _Steam Windows"
|
||||
msgstr "Nach _Steam-Windows konvertieren"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:81
|
||||
msgid "Convert to Steam Linux"
|
||||
msgstr "Nach _Steam-Linux konvertieren"
|
||||
|
||||
#: sgbackup/gui/appmenu.ui:85
|
||||
msgid "Convert to Steam Mac OS"
|
||||
msgstr "Nach _Steam-MacOS konvertieren"
|
||||
@ -25,6 +25,19 @@ fi
|
||||
. "$venv/bin/activate"
|
||||
|
||||
cd $PROJECT_DIR
|
||||
|
||||
# translations
|
||||
make translations
|
||||
MSYS_LOCALEDIR="${MSYSTEM_PREFIX}/share/locale"
|
||||
for i in $( cat "$PROJECT_ROOT/LINGUAS" ); do
|
||||
mo="${PROJECT_ROOT}/sgbackup/locale/${i}/sgbackup.mo"
|
||||
localedir="${MSYS_LOCALEDIR}/${i}/LC_MESSAGES"
|
||||
|
||||
[ ! -d "$localedir" ] && mkdir -p "$localedir"
|
||||
cp -v "$mo" "$localedir"
|
||||
done
|
||||
|
||||
# install
|
||||
pip install --verbose --user .
|
||||
|
||||
bindir=$( realpath "$venv/bin" )
|
||||
|
||||
24
scripts/extract_localestrings.sh
Executable file
24
scripts/extract_localestrings.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
self="$( realpath "$0" )"
|
||||
scriptdir="$( dirname "$self" )"
|
||||
project_root="$( dirname "$( dirname "$self" )" )"
|
||||
|
||||
PO_DIR="${project_root}/PO"
|
||||
|
||||
cd "$prject_root"
|
||||
sources="${PO_DIR}/SOURCES"
|
||||
ui_sources="${PO_DIR}/UI.SOURCES"
|
||||
pot_file="${PO_DIR}/messages.pot"
|
||||
|
||||
[ -f "$sources" ] && rm "$sources"
|
||||
[ -f "$ui_sources" ] && rm "$ui_sources"
|
||||
|
||||
for i in $( find "./sgbackup" | egrep '\.py$' ); do
|
||||
echo "${i#./}" >> "$sources"
|
||||
done
|
||||
for i in $( find "./sgbackup" | egrep '\.ui$' ); do
|
||||
echo "${i#./}" >> "$ui_sources"
|
||||
done
|
||||
|
||||
/usr/bin/xgettext -o "$pot_file" --force-po -l Python -c -k_ -kN_ -kQ_ -f "$sources" --color=auto -n --copyright-holder="sgbackup Team" --package-name="sgbackup"
|
||||
/usr/bin/xgettext -o "$pot_file" -l Glade -j -f "$ui_sources" --color=auto -n
|
||||
21
scripts/make_translations.sh
Executable file
21
scripts/make_translations.sh
Executable file
@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
self="$( realpath "$0" )"
|
||||
scriptdir="$( dirname "$self" )"
|
||||
project_root="$( dirname "$( dirname "$self" )" )"
|
||||
|
||||
PO_DIR="${project_root}/PO"
|
||||
LINGUAS="${PO_DIR}/LINGUAS"
|
||||
LOCALEDIR="${project_root}/sgbackup/locale"
|
||||
|
||||
for i in $( cat "$LINGUAS" );do
|
||||
po="${PO_DIR}/${i}.po"
|
||||
|
||||
[ ! -f "$po" ] && continue
|
||||
|
||||
msgdir="${LOCALEDIR}/${i}/LC_MESSAGES"
|
||||
mo="${msgdir}/sgbackup.mo"
|
||||
|
||||
[ ! -d $msgdir ] && mkdir -pv "$msgdir"
|
||||
|
||||
msgfmt -o "$mo" "$po"
|
||||
done
|
||||
18
scripts/update_po.sh
Executable file
18
scripts/update_po.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
self="$( realpath "$0" )"
|
||||
scriptdir="$( dirname "$0" )"
|
||||
project_root="$( dirname "$(dirname "$self" )" )"
|
||||
|
||||
PO_DIR="${project_root}/PO"
|
||||
LINGUAS="${PO_DIR}/LINGUAS"
|
||||
|
||||
pot_file="${PO_DIR}/messages.pot"
|
||||
|
||||
for i in $( cat "$LINGUAS" ); do
|
||||
po="${PO_DIR}/${i}.po"
|
||||
if [ ! -f "$po" ]; then
|
||||
cp "$pot_file" "$po"
|
||||
else
|
||||
msgmerge --update --previous --lang="$i" "$po" "$pot_file"
|
||||
fi
|
||||
done
|
||||
5
setup.py
5
setup.py
@ -28,6 +28,7 @@ setup(
|
||||
'sgbackup.curses',
|
||||
'sgbackup.help',
|
||||
'sgbackup.gui',
|
||||
'sgbackup.locale',
|
||||
],
|
||||
package_data={
|
||||
'sgbackup':[
|
||||
@ -38,6 +39,10 @@ setup(
|
||||
'sgbackup.gui': [
|
||||
'*.ui'
|
||||
],
|
||||
'sgbackup.locale': [
|
||||
'*/*.mo',
|
||||
'*/LC_MESSAGES/*.po',
|
||||
],
|
||||
},
|
||||
platforms=['win32','linux']
|
||||
)
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
|
||||
from gi.repository import Gtk,Gio,Gdk,GLib
|
||||
from gi.repository.GObject import GObject,Signal,Property,SignalFlags,BindingFlags
|
||||
from ..i18n import gettext as _, noop as N_,pgettext,npgettext,ngettext
|
||||
|
||||
import rapidfuzz
|
||||
|
||||
import logging; logger=logging.getLogger(__name__)
|
||||
@ -30,7 +32,14 @@ from ..settings import settings
|
||||
from ._settingsdialog import SettingsDialog
|
||||
from ._gamedialog import GameDialog
|
||||
from ..game import Game,GameManager,SAVEGAME_TYPE_ICONS,SavegameType
|
||||
from ._steam import SteamLibrariesDialog,NewSteamAppsDialog,NoNewSteamAppsDialog
|
||||
from ._steam import (
|
||||
SteamLibrariesDialog,
|
||||
NewSteamAppsDialog,
|
||||
NoNewSteamAppsDialog,
|
||||
NoIgnoredSteamAppsDialog,
|
||||
SteamIgnoreAppsDialog,
|
||||
)
|
||||
|
||||
from ..steam import Steam
|
||||
from ._backupdialog import BackupSingleDialog,BackupManyDialog
|
||||
from ..archiver import ArchiverManager
|
||||
@ -160,23 +169,6 @@ class GameViewNameSorter(Gtk.Sorter):
|
||||
else:
|
||||
return Gtk.Ordering.EQUAL
|
||||
|
||||
class GameViewColumnSorter(Gtk.ColumnViewSorter):
|
||||
def __init__(self,*args,**kwargs):
|
||||
Gtk.ColumnViewSorter.__init__(self,*args,**kwargs)
|
||||
self.__key_sorter = GameViewKeySorter
|
||||
self.__name_sorter = GameViewNameSorter
|
||||
|
||||
def do_compare(self,item1,item2):
|
||||
game1 = item1.game
|
||||
game2 = item2.game
|
||||
column = self.get_primary_sort_column()
|
||||
sort_ascending = (self.get_primary_sort_order() == Gtk.SortType.ASCENDING)
|
||||
if column == 1:
|
||||
self.__key_sorter.sort_ascending == sort_ascending
|
||||
return self.__key_sorter.do_compare(game1,game2)
|
||||
else:
|
||||
self.__name_sorter.sort_ascending = sort_ascending
|
||||
return self.__name_sorter.do_comapre(game1,game2)
|
||||
|
||||
class GameViewMatchSorter(Gtk.Sorter):
|
||||
def do_compare(self,item1:GameViewData,item2:GameViewData):
|
||||
@ -229,16 +221,15 @@ class GameView(Gtk.Box):
|
||||
icon.set_pixel_size(16)
|
||||
add_game_button=Gtk.Button()
|
||||
add_game_button.set_child(icon)
|
||||
add_game_button.set_tooltip_text("Add a new game.")
|
||||
add_game_button.set_tooltip_text(_("Add a new game."))
|
||||
add_game_button.connect('clicked',self._on_add_game_button_clicked)
|
||||
self.actionbar.pack_start(add_game_button)
|
||||
|
||||
|
||||
|
||||
icon = Gtk.Image.new_from_icon_name('steam-svgrepo-com-symbolic')
|
||||
icon.set_pixel_size(16)
|
||||
new_steam_games_button=Gtk.Button()
|
||||
new_steam_games_button.set_child(icon)
|
||||
new_steam_games_button.set_tooltip_text("Manage new Steam-Apps.")
|
||||
new_steam_games_button.set_tooltip_text(_("Manage new Steam-Apps."))
|
||||
new_steam_games_button.connect('clicked',self._on_new_steam_games_button_clicked)
|
||||
self.actionbar.pack_start(new_steam_games_button)
|
||||
|
||||
@ -248,7 +239,7 @@ class GameView(Gtk.Box):
|
||||
icon.set_pixel_size(16)
|
||||
backup_active_live_button = Gtk.Button()
|
||||
backup_active_live_button.set_child(icon)
|
||||
backup_active_live_button.set_tooltip_markup("Backup all <i>active</i> and <i>live</i> Games.")
|
||||
backup_active_live_button.set_tooltip_markup(_("Backup all <i>active</i> and <i>live</i> Games."))
|
||||
backup_active_live_button.connect('clicked',self._on_backup_active_live_button_clicked)
|
||||
self.actionbar.pack_start(backup_active_live_button)
|
||||
|
||||
@ -267,8 +258,10 @@ class GameView(Gtk.Box):
|
||||
self.__columnview = Gtk.ColumnView()
|
||||
columnview_sorter = self.columnview.get_sorter()
|
||||
self.__liststore = Gio.ListStore.new(GameViewData)
|
||||
for g in GameManager.get_global().games.values():
|
||||
self.__liststore.append(GameViewData(g))
|
||||
|
||||
gamemanager = GameManager.get_global()
|
||||
for g in gamemanager.games.values():
|
||||
self._liststore.append(GameViewData(g))
|
||||
self.__filter_model = Gtk.FilterListModel.new(self._liststore,None)
|
||||
self.__sort_model = Gtk.SortListModel.new(self.__filter_model,columnview_sorter)
|
||||
|
||||
@ -280,13 +273,13 @@ class GameView(Gtk.Box):
|
||||
factory_key = Gtk.SignalListItemFactory.new()
|
||||
factory_key.connect('setup',self._on_key_column_setup)
|
||||
factory_key.connect('bind',self._on_key_column_bind)
|
||||
column_key = Gtk.ColumnViewColumn.new("Key",factory_key)
|
||||
column_key = Gtk.ColumnViewColumn.new(_("Key"),factory_key)
|
||||
column_key.set_sorter(GameViewKeySorter())
|
||||
|
||||
factory_name = Gtk.SignalListItemFactory.new()
|
||||
factory_name.connect('setup',self._on_name_column_setup)
|
||||
factory_name.connect('bind',self._on_name_column_bind)
|
||||
column_name = Gtk.ColumnViewColumn.new("Name",factory_name)
|
||||
column_name = Gtk.ColumnViewColumn.new(_("Name"),factory_name)
|
||||
column_name.set_sorter(GameViewNameSorter())
|
||||
column_name.set_expand(True)
|
||||
|
||||
@ -294,13 +287,13 @@ class GameView(Gtk.Box):
|
||||
factory_active.connect('setup',self._on_active_column_setup)
|
||||
factory_active.connect('bind',self._on_active_column_bind)
|
||||
factory_active.connect('unbind',self._on_active_column_unbind)
|
||||
column_active = Gtk.ColumnViewColumn.new("Active",factory_active)
|
||||
column_active = Gtk.ColumnViewColumn.new(_("Active"),factory_active)
|
||||
|
||||
factory_live = Gtk.SignalListItemFactory.new()
|
||||
factory_live.connect('setup',self._on_live_column_setup)
|
||||
factory_live.connect('bind',self._on_live_column_bind)
|
||||
factory_live.connect('unbind',self._on_live_column_unbind)
|
||||
column_live = Gtk.ColumnViewColumn.new("Live",factory_live)
|
||||
column_live = Gtk.ColumnViewColumn.new(_("Live"),factory_live)
|
||||
|
||||
factory_actions = Gtk.SignalListItemFactory.new()
|
||||
factory_actions.connect('setup',self._on_actions_column_setup)
|
||||
@ -308,15 +301,11 @@ class GameView(Gtk.Box):
|
||||
#factory_actions.connect('unbind',self._on_actions_column_unbind)
|
||||
column_actions = Gtk.ColumnViewColumn.new("",factory_actions)
|
||||
|
||||
self.__selection_model = Gtk.SingleSelection()
|
||||
self.__selection_model.set_autoselect(False)
|
||||
self.__selection_model.set_can_unselect(True)
|
||||
self.__selection_model.set_model(self.__sort_model)
|
||||
self.columnview.set_model(self.__selection_model)
|
||||
|
||||
self.__selection_model = Gtk.SingleSelection(autoselect=False,can_unselect=True,model=self.__sort_model)
|
||||
|
||||
self.columnview.set_vexpand(True)
|
||||
self.columnview.set_hexpand(True)
|
||||
self.columnview.set_single_click_activate(True)
|
||||
self.columnview.append_column(column_icon)
|
||||
self.columnview.append_column(column_key)
|
||||
self.columnview.append_column(column_name)
|
||||
@ -324,16 +313,18 @@ class GameView(Gtk.Box):
|
||||
self.columnview.append_column(column_live)
|
||||
self.columnview.append_column(column_actions)
|
||||
self.columnview.sort_by_column(column_name,Gtk.SortType.ASCENDING)
|
||||
self.columnview.set_single_click_activate(True)
|
||||
self.columnview.get_vadjustment().set_value(0)
|
||||
self.columnview.set_model(self.__selection_model)
|
||||
|
||||
|
||||
cv_vadjustment = self.columnview.get_vadjustment()
|
||||
cv_vadjustment.set_value(cv_vadjustment.get_lower())
|
||||
scrolled.set_child(self.columnview)
|
||||
self.append(scrolled)
|
||||
|
||||
@property
|
||||
def _liststore(self)->Gio.ListStore:
|
||||
"""
|
||||
The `Gio.ListStore` that holds the list of installed games.
|
||||
|
||||
The `Gio.ListStore` that holds the list of registered games.
|
||||
|
||||
:type: Gio.ListStore
|
||||
"""
|
||||
@ -461,7 +452,7 @@ class GameView(Gtk.Box):
|
||||
def transform_to_icon_name(_binding,sgtype):
|
||||
icon_name = SAVEGAME_TYPE_ICONS[sgtype] if sgtype in SAVEGAME_TYPE_ICONS else ""
|
||||
if not icon_name:
|
||||
logger.warning("No icon-name for sgtype {}".format(sgtype.value))
|
||||
logger.warning(_("No icon-name for sgtype {}").format(sgtype.value))
|
||||
return icon_name
|
||||
|
||||
icon = item.get_child()
|
||||
@ -549,9 +540,9 @@ class GameView(Gtk.Box):
|
||||
if not game.is_live:
|
||||
dialog = Gtk.MessageDialog(buttons=Gtk.ButtonsType.YES_NO)
|
||||
dialog.set_transient_for(self.get_root())
|
||||
dialog.props.text = "Do you want to create a new savegame for <i>{game}</i>?".format(game=game.name)
|
||||
dialog.props.text = _("Do you want to create a new savegame for <i>{game}</i>?").format(game=game.name)
|
||||
dialog.props.use_markup = True
|
||||
dialog.props.secondary_text = "The new savegame is added to the finsihed savegames for the game."
|
||||
dialog.props.secondary_text = _("The new savegame is added to the finsihed savegames for the game.")
|
||||
dialog.props.secondary_use_markup = False
|
||||
dialog.connect('response',on_dialog_response)
|
||||
dialog.present()
|
||||
@ -563,7 +554,7 @@ class GameView(Gtk.Box):
|
||||
icon = Gtk.Image.new_from_icon_name('document-save-symbolic')
|
||||
child.backup_button = Gtk.Button()
|
||||
child.backup_button.set_child(icon)
|
||||
child.backup_button.set_tooltip_text("Backup the SaveGames for this game.")
|
||||
child.backup_button.set_tooltip_text(_("Backup the SaveGames for this game."))
|
||||
child.append(child.backup_button)
|
||||
|
||||
icon = Gtk.Image.new_from_icon_name('document-edit-symbolic')
|
||||
@ -575,7 +566,7 @@ class GameView(Gtk.Box):
|
||||
icon = Gtk.Image.new_from_icon_name('list-remove-symbolic')
|
||||
child.remove_button = Gtk.Button()
|
||||
child.remove_button.set_child(icon)
|
||||
child.remove_button.set_tooltip_markup("Remove this game.\n<span weight='ultrabold'>This also deletes the game configuration file!!!</span>")
|
||||
child.remove_button.set_tooltip_markup(_("Remove this game.\n<span weight='ultrabold'>This also deletes the game configuration file!!!</span>"))
|
||||
child.append(child.remove_button)
|
||||
|
||||
item.set_child(child)
|
||||
@ -669,10 +660,10 @@ class GameView(Gtk.Box):
|
||||
|
||||
game = item.get_item().game
|
||||
dialog = Gtk.MessageDialog(buttons=Gtk.ButtonsType.YES_NO,
|
||||
text="Do you really want to remove the game <span weight='bold'>{game}</span>?".format(
|
||||
text=_("Do you really want to remove the game <span weight='bold'>{game}</span>?").format(
|
||||
game=game.name),
|
||||
use_markup=True,
|
||||
secondary_text="Removing games cannot be undone!!!")
|
||||
secondary_text=_("Removing games cannot be undone!!!"))
|
||||
dialog.set_transient_for(self.get_root())
|
||||
dialog.set_modal(False)
|
||||
dialog.connect('response',on_dialog_response,game)
|
||||
@ -692,10 +683,16 @@ class BackupViewData(GObject):
|
||||
basename = os.path.basename(filename)
|
||||
parts = basename.split('.')
|
||||
|
||||
self.__savegame_name = parts[0]
|
||||
self.__timestamp = DateTime.strptime(parts[1],"%Y%m%d-%H%M%S")
|
||||
self.__is_live = parts[3] == 'live'
|
||||
self.__sgtype = SavegameType.from_string(parts[2])
|
||||
try:
|
||||
self.__savegame_name = parts[0]
|
||||
self.__timestamp = DateTime.strptime(parts[1],"%Y%m%d-%H%M%S")
|
||||
self.__sgtype = SavegameType.from_string(parts[2])
|
||||
self.__is_live = parts[3] == 'live'
|
||||
except:
|
||||
self.__savegame_name = basename
|
||||
self.__timestamp = "Unknown"
|
||||
self.__sgtype = SavegameType.UNSET
|
||||
self.__is_live = True
|
||||
|
||||
|
||||
WINDOWS_TYPES = [
|
||||
@ -859,28 +856,28 @@ class BackupView(Gtk.Box):
|
||||
sgos_factory = Gtk.SignalListItemFactory()
|
||||
sgos_factory.connect('setup',self._on_sgos_column_setup)
|
||||
sgos_factory.connect('bind',self._on_sgos_column_bind)
|
||||
sgos_column = Gtk.ColumnViewColumn.new("OS",sgos_factory)
|
||||
sgos_column = Gtk.ColumnViewColumn.new(_("OS"),sgos_factory)
|
||||
|
||||
live_factory = Gtk.SignalListItemFactory()
|
||||
live_factory.connect('setup',self._on_live_column_setup)
|
||||
live_factory.connect('bind',self._on_live_column_bind)
|
||||
live_column = Gtk.ColumnViewColumn.new("Live",live_factory)
|
||||
live_column = Gtk.ColumnViewColumn.new(_("Live"),live_factory)
|
||||
|
||||
sgname_factory = Gtk.SignalListItemFactory()
|
||||
sgname_factory.connect('setup',self._on_savegamename_column_setup)
|
||||
sgname_factory.connect('bind',self._on_savegamename_column_bind)
|
||||
sgname_column = Gtk.ColumnViewColumn.new("Savegame name",sgname_factory)
|
||||
sgname_column = Gtk.ColumnViewColumn.new(_("Savegame name"),sgname_factory)
|
||||
sgname_column.set_expand(True)
|
||||
|
||||
timestamp_factory = Gtk.SignalListItemFactory()
|
||||
timestamp_factory.connect('setup',self._on_timestamp_column_setup)
|
||||
timestamp_factory.connect('bind',self._on_timestamp_column_bind)
|
||||
timestamp_column = Gtk.ColumnViewColumn.new("Timestamp",timestamp_factory)
|
||||
timestamp_column = Gtk.ColumnViewColumn.new(_("Timestamp"),timestamp_factory)
|
||||
|
||||
size_factory = Gtk.SignalListItemFactory()
|
||||
size_factory.connect('setup',self._on_size_column_setup)
|
||||
size_factory.connect('bind',self._on_size_column_bind)
|
||||
size_column = Gtk.ColumnViewColumn.new("Size",size_factory)
|
||||
size_column = Gtk.ColumnViewColumn.new(_("Size"),size_factory)
|
||||
|
||||
actions_factory = Gtk.SignalListItemFactory()
|
||||
actions_factory.connect('setup',self._on_actions_column_setup)
|
||||
@ -1066,7 +1063,7 @@ class BackupView(Gtk.Box):
|
||||
label = item.get_child()
|
||||
data = item.get_item()
|
||||
label.set_markup("<span size=\"large\">{}</span>".format(
|
||||
GLib.markup_escape_text(data.timestamp.strftime("%d.%m.%Y %H:%M:%S"))))
|
||||
GLib.markup_escape_text(data.timestamp.strftime(_("%m.%d.%Y %H:%M:%S")))))
|
||||
|
||||
def _on_size_column_setup(self,factory,item):
|
||||
label = Gtk.Label()
|
||||
@ -1099,12 +1096,12 @@ class BackupView(Gtk.Box):
|
||||
icon = Gtk.Image.new_from_icon_name('document-revert-symbolic')
|
||||
icon.set_pixel_size(16)
|
||||
child.restore_button.set_child(icon)
|
||||
child.restore_button.set_tooltip_text("Restore the SaveGameBackup.")
|
||||
child.restore_button.set_tooltip_text(_("Restore the SaveGameBackup."))
|
||||
child.append(child.restore_button)
|
||||
|
||||
child.convert_button = Gtk.MenuButton()
|
||||
child.convert_button.set_icon_name('document-properties-symbolic')
|
||||
child.convert_button.set_tooltip_text("Convert to another SaveGameBackup.")
|
||||
child.convert_button.set_tooltip_text(_("Convert to another SaveGameBackup."))
|
||||
child.convert_button.set_menu_model(self.__convertmenu)
|
||||
child.convert_button.set_direction(Gtk.ArrowType.UP)
|
||||
child.append(child.convert_button)
|
||||
@ -1113,7 +1110,7 @@ class BackupView(Gtk.Box):
|
||||
icon = Gtk.Image.new_from_icon_name('list-remove-symbolic')
|
||||
icon.set_pixel_size(16)
|
||||
child.delete_button.set_child(icon)
|
||||
child.delete_button.set_tooltip_text("Delete this SaveGameBackup.")
|
||||
child.delete_button.set_tooltip_text(_("Delete this SaveGameBackup."))
|
||||
child.append(child.delete_button)
|
||||
|
||||
item.set_child(child)
|
||||
@ -1170,7 +1167,7 @@ class AppWindow(Gtk.ApplicationWindow):
|
||||
:param application: The `Application` this window belongs to, defaults to `None`.
|
||||
:type application: Application, optional
|
||||
"""
|
||||
kwargs['title'] = "SGBackup"
|
||||
kwargs['title'] = _("SGBackup")
|
||||
|
||||
if (application is not None):
|
||||
kwargs['application']=application
|
||||
@ -1232,7 +1229,7 @@ class AppWindow(Gtk.ApplicationWindow):
|
||||
if game.is_active:
|
||||
n_active += 1
|
||||
|
||||
self.statusbar.push(0,'{games} Games -- {active} Games active -- {live} Games live -- {finished} Games finished'.format(
|
||||
self.statusbar.push(0,_('{games} Games -- {active} Games active -- {live} Games live -- {finished} Games finished').format(
|
||||
games=n_games,
|
||||
active=n_active,
|
||||
live=n_live,
|
||||
@ -1300,7 +1297,7 @@ class AppWindow(Gtk.ApplicationWindow):
|
||||
if game.is_active:
|
||||
n_active += 1
|
||||
|
||||
self.statusbar.push(0,'{games} Games -- {active} Games active -- {live} Games live -- {finished} Games finished'.format(
|
||||
self.statusbar.push(0,_('{games} Games -- {active} Games active -- {live} Games live -- {finished} Games finished').format(
|
||||
games=n_games,
|
||||
active=n_active,
|
||||
live=n_live,
|
||||
@ -1385,6 +1382,10 @@ class Application(Gtk.Application):
|
||||
action_steam_new_apps.connect('activate',self._on_action_steam_new_apps)
|
||||
self.add_action(action_steam_new_apps)
|
||||
|
||||
action_steam_manage_ignore = Gio.SimpleAction.new('steam-manage-ignore',None)
|
||||
action_steam_manage_ignore.connect('activate',self._on_action_steam_manage_ignore)
|
||||
self.add_action(action_steam_manage_ignore)
|
||||
|
||||
# add accels
|
||||
self.set_accels_for_action('app.quit',["<Primary>q"])
|
||||
|
||||
@ -1446,6 +1447,21 @@ class Application(Gtk.Application):
|
||||
dialog = NoNewSteamAppsDialog(self.appwindow)
|
||||
dialog.present()
|
||||
|
||||
def _on_steam_ignore_apps_dialog_response(self,dialog,response):
|
||||
self.appwindow.refresh()
|
||||
|
||||
def _on_action_steam_manage_ignore(self,action,param):
|
||||
|
||||
steam = Steam()
|
||||
if not steam.ignore_apps:
|
||||
dialog = NoIgnoredSteamAppsDialog(self.appwindow)
|
||||
dialog.present()
|
||||
else:
|
||||
dialog = SteamIgnoreAppsDialog(self.appwindow)
|
||||
dialog.connect_after("response",self._on_steam_ignore_apps_dialog_response)
|
||||
|
||||
dialog.present()
|
||||
|
||||
def new_settings_dialog(self)->SettingsDialog:
|
||||
"""
|
||||
new_settings_dialog Create a new `SettingsDialog`.
|
||||
|
||||
@ -414,4 +414,32 @@ class NoNewSteamAppsDialog(Gtk.MessageDialog):
|
||||
|
||||
def do_response(self,response):
|
||||
self.hide()
|
||||
self.destroy()
|
||||
self.destroy()
|
||||
|
||||
class NoIgnoredSteamAppsDialog(Gtk.MessageDialog):
|
||||
def __init__(self,parent:Gtk.Window|None=None):
|
||||
Gtk.MessageDialog.__init__(self,buttons=Gtk.ButtonsType.OK)
|
||||
if parent:
|
||||
self.set_transient_for(parent)
|
||||
|
||||
self.props.text = "There are no Steam-Apps that are ignored!"
|
||||
self.props.use_markup = False
|
||||
|
||||
def do_response(self,response):
|
||||
self.hide()
|
||||
self.destroy()
|
||||
|
||||
|
||||
class SteamIgnoreAppsDialog(Gtk.Dialog):
|
||||
def __init__(self,parent:Gtk.Window|None=None):
|
||||
Gtk.Dialog.__init__(self)
|
||||
if parent:
|
||||
self.set_transient_for(parent)
|
||||
self.set_modal(False)
|
||||
|
||||
self.add_button("Close",Gtk.ResponseType.OK)
|
||||
|
||||
def do_response(self,response):
|
||||
self.hide()
|
||||
self.destroy()
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
<section id='appmenu.help.about'>
|
||||
<item>
|
||||
<attribute name='label' translatable='true'>_About SGBackup</attribute>
|
||||
<attribute name='action' translatable='true'>app.about</attribute>
|
||||
<attribute name='action'>app.about</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</submenu>
|
||||
|
||||
30
sgbackup/i18n.py
Normal file
30
sgbackup/i18n.py
Normal file
@ -0,0 +1,30 @@
|
||||
###############################################################################
|
||||
# sgbackup - The SaveGame Backup tool #
|
||||
# Copyright (C) 2024,2025 Christian Moser #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||
###############################################################################
|
||||
|
||||
from os.path import dirname,join
|
||||
import gettext as _gettext
|
||||
|
||||
TEXTDOMAIN="sgbackup"
|
||||
|
||||
_gettext.bindtextdomain(TEXTDOMAIN,join(dirname(__file__),'locale'))
|
||||
|
||||
gettext = lambda s: _gettext.dgettext(TEXTDOMAIN,s)
|
||||
pgettext = lambda context,s: _gettext.dpgettext(TEXTDOMAIN,context,s)
|
||||
ngettext = lambda singular,plural,n: _gettext.dngettext(TEXTDOMAIN,singular,plural,n)
|
||||
npgettext = lambda context,singular,plural,n: _gettext.dnpgettext(TEXTDOMAIN,context,singular,plural,n)
|
||||
noop = lambda s: s
|
||||
1
sgbackup/locale/__init__.py
Normal file
1
sgbackup/locale/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# just here to make a package
|
||||
Loading…
Reference in New Issue
Block a user