1
0
Fork 0
mirror of https://github.com/deepfakes/faceswap synced 2025-06-09 04:36:50 -04:00

locales: Add GUI menu translations

This commit is contained in:
torzdf 2023-06-07 14:16:27 +01:00
parent 013f3016f1
commit 50a5113690
16 changed files with 1018 additions and 513 deletions

View file

@ -104,6 +104,13 @@ display\_graph module
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
menu module
===========
.. automodule:: lib.gui.menu
:members:
:undoc-members:
:show-inheritance:
popup_configure module popup_configure module
====================== ======================
.. automodule:: lib.gui.popup_configure .. automodule:: lib.gui.popup_configure

View file

@ -7,13 +7,14 @@ import logging
import os import os
import sys import sys
import tkinter as tk import tkinter as tk
import typing as T
from tkinter import ttk from tkinter import ttk
import webbrowser import webbrowser
from subprocess import Popen, PIPE, STDOUT from subprocess import Popen, PIPE, STDOUT
from lib.multithreading import MultiThread from lib.multithreading import MultiThread
from lib.serializer import get_serializer from lib.serializer import get_serializer, Serializer
from lib.utils import FaceswapError from lib.utils import FaceswapError
import update_deps import update_deps
@ -21,23 +22,33 @@ from .popup_configure import open_popup
from .custom_widgets import Tooltip from .custom_widgets import Tooltip
from .utils import get_config, get_images from .utils import get_config, get_images
if T.TYPE_CHECKING:
from scripts.gui import FaceswapGui
logger = logging.getLogger(__name__) # pylint: disable=invalid-name logger = logging.getLogger(__name__) # pylint: disable=invalid-name
# LOCALES # LOCALES
_LANG = gettext.translation("gui.tooltips", localedir="locales", fallback=True) _LANG = gettext.translation("gui.menu", localedir="locales", fallback=True)
_ = _LANG.gettext _ = _LANG.gettext
_WORKING_DIR = os.path.dirname(os.path.realpath(sys.argv[0])) _WORKING_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
_RESOURCES = [(_("faceswap.dev - Guides and Forum"), "https://www.faceswap.dev"), _RESOURCES: T.List[T.Tuple[str, str]] = [
(_("Patreon - Support this project"), "https://www.patreon.com/faceswap"), (_("faceswap.dev - Guides and Forum"), "https://www.faceswap.dev"),
(_("Discord - The FaceSwap Discord server"), "https://discord.gg/VasFUAy"), (_("Patreon - Support this project"), "https://www.patreon.com/faceswap"),
(_("Github - Our Source Code"), "https://github.com/deepfakes/faceswap")] (_("Discord - The FaceSwap Discord server"), "https://discord.gg/VasFUAy"),
(_("Github - Our Source Code"), "https://github.com/deepfakes/faceswap")]
class MainMenuBar(tk.Menu): # pylint:disable=too-many-ancestors class MainMenuBar(tk.Menu): # pylint:disable=too-many-ancestors
""" GUI Main Menu Bar """ """ GUI Main Menu Bar
def __init__(self, master=None):
Parameters
----------
master: :class:`tkinter.Tk`
The root tkinter object
"""
def __init__(self, master: "FaceswapGui") -> None:
logger.debug("Initializing %s", self.__class__.__name__) logger.debug("Initializing %s", self.__class__.__name__)
super().__init__(master) super().__init__(master)
self.root = master self.root = master
@ -46,99 +57,130 @@ class MainMenuBar(tk.Menu): # pylint:disable=too-many-ancestors
self.settings_menu = SettingsMenu(self) self.settings_menu = SettingsMenu(self)
self.help_menu = HelpMenu(self) self.help_menu = HelpMenu(self)
self.add_cascade(label="File", menu=self.file_menu, underline=0) self.add_cascade(label=_("File"), menu=self.file_menu, underline=0)
self.add_cascade(label="Settings", menu=self.settings_menu, underline=0) self.add_cascade(label=_("Settings"), menu=self.settings_menu, underline=0)
self.add_cascade(label="Help", menu=self.help_menu, underline=0) self.add_cascade(label=_("Help"), menu=self.help_menu, underline=0)
logger.debug("Initialized %s", self.__class__.__name__) logger.debug("Initialized %s", self.__class__.__name__)
class SettingsMenu(tk.Menu): # pylint:disable=too-many-ancestors class SettingsMenu(tk.Menu): # pylint:disable=too-many-ancestors
""" Settings menu items and functions """ """ Settings menu items and functions
def __init__(self, parent):
Parameters
----------
parent: :class:`tkinter.Menu`
The main menu bar to hold this menu item
"""
def __init__(self, parent: MainMenuBar) -> None:
logger.debug("Initializing %s", self.__class__.__name__) logger.debug("Initializing %s", self.__class__.__name__)
super().__init__(parent, tearoff=0) super().__init__(parent, tearoff=0)
self.root = parent.root self.root = parent.root
self.build() self._build()
logger.debug("Initialized %s", self.__class__.__name__) logger.debug("Initialized %s", self.__class__.__name__)
def build(self): def _build(self) -> None:
""" Add the settings menu to the menu bar """ """ Add the settings menu to the menu bar """
# pylint: disable=cell-var-from-loop # pylint: disable=cell-var-from-loop
logger.debug("Building settings menu") logger.debug("Building settings menu")
self.add_command(label="Configure Settings...", self.add_command(label=_("Configure Settings..."),
underline=0, underline=0,
command=open_popup) command=open_popup)
logger.debug("Built settings menu") logger.debug("Built settings menu")
class FileMenu(tk.Menu): # pylint:disable=too-many-ancestors class FileMenu(tk.Menu): # pylint:disable=too-many-ancestors
""" File menu items and functions """ """ File menu items and functions
def __init__(self, parent):
Parameters
----------
parent: :class:`tkinter.Menu`
The main menu bar to hold this menu item
"""
def __init__(self, parent: MainMenuBar) -> None:
logger.debug("Initializing %s", self.__class__.__name__) logger.debug("Initializing %s", self.__class__.__name__)
super().__init__(parent, tearoff=0) super().__init__(parent, tearoff=0)
self.root = parent.root self.root = parent.root
self._config = get_config() self._config = get_config()
self.recent_menu = tk.Menu(self, tearoff=0, postcommand=self.refresh_recent_menu) self.recent_menu = tk.Menu(self, tearoff=0, postcommand=self._refresh_recent_menu)
self.build() self._build()
logger.debug("Initialized %s", self.__class__.__name__) logger.debug("Initialized %s", self.__class__.__name__)
def build(self): def _refresh_recent_menu(self) -> None:
""" Refresh recent menu on save/load of files """
self.recent_menu.delete(0, "end")
self._build_recent_menu()
def _build(self) -> None:
""" Add the file menu to the menu bar """ """ Add the file menu to the menu bar """
logger.debug("Building File menu") logger.debug("Building File menu")
self.add_command(label="New Project...", self.add_command(label=_("New Project..."),
underline=0, underline=0,
accelerator="Ctrl+N", accelerator="Ctrl+N",
command=self._config.project.new) command=self._config.project.new)
self.root.bind_all("<Control-n>", self._config.project.new) self.root.bind_all("<Control-n>", self._config.project.new)
self.add_command(label="Open Project...", self.add_command(label=_("Open Project..."),
underline=0, underline=0,
accelerator="Ctrl+O", accelerator="Ctrl+O",
command=self._config.project.load) command=self._config.project.load)
self.root.bind_all("<Control-o>", self._config.project.load) self.root.bind_all("<Control-o>", self._config.project.load)
self.add_command(label="Save Project", self.add_command(label=_("Save Project"),
underline=0, underline=0,
accelerator="Ctrl+S", accelerator="Ctrl+S",
command=lambda: self._config.project.save(save_as=False)) command=lambda: self._config.project.save(save_as=False))
self.root.bind_all("<Control-s>", lambda e: self._config.project.save(e, save_as=False)) self.root.bind_all("<Control-s>", lambda e: self._config.project.save(e, save_as=False))
self.add_command(label="Save Project as...", self.add_command(label=_("Save Project as..."),
underline=13, underline=13,
accelerator="Ctrl+Alt+S", accelerator="Ctrl+Alt+S",
command=lambda: self._config.project.save(save_as=True)) command=lambda: self._config.project.save(save_as=True))
self.root.bind_all("<Control-Alt-s>", lambda e: self._config.project.save(e, save_as=True)) self.root.bind_all("<Control-Alt-s>", lambda e: self._config.project.save(e, save_as=True))
self.add_command(label="Reload Project from Disk", self.add_command(label=_("Reload Project from Disk"),
underline=0, underline=0,
accelerator="F5", accelerator="F5",
command=self._config.project.reload) command=self._config.project.reload)
self.root.bind_all("<F5>", self._config.project.reload) self.root.bind_all("<F5>", self._config.project.reload)
self.add_command(label="Close Project", self.add_command(label=_("Close Project"),
underline=0, underline=0,
accelerator="Ctrl+W", accelerator="Ctrl+W",
command=self._config.project.close) command=self._config.project.close)
self.root.bind_all("<Control-w>", self._config.project.close) self.root.bind_all("<Control-w>", self._config.project.close)
self.add_separator() self.add_separator()
self.add_command(label="Open Task...", self.add_command(label=_("Open Task..."),
underline=5, underline=5,
accelerator="Ctrl+Alt+T", accelerator="Ctrl+Alt+T",
command=lambda: self._config.tasks.load(current_tab=False)) command=lambda: self._config.tasks.load(current_tab=False))
self.root.bind_all("<Control-Alt-t>", self.root.bind_all("<Control-Alt-t>",
lambda e: self._config.tasks.load(e, current_tab=False)) lambda e: self._config.tasks.load(e, current_tab=False))
self.add_separator() self.add_separator()
self.add_cascade(label="Open recent", underline=6, menu=self.recent_menu) self.add_cascade(label=_("Open recent"), underline=6, menu=self.recent_menu)
self.add_separator() self.add_separator()
self.add_command(label="Quit", self.add_command(label=_("Quit"),
underline=0, underline=0,
accelerator="Alt+F4", accelerator="Alt+F4",
command=self.root.close_app) command=self.root.close_app)
self.root.bind_all("<Alt-F4>", self.root.close_app) self.root.bind_all("<Alt-F4>", self.root.close_app)
logger.debug("Built File menu") logger.debug("Built File menu")
def build_recent_menu(self): @classmethod
def _clear_recent_files(cls, serializer: Serializer, menu_file: str) -> None:
""" Creates or clears recent file list
Parameters
----------
serializer: :class:`~lib.serializer.Serializer`
The serializer to use for storing files
menu_file: str
The file name holding the recent files
"""
logger.debug("clearing recent files list: '%s'", menu_file)
serializer.save(menu_file, [])
def _build_recent_menu(self) -> None:
""" Load recent files into menu bar """ """ Load recent files into menu bar """
logger.debug("Building Recent Files menu") logger.debug("Building Recent Files menu")
serializer = get_serializer("json") serializer = get_serializer("json")
menu_file = os.path.join(self._config.pathcache, ".recent.json") menu_file = os.path.join(self._config.pathcache, ".recent.json")
if not os.path.isfile(menu_file) or os.path.getsize(menu_file) == 0: if not os.path.isfile(menu_file) or os.path.getsize(menu_file) == 0:
self.clear_recent_files(serializer, menu_file) self._clear_recent_files(serializer, menu_file)
try: try:
recent_files = serializer.load(menu_file) recent_files = serializer.load(menu_file)
except FaceswapError as err: except FaceswapError as err:
@ -146,7 +188,7 @@ class FileMenu(tk.Menu): # pylint:disable=too-many-ancestors
# Some reports of corruption breaking menus # Some reports of corruption breaking menus
logger.warning("There was an error opening the recent files list so it has been " logger.warning("There was an error opening the recent files list so it has been "
"reset.") "reset.")
self.clear_recent_files(serializer, menu_file) self._clear_recent_files(serializer, menu_file)
recent_files = [] recent_files = []
logger.debug("Loaded recent files: %s", recent_files) logger.debug("Loaded recent files: %s", recent_files)
@ -163,14 +205,14 @@ class FileMenu(tk.Menu): # pylint:disable=too-many-ancestors
if command.lower() == "project": if command.lower() == "project":
load_func = self._config.project.load load_func = self._config.project.load
lbl = command lbl = command
kwargs = dict(filename=filename) kwargs = {"filename": filename}
else: else:
load_func = self._config.tasks.load load_func = self._config.tasks.load # type:ignore
lbl = f"{command} Task" lbl = _("{} Task").format(command)
kwargs = dict(filename=filename, current_tab=False) kwargs = {"filename": filename, "current_tab": False}
self.recent_menu.add_command( self.recent_menu.add_command(
label=f"{filename} ({lbl.title()})", label=f"{filename} ({lbl.title()})",
command=lambda kw=kwargs, fn=load_func: fn(**kw)) command=lambda kw=kwargs, fn=load_func: fn(**kw)) # type:ignore
if removed_files: if removed_files:
for recent_item in removed_files: for recent_item in removed_files:
logger.debug("Removing from recent files: `%s`", recent_item[0]) logger.debug("Removing from recent files: `%s`", recent_item[0])
@ -178,222 +220,76 @@ class FileMenu(tk.Menu): # pylint:disable=too-many-ancestors
serializer.save(menu_file, recent_files) serializer.save(menu_file, recent_files)
self.recent_menu.add_separator() self.recent_menu.add_separator()
self.recent_menu.add_command( self.recent_menu.add_command(
label="Clear recent files", label=_("Clear recent files"),
underline=0, underline=0,
command=lambda srl=serializer, mnu=menu_file: self.clear_recent_files(srl, mnu)) command=lambda srl=serializer, mnu=menu_file: self._clear_recent_files( # type:ignore
srl, mnu))
logger.debug("Built Recent Files menu") logger.debug("Built Recent Files menu")
@staticmethod
def clear_recent_files(serializer, menu_file):
""" Creates or clears recent file list """
logger.debug("clearing recent files list: '%s'", menu_file)
serializer.save(menu_file, [])
def refresh_recent_menu(self):
""" Refresh recent menu on save/load of files """
self.recent_menu.delete(0, "end")
self.build_recent_menu()
class HelpMenu(tk.Menu): # pylint:disable=too-many-ancestors class HelpMenu(tk.Menu): # pylint:disable=too-many-ancestors
""" Help menu items and functions """ """ Help menu items and functions
def __init__(self, parent):
Parameters
----------
parent: :class:`tkinter.Menu`
The main menu bar to hold this menu item
"""
def __init__(self, parent: MainMenuBar) -> None:
logger.debug("Initializing %s", self.__class__.__name__) logger.debug("Initializing %s", self.__class__.__name__)
super().__init__(parent, tearoff=0) super().__init__(parent, tearoff=0)
self.root = parent.root self.root = parent.root
self.recources_menu = tk.Menu(self, tearoff=0) self.recources_menu = tk.Menu(self, tearoff=0)
self._branches_menu = tk.Menu(self, tearoff=0) self._branches_menu = tk.Menu(self, tearoff=0)
self.build() self._build()
logger.debug("Initialized %s", self.__class__.__name__) logger.debug("Initialized %s", self.__class__.__name__)
def build(self): def _in_thread(self, action: str):
""" Build the help menu """ """ Perform selected action inside a thread
logger.debug("Building Help menu")
self.add_command(label="Check for updates...",
underline=0,
command=lambda action="check": self.in_thread(action))
self.add_command(label="Update Faceswap...",
underline=0,
command=lambda action="update": self.in_thread(action))
if self._build_branches_menu():
self.add_cascade(label="Switch Branch", underline=7, menu=self._branches_menu)
self.add_separator()
self._build_recources_menu()
self.add_cascade(label="Resources", underline=0, menu=self.recources_menu)
self.add_separator()
self.add_command(label="Output System Information",
underline=0,
command=lambda action="output_sysinfo": self.in_thread(action))
logger.debug("Built help menu")
def _build_branches_menu(self):
""" Build branch selection menu.
Queries git for available branches and builds a menu based on output.
Returns
-------
bool
``True`` if menu was successfully built otherwise ``False``
"""
stdout = self._get_branches()
if stdout is None:
return False
branches = self._filter_branches(stdout)
if not branches:
return False
for branch in branches:
self._branches_menu.add_command(
label=branch,
command=lambda b=branch: self._switch_branch(b))
return True
@staticmethod
def _get_branches():
""" Get the available github branches
Returns
-------
str
The list of branches available. If no branches were found or there was an
error then `None` is returned
"""
gitcmd = "git branch -a"
with Popen(gitcmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=_WORKING_DIR) as cmd:
stdout, _ = cmd.communicate()
retcode = cmd.poll()
if retcode != 0:
logger.debug("Unable to list git branches. return code: %s, message: %s",
retcode,
stdout.decode(locale.getpreferredencoding(),
errors="replace").strip().replace("\n", " - "))
return None
return stdout.decode(locale.getpreferredencoding(), errors="replace")
@staticmethod
def _filter_branches(stdout):
""" Filter the branches, remove duplicates and the current branch and return a sorted
list.
Parameters Parameters
---------- ----------
stdout: str action: str
The output from the git branch query converted to a string The action to be performed. The action corresponds to the function name to be called
Returns
-------
list
Unique list of available branches sorted in alphabetical order
""" """
current = None
branches = set()
for line in stdout.splitlines():
branch = line[line.rfind("/") + 1:] if "/" in line else line.strip()
if branch.startswith("*"):
branch = branch.replace("*", "").strip()
current = branch
continue
branches.add(branch)
logger.debug("Found branches: %s", branches)
if current in branches:
logger.debug("Removing current branch from output: %s", current)
branches.remove(current)
branches = sorted(list(branches), key=str.casefold)
logger.debug("Final branches: %s", branches)
return branches
@staticmethod
def _switch_branch(branch):
""" Change the currently checked out branch, and return a notification.
Parameters
----------
str
The branch to switch to
"""
logger.info("Switching branch to '%s'...", branch)
gitcmd = f"git checkout {branch}"
with Popen(gitcmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=_WORKING_DIR) as cmd:
stdout, _ = cmd.communicate()
retcode = cmd.poll()
if retcode != 0:
logger.error("Unable to switch branch. return code: %s, message: %s",
retcode,
stdout.decode(locale.getdefaultlocale(),
errors="replace").strip().replace("\n", " - "))
return
logger.info("Succesfully switched to '%s'. You may want to check for updates to make sure "
"that you have the latest code.", branch)
logger.info("Please restart Faceswap to complete the switch.")
def _build_recources_menu(self):
""" Build resources menu """
# pylint: disable=cell-var-from-loop
logger.debug("Building Resources Files menu")
for resource in _RESOURCES:
self.recources_menu.add_command(
label=resource[0],
command=lambda link=resource[1]: webbrowser.open_new(link))
logger.debug("Built resources menu")
def in_thread(self, action):
""" Perform selected action inside a thread """
logger.debug("Performing help action: %s", action) logger.debug("Performing help action: %s", action)
thread = MultiThread(getattr(self, action), thread_count=1) thread = MultiThread(getattr(self, action), thread_count=1)
thread.start() thread.start()
logger.debug("Performed help action: %s", action) logger.debug("Performed help action: %s", action)
@staticmethod def _output_sysinfo(self):
def clear_console():
""" Clear the console window """
get_config().tk_vars.console_clear.set(True)
def output_sysinfo(self):
""" Output system information to console """ """ Output system information to console """
logger.debug("Obtaining system information") logger.debug("Obtaining system information")
self.root.config(cursor="watch") self.root.config(cursor="watch")
self.clear_console() self._clear_console()
try: try:
from lib.sysinfo import sysinfo # pylint:disable=import-outside-toplevel from lib.sysinfo import sysinfo # pylint:disable=import-outside-toplevel
info = sysinfo info = sysinfo
except Exception as err: # pylint:disable=broad-except except Exception as err: # pylint:disable=broad-except
info = f"Error obtaining system info: {str(err)}" info = f"Error obtaining system info: {str(err)}"
self.clear_console() self._clear_console()
logger.debug("Obtained system information: %s", info) logger.debug("Obtained system information: %s", info)
print(info) print(info)
self.root.config(cursor="") self.root.config(cursor="")
def check(self): @classmethod
""" Check for updates and clone repository """ def _check_for_updates(cls, encoding: str, check: bool = False) -> bool:
logger.debug("Checking for updates...") """ Check whether an update is required
self.root.config(cursor="watch")
encoding = locale.getpreferredencoding()
logger.debug("Encoding: %s", encoding)
self.check_for_updates(encoding, check=True)
self.root.config(cursor="")
def update(self): Parameters
""" Check for updates and clone repository """ ----------
logger.debug("Updating Faceswap...") encoding: str
self.root.config(cursor="watch") The encoding to use for decoding process returns
encoding = locale.getpreferredencoding() check: bool
logger.debug("Encoding: %s", encoding) ``True`` if we are just checking for updates ``False`` if a check and update is to be
success = False performed. Default: ``False``
if self.check_for_updates(encoding):
success = self.do_update(encoding)
update_deps.main(is_gui=True)
if success:
logger.info("Please restart Faceswap to complete the update.")
self.root.config(cursor="")
@staticmethod Returns
def check_for_updates(encoding, check=False): -------
""" Check whether an update is required """ bool
``True`` if an update is required
"""
# Do the check # Do the check
logger.info("Checking for updates...") logger.info("Checking for updates...")
update = False update = False
@ -426,9 +322,29 @@ class HelpMenu(tk.Menu): # pylint:disable=too-many-ancestors
logger.debug("Checked for update. Update required: %s", update) logger.debug("Checked for update. Update required: %s", update)
return update return update
@staticmethod def _check(self) -> None:
def do_update(encoding): """ Check for updates and clone repository """
""" Update Faceswap """ logger.debug("Checking for updates...")
self.root.config(cursor="watch")
encoding = locale.getpreferredencoding()
logger.debug("Encoding: %s", encoding)
self._check_for_updates(encoding, check=True)
self.root.config(cursor="")
@classmethod
def _do_update(cls, encoding: str) -> bool:
""" Update Faceswap
Parameters
----------
encoding: str
The encoding to use for decoding process returns
Returns
-------
bool
``True`` if update was successful
"""
logger.info("A new version is available. Updating...") logger.info("A new version is available. Updating...")
gitcmd = "git pull" gitcmd = "git pull"
with Popen(gitcmd, with Popen(gitcmd,
@ -438,7 +354,8 @@ class HelpMenu(tk.Menu): # pylint:disable=too-many-ancestors
bufsize=1, bufsize=1,
cwd=_WORKING_DIR) as cmd: cwd=_WORKING_DIR) as cmd:
while True: while True:
output = cmd.stdout.readline().decode(encoding, errors="replace") out = cmd.stdout
output = "" if out is None else out.readline().decode(encoding, errors="replace")
if output == "" and cmd.poll() is not None: if output == "" and cmd.poll() is not None:
break break
if output: if output:
@ -453,10 +370,170 @@ class HelpMenu(tk.Menu): # pylint:disable=too-many-ancestors
retval = True retval = True
return retval return retval
def _update(self) -> None:
""" Check for updates and clone repository """
logger.debug("Updating Faceswap...")
self.root.config(cursor="watch")
encoding = locale.getpreferredencoding()
logger.debug("Encoding: %s", encoding)
success = False
if self._check_for_updates(encoding):
success = self._do_update(encoding)
update_deps.main(is_gui=True)
if success:
logger.info("Please restart Faceswap to complete the update.")
self.root.config(cursor="")
def _build(self) -> None:
""" Build the help menu """
logger.debug("Building Help menu")
self.add_command(label=_("Check for updates..."),
underline=0,
command=lambda action="_check": self._in_thread(action)) # type:ignore
self.add_command(label=_("Update Faceswap..."),
underline=0,
command=lambda action="_update": self._in_thread(action)) # type:ignore
if self._build_branches_menu():
self.add_cascade(label=_("Switch Branch"), underline=7, menu=self._branches_menu)
self.add_separator()
self._build_recources_menu()
self.add_cascade(label=_("Resources"), underline=0, menu=self.recources_menu)
self.add_separator()
self.add_command(
label=_("Output System Information"),
underline=0,
command=lambda action="_output_sysinfo": self._in_thread(action)) # type:ignore
logger.debug("Built help menu")
def _build_branches_menu(self) -> bool:
""" Build branch selection menu.
Queries git for available branches and builds a menu based on output.
Returns
-------
bool
``True`` if menu was successfully built otherwise ``False``
"""
stdout = self._get_branches()
if stdout is None:
return False
branches = self._filter_branches(stdout)
if not branches:
return False
for branch in branches:
self._branches_menu.add_command(
label=branch,
command=lambda b=branch: self._switch_branch(b)) # type:ignore
return True
@classmethod
def _get_branches(cls) -> T.Optional[str]:
""" Get the available github branches
Returns
-------
str or ``None``
The list of branches available. If no branches were found or there was an
error then `None` is returned
"""
gitcmd = "git branch -a"
with Popen(gitcmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=_WORKING_DIR) as cmd:
stdout, _ = cmd.communicate()
retcode = cmd.poll()
if retcode != 0:
logger.debug("Unable to list git branches. return code: %s, message: %s",
retcode,
stdout.decode(locale.getpreferredencoding(),
errors="replace").strip().replace("\n", " - "))
return None
return stdout.decode(locale.getpreferredencoding(), errors="replace")
@classmethod
def _filter_branches(cls, stdout: str) -> T.List[str]:
""" Filter the branches, remove duplicates and the current branch and return a sorted
list.
Parameters
----------
stdout: str
The output from the git branch query converted to a string
Returns
-------
list[str]
Unique list of available branches sorted in alphabetical order
"""
current = None
branches = set()
for line in stdout.splitlines():
branch = line[line.rfind("/") + 1:] if "/" in line else line.strip()
if branch.startswith("*"):
branch = branch.replace("*", "").strip()
current = branch
continue
branches.add(branch)
logger.debug("Found branches: %s", branches)
if current in branches:
logger.debug("Removing current branch from output: %s", current)
branches.remove(current)
retval = sorted(list(branches), key=str.casefold)
logger.debug("Final branches: %s", retval)
return retval
@classmethod
def _switch_branch(cls, branch: str) -> None:
""" Change the currently checked out branch, and return a notification.
Parameters
----------
str
The branch to switch to
"""
logger.info("Switching branch to '%s'...", branch)
gitcmd = f"git checkout {branch}"
with Popen(gitcmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=_WORKING_DIR) as cmd:
stdout, _ = cmd.communicate()
retcode = cmd.poll()
if retcode != 0:
logger.error("Unable to switch branch. return code: %s, message: %s",
retcode,
stdout.decode(T.cast(str, locale.getdefaultlocale()),
errors="replace").strip().replace("\n", " - "))
return
logger.info("Succesfully switched to '%s'. You may want to check for updates to make sure "
"that you have the latest code.", branch)
logger.info("Please restart Faceswap to complete the switch.")
def _build_recources_menu(self) -> None:
""" Build resources menu """
# pylint: disable=cell-var-from-loop
logger.debug("Building Resources Files menu")
for resource in _RESOURCES:
self.recources_menu.add_command(
label=resource[0],
command=lambda link=resource[1]: webbrowser.open_new(link)) # type:ignore
logger.debug("Built resources menu")
@classmethod
def _clear_console(cls) -> None:
""" Clear the console window """
get_config().tk_vars.console_clear.set(True)
class TaskBar(ttk.Frame): # pylint: disable=too-many-ancestors class TaskBar(ttk.Frame): # pylint: disable=too-many-ancestors
""" Task bar buttons """ """ Task bar buttons
def __init__(self, parent):
Parameters
----------
parent: :class:`tkinter.ttk.Frame`
The frame that holds the task bar
"""
def __init__(self, parent: ttk.Frame) -> None:
super().__init__(parent) super().__init__(parent)
self._config = get_config() self._config = get_config()
self.pack(side=tk.TOP, anchor=tk.W, fill=tk.X, expand=False) self.pack(side=tk.TOP, anchor=tk.W, fill=tk.X, expand=False)
@ -470,75 +547,43 @@ class TaskBar(ttk.Frame): # pylint: disable=too-many-ancestors
self._settings_btns() self._settings_btns()
self._section_separator() self._section_separator()
def _project_btns(self): @classmethod
frame = ttk.Frame(self._btn_frame) def _loader_and_kwargs(cls, btntype: str) -> T.Tuple[str, T.Dict[str, bool]]:
frame.pack(side=tk.LEFT, anchor=tk.W, expand=False, padx=2) """ Get the loader name and key word arguments for the given button type
for btntype in ("new", "load", "save", "save_as", "reload"): Parameters
logger.debug("Adding button: '%s'", btntype) ----------
btntype: str
The button type to obtain the information for
loader, kwargs = self._loader_and_kwargs(btntype) Returns
cmd = getattr(self._config.project, loader) -------
btn = ttk.Button(frame, loader: str
image=get_images().icons[btntype], The name of the loader to use for the given button type
command=lambda fn=cmd, kw=kwargs: fn(**kw)) kwargs: dict[str, bool]
btn.pack(side=tk.LEFT, anchor=tk.W) The keyword arguments to use for the returned loader
hlp = self.set_help(btntype) """
Tooltip(btn, text=hlp, wrap_length=200)
def _task_btns(self):
frame = ttk.Frame(self._btn_frame)
frame.pack(side=tk.LEFT, anchor=tk.W, expand=False, padx=2)
for loadtype in ("load", "save", "save_as", "clear", "reload"):
btntype = f"{loadtype}2"
logger.debug("Adding button: '%s'", btntype)
loader, kwargs = self._loader_and_kwargs(loadtype)
if loadtype == "load":
kwargs["current_tab"] = True
cmd = getattr(self._config.tasks, loader)
btn = ttk.Button(
frame,
image=get_images().icons[btntype],
command=lambda fn=cmd, kw=kwargs: fn(**kw))
btn.pack(side=tk.LEFT, anchor=tk.W)
hlp = self.set_help(btntype)
Tooltip(btn, text=hlp, wrap_length=200)
@staticmethod
def _loader_and_kwargs(btntype):
if btntype == "save": if btntype == "save":
loader = btntype loader = btntype
kwargs = dict(save_as=False) kwargs = {"save_as": False}
elif btntype == "save_as": elif btntype == "save_as":
loader = "save" loader = "save"
kwargs = dict(save_as=True) kwargs = {"save_as": True}
else: else:
loader = btntype loader = btntype
kwargs = {} kwargs = {}
logger.debug("btntype: %s, loader: %s, kwargs: %s", btntype, loader, kwargs) logger.debug("btntype: %s, loader: %s, kwargs: %s", btntype, loader, kwargs)
return loader, kwargs return loader, kwargs
def _settings_btns(self): @classmethod
# pylint: disable=cell-var-from-loop def _set_help(cls, btntype: str) -> str:
frame = ttk.Frame(self._btn_frame) """ Set the helptext for option buttons
frame.pack(side=tk.LEFT, anchor=tk.W, expand=False, padx=2)
for name in ("extract", "train", "convert"):
btntype = f"settings_{name}"
btntype = btntype if btntype in get_images().icons else "settings"
logger.debug("Adding button: '%s'", btntype)
btn = ttk.Button(
frame,
image=get_images().icons[btntype],
command=lambda n=name: open_popup(name=n))
btn.pack(side=tk.LEFT, anchor=tk.W)
hlp = _("Configure {} settings...").format(name.title())
Tooltip(btn, text=hlp, wrap_length=200)
@staticmethod Parameters
def set_help(btntype): ----------
""" Set the helptext for option buttons """ btntype: str
The button type to set the help text for
"""
logger.debug("Setting help") logger.debug("Setting help")
hlp = "" hlp = ""
task = _("currently selected Task") if btntype[-1] == "2" else _("Project") task = _("currently selected Task") if btntype[-1] == "2" else _("Project")
@ -559,11 +604,68 @@ class TaskBar(ttk.Frame): # pylint: disable=too-many-ancestors
hlp = _("Load {}...").format(msg) hlp = _("Load {}...").format(msg)
return hlp return hlp
def _group_separator(self): def _project_btns(self) -> None:
""" Place the project buttons """
frame = ttk.Frame(self._btn_frame)
frame.pack(side=tk.LEFT, anchor=tk.W, expand=False, padx=2)
for btntype in ("new", "load", "save", "save_as", "reload"):
logger.debug("Adding button: '%s'", btntype)
loader, kwargs = self._loader_and_kwargs(btntype)
cmd = getattr(self._config.project, loader)
btn = ttk.Button(frame,
image=get_images().icons[btntype],
command=lambda fn=cmd, kw=kwargs: fn(**kw)) # type:ignore
btn.pack(side=tk.LEFT, anchor=tk.W)
hlp = self._set_help(btntype)
Tooltip(btn, text=hlp, wrap_length=200)
def _task_btns(self) -> None:
""" Place the task buttons """
frame = ttk.Frame(self._btn_frame)
frame.pack(side=tk.LEFT, anchor=tk.W, expand=False, padx=2)
for loadtype in ("load", "save", "save_as", "clear", "reload"):
btntype = f"{loadtype}2"
logger.debug("Adding button: '%s'", btntype)
loader, kwargs = self._loader_and_kwargs(loadtype)
if loadtype == "load":
kwargs["current_tab"] = True
cmd = getattr(self._config.tasks, loader)
btn = ttk.Button(
frame,
image=get_images().icons[btntype],
command=lambda fn=cmd, kw=kwargs: fn(**kw)) # type:ignore
btn.pack(side=tk.LEFT, anchor=tk.W)
hlp = self._set_help(btntype)
Tooltip(btn, text=hlp, wrap_length=200)
def _settings_btns(self) -> None:
""" Place the settings buttons """
# pylint: disable=cell-var-from-loop
frame = ttk.Frame(self._btn_frame)
frame.pack(side=tk.LEFT, anchor=tk.W, expand=False, padx=2)
for name in ("extract", "train", "convert"):
btntype = f"settings_{name}"
btntype = btntype if btntype in get_images().icons else "settings"
logger.debug("Adding button: '%s'", btntype)
btn = ttk.Button(
frame,
image=get_images().icons[btntype],
command=lambda n=name: open_popup(name=n)) # type:ignore
btn.pack(side=tk.LEFT, anchor=tk.W)
hlp = _("Configure {} settings...").format(name.title())
Tooltip(btn, text=hlp, wrap_length=200)
def _group_separator(self) -> None:
""" Place a group separator """
separator = ttk.Separator(self._btn_frame, orient="vertical") separator = ttk.Separator(self._btn_frame, orient="vertical")
separator.pack(padx=(2, 1), fill=tk.Y, side=tk.LEFT) separator.pack(padx=(2, 1), fill=tk.Y, side=tk.LEFT)
def _section_separator(self): def _section_separator(self) -> None:
""" Place a section separator """
frame = ttk.Frame(self) frame = ttk.Frame(self)
frame.pack(side=tk.BOTTOM, fill=tk.X) frame.pack(side=tk.BOTTOM, fill=tk.X)
separator = ttk.Separator(frame, orient="horizontal") separator = ttk.Separator(frame, orient="horizontal")

