forked from Boria138/PortProtonQt
		
	Compare commits
	
		
			5 Commits
		
	
	
		
			be9ecf5db6
			...
			d7ab7dc7ce
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d7ab7dc7ce | |||
| 82a93abb7d | |||
| 25439889f7 | |||
| 4e5ccfc374 | |||
| 3d87718072 | 
| @@ -10,6 +10,7 @@ | ||||
| - Начальная поддержка EGS (Без EOS, скачивания игр и запуска игр из сторонних магазинов) | ||||
| - Автодополнение bash для комманды portprotonqt | ||||
| - Поддержка геймпадов в диалоге выбора игры | ||||
| - Быстрый запуск игры через контекстное меню | ||||
|  | ||||
| ### Changed | ||||
| - Удалены сборки для Fedora 40 | ||||
|   | ||||
| @@ -20,9 +20,9 @@ Current translation status: | ||||
|  | ||||
| | Locale | Progress | Translated | | ||||
| | :----- | -------: | ---------: | | ||||
| | [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 of 182 | | ||||
| | [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 of 182 | | ||||
| | [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 182 of 182 | | ||||
| | [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 of 183 | | ||||
| | [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 of 183 | | ||||
| | [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 183 of 183 | | ||||
|  | ||||
| --- | ||||
|  | ||||
|   | ||||
| @@ -20,9 +20,9 @@ | ||||
|  | ||||
| | Локаль | Прогресс | Переведено | | ||||
| | :----- | -------: | ---------: | | ||||
| | [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 из 182 | | ||||
| | [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 из 182 | | ||||
| | [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 182 из 182 | | ||||
| | [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 из 183 | | ||||
| | [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 из 183 | | ||||
| | [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 183 из 183 | | ||||
|  | ||||
| --- | ||||
|  | ||||
|   | ||||
| @@ -129,6 +129,11 @@ class ContextMenuManager: | ||||
|         menu = QMenu(self.parent) | ||||
|         menu.setStyleSheet(self.theme.CONTEXT_MENU_STYLE) | ||||
|  | ||||
|         launch_action = menu.addAction(_("Launch Game")) | ||||
|         launch_action.triggered.connect( | ||||
|             lambda: self._launch_game(game_card) | ||||
|         ) | ||||
|  | ||||
|         favorites = read_favorites() | ||||
|         is_favorite = game_card.name in favorites | ||||
|         favorite_action = menu.addAction( | ||||
| @@ -219,6 +224,40 @@ class ContextMenuManager: | ||||
|  | ||||
|         menu.exec(game_card.mapToGlobal(pos)) | ||||
|  | ||||
|     def _launch_game(self, game_card): | ||||
|         """ | ||||
|         Launch a game using a validated exec_line, handling EGS games specifically. | ||||
|  | ||||
|         Args: | ||||
|             game_card: The GameCard instance containing game data. | ||||
|         """ | ||||
|         if not self._check_portproton(): | ||||
|             return | ||||
|         if game_card.game_source == "epic": | ||||
|             if not os.path.exists(self.legendary_path): | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("Legendary executable not found at {path}").format(path=self.legendary_path) | ||||
|                 ) | ||||
|                 return | ||||
|             # Construct EGS launch command | ||||
|             wrapper = "flatpak run ru.linux_gaming.PortProton" | ||||
|             start_sh_path = os.path.join(self.portproton_location, "data", "scripts", "start.sh") | ||||
|             if self.portproton_location and ".var" not in self.portproton_location: | ||||
|                 wrapper = start_sh_path | ||||
|                 if not os.path.exists(start_sh_path): | ||||
|                     self.signals.show_warning_dialog.emit( | ||||
|                         _("Error"), | ||||
|                         _("start.sh not found at {path}").format(path=start_sh_path) | ||||
|                     ) | ||||
|                     return | ||||
|             exec_line = f'"{self.legendary_path}" launch {game_card.appid} --no-wine --wrapper "env START_FROM_STEAM=1 {wrapper}"' | ||||
|         else: | ||||
|             exec_line = self._get_exec_line(game_card.name, game_card.exec_line) | ||||
|             if not exec_line: | ||||
|                 return | ||||
|         self.parent.toggleGame(exec_line) | ||||
|  | ||||
|     def add_egs_to_steam(self, game_name: str, app_name: str): | ||||
|         """ | ||||
|         Adds an EGS game to Steam using the egs_api. | ||||
|   | ||||
| @@ -3,7 +3,7 @@ import tempfile | ||||
| from typing import cast, TYPE_CHECKING | ||||
| from PySide6.QtGui import QPixmap, QIcon | ||||
| from PySide6.QtWidgets import ( | ||||
|     QDialog, QLineEdit, QFormLayout, QHBoxLayout, QLabel, QVBoxLayout, QListWidget, QScrollArea, QWidget, QListWidgetItem, QSizePolicy | ||||
|     QDialog, QLineEdit, QFormLayout, QHBoxLayout, QLabel, QVBoxLayout, QListWidget, QScrollArea, QWidget, QListWidgetItem, QSizePolicy, QApplication | ||||
| ) | ||||
| from PySide6.QtCore import Qt, QObject, Signal, QMimeDatabase, QTimer | ||||
| from icoextract import IconExtractor, IconExtractorError | ||||
| @@ -167,6 +167,7 @@ class FileExplorer(QDialog): | ||||
|         self.drives_scroll.setFixedHeight(70) | ||||
|         self.main_layout.addWidget(self.drives_scroll) | ||||
|         self.drives_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) | ||||
|         self.drives_scroll.setFocusPolicy(Qt.FocusPolicy.StrongFocus)  # Allow focus on scroll area | ||||
|  | ||||
|         # Путь | ||||
|         self.path_label = QLabel() | ||||
| @@ -177,7 +178,7 @@ class FileExplorer(QDialog): | ||||
|         self.file_list = QListWidget() | ||||
|         self.file_list.setStyleSheet(self.theme.FILE_EXPLORER_STYLE) | ||||
|         self.file_list.itemClicked.connect(self.handle_item_click) | ||||
|         self.file_list.itemDoubleClicked.connect(self.handle_item_double_click)  # Подключение двойного клика | ||||
|         self.file_list.itemDoubleClicked.connect(self.handle_item_double_click) | ||||
|         self.main_layout.addWidget(self.file_list) | ||||
|  | ||||
|         # Кнопки | ||||
| @@ -227,6 +228,10 @@ class FileExplorer(QDialog): | ||||
|                     # Открываем директорию | ||||
|                     self.current_path = os.path.normpath(full_path) | ||||
|                     self.update_file_list() | ||||
|             elif not self.directory_only: | ||||
|                 # Выбираем файл, если directory_only=False | ||||
|                 self.file_signal.file_selected.emit(os.path.normpath(full_path)) | ||||
|                 self.accept() | ||||
|             else: | ||||
|                 logger.debug("Double-clicked item is not a directory, ignoring: %s", full_path) | ||||
|         except Exception as e: | ||||
| @@ -287,14 +292,37 @@ class FileExplorer(QDialog): | ||||
|                 widget.deleteLater() | ||||
|  | ||||
|         drives = self.get_mounted_drives() | ||||
|         self.drive_buttons = []  # Store buttons for navigation | ||||
|         for drive in drives: | ||||
|             drive_name = os.path.basename(drive) or drive.split('/')[-1] or drive | ||||
|             button = AutoSizeButton(drive_name, icon=self.theme_manager.get_icon("mount_point")) | ||||
|             button.setStyleSheet(self.theme.ACTION_BUTTON_STYLE) | ||||
|             button.setFocusPolicy(Qt.FocusPolicy.StrongFocus)  # Make button focusable | ||||
|             button.clicked.connect(lambda checked, path=drive: self.change_drive(path)) | ||||
|             self.drives_layout.addWidget(button) | ||||
|             self.drive_buttons.append(button) | ||||
|         self.drives_layout.addStretch() | ||||
|  | ||||
|         # Set focus to first drive button if available | ||||
|         if self.drive_buttons: | ||||
|             self.drive_buttons[0].setFocus() | ||||
|  | ||||
|     def select_drive(self): | ||||
|         """Handle drive selection via gamepad""" | ||||
|         focused_widget = QApplication.focusWidget() | ||||
|         if isinstance(focused_widget, AutoSizeButton) and focused_widget in self.drive_buttons: | ||||
|             drive_path = None | ||||
|             for drive in self.get_mounted_drives(): | ||||
|                 drive_name = os.path.basename(drive) or drive.split('/')[-1] or drive | ||||
|                 if drive_name == focused_widget.text(): | ||||
|                     drive_path = drive | ||||
|                     break | ||||
|             if drive_path and os.path.isdir(drive_path) and os.access(drive_path, os.R_OK): | ||||
|                 self.current_path = os.path.normpath(drive_path) | ||||
|                 self.update_file_list() | ||||
|             else: | ||||
|                 logger.warning(f"Путь диска недоступен: {drive_path}") | ||||
|  | ||||
|     def change_drive(self, drive_path): | ||||
|         """Переход к выбранному диску""" | ||||
|         if os.path.isdir(drive_path) and os.access(drive_path, os.R_OK): | ||||
|   | ||||
| @@ -9,7 +9,7 @@ from PySide6.QtCore import Qt, QObject, QEvent, QPoint, Signal, Slot, QTimer | ||||
| from PySide6.QtGui import QKeyEvent | ||||
| from portprotonqt.logger import get_logger | ||||
| from portprotonqt.image_utils import FullscreenDialog | ||||
| from portprotonqt.custom_widgets import NavLabel | ||||
| from portprotonqt.custom_widgets import NavLabel, AutoSizeButton | ||||
| from portprotonqt.game_card import GameCard | ||||
| from portprotonqt.config_utils import read_fullscreen_config, read_window_geometry, save_window_geometry, read_auto_fullscreen_gamepad, read_rumble_config | ||||
| from portprotonqt.dialogs import AddGameDialog | ||||
| @@ -162,7 +162,26 @@ class InputManager(QObject): | ||||
|             if not self.file_explorer or not hasattr(self.file_explorer, 'file_list'): | ||||
|                 return | ||||
|  | ||||
|             if button_code in BUTTONS['add_game']: | ||||
|             focused_widget = QApplication.focusWidget() | ||||
|             if button_code in BUTTONS['confirm']:  # A button (BTN_SOUTH) | ||||
|                 if isinstance(focused_widget, AutoSizeButton) and hasattr(self.file_explorer, 'drive_buttons') and focused_widget in self.file_explorer.drive_buttons: | ||||
|                     self.file_explorer.select_drive()  # Select the focused drive | ||||
|                 elif self.file_explorer.file_list.count() == 0: | ||||
|                     return | ||||
|                 else: | ||||
|                     selected = self.file_explorer.file_list.currentItem().text() | ||||
|                     full_path = os.path.join(self.file_explorer.current_path, selected) | ||||
|                     if os.path.isdir(full_path): | ||||
|                         # Открываем директорию | ||||
|                         self.file_explorer.current_path = os.path.normpath(full_path) | ||||
|                         self.file_explorer.update_file_list() | ||||
|                     elif not self.file_explorer.directory_only: | ||||
|                         # Выбираем файл, если directory_only=False | ||||
|                         self.file_explorer.file_signal.file_selected.emit(os.path.normpath(full_path)) | ||||
|                         self.file_explorer.accept() | ||||
|                     else: | ||||
|                         logger.debug("Selected item is not a directory, cannot select: %s", full_path) | ||||
|             elif button_code in BUTTONS['add_game']:  # X button | ||||
|                 if self.file_explorer.file_list.count() == 0: | ||||
|                     return | ||||
|                 selected = self.file_explorer.file_list.currentItem().text() | ||||
| @@ -173,24 +192,9 @@ class InputManager(QObject): | ||||
|                     self.file_explorer.accept() | ||||
|                 else: | ||||
|                     logger.debug("Selected item is not a directory: %s", full_path) | ||||
|             elif button_code in BUTTONS['confirm']: | ||||
|                 if self.file_explorer.file_list.count() == 0: | ||||
|                     return | ||||
|                 selected = self.file_explorer.file_list.currentItem().text() | ||||
|                 full_path = os.path.join(self.file_explorer.current_path, selected) | ||||
|                 if os.path.isdir(full_path): | ||||
|                     # Открываем директорию | ||||
|                     self.file_explorer.current_path = os.path.normpath(full_path) | ||||
|                     self.file_explorer.update_file_list() | ||||
|                 elif not self.file_explorer.directory_only: | ||||
|                     # Выбираем файл, если directory_only=False | ||||
|                     self.file_explorer.file_signal.file_selected.emit(os.path.normpath(full_path)) | ||||
|                     self.file_explorer.accept() | ||||
|                 else: | ||||
|                     logger.debug("Selected item is not a directory, cannot select: %s", full_path) | ||||
|             elif button_code in BUTTONS['back']: | ||||
|             elif button_code in BUTTONS['back']:  # B button | ||||
|                 self.file_explorer.close() | ||||
|             elif button_code in BUTTONS['prev_dir']: | ||||
|             elif button_code in BUTTONS['prev_dir']:  # Y button | ||||
|                 self.file_explorer.previous_dir() | ||||
|             else: | ||||
|                 if self.original_button_handler: | ||||
| @@ -204,15 +208,33 @@ class InputManager(QObject): | ||||
|             if not self.file_explorer or not hasattr(self.file_explorer, 'file_list') or not self.file_explorer.file_list: | ||||
|                 return | ||||
|  | ||||
|             if not self.file_explorer.file_list.count(): | ||||
|                 return | ||||
|  | ||||
|             if code in (ecodes.ABS_HAT0Y, ecodes.ABS_Y): | ||||
|             focused_widget = QApplication.focusWidget() | ||||
|             if code in (ecodes.ABS_HAT0X, ecodes.ABS_X) and hasattr(self.file_explorer, 'drive_buttons') and self.file_explorer.drive_buttons: | ||||
|                 # Navigate drive buttons horizontally | ||||
|                 if not isinstance(focused_widget, AutoSizeButton) or focused_widget not in self.file_explorer.drive_buttons: | ||||
|                     # If not focused on a drive button, focus the first one | ||||
|                     self.file_explorer.drive_buttons[0].setFocus() | ||||
|                     return | ||||
|                 current_idx = self.file_explorer.drive_buttons.index(focused_widget) | ||||
|                 if value < 0:  # Left | ||||
|                     next_idx = max(current_idx - 1, 0) | ||||
|                     self.file_explorer.drive_buttons[next_idx].setFocus() | ||||
|                 elif value > 0:  # Right | ||||
|                     next_idx = min(current_idx + 1, len(self.file_explorer.drive_buttons) - 1) | ||||
|                     self.file_explorer.drive_buttons[next_idx].setFocus() | ||||
|             elif code in (ecodes.ABS_HAT0Y, ecodes.ABS_Y): | ||||
|                 if isinstance(focused_widget, AutoSizeButton) and focused_widget in self.file_explorer.drive_buttons: | ||||
|                     # Move focus to file list if navigating down from drive buttons | ||||
|                     if value > 0 and self.file_explorer.file_list.count() > 0: | ||||
|                         self.file_explorer.file_list.setFocus() | ||||
|                         self.file_explorer.file_list.setCurrentRow(0) | ||||
|                         self.file_explorer.file_list.scrollToItem(self.file_explorer.file_list.currentItem()) | ||||
|                     return | ||||
|                 # Для D-pad - реакция с фиксированной скоростью | ||||
|                 if code == ecodes.ABS_HAT0Y: | ||||
|                     if value != 0: | ||||
|                         self.current_direction = value | ||||
|                         self.stick_value = 1.0  # Максимальная скорость для D-pad, чтобы скачков не было | ||||
|                         self.stick_value = 1.0  # Максимальная скорость для D-pad | ||||
|                         if not self.nav_timer.isActive(): | ||||
|                             self.file_explorer.move_selection(self.current_direction) | ||||
|                             self.last_nav_time = current_time | ||||
| @@ -220,7 +242,6 @@ class InputManager(QObject): | ||||
|                     else: | ||||
|                         self.current_direction = 0 | ||||
|                         self.nav_timer.stop() | ||||
|  | ||||
|                 # Для стика - плавное управление с учетом степени отклонения | ||||
|                 elif code == ecodes.ABS_Y: | ||||
|                     if abs(value) < self.dead_zone: | ||||
| @@ -229,19 +250,15 @@ class InputManager(QObject): | ||||
|                             self.nav_timer.stop() | ||||
|                             self.stick_activated = False | ||||
|                         return | ||||
|  | ||||
|                     # Рассчитываем "силу" отклонения (0.3 - 1.0) | ||||
|                     normalized_value = (abs(value) - self.dead_zone) / (32768 - self.dead_zone) | ||||
|                     speed_factor = 0.3 + (normalized_value * 0.7)  # От 30% до 100% скорости | ||||
|                     self.current_direction = -1 if value < 0 else 1 | ||||
|                     self.stick_value = speed_factor | ||||
|                     self.stick_activated = True | ||||
|  | ||||
|                     if not self.nav_timer.isActive(): | ||||
|                         self.file_explorer.move_selection(self.current_direction) | ||||
|                         self.last_nav_time = current_time | ||||
|                         self.nav_timer.start(int(self.initial_nav_delay * 1000)) | ||||
|  | ||||
|             elif self.original_dpad_handler: | ||||
|                 self.original_dpad_handler(code, value, current_time) | ||||
|         except Exception as e: | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| @@ -9,7 +9,7 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PROJECT VERSION\n" | ||||
| "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" | ||||
| "POT-Creation-Date: 2025-07-01 00:15+0500\n" | ||||
| "POT-Creation-Date: 2025-07-01 15:54+0500\n" | ||||
| "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||
| "Language: de_DE\n" | ||||
| @@ -26,6 +26,9 @@ msgstr "" | ||||
| msgid "PortProton is not found" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Launch Game" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -66,6 +69,10 @@ msgstr "" | ||||
| msgid "Legendary executable not found at {path}" | ||||
| msgstr "" | ||||
|  | ||||
| #, python-brace-format | ||||
| msgid "start.sh not found at {path}" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Success" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -110,10 +117,6 @@ msgstr "" | ||||
| msgid "Removed '{game_name}' from favorites" | ||||
| msgstr "" | ||||
|  | ||||
| #, python-brace-format | ||||
| msgid "start.sh not found at {path}" | ||||
| msgstr "" | ||||
|  | ||||
| #, python-brace-format | ||||
| msgid "Launch game \"{name}\" with PortProton" | ||||
| msgstr "" | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| @@ -9,7 +9,7 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PROJECT VERSION\n" | ||||
| "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" | ||||
| "POT-Creation-Date: 2025-07-01 00:15+0500\n" | ||||
| "POT-Creation-Date: 2025-07-01 15:54+0500\n" | ||||
| "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||
| "Language: es_ES\n" | ||||
| @@ -26,6 +26,9 @@ msgstr "" | ||||
| msgid "PortProton is not found" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Launch Game" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -66,6 +69,10 @@ msgstr "" | ||||
| msgid "Legendary executable not found at {path}" | ||||
| msgstr "" | ||||
|  | ||||
| #, python-brace-format | ||||
| msgid "start.sh not found at {path}" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Success" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -110,10 +117,6 @@ msgstr "" | ||||
| msgid "Removed '{game_name}' from favorites" | ||||
| msgstr "" | ||||
|  | ||||
| #, python-brace-format | ||||
| msgid "start.sh not found at {path}" | ||||
| msgstr "" | ||||
|  | ||||
| #, python-brace-format | ||||
| msgid "Launch game \"{name}\" with PortProton" | ||||
| msgstr "" | ||||
|   | ||||
| @@ -9,7 +9,7 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PortProtonQt 0.1.1\n" | ||||
| "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" | ||||
| "POT-Creation-Date: 2025-07-01 00:15+0500\n" | ||||
| "POT-Creation-Date: 2025-07-01 15:54+0500\n" | ||||
| "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||
| "Language-Team: LANGUAGE <LL@li.org>\n" | ||||
| @@ -24,6 +24,9 @@ msgstr "" | ||||
| msgid "PortProton is not found" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Launch Game" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -64,6 +67,10 @@ msgstr "" | ||||
| msgid "Legendary executable not found at {path}" | ||||
| msgstr "" | ||||
|  | ||||
| #, python-brace-format | ||||
| msgid "start.sh not found at {path}" | ||||
| msgstr "" | ||||
|  | ||||
| msgid "Success" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -108,10 +115,6 @@ msgstr "" | ||||
| msgid "Removed '{game_name}' from favorites" | ||||
| msgstr "" | ||||
|  | ||||
| #, python-brace-format | ||||
| msgid "start.sh not found at {path}" | ||||
| msgstr "" | ||||
|  | ||||
| #, python-brace-format | ||||
| msgid "Launch game \"{name}\" with PortProton" | ||||
| msgstr "" | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| @@ -9,8 +9,8 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PROJECT VERSION\n" | ||||
| "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" | ||||
| "POT-Creation-Date: 2025-07-01 00:15+0500\n" | ||||
| "PO-Revision-Date: 2025-07-01 00:15+0500\n" | ||||
| "POT-Creation-Date: 2025-07-01 15:54+0500\n" | ||||
| "PO-Revision-Date: 2025-07-01 15:54+0500\n" | ||||
| "Last-Translator: \n" | ||||
| "Language: ru_RU\n" | ||||
| "Language-Team: ru_RU <LL@li.org>\n" | ||||
| @@ -27,6 +27,9 @@ msgstr "Ошибка" | ||||
| msgid "PortProton is not found" | ||||
| msgstr "PortProton не найден" | ||||
|  | ||||
| msgid "Launch Game" | ||||
| msgstr "Запустить игру" | ||||
|  | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "Удалить из Избранного" | ||||
|  | ||||
| @@ -67,6 +70,10 @@ msgstr "Удалить из PortProton" | ||||
| msgid "Legendary executable not found at {path}" | ||||
| msgstr "Legendary не найден по пути {path}" | ||||
|  | ||||
| #, python-brace-format | ||||
| msgid "start.sh not found at {path}" | ||||
| msgstr "start.sh не найден по адресу {path}" | ||||
|  | ||||
| msgid "Success" | ||||
| msgstr "Успешно" | ||||
|  | ||||
| @@ -113,10 +120,6 @@ msgstr "'{game_name}' был(а) добавлен(а) в избранное" | ||||
| msgid "Removed '{game_name}' from favorites" | ||||
| msgstr "'{game_name}' был(а) удалён(а) из избранного" | ||||
|  | ||||
| #, python-brace-format | ||||
| msgid "start.sh not found at {path}" | ||||
| msgstr "start.sh не найден по адресу {path}" | ||||
|  | ||||
| #, python-brace-format | ||||
| msgid "Launch game \"{name}\" with PortProton" | ||||
| msgstr "Запустить игру \"{name}\" с помощью PortProton" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user