Binary file not shown.

View file

@ -0,0 +1,155 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: faceswap.spanish\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-06-07 13:54+0100\n"
"PO-Revision-Date: 2023-06-07 14:11+0100\n"
"Last-Translator: \n"
"Language-Team: tokafondo\n"
"Language: es_ES\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"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 3.3.1\n"
#: lib/gui/menu.py:37
msgid "faceswap.dev - Guides and Forum"
msgstr "faceswap.dev - Guías y foro"
#: lib/gui/menu.py:38
msgid "Patreon - Support this project"
msgstr "Patreon - Apoya este proyecto"
#: lib/gui/menu.py:39
msgid "Discord - The FaceSwap Discord server"
msgstr "Discord - El servidor de Discord de FaceSwap"
#: lib/gui/menu.py:40
msgid "Github - Our Source Code"
msgstr "Github - Nuestro código fuente"
#: lib/gui/menu.py:60
msgid "File"
msgstr ""
#: lib/gui/menu.py:61
msgid "Settings"
msgstr ""
#: lib/gui/menu.py:62
msgid "Help"
msgstr ""
#: lib/gui/menu.py:85
msgid "Configure Settings..."
msgstr ""
#: lib/gui/menu.py:116
msgid "New Project..."
msgstr ""
#: lib/gui/menu.py:121
msgid "Open Project..."
msgstr ""
#: lib/gui/menu.py:126
msgid "Save Project"
msgstr ""
#: lib/gui/menu.py:131
msgid "Save Project as..."
msgstr ""
#: lib/gui/menu.py:136
msgid "Reload Project from Disk"
msgstr ""
#: lib/gui/menu.py:141
msgid "Close Project"
msgstr ""
#: lib/gui/menu.py:147
msgid "Open Task..."
msgstr ""
#: lib/gui/menu.py:154
msgid "Open recent"
msgstr ""
#: lib/gui/menu.py:156
msgid "Quit"
msgstr ""
#: lib/gui/menu.py:211
msgid "{} Task"
msgstr ""
#: lib/gui/menu.py:223
msgid "Clear recent files"
msgstr ""
#: lib/gui/menu.py:391
msgid "Check for updates..."
msgstr ""
#: lib/gui/menu.py:394
msgid "Update Faceswap..."
msgstr ""
#: lib/gui/menu.py:398
msgid "Switch Branch"
msgstr ""
#: lib/gui/menu.py:401
msgid "Resources"
msgstr ""
#: lib/gui/menu.py:404
msgid "Output System Information"
msgstr ""
#: lib/gui/menu.py:589
msgid "currently selected Task"
msgstr "tarea actualmente seleccionada"
#: lib/gui/menu.py:589
msgid "Project"
msgstr "Proyecto"
#: lib/gui/menu.py:591
msgid "Reload {} from disk"
msgstr "Recargar {} del disco"
#: lib/gui/menu.py:593
msgid "Create a new {}..."
msgstr "Crear un nuevo {}..."
#: lib/gui/menu.py:595
msgid "Reset {} to default"
msgstr "Reiniciar {} a los ajustes por defecto"
#: lib/gui/menu.py:597
msgid "Save {}"
msgstr "Guardar {}"
#: lib/gui/menu.py:599
msgid "Save {} as..."
msgstr "Guardar {} como..."
#: lib/gui/menu.py:603
msgid " from a task or project file"
msgstr " de un archivo de tarea o proyecto"
#: lib/gui/menu.py:604
msgid "Load {}..."
msgstr "Cargar {}..."
#: lib/gui/menu.py:659
msgid "Configure {} settings..."
msgstr "Configurar los ajustes de {}..."

View file

@ -6,16 +6,16 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: faceswap.spanish\n" "Project-Id-Version: faceswap.spanish\n"
"POT-Creation-Date: 2021-03-22 18:37+0000\n" "POT-Creation-Date: 2021-03-22 18:37+0000\n"
"PO-Revision-Date: 2021-03-22 18:39+0000\n" "PO-Revision-Date: 2023-06-07 14:12+0100\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: tokafondo\n" "Language-Team: tokafondo\n"
"Language: es_ES\n" "Language: es_ES\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 2.4.2\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 3.3.1\n"
#: lib/gui/command.py:184 #: lib/gui/command.py:184
msgid "Output command line options to the console" msgid "Output command line options to the console"
@ -129,62 +129,6 @@ msgstr "Grabar {} a un fichero"
msgid "Enable or disable {} display" msgid "Enable or disable {} display"
msgstr "Activar o desactivar la muestra de {}" msgstr "Activar o desactivar la muestra de {}"
#: lib/gui/menu.py:32
msgid "faceswap.dev - Guides and Forum"
msgstr "faceswap.dev - Guías y foro"
#: lib/gui/menu.py:33
msgid "Patreon - Support this project"
msgstr "Patreon - Apoya este proyecto"
#: lib/gui/menu.py:34
msgid "Discord - The FaceSwap Discord server"
msgstr "Discord - El servidor de Discord de FaceSwap"
#: lib/gui/menu.py:35
msgid "Github - Our Source Code"
msgstr "Github - Nuestro código fuente"
#: lib/gui/menu.py:527
msgid "Configure {} settings..."
msgstr "Configurar los ajustes de {}..."
#: lib/gui/menu.py:535
msgid "Project"
msgstr "Proyecto"
#: lib/gui/menu.py:535
msgid "currently selected Task"
msgstr "tarea actualmente seleccionada"
#: lib/gui/menu.py:537
msgid "Reload {} from disk"
msgstr "Recargar {} del disco"
#: lib/gui/menu.py:539
msgid "Create a new {}..."
msgstr "Crear un nuevo {}..."
#: lib/gui/menu.py:541
msgid "Reset {} to default"
msgstr "Reiniciar {} a los ajustes por defecto"
#: lib/gui/menu.py:543
msgid "Save {}"
msgstr "Guardar {}"
#: lib/gui/menu.py:545
msgid "Save {} as..."
msgstr "Guardar {} como..."
#: lib/gui/menu.py:549
msgid " from a task or project file"
msgstr " de un archivo de tarea o proyecto"
#: lib/gui/menu.py:550
msgid "Load {}..."
msgstr "Cargar {}..."
#: lib/gui/popup_configure.py:209 #: lib/gui/popup_configure.py:209
msgid "Close without saving" msgid "Close without saving"
msgstr "Cerrar sin guardar" msgstr "Cerrar sin guardar"

154
locales/gui.menu.pot Normal file
View file

@ -0,0 +1,154 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-06-07 13:54+0100\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"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ./lib/gui/menu.py:37
msgid "faceswap.dev - Guides and Forum"
msgstr ""
#: ./lib/gui/menu.py:38
msgid "Patreon - Support this project"
msgstr ""
#: ./lib/gui/menu.py:39
msgid "Discord - The FaceSwap Discord server"
msgstr ""
#: ./lib/gui/menu.py:40
msgid "Github - Our Source Code"
msgstr ""
#: ./lib/gui/menu.py:60
msgid "File"
msgstr ""
#: ./lib/gui/menu.py:61
msgid "Settings"
msgstr ""
#: ./lib/gui/menu.py:62
msgid "Help"
msgstr ""
#: ./lib/gui/menu.py:85
msgid "Configure Settings..."
msgstr ""
#: ./lib/gui/menu.py:116
msgid "New Project..."
msgstr ""
#: ./lib/gui/menu.py:121
msgid "Open Project..."
msgstr ""
#: ./lib/gui/menu.py:126
msgid "Save Project"
msgstr ""
#: ./lib/gui/menu.py:131
msgid "Save Project as..."
msgstr ""
#: ./lib/gui/menu.py:136
msgid "Reload Project from Disk"
msgstr ""
#: ./lib/gui/menu.py:141
msgid "Close Project"
msgstr ""
#: ./lib/gui/menu.py:147
msgid "Open Task..."
msgstr ""
#: ./lib/gui/menu.py:154
msgid "Open recent"
msgstr ""
#: ./lib/gui/menu.py:156
msgid "Quit"
msgstr ""
#: ./lib/gui/menu.py:211
msgid "{} Task"
msgstr ""
#: ./lib/gui/menu.py:223
msgid "Clear recent files"
msgstr ""
#: ./lib/gui/menu.py:391
msgid "Check for updates..."
msgstr ""
#: ./lib/gui/menu.py:394
msgid "Update Faceswap..."
msgstr ""
#: ./lib/gui/menu.py:398
msgid "Switch Branch"
msgstr ""
#: ./lib/gui/menu.py:401
msgid "Resources"
msgstr ""
#: ./lib/gui/menu.py:404
msgid "Output System Information"
msgstr ""
#: ./lib/gui/menu.py:589
msgid "currently selected Task"
msgstr ""
#: ./lib/gui/menu.py:589
msgid "Project"
msgstr ""
#: ./lib/gui/menu.py:591
msgid "Reload {} from disk"
msgstr ""
#: ./lib/gui/menu.py:593
msgid "Create a new {}..."
msgstr ""
#: ./lib/gui/menu.py:595
msgid "Reset {} to default"
msgstr ""
#: ./lib/gui/menu.py:597
msgid "Save {}"
msgstr ""
#: ./lib/gui/menu.py:599
msgid "Save {} as..."
msgstr ""
#: ./lib/gui/menu.py:603
msgid " from a task or project file"
msgstr ""
#: ./lib/gui/menu.py:604
msgid "Load {}..."
msgstr ""
#: ./lib/gui/menu.py:659
msgid "Configure {} settings..."
msgstr ""

View file

@ -119,62 +119,6 @@ msgstr ""
msgid "Enable or disable {} display" msgid "Enable or disable {} display"
msgstr "" msgstr ""
#: ./lib/gui/menu.py:32
msgid "faceswap.dev - Guides and Forum"
msgstr ""
#: ./lib/gui/menu.py:33
msgid "Patreon - Support this project"
msgstr ""
#: ./lib/gui/menu.py:34
msgid "Discord - The FaceSwap Discord server"
msgstr ""
#: ./lib/gui/menu.py:35
msgid "Github - Our Source Code"
msgstr ""
#: ./lib/gui/menu.py:527
msgid "Configure {} settings..."
msgstr ""
#: ./lib/gui/menu.py:535
msgid "Project"
msgstr ""
#: ./lib/gui/menu.py:535
msgid "currently selected Task"
msgstr ""
#: ./lib/gui/menu.py:537
msgid "Reload {} from disk"
msgstr ""
#: ./lib/gui/menu.py:539
msgid "Create a new {}..."
msgstr ""
#: ./lib/gui/menu.py:541
msgid "Reset {} to default"
msgstr ""
#: ./lib/gui/menu.py:543
msgid "Save {}"
msgstr ""
#: ./lib/gui/menu.py:545
msgid "Save {} as..."
msgstr ""
#: ./lib/gui/menu.py:549
msgid " from a task or project file"
msgstr ""
#: ./lib/gui/menu.py:550
msgid "Load {}..."
msgstr ""
#: ./lib/gui/popup_configure.py:209 #: ./lib/gui/popup_configure.py:209
msgid "Close without saving" msgid "Close without saving"
msgstr "" msgstr ""

Binary file not shown.

View file

@ -0,0 +1,155 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-06-07 13:54+0100\n"
"PO-Revision-Date: 2023-06-07 14:11+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: ko_KR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 3.3.1\n"
#: lib/gui/menu.py:37
msgid "faceswap.dev - Guides and Forum"
msgstr "faceswap.dev - Guides and Forum"
#: lib/gui/menu.py:38
msgid "Patreon - Support this project"
msgstr "Patreon - Support this project"
#: lib/gui/menu.py:39
msgid "Discord - The FaceSwap Discord server"
msgstr "Discord - The FaceSwap Discord server"
#: lib/gui/menu.py:40
msgid "Github - Our Source Code"
msgstr "Github - Our Source Code"
#: lib/gui/menu.py:60
msgid "File"
msgstr ""
#: lib/gui/menu.py:61
msgid "Settings"
msgstr ""
#: lib/gui/menu.py:62
msgid "Help"
msgstr ""
#: lib/gui/menu.py:85
msgid "Configure Settings..."
msgstr ""
#: lib/gui/menu.py:116
msgid "New Project..."
msgstr ""
#: lib/gui/menu.py:121
msgid "Open Project..."
msgstr ""
#: lib/gui/menu.py:126
msgid "Save Project"
msgstr ""
#: lib/gui/menu.py:131
msgid "Save Project as..."
msgstr ""
#: lib/gui/menu.py:136
msgid "Reload Project from Disk"
msgstr ""
#: lib/gui/menu.py:141
msgid "Close Project"
msgstr ""
#: lib/gui/menu.py:147
msgid "Open Task..."
msgstr ""
#: lib/gui/menu.py:154
msgid "Open recent"
msgstr ""
#: lib/gui/menu.py:156
msgid "Quit"
msgstr ""
#: lib/gui/menu.py:211
msgid "{} Task"
msgstr ""
#: lib/gui/menu.py:223
msgid "Clear recent files"
msgstr ""
#: lib/gui/menu.py:391
msgid "Check for updates..."
msgstr ""
#: lib/gui/menu.py:394
msgid "Update Faceswap..."
msgstr ""
#: lib/gui/menu.py:398
msgid "Switch Branch"
msgstr ""
#: lib/gui/menu.py:401
msgid "Resources"
msgstr ""
#: lib/gui/menu.py:404
msgid "Output System Information"
msgstr ""
#: lib/gui/menu.py:589
msgid "currently selected Task"
msgstr "현재 선택된 작업"
#: lib/gui/menu.py:589
msgid "Project"
msgstr "프로젝트"
#: lib/gui/menu.py:591
msgid "Reload {} from disk"
msgstr "디스크에서 {}를 다시 가져옵니다"
#: lib/gui/menu.py:593
msgid "Create a new {}..."
msgstr "새로운 {}를 만들기."
#: lib/gui/menu.py:595
msgid "Reset {} to default"
msgstr "{} 기본으로 재설정"
#: lib/gui/menu.py:597
msgid "Save {}"
msgstr "{} 저장"
#: lib/gui/menu.py:599
msgid "Save {} as..."
msgstr "{}를 다른 이름으로 저장."
#: lib/gui/menu.py:603
msgid " from a task or project file"
msgstr " 작업 또는 프로젝트 파일에서"
#: lib/gui/menu.py:604
msgid "Load {}..."
msgstr "{} 가져오기."
#: lib/gui/menu.py:659
msgid "Configure {} settings..."
msgstr "{} 세팅 설정하기."

View file

@ -6,7 +6,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"POT-Creation-Date: 2021-03-22 18:37+0000\n" "POT-Creation-Date: 2021-03-22 18:37+0000\n"
"PO-Revision-Date: 2022-11-26 16:12+0900\n" "PO-Revision-Date: 2023-06-07 14:13+0100\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"Language: ko_KR\n" "Language: ko_KR\n"
@ -15,7 +15,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
"Generated-By: pygettext.py 1.5\n" "Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 3.2\n" "X-Generator: Poedit 3.3.1\n"
#: lib/gui/command.py:184 #: lib/gui/command.py:184
msgid "Output command line options to the console" msgid "Output command line options to the console"
@ -128,62 +128,6 @@ msgstr "{}(s)를 파일에 저장합니다"
msgid "Enable or disable {} display" msgid "Enable or disable {} display"
msgstr "{} display를 활성화 또는 비활성화" msgstr "{} display를 활성화 또는 비활성화"
#: lib/gui/menu.py:32
msgid "faceswap.dev - Guides and Forum"
msgstr "faceswap.dev - Guides and Forum"
#: lib/gui/menu.py:33
msgid "Patreon - Support this project"
msgstr "Patreon - Support this project"
#: lib/gui/menu.py:34
msgid "Discord - The FaceSwap Discord server"
msgstr "Discord - The FaceSwap Discord server"
#: lib/gui/menu.py:35
msgid "Github - Our Source Code"
msgstr "Github - Our Source Code"
#: lib/gui/menu.py:527
msgid "Configure {} settings..."
msgstr "{} 세팅 설정하기."
#: lib/gui/menu.py:535
msgid "Project"
msgstr "프로젝트"
#: lib/gui/menu.py:535
msgid "currently selected Task"
msgstr "현재 선택된 작업"
#: lib/gui/menu.py:537
msgid "Reload {} from disk"
msgstr "디스크에서 {}를 다시 가져옵니다"
#: lib/gui/menu.py:539
msgid "Create a new {}..."
msgstr "새로운 {}를 만들기."
#: lib/gui/menu.py:541
msgid "Reset {} to default"
msgstr "{} 기본으로 재설정"
#: lib/gui/menu.py:543
msgid "Save {}"
msgstr "{} 저장"
#: lib/gui/menu.py:545
msgid "Save {} as..."
msgstr "{}를 다른 이름으로 저장."
#: lib/gui/menu.py:549
msgid " from a task or project file"
msgstr " 작업 또는 프로젝트 파일에서"
#: lib/gui/menu.py:550
msgid "Load {}..."
msgstr "{} 가져오기."
#: lib/gui/popup_configure.py:209 #: lib/gui/popup_configure.py:209
msgid "Close without saving" msgid "Close without saving"
msgstr "저장하지 않고 닫기" msgstr "저장하지 않고 닫기"

Binary file not shown.

View file

@ -0,0 +1,156 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-06-07 13:54+0100\n"
"PO-Revision-Date: 2023-06-07 14:05+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: ru\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%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 3.3.1\n"
#: ./lib/gui/menu.py:37
msgid "faceswap.dev - Guides and Forum"
msgstr "faceswap.dev - Руководства и Форум"
#: ./lib/gui/menu.py:38
msgid "Patreon - Support this project"
msgstr "Patreon - Поддержите этот проект"
#: ./lib/gui/menu.py:39
msgid "Discord - The FaceSwap Discord server"
msgstr "Discord - Discord сервер Faceswap"
#: ./lib/gui/menu.py:40
msgid "Github - Our Source Code"
msgstr "Github - Наш исходный код"
#: ./lib/gui/menu.py:60
msgid "File"
msgstr ""
#: ./lib/gui/menu.py:61
msgid "Settings"
msgstr ""
#: ./lib/gui/menu.py:62
msgid "Help"
msgstr ""
#: ./lib/gui/menu.py:85
msgid "Configure Settings..."
msgstr ""
#: ./lib/gui/menu.py:116
msgid "New Project..."
msgstr ""
#: ./lib/gui/menu.py:121
msgid "Open Project..."
msgstr ""
#: ./lib/gui/menu.py:126
msgid "Save Project"
msgstr ""
#: ./lib/gui/menu.py:131
msgid "Save Project as..."
msgstr ""
#: ./lib/gui/menu.py:136
msgid "Reload Project from Disk"
msgstr ""
#: ./lib/gui/menu.py:141
msgid "Close Project"
msgstr ""
#: ./lib/gui/menu.py:147
msgid "Open Task..."
msgstr ""
#: ./lib/gui/menu.py:154
msgid "Open recent"
msgstr ""
#: ./lib/gui/menu.py:156
msgid "Quit"
msgstr ""
#: ./lib/gui/menu.py:211
msgid "{} Task"
msgstr ""
#: ./lib/gui/menu.py:223
msgid "Clear recent files"
msgstr ""
#: ./lib/gui/menu.py:391
msgid "Check for updates..."
msgstr ""
#: ./lib/gui/menu.py:394
msgid "Update Faceswap..."
msgstr ""
#: ./lib/gui/menu.py:398
msgid "Switch Branch"
msgstr ""
#: ./lib/gui/menu.py:401
msgid "Resources"
msgstr ""
#: ./lib/gui/menu.py:404
msgid "Output System Information"
msgstr ""
#: ./lib/gui/menu.py:589
msgid "currently selected Task"
msgstr "текущая выбранная задача"
#: ./lib/gui/menu.py:589
msgid "Project"
msgstr "Проект"
#: ./lib/gui/menu.py:591
msgid "Reload {} from disk"
msgstr "Перезагрузить {} из диска"
#: ./lib/gui/menu.py:593
msgid "Create a new {}..."
msgstr "Создать новый {}..."
#: ./lib/gui/menu.py:595
msgid "Reset {} to default"
msgstr "Сбросить {} по умолчанию"
#: ./lib/gui/menu.py:597
msgid "Save {}"
msgstr "Сохранить {}"
#: ./lib/gui/menu.py:599
msgid "Save {} as..."
msgstr "Сохранить {} как..."
#: ./lib/gui/menu.py:603
msgid " from a task or project file"
msgstr " из файла задачи или проекта"
#: ./lib/gui/menu.py:604
msgid "Load {}..."
msgstr "Загрузить {}..."
#: ./lib/gui/menu.py:659
msgid "Configure {} settings..."
msgstr "Настройка параметров {}..."

View file

@ -6,7 +6,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"POT-Creation-Date: 2021-03-22 18:37+0000\n" "POT-Creation-Date: 2021-03-22 18:37+0000\n"
"PO-Revision-Date: 2023-04-11 16:07+0700\n" "PO-Revision-Date: 2023-06-07 14:14+0100\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"Language: ru\n" "Language: ru\n"
@ -16,7 +16,7 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n" "n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
"Generated-By: pygettext.py 1.5\n" "Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 3.2.2\n" "X-Generator: Poedit 3.3.1\n"
#: lib/gui/command.py:184 #: lib/gui/command.py:184
msgid "Output command line options to the console" msgid "Output command line options to the console"
@ -129,62 +129,6 @@ msgstr "Сохранить {}(ы) в файл"
msgid "Enable or disable {} display" msgid "Enable or disable {} display"
msgstr "Включить или выключить отображение {}" msgstr "Включить или выключить отображение {}"
#: lib/gui/menu.py:32
msgid "faceswap.dev - Guides and Forum"
msgstr "faceswap.dev - Руководства и Форум"
#: lib/gui/menu.py:33
msgid "Patreon - Support this project"
msgstr "Patreon - Поддержите этот проект"
#: lib/gui/menu.py:34
msgid "Discord - The FaceSwap Discord server"
msgstr "Discord - Discord сервер Faceswap"
#: lib/gui/menu.py:35
msgid "Github - Our Source Code"
msgstr "Github - Наш исходный код"
#: lib/gui/menu.py:527
msgid "Configure {} settings..."
msgstr "Настройка параметров {}..."
#: lib/gui/menu.py:535
msgid "Project"
msgstr "Проект"
#: lib/gui/menu.py:535
msgid "currently selected Task"
msgstr "текущая выбранная задача"
#: lib/gui/menu.py:537
msgid "Reload {} from disk"
msgstr "Перезагрузить {} из диска"
#: lib/gui/menu.py:539
msgid "Create a new {}..."
msgstr "Создать новый {}..."
#: lib/gui/menu.py:541
msgid "Reset {} to default"
msgstr "Сбросить {} по умолчанию"
#: lib/gui/menu.py:543
msgid "Save {}"
msgstr "Сохранить {}"
#: lib/gui/menu.py:545
msgid "Save {} as..."
msgstr "Сохранить {} как..."
#: lib/gui/menu.py:549
msgid " from a task or project file"
msgstr " из файла задачи или проекта"
#: lib/gui/menu.py:550
msgid "Load {}..."
msgstr "Загрузить {}..."
#: lib/gui/popup_configure.py:209 #: lib/gui/popup_configure.py:209
msgid "Close without saving" msgid "Close without saving"
msgstr "Закрыть без сохранения" msgstr "Закрыть без сохранения"