1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2026-01-25 16:11:39 +00:00

Compare commits

...

71 Commits

Author SHA1 Message Date
5a4958cff9 Update translation .pot files 2021-08-17 21:18:47 -05:00
be10b462fc Add portable mode
If settings.ini is present next to the executable, will run in portable mode.
This results in settings, data, and cache all being in same folder as dupeGuru.
2021-08-17 21:12:32 -05:00
d62b13bcdb Removing travis
- All CI is now covered by Github Actions
- Remove .travis.yml
- Remove tox-travis in requirements-extra.txt
2021-08-17 18:16:20 -05:00
06eca11f0b Remove format check from lint job 2021-08-17 00:52:14 -05:00
2879f18e0d Run linting and formatting check in parallel before test 2021-08-17 00:50:41 -05:00
3ee21771f9 Fix workflow file format 2021-08-17 00:33:54 -05:00
c0ba6fb57a Test out github actions
Add a workflow to test
2021-08-17 00:31:15 -05:00
bc942b8263 Add black format check to tox runs 2021-08-15 04:10:46 -05:00
ffe6b7047c Format all files with black correcting line length 2021-08-15 04:10:18 -05:00
9446f37fad Remove flake8 E731 Errors
Note: black formatting is now applying correctly as well.
2021-08-15 03:53:43 -05:00
af19660c18 Update flake8 and black configuration
- Update black to now use 120 lines
- Update flake8 to use recommended settings for black integration
2021-08-15 03:32:31 -05:00
99ad297906 Change preferences to use spinboxes where applicable
- Change LineEdit to Spinbox for minimum file size 0-1,000,000KB
- Change LineEdit to Spinbox for big file size 0-1,000,000MB
2021-08-15 02:11:42 -05:00
e11f996dfc Merge pull request #908 from glubsy/hash_sample_optimization
Hash sample optimization
2021-08-13 23:41:17 -05:00
glubsy
e95306e58f Fix flake 8 2021-08-14 02:52:00 +02:00
glubsy
891a875990 Cache constant expression
Perhaps the python byte code is already optimized, but just in case it is not, keep pre-compute the constant expression.
2021-08-13 21:33:21 +02:00
glubsy
545a5a75fb Fix for older python versions
The "walrus" operator is only available in python 3.8 and later. Fall back to more traditional notation.
2021-08-13 20:56:33 +02:00
glubsy
7b764f183e Avoid partially hashing small files
Computing 3 hash samples for files less than 3MiB (3 * CHUNK_SIZE) is not efficient since spans of later samples would overlap a previous one.
Therefore we can simply return the hash of the entire small file instead.
2021-08-13 20:47:01 +02:00
fdc8a17d26 Update .travis.yml
- Windows test uses 3.9.6 now
- Intentation changes
2021-08-07 19:35:57 -05:00
cb3bbbec6e Upgrade Requirement Minimums
- Upgrade requirements to specify more current minimums
- Remove compatability code from sphinxgen for old versions
- Upgrade pyinstaller to a minimum version that works with latest macOS
2021-08-07 19:28:41 -05:00
c51a82a2ce Fix Issues from Translation Update
- Add Qtlib to transifex config
- Pull latest qtlib translations
- Fix flake8 error
- Remove code for manual translation import, use transifex-client instead
2021-08-06 22:21:35 -05:00
0cd8f5e948 Update translation pot files 2021-08-06 21:41:52 -05:00
9c09607c08 Add Turkish & Updates from Transifex
- Pull updates from Transifex
- Add Turkish
- Sort language lists in code
- Remove old locale conversion code as it appears to work correctly on
windows without different conversions.
2021-08-06 21:41:52 -05:00
3bd342770c Update configurations
- Enable Unicode for NSIS Installer
- Update transifex config to new project
2021-08-06 21:41:52 -05:00
14b456dcf9 Merge pull request #927 from glubsy/fix_directories_tests
Fix Directories regex test
2021-08-06 20:08:27 -05:00
glubsy
3dccb686e2 Fix Directories regex test
The entire path to the file would match unless another path separator is added.
2021-08-06 17:18:23 +02:00
0db66baace Merge pull request #907 from glubsy/missing_renamed_regex
Missing renamed regex
2021-08-03 22:26:08 -05:00
e3828ae2ca Merge pull request #911 from glubsy/fix_757_fix_regression
Fix infinite recursion
2021-06-22 22:44:12 -05:00
glubsy
23c59787e5 Fix infinite recursion
Force the Results to update its internal __dupes list whenever at least one group has re-prioritized and changed its dupes/ref.
2021-06-23 05:36:10 +02:00
2f8d603251 Merge pull request #910 from glubsy/757_fix
Fix refs appearing in dupes-only view
2021-06-22 21:54:49 -05:00
glubsy
a51f263632 Fix refs appearing in dupes-only view
* Some refs appeared in the dupes-only view after a re-prioritization was done a second time.
* It seems the core.Results.__dupes list was not properly updated whenever core.app.Dupeguru.reprioritize_groups() -> core.Results.sort_dupes() was called.
When a re-prioritization is done, some refs became dupe, and some dupes became ref in their place. So we need to update the new state of the internal list of dupes kept by the Results object, instead of relying on the outdated cached one.
* Fix #757.
2021-06-22 22:57:57 +02:00
glubsy
718ca5b313 Remove unused import 2021-06-22 02:41:33 +02:00
glubsy
277bc3fbb8 Add unit tests for hash sample optimization
* Instead of keeping md5 samples separate, merge them as one hash computed from the various selected chunks we picked.
* We don't need to keep a boolean to see whether or not the user chose to optimize; we can simply compare the value of the threshold, since 0 means no optimization currently active.
2021-06-21 22:44:05 +02:00
glubsy
e07dfd5955 Add partial hashes optimization for big files
* Big files above the user selected threshold can be partially hashed in 3 places.
* If the user is willing to take the risk, we consider files with identical md5samples as being identical.
2021-06-21 19:03:21 +02:00
4641bd6ec9 Merge pull request #905 from glubsy/fix_863
Fix exception when deleting while in delta view
2021-06-19 20:29:47 -05:00
glubsy
a6f83ad3d7 Fix missing regexp after rename
* Doing a full match should be safer to avoid partial results which would result in overly aggressive filtering.
* Add new tests to test suite to cover this issue.
* Fixes #903.
2021-06-19 02:00:25 +02:00
glubsy
ab8750eedb Fix partial regex match yielding false positive 2021-06-17 03:49:59 +02:00
glubsy
22033211d6 Fix exception when deleting while in delta view 2021-05-31 23:49:21 +02:00
0b46ca2222 Merge pull request #879 from glubsy/fix_unicode
Fix stripping (japanese) unicode characters
2021-05-25 19:11:19 -05:00
72e0f76242 Merge pull request #898 from AlttiRi/master
Change reference background color #894
2021-05-25 19:10:31 -05:00
[Alt'tiRi]
65c1d463f8 Change reference background color #894 2021-05-22 02:52:41 +03:00
e6c791ab0a Merge pull request #884 from samusz/master
Small typo
2021-05-09 23:32:32 -05:00
Sacha Muszlak
78f5088101 Merge pull request #1 from samusz/samusz-patch-1
typo correction
2021-05-07 09:41:47 +02:00
Sacha Muszlak
095df5eb95 typo correction 2021-05-07 09:40:08 +02:00
glubsy
f1ae478433 Fix including character at the border 2021-04-29 05:29:35 +02:00
glubsy
c4dcfd3d4b Fix stripping (japanese) unicode characters
* Accents are getting removed from Unicode characters to generate similar "words".
* Non-latin characters which cannot be processed that way (eg. japanese, greek, russian, etc.) should not be filtered out at all otherwise files are erroneously skipped or detected as dupes if only some characters make it passed the filter.
* Starting from an arbitrary unicode codepoint (converted to decimal), above which we know it is pointless to try any sort of processing, we leave the characters as is.
* Fix #878.
2021-04-29 05:15:34 +02:00
0840104edf Merge pull request #873 from glubsy/fix_857
Fix 857
2021-04-20 20:05:05 -05:00
glubsy
6b4b436251 Fix crash on shutdown
* Fixes "'DetailsPanel' object has no attribute '_table'" error on shutdown if the Results table is updated (item removed) while the Details Dialog is shown as a floating window.
* It seems that QApplication.quit() triggers some sort of refresh on the floating QDockWidget, which in turn makes calls to the underlying model that is possibly being destroyed, ie. there might be a race condition here.
* Closing or hiding the QDockWidget before the cal to quit() is a workaround. Similarly, this is already done in the quitTriggered() method anyway.
* This fixes #857.
2021-04-16 17:54:49 +02:00
glubsy
d18b8c10ec Remove redundant assignment
The "app" field is already set in the parent class.
2021-04-15 18:03:00 +02:00
4a40b346a4 Update to 4.1.1 2021-03-21 22:50:33 -05:00
035cdc23b1 Update translations from Transifex 2021-03-21 22:45:19 -05:00
fbdb333457 Update a few translation items
- Add Japanese as a selectable language
- Wrap a few missed strings in tr()
- Regenerate .pot files
2021-03-17 20:21:29 -05:00
e36aab177c Add import feature to build.py for translations 2021-03-17 19:55:00 -05:00
77116ba94b Bring in the languages that came incorrect last import again 2021-03-17 19:44:16 -05:00
d7f79aefd2 Remove translations imported incorrectly 2021-03-17 19:40:47 -05:00
4c939f379c Update translations from transifex 2021-03-09 21:16:37 -06:00
d098fe2281 Update translation pot files 2021-03-09 20:38:03 -06:00
09cfbad38d Merge pull request #844 from glubsy/translation_fixes
Fix problematic string for translations
2021-03-09 20:19:08 -06:00
glubsy
528dedd813 Fix problematic string for translations
Some languages have very different phrase syntaxes depending on which word is used.
Better used two separate strings than a dynamically created one.
2021-02-09 01:40:00 +01:00
b30d67b834 Merge pull request #775 from glubsy/PR_typo_fix
Fix label strings
2021-02-02 19:08:28 -06:00
glubsy
3e6e74e2a9 Update URL 2021-01-30 22:17:43 +01:00
glubsy
b919b3ddc8 Fix typo 2021-01-30 04:20:22 +01:00
glubsy
be3862fa8f fix typo 2021-01-29 18:56:29 +01:00
glubsy
da09920553 Update exclusion filter help string 2021-01-29 17:57:44 +01:00
glubsy
2baba3bfa0 Fix selection label 2021-01-29 17:38:37 +01:00
a659a70dbe Add transifex project link to readme 2021-01-28 23:04:44 -06:00
c9e48a5e3b Update pyrcc5 note with new information
New information about the other system package which resolves the dependency
added.
This was brought up in #766.
2021-01-21 19:08:59 -06:00
68711162d1 Add note about pyrcc5 2021-01-21 18:49:44 -06:00
0b0fd36629 Revert "Update ReadMe and requirements"
This reverts commit bf5d151799.
2021-01-21 18:33:40 -06:00
bf5d151799 Update ReadMe and requirements
- On linux (Debian based) pyrcc5 does not make it onto the path so
updating the notes here to take care of this behavior and update requirements
so virtual environment load it correctly.
- Fix #766
2021-01-21 18:13:17 -06:00
e29a427caf Update translation files 2021-01-11 22:38:03 -06:00
95ccbad92b Fix #760, issue with language on windows
Fix the issue related to run.py qsettings not using the same options as
in preferences.py
2021-01-11 21:41:14 -06:00
188 changed files with 18357 additions and 9181 deletions

74
.github/workflows/default.yml vendored Normal file
View File

@@ -0,0 +1,74 @@
# Workflow lints, and checks format in parallel then runs tests on all platforms
name: Default CI/CD
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt -r requirements-extra.txt
- name: Lint with flake8
run: |
flake8 .
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt -r requirements-extra.txt
- name: Check format with black
run: |
black .
test:
needs: [lint, format]
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [3.6, 3.7, 3.8, 3.9]
exclude:
- os: macos-latest
python-version: 3.6
- os: macos-latest
python-version: 3.7
- os: windows-latest
python-version: 3.6
- os: windows-latest
python-version: 3.7
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt -r requirements-extra.txt
- name: Build python modules
run: |
python build.py --modules
- name: Run tests
run: |
pytest core hscommon

1
.gitignore vendored
View File

@@ -19,6 +19,7 @@ cocoa/autogen
/qt/*_rc.py /qt/*_rc.py
/help/*/conf.py /help/*/conf.py
/help/*/changelog.rst /help/*/changelog.rst
/transifex
*.pyd *.pyd
*.exe *.exe

View File

@@ -1,27 +0,0 @@
sudo: false
language: python
install:
- pip3 install -r requirements.txt -r requirements-extra.txt
script: tox
matrix:
include:
- os: "linux"
dist: "xenial"
python: "3.6"
- os: "linux"
dist: "xenial"
python: "3.7"
- os: "linux"
dist: "focal"
python: "3.8"
- os: "linux"
dist: "focal"
python: "3.9"
- os: "windows"
language: shell
python: "3.8"
env: "PATH=/c/python38:/c/python38/Scripts:$PATH"
before_install:
- choco install python --version=3.8.6
- cp /c/python38/python.exe /c/python38/python3.exe
script: tox -e py38

View File

@@ -1,21 +1,26 @@
[main] [main]
host = https://www.transifex.com host = https://www.transifex.com
[dupeguru.core] [dupeguru-1.core]
file_filter = locale/<lang>/LC_MESSAGES/core.po file_filter = locale/<lang>/LC_MESSAGES/core.po
source_file = locale/core.pot source_file = locale/core.pot
source_lang = en source_lang = en
type = PO type = PO
[dupeguru.columns] [dupeguru-1.columns]
file_filter = locale/<lang>/LC_MESSAGES/columns.po file_filter = locale/<lang>/LC_MESSAGES/columns.po
source_file = locale/columns.pot source_file = locale/columns.pot
source_lang = en source_lang = en
type = PO type = PO
[dupeguru.ui] [dupeguru-1.ui]
file_filter = locale/<lang>/LC_MESSAGES/ui.po file_filter = locale/<lang>/LC_MESSAGES/ui.po
source_file = locale/ui.pot source_file = locale/ui.pot
source_lang = en source_lang = en
type = PO type = PO
[dupeguru-1.qtlib]
file_filter = qtlib/locale/<lang>/LC_MESSAGES/qtlib.po
source_file = qtlib/locale/qtlib.pot
source_lang = en
type = PO

View File

@@ -8,13 +8,10 @@ is written in Objective-C and uses Cocoa. On Linux, it is written in Python and
The Cocoa UI of dupeGuru is hosted in a separate repo: https://github.com/arsenetar/dupeguru-cocoa The Cocoa UI of dupeGuru is hosted in a separate repo: https://github.com/arsenetar/dupeguru-cocoa
## Current status ## Current status
2020: various bug fixes and small UI improvements have been added. Packaging for MacOS is still a problem.
Still looking for additional help especially with regards to: Still looking for additional help especially with regards to:
* OSX maintenance: reproducing bugs & cocoa version, building package with Cocoa UI. * OSX maintenance: reproducing bugs & cocoa version, building package with Cocoa UI.
* Linux maintenance: reproducing bugs, maintaining PPA repository, Debian package. * Linux maintenance: reproducing bugs, maintaining PPA repository, Debian package.
* Translations: updating missing strings. * Translations: updating missing strings, transifex project at https://www.transifex.com/voltaicideas/dupeguru-1
* Documentation: keeping it up-to-date. * Documentation: keeping it up-to-date.
## Contents of this folder ## Contents of this folder
@@ -45,11 +42,15 @@ For macos instructions (qt version) see the [macOS Instructions](macos.md).
### System Setup ### System Setup
When running in a linux based environment the following system packages or equivalents are needed to build: When running in a linux based environment the following system packages or equivalents are needed to build:
* python3-pyqt5 * python3-pyqt5
* pyqt5-dev-tools (on some systems, see note)
* python3-wheel (for hsaudiotag3k) * python3-wheel (for hsaudiotag3k)
* python3-venv (only if using a virtual environment) * python3-venv (only if using a virtual environment)
* python3-dev * python3-dev
* build-essential * build-essential
Note: On some linux systems pyrcc5 is not put on the path when installing python3-pyqt5, this will cause some issues with the resource files (and icons). These systems should have a respective pyqt5-dev-tools package, which should also be installed. The presence of pyrcc5 can be checked with `which pyrcc5`. Debian based systems need the extra package, and Arch does not.
To create packages the following are also needed: To create packages the following are also needed:
* python3-setuptools * python3-setuptools
* debhelper * debhelper

View File

@@ -30,12 +30,8 @@ def parse_args():
dest="clean", dest="clean",
help="Clean build folder before building", help="Clean build folder before building",
) )
parser.add_option( parser.add_option("--doc", action="store_true", dest="doc", help="Build only the help file")
"--doc", action="store_true", dest="doc", help="Build only the help file" parser.add_option("--loc", action="store_true", dest="loc", help="Build only localization")
)
parser.add_option(
"--loc", action="store_true", dest="loc", help="Build only localization"
)
parser.add_option( parser.add_option(
"--updatepot", "--updatepot",
action="store_true", action="store_true",
@@ -70,7 +66,7 @@ def build_help():
help_basepath = op.join(current_path, "help", "en") help_basepath = op.join(current_path, "help", "en")
help_destpath = op.join(current_path, "build", "help") help_destpath = op.join(current_path, "build", "help")
changelog_path = op.join(current_path, "help", "changelog") changelog_path = op.join(current_path, "help", "changelog")
tixurl = "https://github.com/hsoft/dupeguru/issues/{}" tixurl = "https://github.com/arsenetar/dupeguru/issues/{}"
confrepl = {"language": "en"} confrepl = {"language": "en"}
changelogtmpl = op.join(current_path, "help", "changelog.tmpl") changelogtmpl = op.join(current_path, "help", "changelog.tmpl")
conftmpl = op.join(current_path, "help", "conf.tmpl") conftmpl = op.join(current_path, "help", "conf.tmpl")
@@ -96,9 +92,7 @@ def build_localizations():
locale_dest = op.join("build", "locale") locale_dest = op.join("build", "locale")
if op.exists(locale_dest): if op.exists(locale_dest):
shutil.rmtree(locale_dest) shutil.rmtree(locale_dest)
shutil.copytree( shutil.copytree("locale", locale_dest, ignore=shutil.ignore_patterns("*.po", "*.pot"))
"locale", locale_dest, ignore=shutil.ignore_patterns("*.po", "*.pot")
)
def build_updatepot(): def build_updatepot():
@@ -120,13 +114,13 @@ def build_mergepot():
print("Updating .po files using .pot files") print("Updating .po files using .pot files")
loc.merge_pots_into_pos("locale") loc.merge_pots_into_pos("locale")
loc.merge_pots_into_pos(op.join("qtlib", "locale")) loc.merge_pots_into_pos(op.join("qtlib", "locale"))
loc.merge_pots_into_pos(op.join("cocoalib", "locale")) # loc.merge_pots_into_pos(op.join("cocoalib", "locale"))
def build_normpo(): def build_normpo():
loc.normalize_all_pos("locale") loc.normalize_all_pos("locale")
loc.normalize_all_pos(op.join("qtlib", "locale")) loc.normalize_all_pos(op.join("qtlib", "locale"))
loc.normalize_all_pos(op.join("cocoalib", "locale")) # loc.normalize_all_pos(op.join("cocoalib", "locale"))
def build_pe_modules(): def build_pe_modules():
@@ -149,7 +143,8 @@ def build_pe_modules():
] ]
exts.append(Extension("_block_qt", [op.join("qt", "pe", "modules", "block.c")])) exts.append(Extension("_block_qt", [op.join("qt", "pe", "modules", "block.c")]))
setup( setup(
script_args=["build_ext", "--inplace"], ext_modules=exts, script_args=["build_ext", "--inplace"],
ext_modules=exts,
) )
move_all("_block_qt*", op.join("qt", "pe")) move_all("_block_qt*", op.join("qt", "pe"))
move_all("_block*", op.join("core", "pe")) move_all("_block*", op.join("core", "pe"))
@@ -164,9 +159,7 @@ def build_normal():
print("Building localizations") print("Building localizations")
build_localizations() build_localizations()
print("Building Qt stuff") print("Building Qt stuff")
print_and_do( print_and_do("pyrcc5 {0} > {1}".format(op.join("qt", "dg.qrc"), op.join("qt", "dg_rc.py")))
"pyrcc5 {0} > {1}".format(op.join("qt", "dg.qrc"), op.join("qt", "dg_rc.py"))
)
fix_qt_resource_file(op.join("qt", "dg_rc.py")) fix_qt_resource_file(op.join("qt", "dg_rc.py"))
build_help() build_help()

View File

@@ -1,2 +1,2 @@
__version__ = "4.1.0" __version__ = "4.1.1"
__appname__ = "dupeGuru" __appname__ = "dupeGuru"

View File

@@ -126,15 +126,13 @@ class DupeGuru(Broadcaster):
PICTURE_CACHE_TYPE = "sqlite" # set to 'shelve' for a ShelveCache PICTURE_CACHE_TYPE = "sqlite" # set to 'shelve' for a ShelveCache
def __init__(self, view): def __init__(self, view, portable=False):
if view.get_default(DEBUG_MODE_PREFERENCE): if view.get_default(DEBUG_MODE_PREFERENCE):
logging.getLogger().setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG)
logging.debug("Debug mode enabled") logging.debug("Debug mode enabled")
Broadcaster.__init__(self) Broadcaster.__init__(self)
self.view = view self.view = view
self.appdata = desktop.special_folder_path( self.appdata = desktop.special_folder_path(desktop.SpecialFolder.AppData, appname=self.NAME, portable=portable)
desktop.SpecialFolder.AppData, appname=self.NAME
)
if not op.exists(self.appdata): if not op.exists(self.appdata):
os.makedirs(self.appdata) os.makedirs(self.appdata)
self.app_mode = AppMode.Standard self.app_mode = AppMode.Standard
@@ -182,17 +180,13 @@ class DupeGuru(Broadcaster):
def _get_picture_cache_path(self): def _get_picture_cache_path(self):
cache_type = self.options["picture_cache_type"] cache_type = self.options["picture_cache_type"]
cache_name = ( cache_name = "cached_pictures.shelve" if cache_type == "shelve" else "cached_pictures.db"
"cached_pictures.shelve" if cache_type == "shelve" else "cached_pictures.db"
)
return op.join(self.appdata, cache_name) return op.join(self.appdata, cache_name)
def _get_dupe_sort_key(self, dupe, get_group, key, delta): def _get_dupe_sort_key(self, dupe, get_group, key, delta):
if self.app_mode in (AppMode.Music, AppMode.Picture): if self.app_mode in (AppMode.Music, AppMode.Picture):
if key == "folder_path": if key == "folder_path":
dupe_folder_path = getattr( dupe_folder_path = getattr(dupe, "display_folder_path", dupe.folder_path)
dupe, "display_folder_path", dupe.folder_path
)
return str(dupe_folder_path).lower() return str(dupe_folder_path).lower()
if self.app_mode == AppMode.Picture: if self.app_mode == AppMode.Picture:
if delta and key == "dimensions": if delta and key == "dimensions":
@@ -220,9 +214,7 @@ class DupeGuru(Broadcaster):
def _get_group_sort_key(self, group, key): def _get_group_sort_key(self, group, key):
if self.app_mode in (AppMode.Music, AppMode.Picture): if self.app_mode in (AppMode.Music, AppMode.Picture):
if key == "folder_path": if key == "folder_path":
dupe_folder_path = getattr( dupe_folder_path = getattr(group.ref, "display_folder_path", group.ref.folder_path)
group.ref, "display_folder_path", group.ref.folder_path
)
return str(dupe_folder_path).lower() return str(dupe_folder_path).lower()
if key == "percentage": if key == "percentage":
return group.percentage return group.percentage
@@ -235,9 +227,7 @@ class DupeGuru(Broadcaster):
def _do_delete(self, j, link_deleted, use_hardlinks, direct_deletion): def _do_delete(self, j, link_deleted, use_hardlinks, direct_deletion):
def op(dupe): def op(dupe):
j.add_progress() j.add_progress()
return self._do_delete_dupe( return self._do_delete_dupe(dupe, link_deleted, use_hardlinks, direct_deletion)
dupe, link_deleted, use_hardlinks, direct_deletion
)
j.start_job(self.results.mark_count) j.start_job(self.results.mark_count)
self.results.perform_on_marked(op, True) self.results.perform_on_marked(op, True)
@@ -277,11 +267,7 @@ class DupeGuru(Broadcaster):
return None return None
def _get_export_data(self): def _get_export_data(self):
columns = [ columns = [col for col in self.result_table.columns.ordered_columns if col.visible and col.name != "marked"]
col
for col in self.result_table.columns.ordered_columns
if col.visible and col.name != "marked"
]
colnames = [col.display for col in columns] colnames = [col.display for col in columns]
rows = [] rows = []
for group_id, group in enumerate(self.results.groups): for group_id, group in enumerate(self.results.groups):
@@ -293,11 +279,7 @@ class DupeGuru(Broadcaster):
return colnames, rows return colnames, rows
def _results_changed(self): def _results_changed(self):
self.selected_dupes = [ self.selected_dupes = [d for d in self.selected_dupes if self.results.get_group_of_duplicate(d) is not None]
d
for d in self.selected_dupes
if self.results.get_group_of_duplicate(d) is not None
]
self.notify("results_changed") self.notify("results_changed")
def _start_job(self, jobid, func, args=()): def _start_job(self, jobid, func, args=()):
@@ -332,9 +314,7 @@ class DupeGuru(Broadcaster):
msg = { msg = {
JobType.Copy: tr("All marked files were copied successfully."), JobType.Copy: tr("All marked files were copied successfully."),
JobType.Move: tr("All marked files were moved successfully."), JobType.Move: tr("All marked files were moved successfully."),
JobType.Delete: tr( JobType.Delete: tr("All marked files were successfully sent to Trash."),
"All marked files were successfully sent to Trash."
),
}[jobid] }[jobid]
self.view.show_message(msg) self.view.show_message(msg)
@@ -401,15 +381,12 @@ class DupeGuru(Broadcaster):
self.view.show_message(tr("'{}' does not exist.").format(d)) self.view.show_message(tr("'{}' does not exist.").format(d))
def add_selected_to_ignore_list(self): def add_selected_to_ignore_list(self):
"""Adds :attr:`selected_dupes` to :attr:`ignore_list`. """Adds :attr:`selected_dupes` to :attr:`ignore_list`."""
"""
dupes = self.without_ref(self.selected_dupes) dupes = self.without_ref(self.selected_dupes)
if not dupes: if not dupes:
self.view.show_message(MSG_NO_SELECTED_DUPES) self.view.show_message(MSG_NO_SELECTED_DUPES)
return return
msg = tr( msg = tr("All selected %d matches are going to be ignored in all subsequent scans. Continue?")
"All selected %d matches are going to be ignored in all subsequent scans. Continue?"
)
if not self.view.ask_yes_no(msg % len(dupes)): if not self.view.ask_yes_no(msg % len(dupes)):
return return
for dupe in dupes: for dupe in dupes:
@@ -482,17 +459,18 @@ class DupeGuru(Broadcaster):
if not self.results.mark_count: if not self.results.mark_count:
self.view.show_message(MSG_NO_MARKED_DUPES) self.view.show_message(MSG_NO_MARKED_DUPES)
return return
opname = tr("copy") if copy else tr("move") destination = self.view.select_dest_folder(
prompt = tr("Select a directory to {} marked files to").format(opname) tr("Select a directory to copy marked files to")
destination = self.view.select_dest_folder(prompt) if copy
else tr("Select a directory to move marked files to")
)
if destination: if destination:
desttype = self.options["copymove_dest_type"] desttype = self.options["copymove_dest_type"]
jobid = JobType.Copy if copy else JobType.Move jobid = JobType.Copy if copy else JobType.Move
self._start_job(jobid, do) self._start_job(jobid, do)
def delete_marked(self): def delete_marked(self):
"""Start an async job to send marked duplicates to the trash. """Start an async job to send marked duplicates to the trash."""
"""
if not self.results.mark_count: if not self.results.mark_count:
self.view.show_message(MSG_NO_MARKED_DUPES) self.view.show_message(MSG_NO_MARKED_DUPES)
return return
@@ -523,9 +501,7 @@ class DupeGuru(Broadcaster):
The columns and their order in the resulting CSV file is determined in the same way as in The columns and their order in the resulting CSV file is determined in the same way as in
:meth:`export_to_xhtml`. :meth:`export_to_xhtml`.
""" """
dest_file = self.view.select_dest_file( dest_file = self.view.select_dest_file(tr("Select a destination for your exported CSV"), "csv")
tr("Select a destination for your exported CSV"), "csv"
)
if dest_file: if dest_file:
colnames, rows = self._get_export_data() colnames, rows = self._get_export_data()
try: try:
@@ -542,9 +518,7 @@ class DupeGuru(Broadcaster):
try: try:
return dupe.get_display_info(group, delta) return dupe.get_display_info(group, delta)
except Exception as e: except Exception as e:
logging.warning( logging.warning("Exception (type: %s) on GetDisplayInfo for %s: %s", type(e), str(dupe.path), str(e))
"Exception (type: %s) on GetDisplayInfo for %s: %s",
type(e), str(dupe.path), str(e))
return empty_data() return empty_data()
def invoke_custom_command(self): def invoke_custom_command(self):
@@ -556,9 +530,7 @@ class DupeGuru(Broadcaster):
""" """
cmd = self.view.get_default("CustomCommand") cmd = self.view.get_default("CustomCommand")
if not cmd: if not cmd:
msg = tr( msg = tr("You have no custom command set up. Set it up in your preferences.")
"You have no custom command set up. Set it up in your preferences."
)
self.view.show_message(msg) self.view.show_message(msg)
return return
if not self.selected_dupes: if not self.selected_dupes:
@@ -634,9 +606,7 @@ class DupeGuru(Broadcaster):
if not self.result_table.power_marker: if not self.result_table.power_marker:
if changed_groups: if changed_groups:
self.selected_dupes = [ self.selected_dupes = [
d d for d in self.selected_dupes if self.results.get_group_of_duplicate(d).ref is d
for d in self.selected_dupes
if self.results.get_group_of_duplicate(d).ref is d
] ]
self.notify("results_changed") self.notify("results_changed")
else: else:
@@ -648,20 +618,17 @@ class DupeGuru(Broadcaster):
self.notify("results_changed_but_keep_selection") self.notify("results_changed_but_keep_selection")
def mark_all(self): def mark_all(self):
"""Set all dupes in the results as marked. """Set all dupes in the results as marked."""
"""
self.results.mark_all() self.results.mark_all()
self.notify("marking_changed") self.notify("marking_changed")
def mark_none(self): def mark_none(self):
"""Set all dupes in the results as unmarked. """Set all dupes in the results as unmarked."""
"""
self.results.mark_none() self.results.mark_none()
self.notify("marking_changed") self.notify("marking_changed")
def mark_invert(self): def mark_invert(self):
"""Invert the marked state of all dupes in the results. """Invert the marked state of all dupes in the results."""
"""
self.results.mark_invert() self.results.mark_invert()
self.notify("marking_changed") self.notify("marking_changed")
@@ -679,8 +646,7 @@ class DupeGuru(Broadcaster):
self.notify("marking_changed") self.notify("marking_changed")
def open_selected(self): def open_selected(self):
"""Open :attr:`selected_dupes` with their associated application. """Open :attr:`selected_dupes` with their associated application."""
"""
if len(self.selected_dupes) > 10: if len(self.selected_dupes) > 10:
if not self.view.ask_yes_no(MSG_MANY_FILES_TO_OPEN): if not self.view.ask_yes_no(MSG_MANY_FILES_TO_OPEN):
return return
@@ -688,8 +654,7 @@ class DupeGuru(Broadcaster):
desktop.open_path(dupe.path) desktop.open_path(dupe.path)
def purge_ignore_list(self): def purge_ignore_list(self):
"""Remove files that don't exist from :attr:`ignore_list`. """Remove files that don't exist from :attr:`ignore_list`."""
"""
self.ignore_list.Filter(lambda f, s: op.exists(f) and op.exists(s)) self.ignore_list.Filter(lambda f, s: op.exists(f) and op.exists(s))
self.ignore_list_dialog.refresh() self.ignore_list_dialog.refresh()
@@ -719,8 +684,7 @@ class DupeGuru(Broadcaster):
self.notify("results_changed_but_keep_selection") self.notify("results_changed_but_keep_selection")
def remove_marked(self): def remove_marked(self):
"""Removed marked duplicates from the results (without touching the files themselves). """Removed marked duplicates from the results (without touching the files themselves)."""
"""
if not self.results.mark_count: if not self.results.mark_count:
self.view.show_message(MSG_NO_MARKED_DUPES) self.view.show_message(MSG_NO_MARKED_DUPES)
return return
@@ -731,8 +695,7 @@ class DupeGuru(Broadcaster):
self._results_changed() self._results_changed()
def remove_selected(self): def remove_selected(self):
"""Removed :attr:`selected_dupes` from the results (without touching the files themselves). """Removed :attr:`selected_dupes` from the results (without touching the files themselves)."""
"""
dupes = self.without_ref(self.selected_dupes) dupes = self.without_ref(self.selected_dupes)
if not dupes: if not dupes:
self.view.show_message(MSG_NO_SELECTED_DUPES) self.view.show_message(MSG_NO_SELECTED_DUPES)
@@ -770,10 +733,10 @@ class DupeGuru(Broadcaster):
for group in self.results.groups: for group in self.results.groups:
if group.prioritize(key_func=sort_key): if group.prioritize(key_func=sort_key):
count += 1 count += 1
if count:
self.results.refresh_required = True
self._results_changed() self._results_changed()
msg = tr("{} duplicate groups were changed by the re-prioritization.").format( msg = tr("{} duplicate groups were changed by the re-prioritization.").format(count)
count
)
self.view.show_message(msg) self.view.show_message(msg)
def reveal_selected(self): def reveal_selected(self):
@@ -817,9 +780,7 @@ class DupeGuru(Broadcaster):
""" """
scanner = self.SCANNER_CLASS() scanner = self.SCANNER_CLASS()
if not self.directories.has_any_file(): if not self.directories.has_any_file():
self.view.show_message( self.view.show_message(tr("The selected directories contain no scannable file."))
tr("The selected directories contain no scannable file.")
)
return return
# Send relevant options down to the scanner instance # Send relevant options down to the scanner instance
for k, v in self.options.items(): for k, v in self.options.items():
@@ -834,13 +795,9 @@ class DupeGuru(Broadcaster):
def do(j): def do(j):
j.set_progress(0, tr("Collecting files to scan")) j.set_progress(0, tr("Collecting files to scan"))
if scanner.scan_type == ScanType.Folders: if scanner.scan_type == ScanType.Folders:
files = list( files = list(self.directories.get_folders(folderclass=se.fs.Folder, j=j))
self.directories.get_folders(folderclass=se.fs.Folder, j=j)
)
else: else:
files = list( files = list(self.directories.get_files(fileclasses=self.fileclasses, j=j))
self.directories.get_files(fileclasses=self.fileclasses, j=j)
)
if self.options["ignore_hardlink_matches"]: if self.options["ignore_hardlink_matches"]:
files = self._remove_hardlink_dupes(files) files = self._remove_hardlink_dupes(files)
logging.info("Scanning %d files" % len(files)) logging.info("Scanning %d files" % len(files))
@@ -862,13 +819,8 @@ class DupeGuru(Broadcaster):
self.notify("marking_changed") self.notify("marking_changed")
def without_ref(self, dupes): def without_ref(self, dupes):
"""Returns ``dupes`` with all reference elements removed. """Returns ``dupes`` with all reference elements removed."""
""" return [dupe for dupe in dupes if self.results.get_group_of_duplicate(dupe).ref is not dupe]
return [
dupe
for dupe in dupes
if self.results.get_group_of_duplicate(dupe).ref is not dupe
]
def get_default(self, key, fallback_value=None): def get_default(self, key, fallback_value=None):
result = nonone(self.view.get_default(key), fallback_value) result = nonone(self.view.get_default(key), fallback_value)

View File

@@ -108,17 +108,7 @@ class Directories:
found_files = [] found_files = []
# print(f"len of files: {len(files)} {files}") # print(f"len of files: {len(files)} {files}")
for f in files: for f in files:
found = False if not self._exclude_list.is_excluded(root, f):
for expr in self._exclude_list.compiled_files:
if expr.match(f):
found = True
break
if not found:
for expr in self._exclude_list.compiled_paths:
if expr.match(root + os.sep + f):
found = True
break
if not found:
found_files.append(fs.get_file(rootPath + f, fileclasses=fileclasses)) found_files.append(fs.get_file(rootPath + f, fileclasses=fileclasses))
found_files = [f for f in found_files if f is not None] found_files = [f for f in found_files if f is not None]
# In some cases, directories can be considered as files by dupeGuru, which is # In some cases, directories can be considered as files by dupeGuru, which is

View File

@@ -17,7 +17,11 @@ from hscommon.util import flatten, multi_replace
from hscommon.trans import tr from hscommon.trans import tr
from hscommon.jobprogress import job from hscommon.jobprogress import job
(WEIGHT_WORDS, MATCH_SIMILAR_WORDS, NO_FIELD_ORDER,) = range(3) (
WEIGHT_WORDS,
MATCH_SIMILAR_WORDS,
NO_FIELD_ORDER,
) = range(3)
JOB_REFRESH_RATE = 100 JOB_REFRESH_RATE = 100
@@ -26,8 +30,17 @@ def getwords(s):
# We decompose the string so that ascii letters with accents can be part of the word. # We decompose the string so that ascii letters with accents can be part of the word.
s = normalize("NFD", s) s = normalize("NFD", s)
s = multi_replace(s, "-_&+():;\\[]{}.,<>/?~!@#$*", " ").lower() s = multi_replace(s, "-_&+():;\\[]{}.,<>/?~!@#$*", " ").lower()
# logging.debug(f"DEBUG chars for: {s}\n"
# f"{[c for c in s if ord(c) != 32]}\n"
# f"{[ord(c) for c in s if ord(c) != 32]}")
# HACK We shouldn't ignore non-ascii characters altogether. Any Unicode char
# above common european characters that cannot be "sanitized" (ie. stripped
# of their accents, etc.) are preserved as is. The arbitrary limit is
# obtained from this one: ord("\u037e") GREEK QUESTION MARK
s = "".join( s = "".join(
c for c in s if c in string.ascii_letters + string.digits + string.whitespace c
for c in s
if (ord(c) <= 894 and c in string.ascii_letters + string.digits + string.whitespace) or ord(c) > 894
) )
return [_f for _f in s.split(" ") if _f] # remove empty elements return [_f for _f in s.split(" ") if _f] # remove empty elements
@@ -104,9 +117,7 @@ def compare_fields(first, second, flags=()):
if matched_field: if matched_field:
second.remove(matched_field) second.remove(matched_field)
else: else:
results = [ results = [compare(field1, field2, flags) for field1, field2 in zip(first, second)]
compare(field1, field2, flags) for field1, field2 in zip(first, second)
]
return min(results) if results else 0 return min(results) if results else 0
@@ -119,9 +130,7 @@ def build_word_dict(objects, j=job.nulljob):
The result will be a dict with words as keys, lists of objects as values. The result will be a dict with words as keys, lists of objects as values.
""" """
result = defaultdict(set) result = defaultdict(set)
for object in j.iter_with_progress( for object in j.iter_with_progress(objects, "Prepared %d/%d files", JOB_REFRESH_RATE):
objects, "Prepared %d/%d files", JOB_REFRESH_RATE
):
for word in unpack_fields(object.words): for word in unpack_fields(object.words):
result[word].add(object) result[word].add(object)
return result return result
@@ -156,9 +165,7 @@ def reduce_common_words(word_dict, threshold):
The exception to this removal are the objects where all the words of the object are common. The exception to this removal are the objects where all the words of the object are common.
Because if we remove them, we will miss some duplicates! Because if we remove them, we will miss some duplicates!
""" """
uncommon_words = set( uncommon_words = set(word for word, objects in word_dict.items() if len(objects) < threshold)
word for word, objects in word_dict.items() if len(objects) < threshold
)
for word, objects in list(word_dict.items()): for word, objects in list(word_dict.items()):
if len(objects) < threshold: if len(objects) < threshold:
continue continue
@@ -264,17 +271,16 @@ def getmatches(
# This is the place where the memory usage is at its peak during the scan. # This is the place where the memory usage is at its peak during the scan.
# Just continue the process with an incomplete list of matches. # Just continue the process with an incomplete list of matches.
del compared # This should give us enough room to call logging. del compared # This should give us enough room to call logging.
logging.warning( logging.warning("Memory Overflow. Matches: %d. Word dict: %d" % (len(result), len(word_dict)))
"Memory Overflow. Matches: %d. Word dict: %d"
% (len(result), len(word_dict))
)
return result return result
return result return result
def getmatches_by_contents(files, j=job.nulljob): def getmatches_by_contents(files, bigsize=0, j=job.nulljob):
"""Returns a list of :class:`Match` within ``files`` if their contents is the same. """Returns a list of :class:`Match` within ``files`` if their contents is the same.
:param bigsize: The size in bytes over which we consider files big enough to
justify taking samples of md5. If 0, compute md5 as usual.
:param j: A :ref:`job progress instance <jobs>`. :param j: A :ref:`job progress instance <jobs>`.
""" """
size2files = defaultdict(set) size2files = defaultdict(set)
@@ -291,6 +297,10 @@ def getmatches_by_contents(files, j=job.nulljob):
if first.is_ref and second.is_ref: if first.is_ref and second.is_ref:
continue # Don't spend time comparing two ref pics together. continue # Don't spend time comparing two ref pics together.
if first.md5partial == second.md5partial: if first.md5partial == second.md5partial:
if bigsize > 0 and first.size > bigsize:
if first.md5samples == second.md5samples:
result.append(Match(first, second, 100))
else:
if first.md5 == second.md5: if first.md5 == second.md5:
result.append(Match(first, second, 100)) result.append(Match(first, second, 100))
j.add_progress(desc=tr("%d matches found") % len(result)) j.add_progress(desc=tr("%d matches found") % len(result))
@@ -391,18 +401,13 @@ class Group:
You can call this after the duplicate scanning process to free a bit of memory. You can call this after the duplicate scanning process to free a bit of memory.
""" """
discarded = set( discarded = set(m for m in self.matches if not all(obj in self.unordered for obj in [m.first, m.second]))
m
for m in self.matches
if not all(obj in self.unordered for obj in [m.first, m.second])
)
self.matches -= discarded self.matches -= discarded
self.candidates = defaultdict(set) self.candidates = defaultdict(set)
return discarded return discarded
def get_match_of(self, item): def get_match_of(self, item):
"""Returns the match pair between ``item`` and :attr:`ref`. """Returns the match pair between ``item`` and :attr:`ref`."""
"""
if item is self.ref: if item is self.ref:
return return
for m in self._get_matches_for_ref(): for m in self._get_matches_for_ref():
@@ -418,8 +423,7 @@ class Group:
""" """
# tie_breaker(ref, dupe) --> True if dupe should be ref # tie_breaker(ref, dupe) --> True if dupe should be ref
# Returns True if anything changed during prioritization. # Returns True if anything changed during prioritization.
master_key_func = lambda x: (-x.is_ref, key_func(x)) new_order = sorted(self.ordered, key=lambda x: (-x.is_ref, key_func(x)))
new_order = sorted(self.ordered, key=master_key_func)
changed = new_order != self.ordered changed = new_order != self.ordered
self.ordered = new_order self.ordered = new_order
if tie_breaker is None: if tie_breaker is None:
@@ -442,9 +446,7 @@ class Group:
self.unordered.remove(item) self.unordered.remove(item)
self._percentage = None self._percentage = None
self._matches_for_ref = None self._matches_for_ref = None
if (len(self) > 1) and any( if (len(self) > 1) and any(not getattr(item, "is_ref", False) for item in self):
not getattr(item, "is_ref", False) for item in self
):
if discard_matches: if discard_matches:
self.matches = set(m for m in self.matches if item not in m) self.matches = set(m for m in self.matches if item not in m)
else: else:
@@ -453,8 +455,7 @@ class Group:
pass pass
def switch_ref(self, with_dupe): def switch_ref(self, with_dupe):
"""Make the :attr:`ref` dupe of the group switch position with ``with_dupe``. """Make the :attr:`ref` dupe of the group switch position with ``with_dupe``."""
"""
if self.ref.is_ref: if self.ref.is_ref:
return False return False
try: try:
@@ -473,9 +474,7 @@ class Group:
if self._percentage is None: if self._percentage is None:
if self.dupes: if self.dupes:
matches = self._get_matches_for_ref() matches = self._get_matches_for_ref()
self._percentage = sum(match.percentage for match in matches) // len( self._percentage = sum(match.percentage for match in matches) // len(matches)
matches
)
else: else:
self._percentage = 0 self._percentage = 0
return self._percentage return self._percentage
@@ -530,12 +529,8 @@ def get_groups(matches):
orphan_matches = [] orphan_matches = []
for group in groups: for group in groups:
orphan_matches += { orphan_matches += {
m m for m in group.discard_matches() if not any(obj in matched_files for obj in [m.first, m.second])
for m in group.discard_matches()
if not any(obj in matched_files for obj in [m.first, m.second])
} }
if groups and orphan_matches: if groups and orphan_matches:
groups += get_groups( groups += get_groups(orphan_matches) # no job, as it isn't supposed to take a long time
orphan_matches
) # no job, as it isn't supposed to take a long time
return groups return groups

View File

@@ -4,6 +4,7 @@
from .markable import Markable from .markable import Markable
from xml.etree import ElementTree as ET from xml.etree import ElementTree as ET
# TODO: perhaps use regex module for better Unicode support? https://pypi.org/project/regex/ # TODO: perhaps use regex module for better Unicode support? https://pypi.org/project/regex/
# also https://pypi.org/project/re2/ # also https://pypi.org/project/re2/
# TODO update the Result list with newly added regexes if possible # TODO update the Result list with newly added regexes if possible
@@ -15,7 +16,8 @@ from hscommon.util import FileOrPath
from hscommon.plat import ISWINDOWS from hscommon.plat import ISWINDOWS
import time import time
default_regexes = [r"^thumbs\.db$", # Obsolete after WindowsXP default_regexes = [
r"^thumbs\.db$", # Obsolete after WindowsXP
r"^desktop\.ini$", # Windows metadata r"^desktop\.ini$", # Windows metadata
r"^\.DS_Store$", # MacOS metadata r"^\.DS_Store$", # MacOS metadata
r"^\.Trash\-.*", # Linux trash directories r"^\.Trash\-.*", # Linux trash directories
@@ -34,6 +36,7 @@ def timer(func):
end = time.perf_counter_ns() end = time.perf_counter_ns()
print(f"DEBUG: func {func.__name__!r} took {end - start} ns.") print(f"DEBUG: func {func.__name__!r} took {end - start} ns.")
return value return value
return wrapper_timer return wrapper_timer
@@ -45,11 +48,13 @@ def memoize(func):
if args not in func.cache: if args not in func.cache:
func.cache[args] = func(*args) func.cache[args] = func(*args)
return func.cache[args] return func.cache[args]
return _memoize return _memoize
class AlreadyThereException(Exception): class AlreadyThereException(Exception):
"""Expression already in the list""" """Expression already in the list"""
def __init__(self, arg="Expression is already in excluded list."): def __init__(self, arg="Expression is already in excluded list."):
super().__init__(arg) super().__init__(arg)
@@ -81,7 +86,7 @@ class ExcludeList(Markable):
yield self.is_marked(regex), regex yield self.is_marked(regex), regex
def __contains__(self, item): def __contains__(self, item):
return self.isExcluded(item) return self.has_entry(item)
def __len__(self): def __len__(self):
"""Returns the total number of regexes regardless of mark status.""" """Returns the total number of regexes regardless of mark status."""
@@ -169,11 +174,11 @@ class ExcludeList(Markable):
def build_compiled_caches(self, union=False): def build_compiled_caches(self, union=False):
if not union: if not union:
self._cached_compiled_files =\ self._cached_compiled_files = [x for x in self._excluded_compiled if not has_sep(x.pattern)]
[x for x in self._excluded_compiled if not has_sep(x.pattern)] self._cached_compiled_paths = [x for x in self._excluded_compiled if has_sep(x.pattern)]
self._cached_compiled_paths =\ self._dirty = False
[x for x in self._excluded_compiled if has_sep(x.pattern)]
return return
marked_count = [x for marked, x in self if marked] marked_count = [x for marked, x in self if marked]
# If there is no item, the compiled Pattern will be '' and match everything! # If there is no item, the compiled Pattern will be '' and match everything!
if not marked_count: if not marked_count:
@@ -183,28 +188,25 @@ class ExcludeList(Markable):
else: else:
# HACK returned as a tuple to get a free iterator and keep interface # HACK returned as a tuple to get a free iterator and keep interface
# the same regardless of whether the client asked for union or not # the same regardless of whether the client asked for union or not
self._cached_compiled_union_all =\ self._cached_compiled_union_all = (re.compile("|".join(marked_count)),)
(re.compile('|'.join(marked_count)),)
files_marked = [x for x in marked_count if not has_sep(x)] files_marked = [x for x in marked_count if not has_sep(x)]
if not files_marked: if not files_marked:
self._cached_compiled_union_files = tuple() self._cached_compiled_union_files = tuple()
else: else:
self._cached_compiled_union_files =\ self._cached_compiled_union_files = (re.compile("|".join(files_marked)),)
(re.compile('|'.join(files_marked)),)
paths_marked = [x for x in marked_count if has_sep(x)] paths_marked = [x for x in marked_count if has_sep(x)]
if not paths_marked: if not paths_marked:
self._cached_compiled_union_paths = tuple() self._cached_compiled_union_paths = tuple()
else: else:
self._cached_compiled_union_paths =\ self._cached_compiled_union_paths = (re.compile("|".join(paths_marked)),)
(re.compile('|'.join(paths_marked)),) self._dirty = False
@property @property
def compiled(self): def compiled(self):
"""Should be used by other classes to retrieve the up-to-date list of patterns.""" """Should be used by other classes to retrieve the up-to-date list of patterns."""
if self._use_union: if self._use_union:
if self._dirty: if self._dirty:
self.build_compiled_caches(True) self.build_compiled_caches(self._use_union)
self._dirty = False
return self._cached_compiled_union_all return self._cached_compiled_union_all
return self._excluded_compiled return self._excluded_compiled
@@ -215,25 +217,21 @@ class ExcludeList(Markable):
The interface should be expected to be a generator, even if it returns only The interface should be expected to be a generator, even if it returns only
one item (one Pattern in the union case).""" one item (one Pattern in the union case)."""
if self._dirty: if self._dirty:
self.build_compiled_caches(True if self._use_union else False) self.build_compiled_caches(self._use_union)
self._dirty = False return self._cached_compiled_union_files if self._use_union else self._cached_compiled_files
return self._cached_compiled_union_files if self._use_union\
else self._cached_compiled_files
@property @property
def compiled_paths(self): def compiled_paths(self):
"""Returns patterns with only separators in them, for more precise filtering.""" """Returns patterns with only separators in them, for more precise filtering."""
if self._dirty: if self._dirty:
self.build_compiled_caches(True if self._use_union else False) self.build_compiled_caches(self._use_union)
self._dirty = False return self._cached_compiled_union_paths if self._use_union else self._cached_compiled_paths
return self._cached_compiled_union_paths if self._use_union\
else self._cached_compiled_paths
# ---Public # ---Public
def add(self, regex, forced=False): def add(self, regex, forced=False):
"""This interface should throw exceptions if there is an error during """This interface should throw exceptions if there is an error during
regex compilation""" regex compilation"""
if self.isExcluded(regex): if self.has_entry(regex):
# This exception should never be ignored # This exception should never be ignored
raise AlreadyThereException() raise AlreadyThereException()
if regex in forbidden_regexes: if regex in forbidden_regexes:
@@ -256,12 +254,27 @@ class ExcludeList(Markable):
"""Returns the number of marked regexes only.""" """Returns the number of marked regexes only."""
return len([x for marked, x in self if marked]) return len([x for marked, x in self if marked])
def isExcluded(self, regex): def has_entry(self, regex):
for item in self._excluded: for item in self._excluded:
if regex == item[0]: if regex == item[0]:
return True return True
return False return False
def is_excluded(self, dirname, filename):
"""Return True if the file or the absolute path to file is supposed to be
filtered out, False otherwise."""
matched = False
for expr in self.compiled_files:
if expr.fullmatch(filename):
matched = True
break
if not matched:
for expr in self.compiled_paths:
if expr.fullmatch(dirname + sep + filename):
matched = True
break
return matched
def remove(self, regex): def remove(self, regex):
for item in self._excluded: for item in self._excluded:
if item[0] == regex: if item[0] == regex:
@@ -280,13 +293,14 @@ class ExcludeList(Markable):
was_marked = self.is_marked(regex) was_marked = self.is_marked(regex)
is_compilable, exception, compiled = self.compile_re(newregex) is_compilable, exception, compiled = self.compile_re(newregex)
# We overwrite the found entry # We overwrite the found entry
self._excluded[self._excluded.index(item)] =\ self._excluded[self._excluded.index(item)] = [newregex, is_compilable, exception, compiled]
[newregex, is_compilable, exception, compiled]
self._remove_compiled(regex) self._remove_compiled(regex)
break break
if not found: if not found:
return return
if is_compilable and was_marked: if is_compilable:
self._add_compiled(newregex)
if was_marked:
# Not marked by default when added, add it back # Not marked by default when added, add it back
self.mark(newregex) self.mark(newregex)
@@ -300,7 +314,7 @@ class ExcludeList(Markable):
if regex not in default_regexes: if regex not in default_regexes:
self.unmark(regex) self.unmark(regex)
for default_regex in default_regexes: for default_regex in default_regexes:
if not self.isExcluded(default_regex): if not self.has_entry(default_regex):
self.add(default_regex) self.add(default_regex)
self.mark(default_regex) self.mark(default_regex)
@@ -326,8 +340,10 @@ class ExcludeList(Markable):
# "forced" avoids compilation exceptions and adds anyway # "forced" avoids compilation exceptions and adds anyway
self.add(regex_string, forced=True) self.add(regex_string, forced=True)
except AlreadyThereException: except AlreadyThereException:
logging.error(f"Regex \"{regex_string}\" \ logging.error(
loaded from XML was already present in the list.") f'Regex "{regex_string}" \
loaded from XML was already present in the list.'
)
continue continue
if exclude_item.get("marked") == "y": if exclude_item.get("marked") == "y":
marked.add(regex_string) marked.add(regex_string)
@@ -352,6 +368,7 @@ loaded from XML was already present in the list.")
class ExcludeDict(ExcludeList): class ExcludeDict(ExcludeList):
"""Exclusion list holding a set of regular expressions as keys, the compiled """Exclusion list holding a set of regular expressions as keys, the compiled
Pattern, compilation error and compilable boolean as values.""" Pattern, compilation error and compilable boolean as values."""
# Implemntation around a dictionary instead of a list, which implies # Implemntation around a dictionary instead of a list, which implies
# to keep the index of each string-key as its sub-element and keep it updated # to keep the index of each string-key as its sub-element and keep it updated
# whenever insert/remove is done. # whenever insert/remove is done.
@@ -399,9 +416,9 @@ class ExcludeDict(ExcludeList):
if self._use_union: if self._use_union:
return return
try: try:
self._excluded_compiled.add(self._excluded[regex]["compiled"]) self._excluded_compiled.add(self._excluded.get(regex).get("compiled"))
except Exception as e: except Exception as e:
logging.warning(f"Exception while adding regex {regex} to compiled set: {e}") logging.error(f"Exception while adding regex {regex} to compiled set: {e}")
return return
def is_compilable(self, regex): def is_compilable(self, regex):
@@ -418,14 +435,9 @@ class ExcludeDict(ExcludeList):
# and other indices should be pushed by one # and other indices should be pushed by one
for value in self._excluded.values(): for value in self._excluded.values():
value["index"] += 1 value["index"] += 1
self._excluded[regex] = { self._excluded[regex] = {"index": 0, "compilable": iscompilable, "error": exception, "compiled": compiled}
"index": 0,
"compilable": iscompilable,
"error": exception,
"compiled": compiled
}
def isExcluded(self, regex): def has_entry(self, regex):
if regex in self._excluded.keys(): if regex in self._excluded.keys():
return True return True
return False return False
@@ -451,13 +463,15 @@ class ExcludeDict(ExcludeList):
previous = self._excluded.pop(regex) previous = self._excluded.pop(regex)
iscompilable, error, compiled = self.compile_re(newregex) iscompilable, error, compiled = self.compile_re(newregex)
self._excluded[newregex] = { self._excluded[newregex] = {
"index": previous["index"], "index": previous.get("index"),
"compilable": iscompilable, "compilable": iscompilable,
"error": error, "error": error,
"compiled": compiled "compiled": compiled,
} }
self._remove_compiled(regex) self._remove_compiled(regex)
if was_marked and iscompilable: if iscompilable:
self._add_compiled(newregex)
if was_marked:
self.mark(newregex) self.mark(newregex)
def save_to_xml(self, outfile): def save_to_xml(self, outfile):
@@ -492,8 +506,12 @@ def ordered_keys(_dict):
if ISWINDOWS: if ISWINDOWS:
def has_sep(x):
return '\\' + sep in x def has_sep(regexp):
return "\\" + sep in regexp
else: else:
def has_sep(x):
return sep in x def has_sep(regexp):
return sep in regexp

View File

@@ -131,15 +131,11 @@ def export_to_xhtml(colnames, rows):
indented = "indented" indented = "indented"
filename = row[1] filename = row[1]
cells = "".join(CELL_TEMPLATE.format(value=value) for value in row[2:]) cells = "".join(CELL_TEMPLATE.format(value=value) for value in row[2:])
rendered_rows.append( rendered_rows.append(ROW_TEMPLATE.format(indented=indented, filename=filename, cells=cells))
ROW_TEMPLATE.format(indented=indented, filename=filename, cells=cells)
)
previous_group_id = row[0] previous_group_id = row[0]
rendered_rows = "".join(rendered_rows) rendered_rows = "".join(rendered_rows)
# The main template can't use format because the css code uses {} # The main template can't use format because the css code uses {}
content = MAIN_TEMPLATE.replace("$colheaders", colheaders).replace( content = MAIN_TEMPLATE.replace("$colheaders", colheaders).replace("$rows", rendered_rows)
"$rows", rendered_rows
)
folder = mkdtemp() folder = mkdtemp()
destpath = op.join(folder, "export.htm") destpath = op.join(folder, "export.htm")
fp = open(destpath, "wt", encoding="utf-8") fp = open(destpath, "wt", encoding="utf-8")

View File

@@ -12,6 +12,7 @@
# and I'm doing it now. # and I'm doing it now.
import hashlib import hashlib
from math import floor
import logging import logging
from hscommon.util import nonone, get_file_ext from hscommon.util import nonone, get_file_ext
@@ -30,6 +31,14 @@ __all__ = [
NOT_SET = object() NOT_SET = object()
# The goal here is to not run out of memory on really big files. However, the chunk
# size has to be large enough so that the python loop isn't too costly in terms of
# CPU.
CHUNK_SIZE = 1024 * 1024 # 1 MiB
# Minimum size below which partial hashes don't need to be computed
MIN_FILE_SIZE = 3 * CHUNK_SIZE # 3MiB, because we take 3 samples
class FSError(Exception): class FSError(Exception):
cls_message = "An error has occured on '{name}' in '{parent}'" cls_message = "An error has occured on '{name}' in '{parent}'"
@@ -70,15 +79,9 @@ class OperationError(FSError):
class File: class File:
"""Represents a file and holds metadata to be used for scanning. """Represents a file and holds metadata to be used for scanning."""
"""
INITIAL_INFO = { INITIAL_INFO = {"size": 0, "mtime": 0, "md5": b"", "md5partial": b"", "md5samples": b""}
"size": 0,
"mtime": 0,
"md5": "",
"md5partial": "",
}
# Slots for File make us save quite a bit of memory. In a memory test I've made with a lot of # Slots for File make us save quite a bit of memory. In a memory test I've made with a lot of
# files, I saved 35% memory usage with "unread" files (no _read_info() call) and gains become # files, I saved 35% memory usage with "unread" files (no _read_info() call) and gains become
# even greater when we take into account read attributes (70%!). Yeah, it's worth it. # even greater when we take into account read attributes (70%!). Yeah, it's worth it.
@@ -98,9 +101,7 @@ class File:
try: try:
self._read_info(attrname) self._read_info(attrname)
except Exception as e: except Exception as e:
logging.warning( logging.warning("An error '%s' was raised while decoding '%s'", e, repr(self.path))
"An error '%s' was raised while decoding '%s'", e, repr(self.path)
)
result = object.__getattribute__(self, attrname) result = object.__getattribute__(self, attrname)
if result is NOT_SET: if result is NOT_SET:
result = self.INITIAL_INFO[attrname] result = self.INITIAL_INFO[attrname]
@@ -112,37 +113,62 @@ class File:
return (0x4000, 0x4000) # 16Kb return (0x4000, 0x4000) # 16Kb
def _read_info(self, field): def _read_info(self, field):
# print(f"_read_info({field}) for {self}")
if field in ("size", "mtime"): if field in ("size", "mtime"):
stats = self.path.stat() stats = self.path.stat()
self.size = nonone(stats.st_size, 0) self.size = nonone(stats.st_size, 0)
self.mtime = nonone(stats.st_mtime, 0) self.mtime = nonone(stats.st_mtime, 0)
elif field == "md5partial": elif field == "md5partial":
try: try:
fp = self.path.open("rb") with self.path.open("rb") as fp:
offset, size = self._get_md5partial_offset_and_size() offset, size = self._get_md5partial_offset_and_size()
fp.seek(offset) fp.seek(offset)
partialdata = fp.read(size) partialdata = fp.read(size)
md5 = hashlib.md5(partialdata) md5 = hashlib.md5(partialdata)
self.md5partial = md5.digest() self.md5partial = md5.digest()
fp.close()
except Exception: except Exception:
pass pass
elif field == "md5": elif field == "md5":
try: try:
fp = self.path.open("rb") with self.path.open("rb") as fp:
md5 = hashlib.md5() md5 = hashlib.md5()
# The goal here is to not run out of memory on really big files. However, the chunk
# size has to be large enough so that the python loop isn't too costly in terms of
# CPU.
CHUNK_SIZE = 1024 * 1024 # 1 mb
filedata = fp.read(CHUNK_SIZE) filedata = fp.read(CHUNK_SIZE)
while filedata: while filedata:
md5.update(filedata) md5.update(filedata)
filedata = fp.read(CHUNK_SIZE) filedata = fp.read(CHUNK_SIZE)
# FIXME For python 3.8 and later
# while filedata := fp.read(CHUNK_SIZE):
# md5.update(filedata)
self.md5 = md5.digest() self.md5 = md5.digest()
fp.close()
except Exception: except Exception:
pass pass
elif field == "md5samples":
try:
with self.path.open("rb") as fp:
size = self.size
# Might as well hash such small files entirely.
if size <= MIN_FILE_SIZE:
setattr(self, field, self.md5)
return
# Chunk at 25% of the file
fp.seek(floor(size * 25 / 100), 0)
filedata = fp.read(CHUNK_SIZE)
md5 = hashlib.md5(filedata)
# Chunk at 60% of the file
fp.seek(floor(size * 60 / 100), 0)
filedata = fp.read(CHUNK_SIZE)
md5.update(filedata)
# Last chunk of the file
fp.seek(-CHUNK_SIZE, 2)
filedata = fp.read(CHUNK_SIZE)
md5.update(filedata)
setattr(self, field, md5.digest())
except Exception as e:
logging.error(f"Error computing md5samples: {e}")
pass
def _read_all_info(self, attrnames=None): def _read_all_info(self, attrnames=None):
"""Cache all possible info. """Cache all possible info.
@@ -157,8 +183,7 @@ class File:
# --- Public # --- Public
@classmethod @classmethod
def can_handle(cls, path): def can_handle(cls, path):
"""Returns whether this file wrapper class can handle ``path``. """Returns whether this file wrapper class can handle ``path``."""
"""
return not path.islink() and path.isfile() return not path.islink() and path.isfile()
def rename(self, newname): def rename(self, newname):
@@ -176,8 +201,7 @@ class File:
self.path = destpath self.path = destpath
def get_display_info(self, group, delta): def get_display_info(self, group, delta):
"""Returns a display-ready dict of dupe's data. """Returns a display-ready dict of dupe's data."""
"""
raise NotImplementedError() raise NotImplementedError()
# --- Properties # --- Properties
@@ -197,7 +221,7 @@ class File:
class Folder(File): class Folder(File):
"""A wrapper around a folder path. """A wrapper around a folder path.
It has the size/md5 info of a File, but it's value are the sum of its subitems. It has the size/md5 info of a File, but its value is the sum of its subitems.
""" """
__slots__ = File.__slots__ + ("_subfolders",) __slots__ = File.__slots__ + ("_subfolders",)
@@ -212,15 +236,17 @@ class Folder(File):
return folders + files return folders + files
def _read_info(self, field): def _read_info(self, field):
# print(f"_read_info({field}) for Folder {self}")
if field in {"size", "mtime"}: if field in {"size", "mtime"}:
size = sum((f.size for f in self._all_items()), 0) size = sum((f.size for f in self._all_items()), 0)
self.size = size self.size = size
stats = self.path.stat() stats = self.path.stat()
self.mtime = nonone(stats.st_mtime, 0) self.mtime = nonone(stats.st_mtime, 0)
elif field in {"md5", "md5partial"}: elif field in {"md5", "md5partial", "md5samples"}:
# What's sensitive here is that we must make sure that subfiles' # What's sensitive here is that we must make sure that subfiles'
# md5 are always added up in the same order, but we also want a # md5 are always added up in the same order, but we also want a
# different md5 if a file gets moved in a different subdirectory. # different md5 if a file gets moved in a different subdirectory.
def get_dir_md5_concat(): def get_dir_md5_concat():
items = self._all_items() items = self._all_items()
items.sort(key=lambda f: f.path) items.sort(key=lambda f: f.path)
@@ -234,9 +260,7 @@ class Folder(File):
@property @property
def subfolders(self): def subfolders(self):
if self._subfolders is None: if self._subfolders is None:
subfolders = [ subfolders = [p for p in self.path.listdir() if not p.islink() and p.isdir()]
p for p in self.path.listdir() if not p.islink() and p.isdir()
]
self._subfolders = [self.__class__(p) for p in subfolders] self._subfolders = [self.__class__(p) for p in subfolders]
return self._subfolders return self._subfolders

View File

@@ -29,8 +29,7 @@ class DeletionOptionsView:
""" """
def update_msg(self, msg: str): def update_msg(self, msg: str):
"""Update the dialog's prompt with ``str``. """Update the dialog's prompt with ``str``."""
"""
def show(self): def show(self):
"""Show the dialog in a modal fashion. """Show the dialog in a modal fashion.
@@ -39,8 +38,7 @@ class DeletionOptionsView:
""" """
def set_hardlink_option_enabled(self, is_enabled: bool): def set_hardlink_option_enabled(self, is_enabled: bool):
"""Enable or disable the widget controlling :attr:`DeletionOptions.use_hardlinks`. """Enable or disable the widget controlling :attr:`DeletionOptions.use_hardlinks`."""
"""
class DeletionOptions(GUIObject): class DeletionOptions(GUIObject):
@@ -75,8 +73,7 @@ class DeletionOptions(GUIObject):
return self.view.show() return self.view.show()
def supports_links(self): def supports_links(self):
"""Returns whether our platform supports symlinks. """Returns whether our platform supports symlinks."""
"""
# When on a platform that doesn't implement it, calling os.symlink() (with the wrong number # When on a platform that doesn't implement it, calling os.symlink() (with the wrong number
# of arguments) raises NotImplementedError, which allows us to gracefully check for the # of arguments) raises NotImplementedError, which allows us to gracefully check for the
# feature. # feature.

View File

@@ -32,9 +32,7 @@ class DetailsPanel(GUIObject, DupeGuruGUIObject):
# we don't want the two sides of the table to display the stats for the same file # we don't want the two sides of the table to display the stats for the same file
ref = group.ref if group is not None and group.ref is not dupe else None ref = group.ref if group is not None and group.ref is not dupe else None
data2 = self.app.get_display_info(ref, group, False) data2 = self.app.get_display_info(ref, group, False)
columns = self.app.result_table.COLUMNS[ columns = self.app.result_table.COLUMNS[1:] # first column is the 'marked' column
1:
] # first column is the 'marked' column
self._table = [(c.display, data1[c.name], data2[c.name]) for c in columns] self._table = [(c.display, data1[c.name], data2[c.name]) for c in columns]
# --- Public # --- Public

View File

@@ -36,9 +36,7 @@ class DirectoryNode(Node):
self._loaded = True self._loaded = True
def update_all_states(self): def update_all_states(self):
self._state = STATE_ORDER.index( self._state = STATE_ORDER.index(self._tree.app.directories.get_state(self._directory_path))
self._tree.app.directories.get_state(self._directory_path)
)
for node in self: for node in self:
node.update_all_states() node.update_all_states()

View File

@@ -7,6 +7,8 @@
# from hscommon.trans import tr # from hscommon.trans import tr
from .exclude_list_table import ExcludeListTable from .exclude_list_table import ExcludeListTable
from core.exclude import has_sep
from os import sep
import logging import logging
@@ -30,9 +32,10 @@ class ExcludeListDialogCore:
self.refresh() self.refresh()
def rename_selected(self, newregex): def rename_selected(self, newregex):
"""Renames the selected regex to ``newregex``. """Rename the selected regex to ``newregex``.
If there's more than one selected row, the first one is used. If there is more than one selected row, the first one is used.
:param str newregex: The regex to rename the row's regex to. :param str newregex: The regex to rename the row's regex to.
:return bool: true if success, false if error.
""" """
try: try:
r = self.exclude_list_table.selected_rows[0] r = self.exclude_list_table.selected_rows[0]
@@ -52,17 +55,37 @@ class ExcludeListDialogCore:
self.exclude_list_table.add(regex) self.exclude_list_table.add(regex)
def test_string(self, test_string): def test_string(self, test_string):
"""Sets property on row to highlight if its regex matches test_string supplied.""" """Set the highlight property on each row when its regex matches the
test_string supplied. Return True if any row matched."""
matched = False matched = False
for row in self.exclude_list_table.rows: for row in self.exclude_list_table.rows:
compiled_regex = self.exclude_list.get_compiled(row.regex) compiled_regex = self.exclude_list.get_compiled(row.regex)
if compiled_regex and compiled_regex.match(test_string):
matched = True if self.is_match(test_string, compiled_regex):
row.highlight = True row.highlight = True
matched = True
else: else:
row.highlight = False row.highlight = False
return matched return matched
def is_match(self, test_string, compiled_regex):
# This method is like an inverted version of ExcludeList.is_excluded()
if not compiled_regex:
return False
matched = False
# Test only the filename portion of the path
if not has_sep(compiled_regex.pattern) and sep in test_string:
filename = test_string.rsplit(sep, 1)[1]
if compiled_regex.fullmatch(filename):
matched = True
return matched
# Test the entire path + filename
if compiled_regex.fullmatch(test_string):
matched = True
return matched
def reset_rows_highlight(self): def reset_rows_highlight(self):
for row in self.exclude_list_table.rows: for row in self.exclude_list_table.rows:
row.highlight = False row.highlight = False

View File

@@ -6,14 +6,12 @@ from .base import DupeGuruGUIObject
from hscommon.gui.table import GUITable, Row from hscommon.gui.table import GUITable, Row
from hscommon.gui.column import Column, Columns from hscommon.gui.column import Column, Columns
from hscommon.trans import trget from hscommon.trans import trget
tr = trget("ui") tr = trget("ui")
class ExcludeListTable(GUITable, DupeGuruGUIObject): class ExcludeListTable(GUITable, DupeGuruGUIObject):
COLUMNS = [ COLUMNS = [Column("marked", ""), Column("regex", tr("Regular Expressions"))]
Column("marked", ""),
Column("regex", tr("Regular Expressions"))
]
def __init__(self, exclude_list_dialog, app): def __init__(self, exclude_list_dialog, app):
GUITable.__init__(self) GUITable.__init__(self)
@@ -36,7 +34,7 @@ class ExcludeListTable(GUITable, DupeGuruGUIObject):
return ExcludeListRow(self, self.dialog.exclude_list.is_marked(regex), regex), 0 return ExcludeListRow(self, self.dialog.exclude_list.is_marked(regex), regex), 0
def _do_delete(self): def _do_delete(self):
self.dalog.exclude_list.remove(self.selected_row.regex) self.dialog.exclude_list.remove(self.selected_row.regex)
# --- Override # --- Override
def add(self, regex): def add(self, regex):

View File

@@ -22,9 +22,7 @@ class IgnoreListDialog:
def clear(self): def clear(self):
if not self.ignore_list: if not self.ignore_list:
return return
msg = tr( msg = tr("Do you really want to remove all %d items from the ignore list?") % len(self.ignore_list)
"Do you really want to remove all %d items from the ignore list?"
) % len(self.ignore_list)
if self.app.view.ask_yes_no(msg): if self.app.view.ask_yes_no(msg):
self.ignore_list.Clear() self.ignore_list.Clear()
self.refresh() self.refresh()

View File

@@ -41,11 +41,11 @@ class DupeRow(Row):
# table.DELTA_COLUMNS are always "delta" # table.DELTA_COLUMNS are always "delta"
self._delta_columns = self.table.DELTA_COLUMNS.copy() self._delta_columns = self.table.DELTA_COLUMNS.copy()
dupe_info = self.data dupe_info = self.data
if self._group.ref is None:
return False
ref_info = self._group.ref.get_display_info(group=self._group, delta=False) ref_info = self._group.ref.get_display_info(group=self._group, delta=False)
for key, value in dupe_info.items(): for key, value in dupe_info.items():
if (key not in self._delta_columns) and ( if (key not in self._delta_columns) and (ref_info[key].lower() != value.lower()):
ref_info[key].lower() != value.lower()
):
self._delta_columns.add(key) self._delta_columns.add(key)
return column_name in self._delta_columns return column_name in self._delta_columns

View File

@@ -33,8 +33,7 @@ CacheRow = namedtuple("CacheRow", "id path blocks mtime")
class ShelveCache: class ShelveCache:
"""A class to cache picture blocks in a shelve backend. """A class to cache picture blocks in a shelve backend."""
"""
def __init__(self, db=None, readonly=False): def __init__(self, db=None, readonly=False):
self.istmp = db is None self.istmp = db is None
@@ -81,9 +80,7 @@ class ShelveCache:
self.shelve[wrap_id(rowid)] = wrap_path(path_str) self.shelve[wrap_id(rowid)] = wrap_path(path_str)
def _compute_maxid(self): def _compute_maxid(self):
return max( return max((unwrap_id(k) for k in self.shelve if k.startswith("id:")), default=1)
(unwrap_id(k) for k in self.shelve if k.startswith("id:")), default=1
)
def _get_new_id(self): def _get_new_id(self):
self.maxid += 1 self.maxid += 1

View File

@@ -13,8 +13,7 @@ from .cache import string_to_colors, colors_to_string
class SqliteCache: class SqliteCache:
"""A class to cache picture blocks in a sqlite backend. """A class to cache picture blocks in a sqlite backend."""
"""
def __init__(self, db=":memory:", readonly=False): def __init__(self, db=":memory:", readonly=False):
# readonly is not used in the sqlite version of the cache # readonly is not used in the sqlite version of the cache
@@ -71,18 +70,14 @@ class SqliteCache:
except sqlite.OperationalError: except sqlite.OperationalError:
logging.warning("Picture cache could not set value for key %r", path_str) logging.warning("Picture cache could not set value for key %r", path_str)
except sqlite.DatabaseError as e: except sqlite.DatabaseError as e:
logging.warning( logging.warning("DatabaseError while setting value for key %r: %s", path_str, str(e))
"DatabaseError while setting value for key %r: %s", path_str, str(e)
)
def _create_con(self, second_try=False): def _create_con(self, second_try=False):
def create_tables(): def create_tables():
logging.debug("Creating picture cache tables.") logging.debug("Creating picture cache tables.")
self.con.execute("drop table if exists pictures") self.con.execute("drop table if exists pictures")
self.con.execute("drop index if exists idx_path") self.con.execute("drop index if exists idx_path")
self.con.execute( self.con.execute("create table pictures(path TEXT, mtime INTEGER, blocks TEXT)")
"create table pictures(path TEXT, mtime INTEGER, blocks TEXT)"
)
self.con.execute("create index idx_path on pictures (path)") self.con.execute("create index idx_path on pictures (path)")
self.con = sqlite.connect(self.dbname, isolation_level=None) self.con = sqlite.connect(self.dbname, isolation_level=None)
@@ -93,9 +88,7 @@ class SqliteCache:
except sqlite.DatabaseError as e: # corrupted db except sqlite.DatabaseError as e: # corrupted db
if second_try: if second_try:
raise # Something really strange is happening raise # Something really strange is happening
logging.warning( logging.warning("Could not create picture cache because of an error: %s", str(e))
"Could not create picture cache because of an error: %s", str(e)
)
self.con.close() self.con.close()
os.remove(self.dbname) os.remove(self.dbname)
self._create_con(second_try=True) self._create_con(second_try=True)
@@ -125,9 +118,7 @@ class SqliteCache:
raise ValueError(path) raise ValueError(path)
def get_multiple(self, rowids): def get_multiple(self, rowids):
sql = "select rowid, blocks from pictures where rowid in (%s)" % ",".join( sql = "select rowid, blocks from pictures where rowid in (%s)" % ",".join(map(str, rowids))
map(str, rowids)
)
cur = self.con.execute(sql) cur = self.con.execute(sql)
return ((rowid, string_to_colors(blocks)) for rowid, blocks in cur) return ((rowid, string_to_colors(blocks)) for rowid, blocks in cur)
@@ -148,7 +139,5 @@ class SqliteCache:
continue continue
todelete.append(rowid) todelete.append(rowid)
if todelete: if todelete:
sql = "delete from pictures where rowid in (%s)" % ",".join( sql = "delete from pictures where rowid in (%s)" % ",".join(map(str, todelete))
map(str, todelete)
)
self.con.execute(sql) self.con.execute(sql)

View File

@@ -256,9 +256,7 @@ class TIFF_file:
for j in range(count): for j in range(count):
if type in {5, 10}: if type in {5, 10}:
# The type is either 5 or 10 # The type is either 5 or 10
value_j = Fraction( value_j = Fraction(self.s2n(offset, 4, signed), self.s2n(offset + 4, 4, signed))
self.s2n(offset, 4, signed), self.s2n(offset + 4, 4, signed)
)
else: else:
# Not a fraction # Not a fraction
value_j = self.s2n(offset, typelen, signed) value_j = self.s2n(offset, typelen, signed)
@@ -296,9 +294,7 @@ def get_fields(fp):
logging.debug("Exif header length: %d bytes", length) logging.debug("Exif header length: %d bytes", length)
data = fp.read(length - 8) data = fp.read(length - 8)
data_format = data[0] data_format = data[0]
logging.debug( logging.debug("%s format", {INTEL_ENDIAN: "Intel", MOTOROLA_ENDIAN: "Motorola"}[data_format])
"%s format", {INTEL_ENDIAN: "Intel", MOTOROLA_ENDIAN: "Motorola"}[data_format]
)
T = TIFF_file(data) T = TIFF_file(data)
# There may be more than one IFD per file, but we only read the first one because others are # There may be more than one IFD per file, but we only read the first one because others are
# most likely thumbnails. # most likely thumbnails.

View File

@@ -95,9 +95,7 @@ def prepare_pictures(pictures, cache_path, with_dimensions, j=job.nulljob):
picture.unicode_path, picture.unicode_path,
picture.size, picture.size,
) )
if ( if picture.size < 10 * 1024 * 1024: # We're really running out of memory
picture.size < 10 * 1024 * 1024
): # We're really running out of memory
raise raise
except MemoryError: except MemoryError:
logging.warning("Ran out of memory while preparing pictures") logging.warning("Ran out of memory while preparing pictures")
@@ -106,9 +104,7 @@ def prepare_pictures(pictures, cache_path, with_dimensions, j=job.nulljob):
def get_chunks(pictures): def get_chunks(pictures):
min_chunk_count = ( min_chunk_count = multiprocessing.cpu_count() * 2 # have enough chunks to feed all subprocesses
multiprocessing.cpu_count() * 2
) # have enough chunks to feed all subprocesses
chunk_count = len(pictures) // DEFAULT_CHUNK_SIZE chunk_count = len(pictures) // DEFAULT_CHUNK_SIZE
chunk_count = max(min_chunk_count, chunk_count) chunk_count = max(min_chunk_count, chunk_count)
chunk_size = (len(pictures) // chunk_count) + 1 chunk_size = (len(pictures) // chunk_count) + 1
@@ -185,9 +181,7 @@ def getmatches(pictures, cache_path, threshold, match_scaled=False, j=job.nulljo
j.set_progress(comparison_count, progress_msg) j.set_progress(comparison_count, progress_msg)
j = j.start_subjob([3, 7]) j = j.start_subjob([3, 7])
pictures = prepare_pictures( pictures = prepare_pictures(pictures, cache_path, with_dimensions=not match_scaled, j=j)
pictures, cache_path, with_dimensions=not match_scaled, j=j
)
j = j.start_subjob([9, 1], tr("Preparing for matching")) j = j.start_subjob([9, 1], tr("Preparing for matching"))
cache = get_cache(cache_path) cache = get_cache(cache_path)
id2picture = {} id2picture = {}
@@ -231,12 +225,8 @@ def getmatches(pictures, cache_path, threshold, match_scaled=False, j=job.nulljo
chunks, chunks,
pictures, pictures,
) # some wiggle room for the next statements ) # some wiggle room for the next statements
logging.warning( logging.warning("Ran out of memory when scanning! We had %d matches.", len(matches))
"Ran out of memory when scanning! We had %d matches.", len(matches) del matches[-len(matches) // 3 :] # some wiggle room to ensure we don't run out of memory again.
)
del matches[
-len(matches) // 3 :
] # some wiggle room to ensure we don't run out of memory again.
pool.close() pool.close()
result = [] result = []
myiter = j.iter_with_progress( myiter = j.iter_with_progress(

View File

@@ -52,6 +52,7 @@ class Results(Markable):
self.app = app self.app = app
self.problems = [] # (dupe, error_msg) self.problems = [] # (dupe, error_msg)
self.is_modified = False self.is_modified = False
self.refresh_required = False
def _did_mark(self, dupe): def _did_mark(self, dupe):
self.__marked_size += dupe.size self.__marked_size += dupe.size
@@ -94,8 +95,9 @@ class Results(Markable):
# ---Private # ---Private
def __get_dupe_list(self): def __get_dupe_list(self):
if self.__dupes is None: if self.__dupes is None or self.refresh_required:
self.__dupes = flatten(group.dupes for group in self.groups) self.__dupes = flatten(group.dupes for group in self.groups)
self.refresh_required = False
if None in self.__dupes: if None in self.__dupes:
# This is debug logging to try to figure out #44 # This is debug logging to try to figure out #44
logging.warning( logging.warning(
@@ -104,9 +106,7 @@ class Results(Markable):
self.groups, self.groups,
) )
if self.__filtered_dupes: if self.__filtered_dupes:
self.__dupes = [ self.__dupes = [dupe for dupe in self.__dupes if dupe in self.__filtered_dupes]
dupe for dupe in self.__dupes if dupe in self.__filtered_dupes
]
sd = self.__dupes_sort_descriptor sd = self.__dupes_sort_descriptor
if sd: if sd:
self.sort_dupes(sd[0], sd[1], sd[2]) self.sort_dupes(sd[0], sd[1], sd[2])
@@ -125,18 +125,10 @@ class Results(Markable):
total_count = self.__total_count total_count = self.__total_count
total_size = self.__total_size total_size = self.__total_size
else: else:
mark_count = len( mark_count = len([dupe for dupe in self.__filtered_dupes if self.is_marked(dupe)])
[dupe for dupe in self.__filtered_dupes if self.is_marked(dupe)] marked_size = sum(dupe.size for dupe in self.__filtered_dupes if self.is_marked(dupe))
) total_count = len([dupe for dupe in self.__filtered_dupes if self.is_markable(dupe)])
marked_size = sum( total_size = sum(dupe.size for dupe in self.__filtered_dupes if self.is_markable(dupe))
dupe.size for dupe in self.__filtered_dupes if self.is_marked(dupe)
)
total_count = len(
[dupe for dupe in self.__filtered_dupes if self.is_markable(dupe)]
)
total_size = sum(
dupe.size for dupe in self.__filtered_dupes if self.is_markable(dupe)
)
if self.mark_inverted: if self.mark_inverted:
marked_size = self.__total_size - marked_size marked_size = self.__total_size - marked_size
result = tr("%d / %d (%s / %s) duplicates marked.") % ( result = tr("%d / %d (%s / %s) duplicates marked.") % (
@@ -199,11 +191,7 @@ class Results(Markable):
self.__filters.append(filter_str) self.__filters.append(filter_str)
if self.__filtered_dupes is None: if self.__filtered_dupes is None:
self.__filtered_dupes = flatten(g[:] for g in self.groups) self.__filtered_dupes = flatten(g[:] for g in self.groups)
self.__filtered_dupes = set( self.__filtered_dupes = set(dupe for dupe in self.__filtered_dupes if filter_re.search(str(dupe.path)))
dupe
for dupe in self.__filtered_dupes
if filter_re.search(str(dupe.path))
)
filtered_groups = set() filtered_groups = set()
for dupe in self.__filtered_dupes: for dupe in self.__filtered_dupes:
filtered_groups.add(self.get_group_of_duplicate(dupe)) filtered_groups.add(self.get_group_of_duplicate(dupe))
@@ -215,8 +203,7 @@ class Results(Markable):
self.__dupes = None self.__dupes = None
def get_group_of_duplicate(self, dupe): def get_group_of_duplicate(self, dupe):
"""Returns :class:`~core.engine.Group` in which ``dupe`` belongs. """Returns :class:`~core.engine.Group` in which ``dupe`` belongs."""
"""
try: try:
return self.__group_of_duplicate[dupe] return self.__group_of_duplicate[dupe]
except (TypeError, KeyError): except (TypeError, KeyError):
@@ -282,8 +269,7 @@ class Results(Markable):
self.is_modified = False self.is_modified = False
def make_ref(self, dupe): def make_ref(self, dupe):
"""Make ``dupe`` take the :attr:`~core.engine.Group.ref` position of its group. """Make ``dupe`` take the :attr:`~core.engine.Group.ref` position of its group."""
"""
g = self.get_group_of_duplicate(dupe) g = self.get_group_of_duplicate(dupe)
r = g.ref r = g.ref
if not g.switch_ref(dupe): if not g.switch_ref(dupe):
@@ -410,10 +396,10 @@ class Results(Markable):
""" """
if not self.__dupes: if not self.__dupes:
self.__get_dupe_list() self.__get_dupe_list()
keyfunc = lambda d: self.app._get_dupe_sort_key( self.__dupes.sort(
d, lambda: self.get_group_of_duplicate(d), key, delta key=lambda d: self.app._get_dupe_sort_key(d, lambda: self.get_group_of_duplicate(d), key, delta),
reverse=not asc,
) )
self.__dupes.sort(key=keyfunc, reverse=not asc)
self.__dupes_sort_descriptor = (key, asc, delta) self.__dupes_sort_descriptor = (key, asc, delta)
def sort_groups(self, key, asc=True): def sort_groups(self, key, asc=True):
@@ -424,8 +410,7 @@ class Results(Markable):
:param str key: key attribute name to sort with. :param str key: key attribute name to sort with.
:param bool asc: If false, sorting is reversed. :param bool asc: If false, sorting is reversed.
""" """
keyfunc = lambda g: self.app._get_group_sort_key(g, key) self.groups.sort(key=lambda g: self.app._get_group_sort_key(g, key), reverse=not asc)
self.groups.sort(key=keyfunc, reverse=not asc)
self.__groups_sort_descriptor = (key, asc) self.__groups_sort_descriptor = (key, asc)
# ---Properties # ---Properties

View File

@@ -87,7 +87,7 @@ class Scanner:
if self.size_threshold: if self.size_threshold:
files = [f for f in files if f.size >= self.size_threshold] files = [f for f in files if f.size >= self.size_threshold]
if self.scan_type in {ScanType.Contents, ScanType.Folders}: if self.scan_type in {ScanType.Contents, ScanType.Folders}:
return engine.getmatches_by_contents(files, j=j) return engine.getmatches_by_contents(files, bigsize=self.big_file_size_threshold, j=j)
else: else:
j = j.start_subjob([2, 8]) j = j.start_subjob([2, 8])
kw = {} kw = {}
@@ -161,27 +161,13 @@ class Scanner:
toremove.add(p) toremove.add(p)
else: else:
last_parent_path = p last_parent_path = p
matches = [ matches = [m for m in matches if m.first.path not in toremove or m.second.path not in toremove]
m
for m in matches
if m.first.path not in toremove or m.second.path not in toremove
]
if not self.mix_file_kind: if not self.mix_file_kind:
matches = [ matches = [m for m in matches if get_file_ext(m.first.name) == get_file_ext(m.second.name)]
m matches = [m for m in matches if m.first.path.exists() and m.second.path.exists()]
for m in matches
if get_file_ext(m.first.name) == get_file_ext(m.second.name)
]
matches = [
m for m in matches if m.first.path.exists() and m.second.path.exists()
]
matches = [m for m in matches if not (m.first.is_ref and m.second.is_ref)] matches = [m for m in matches if not (m.first.is_ref and m.second.is_ref)]
if ignore_list: if ignore_list:
matches = [ matches = [m for m in matches if not ignore_list.AreIgnored(str(m.first.path), str(m.second.path))]
m
for m in matches
if not ignore_list.AreIgnored(str(m.first.path), str(m.second.path))
]
logging.info("Grouping matches") logging.info("Grouping matches")
groups = engine.get_groups(matches) groups = engine.get_groups(matches)
if self.scan_type in { if self.scan_type in {
@@ -190,9 +176,7 @@ class Scanner:
ScanType.FieldsNoOrder, ScanType.FieldsNoOrder,
ScanType.Tag, ScanType.Tag,
}: }:
matched_files = dedupe( matched_files = dedupe([m.first for m in matches] + [m.second for m in matches])
[m.first for m in matches] + [m.second for m in matches]
)
self.discarded_file_count = len(matched_files) - sum(len(g) for g in groups) self.discarded_file_count = len(matched_files) - sum(len(g) for g in groups)
else: else:
# Ticket #195 # Ticket #195
@@ -218,4 +202,5 @@ class Scanner:
scan_type = ScanType.Filename scan_type = ScanType.Filename
scanned_tags = {"artist", "title"} scanned_tags = {"artist", "title"}
size_threshold = 0 size_threshold = 0
big_file_size_threshold = 0
word_weighting = False word_weighting = False

View File

@@ -29,9 +29,7 @@ def add_fake_files_to_directories(directories, files):
class TestCaseDupeGuru: class TestCaseDupeGuru:
def test_apply_filter_calls_results_apply_filter(self, monkeypatch): def test_apply_filter_calls_results_apply_filter(self, monkeypatch):
dgapp = TestApp().app dgapp = TestApp().app
monkeypatch.setattr( monkeypatch.setattr(dgapp.results, "apply_filter", log_calls(dgapp.results.apply_filter))
dgapp.results, "apply_filter", log_calls(dgapp.results.apply_filter)
)
dgapp.apply_filter("foo") dgapp.apply_filter("foo")
eq_(2, len(dgapp.results.apply_filter.calls)) eq_(2, len(dgapp.results.apply_filter.calls))
call = dgapp.results.apply_filter.calls[0] call = dgapp.results.apply_filter.calls[0]
@@ -41,15 +39,11 @@ class TestCaseDupeGuru:
def test_apply_filter_escapes_regexp(self, monkeypatch): def test_apply_filter_escapes_regexp(self, monkeypatch):
dgapp = TestApp().app dgapp = TestApp().app
monkeypatch.setattr( monkeypatch.setattr(dgapp.results, "apply_filter", log_calls(dgapp.results.apply_filter))
dgapp.results, "apply_filter", log_calls(dgapp.results.apply_filter)
)
dgapp.apply_filter("()[]\\.|+?^abc") dgapp.apply_filter("()[]\\.|+?^abc")
call = dgapp.results.apply_filter.calls[1] call = dgapp.results.apply_filter.calls[1]
eq_("\\(\\)\\[\\]\\\\\\.\\|\\+\\?\\^abc", call["filter_str"]) eq_("\\(\\)\\[\\]\\\\\\.\\|\\+\\?\\^abc", call["filter_str"])
dgapp.apply_filter( dgapp.apply_filter("(*)") # In "simple mode", we want the * to behave as a wilcard
"(*)"
) # In "simple mode", we want the * to behave as a wilcard
call = dgapp.results.apply_filter.calls[3] call = dgapp.results.apply_filter.calls[3]
eq_(r"\(.*\)", call["filter_str"]) eq_(r"\(.*\)", call["filter_str"])
dgapp.options["escape_filter_regexp"] = False dgapp.options["escape_filter_regexp"] = False
@@ -70,9 +64,7 @@ class TestCaseDupeGuru:
) )
# XXX This monkeypatch is temporary. will be fixed in a better monkeypatcher. # XXX This monkeypatch is temporary. will be fixed in a better monkeypatcher.
monkeypatch.setattr(app, "smart_copy", hscommon.conflict.smart_copy) monkeypatch.setattr(app, "smart_copy", hscommon.conflict.smart_copy)
monkeypatch.setattr( monkeypatch.setattr(os, "makedirs", lambda path: None) # We don't want the test to create that fake directory
os, "makedirs", lambda path: None
) # We don't want the test to create that fake directory
dgapp = TestApp().app dgapp = TestApp().app
dgapp.directories.add_path(p) dgapp.directories.add_path(p)
[f] = dgapp.directories.get_files() [f] = dgapp.directories.get_files()
@@ -320,9 +312,7 @@ class TestCaseDupeGuruWithResults:
assert groups[0].ref is objects[1] assert groups[0].ref is objects[1]
assert groups[1].ref is objects[4] assert groups[1].ref is objects[4]
def test_makeSelectedReference_by_selecting_two_dupes_in_the_same_group( def test_makeSelectedReference_by_selecting_two_dupes_in_the_same_group(self, do_setup):
self, do_setup
):
app = self.app app = self.app
objects = self.objects objects = self.objects
groups = self.groups groups = self.groups
@@ -404,9 +394,7 @@ class TestCaseDupeGuruWithResults:
# results table. # results table.
app = self.app app = self.app
app.JOB = Job(1, lambda *args, **kw: False) # Cancels the task app.JOB = Job(1, lambda *args, **kw: False) # Cancels the task
add_fake_files_to_directories( add_fake_files_to_directories(app.directories, self.objects) # We want the scan to at least start
app.directories, self.objects
) # We want the scan to at least start
app.start_scanning() # will be cancelled immediately app.start_scanning() # will be cancelled immediately
eq_(len(app.result_table), 0) eq_(len(app.result_table), 0)

View File

@@ -88,6 +88,7 @@ class NamedObject:
self.size = size self.size = size
self.md5partial = name self.md5partial = name
self.md5 = name self.md5 = name
self.md5samples = name
if with_words: if with_words:
self.words = getwords(name) self.words = getwords(name)
self.is_ref = False self.is_ref = False
@@ -139,9 +140,7 @@ def GetTestGroups():
matches = engine.getmatches(objects) # we should have 5 matches matches = engine.getmatches(objects) # we should have 5 matches
groups = engine.get_groups(matches) # We should have 2 groups groups = engine.get_groups(matches) # We should have 2 groups
for g in groups: for g in groups:
g.prioritize( g.prioritize(lambda x: objects.index(x)) # We want the dupes to be in the same order as the list is
lambda x: objects.index(x)
) # We want the dupes to be in the same order as the list is
groups.sort(key=len, reverse=True) # We want the group with 3 members to be first. groups.sort(key=len, reverse=True) # We want the group with 3 members to be first.
return (objects, matches, groups) return (objects, matches, groups)

View File

@@ -14,9 +14,7 @@ except ImportError:
skip("Can't import the block module, probably hasn't been compiled.") skip("Can't import the block module, probably hasn't been compiled.")
def my_avgdiff( def my_avgdiff(first, second, limit=768, min_iter=3): # this is so I don't have to re-write every call
first, second, limit=768, min_iter=3
): # this is so I don't have to re-write every call
return avgdiff(first, second, limit, min_iter) return avgdiff(first, second, limit, min_iter)

View File

@@ -254,7 +254,12 @@ def test_invalid_path():
def test_set_state_on_invalid_path(): def test_set_state_on_invalid_path():
d = Directories() d = Directories()
try: try:
d.set_state(Path("foobar",), DirectoryState.Normal) d.set_state(
Path(
"foobar",
),
DirectoryState.Normal,
)
except LookupError: except LookupError:
assert False assert False
@@ -345,15 +350,17 @@ def test_default_path_state_override(tmpdir):
eq_(len(list(d.get_files())), 2) eq_(len(list(d.get_files())), 2)
class TestExcludeList(): class TestExcludeList:
def setup_method(self, method): def setup_method(self, method):
self.d = Directories(exclude_list=ExcludeList(union_regex=False)) self.d = Directories(exclude_list=ExcludeList(union_regex=False))
def get_files_and_expect_num_result(self, num_result): def get_files_and_expect_num_result(self, num_result):
"""Calls get_files(), get the filenames only, print for debugging. """Calls get_files(), get the filenames only, print for debugging.
num_result is how many files are expected as a result.""" num_result is how many files are expected as a result."""
print(f"EXCLUDED REGEX: paths {self.d._exclude_list.compiled_paths} \ print(
files: {self.d._exclude_list.compiled_files} all: {self.d._exclude_list.compiled}") f"EXCLUDED REGEX: paths {self.d._exclude_list.compiled_paths} \
files: {self.d._exclude_list.compiled_files} all: {self.d._exclude_list.compiled}"
)
files = list(self.d.get_files()) files = list(self.d.get_files())
files = [file.name for file in files] files = [file.name for file in files]
print(f"FINAL FILES {files}") print(f"FINAL FILES {files}")
@@ -473,6 +480,29 @@ files: {self.d._exclude_list.compiled_files} all: {self.d._exclude_list.compiled
assert "file_ending_with_subdir" not in files assert "file_ending_with_subdir" not in files
assert "file_which_shouldnt_match" in files assert "file_which_shouldnt_match" in files
# This should match the directory only
regex6 = r".*/.*subdir.*/.*"
if ISWINDOWS:
regex6 = r".*\\.*subdir.*\\.*"
assert os.sep in regex6
self.d._exclude_list.rename(regex5, regex6)
self.d._exclude_list.remove(regex1)
eq_(len(self.d._exclude_list.compiled), 1)
assert regex1 not in self.d._exclude_list
assert regex5 not in self.d._exclude_list
assert self.d._exclude_list.error(regex6) is None
assert regex6 in self.d._exclude_list
# This still should not be affected
eq_(self.d.get_state(p1["$Recycle.Bin"]["subdir"]), DirectoryState.Normal)
files = self.get_files_and_expect_num_result(5)
# These files are under the "/subdir" directory
assert "somesubdirfile.png" not in files
assert "unwanted_subdirfile.gif" not in files
# This file under "subdar" directory should not be filtered out
assert "file_ending_with_subdir" in files
# This file is in a directory that should be filtered out
assert "file_which_shouldnt_match" not in files
def test_japanese_unicode(self, tmpdir): def test_japanese_unicode(self, tmpdir):
p1 = Path(str(tmpdir)) p1 = Path(str(tmpdir))
p1["$Recycle.Bin"].mkdir() p1["$Recycle.Bin"].mkdir()

View File

@@ -69,6 +69,10 @@ class TestCasegetwords:
eq_(["a", "b", "c", "d"], getwords("a b c d")) eq_(["a", "b", "c", "d"], getwords("a b c d"))
eq_(["a", "b", "c", "d"], getwords(" a b c d ")) eq_(["a", "b", "c", "d"], getwords(" a b c d "))
def test_unicode(self):
eq_(["e", "c", "0", "a", "o", "u", "e", "u"], getwords("é ç 0 à ö û è ¤ ù"))
eq_(["02", "君のこころは輝いてるかい?", "国木田花丸", "solo", "ver"], getwords("02 君のこころは輝いてるかい? 国木田花丸 Solo Ver"))
def test_splitter_chars(self): def test_splitter_chars(self):
eq_( eq_(
[chr(i) for i in range(ord("a"), ord("z") + 1)], [chr(i) for i in range(ord("a"), ord("z") + 1)],
@@ -85,7 +89,7 @@ class TestCasegetwords:
eq_(["foo", "bar"], getwords("FOO BAR")) eq_(["foo", "bar"], getwords("FOO BAR"))
def test_decompose_unicode(self): def test_decompose_unicode(self):
eq_(getwords("foo\xe9bar"), ["fooebar"]) eq_(["fooebar"], getwords("foo\xe9bar"))
class TestCasegetfields: class TestCasegetfields:
@@ -173,9 +177,7 @@ class TestCaseWordCompareWithFields:
def test_simple(self): def test_simple(self):
eq_( eq_(
67, 67,
compare_fields( compare_fields([["a", "b"], ["c", "d", "e"]], [["a", "b"], ["c", "d", "f"]]),
[["a", "b"], ["c", "d", "e"]], [["a", "b"], ["c", "d", "f"]]
),
) )
def test_empty(self): def test_empty(self):
@@ -261,9 +263,7 @@ class TestCasebuild_word_dict:
j = job.Job(1, do_progress) j = job.Job(1, do_progress)
self.log = [] self.log = []
s = "foo bar" s = "foo bar"
build_word_dict( build_word_dict([NamedObject(s, True), NamedObject(s, True), NamedObject(s, True)], j)
[NamedObject(s, True), NamedObject(s, True), NamedObject(s, True)], j
)
# We don't have intermediate log because iter_with_progress is called with every > 1 # We don't have intermediate log because iter_with_progress is called with every > 1
eq_(0, self.log[0]) eq_(0, self.log[0])
eq_(100, self.log[1]) eq_(100, self.log[1])
@@ -293,10 +293,7 @@ class TestCasereduce_common_words:
def test_dont_remove_objects_with_only_common_words(self): def test_dont_remove_objects_with_only_common_words(self):
d = { d = {
"common": set( "common": set([NamedObject("common uncommon", True) for i in range(50)] + [NamedObject("common", True)]),
[NamedObject("common uncommon", True) for i in range(50)]
+ [NamedObject("common", True)]
),
"uncommon": set([NamedObject("common uncommon", True)]), "uncommon": set([NamedObject("common uncommon", True)]),
} }
reduce_common_words(d, 50) reduce_common_words(d, 50)
@@ -305,10 +302,7 @@ class TestCasereduce_common_words:
def test_values_still_are_set_instances(self): def test_values_still_are_set_instances(self):
d = { d = {
"common": set( "common": set([NamedObject("common uncommon", True) for i in range(50)] + [NamedObject("common", True)]),
[NamedObject("common uncommon", True) for i in range(50)]
+ [NamedObject("common", True)]
),
"uncommon": set([NamedObject("common uncommon", True)]), "uncommon": set([NamedObject("common uncommon", True)]),
} }
reduce_common_words(d, 50) reduce_common_words(d, 50)
@@ -348,12 +342,8 @@ class TestCasereduce_common_words:
# would not stay in 'bar' because 'foo' is not a common word anymore. # would not stay in 'bar' because 'foo' is not a common word anymore.
only_common = NamedObject("foo bar", True) only_common = NamedObject("foo bar", True)
d = { d = {
"foo": set( "foo": set([NamedObject("foo bar baz", True) for i in range(49)] + [only_common]),
[NamedObject("foo bar baz", True) for i in range(49)] + [only_common] "bar": set([NamedObject("foo bar baz", True) for i in range(49)] + [only_common]),
),
"bar": set(
[NamedObject("foo bar baz", True) for i in range(49)] + [only_common]
),
"baz": set([NamedObject("foo bar baz", True) for i in range(49)]), "baz": set([NamedObject("foo bar baz", True) for i in range(49)]),
} }
reduce_common_words(d, 50) reduce_common_words(d, 50)
@@ -382,9 +372,7 @@ class TestCaseget_match:
assert object() not in m assert object() not in m
def test_word_weight(self): def test_word_weight(self):
m = get_match( m = get_match(NamedObject("foo bar", True), NamedObject("bar bleh", True), (WEIGHT_WORDS,))
NamedObject("foo bar", True), NamedObject("bar bleh", True), (WEIGHT_WORDS,)
)
eq_(m.percentage, int((6.0 / 13.0) * 100)) eq_(m.percentage, int((6.0 / 13.0) * 100))
@@ -547,6 +535,32 @@ class TestCaseGetMatchesByContents:
o1, o2 = no(size=0), no(size=0) o1, o2 = no(size=0), no(size=0)
assert not getmatches_by_contents([o1, o2]) assert not getmatches_by_contents([o1, o2])
def test_big_file_partial_hashes(self):
smallsize = 1
bigsize = 100 * 1024 * 1024 # 100MB
f = [
no("bigfoo", size=bigsize),
no("bigbar", size=bigsize),
no("smallfoo", size=smallsize),
no("smallbar", size=smallsize),
]
f[0].md5 = f[0].md5partial = f[0].md5samples = "foobar"
f[1].md5 = f[1].md5partial = f[1].md5samples = "foobar"
f[2].md5 = f[2].md5partial = "bleh"
f[3].md5 = f[3].md5partial = "bleh"
r = getmatches_by_contents(f, bigsize=bigsize)
eq_(len(r), 2)
# User disabled optimization for big files, compute hashes as usual
r = getmatches_by_contents(f, bigsize=0)
eq_(len(r), 2)
# Other file is now slightly different, md5partial is still the same
f[1].md5 = f[1].md5samples = "foobardiff"
r = getmatches_by_contents(f, bigsize=bigsize)
# Successfully filter it out
eq_(len(r), 1)
r = getmatches_by_contents(f, bigsize=0)
eq_(len(r), 1)
class TestCaseGroup: class TestCaseGroup:
def test_empy(self): def test_empy(self):
@@ -723,8 +737,7 @@ class TestCaseGroup:
# if the ref has the same key as one or more of the dupe, run the tie_breaker func among them # if the ref has the same key as one or more of the dupe, run the tie_breaker func among them
g = get_test_group() g = get_test_group()
o1, o2, o3 = g.ordered o1, o2, o3 = g.ordered
tie_breaker = lambda ref, dupe: dupe is o3 g.prioritize(lambda x: 0, lambda ref, dupe: dupe is o3)
g.prioritize(lambda x: 0, tie_breaker)
assert g.ref is o3 assert g.ref is o3
def test_prioritize_with_tie_breaker_runs_on_all_dupes(self): def test_prioritize_with_tie_breaker_runs_on_all_dupes(self):
@@ -735,8 +748,7 @@ class TestCaseGroup:
o1.foo = 1 o1.foo = 1
o2.foo = 2 o2.foo = 2
o3.foo = 3 o3.foo = 3
tie_breaker = lambda ref, dupe: dupe.foo > ref.foo g.prioritize(lambda x: 0, lambda ref, dupe: dupe.foo > ref.foo)
g.prioritize(lambda x: 0, tie_breaker)
assert g.ref is o3 assert g.ref is o3
def test_prioritize_with_tie_breaker_runs_only_on_tie_dupes(self): def test_prioritize_with_tie_breaker_runs_only_on_tie_dupes(self):
@@ -749,9 +761,7 @@ class TestCaseGroup:
o1.bar = 1 o1.bar = 1
o2.bar = 2 o2.bar = 2
o3.bar = 3 o3.bar = 3
key_func = lambda x: -x.foo g.prioritize(lambda x: -x.foo, lambda ref, dupe: dupe.bar > ref.bar)
tie_breaker = lambda ref, dupe: dupe.bar > ref.bar
g.prioritize(key_func, tie_breaker)
assert g.ref is o2 assert g.ref is o2
def test_prioritize_with_ref_dupe(self): def test_prioritize_with_ref_dupe(self):
@@ -883,9 +893,7 @@ class TestCaseget_groups:
m1 = Match(A, B, 90) # This is the strongest "A" match m1 = Match(A, B, 90) # This is the strongest "A" match
m2 = Match(A, C, 80) # Because C doesn't match with B, it won't be in the group m2 = Match(A, C, 80) # Because C doesn't match with B, it won't be in the group
m3 = Match(A, D, 80) # Same thing for D m3 = Match(A, D, 80) # Same thing for D
m4 = Match( m4 = Match(C, D, 70) # However, because C and D match, they should have their own group.
C, D, 70
) # However, because C and D match, they should have their own group.
groups = get_groups([m1, m2, m3, m4]) groups = get_groups([m1, m2, m3, m4])
eq_(len(groups), 2) eq_(len(groups), 2)
g1, g2 = groups g1, g2 = groups

View File

@@ -5,6 +5,7 @@
# http://www.gnu.org/licenses/gpl-3.0.html # http://www.gnu.org/licenses/gpl-3.0.html
import io import io
# import os.path as op # import os.path as op
from xml.etree import ElementTree as ET from xml.etree import ElementTree as ET
@@ -104,7 +105,7 @@ class TestCaseListEmpty:
regex1 = r"one" regex1 = r"one"
regex2 = r"two" regex2 = r"two"
self.exclude_list.add(regex1) self.exclude_list.add(regex1)
assert(regex1 in self.exclude_list) assert regex1 in self.exclude_list
self.exclude_list.add(regex2) self.exclude_list.add(regex2)
self.exclude_list.mark(regex1) self.exclude_list.mark(regex1)
self.exclude_list.mark(regex2) self.exclude_list.mark(regex2)
@@ -113,7 +114,7 @@ class TestCaseListEmpty:
compiled_files = [x for x in self.exclude_list.compiled_files] compiled_files = [x for x in self.exclude_list.compiled_files]
eq_(len(compiled_files), 2) eq_(len(compiled_files), 2)
self.exclude_list.remove(regex2) self.exclude_list.remove(regex2)
assert(regex2 not in self.exclude_list) assert regex2 not in self.exclude_list
eq_(len(self.exclude_list), 1) eq_(len(self.exclude_list), 1)
def test_add_duplicate(self): def test_add_duplicate(self):
@@ -188,6 +189,28 @@ class TestCaseListEmpty:
self.exclude_list.rename(regex_renamed_compilable, regex_compilable) self.exclude_list.rename(regex_renamed_compilable, regex_compilable)
eq_(self.exclude_list.is_marked(regex_compilable), True) eq_(self.exclude_list.is_marked(regex_compilable), True)
def test_rename_regex_file_to_path(self):
regex = r".*/one.*"
if ISWINDOWS:
regex = r".*\\one.*"
regex2 = r".*one.*"
self.exclude_list.add(regex)
self.exclude_list.mark(regex)
compiled_re = [x.pattern for x in self.exclude_list._excluded_compiled]
files_re = [x.pattern for x in self.exclude_list.compiled_files]
paths_re = [x.pattern for x in self.exclude_list.compiled_paths]
assert regex in compiled_re
assert regex not in files_re
assert regex in paths_re
self.exclude_list.rename(regex, regex2)
compiled_re = [x.pattern for x in self.exclude_list._excluded_compiled]
files_re = [x.pattern for x in self.exclude_list.compiled_files]
paths_re = [x.pattern for x in self.exclude_list.compiled_paths]
assert regex not in compiled_re
assert regex2 in compiled_re
assert regex2 in files_re
assert regex2 not in paths_re
def test_restore_default(self): def test_restore_default(self):
"""Only unmark previously added regexes and mark the pre-defined ones""" """Only unmark previously added regexes and mark the pre-defined ones"""
regex = r"one" regex = r"one"
@@ -213,21 +236,159 @@ class TestCaseListEmpty:
eq_(len(default_regexes), len(self.exclude_list.compiled)) eq_(len(default_regexes), len(self.exclude_list.compiled))
class TestCaseListEmptyUnion(TestCaseListEmpty):
"""Same but with union regex"""
def setup_method(self, method):
self.app = DupeGuru()
self.app.exclude_list = ExcludeList(union_regex=True)
self.exclude_list = self.app.exclude_list
def test_add_mark_and_remove_regex(self):
regex1 = r"one"
regex2 = r"two"
self.exclude_list.add(regex1)
assert regex1 in self.exclude_list
self.exclude_list.add(regex2)
self.exclude_list.mark(regex1)
self.exclude_list.mark(regex2)
eq_(len(self.exclude_list), 2)
eq_(len(self.exclude_list.compiled), 1)
compiled_files = [x for x in self.exclude_list.compiled_files]
eq_(len(compiled_files), 1) # Two patterns joined together into one
assert "|" in compiled_files[0].pattern
self.exclude_list.remove(regex2)
assert regex2 not in self.exclude_list
eq_(len(self.exclude_list), 1)
def test_rename_regex_file_to_path(self):
regex = r".*/one.*"
if ISWINDOWS:
regex = r".*\\one.*"
regex2 = r".*one.*"
self.exclude_list.add(regex)
self.exclude_list.mark(regex)
eq_(len([x for x in self.exclude_list]), 1)
compiled_re = [x.pattern for x in self.exclude_list.compiled]
files_re = [x.pattern for x in self.exclude_list.compiled_files]
paths_re = [x.pattern for x in self.exclude_list.compiled_paths]
assert regex in compiled_re
assert regex not in files_re
assert regex in paths_re
self.exclude_list.rename(regex, regex2)
eq_(len([x for x in self.exclude_list]), 1)
compiled_re = [x.pattern for x in self.exclude_list.compiled]
files_re = [x.pattern for x in self.exclude_list.compiled_files]
paths_re = [x.pattern for x in self.exclude_list.compiled_paths]
assert regex not in compiled_re
assert regex2 in compiled_re
assert regex2 in files_re
assert regex2 not in paths_re
def test_restore_default(self):
"""Only unmark previously added regexes and mark the pre-defined ones"""
regex = r"one"
self.exclude_list.add(regex)
self.exclude_list.mark(regex)
self.exclude_list.restore_defaults()
eq_(len(default_regexes), self.exclude_list.marked_count)
# added regex shouldn't be marked
eq_(self.exclude_list.is_marked(regex), False)
# added regex shouldn't be in compiled list either
compiled = [x for x in self.exclude_list.compiled]
assert regex not in compiled
# Need to escape both to get the same strings after compilation
compiled_escaped = set([x.encode("unicode-escape").decode() for x in compiled[0].pattern.split("|")])
default_escaped = set([x.encode("unicode-escape").decode() for x in default_regexes])
assert compiled_escaped == default_escaped
eq_(len(default_regexes), len(compiled[0].pattern.split("|")))
class TestCaseDictEmpty(TestCaseListEmpty): class TestCaseDictEmpty(TestCaseListEmpty):
"""Same, but with dictionary implementation""" """Same, but with dictionary implementation"""
def setup_method(self, method): def setup_method(self, method):
self.app = DupeGuru() self.app = DupeGuru()
self.app.exclude_list = ExcludeDict(union_regex=False) self.app.exclude_list = ExcludeDict(union_regex=False)
self.exclude_list = self.app.exclude_list self.exclude_list = self.app.exclude_list
class TestCaseDictEmptyUnion(TestCaseDictEmpty):
"""Same, but with union regex"""
def setup_method(self, method):
self.app = DupeGuru()
self.app.exclude_list = ExcludeDict(union_regex=True)
self.exclude_list = self.app.exclude_list
def test_add_mark_and_remove_regex(self):
regex1 = r"one"
regex2 = r"two"
self.exclude_list.add(regex1)
assert regex1 in self.exclude_list
self.exclude_list.add(regex2)
self.exclude_list.mark(regex1)
self.exclude_list.mark(regex2)
eq_(len(self.exclude_list), 2)
eq_(len(self.exclude_list.compiled), 1)
compiled_files = [x for x in self.exclude_list.compiled_files]
# two patterns joined into one
eq_(len(compiled_files), 1)
self.exclude_list.remove(regex2)
assert regex2 not in self.exclude_list
eq_(len(self.exclude_list), 1)
def test_rename_regex_file_to_path(self):
regex = r".*/one.*"
if ISWINDOWS:
regex = r".*\\one.*"
regex2 = r".*one.*"
self.exclude_list.add(regex)
self.exclude_list.mark(regex)
marked_re = [x for marked, x in self.exclude_list if marked]
eq_(len(marked_re), 1)
compiled_re = [x.pattern for x in self.exclude_list.compiled]
files_re = [x.pattern for x in self.exclude_list.compiled_files]
paths_re = [x.pattern for x in self.exclude_list.compiled_paths]
assert regex in compiled_re
assert regex not in files_re
assert regex in paths_re
self.exclude_list.rename(regex, regex2)
compiled_re = [x.pattern for x in self.exclude_list.compiled]
files_re = [x.pattern for x in self.exclude_list.compiled_files]
paths_re = [x.pattern for x in self.exclude_list.compiled_paths]
assert regex not in compiled_re
assert regex2 in compiled_re
assert regex2 in files_re
assert regex2 not in paths_re
def test_restore_default(self):
"""Only unmark previously added regexes and mark the pre-defined ones"""
regex = r"one"
self.exclude_list.add(regex)
self.exclude_list.mark(regex)
self.exclude_list.restore_defaults()
eq_(len(default_regexes), self.exclude_list.marked_count)
# added regex shouldn't be marked
eq_(self.exclude_list.is_marked(regex), False)
# added regex shouldn't be in compiled list either
compiled = [x for x in self.exclude_list.compiled]
assert regex not in compiled
# Need to escape both to get the same strings after compilation
compiled_escaped = set([x.encode("unicode-escape").decode() for x in compiled[0].pattern.split("|")])
default_escaped = set([x.encode("unicode-escape").decode() for x in default_regexes])
assert compiled_escaped == default_escaped
eq_(len(default_regexes), len(compiled[0].pattern.split("|")))
def split_union(pattern_object): def split_union(pattern_object):
"""Returns list of strings for each union pattern""" """Returns list of strings for each union pattern"""
return [x for x in pattern_object.pattern.split("|")] return [x for x in pattern_object.pattern.split("|")]
class TestCaseCompiledList(): class TestCaseCompiledList:
"""Test consistency between union or and separate versions.""" """Test consistency between union or and separate versions."""
def setup_method(self, method): def setup_method(self, method):
self.e_separate = ExcludeList(union_regex=False) self.e_separate = ExcludeList(union_regex=False)
self.e_separate.restore_defaults() self.e_separate.restore_defaults()
@@ -275,6 +436,7 @@ class TestCaseCompiledList():
class TestCaseCompiledDict(TestCaseCompiledList): class TestCaseCompiledDict(TestCaseCompiledList):
"""Test the dictionary version""" """Test the dictionary version"""
def setup_method(self, method): def setup_method(self, method):
self.e_separate = ExcludeDict(union_regex=False) self.e_separate = ExcludeDict(union_regex=False)
self.e_separate.restore_defaults() self.e_separate.restore_defaults()

View File

@@ -7,6 +7,7 @@
# http://www.gnu.org/licenses/gpl-3.0.html # http://www.gnu.org/licenses/gpl-3.0.html
import hashlib import hashlib
from os import urandom
from hscommon.path import Path from hscommon.path import Path
from hscommon.testutil import eq_ from hscommon.testutil import eq_
@@ -15,6 +16,36 @@ from core.tests.directories_test import create_fake_fs
from .. import fs from .. import fs
def create_fake_fs_with_random_data(rootpath):
rootpath = rootpath["fs"]
rootpath.mkdir()
rootpath["dir1"].mkdir()
rootpath["dir2"].mkdir()
rootpath["dir3"].mkdir()
fp = rootpath["file1.test"].open("wb")
data1 = urandom(200 * 1024) # 200KiB
data2 = urandom(1024 * 1024) # 1MiB
data3 = urandom(10 * 1024 * 1024) # 10MiB
fp.write(data1)
fp.close()
fp = rootpath["file2.test"].open("wb")
fp.write(data2)
fp.close()
fp = rootpath["file3.test"].open("wb")
fp.write(data3)
fp.close()
fp = rootpath["dir1"]["file1.test"].open("wb")
fp.write(data1)
fp.close()
fp = rootpath["dir2"]["file2.test"].open("wb")
fp.write(data2)
fp.close()
fp = rootpath["dir3"]["file3.test"].open("wb")
fp.write(data3)
fp.close()
return rootpath
def test_size_aggregates_subfiles(tmpdir): def test_size_aggregates_subfiles(tmpdir):
p = create_fake_fs(Path(str(tmpdir))) p = create_fake_fs(Path(str(tmpdir)))
b = fs.Folder(p) b = fs.Folder(p)
@@ -25,7 +56,7 @@ def test_md5_aggregate_subfiles_sorted(tmpdir):
# dir.allfiles can return child in any order. Thus, bundle.md5 must aggregate # dir.allfiles can return child in any order. Thus, bundle.md5 must aggregate
# all files' md5 it contains, but it must make sure that it does so in the # all files' md5 it contains, but it must make sure that it does so in the
# same order everytime. # same order everytime.
p = create_fake_fs(Path(str(tmpdir))) p = create_fake_fs_with_random_data(Path(str(tmpdir)))
b = fs.Folder(p) b = fs.Folder(p)
md51 = fs.File(p["dir1"]["file1.test"]).md5 md51 = fs.File(p["dir1"]["file1.test"]).md5
md52 = fs.File(p["dir2"]["file2.test"]).md5 md52 = fs.File(p["dir2"]["file2.test"]).md5
@@ -41,6 +72,36 @@ def test_md5_aggregate_subfiles_sorted(tmpdir):
eq_(b.md5, md5.digest()) eq_(b.md5, md5.digest())
def test_partial_md5_aggregate_subfile_sorted(tmpdir):
p = create_fake_fs_with_random_data(Path(str(tmpdir)))
b = fs.Folder(p)
md51 = fs.File(p["dir1"]["file1.test"]).md5partial
md52 = fs.File(p["dir2"]["file2.test"]).md5partial
md53 = fs.File(p["dir3"]["file3.test"]).md5partial
md54 = fs.File(p["file1.test"]).md5partial
md55 = fs.File(p["file2.test"]).md5partial
md56 = fs.File(p["file3.test"]).md5partial
# The expected md5 is the md5 of md5s for folders and the direct md5 for files
folder_md51 = hashlib.md5(md51).digest()
folder_md52 = hashlib.md5(md52).digest()
folder_md53 = hashlib.md5(md53).digest()
md5 = hashlib.md5(folder_md51 + folder_md52 + folder_md53 + md54 + md55 + md56)
eq_(b.md5partial, md5.digest())
md51 = fs.File(p["dir1"]["file1.test"]).md5samples
md52 = fs.File(p["dir2"]["file2.test"]).md5samples
md53 = fs.File(p["dir3"]["file3.test"]).md5samples
md54 = fs.File(p["file1.test"]).md5samples
md55 = fs.File(p["file2.test"]).md5samples
md56 = fs.File(p["file3.test"]).md5samples
# The expected md5 is the md5 of md5s for folders and the direct md5 for files
folder_md51 = hashlib.md5(md51).digest()
folder_md52 = hashlib.md5(md52).digest()
folder_md53 = hashlib.md5(md53).digest()
md5 = hashlib.md5(folder_md51 + folder_md52 + folder_md53 + md54 + md55 + md56)
eq_(b.md5samples, md5.digest())
def test_has_file_attrs(tmpdir): def test_has_file_attrs(tmpdir):
# a Folder must behave like a file, so it must have mtime attributes # a Folder must behave like a file, so it must have mtime attributes
b = fs.Folder(Path(str(tmpdir))) b = fs.Folder(Path(str(tmpdir)))

View File

@@ -73,9 +73,7 @@ def test_save_to_xml():
eq_(len(root), 2) eq_(len(root), 2)
eq_(len([c for c in root if c.tag == "file"]), 2) eq_(len([c for c in root if c.tag == "file"]), 2)
f1, f2 = root[:] f1, f2 = root[:]
subchildren = [c for c in f1 if c.tag == "file"] + [ subchildren = [c for c in f1 if c.tag == "file"] + [c for c in f2 if c.tag == "file"]
c for c in f2 if c.tag == "file"
]
eq_(len(subchildren), 3) eq_(len(subchildren), 3)
@@ -96,9 +94,7 @@ def test_SaveThenLoad():
def test_LoadXML_with_empty_file_tags(): def test_LoadXML_with_empty_file_tags():
f = io.BytesIO() f = io.BytesIO()
f.write( f.write(b'<?xml version="1.0" encoding="utf-8"?><ignore_list><file><file/></file></ignore_list>')
b'<?xml version="1.0" encoding="utf-8"?><ignore_list><file><file/></file></ignore_list>'
)
f.seek(0) f.seek(0)
il = IgnoreList() il = IgnoreList()
il.load_from_xml(f) il.load_from_xml(f)

View File

@@ -117,9 +117,7 @@ class TestCaseResultsWithSomeGroups:
assert d is g.ref assert d is g.ref
def test_sort_groups(self): def test_sort_groups(self):
self.results.make_ref( self.results.make_ref(self.objects[1]) # We want to make the 1024 sized object to go ref.
self.objects[1]
) # We want to make the 1024 sized object to go ref.
g1, g2 = self.groups g1, g2 = self.groups
self.results.sort_groups("size") self.results.sort_groups("size")
assert self.results.groups[0] is g2 assert self.results.groups[0] is g2
@@ -129,9 +127,7 @@ class TestCaseResultsWithSomeGroups:
assert self.results.groups[1] is g2 assert self.results.groups[1] is g2
def test_set_groups_when_sorted(self): def test_set_groups_when_sorted(self):
self.results.make_ref( self.results.make_ref(self.objects[1]) # We want to make the 1024 sized object to go ref.
self.objects[1]
) # We want to make the 1024 sized object to go ref.
self.results.sort_groups("size") self.results.sort_groups("size")
objects, matches, groups = GetTestGroups() objects, matches, groups = GetTestGroups()
g1, g2 = groups g1, g2 = groups
@@ -601,9 +597,7 @@ class TestCaseResultsXML:
matches = engine.getmatches(objects) # we should have 5 matches matches = engine.getmatches(objects) # we should have 5 matches
groups = engine.get_groups(matches) # We should have 2 groups groups = engine.get_groups(matches) # We should have 2 groups
for g in groups: for g in groups:
g.prioritize( g.prioritize(lambda x: objects.index(x)) # We want the dupes to be in the same order as the list is
lambda x: objects.index(x)
) # We want the dupes to be in the same order as the list is
app = DupeGuru() app = DupeGuru()
results = Results(app) results = Results(app)
results.groups = groups results.groups = groups
@@ -807,9 +801,7 @@ class TestCaseResultsFilter:
# Now the stats should display *2* markable dupes (instead of 1) # Now the stats should display *2* markable dupes (instead of 1)
expected = "0 / 2 (0.00 B / 2.00 B) duplicates marked. filter: foo" expected = "0 / 2 (0.00 B / 2.00 B) duplicates marked. filter: foo"
eq_(expected, self.results.stat_line) eq_(expected, self.results.stat_line)
self.results.apply_filter( self.results.apply_filter(None) # Now let's make sure our unfiltered results aren't fucked up
None
) # Now let's make sure our unfiltered results aren't fucked up
expected = "0 / 3 (0.00 B / 3.00 B) duplicates marked." expected = "0 / 3 (0.00 B / 3.00 B) duplicates marked."
eq_(expected, self.results.stat_line) eq_(expected, self.results.stat_line)

View File

@@ -56,6 +56,7 @@ def test_default_settings(fake_fileexists):
eq_(s.mix_file_kind, True) eq_(s.mix_file_kind, True)
eq_(s.word_weighting, False) eq_(s.word_weighting, False)
eq_(s.match_similar_words, False) eq_(s.match_similar_words, False)
eq_(s.big_file_size_threshold, 0)
def test_simple_with_default_settings(fake_fileexists): def test_simple_with_default_settings(fake_fileexists):
@@ -120,9 +121,9 @@ def test_content_scan(fake_fileexists):
s = Scanner() s = Scanner()
s.scan_type = ScanType.Contents s.scan_type = ScanType.Contents
f = [no("foo"), no("bar"), no("bleh")] f = [no("foo"), no("bar"), no("bleh")]
f[0].md5 = f[0].md5partial = "foobar" f[0].md5 = f[0].md5partial = f[0].md5samples = "foobar"
f[1].md5 = f[1].md5partial = "foobar" f[1].md5 = f[1].md5partial = f[1].md5samples = "foobar"
f[2].md5 = f[2].md5partial = "bleh" f[2].md5 = f[2].md5partial = f[1].md5samples = "bleh"
r = s.get_dupe_groups(f) r = s.get_dupe_groups(f)
eq_(len(r), 1) eq_(len(r), 1)
eq_(len(r[0]), 2) eq_(len(r[0]), 2)
@@ -141,13 +142,42 @@ def test_content_scan_compare_sizes_first(fake_fileexists):
eq_(len(s.get_dupe_groups(f)), 0) eq_(len(s.get_dupe_groups(f)), 0)
def test_big_file_partial_hashes(fake_fileexists):
s = Scanner()
s.scan_type = ScanType.Contents
smallsize = 1
bigsize = 100 * 1024 * 1024 # 100MB
s.big_file_size_threshold = bigsize
f = [no("bigfoo", bigsize), no("bigbar", bigsize), no("smallfoo", smallsize), no("smallbar", smallsize)]
f[0].md5 = f[0].md5partial = f[0].md5samples = "foobar"
f[1].md5 = f[1].md5partial = f[1].md5samples = "foobar"
f[2].md5 = f[2].md5partial = "bleh"
f[3].md5 = f[3].md5partial = "bleh"
r = s.get_dupe_groups(f)
eq_(len(r), 2)
# md5partial is still the same, but the file is actually different
f[1].md5 = f[1].md5samples = "difffoobar"
# here we compare the full md5s, as the user disabled the optimization
s.big_file_size_threshold = 0
r = s.get_dupe_groups(f)
eq_(len(r), 1)
# here we should compare the md5samples, and see they are different
s.big_file_size_threshold = bigsize
r = s.get_dupe_groups(f)
eq_(len(r), 1)
def test_min_match_perc_doesnt_matter_for_content_scan(fake_fileexists): def test_min_match_perc_doesnt_matter_for_content_scan(fake_fileexists):
s = Scanner() s = Scanner()
s.scan_type = ScanType.Contents s.scan_type = ScanType.Contents
f = [no("foo"), no("bar"), no("bleh")] f = [no("foo"), no("bar"), no("bleh")]
f[0].md5 = f[0].md5partial = "foobar" f[0].md5 = f[0].md5partial = f[0].md5samples = "foobar"
f[1].md5 = f[1].md5partial = "foobar" f[1].md5 = f[1].md5partial = f[1].md5samples = "foobar"
f[2].md5 = f[2].md5partial = "bleh" f[2].md5 = f[2].md5partial = f[2].md5samples = "bleh"
s.min_match_percentage = 101 s.min_match_percentage = 101
r = s.get_dupe_groups(f) r = s.get_dupe_groups(f)
eq_(len(r), 1) eq_(len(r), 1)
@@ -162,13 +192,10 @@ def test_content_scan_doesnt_put_md5_in_words_at_the_end(fake_fileexists):
s = Scanner() s = Scanner()
s.scan_type = ScanType.Contents s.scan_type = ScanType.Contents
f = [no("foo"), no("bar")] f = [no("foo"), no("bar")]
f[0].md5 = f[ f[0].md5 = f[0].md5partial = f[0].md5samples = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
0 f[1].md5 = f[1].md5partial = f[1].md5samples = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
].md5partial = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
f[1].md5 = f[
1
].md5partial = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
r = s.get_dupe_groups(f) r = s.get_dupe_groups(f)
# FIXME looks like we are missing something here?
r[0] r[0]
@@ -514,21 +541,21 @@ def test_folder_scan_exclude_subfolder_matches(fake_fileexists):
s = Scanner() s = Scanner()
s.scan_type = ScanType.Folders s.scan_type = ScanType.Folders
topf1 = no("top folder 1", size=42) topf1 = no("top folder 1", size=42)
topf1.md5 = topf1.md5partial = b"some_md5_1" topf1.md5 = topf1.md5partial = topf1.md5samples = b"some_md5_1"
topf1.path = Path("/topf1") topf1.path = Path("/topf1")
topf2 = no("top folder 2", size=42) topf2 = no("top folder 2", size=42)
topf2.md5 = topf2.md5partial = b"some_md5_1" topf2.md5 = topf2.md5partial = topf2.md5samples = b"some_md5_1"
topf2.path = Path("/topf2") topf2.path = Path("/topf2")
subf1 = no("sub folder 1", size=41) subf1 = no("sub folder 1", size=41)
subf1.md5 = subf1.md5partial = b"some_md5_2" subf1.md5 = subf1.md5partial = subf1.md5samples = b"some_md5_2"
subf1.path = Path("/topf1/sub") subf1.path = Path("/topf1/sub")
subf2 = no("sub folder 2", size=41) subf2 = no("sub folder 2", size=41)
subf2.md5 = subf2.md5partial = b"some_md5_2" subf2.md5 = subf2.md5partial = subf2.md5samples = b"some_md5_2"
subf2.path = Path("/topf2/sub") subf2.path = Path("/topf2/sub")
eq_(len(s.get_dupe_groups([topf1, topf2, subf1, subf2])), 1) # only top folders eq_(len(s.get_dupe_groups([topf1, topf2, subf1, subf2])), 1) # only top folders
# however, if another folder matches a subfolder, keep in in the matches # however, if another folder matches a subfolder, keep in in the matches
otherf = no("other folder", size=41) otherf = no("other folder", size=41)
otherf.md5 = otherf.md5partial = b"some_md5_2" otherf.md5 = otherf.md5partial = otherf.md5samples = b"some_md5_2"
otherf.path = Path("/otherfolder") otherf.path = Path("/otherfolder")
eq_(len(s.get_dupe_groups([topf1, topf2, subf1, subf2, otherf])), 2) eq_(len(s.get_dupe_groups([topf1, topf2, subf1, subf2, otherf])), 2)
@@ -551,9 +578,9 @@ def test_dont_count_ref_files_as_discarded(fake_fileexists):
o1 = no("foo", path="p1") o1 = no("foo", path="p1")
o2 = no("foo", path="p2") o2 = no("foo", path="p2")
o3 = no("foo", path="p3") o3 = no("foo", path="p3")
o1.md5 = o1.md5partial = "foobar" o1.md5 = o1.md5partial = o1.md5samples = "foobar"
o2.md5 = o2.md5partial = "foobar" o2.md5 = o2.md5partial = o2.md5samples = "foobar"
o3.md5 = o3.md5partial = "foobar" o3.md5 = o3.md5partial = o3.md5samples = "foobar"
o1.is_ref = True o1.is_ref = True
o2.is_ref = True o2.is_ref = True
eq_(len(s.get_dupe_groups([o1, o2, o3])), 1) eq_(len(s.get_dupe_groups([o1, o2, o3])), 1)

View File

@@ -5,6 +5,8 @@
# http://www.gnu.org/licenses/gpl-3.0.html # http://www.gnu.org/licenses/gpl-3.0.html
import time import time
import sys
import os
from hscommon.util import format_time_decimal from hscommon.util import format_time_decimal
@@ -58,3 +60,7 @@ def fix_surrogate_encoding(s, encoding="utf-8"):
return s.encode(encoding, "replace").decode(encoding) return s.encode(encoding, "replace").decode(encoding)
else: else:
return s return s
def executable_folder():
return os.path.dirname(os.path.abspath(sys.argv[0]))

View File

@@ -1,3 +1,12 @@
=== 4.1.1 (2021-03-21)
* Add Japanese
* Update internationalization and translations to be up to date with current UI.
* Minor translation and UI language updates
* Fix language selection issues on Windows (#760)
* Add some additional notes about builds on Linux based systems
* Add import from transifex export to build.py
=== 4.1.0 (2020-12-29) === 4.1.0 (2020-12-29)
* Use tabs instead of separate windows (#688) * Use tabs instead of separate windows (#688)

View File

@@ -30,8 +30,7 @@ from .util import ensure_folder, delete_files_with_pattern
def print_and_do(cmd): def print_and_do(cmd):
"""Prints ``cmd`` and executes it in the shell. """Prints ``cmd`` and executes it in the shell."""
"""
print(cmd) print(cmd)
p = Popen(cmd, shell=True) p = Popen(cmd, shell=True)
return p.wait() return p.wait()
@@ -91,16 +90,14 @@ def copy_all(pattern, dst):
def ensure_empty_folder(path): def ensure_empty_folder(path):
"""Make sure that the path exists and that it's an empty folder. """Make sure that the path exists and that it's an empty folder."""
"""
if op.exists(path): if op.exists(path):
shutil.rmtree(path) shutil.rmtree(path)
os.mkdir(path) os.mkdir(path)
def filereplace(filename, outfilename=None, **kwargs): def filereplace(filename, outfilename=None, **kwargs):
"""Reads `filename`, replaces all {variables} in kwargs, and writes the result to `outfilename`. """Reads `filename`, replaces all {variables} in kwargs, and writes the result to `outfilename`."""
"""
if outfilename is None: if outfilename is None:
outfilename = filename outfilename = filename
fp = open(filename, "rt", encoding="utf-8") fp = open(filename, "rt", encoding="utf-8")
@@ -152,9 +149,7 @@ def package_cocoa_app_in_dmg(app_path, destfolder, args):
# a valid signature. # a valid signature.
if args.sign_identity: if args.sign_identity:
sign_identity = "Developer ID Application: {}".format(args.sign_identity) sign_identity = "Developer ID Application: {}".format(args.sign_identity)
result = print_and_do( result = print_and_do('codesign --force --deep --sign "{}" "{}"'.format(sign_identity, app_path))
'codesign --force --deep --sign "{}" "{}"'.format(sign_identity, app_path)
)
if result != 0: if result != 0:
print("ERROR: Signing failed. Aborting packaging.") print("ERROR: Signing failed. Aborting packaging.")
return return
@@ -182,10 +177,7 @@ def build_dmg(app_path, destfolder):
) )
print("Building %s" % dmgname) print("Building %s" % dmgname)
# UDBZ = bzip compression. UDZO (zip compression) was used before, but it compresses much less. # UDBZ = bzip compression. UDZO (zip compression) was used before, but it compresses much less.
print_and_do( print_and_do('hdiutil create "%s" -format UDBZ -nocrossdev -srcdir "%s"' % (op.join(destfolder, dmgname), dmgpath))
'hdiutil create "%s" -format UDBZ -nocrossdev -srcdir "%s"'
% (op.join(destfolder, dmgname), dmgpath)
)
print("Build Complete") print("Build Complete")
@@ -207,8 +199,7 @@ sysconfig.get_config_h_filename = lambda: op.join(op.dirname(__file__), 'pyconfi
def add_to_pythonpath(path): def add_to_pythonpath(path):
"""Adds ``path`` to both ``PYTHONPATH`` env and ``sys.path``. """Adds ``path`` to both ``PYTHONPATH`` env and ``sys.path``."""
"""
abspath = op.abspath(path) abspath = op.abspath(path)
pythonpath = os.environ.get("PYTHONPATH", "") pythonpath = os.environ.get("PYTHONPATH", "")
pathsep = ";" if ISWINDOWS else ":" pathsep = ";" if ISWINDOWS else ":"
@@ -231,9 +222,7 @@ def copy_packages(packages_names, dest, create_links=False, extra_ignores=None):
create_links = False create_links = False
if not extra_ignores: if not extra_ignores:
extra_ignores = [] extra_ignores = []
ignore = shutil.ignore_patterns( ignore = shutil.ignore_patterns(".hg*", "tests", "testdata", "modules", "docs", "locale", *extra_ignores)
".hg*", "tests", "testdata", "modules", "docs", "locale", *extra_ignores
)
for package_name in packages_names: for package_name in packages_names:
if op.exists(package_name): if op.exists(package_name):
source_path = package_name source_path = package_name
@@ -444,11 +433,10 @@ class OSXFrameworkStructure:
def create_symlinks(self): def create_symlinks(self):
# Only call this after create() and copy_executable() # Only call this after create() and copy_executable()
rel = lambda path: op.relpath(path, self.dest)
os.symlink("A", op.join(self.dest, "Versions", "Current")) os.symlink("A", op.join(self.dest, "Versions", "Current"))
os.symlink(rel(self.executablepath), op.join(self.dest, self.executablename)) os.symlink(op.relpath(self.executablepath, self.dest), op.join(self.dest, self.executablename))
os.symlink(rel(self.headers), op.join(self.dest, "Headers")) os.symlink(op.relpath(self.headers, self.dest), op.join(self.dest, "Headers"))
os.symlink(rel(self.resources), op.join(self.dest, "Resources")) os.symlink(op.relpath(self.resources, self.dest), op.join(self.dest, "Resources"))
def copy_executable(self, executable): def copy_executable(self, executable):
copy(executable, self.executablepath) copy(executable, self.executablepath)
@@ -481,9 +469,7 @@ def copy_embeddable_python_dylib(dst):
def collect_stdlib_dependencies(script, dest_folder, extra_deps=None): def collect_stdlib_dependencies(script, dest_folder, extra_deps=None):
sysprefix = sys.prefix # could be a virtualenv sysprefix = sys.prefix # could be a virtualenv
basesysprefix = sys.base_prefix # seems to be path to non-virtual sys basesysprefix = sys.base_prefix # seems to be path to non-virtual sys
real_lib_prefix = sysconfig.get_config_var( real_lib_prefix = sysconfig.get_config_var("LIBDEST") # leaving this in case it is neede
"LIBDEST"
) # leaving this in case it is neede
def is_stdlib_path(path): def is_stdlib_path(path):
# A module path is only a stdlib path if it's in either sys.prefix or # A module path is only a stdlib path if it's in either sys.prefix or
@@ -493,11 +479,7 @@ def collect_stdlib_dependencies(script, dest_folder, extra_deps=None):
return False return False
if "site-package" in path: if "site-package" in path:
return False return False
if not ( if not (path.startswith(sysprefix) or path.startswith(basesysprefix) or path.startswith(real_lib_prefix)):
path.startswith(sysprefix)
or path.startswith(basesysprefix)
or path.startswith(real_lib_prefix)
):
return False return False
return True return True
@@ -511,9 +493,7 @@ def collect_stdlib_dependencies(script, dest_folder, extra_deps=None):
relpath = op.relpath(p, real_lib_prefix) relpath = op.relpath(p, real_lib_prefix)
elif p.startswith(sysprefix): elif p.startswith(sysprefix):
relpath = op.relpath(p, sysprefix) relpath = op.relpath(p, sysprefix)
assert relpath.startswith( assert relpath.startswith("lib/python3.") # we want to get rid of that lib/python3.x part
"lib/python3."
) # we want to get rid of that lib/python3.x part
relpath = relpath[len("lib/python3.X/") :] relpath = relpath[len("lib/python3.X/") :]
elif p.startswith(basesysprefix): elif p.startswith(basesysprefix):
relpath = op.relpath(p, basesysprefix) relpath = op.relpath(p, basesysprefix)
@@ -521,9 +501,7 @@ def collect_stdlib_dependencies(script, dest_folder, extra_deps=None):
relpath = relpath[len("lib/python3.X/") :] relpath = relpath[len("lib/python3.X/") :]
else: else:
raise AssertionError() raise AssertionError()
if relpath.startswith( if relpath.startswith("lib-dynload"): # We copy .so files in lib-dynload directly in our dest
"lib-dynload"
): # We copy .so files in lib-dynload directly in our dest
relpath = relpath[len("lib-dynload/") :] relpath = relpath[len("lib-dynload/") :]
if relpath.startswith("encodings") or relpath.startswith("distutils"): if relpath.startswith("encodings") or relpath.startswith("distutils"):
# We force their inclusion later. # We force their inclusion later.
@@ -562,9 +540,7 @@ def fix_qt_resource_file(path):
fp.write(b"\n".join(lines)) fp.write(b"\n".join(lines))
def build_cocoa_ext( def build_cocoa_ext(extname, dest, source_files, extra_frameworks=(), extra_includes=()):
extname, dest, source_files, extra_frameworks=(), extra_includes=()
):
extra_link_args = ["-framework", "CoreFoundation", "-framework", "Foundation"] extra_link_args = ["-framework", "CoreFoundation", "-framework", "Foundation"]
for extra in extra_frameworks: for extra in extra_frameworks:
extra_link_args += ["-framework", extra] extra_link_args += ["-framework", extra]

View File

@@ -11,9 +11,7 @@ from setuptools import setup, Extension
def get_parser(): def get_parser():
parser = argparse.ArgumentParser(description="Build an arbitrary Python extension.") parser = argparse.ArgumentParser(description="Build an arbitrary Python extension.")
parser.add_argument( parser.add_argument("source_files", nargs="+", help="List of source files to compile")
"source_files", nargs="+", help="List of source files to compile"
)
parser.add_argument("name", nargs=1, help="Name of the resulting extension") parser.add_argument("name", nargs=1, help="Name of the resulting extension")
return parser return parser
@@ -23,7 +21,8 @@ def main():
print("Building {}...".format(args.name[0])) print("Building {}...".format(args.name[0]))
ext = Extension(args.name[0], args.source_files) ext = Extension(args.name[0], args.source_files)
setup( setup(
script_args=["build_ext", "--inplace"], ext_modules=[ext], script_args=["build_ext", "--inplace"],
ext_modules=[ext],
) )

View File

@@ -48,15 +48,13 @@ def get_unconflicted_name(name):
def is_conflicted(name): def is_conflicted(name):
"""Returns whether ``name`` is prepended with a bracketed number. """Returns whether ``name`` is prepended with a bracketed number."""
"""
return re_conflict.match(name) is not None return re_conflict.match(name) is not None
@pathify @pathify
def _smart_move_or_copy(operation, source_path: Path, dest_path: Path): def _smart_move_or_copy(operation, source_path: Path, dest_path: Path):
"""Use move() or copy() to move and copy file with the conflict management. """Use move() or copy() to move and copy file with the conflict management."""
"""
if dest_path.isdir() and not source_path.isdir(): if dest_path.isdir() and not source_path.isdir():
dest_path = dest_path[source_path.name] dest_path = dest_path[source_path.name]
if dest_path.exists(): if dest_path.exists():
@@ -68,14 +66,12 @@ def _smart_move_or_copy(operation, source_path: Path, dest_path: Path):
def smart_move(source_path, dest_path): def smart_move(source_path, dest_path):
"""Same as :func:`smart_copy`, but it moves files instead. """Same as :func:`smart_copy`, but it moves files instead."""
"""
_smart_move_or_copy(shutil.move, source_path, dest_path) _smart_move_or_copy(shutil.move, source_path, dest_path)
def smart_copy(source_path, dest_path): def smart_copy(source_path, dest_path):
"""Copies ``source_path`` to ``dest_path``, recursively and with conflict resolution. """Copies ``source_path`` to ``dest_path``, recursively and with conflict resolution."""
"""
try: try:
_smart_move_or_copy(shutil.copy, source_path, dest_path) _smart_move_or_copy(shutil.copy, source_path, dest_path)
except IOError as e: except IOError as e:

View File

@@ -16,24 +16,21 @@ class SpecialFolder:
def open_url(url): def open_url(url):
"""Open ``url`` with the default browser. """Open ``url`` with the default browser."""
"""
_open_url(url) _open_url(url)
def open_path(path): def open_path(path):
"""Open ``path`` with its associated application. """Open ``path`` with its associated application."""
"""
_open_path(str(path)) _open_path(str(path))
def reveal_path(path): def reveal_path(path):
"""Open the folder containing ``path`` with the default file browser. """Open the folder containing ``path`` with the default file browser."""
"""
_reveal_path(str(path)) _reveal_path(str(path))
def special_folder_path(special_folder, appname=None): def special_folder_path(special_folder, appname=None, portable=False):
"""Returns the path of ``special_folder``. """Returns the path of ``special_folder``.
``special_folder`` is a SpecialFolder.* const. The result is the special folder for the current ``special_folder`` is a SpecialFolder.* const. The result is the special folder for the current
@@ -41,7 +38,7 @@ def special_folder_path(special_folder, appname=None):
You can override the application name with ``appname``. This argument is ingored under Qt. You can override the application name with ``appname``. This argument is ingored under Qt.
""" """
return _special_folder_path(special_folder, appname) return _special_folder_path(special_folder, appname, portable=portable)
try: try:
@@ -57,7 +54,7 @@ try:
_open_path = proxy.openPath_ _open_path = proxy.openPath_
_reveal_path = proxy.revealPath_ _reveal_path = proxy.revealPath_
def _special_folder_path(special_folder, appname=None): def _special_folder_path(special_folder, appname=None, portable=False):
if special_folder == SpecialFolder.Cache: if special_folder == SpecialFolder.Cache:
base = proxy.getCachePath() base = proxy.getCachePath()
else: else:
@@ -71,6 +68,9 @@ except ImportError:
try: try:
from PyQt5.QtCore import QUrl, QStandardPaths from PyQt5.QtCore import QUrl, QStandardPaths
from PyQt5.QtGui import QDesktopServices from PyQt5.QtGui import QDesktopServices
from qtlib.util import getAppData
from core.util import executable_folder
from hscommon.plat import ISWINDOWS
def _open_url(url): def _open_url(url):
QDesktopServices.openUrl(QUrl(url)) QDesktopServices.openUrl(QUrl(url))
@@ -82,12 +82,15 @@ except ImportError:
def _reveal_path(path): def _reveal_path(path):
_open_path(op.dirname(str(path))) _open_path(op.dirname(str(path)))
def _special_folder_path(special_folder, appname=None): def _special_folder_path(special_folder, appname=None, portable=False):
if special_folder == SpecialFolder.Cache: if special_folder == SpecialFolder.Cache:
qtfolder = QStandardPaths.CacheLocation if ISWINDOWS and portable:
folder = op.join(executable_folder(), "cache")
else: else:
qtfolder = QStandardPaths.DataLocation folder = QStandardPaths.standardLocations(QStandardPaths.CacheLocation)[0]
return QStandardPaths.standardLocations(qtfolder)[0] else:
folder = getAppData(portable)
return folder
except ImportError: except ImportError:
# We're either running tests, and these functions don't matter much or we're in a really # We're either running tests, and these functions don't matter much or we're in a really
@@ -100,5 +103,5 @@ except ImportError:
def _reveal_path(path): def _reveal_path(path):
pass pass
def _special_folder_path(special_folder, appname=None): def _special_folder_path(special_folder, appname=None, portable=False):
return "/tmp" return "/tmp"

View File

@@ -149,8 +149,7 @@ class Rect:
return l1, l2, l3, l4 return l1, l2, l3, l4
def scaled_rect(self, dx, dy): def scaled_rect(self, dx, dy):
"""Returns a rect that has the same borders at self, but grown/shrunk by dx/dy on each side. """Returns a rect that has the same borders at self, but grown/shrunk by dx/dy on each side."""
"""
x, y, w, h = self x, y, w, h = self
x -= dx x -= dx
y -= dy y -= dy
@@ -159,8 +158,7 @@ class Rect:
return Rect(x, y, w, h) return Rect(x, y, w, h)
def united(self, other): def united(self, other):
"""Returns the bounding rectangle of this rectangle and `other`. """Returns the bounding rectangle of this rectangle and `other`."""
"""
# ul=upper left lr=lower right # ul=upper left lr=lower right
ulcorner1, lrcorner1 = self.corners() ulcorner1, lrcorner1 = self.corners()
ulcorner2, lrcorner2 = other.corners() ulcorner2, lrcorner2 = other.corners()

View File

@@ -80,8 +80,7 @@ class PrefAccessInterface:
""" """
def set_default(self, key, value): def set_default(self, key, value):
"""Set the value ``value`` for ``key`` in the currently running app's preference store. """Set the value ``value`` for ``key`` in the currently running app's preference store."""
"""
class Columns(GUIObject): class Columns(GUIObject):
@@ -140,33 +139,27 @@ class Columns(GUIObject):
# --- Public # --- Public
def column_by_index(self, index): def column_by_index(self, index):
"""Return the :class:`Column` having the :attr:`~Column.logical_index` ``index``. """Return the :class:`Column` having the :attr:`~Column.logical_index` ``index``."""
"""
return self.column_list[index] return self.column_list[index]
def column_by_name(self, name): def column_by_name(self, name):
"""Return the :class:`Column` having the :attr:`~Column.name` ``name``. """Return the :class:`Column` having the :attr:`~Column.name` ``name``."""
"""
return self.coldata[name] return self.coldata[name]
def columns_count(self): def columns_count(self):
"""Returns the number of columns in our set. """Returns the number of columns in our set."""
"""
return len(self.column_list) return len(self.column_list)
def column_display(self, colname): def column_display(self, colname):
"""Returns display name for column named ``colname``, or ``''`` if there's none. """Returns display name for column named ``colname``, or ``''`` if there's none."""
"""
return self._get_colname_attr(colname, "display", "") return self._get_colname_attr(colname, "display", "")
def column_is_visible(self, colname): def column_is_visible(self, colname):
"""Returns visibility for column named ``colname``, or ``True`` if there's none. """Returns visibility for column named ``colname``, or ``True`` if there's none."""
"""
return self._get_colname_attr(colname, "visible", True) return self._get_colname_attr(colname, "visible", True)
def column_width(self, colname): def column_width(self, colname):
"""Returns width for column named ``colname``, or ``0`` if there's none. """Returns width for column named ``colname``, or ``0`` if there's none."""
"""
return self._get_colname_attr(colname, "width", 0) return self._get_colname_attr(colname, "width", 0)
def columns_to_right(self, colname): def columns_to_right(self, colname):
@@ -177,11 +170,7 @@ class Columns(GUIObject):
""" """
column = self.coldata[colname] column = self.coldata[colname]
index = column.ordered_index index = column.ordered_index
return [ return [col.name for col in self.column_list if (col.visible and col.ordered_index > index)]
col.name
for col in self.column_list
if (col.visible and col.ordered_index > index)
]
def menu_items(self): def menu_items(self):
"""Returns a list of items convenient for quick visibility menu generation. """Returns a list of items convenient for quick visibility menu generation.
@@ -207,8 +196,7 @@ class Columns(GUIObject):
self.set_column_order(colnames) self.set_column_order(colnames)
def reset_to_defaults(self): def reset_to_defaults(self):
"""Reset all columns' width and visibility to their default values. """Reset all columns' width and visibility to their default values."""
"""
self.set_column_order([col.name for col in self.column_list]) self.set_column_order([col.name for col in self.column_list])
for col in self._optional_columns(): for col in self._optional_columns():
col.visible = col.default_visible col.visible = col.default_visible
@@ -216,13 +204,11 @@ class Columns(GUIObject):
self.view.restore_columns() self.view.restore_columns()
def resize_column(self, colname, newwidth): def resize_column(self, colname, newwidth):
"""Set column ``colname``'s width to ``newwidth``. """Set column ``colname``'s width to ``newwidth``."""
"""
self._set_colname_attr(colname, "width", newwidth) self._set_colname_attr(colname, "width", newwidth)
def restore_columns(self): def restore_columns(self):
"""Restore's column persistent attributes from the last :meth:`save_columns`. """Restore's column persistent attributes from the last :meth:`save_columns`."""
"""
if not (self.prefaccess and self.savename and self.coldata): if not (self.prefaccess and self.savename and self.coldata):
if (not self.savename) and (self.coldata): if (not self.savename) and (self.coldata):
# This is a table that will not have its coldata saved/restored. we should # This is a table that will not have its coldata saved/restored. we should
@@ -241,8 +227,7 @@ class Columns(GUIObject):
self.view.restore_columns() self.view.restore_columns()
def save_columns(self): def save_columns(self):
"""Save column attributes in persistent storage for restoration in :meth:`restore_columns`. """Save column attributes in persistent storage for restoration in :meth:`restore_columns`."""
"""
if not (self.prefaccess and self.savename and self.coldata): if not (self.prefaccess and self.savename and self.coldata):
return return
for col in self.column_list: for col in self.column_list:
@@ -263,15 +248,13 @@ class Columns(GUIObject):
col.ordered_index = i col.ordered_index = i
def set_column_visible(self, colname, visible): def set_column_visible(self, colname, visible):
"""Set the visibility of column ``colname``. """Set the visibility of column ``colname``."""
"""
self.table.save_edits() # the table on the GUI side will stop editing when the columns change self.table.save_edits() # the table on the GUI side will stop editing when the columns change
self._set_colname_attr(colname, "visible", visible) self._set_colname_attr(colname, "visible", visible)
self.view.set_column_visible(colname, visible) self.view.set_column_visible(colname, visible)
def set_default_width(self, colname, width): def set_default_width(self, colname, width):
"""Set the default width or column ``colname``. """Set the default width or column ``colname``."""
"""
self._set_colname_attr(colname, "default_width", width) self._set_colname_attr(colname, "default_width", width)
def toggle_menu_item(self, index): def toggle_menu_item(self, index):
@@ -289,14 +272,10 @@ class Columns(GUIObject):
# --- Properties # --- Properties
@property @property
def ordered_columns(self): def ordered_columns(self):
"""List of :class:`Column` in visible order. """List of :class:`Column` in visible order."""
""" return [col for col in sorted(self.column_list, key=lambda col: col.ordered_index)]
return [
col for col in sorted(self.column_list, key=lambda col: col.ordered_index)
]
@property @property
def colnames(self): def colnames(self):
"""List of column names in visible order. """List of column names in visible order."""
"""
return [col.name for col in self.ordered_columns] return [col.name for col in self.ordered_columns]

View File

@@ -21,12 +21,10 @@ class ProgressWindowView:
""" """
def show(self): def show(self):
"""Show the dialog. """Show the dialog."""
"""
def close(self): def close(self):
"""Close the dialog. """Close the dialog."""
"""
def set_progress(self, progress): def set_progress(self, progress):
"""Set the progress of the progress bar to ``progress``. """Set the progress of the progress bar to ``progress``.
@@ -76,8 +74,7 @@ class ProgressWindow(GUIObject, ThreadedJobPerformer):
self.jobid = None self.jobid = None
def cancel(self): def cancel(self):
"""Call for a user-initiated job cancellation. """Call for a user-initiated job cancellation."""
"""
# The UI is sometimes a bit buggy and calls cancel() on self.view.close(). We just want to # The UI is sometimes a bit buggy and calls cancel() on self.view.close(). We just want to
# make sure that this doesn't lead us to think that the user acually cancelled the task, so # make sure that this doesn't lead us to think that the user acually cancelled the task, so
# we verify that the job is still running. # we verify that the job is still running.

View File

@@ -27,9 +27,7 @@ class Selectable(Sequence):
self._selected_indexes = [] self._selected_indexes = []
if not self._selected_indexes: if not self._selected_indexes:
return return
self._selected_indexes = [ self._selected_indexes = [index for index in self._selected_indexes if index < len(self)]
index for index in self._selected_indexes if index < len(self)
]
if not self._selected_indexes: if not self._selected_indexes:
self._selected_indexes = [len(self) - 1] self._selected_indexes = [len(self) - 1]

View File

@@ -97,8 +97,7 @@ class Table(MutableSequence, Selectable):
self._rows.pop(0) self._rows.pop(0)
if self._footer is not None: if self._footer is not None:
self._rows.pop() self._rows.pop()
key = lambda row: row.sort_key_for_column(column_name) self._rows.sort(key=lambda row: row.sort_key_for_column(column_name), reverse=desc)
self._rows.sort(key=key, reverse=desc)
if self._header is not None: if self._header is not None:
self._rows.insert(0, self._header) self._rows.insert(0, self._header)
if self._footer is not None: if self._footer is not None:
@@ -277,8 +276,7 @@ class GUITable(Table, GUIObject):
raise NotImplementedError() raise NotImplementedError()
def _do_delete(self): def _do_delete(self):
"""(Virtual) Delete the selected rows. """(Virtual) Delete the selected rows."""
"""
pass pass
def _fill(self): def _fill(self):

View File

@@ -71,8 +71,7 @@ class TextField(GUIObject):
# --- Public # --- Public
def refresh(self): def refresh(self):
"""Triggers a view :meth:`~TextFieldView.refresh`. """Triggers a view :meth:`~TextFieldView.refresh`."""
"""
self.view.refresh() self.view.refresh()
@property @property

View File

@@ -55,8 +55,7 @@ class Node(MutableSequence):
# --- Public # --- Public
def clear(self): def clear(self):
"""Clears the node of all its children. """Clears the node of all its children."""
"""
del self[:] del self[:]
def find(self, predicate, include_self=True): def find(self, predicate, include_self=True):
@@ -103,14 +102,12 @@ class Node(MutableSequence):
@property @property
def children_count(self): def children_count(self):
"""Same as ``len(self)``. """Same as ``len(self)``."""
"""
return len(self) return len(self)
@property @property
def name(self): def name(self):
"""Name for the node, supplied on init. """Name for the node, supplied on init."""
"""
return self._name return self._name
@property @property

View File

@@ -56,8 +56,7 @@ class Job:
# ---Private # ---Private
def _subjob_callback(self, progress, desc=""): def _subjob_callback(self, progress, desc=""):
"""This is the callback passed to children jobs. """This is the callback passed to children jobs."""
"""
self.set_progress(progress, desc) self.set_progress(progress, desc)
return True # if JobCancelled has to be raised, it will be at the highest level return True # if JobCancelled has to be raised, it will be at the highest level

View File

@@ -45,7 +45,10 @@ def generate_pot(folders, outpath, keywords, merge=False):
pygettext.main(pyfiles, outpath=genpath, keywords=keywords) pygettext.main(pyfiles, outpath=genpath, keywords=keywords)
if merge: if merge:
merge_po_and_preserve(genpath, outpath) merge_po_and_preserve(genpath, outpath)
try:
os.remove(genpath) os.remove(genpath)
except Exception:
print("Exception while removing temporary folder %s\n", genpath)
def compile_all_po(base_folder): def compile_all_po(base_folder):
@@ -151,9 +154,7 @@ def strings2pot(target, dest):
def allstrings2pot(lprojpath, dest, excludes=None): def allstrings2pot(lprojpath, dest, excludes=None):
allstrings = files_with_ext(lprojpath, ".strings") allstrings = files_with_ext(lprojpath, ".strings")
if excludes: if excludes:
allstrings = [ allstrings = [p for p in allstrings if op.splitext(op.basename(p))[0] not in excludes]
p for p in allstrings if op.splitext(op.basename(p))[0] not in excludes
]
for strings_path in allstrings: for strings_path in allstrings:
strings2pot(strings_path, dest) strings2pot(strings_path, dest)
@@ -192,11 +193,7 @@ def generate_cocoa_strings_from_code(code_folder, dest_folder):
# genstrings produces utf-16 files with comments. After having generated the files, we convert # genstrings produces utf-16 files with comments. After having generated the files, we convert
# them to utf-8 and remove the comments. # them to utf-8 and remove the comments.
ensure_empty_folder(dest_folder) ensure_empty_folder(dest_folder)
print_and_do( print_and_do('genstrings -o "{}" `find "{}" -name *.m | xargs`'.format(dest_folder, code_folder))
'genstrings -o "{}" `find "{}" -name *.m | xargs`'.format(
dest_folder, code_folder
)
)
for stringsfile in os.listdir(dest_folder): for stringsfile in os.listdir(dest_folder):
stringspath = op.join(dest_folder, stringsfile) stringspath = op.join(dest_folder, stringsfile)
with open(stringspath, "rt", encoding="utf-16") as fp: with open(stringspath, "rt", encoding="utf-16") as fp:
@@ -211,9 +208,7 @@ def generate_cocoa_strings_from_code(code_folder, dest_folder):
def generate_cocoa_strings_from_xib(xib_folder): def generate_cocoa_strings_from_xib(xib_folder):
xibs = [ xibs = [op.join(xib_folder, fn) for fn in os.listdir(xib_folder) if fn.endswith(".xib")]
op.join(xib_folder, fn) for fn in os.listdir(xib_folder) if fn.endswith(".xib")
]
for xib in xibs: for xib in xibs:
dest = xib.replace(".xib", ".strings") dest = xib.replace(".xib", ".strings")
print_and_do("ibtool {} --generate-strings-file {}".format(xib, dest)) print_and_do("ibtool {} --generate-strings-file {}".format(xib, dest))
@@ -231,10 +226,6 @@ def localize_stringsfile(stringsfile, dest_root_folder):
def localize_all_stringsfiles(src_folder, dest_root_folder): def localize_all_stringsfiles(src_folder, dest_root_folder):
stringsfiles = [ stringsfiles = [op.join(src_folder, fn) for fn in os.listdir(src_folder) if fn.endswith(".strings")]
op.join(src_folder, fn)
for fn in os.listdir(src_folder)
if fn.endswith(".strings")
]
for path in stringsfiles: for path in stringsfiles:
localize_stringsfile(path, dest_root_folder) localize_stringsfile(path, dest_root_folder)

View File

@@ -16,8 +16,7 @@ from collections import defaultdict
class Broadcaster: class Broadcaster:
"""Broadcasts messages that are received by all listeners. """Broadcasts messages that are received by all listeners."""
"""
def __init__(self): def __init__(self):
self.listeners = set() self.listeners = set()
@@ -39,8 +38,7 @@ class Broadcaster:
class Listener: class Listener:
"""A listener is initialized with the broadcaster it's going to listen to. Initially, it is not connected. """A listener is initialized with the broadcaster it's going to listen to. Initially, it is not connected."""
"""
def __init__(self, broadcaster): def __init__(self, broadcaster):
self.broadcaster = broadcaster self.broadcaster = broadcaster
@@ -57,13 +55,11 @@ class Listener:
self._bound_notifications[message].append(func) self._bound_notifications[message].append(func)
def connect(self): def connect(self):
"""Connects the listener to its broadcaster. """Connects the listener to its broadcaster."""
"""
self.broadcaster.add_listener(self) self.broadcaster.add_listener(self)
def disconnect(self): def disconnect(self):
"""Disconnects the listener from its broadcaster. """Disconnects the listener from its broadcaster."""
"""
self.broadcaster.remove_listener(self) self.broadcaster.remove_listener(self)
def dispatch(self, msg): def dispatch(self, msg):

View File

@@ -85,9 +85,7 @@ class Path(tuple):
def __getitem__(self, key): def __getitem__(self, key):
if isinstance(key, slice): if isinstance(key, slice):
if isinstance(key.start, Path): if isinstance(key.start, Path):
equal_elems = list( equal_elems = list(takewhile(lambda pair: pair[0] == pair[1], zip(self, key.start)))
takewhile(lambda pair: pair[0] == pair[1], zip(self, key.start))
)
key = slice(len(equal_elems), key.stop, key.step) key = slice(len(equal_elems), key.stop, key.step)
if isinstance(key.stop, Path): if isinstance(key.stop, Path):
equal_elems = list( equal_elems = list(
@@ -226,9 +224,7 @@ def pathify(f):
Calling ``foo('/bar', 0)`` will convert ``'/bar'`` to ``Path('/bar')``. Calling ``foo('/bar', 0)`` will convert ``'/bar'`` to ``Path('/bar')``.
""" """
sig = signature(f) sig = signature(f)
pindexes = { pindexes = {i for i, p in enumerate(sig.parameters.values()) if p.annotation is Path}
i for i, p in enumerate(sig.parameters.values()) if p.annotation is Path
}
pkeys = {k: v for k, v in sig.parameters.items() if v.annotation is Path} pkeys = {k: v for k, v in sig.parameters.items() if v.annotation is Path}
def path_or_none(p): def path_or_none(p):
@@ -236,9 +232,7 @@ def pathify(f):
@wraps(f) @wraps(f)
def wrapped(*args, **kwargs): def wrapped(*args, **kwargs):
args = tuple( args = tuple((path_or_none(a) if i in pindexes else a) for i, a in enumerate(args))
(path_or_none(a) if i in pindexes else a) for i, a in enumerate(args)
)
kwargs = {k: (path_or_none(v) if k in pkeys else v) for k, v in kwargs.items()} kwargs = {k: (path_or_none(v) if k in pkeys else v) for k, v in kwargs.items()}
return f(*args, **kwargs) return f(*args, **kwargs)
@@ -246,8 +240,7 @@ def pathify(f):
def log_io_error(func): def log_io_error(func):
""" Catches OSError, IOError and WindowsError and log them """Catches OSError, IOError and WindowsError and log them"""
"""
@wraps(func) @wraps(func)
def wrapper(path, *args, **kwargs): def wrapper(path, *args, **kwargs):

View File

@@ -110,22 +110,14 @@ def _visit_pyfiles(list, dirname, names):
# get extension for python source files # get extension for python source files
if "_py_ext" not in globals(): if "_py_ext" not in globals():
global _py_ext global _py_ext
_py_ext = [ _py_ext = [triple[0] for triple in imp.get_suffixes() if triple[2] == imp.PY_SOURCE][0]
triple[0] for triple in imp.get_suffixes() if triple[2] == imp.PY_SOURCE
][0]
# don't recurse into CVS directories # don't recurse into CVS directories
if "CVS" in names: if "CVS" in names:
names.remove("CVS") names.remove("CVS")
# add all *.py files to list # add all *.py files to list
list.extend( list.extend([os.path.join(dirname, file) for file in names if os.path.splitext(file)[1] == _py_ext])
[
os.path.join(dirname, file)
for file in names
if os.path.splitext(file)[1] == _py_ext
]
)
def _get_modpkg_path(dotted_name, pathlist=None): def _get_modpkg_path(dotted_name, pathlist=None):
@@ -406,8 +398,7 @@ def main(source_files, outpath, keywords=None):
eater(*_token) eater(*_token)
except tokenize.TokenError as e: except tokenize.TokenError as e:
print( print(
"%s: %s, line %d, column %d" "%s: %s, line %d, column %d" % (e.args[0], filename, e.args[1][0], e.args[1][1]),
% (e.args[0], filename, e.args[1][0], e.args[1][1]),
file=sys.stderr, file=sys.stderr,
) )
finally: finally:

View File

@@ -7,10 +7,8 @@
import os.path as op import os.path as op
import re import re
from distutils.version import LooseVersion
from pkg_resources import load_entry_point, get_distribution
from .build import read_changelog_file, filereplace from .build import read_changelog_file, filereplace
from sphinx.cmd.build import build_main as sphinx_build
CHANGELOG_FORMAT = """ CHANGELOG_FORMAT = """
{version} ({date}) {version} ({date})
@@ -24,9 +22,7 @@ def tixgen(tixurl):
"""This is a filter *generator*. tixurl is a url pattern for the tix with a {0} placeholder """This is a filter *generator*. tixurl is a url pattern for the tix with a {0} placeholder
for the tix # for the tix #
""" """
urlpattern = tixurl.format( urlpattern = tixurl.format("\\1") # will be replaced buy the content of the first group in re
"\\1"
) # will be replaced buy the content of the first group in re
R = re.compile(r"#(\d+)") R = re.compile(r"#(\d+)")
repl = "`#\\1 <{}>`__".format(urlpattern) repl = "`#\\1 <{}>`__".format(urlpattern)
return lambda text: R.sub(repl, text) return lambda text: R.sub(repl, text)
@@ -63,9 +59,7 @@ def gen(
# The format of the changelog descriptions is in markdown, but since we only use bulled list # The format of the changelog descriptions is in markdown, but since we only use bulled list
# and links, it's not worth depending on the markdown package. A simple regexp suffice. # and links, it's not worth depending on the markdown package. A simple regexp suffice.
description = re.sub(r"\[(.*?)\]\((.*?)\)", "`\\1 <\\2>`__", description) description = re.sub(r"\[(.*?)\]\((.*?)\)", "`\\1 <\\2>`__", description)
rendered = CHANGELOG_FORMAT.format( rendered = CHANGELOG_FORMAT.format(version=log["version"], date=log["date_str"], description=description)
version=log["version"], date=log["date_str"], description=description
)
rendered_logs.append(rendered) rendered_logs.append(rendered)
confrepl["version"] = changelog[0]["version"] confrepl["version"] = changelog[0]["version"]
changelog_out = op.join(basepath, "changelog.rst") changelog_out = op.join(basepath, "changelog.rst")
@@ -73,26 +67,8 @@ def gen(
if op.exists(confpath): if op.exists(confpath):
conf_out = op.join(basepath, "conf.py") conf_out = op.join(basepath, "conf.py")
filereplace(confpath, conf_out, **confrepl) filereplace(confpath, conf_out, **confrepl)
if LooseVersion(get_distribution("sphinx").version) >= LooseVersion("1.7.0"):
from sphinx.cmd.build import build_main as sphinx_build
# Call the sphinx_build function, which is the same as doing sphinx-build from cli # Call the sphinx_build function, which is the same as doing sphinx-build from cli
try: try:
sphinx_build([basepath, destpath]) sphinx_build([basepath, destpath])
except SystemExit: except SystemExit:
print( print("Sphinx called sys.exit(), but we're cancelling it because we don't actually want to exit")
"Sphinx called sys.exit(), but we're cancelling it because we don't actually want to exit"
)
else:
# We used to call sphinx-build with print_and_do(), but the problem was that the virtualenv
# of the calling python wasn't correctly considered and caused problems with documentation
# relying on autodoc (which tries to import the module to auto-document, but fail because of
# missing dependencies which are in the virtualenv). Here, we do exactly what is done when
# calling the command from bash.
cmd = load_entry_point("Sphinx", "console_scripts", "sphinx-build")
try:
cmd(["sphinx-build", basepath, destpath])
except SystemExit:
print(
"Sphinx called sys.exit(), but we're cancelling it because we don't actually want to exit"
)

View File

@@ -80,9 +80,7 @@ class TestCase_move_copy:
assert self.path["baz"].exists() assert self.path["baz"].exists()
assert not self.path["foo"].exists() assert not self.path["foo"].exists()
def test_copy_no_conflict( def test_copy_no_conflict(self, do_setup): # No need to duplicate the rest of the tests... Let's just test on move
self, do_setup
): # No need to duplicate the rest of the tests... Let's just test on move
smart_copy(self.path + "foo", self.path + "baz") smart_copy(self.path + "foo", self.path + "baz")
assert self.path["baz"].exists() assert self.path["baz"].exists()
assert self.path["foo"].exists() assert self.path["foo"].exists()

View File

@@ -128,9 +128,7 @@ def test_repeater_with_repeated_notifications():
r.connect() r.connect()
listener.connect() listener.connect()
b.notify("hello") b.notify("hello")
b.notify( b.notify("foo") # if the repeater repeated this notif, we'd get a crash on HelloListener
"foo"
) # if the repeater repeated this notif, we'd get a crash on HelloListener
eq_(r.hello_count, 1) eq_(r.hello_count, 1)
eq_(listener.hello_count, 1) eq_(listener.hello_count, 1)
eq_(r.foo_count, 1) eq_(r.foo_count, 1)

View File

@@ -87,8 +87,7 @@ def test_filename(force_ossep):
def test_deal_with_empty_components(force_ossep): def test_deal_with_empty_components(force_ossep):
"""Keep ONLY a leading space, which means we want a leading slash. """Keep ONLY a leading space, which means we want a leading slash."""
"""
eq_("foo//bar", str(Path(("foo", "", "bar")))) eq_("foo//bar", str(Path(("foo", "", "bar"))))
eq_("/foo/bar", str(Path(("", "foo", "bar")))) eq_("/foo/bar", str(Path(("", "foo", "bar"))))
eq_("foo/bar", str(Path("foo/bar/"))) eq_("foo/bar", str(Path("foo/bar/")))
@@ -154,8 +153,7 @@ def test_path_slice(force_ossep):
def test_add_with_root_path(force_ossep): def test_add_with_root_path(force_ossep):
"""if I perform /a/b/c + /d/e/f, I want /a/b/c/d/e/f, not /a/b/c//d/e/f """if I perform /a/b/c + /d/e/f, I want /a/b/c/d/e/f, not /a/b/c//d/e/f"""
"""
eq_("/foo/bar", str(Path("/foo") + Path("/bar"))) eq_("/foo/bar", str(Path("/foo") + Path("/bar")))
@@ -166,8 +164,7 @@ def test_create_with_tuple_that_have_slash_inside(force_ossep, monkeypatch):
def test_auto_decode_os_sep(force_ossep, monkeypatch): def test_auto_decode_os_sep(force_ossep, monkeypatch):
"""Path should decode any either / or os.sep, but always encode in os.sep. """Path should decode any either / or os.sep, but always encode in os.sep."""
"""
eq_(("foo\\bar", "bleh"), Path("foo\\bar/bleh")) eq_(("foo\\bar", "bleh"), Path("foo\\bar/bleh"))
monkeypatch.setattr(os, "sep", "\\") monkeypatch.setattr(os, "sep", "\\")
eq_(("foo", "bar/bleh"), Path("foo\\bar/bleh")) eq_(("foo", "bar/bleh"), Path("foo\\bar/bleh"))

View File

@@ -44,9 +44,7 @@ def test_guicalls():
# A GUISelectableList appropriately calls its view. # A GUISelectableList appropriately calls its view.
sl = GUISelectableList(["foo", "bar"]) sl = GUISelectableList(["foo", "bar"])
sl.view = CallLogger() sl.view = CallLogger()
sl.view.check_gui_calls( sl.view.check_gui_calls(["refresh"]) # Upon setting the view, we get a call to refresh()
["refresh"]
) # Upon setting the view, we get a call to refresh()
sl[1] = "baz" sl[1] = "baz"
sl.view.check_gui_calls(["refresh"]) sl.view.check_gui_calls(["refresh"])
sl.append("foo") sl.append("foo")

View File

@@ -105,9 +105,7 @@ def test_findall_dont_include_self():
# When calling findall with include_self=False, the node itself is never evaluated. # When calling findall with include_self=False, the node itself is never evaluated.
t = tree_with_some_nodes() t = tree_with_some_nodes()
del t._name # so that if the predicate is called on `t`, we crash del t._name # so that if the predicate is called on `t`, we crash
r = t.findall( r = t.findall(lambda n: not n.name.startswith("sub"), include_self=False) # no crash
lambda n: not n.name.startswith("sub"), include_self=False
) # no crash
eq_(set(r), set([t[0], t[1], t[2]])) eq_(set(r), set([t[0], t[1], t[2]]))

View File

@@ -105,9 +105,7 @@ def test_iterconsume():
# We just want to make sure that we return *all* items and that we're not mistakenly skipping # We just want to make sure that we return *all* items and that we're not mistakenly skipping
# one. # one.
eq_(list(range(2500)), list(iterconsume(list(range(2500))))) eq_(list(range(2500)), list(iterconsume(list(range(2500)))))
eq_( eq_(list(reversed(range(2500))), list(iterconsume(list(range(2500)), reverse=False)))
list(reversed(range(2500))), list(iterconsume(list(range(2500)), reverse=False))
)
# --- String # --- String

View File

@@ -86,9 +86,7 @@ class CallLogger:
eq_(set(self.calls), set(expected)) eq_(set(self.calls), set(expected))
self.clear_calls() self.clear_calls()
def check_gui_calls_partial( def check_gui_calls_partial(self, expected=None, not_expected=None, verify_order=False):
self, expected=None, not_expected=None, verify_order=False
):
"""Checks that the expected calls have been made to 'self', then clears the log. """Checks that the expected calls have been made to 'self', then clears the log.
`expected` is an iterable of strings representing method names. Order doesn't matter. `expected` is an iterable of strings representing method names. Order doesn't matter.
@@ -99,25 +97,17 @@ class CallLogger:
__tracebackhide__ = True __tracebackhide__ = True
if expected is not None: if expected is not None:
not_called = set(expected) - set(self.calls) not_called = set(expected) - set(self.calls)
assert not not_called, "These calls haven't been made: {0}".format( assert not not_called, "These calls haven't been made: {0}".format(not_called)
not_called
)
if verify_order: if verify_order:
max_index = 0 max_index = 0
for call in expected: for call in expected:
index = self.calls.index(call) index = self.calls.index(call)
if index < max_index: if index < max_index:
raise AssertionError( raise AssertionError("The call {0} hasn't been made in the correct order".format(call))
"The call {0} hasn't been made in the correct order".format(
call
)
)
max_index = index max_index = index
if not_expected is not None: if not_expected is not None:
called = set(not_expected) & set(self.calls) called = set(not_expected) & set(self.calls)
assert not called, "These calls shouldn't have been made: {0}".format( assert not called, "These calls shouldn't have been made: {0}".format(called)
called
)
self.clear_calls() self.clear_calls()
@@ -211,9 +201,7 @@ def _unify_args(func, args, kwargs, args_to_ignore=None):
result = kwargs.copy() result = kwargs.copy()
if hasattr(func, "__code__"): # built-in functions don't have func_code if hasattr(func, "__code__"): # built-in functions don't have func_code
args = list(args) args = list(args)
if ( if getattr(func, "__self__", None) is not None: # bound method, we have to add self to args list
getattr(func, "__self__", None) is not None
): # bound method, we have to add self to args list
args = [func.__self__] + args args = [func.__self__] + args
defaults = list(func.__defaults__) if func.__defaults__ is not None else [] defaults = list(func.__defaults__) if func.__defaults__ is not None else []
arg_count = func.__code__.co_argcount arg_count = func.__code__.co_argcount

View File

@@ -13,7 +13,7 @@ import locale
import logging import logging
import os.path as op import os.path as op
from .plat import ISWINDOWS, ISLINUX from .plat import ISLINUX
_trfunc = None _trfunc = None
_trget = None _trget = None
@@ -46,36 +46,23 @@ def set_tr(new_tr, new_trget=None):
def get_locale_name(lang): def get_locale_name(lang):
if ISWINDOWS: # Removed old conversion code as windows seems to support these
# http://msdn.microsoft.com/en-us/library/39cwe7zf(vs.71).aspx
LANG2LOCALENAME = {
"cs": "czy",
"de": "deu",
"el": "grc",
"es": "esn",
"fr": "fra",
"it": "ita",
"ko": "korean",
"nl": "nld",
"pl_PL": "polish_poland",
"pt_BR": "ptb",
"ru": "rus",
"zh_CN": "chs",
}
else:
LANG2LOCALENAME = { LANG2LOCALENAME = {
"cs": "cs_CZ", "cs": "cs_CZ",
"de": "de_DE", "de": "de_DE",
"el": "el_GR", "el": "el_GR",
"en": "en",
"es": "es_ES", "es": "es_ES",
"fr": "fr_FR", "fr": "fr_FR",
"it": "it_IT",
"nl": "nl_NL",
"hy": "hy_AM", "hy": "hy_AM",
"it": "it_IT",
"ja": "ja_JP",
"ko": "ko_KR", "ko": "ko_KR",
"nl": "nl_NL",
"pl_PL": "pl_PL", "pl_PL": "pl_PL",
"pt_BR": "pt_BR", "pt_BR": "pt_BR",
"ru": "ru_RU", "ru": "ru_RU",
"tr": "tr_TR",
"uk": "uk_UA", "uk": "uk_UA",
"vi": "vi_VN", "vi": "vi_VN",
"zh_CN": "zh_CN", "zh_CN": "zh_CN",
@@ -123,9 +110,7 @@ def install_gettext_trans(base_folder, lang):
if not lang: if not lang:
return lambda s: s return lambda s: s
try: try:
return gettext.translation( return gettext.translation(domain, localedir=base_folder, languages=[lang]).gettext
domain, localedir=base_folder, languages=[lang]
).gettext
except IOError: except IOError:
return lambda s: s return lambda s: s

View File

@@ -19,8 +19,7 @@ from .path import Path, pathify, log_io_error
def nonone(value, replace_value): def nonone(value, replace_value):
"""Returns ``value`` if ``value`` is not ``None``. Returns ``replace_value`` otherwise. """Returns ``value`` if ``value`` is not ``None``. Returns ``replace_value`` otherwise."""
"""
if value is None: if value is None:
return replace_value return replace_value
else: else:
@@ -28,8 +27,7 @@ def nonone(value, replace_value):
def tryint(value, default=0): def tryint(value, default=0):
"""Tries to convert ``value`` to in ``int`` and returns ``default`` if it fails. """Tries to convert ``value`` to in ``int`` and returns ``default`` if it fails."""
"""
try: try:
return int(value) return int(value)
except (TypeError, ValueError): except (TypeError, ValueError):
@@ -37,8 +35,7 @@ def tryint(value, default=0):
def minmax(value, min_value, max_value): def minmax(value, min_value, max_value):
"""Returns `value` or one of the min/max bounds if `value` is not between them. """Returns `value` or one of the min/max bounds if `value` is not between them."""
"""
return min(max(value, min_value), max_value) return min(max(value, min_value), max_value)
@@ -75,8 +72,7 @@ def flatten(iterables, start_with=None):
def first(iterable): def first(iterable):
"""Returns the first item of ``iterable``. """Returns the first item of ``iterable``."""
"""
try: try:
return next(iter(iterable)) return next(iter(iterable))
except StopIteration: except StopIteration:
@@ -84,14 +80,12 @@ def first(iterable):
def stripfalse(seq): def stripfalse(seq):
"""Returns a sequence with all false elements stripped out of seq. """Returns a sequence with all false elements stripped out of seq."""
"""
return [x for x in seq if x] return [x for x in seq if x]
def extract(predicate, iterable): def extract(predicate, iterable):
"""Separates the wheat from the shaft (`predicate` defines what's the wheat), and returns both. """Separates the wheat from the shaft (`predicate` defines what's the wheat), and returns both."""
"""
wheat = [] wheat = []
shaft = [] shaft = []
for item in iterable: for item in iterable:
@@ -103,8 +97,7 @@ def extract(predicate, iterable):
def allsame(iterable): def allsame(iterable):
"""Returns whether all elements of 'iterable' are the same. """Returns whether all elements of 'iterable' are the same."""
"""
it = iter(iterable) it = iter(iterable)
try: try:
first_item = next(it) first_item = next(it)
@@ -152,14 +145,12 @@ def iterconsume(seq, reverse=True):
def escape(s, to_escape, escape_with="\\"): def escape(s, to_escape, escape_with="\\"):
"""Returns ``s`` with characters in ``to_escape`` all prepended with ``escape_with``. """Returns ``s`` with characters in ``to_escape`` all prepended with ``escape_with``."""
"""
return "".join((escape_with + c if c in to_escape else c) for c in s) return "".join((escape_with + c if c in to_escape else c) for c in s)
def get_file_ext(filename): def get_file_ext(filename):
"""Returns the lowercase extension part of filename, without the dot. """Returns the lowercase extension part of filename, without the dot."""
"""
pos = filename.rfind(".") pos = filename.rfind(".")
if pos > -1: if pos > -1:
return filename[pos + 1 :].lower() return filename[pos + 1 :].lower()
@@ -168,8 +159,7 @@ def get_file_ext(filename):
def rem_file_ext(filename): def rem_file_ext(filename):
"""Returns the filename without extension. """Returns the filename without extension."""
"""
pos = filename.rfind(".") pos = filename.rfind(".")
if pos > -1: if pos > -1:
return filename[:pos] return filename[:pos]
@@ -217,8 +207,7 @@ def format_time(seconds, with_hours=True):
def format_time_decimal(seconds): def format_time_decimal(seconds):
"""Transforms seconds in a strings like '3.4 minutes'. """Transforms seconds in a strings like '3.4 minutes'."""
"""
minus = seconds < 0 minus = seconds < 0
if minus: if minus:
seconds *= -1 seconds *= -1
@@ -320,8 +309,7 @@ ONE_DAY = timedelta(1)
def iterdaterange(start, end): def iterdaterange(start, end):
"""Yields every day between ``start`` and ``end``. """Yields every day between ``start`` and ``end``."""
"""
date = start date = start
while date <= end: while date <= end:
yield date yield date
@@ -365,8 +353,7 @@ def find_in_path(name, paths=None):
@log_io_error @log_io_error
@pathify @pathify
def delete_if_empty(path: Path, files_to_delete=[]): def delete_if_empty(path: Path, files_to_delete=[]):
"""Deletes the directory at 'path' if it is empty or if it only contains files_to_delete. """Deletes the directory at 'path' if it is empty or if it only contains files_to_delete."""
"""
if not path.exists() or not path.isdir(): if not path.exists() or not path.isdir():
return return
contents = path.listdir() contents = path.listdir()
@@ -411,8 +398,7 @@ def ensure_file(path):
def delete_files_with_pattern(folder_path, pattern, recursive=True): def delete_files_with_pattern(folder_path, pattern, recursive=True):
"""Delete all files (or folders) in `folder_path` that match the glob `pattern`. """Delete all files (or folders) in `folder_path` that match the glob `pattern`."""
"""
to_delete = glob.glob(op.join(folder_path, pattern)) to_delete = glob.glob(op.join(folder_path, pattern))
for fn in to_delete: for fn in to_delete:
if op.isdir(fn): if op.isdir(fn):

View File

@@ -0,0 +1,119 @@
#
msgid ""
msgstr ""
"Language-Team: Arabic (https://www.transifex.com/voltaicideas/teams/116153/ar/)\n"
"Language: ar\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
#: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core\gui\problem_table.py:18
msgid "File Path"
msgstr ""
#: core\gui\problem_table.py:19
msgid "Error Message"
msgstr ""
#: core\me\prioritize.py:23
msgid "Duration"
msgstr ""
#: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate"
msgstr ""
#: core\me\prioritize.py:37
msgid "Samplerate"
msgstr ""
#: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
#: core\se\result_table.py:19
msgid "Filename"
msgstr ""
#: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core\se\result_table.py:20
msgid "Folder"
msgstr ""
#: core\me\result_table.py:21
msgid "Size (MB)"
msgstr ""
#: core\me\result_table.py:22
msgid "Time"
msgstr ""
#: core\me\result_table.py:24
msgid "Sample Rate"
msgstr ""
#: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core\se\result_table.py:22
msgid "Kind"
msgstr ""
#: core\me\result_table.py:26 core\pe\result_table.py:25
#: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification"
msgstr ""
#: core\me\result_table.py:27
msgid "Title"
msgstr ""
#: core\me\result_table.py:28
msgid "Artist"
msgstr ""
#: core\me\result_table.py:29
msgid "Album"
msgstr ""
#: core\me\result_table.py:30
msgid "Genre"
msgstr ""
#: core\me\result_table.py:31
msgid "Year"
msgstr ""
#: core\me\result_table.py:32
msgid "Track Number"
msgstr ""
#: core\me\result_table.py:33
msgid "Comment"
msgstr ""
#: core\me\result_table.py:34 core\pe\result_table.py:26
#: core\se\result_table.py:24
msgid "Match %"
msgstr ""
#: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used"
msgstr ""
#: core\me\result_table.py:36 core\pe\result_table.py:27
#: core\se\result_table.py:26
msgid "Dupe Count"
msgstr ""
#: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions"
msgstr ""
#: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)"
msgstr ""
#: core\pe\result_table.py:24
msgid "EXIF Timestamp"
msgstr ""
#: core\prioritize.py:156
msgid "Size"
msgstr ""

View File

@@ -0,0 +1,246 @@
#
msgid ""
msgstr ""
"Language-Team: Arabic (https://www.transifex.com/voltaicideas/teams/116153/ar/)\n"
"Language: ar\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
#: core\app.py:42
msgid "There are no marked duplicates. Nothing has been done."
msgstr ""
#: core\app.py:43
msgid "There are no selected duplicates. Nothing has been done."
msgstr ""
#: core\app.py:44
msgid ""
"You're about to open many files at once. Depending on what those files are "
"opened with, doing so can create quite a mess. Continue?"
msgstr ""
#: core\app.py:71
msgid "Scanning for duplicates"
msgstr ""
#: core\app.py:72
msgid "Loading"
msgstr ""
#: core\app.py:73
msgid "Moving"
msgstr ""
#: core\app.py:74
msgid "Copying"
msgstr ""
#: core\app.py:75
msgid "Sending to Trash"
msgstr ""
#: core\app.py:308
msgid ""
"A previous action is still hanging in there. You can't start a new one yet. "
"Wait a few seconds, then try again."
msgstr ""
#: core\app.py:318
msgid "No duplicates found."
msgstr ""
#: core\app.py:333
msgid "All marked files were copied successfully."
msgstr ""
#: core\app.py:334
msgid "All marked files were moved successfully."
msgstr ""
#: core\app.py:335
msgid "All marked files were successfully sent to Trash."
msgstr ""
#: core\app.py:343
msgid "Could not load file: {}"
msgstr ""
#: core\app.py:399
msgid "'{}' already is in the list."
msgstr ""
#: core\app.py:401
msgid "'{}' does not exist."
msgstr ""
#: core\app.py:410
msgid ""
"All selected %d matches are going to be ignored in all subsequent scans. "
"Continue?"
msgstr ""
#: core\app.py:486
msgid "Select a directory to copy marked files to"
msgstr ""
#: core\app.py:487
msgid "Select a directory to move marked files to"
msgstr ""
#: core\app.py:527
msgid "Select a destination for your exported CSV"
msgstr ""
#: core\app.py:534 core\app.py:801 core\app.py:811
msgid "Couldn't write to file: {}"
msgstr ""
#: core\app.py:559
msgid "You have no custom command set up. Set it up in your preferences."
msgstr ""
#: core\app.py:727 core\app.py:740
msgid "You are about to remove %d files from results. Continue?"
msgstr ""
#: core\app.py:774
msgid "{} duplicate groups were changed by the re-prioritization."
msgstr ""
#: core\app.py:821
msgid "The selected directories contain no scannable file."
msgstr ""
#: core\app.py:835
msgid "Collecting files to scan"
msgstr ""
#: core\app.py:891
msgid "%s (%d discarded)"
msgstr ""
#: core\engine.py:244 core\engine.py:288
msgid "0 matches found"
msgstr ""
#: core\engine.py:262 core\engine.py:296
msgid "%d matches found"
msgstr ""
#: core\gui\deletion_options.py:73
msgid "You are sending {} file(s) to the Trash."
msgstr ""
#: core\gui\exclude_list_table.py:15
msgid "Regular Expressions"
msgstr ""
#: core\gui\ignore_list_dialog.py:25
msgid "Do you really want to remove all %d items from the ignore list?"
msgstr ""
#: core\me\scanner.py:20 core\se\scanner.py:16
msgid "Filename"
msgstr ""
#: core\me\scanner.py:21
msgid "Filename - Fields"
msgstr ""
#: core\me\scanner.py:22
msgid "Filename - Fields (No Order)"
msgstr ""
#: core\me\scanner.py:23
msgid "Tags"
msgstr ""
#: core\me\scanner.py:24 core\pe\scanner.py:21 core\se\scanner.py:17
msgid "Contents"
msgstr ""
#: core\pe\matchblock.py:72
msgid "Analyzed %d/%d pictures"
msgstr ""
#: core\pe\matchblock.py:181
msgid "Performed %d/%d chunk matches"
msgstr ""
#: core\pe\matchblock.py:191
msgid "Preparing for matching"
msgstr ""
#: core\pe\matchblock.py:244
msgid "Verified %d/%d matches"
msgstr ""
#: core\pe\matchexif.py:19
msgid "Read EXIF of %d/%d pictures"
msgstr ""
#: core\pe\scanner.py:22
msgid "EXIF Timestamp"
msgstr ""
#: core\prioritize.py:70
msgid "None"
msgstr ""
#: core\prioritize.py:100
msgid "Ends with number"
msgstr ""
#: core\prioritize.py:101
msgid "Doesn't end with number"
msgstr ""
#: core\prioritize.py:102
msgid "Longest"
msgstr ""
#: core\prioritize.py:103
msgid "Shortest"
msgstr ""
#: core\prioritize.py:140
msgid "Highest"
msgstr ""
#: core\prioritize.py:140
msgid "Lowest"
msgstr ""
#: core\prioritize.py:169
msgid "Newest"
msgstr ""
#: core\prioritize.py:169
msgid "Oldest"
msgstr ""
#: core\results.py:142
msgid "%d / %d (%s / %s) duplicates marked."
msgstr ""
#: core\results.py:149
msgid " filter: %s"
msgstr ""
#: core\scanner.py:85
msgid "Read size of %d/%d files"
msgstr ""
#: core\scanner.py:109
msgid "Read metadata of %d/%d files"
msgstr ""
#: core\scanner.py:147
msgid "Almost done! Fiddling with results..."
msgstr ""
#: core\se\scanner.py:18
msgid "Folders"
msgstr ""

910
locale/ar/LC_MESSAGES/ui.po Normal file
View File

@@ -0,0 +1,910 @@
#
msgid ""
msgstr ""
"Language-Team: Arabic (https://www.transifex.com/voltaicideas/teams/116153/ar/)\n"
"Language: ar\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
#: qt/app.py:81
msgid "Quit"
msgstr ""
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr ""
#: qt/app.py:83 qt/ignore_list_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Ignore List"
msgstr ""
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr ""
#: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Help"
msgstr ""
#: qt/app.py:86 cocoa/en.lproj/Localizable.strings:0
msgid "About dupeGuru"
msgstr ""
#: qt/app.py:87
msgid "Open Debug Log"
msgstr ""
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr ""
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr ""
#: qt/app.py:251
msgid "{} file (*.{})"
msgstr ""
#: qt/deletion_options.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Deletion Options"
msgstr ""
#: qt/deletion_options.py:35 cocoa/en.lproj/Localizable.strings:0
msgid "Link deleted files"
msgstr ""
#: qt/deletion_options.py:37 cocoa/en.lproj/Localizable.strings:0
msgid ""
"After having deleted a duplicate, place a link targeting the reference file "
"to replace the deleted file."
msgstr ""
#: qt/deletion_options.py:44
msgid "Hardlink"
msgstr ""
#: qt/deletion_options.py:44
msgid "Symlink"
msgstr ""
#: qt/deletion_options.py:48
msgid " (unsupported)"
msgstr ""
#: qt/deletion_options.py:49 cocoa/en.lproj/Localizable.strings:0
msgid "Directly delete files"
msgstr ""
#: qt/deletion_options.py:51 cocoa/en.lproj/Localizable.strings:0
msgid ""
"Instead of sending files to trash, delete them directly. This option is "
"usually used as a workaround when the normal deletion method doesn't work."
msgstr ""
#: qt/deletion_options.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Proceed"
msgstr ""
#: qt/deletion_options.py:60 cocoa/en.lproj/Localizable.strings:0
msgid "Cancel"
msgstr ""
#: qt/details_table.py:16 cocoa/en.lproj/Localizable.strings:0
msgid "Attribute"
msgstr ""
#: qt/details_table.py:16 cocoa/en.lproj/Localizable.strings:0
msgid "Selected"
msgstr ""
#: qt/details_table.py:16 qt/directories_model.py:24
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reference"
msgstr ""
#: qt/directories_dialog.py:64 cocoa/en.lproj/Localizable.strings:0
msgid "Load Results..."
msgstr ""
#: qt/directories_dialog.py:65 cocoa/en.lproj/Localizable.strings:0
msgid "Results Window"
msgstr ""
#: qt/directories_dialog.py:66
msgid "Add Folder..."
msgstr ""
#: qt/directories_dialog.py:74 qt/result_window.py:100
#: cocoa/en.lproj/Localizable.strings:0
msgid "File"
msgstr ""
#: qt/directories_dialog.py:76 qt/result_window.py:108
msgid "View"
msgstr ""
#: qt/directories_dialog.py:78 qt/result_window.py:110
#: cocoa/en.lproj/Localizable.strings:0
msgid "Help"
msgstr ""
#: qt/directories_dialog.py:80 cocoa/en.lproj/Localizable.strings:0
msgid "Load Recent Results"
msgstr ""
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0
msgid "Application Mode:"
msgstr ""
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Music"
msgstr ""
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Picture"
msgstr ""
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Standard"
msgstr ""
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0
msgid "Scan Type:"
msgstr ""
#: qt/directories_dialog.py:135
msgid "More Options"
msgstr ""
#: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0
msgid "Select folders to scan and press \"Scan\"."
msgstr ""
#: qt/directories_dialog.py:163 cocoa/en.lproj/Localizable.strings:0
msgid "Load Results"
msgstr ""
#: qt/directories_dialog.py:166 cocoa/en.lproj/Localizable.strings:0
msgid "Scan"
msgstr ""
#: qt/directories_dialog.py:230
msgid "Unsaved results"
msgstr ""
#: qt/directories_dialog.py:231 cocoa/en.lproj/Localizable.strings:0
msgid "You have unsaved results, do you really want to quit?"
msgstr ""
#: qt/directories_dialog.py:239 cocoa/en.lproj/Localizable.strings:0
msgid "Select a folder to add to the scanning list"
msgstr ""
#: qt/directories_dialog.py:266 cocoa/en.lproj/Localizable.strings:0
msgid "Select a results file to load"
msgstr ""
#: qt/directories_dialog.py:267
msgid "All Files (*.*)"
msgstr ""
#: qt/directories_dialog.py:267 qt/result_window.py:311
msgid "dupeGuru Results (*.dupeguru)"
msgstr ""
#: qt/directories_dialog.py:278
msgid "Start a new scan"
msgstr ""
#: qt/directories_dialog.py:279 cocoa/en.lproj/Localizable.strings:0
msgid "You have unsaved results, do you really want to continue?"
msgstr ""
#: qt/directories_model.py:23 cocoa/en.lproj/Localizable.strings:0
msgid "Name"
msgstr ""
#: qt/directories_model.py:23 cocoa/en.lproj/Localizable.strings:0
msgid "State"
msgstr ""
#: qt/directories_model.py:24 cocoa/en.lproj/Localizable.strings:0
msgid "Excluded"
msgstr ""
#: qt/directories_model.py:24 cocoa/en.lproj/Localizable.strings:0
msgid "Normal"
msgstr ""
#: qt/ignore_list_dialog.py:45 cocoa/en.lproj/Localizable.strings:0
msgid "Remove Selected"
msgstr ""
#: qt/ignore_list_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Clear"
msgstr ""
#: qt/ignore_list_dialog.py:47 qt/problem_dialog.py:61
#: cocoa/en.lproj/Localizable.strings:0
msgid "Close"
msgstr ""
#: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
#: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr ""
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr ""
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr ""
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr ""
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr ""
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr ""
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr ""
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr ""
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr ""
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr ""
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr ""
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr ""
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr ""
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr ""
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr ""
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr ""
#: qt/preferences_dialog.py:43
msgid "Filter Hardness:"
msgstr ""
#: qt/preferences_dialog.py:69
msgid "More Results"
msgstr ""
#: qt/preferences_dialog.py:74
msgid "Fewer Results"
msgstr ""
#: qt/preferences_dialog.py:81
msgid "Font size:"
msgstr ""
#: qt/preferences_dialog.py:85
msgid "Language:"
msgstr ""
#: qt/preferences_dialog.py:91 cocoa/en.lproj/Localizable.strings:0
msgid "Copy and Move:"
msgstr ""
#: qt/preferences_dialog.py:94 cocoa/en.lproj/Localizable.strings:0
msgid "Right in destination"
msgstr ""
#: qt/preferences_dialog.py:95 cocoa/en.lproj/Localizable.strings:0
msgid "Recreate relative path"
msgstr ""
#: qt/preferences_dialog.py:96 cocoa/en.lproj/Localizable.strings:0
msgid "Recreate absolute path"
msgstr ""
#: qt/preferences_dialog.py:99
msgid "Custom Command (arguments: %d for dupe, %r for ref):"
msgstr ""
#: qt/preferences_dialog.py:174
msgid "dupeGuru has to restart for language changes to take effect."
msgstr ""
#: qt/prioritize_dialog.py:75 cocoa/en.lproj/Localizable.strings:0
msgid "Re-Prioritize duplicates"
msgstr ""
#: qt/prioritize_dialog.py:79 cocoa/en.lproj/Localizable.strings:0
msgid ""
"Add criteria to the right box and click OK to send the dupes that correspond"
" the best to these criteria to their respective group's reference position. "
"Read the help file for more information."
msgstr ""
#: qt/problem_dialog.py:33 cocoa/en.lproj/Localizable.strings:0
msgid "Problems!"
msgstr ""
#: qt/problem_dialog.py:37 cocoa/en.lproj/Localizable.strings:0
msgid ""
"There were problems processing some (or all) of the files. The cause of "
"these problems are described in the table below. Those files were not "
"removed from your results."
msgstr ""
#: qt/problem_dialog.py:56
msgid "Reveal Selected"
msgstr ""
#: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167
#: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0
msgid "Actions"
msgstr ""
#: qt/result_window.py:58 cocoa/en.lproj/Localizable.strings:0
msgid "Show Dupes Only"
msgstr ""
#: qt/result_window.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Show Delta Values"
msgstr ""
#: qt/result_window.py:60
msgid "Send Marked to Recycle Bin..."
msgstr ""
#: qt/result_window.py:61 cocoa/en.lproj/Localizable.strings:0
msgid "Move Marked to..."
msgstr ""
#: qt/result_window.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Copy Marked to..."
msgstr ""
#: qt/result_window.py:63 cocoa/en.lproj/Localizable.strings:0
msgid "Remove Marked from Results"
msgstr ""
#: qt/result_window.py:64 cocoa/en.lproj/Localizable.strings:0
msgid "Re-Prioritize Results..."
msgstr ""
#: qt/result_window.py:67 cocoa/en.lproj/Localizable.strings:0
msgid "Remove Selected from Results"
msgstr ""
#: qt/result_window.py:71 cocoa/en.lproj/Localizable.strings:0
msgid "Add Selected to Ignore List"
msgstr ""
#: qt/result_window.py:75 cocoa/en.lproj/Localizable.strings:0
msgid "Make Selected into Reference"
msgstr ""
#: qt/result_window.py:77 cocoa/en.lproj/Localizable.strings:0
msgid "Open Selected with Default Application"
msgstr ""
#: qt/result_window.py:80
msgid "Open Containing Folder of Selected"
msgstr ""
#: qt/result_window.py:82 cocoa/en.lproj/Localizable.strings:0
msgid "Rename Selected"
msgstr ""
#: qt/result_window.py:83 cocoa/en.lproj/Localizable.strings:0
msgid "Mark All"
msgstr ""
#: qt/result_window.py:84 cocoa/en.lproj/Localizable.strings:0
msgid "Mark None"
msgstr ""
#: qt/result_window.py:85 cocoa/en.lproj/Localizable.strings:0
msgid "Invert Marking"
msgstr ""
#: qt/result_window.py:86 cocoa/en.lproj/Localizable.strings:0
msgid "Mark Selected"
msgstr ""
#: qt/result_window.py:87
msgid "Export To HTML"
msgstr ""
#: qt/result_window.py:88
msgid "Export To CSV"
msgstr ""
#: qt/result_window.py:89 cocoa/en.lproj/Localizable.strings:0
msgid "Save Results..."
msgstr ""
#: qt/result_window.py:90 cocoa/en.lproj/Localizable.strings:0
msgid "Invoke Custom Command"
msgstr ""
#: qt/result_window.py:102
msgid "Mark"
msgstr ""
#: qt/result_window.py:106 cocoa/en.lproj/Localizable.strings:0
msgid "Columns"
msgstr ""
#: qt/result_window.py:163
msgid "Reset to Defaults"
msgstr ""
#: qt/result_window.py:185
msgid "{} Results"
msgstr ""
#: qt/result_window.py:193 cocoa/en.lproj/Localizable.strings:0
msgid "Dupes Only"
msgstr ""
#: qt/result_window.py:194
msgid "Delta Values"
msgstr ""
#: qt/result_window.py:310 cocoa/en.lproj/Localizable.strings:0
msgid "Select a file to save your results to"
msgstr ""
#: qt/se/preferences_dialog.py:41
msgid "Ignore files smaller than"
msgstr ""
#: qt/se/preferences_dialog.py:52 cocoa/en.lproj/Localizable.strings:0
msgid "KB"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "%@ Results"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Action"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Add New Folder..."
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Advanced"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Automatically check for updates"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Basic"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Bring All to Front"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Check for update..."
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Close Window"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Copy"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Custom command (arguments: %d for dupe, %r for ref):"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Cut"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Delta"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details of Selected File"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details Panel"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Directories"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Preferences"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Results"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Website"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Edit"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Export Results to CSV"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Export Results to XHTML"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Fewer results"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Filter"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Filter hardness:"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Filter Results..."
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Folder Selection Window"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Font Size:"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Hide dupeGuru"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Hide Others"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Ignore files smaller than:"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Load from file..."
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Minimize"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Mode"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "More results"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Ok"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Paste"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Preferences..."
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Quick Look"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Quit dupeGuru"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reset to Default"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reset To Defaults"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reveal"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reveal Selected in Finder"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Select All"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Send Marked to Trash..."
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Services"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Show All"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Start Duplicate Scan"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "The name '%@' already exists."
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Window"
msgstr ""
#: cocoa/en.lproj/Localizable.strings:0
msgid "Zoom"
msgstr ""
#: qt\app.py:158
msgid "Exclusion Filters"
msgstr ""
#: qt\directories_dialog.py:91
msgid "Scan Results"
msgstr ""
#: qt\directories_dialog.py:95
msgid "Load Directories..."
msgstr ""
#: qt\directories_dialog.py:96
msgid "Save Directories..."
msgstr ""
#: qt\directories_dialog.py:337
msgid "Select a directories file to load"
msgstr ""
#: qt\directories_dialog.py:338
msgid "dupeGuru Results (*.dupegurudirs)"
msgstr ""
#: qt\directories_dialog.py:347
msgid "Select a file to save your directories to"
msgstr ""
#: qt\directories_dialog.py:348
msgid "dupeGuru Directories (*.dupegurudirs)"
msgstr ""
#: qt\exclude_list_dialog.py:44
msgid "Add"
msgstr ""
#: qt\exclude_list_dialog.py:46
msgid "Restore defaults"
msgstr ""
#: qt\exclude_list_dialog.py:47
msgid "Test string"
msgstr ""
#: qt\exclude_list_dialog.py:83
msgid "Type a python regular expression here..."
msgstr ""
#: qt\exclude_list_dialog.py:85
msgid "Type a file system path or filename here..."
msgstr ""
#: qt\exclude_list_dialog.py:152
msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happen to match one of the regular expressions.<br>For each file collected two tests are perfomed on each of them to determine whether or not to filter them out:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with no path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the test string feature by pasting a fake path in it:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
#: qt\exclude_list_table.py:36
msgid "Compilation error: "
msgstr ""
#: qt\pe\image_viewer.py:56
msgid "Increase zoom"
msgstr ""
#: qt\pe\image_viewer.py:66
msgid "Decrease zoom"
msgstr ""
#: qt\pe\image_viewer.py:71
msgid "Ctrl+/"
msgstr ""
#: qt\pe\image_viewer.py:76
msgid "Normal size"
msgstr ""
#: qt\pe\image_viewer.py:81
msgid "Ctrl+*"
msgstr ""
#: qt\pe\image_viewer.py:86
msgid "Best fit"
msgstr ""
#: qt\pe\preferences_dialog.py:49
msgid "Picture cache mode:"
msgstr ""
#: qt\pe\preferences_dialog.py:56
msgid "Override theme icons in viewer toolbar"
msgstr ""
#: qt\pe\preferences_dialog.py:58
msgid ""
"Use our own internal icons instead of those provided by the theme engine"
msgstr ""
#: qt\pe\preferences_dialog.py:66
msgid "Show scrollbars in image viewers"
msgstr ""
#: qt\pe\preferences_dialog.py:68
msgid ""
"When the image displayed doesn't fit the viewport, show scrollbars to span "
"the view around"
msgstr ""
#: qt\preferences_dialog.py:156
msgid "Use default position for tab bar (requires restart)"
msgstr ""
#: qt\preferences_dialog.py:158
msgid ""
"Place the tab bar below the main menu instead of next to it\n"
"On MacOS, the tab bar will fill up the window's width instead."
msgstr ""
#: qt\preferences_dialog.py:172
msgid "Use bold font for references"
msgstr ""
#: qt\preferences_dialog.py:176
msgid "Reference foreground color:"
msgstr ""
#: qt\preferences_dialog.py:179
msgid "Reference background color:"
msgstr ""
#: qt\preferences_dialog.py:182 qt\preferences_dialog.py:216
msgid "Delta foreground color:"
msgstr ""
#: qt\preferences_dialog.py:195
msgid "Show the title bar and can be docked"
msgstr ""
#: qt\preferences_dialog.py:197
msgid ""
"While the title bar is hidden, use the modifier key to drag the floating "
"window around"
msgstr ""
#: qt\preferences_dialog.py:199
msgid "The title bar can only be disabled while the window is docked"
msgstr ""
#: qt\preferences_dialog.py:202
msgid "Vertical title bar"
msgstr ""
#: qt\preferences_dialog.py:204
msgid ""
"Change the title bar from horizontal on top, to vertical on the left side"
msgstr ""
#: qt\tabbed_window.py:44
msgid "Show tab bar"
msgstr ""
#: qt\exclude_list_dialog.py:152
msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happens to match one of the selected regular expressions.<br>For each file collected, two tests are performed to determine whether or not to completely ignore it:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with at least one path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the \"test string\" button after pasting a fake path in the test field:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path or filename tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
#: qt\app.py:256
msgid "Results"
msgstr ""
#: qt\preferences_dialog.py:150
msgid "General Interface"
msgstr ""
#: qt\preferences_dialog.py:176
msgid "Result Table"
msgstr ""
#: qt\preferences_dialog.py:205
msgid "Details Window"
msgstr ""
#: qt\preferences_dialog.py:285
msgid "General"
msgstr ""
#: qt\preferences_dialog.py:286
msgid "Display"
msgstr ""

View File

@@ -4,114 +4,114 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
#: core/gui/ignore_list_table.py:18 core/gui/ignore_list_table.py:19 #: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core/gui/problem_table.py:17 #: core\gui\problem_table.py:18
msgid "File Path" msgid "File Path"
msgstr "" msgstr ""
#: core/gui/problem_table.py:18 #: core\gui\problem_table.py:19
msgid "Error Message" msgid "Error Message"
msgstr "" msgstr ""
#: core/me/prioritize.py:18 #: core\me\prioritize.py:23
msgid "Duration" msgid "Duration"
msgstr "" msgstr ""
#: core/me/prioritize.py:24 core/me/result_table.py:22 #: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate" msgid "Bitrate"
msgstr "" msgstr ""
#: core/me/prioritize.py:30 #: core\me\prioritize.py:37
msgid "Samplerate" msgid "Samplerate"
msgstr "" msgstr ""
#: core/me/result_table.py:18 core/pe/result_table.py:18 core/prioritize.py:88 #: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
#: core/se/result_table.py:18 #: core\se\result_table.py:19
msgid "Filename" msgid "Filename"
msgstr "" msgstr ""
#: core/me/result_table.py:19 core/pe/result_table.py:19 core/prioritize.py:72 #: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core/se/result_table.py:19 #: core\se\result_table.py:20
msgid "Folder" msgid "Folder"
msgstr "" msgstr ""
#: core/me/result_table.py:20 #: core\me\result_table.py:21
msgid "Size (MB)" msgid "Size (MB)"
msgstr "" msgstr ""
#: core/me/result_table.py:21 #: core\me\result_table.py:22
msgid "Time" msgid "Time"
msgstr "" msgstr ""
#: core/me/result_table.py:23 #: core\me\result_table.py:24
msgid "Sample Rate" msgid "Sample Rate"
msgstr "" msgstr ""
#: core/me/result_table.py:24 core/pe/result_table.py:21 core/prioritize.py:63 #: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core/se/result_table.py:21 #: core\se\result_table.py:22
msgid "Kind" msgid "Kind"
msgstr "" msgstr ""
#: core/me/result_table.py:25 core/pe/result_table.py:24 #: core\me\result_table.py:26 core\pe\result_table.py:25
#: core/prioritize.py:153 core/se/result_table.py:22 #: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification" msgid "Modification"
msgstr "" msgstr ""
#: core/me/result_table.py:26 #: core\me\result_table.py:27
msgid "Title" msgid "Title"
msgstr "" msgstr ""
#: core/me/result_table.py:27 #: core\me\result_table.py:28
msgid "Artist" msgid "Artist"
msgstr "" msgstr ""
#: core/me/result_table.py:28 #: core\me\result_table.py:29
msgid "Album" msgid "Album"
msgstr "" msgstr ""
#: core/me/result_table.py:29 #: core\me\result_table.py:30
msgid "Genre" msgid "Genre"
msgstr "" msgstr ""
#: core/me/result_table.py:30 #: core\me\result_table.py:31
msgid "Year" msgid "Year"
msgstr "" msgstr ""
#: core/me/result_table.py:31 #: core\me\result_table.py:32
msgid "Track Number" msgid "Track Number"
msgstr "" msgstr ""
#: core/me/result_table.py:32 #: core\me\result_table.py:33
msgid "Comment" msgid "Comment"
msgstr "" msgstr ""
#: core/me/result_table.py:33 core/pe/result_table.py:25 #: core\me\result_table.py:34 core\pe\result_table.py:26
#: core/se/result_table.py:23 #: core\se\result_table.py:24
msgid "Match %" msgid "Match %"
msgstr "" msgstr ""
#: core/me/result_table.py:34 core/se/result_table.py:24 #: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used" msgid "Words Used"
msgstr "" msgstr ""
#: core/me/result_table.py:35 core/pe/result_table.py:26 #: core\me\result_table.py:36 core\pe\result_table.py:27
#: core/se/result_table.py:25 #: core\se\result_table.py:26
msgid "Dupe Count" msgid "Dupe Count"
msgstr "" msgstr ""
#: core/pe/prioritize.py:18 core/pe/result_table.py:22 #: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions" msgid "Dimensions"
msgstr "" msgstr ""
#: core/pe/result_table.py:20 core/se/result_table.py:20 #: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)" msgid "Size (KB)"
msgstr "" msgstr ""
#: core/pe/result_table.py:23 #: core\pe\result_table.py:24
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "" msgstr ""
#: core/prioritize.py:147 #: core\prioritize.py:156
msgid "Size" msgid "Size"
msgstr "" msgstr ""

View File

@@ -4,235 +4,235 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
#: core/app.py:40 #: core\app.py:42
msgid "There are no marked duplicates. Nothing has been done." msgid "There are no marked duplicates. Nothing has been done."
msgstr "" msgstr ""
#: core/app.py:41 #: core\app.py:43
msgid "There are no selected duplicates. Nothing has been done." msgid "There are no selected duplicates. Nothing has been done."
msgstr "" msgstr ""
#: core/app.py:42 #: core\app.py:44
msgid "You're about to open many files at once. Depending on what those files are opened with, doing so can create quite a mess. Continue?" msgid "You're about to open many files at once. Depending on what those files are opened with, doing so can create quite a mess. Continue?"
msgstr "" msgstr ""
#: core/app.py:65 #: core\app.py:71
msgid "Scanning for duplicates" msgid "Scanning for duplicates"
msgstr "" msgstr ""
#: core/app.py:66 #: core\app.py:72
msgid "Loading" msgid "Loading"
msgstr "" msgstr ""
#: core/app.py:67 #: core\app.py:73
msgid "Moving" msgid "Moving"
msgstr "" msgstr ""
#: core/app.py:68 #: core\app.py:74
msgid "Copying" msgid "Copying"
msgstr "" msgstr ""
#: core/app.py:69 #: core\app.py:75
msgid "Sending to Trash" msgid "Sending to Trash"
msgstr "" msgstr ""
#: core/app.py:279 #: core\app.py:290
msgid "A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again." msgid "A previous action is still hanging in there. You can't start a new one yet. Wait a few seconds, then try again."
msgstr "" msgstr ""
#: core/app.py:289 #: core\app.py:300
msgid "No duplicates found." msgid "No duplicates found."
msgstr "" msgstr ""
#: core/app.py:304 #: core\app.py:315
msgid "All marked files were copied successfully." msgid "All marked files were copied successfully."
msgstr "" msgstr ""
#: core/app.py:305 #: core\app.py:316
msgid "All marked files were moved successfully." msgid "All marked files were moved successfully."
msgstr "" msgstr ""
#: core/app.py:306 #: core\app.py:317
msgid "All marked files were successfully sent to Trash." msgid "All marked files were successfully sent to Trash."
msgstr "" msgstr ""
#: core/app.py:312 #: core\app.py:323
msgid "Could not load file: {}" msgid "Could not load file: {}"
msgstr "" msgstr ""
#: core/app.py:368 #: core\app.py:379
msgid "'{}' already is in the list." msgid "'{}' already is in the list."
msgstr "" msgstr ""
#: core/app.py:370 #: core\app.py:381
msgid "'{}' does not exist." msgid "'{}' does not exist."
msgstr "" msgstr ""
#: core/app.py:379 #: core\app.py:389
msgid "All selected %d matches are going to be ignored in all subsequent scans. Continue?" msgid "All selected %d matches are going to be ignored in all subsequent scans. Continue?"
msgstr "" msgstr ""
#: core/app.py:450 #: core\app.py:463
msgid "copy" msgid "Select a directory to copy marked files to"
msgstr "" msgstr ""
#: core/app.py:450 #: core\app.py:465
msgid "move" msgid "Select a directory to move marked files to"
msgstr "" msgstr ""
#: core/app.py:451 #: core\app.py:504
msgid "Select a directory to {} marked files to"
msgstr ""
#: core/app.py:490
msgid "Select a destination for your exported CSV" msgid "Select a destination for your exported CSV"
msgstr "" msgstr ""
#: core/app.py:496 core/app.py:742 #: core\app.py:510 core\app.py:764 core\app.py:774
msgid "Couldn't write to file: {}" msgid "Couldn't write to file: {}"
msgstr "" msgstr ""
#: core/app.py:518 #: core\app.py:533
msgid "You have no custom command set up. Set it up in your preferences." msgid "You have no custom command set up. Set it up in your preferences."
msgstr "" msgstr ""
#: core/app.py:672 core/app.py:685 #: core\app.py:691 core\app.py:703
msgid "You are about to remove %d files from results. Continue?" msgid "You are about to remove %d files from results. Continue?"
msgstr "" msgstr ""
#: core/app.py:719 #: core\app.py:739
msgid "{} duplicate groups were changed by the re-prioritization." msgid "{} duplicate groups were changed by the re-prioritization."
msgstr "" msgstr ""
#: core/app.py:751 #: core\app.py:783
msgid "The selected directories contain no scannable file." msgid "The selected directories contain no scannable file."
msgstr "" msgstr ""
#: core/app.py:762 #: core\app.py:796
msgid "Collecting files to scan" msgid "Collecting files to scan"
msgstr "" msgstr ""
#: core/app.py:810 #: core\app.py:843
msgid "%s (%d discarded)" msgid "%s (%d discarded)"
msgstr "" msgstr ""
#: core/engine.py:222 core/engine.py:262 #: core\engine.py:251 core\engine.py:294
msgid "0 matches found" msgid "0 matches found"
msgstr "" msgstr ""
#: core/engine.py:240 core/engine.py:270 #: core\engine.py:269 core\engine.py:306
msgid "%d matches found" msgid "%d matches found"
msgstr "" msgstr ""
#: core/gui/deletion_options.py:69 #: core\gui\deletion_options.py:71
msgid "You are sending {} file(s) to the Trash." msgid "You are sending {} file(s) to the Trash."
msgstr "" msgstr ""
#: core/gui/ignore_list_dialog.py:24 #: core\gui\exclude_list_table.py:14
msgid "Regular Expressions"
msgstr ""
#: core\gui\ignore_list_dialog.py:25
msgid "Do you really want to remove all %d items from the ignore list?" msgid "Do you really want to remove all %d items from the ignore list?"
msgstr "" msgstr ""
#: core/me/scanner.py:19 core/se/scanner.py:15 #: core\me\scanner.py:20 core\se\scanner.py:16
msgid "Filename" msgid "Filename"
msgstr "" msgstr ""
#: core/me/scanner.py:20 #: core\me\scanner.py:21
msgid "Filename - Fields" msgid "Filename - Fields"
msgstr "" msgstr ""
#: core/me/scanner.py:21 #: core\me\scanner.py:22
msgid "Filename - Fields (No Order)" msgid "Filename - Fields (No Order)"
msgstr "" msgstr ""
#: core/me/scanner.py:22 #: core\me\scanner.py:23
msgid "Tags" msgid "Tags"
msgstr "" msgstr ""
#: core/me/scanner.py:23 core/pe/scanner.py:20 core/se/scanner.py:16 #: core\me\scanner.py:24 core\pe\scanner.py:21 core\se\scanner.py:17
msgid "Contents" msgid "Contents"
msgstr "" msgstr ""
#: core/pe/matchblock.py:61 #: core\pe\matchblock.py:72
msgid "Analyzed %d/%d pictures" msgid "Analyzed %d/%d pictures"
msgstr "" msgstr ""
#: core/pe/matchblock.py:156 #: core\pe\matchblock.py:177
msgid "Performed %d/%d chunk matches" msgid "Performed %d/%d chunk matches"
msgstr "" msgstr ""
#: core/pe/matchblock.py:161 #: core\pe\matchblock.py:185
msgid "Preparing for matching" msgid "Preparing for matching"
msgstr "" msgstr ""
#: core/pe/matchblock.py:206 #: core\pe\matchblock.py:234
msgid "Verified %d/%d matches" msgid "Verified %d/%d matches"
msgstr "" msgstr ""
#: core/pe/matchexif.py:18 #: core\pe\matchexif.py:19
msgid "Read EXIF of %d/%d pictures" msgid "Read EXIF of %d/%d pictures"
msgstr "" msgstr ""
#: core/pe/scanner.py:21 #: core\pe\scanner.py:22
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "" msgstr ""
#: core/prioritize.py:68 #: core\prioritize.py:70
msgid "None" msgid "None"
msgstr "" msgstr ""
#: core/prioritize.py:96 #: core\prioritize.py:100
msgid "Ends with number" msgid "Ends with number"
msgstr "" msgstr ""
#: core/prioritize.py:97 #: core\prioritize.py:101
msgid "Doesn't end with number" msgid "Doesn't end with number"
msgstr "" msgstr ""
#: core/prioritize.py:98 #: core\prioritize.py:102
msgid "Longest" msgid "Longest"
msgstr "" msgstr ""
#: core/prioritize.py:99 #: core\prioritize.py:103
msgid "Shortest" msgid "Shortest"
msgstr "" msgstr ""
#: core/prioritize.py:132 #: core\prioritize.py:140
msgid "Highest" msgid "Highest"
msgstr "" msgstr ""
#: core/prioritize.py:132 #: core\prioritize.py:140
msgid "Lowest" msgid "Lowest"
msgstr "" msgstr ""
#: core/prioritize.py:159 #: core\prioritize.py:169
msgid "Newest" msgid "Newest"
msgstr "" msgstr ""
#: core/prioritize.py:159 #: core\prioritize.py:169
msgid "Oldest" msgid "Oldest"
msgstr "" msgstr ""
#: core/results.py:129 #: core\results.py:134
msgid "%d / %d (%s / %s) duplicates marked." msgid "%d / %d (%s / %s) duplicates marked."
msgstr "" msgstr ""
#: core/results.py:136 #: core\results.py:141
msgid " filter: %s" msgid " filter: %s"
msgstr "" msgstr ""
#: core/scanner.py:77 #: core\scanner.py:85
msgid "Read size of %d/%d files" msgid "Read size of %d/%d files"
msgstr "" msgstr ""
#: core/scanner.py:101 #: core\scanner.py:109
msgid "Read metadata of %d/%d files" msgid "Read metadata of %d/%d files"
msgstr "" msgstr ""
#: core/scanner.py:139 #: core\scanner.py:147
msgid "Almost done! Fiddling with results..." msgid "Almost done! Fiddling with results..."
msgstr "" msgstr ""
#: core/se/scanner.py:17 #: core\se\scanner.py:18
msgid "Folders" msgid "Folders"
msgstr "" msgstr ""

View File

@@ -1,122 +1,123 @@
# Translators: # Translators:
# Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2013-11-20 11:53+0000\n" "Language-Team: Czech (https://www.transifex.com/voltaicideas/teams/116153/cs/)\n"
"Last-Translator: hsoft <hsoft@hardcoded.net>\n" "Language: cs\n"
"Language-Team: Czech (http://www.transifex.com/projects/p/dupeguru/language/cs/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: cs\n" "Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
#: core/gui/ignore_list_table.py:18 core/gui/ignore_list_table.py:19 #: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core/gui/problem_table.py:17 #: core\gui\problem_table.py:18
msgid "File Path" msgid "File Path"
msgstr "Cesta k souboru" msgstr "Cesta k souboru"
#: core/gui/problem_table.py:18 #: core\gui\problem_table.py:19
msgid "Error Message" msgid "Error Message"
msgstr "Chybové hlášení" msgstr "Chybové hlášení"
#: core/me/result_table.py:24 core/pe/result_table.py:21 core/prioritize.py:63 #: core\me\prioritize.py:23
#: core/se/result_table.py:21
msgid "Kind"
msgstr "Typ"
#: core/me/result_table.py:19 core/pe/result_table.py:19 core/prioritize.py:72
#: core/se/result_table.py:19
msgid "Folder"
msgstr "Složka"
#: core/me/result_table.py:18 core/pe/result_table.py:18 core/prioritize.py:88
#: core/se/result_table.py:18
msgid "Filename"
msgstr "Název souboru"
#: core/prioritize.py:147
msgid "Size"
msgstr "Velikost"
#: core/me/result_table.py:25 core/pe/result_table.py:24
#: core/prioritize.py:153 core/se/result_table.py:22
msgid "Modification"
msgstr "Změna"
#: core/me/prioritize.py:18
msgid "Duration" msgid "Duration"
msgstr "" msgstr "Doba trvání"
#: core/me/prioritize.py:24 core/me/result_table.py:22 #: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate" msgid "Bitrate"
msgstr "Bitrate" msgstr "Bitrate"
#: core/me/prioritize.py:30 #: core\me\prioritize.py:37
msgid "Samplerate" msgid "Samplerate"
msgstr "" msgstr "Vzorkovací frekvence"
#: core/me/result_table.py:20 #: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
#: core\se\result_table.py:19
msgid "Filename"
msgstr "Název souboru"
#: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core\se\result_table.py:20
msgid "Folder"
msgstr "Složka"
#: core\me\result_table.py:21
msgid "Size (MB)" msgid "Size (MB)"
msgstr "Velikost (MB)" msgstr "Velikost (MB)"
#: core/me/result_table.py:21 #: core\me\result_table.py:22
msgid "Time" msgid "Time"
msgstr "Čas" msgstr "Čas"
#: core/me/result_table.py:23 #: core\me\result_table.py:24
msgid "Sample Rate" msgid "Sample Rate"
msgstr "Vzorkovací frekvence" msgstr "Vzorkovací frekvence"
#: core/me/result_table.py:26 #: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core\se\result_table.py:22
msgid "Kind"
msgstr "Typ"
#: core\me\result_table.py:26 core\pe\result_table.py:25
#: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification"
msgstr "Změna"
#: core\me\result_table.py:27
msgid "Title" msgid "Title"
msgstr "Titul" msgstr "Titul"
#: core/me/result_table.py:27 #: core\me\result_table.py:28
msgid "Artist" msgid "Artist"
msgstr "Umělec" msgstr "Umělec"
#: core/me/result_table.py:28 #: core\me\result_table.py:29
msgid "Album" msgid "Album"
msgstr "Album" msgstr "Album"
#: core/me/result_table.py:29 #: core\me\result_table.py:30
msgid "Genre" msgid "Genre"
msgstr "Žánr" msgstr "Žánr"
#: core/me/result_table.py:30 #: core\me\result_table.py:31
msgid "Year" msgid "Year"
msgstr "Rok" msgstr "Rok"
#: core/me/result_table.py:31 #: core\me\result_table.py:32
msgid "Track Number" msgid "Track Number"
msgstr "Číslo stopy" msgstr "Číslo stopy"
#: core/me/result_table.py:32 #: core\me\result_table.py:33
msgid "Comment" msgid "Comment"
msgstr "Komentář" msgstr "Komentář"
#: core/me/result_table.py:33 core/pe/result_table.py:25 #: core\me\result_table.py:34 core\pe\result_table.py:26
#: core/se/result_table.py:23 #: core\se\result_table.py:24
msgid "Match %" msgid "Match %"
msgstr "Shoda %" msgstr "Shoda %"
#: core/me/result_table.py:34 core/se/result_table.py:24 #: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used" msgid "Words Used"
msgstr "Slov" msgstr "Slov"
#: core/me/result_table.py:35 core/pe/result_table.py:26 #: core\me\result_table.py:36 core\pe\result_table.py:27
#: core/se/result_table.py:25 #: core\se\result_table.py:26
msgid "Dupe Count" msgid "Dupe Count"
msgstr "Počet kopií" msgstr "Počet kopií"
#: core/pe/prioritize.py:18 core/pe/result_table.py:22 #: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions" msgid "Dimensions"
msgstr "Rozměry" msgstr "Rozměry"
#: core/pe/result_table.py:20 core/se/result_table.py:20 #: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)" msgid "Size (KB)"
msgstr "Velikost (KB)" msgstr "Velikost (KB)"
#: core/pe/result_table.py:23 #: core\pe\result_table.py:24
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "" msgstr "Časové razítko EXIF"
#: core\prioritize.py:156
msgid "Size"
msgstr "Velikost"

View File

@@ -1,50 +1,53 @@
# Translators: # Translators:
# Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2013-12-07 15:22+0000\n" "Language-Team: Czech (https://www.transifex.com/voltaicideas/teams/116153/cs/)\n"
"Last-Translator: hsoft <hsoft@hardcoded.net>\n" "Language: cs\n"
"Language-Team: Czech (http://www.transifex.com/projects/p/dupeguru/language/cs/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: cs\n" "Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
#: core/app.py:40 #: core\app.py:42
msgid "There are no marked duplicates. Nothing has been done." msgid "There are no marked duplicates. Nothing has been done."
msgstr "" msgstr "Neexistují žádné označené duplikáty. Nic se nestalo."
#: core/app.py:41 #: core\app.py:43
msgid "There are no selected duplicates. Nothing has been done." msgid "There are no selected duplicates. Nothing has been done."
msgstr "" msgstr "Nejsou k dispozici žádné vybrané duplikáty. Nic se nestalo."
#: core/app.py:42 #: core\app.py:44
msgid "" msgid ""
"You're about to open many files at once. Depending on what those files are " "You're about to open many files at once. Depending on what those files are "
"opened with, doing so can create quite a mess. Continue?" "opened with, doing so can create quite a mess. Continue?"
msgstr "" msgstr ""
"Chystáte se otevřít více souborů najednou. V závislosti na tom, s čím jsou "
"tyto soubory otevřeny, to může způsobit docela nepořádek. Pokračovat?"
#: core/app.py:65 #: core\app.py:71
msgid "Scanning for duplicates" msgid "Scanning for duplicates"
msgstr "Vyhledávám duplicity" msgstr "Vyhledávám duplicity"
#: core/app.py:66 #: core\app.py:72
msgid "Loading" msgid "Loading"
msgstr "Nahrávám" msgstr "Nahrávám"
#: core/app.py:67 #: core\app.py:73
msgid "Moving" msgid "Moving"
msgstr "Přesouvám" msgstr "Přesouvám"
#: core/app.py:68 #: core\app.py:74
msgid "Copying" msgid "Copying"
msgstr "Kopíruji" msgstr "Kopíruji"
#: core/app.py:69 #: core\app.py:75
msgid "Sending to Trash" msgid "Sending to Trash"
msgstr "Vyhazuji do koše" msgstr "Vyhazuji do koše"
#: core/app.py:279 #: core\app.py:308
msgid "" msgid ""
"A previous action is still hanging in there. You can't start a new one yet. " "A previous action is still hanging in there. You can't start a new one yet. "
"Wait a few seconds, then try again." "Wait a few seconds, then try again."
@@ -52,31 +55,35 @@ msgstr ""
"Předchozí akce stále nebyla ukončena. Novou zatím nemůžete spustit. Počkejte" "Předchozí akce stále nebyla ukončena. Novou zatím nemůžete spustit. Počkejte"
" pár sekund a zkuste to znovu." " pár sekund a zkuste to znovu."
#: core/app.py:289 #: core\app.py:318
msgid "No duplicates found." msgid "No duplicates found."
msgstr "Nebyli nalezeny žádné duplicity." msgstr "Nebyli nalezeny žádné duplicity."
#: core/app.py:304 #: core\app.py:333
msgid "All marked files were copied successfully." msgid "All marked files were copied successfully."
msgstr "" msgstr "Všechny označené soubory byly úspěšně zkopírovány."
#: core/app.py:305 #: core\app.py:334
msgid "All marked files were moved successfully." msgid "All marked files were moved successfully."
msgstr "" msgstr "Všechny označené soubory byly úspěšně přesunuty."
#: core/app.py:306 #: core\app.py:335
msgid "All marked files were successfully sent to Trash." msgid "All marked files were successfully sent to Trash."
msgstr "" msgstr "Všechny označené soubory byly úspěšně odeslány do koše."
#: core/app.py:368 #: core\app.py:343
msgid "Could not load file: {}"
msgstr "Soubor se nepodařilo načíst: {}"
#: core\app.py:399
msgid "'{}' already is in the list." msgid "'{}' already is in the list."
msgstr "" msgstr "'{}' již je v seznamu."
#: core/app.py:370 #: core\app.py:401
msgid "'{}' does not exist." msgid "'{}' does not exist."
msgstr "" msgstr "'{}' neexistuje."
#: core/app.py:379 #: core\app.py:410
msgid "" msgid ""
"All selected %d matches are going to be ignored in all subsequent scans. " "All selected %d matches are going to be ignored in all subsequent scans. "
"Continue?" "Continue?"
@@ -84,186 +91,167 @@ msgstr ""
"Všech %d vybraných shod bude v následujících hledáních ignorováno. " "Všech %d vybraných shod bude v následujících hledáních ignorováno. "
"Pokračovat?" "Pokračovat?"
#: core/app.py:450 #: core\app.py:486
msgid "copy" msgid "Select a directory to copy marked files to"
msgstr "" msgstr "Vyberte adresář, do kterého chcete zkopírovat označené soubory"
#: core/app.py:450 #: core\app.py:487
msgid "move" msgid "Select a directory to move marked files to"
msgstr "" msgstr "Vyberte adresář, kam chcete přesunout označené soubory"
#: core/app.py:451 #: core\app.py:527
msgid "Select a directory to {} marked files to"
msgstr ""
#: core/app.py:490
msgid "Select a destination for your exported CSV" msgid "Select a destination for your exported CSV"
msgstr "" msgstr "Vyberte cíl pro exportovaný soubor CSV"
#: core/app.py:518 #: core\app.py:534 core\app.py:801 core\app.py:811
msgid "Couldn't write to file: {}"
msgstr "Nelze zapisovat do souboru: {}"
#: core\app.py:559
msgid "You have no custom command set up. Set it up in your preferences." msgid "You have no custom command set up. Set it up in your preferences."
msgstr "" msgstr ""
"Nedefinoval jste žádný uživatelský příkaz. Nadefinujete ho v předvolbách." "Nedefinoval jste žádný uživatelský příkaz. Nadefinujete ho v předvolbách."
#: core/app.py:672 core/app.py:685 #: core\app.py:727 core\app.py:740
msgid "You are about to remove %d files from results. Continue?" msgid "You are about to remove %d files from results. Continue?"
msgstr "Chystáte se z výsledků odstranit %d souborů. Pokračovat?" msgstr "Chystáte se z výsledků odstranit %d souborů. Pokračovat?"
#: core/app.py:719 #: core\app.py:774
msgid "{} duplicate groups were changed by the re-prioritization." msgid "{} duplicate groups were changed by the re-prioritization."
msgstr "" msgstr "{} duplicitní skupiny byly změněny změně priorit."
#: core/app.py:762 #: core\app.py:821
msgid "Collecting files to scan"
msgstr "Shromažďuji prohlížené soubory"
#: core/app.py:751
msgid "The selected directories contain no scannable file." msgid "The selected directories contain no scannable file."
msgstr "Vybrané adresáře neobsahují žádné soubory vhodné k prohledávání." msgstr "Vybrané adresáře neobsahují žádné soubory vhodné k prohledávání."
#: core/app.py:810 #: core\app.py:835
msgid "Collecting files to scan"
msgstr "Shromažďuji prohlížené soubory"
#: core\app.py:891
msgid "%s (%d discarded)" msgid "%s (%d discarded)"
msgstr "%s (%d vyřazeno)" msgstr "%s (%d vyřazeno)"
#: core/engine.py:222 core/engine.py:262 #: core\engine.py:244 core\engine.py:288
msgid "0 matches found" msgid "0 matches found"
msgstr "Nalezeno 0 shod" msgstr "Nalezeno 0 shod"
#: core/engine.py:240 core/engine.py:270 #: core\engine.py:262 core\engine.py:296
msgid "%d matches found" msgid "%d matches found"
msgstr "Nalezeno %d shod" msgstr "Nalezeno %d shod"
#: core/scanner.py:77 #: core\gui\deletion_options.py:73
msgid "Read size of %d/%d files"
msgstr "Read size of %d/%d files"
#: core/gui/deletion_options.py:69
msgid "You are sending {} file(s) to the Trash." msgid "You are sending {} file(s) to the Trash."
msgstr "" msgstr "Posíláte-{} soubory do koše."
#: core/gui/ignore_list_dialog.py:24 #: core\gui\exclude_list_table.py:15
msgid "Regular Expressions"
msgstr "Regulární výrazy"
#: core\gui\ignore_list_dialog.py:25
msgid "Do you really want to remove all %d items from the ignore list?" msgid "Do you really want to remove all %d items from the ignore list?"
msgstr "Opravdu chcete odstranit všech %d položek ze seznamu výjimek?" msgstr "Opravdu chcete odstranit všech %d položek ze seznamu výjimek?"
#: core/prioritize.py:68 #: core\me\scanner.py:20 core\se\scanner.py:16
msgid "None" msgid "Filename"
msgstr "" msgstr "Název souboru"
#: core/prioritize.py:96 #: core\me\scanner.py:21
msgid "Ends with number" msgid "Filename - Fields"
msgstr "Končí číslem" msgstr "Název souboru - pole"
#: core/prioritize.py:97 #: core\me\scanner.py:22
msgid "Doesn't end with number" msgid "Filename - Fields (No Order)"
msgstr "Nekončí číslem" msgstr "Název souboru - pole (bez objednávky)"
#: core/prioritize.py:98 #: core\me\scanner.py:23
msgid "Longest" msgid "Tags"
msgstr "" msgstr "Tagy"
#: core/prioritize.py:99 #: core\me\scanner.py:24 core\pe\scanner.py:21 core\se\scanner.py:17
msgid "Shortest" msgid "Contents"
msgstr "" msgstr "Obsah"
#: core/prioritize.py:132 #: core\pe\matchblock.py:72
msgid "Highest"
msgstr "Nejvyšší"
#: core/prioritize.py:132
msgid "Lowest"
msgstr "Nejnižší"
#: core/prioritize.py:159
msgid "Newest"
msgstr "Nejnovější"
#: core/prioritize.py:159
msgid "Oldest"
msgstr "Nejstarší"
#: core/results.py:129
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) duplicit označeno."
#: core/results.py:136
msgid " filter: %s"
msgstr " filtr: %s"
#: core/scanner.py:101
msgid "Read metadata of %d/%d files"
msgstr "Načtena metadata %d/%d souborů"
#: core/pe/matchblock.py:61
msgid "Analyzed %d/%d pictures" msgid "Analyzed %d/%d pictures"
msgstr "Analyzováno %d/%d snímků" msgstr "Analyzováno %d/%d snímků"
#: core/pe/matchblock.py:156 #: core\pe\matchblock.py:181
msgid "Performed %d/%d chunk matches" msgid "Performed %d/%d chunk matches"
msgstr "Provedeno %d/%d porovnání bloků" msgstr "Provedeno %d/%d porovnání bloků"
#: core/pe/matchblock.py:161 #: core\pe\matchblock.py:191
msgid "Preparing for matching" msgid "Preparing for matching"
msgstr "Připravuji porovnávání" msgstr "Připravuji porovnávání"
#: core/pe/matchblock.py:206 #: core\pe\matchblock.py:244
msgid "Verified %d/%d matches" msgid "Verified %d/%d matches"
msgstr "Ověřeno %d/%d shod" msgstr "Ověřeno %d/%d shod"
#: core/pe/matchexif.py:18 #: core\pe\matchexif.py:19
msgid "Read EXIF of %d/%d pictures" msgid "Read EXIF of %d/%d pictures"
msgstr "" msgstr "Přečetl EXIF %d/%d obrázků"
#: core/app.py:312 #: core\pe\scanner.py:22
msgid "Could not load file: {}"
msgstr ""
#: core/app.py:496 core/app.py:742
msgid "Couldn't write to file: {}"
msgstr ""
#: core/me/scanner.py:19 core/se/scanner.py:15
msgid "Filename"
msgstr ""
#: core/me/scanner.py:20
msgid "Filename - Fields"
msgstr ""
#: core/me/scanner.py:21
msgid "Filename - Fields (No Order)"
msgstr ""
#: core/me/scanner.py:22
msgid "Tags"
msgstr ""
#: core/me/scanner.py:23 core/pe/scanner.py:20 core/se/scanner.py:16
msgid "Contents"
msgstr ""
#: core/pe/scanner.py:21
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "" msgstr "Časové razítko EXIF"
#: core/scanner.py:139 #: core\prioritize.py:70
msgid "None"
msgstr "Zádný"
#: core\prioritize.py:100
msgid "Ends with number"
msgstr "Končí číslem"
#: core\prioritize.py:101
msgid "Doesn't end with number"
msgstr "Nekončí číslem"
#: core\prioritize.py:102
msgid "Longest"
msgstr "Nejdelší"
#: core\prioritize.py:103
msgid "Shortest"
msgstr "Nejkratší"
#: core\prioritize.py:140
msgid "Highest"
msgstr "Nejvyšší"
#: core\prioritize.py:140
msgid "Lowest"
msgstr "Nejnižší"
#: core\prioritize.py:169
msgid "Newest"
msgstr "Nejnovější"
#: core\prioritize.py:169
msgid "Oldest"
msgstr "Nejstarší"
#: core\results.py:142
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) duplicit označeno."
#: core\results.py:149
msgid " filter: %s"
msgstr " filtr: %s"
#: core\scanner.py:85
msgid "Read size of %d/%d files"
msgstr "Read size of %d/%d files"
#: core\scanner.py:109
msgid "Read metadata of %d/%d files"
msgstr "Načtena metadata %d/%d souborů"
#: core\scanner.py:147
msgid "Almost done! Fiddling with results..." msgid "Almost done! Fiddling with results..."
msgstr "" msgstr "Skoro hotovo! Fidlování s výsledky..."
#: core/se/scanner.py:17 #: core\se\scanner.py:18
msgid "Folders" msgid "Folders"
msgstr "" msgstr "Složky"
#~ msgid "Sending files to the recycle bin"
#~ msgstr ""
#~ msgid "Grouped %d/%d matches"
#~ msgstr "Grouped %d/%d matches"
#~ msgid "Removing false matches"
#~ msgstr "Odstraňuji falešné shody"
#~ msgid "Processed %d/%d matches against the ignore list"
#~ msgstr "Zpracováno %d/%d shod se seznamem výjimek"
#~ msgid "Doing group prioritization"
#~ msgstr "Přiřazuji prioritu skupině"

File diff suppressed because it is too large Load Diff

View File

@@ -1,123 +1,122 @@
# Translators: # Translators:
# Harakiri1337, 2014 # Andrew Senetar <arsenetar@gmail.com>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Andrew Senetar <arsenetar@gmail.com>, 2021\n"
"PO-Revision-Date: 2014-06-03 21:56+0000\n" "Language-Team: German (https://www.transifex.com/voltaicideas/teams/116153/de/)\n"
"Last-Translator: Harakiri1337\n" "Language: de\n"
"Language-Team: German (http://www.transifex.com/projects/p/dupeguru/language/de/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: core/gui/ignore_list_table.py:18 core/gui/ignore_list_table.py:19 #: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core/gui/problem_table.py:17 #: core\gui\problem_table.py:18
msgid "File Path" msgid "File Path"
msgstr "Dateipfad" msgstr "Dateipfad"
#: core/gui/problem_table.py:18 #: core\gui\problem_table.py:19
msgid "Error Message" msgid "Error Message"
msgstr "Fehlermeldung" msgstr "Fehlermeldung"
#: core/me/result_table.py:24 core/pe/result_table.py:21 core/prioritize.py:63 #: core\me\prioritize.py:23
#: core/se/result_table.py:21
msgid "Kind"
msgstr "Typ"
#: core/me/result_table.py:19 core/pe/result_table.py:19 core/prioritize.py:72
#: core/se/result_table.py:19
msgid "Folder"
msgstr "Ordner"
#: core/me/result_table.py:18 core/pe/result_table.py:18 core/prioritize.py:88
#: core/se/result_table.py:18
msgid "Filename"
msgstr "Dateiname"
#: core/prioritize.py:147
msgid "Size"
msgstr "Größe"
#: core/me/result_table.py:25 core/pe/result_table.py:24
#: core/prioritize.py:153 core/se/result_table.py:22
msgid "Modification"
msgstr "Geändert"
#: core/me/prioritize.py:18
msgid "Duration" msgid "Duration"
msgstr "Dauer" msgstr "Dauer"
#: core/me/prioritize.py:24 core/me/result_table.py:22 #: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate" msgid "Bitrate"
msgstr "Bitrate" msgstr "Bitrate"
#: core/me/prioritize.py:30 #: core\me\prioritize.py:37
msgid "Samplerate" msgid "Samplerate"
msgstr "Abtastrate" msgstr "Abtastrate"
#: core/me/result_table.py:20 #: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
#: core\se\result_table.py:19
msgid "Filename"
msgstr "Dateiname"
#: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core\se\result_table.py:20
msgid "Folder"
msgstr "Ordner"
#: core\me\result_table.py:21
msgid "Size (MB)" msgid "Size (MB)"
msgstr "Größe (MB)" msgstr "Größe (MB)"
#: core/me/result_table.py:21 #: core\me\result_table.py:22
msgid "Time" msgid "Time"
msgstr "Zeit" msgstr "Zeit"
#: core/me/result_table.py:23 #: core\me\result_table.py:24
msgid "Sample Rate" msgid "Sample Rate"
msgstr "Abtastrate" msgstr "Abtastrate"
#: core/me/result_table.py:26 #: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core\se\result_table.py:22
msgid "Kind"
msgstr "Typ"
#: core\me\result_table.py:26 core\pe\result_table.py:25
#: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification"
msgstr "Geändert"
#: core\me\result_table.py:27
msgid "Title" msgid "Title"
msgstr "Titel" msgstr "Titel"
#: core/me/result_table.py:27 #: core\me\result_table.py:28
msgid "Artist" msgid "Artist"
msgstr "Künstler" msgstr "Künstler"
#: core/me/result_table.py:28 #: core\me\result_table.py:29
msgid "Album" msgid "Album"
msgstr "Album" msgstr "Album"
#: core/me/result_table.py:29 #: core\me\result_table.py:30
msgid "Genre" msgid "Genre"
msgstr "Genre" msgstr "Genre"
#: core/me/result_table.py:30 #: core\me\result_table.py:31
msgid "Year" msgid "Year"
msgstr "Jahr" msgstr "Jahr"
#: core/me/result_table.py:31 #: core\me\result_table.py:32
msgid "Track Number" msgid "Track Number"
msgstr "Titel Nummer" msgstr "Titel Nummer"
#: core/me/result_table.py:32 #: core\me\result_table.py:33
msgid "Comment" msgid "Comment"
msgstr "Kommentar" msgstr "Kommentar"
#: core/me/result_table.py:33 core/pe/result_table.py:25 #: core\me\result_table.py:34 core\pe\result_table.py:26
#: core/se/result_table.py:23 #: core\se\result_table.py:24
msgid "Match %" msgid "Match %"
msgstr "Übereinstimmung %" msgstr "Übereinstimmung %"
#: core/me/result_table.py:34 core/se/result_table.py:24 #: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used" msgid "Words Used"
msgstr "genutzte Wörter" msgstr "genutzte Wörter"
#: core/me/result_table.py:35 core/pe/result_table.py:26 #: core\me\result_table.py:36 core\pe\result_table.py:27
#: core/se/result_table.py:25 #: core\se\result_table.py:26
msgid "Dupe Count" msgid "Dupe Count"
msgstr "Anzahl der Duplikate" msgstr "Anzahl der Duplikate"
#: core/pe/prioritize.py:18 core/pe/result_table.py:22 #: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions" msgid "Dimensions"
msgstr "Auflösung" msgstr "Auflösung"
#: core/pe/result_table.py:20 core/se/result_table.py:20 #: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)" msgid "Size (KB)"
msgstr "Größe (KB)" msgstr "Größe (KB)"
#: core/pe/result_table.py:23 #: core\pe\result_table.py:24
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "EXIF Zeitstempel" msgstr "EXIF Zeitstempel"
#: core\prioritize.py:156
msgid "Size"
msgstr "Größe"

View File

@@ -1,26 +1,25 @@
# Translators: # Translators:
# Harakiri1337, 2014 # Andrew Senetar <arsenetar@gmail.com>, 2021
# Frank Weber <frank.weber@gmail.com>, 2014 # Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2014-09-26 21:24+0000\n" "Language-Team: German (https://www.transifex.com/voltaicideas/teams/116153/de/)\n"
"Last-Translator: Frank Weber <frank.weber@gmail.com>\n" "Language: de\n"
"Language-Team: German (http://www.transifex.com/projects/p/dupeguru/language/de/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: core/app.py:40 #: core\app.py:42
msgid "There are no marked duplicates. Nothing has been done." msgid "There are no marked duplicates. Nothing has been done."
msgstr "Keine markierten Duplikate, daher wurde nichts getan." msgstr "Keine markierten Duplikate, daher wurde nichts getan."
#: core/app.py:41 #: core\app.py:43
msgid "There are no selected duplicates. Nothing has been done." msgid "There are no selected duplicates. Nothing has been done."
msgstr "Keine ausgewählten Duplikate, daher wurde nichts getan." msgstr "Keine ausgewählten Duplikate, daher wurde nichts getan."
#: core/app.py:42 #: core\app.py:44
msgid "" msgid ""
"You're about to open many files at once. Depending on what those files are " "You're about to open many files at once. Depending on what those files are "
"opened with, doing so can create quite a mess. Continue?" "opened with, doing so can create quite a mess. Continue?"
@@ -28,27 +27,27 @@ msgstr ""
"Sie sind dabei, sehr viele Dateien gleichzeitig zu öffnen. Das kann zu " "Sie sind dabei, sehr viele Dateien gleichzeitig zu öffnen. Das kann zu "
"ziemlichem Durcheinander führen! Trotzdem fortfahren?" "ziemlichem Durcheinander führen! Trotzdem fortfahren?"
#: core/app.py:65 #: core\app.py:71
msgid "Scanning for duplicates" msgid "Scanning for duplicates"
msgstr "Suche nach Duplikaten" msgstr "Suche nach Duplikaten"
#: core/app.py:66 #: core\app.py:72
msgid "Loading" msgid "Loading"
msgstr "Lade" msgstr "Lade"
#: core/app.py:67 #: core\app.py:73
msgid "Moving" msgid "Moving"
msgstr "Verschiebe" msgstr "Verschiebe"
#: core/app.py:68 #: core\app.py:74
msgid "Copying" msgid "Copying"
msgstr "Kopiere" msgstr "Kopiere"
#: core/app.py:69 #: core\app.py:75
msgid "Sending to Trash" msgid "Sending to Trash"
msgstr "Verschiebe in den Papierkorb" msgstr "Verschiebe in den Papierkorb"
#: core/app.py:279 #: core\app.py:308
msgid "" msgid ""
"A previous action is still hanging in there. You can't start a new one yet. " "A previous action is still hanging in there. You can't start a new one yet. "
"Wait a few seconds, then try again." "Wait a few seconds, then try again."
@@ -56,32 +55,36 @@ msgstr ""
"Eine vorherige Aktion ist noch in der Bearbeitung. Sie können noch keine " "Eine vorherige Aktion ist noch in der Bearbeitung. Sie können noch keine "
"Neue starten. Warten Sie einige Sekunden und versuchen es erneut." "Neue starten. Warten Sie einige Sekunden und versuchen es erneut."
#: core/app.py:289 #: core\app.py:318
msgid "No duplicates found." msgid "No duplicates found."
msgstr "Keine Duplikate gefunden." msgstr "Keine Duplikate gefunden."
#: core/app.py:304 #: core\app.py:333
msgid "All marked files were copied successfully." msgid "All marked files were copied successfully."
msgstr "Alle markierten Dateien wurden erfolgreich kopiert." msgstr "Alle markierten Dateien wurden erfolgreich kopiert."
#: core/app.py:305 #: core\app.py:334
msgid "All marked files were moved successfully." msgid "All marked files were moved successfully."
msgstr "Alle markierten Dateien wurden erfolgreich verschoben." msgstr "Alle markierten Dateien wurden erfolgreich verschoben."
#: core/app.py:306 #: core\app.py:335
msgid "All marked files were successfully sent to Trash." msgid "All marked files were successfully sent to Trash."
msgstr "" msgstr ""
"Alle markierten Dateien wurden erfolgreich in den Papierkorb verschoben." "Alle markierten Dateien wurden erfolgreich in den Papierkorb verschoben."
#: core/app.py:368 #: core\app.py:343
msgid "Could not load file: {}"
msgstr "Konnte Datei {} nicht laden."
#: core\app.py:399
msgid "'{}' already is in the list." msgid "'{}' already is in the list."
msgstr "'{}' ist bereits in der Liste." msgstr "'{}' ist bereits in der Liste."
#: core/app.py:370 #: core\app.py:401
msgid "'{}' does not exist." msgid "'{}' does not exist."
msgstr "'{}' existiert nicht." msgstr "'{}' existiert nicht."
#: core/app.py:379 #: core\app.py:410
msgid "" msgid ""
"All selected %d matches are going to be ignored in all subsequent scans. " "All selected %d matches are going to be ignored in all subsequent scans. "
"Continue?" "Continue?"
@@ -89,187 +92,172 @@ msgstr ""
"Alle %d ausgewählten Dateien werden in zukünftigen Scans ignoriert. " "Alle %d ausgewählten Dateien werden in zukünftigen Scans ignoriert. "
"Fortfahren?" "Fortfahren?"
#: core/app.py:450 #: core\app.py:486
msgid "copy" msgid "Select a directory to copy marked files to"
msgstr "kopieren" msgstr ""
"Wählen Sie ein Verzeichnis aus, in das markierte Dateien kopiert werden "
"sollen"
#: core/app.py:450 #: core\app.py:487
msgid "move" msgid "Select a directory to move marked files to"
msgstr "verschieben" msgstr ""
"Wählen Sie ein Verzeichnis aus, in das markierte Dateien verschoben werden "
"sollen"
#: core/app.py:451 #: core\app.py:527
msgid "Select a directory to {} marked files to"
msgstr "Wählen Sie einen Ordner zum {} der ausgewählten Dateien."
#: core/app.py:490
msgid "Select a destination for your exported CSV" msgid "Select a destination for your exported CSV"
msgstr "Zielverzeichnis für den CSV Export angeben" msgstr "Zielverzeichnis für den CSV Export angeben"
#: core/app.py:518 #: core\app.py:534 core\app.py:801 core\app.py:811
msgid "Couldn't write to file: {}"
msgstr "Konnte Datei {} nicht schreiben."
#: core\app.py:559
msgid "You have no custom command set up. Set it up in your preferences." msgid "You have no custom command set up. Set it up in your preferences."
msgstr "" msgstr ""
"Sie haben noch keinen Befehl erstellt. Bitte dies in den Einstellungen vornehmen.\n" "Sie haben noch keinen Befehl erstellt. Bitte dies in den Einstellungen vornehmen.\n"
"Bsp.: \"C:\\Program Files\\Diff\\Diff.exe\" \"%d\" \"%r\"" "Bsp.: \"C:\\Program Files\\Diff\\Diff.exe\" \"%d\" \"%r\""
#: core/app.py:672 core/app.py:685 #: core\app.py:727 core\app.py:740
msgid "You are about to remove %d files from results. Continue?" msgid "You are about to remove %d files from results. Continue?"
msgstr "%d Dateien werden aus der Ergebnisliste entfernt. Fortfahren?" msgstr "%d Dateien werden aus der Ergebnisliste entfernt. Fortfahren?"
#: core/app.py:719 #: core\app.py:774
msgid "{} duplicate groups were changed by the re-prioritization." msgid "{} duplicate groups were changed by the re-prioritization."
msgstr "{} Duplikat-Gruppen wurden durch die Neu-Priorisierung geändert." msgstr "{} Duplikat-Gruppen wurden durch die Neu-Priorisierung geändert."
#: core/app.py:762 #: core\app.py:821
msgid "Collecting files to scan"
msgstr "Sammle zu scannende Dateien..."
#: core/app.py:751
msgid "The selected directories contain no scannable file." msgid "The selected directories contain no scannable file."
msgstr "Ausgewählte Ordner enthalten keine scannbaren Dateien." msgstr "Ausgewählte Ordner enthalten keine scannbaren Dateien."
#: core/app.py:810 #: core\app.py:835
msgid "Collecting files to scan"
msgstr "Sammle zu scannende Dateien..."
#: core\app.py:891
msgid "%s (%d discarded)" msgid "%s (%d discarded)"
msgstr "%s (%d verworfen)" msgstr "%s (%d verworfen)"
#: core/engine.py:222 core/engine.py:262 #: core\engine.py:244 core\engine.py:288
msgid "0 matches found" msgid "0 matches found"
msgstr "0 Übereinstimmungen gefunden" msgstr "0 Übereinstimmungen gefunden"
#: core/engine.py:240 core/engine.py:270 #: core\engine.py:262 core\engine.py:296
msgid "%d matches found" msgid "%d matches found"
msgstr "%d Übereinstimmungen gefunden" msgstr "%d Übereinstimmungen gefunden"
#: core/scanner.py:77 #: core\gui\deletion_options.py:73
msgid "Read size of %d/%d files"
msgstr "Lese Größe von %d/%d Dateien"
#: core/gui/deletion_options.py:69
msgid "You are sending {} file(s) to the Trash." msgid "You are sending {} file(s) to the Trash."
msgstr "Verschiebe {} Datei(en) in den Papierkorb." msgstr "Verschiebe {} Datei(en) in den Papierkorb."
#: core/gui/ignore_list_dialog.py:24 #: core\gui\exclude_list_table.py:15
msgid "Regular Expressions"
msgstr "Reguläre Ausdrücke"
#: core\gui\ignore_list_dialog.py:25
msgid "Do you really want to remove all %d items from the ignore list?" msgid "Do you really want to remove all %d items from the ignore list?"
msgstr "Möchten Sie wirklich alle %d Einträge aus der Ausnahmeliste löschen?" msgstr "Möchten Sie wirklich alle %d Einträge aus der Ausnahmeliste löschen?"
#: core/prioritize.py:68 #: core\me\scanner.py:20 core\se\scanner.py:16
msgid "None"
msgstr "Nichts"
#: core/prioritize.py:96
msgid "Ends with number"
msgstr "Endet mit Zahl"
#: core/prioritize.py:97
msgid "Doesn't end with number"
msgstr "Endet nicht mit Zahl"
#: core/prioritize.py:98
msgid "Longest"
msgstr "Längste"
#: core/prioritize.py:99
msgid "Shortest"
msgstr "Kürzeste"
#: core/prioritize.py:132
msgid "Highest"
msgstr "Höchste"
#: core/prioritize.py:132
msgid "Lowest"
msgstr "Niedrigste"
#: core/prioritize.py:159
msgid "Newest"
msgstr "Neuste"
#: core/prioritize.py:159
msgid "Oldest"
msgstr "Älterste"
#: core/results.py:129
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) Duplikate markiert."
#: core/results.py:136
msgid " filter: %s"
msgstr " Filter: %s"
#: core/scanner.py:101
msgid "Read metadata of %d/%d files"
msgstr "Lese Metadaten von %d/%d Dateien"
#: core/pe/matchblock.py:61
msgid "Analyzed %d/%d pictures"
msgstr "Analysiere Bild %d/%d"
#: core/pe/matchblock.py:156
msgid "Performed %d/%d chunk matches"
msgstr "%d/%d Chunk-Matches ausgeführt"
#: core/pe/matchblock.py:161
msgid "Preparing for matching"
msgstr "Bereite Matching vor"
#: core/pe/matchblock.py:206
msgid "Verified %d/%d matches"
msgstr "%d/%d verifizierte Übereinstimmungen"
#: core/pe/matchexif.py:18
msgid "Read EXIF of %d/%d pictures"
msgstr "Lese EXIF von Bild %d/%d"
#: core/app.py:312
msgid "Could not load file: {}"
msgstr "Konnte Datei {} nicht laden."
#: core/app.py:496 core/app.py:742
msgid "Couldn't write to file: {}"
msgstr "Konnte Datei {} nicht schreiben."
#: core/me/scanner.py:19 core/se/scanner.py:15
msgid "Filename" msgid "Filename"
msgstr "Dateiname" msgstr "Dateiname"
#: core/me/scanner.py:20 #: core\me\scanner.py:21
msgid "Filename - Fields" msgid "Filename - Fields"
msgstr "Dateiname - Bereiche" msgstr "Dateiname - Bereiche"
#: core/me/scanner.py:21 #: core\me\scanner.py:22
msgid "Filename - Fields (No Order)" msgid "Filename - Fields (No Order)"
msgstr "Dateiname - Bereiche (ohne Reihenfolge)" msgstr "Dateiname - Bereiche (ohne Reihenfolge)"
#: core/me/scanner.py:22 #: core\me\scanner.py:23
msgid "Tags" msgid "Tags"
msgstr "Tags" msgstr "Tags"
#: core/me/scanner.py:23 core/pe/scanner.py:20 core/se/scanner.py:16 #: core\me\scanner.py:24 core\pe\scanner.py:21 core\se\scanner.py:17
msgid "Contents" msgid "Contents"
msgstr "Inhalt" msgstr "Inhalt"
#: core/pe/scanner.py:21 #: core\pe\matchblock.py:72
msgid "Analyzed %d/%d pictures"
msgstr "Analysiere Bild %d/%d"
#: core\pe\matchblock.py:181
msgid "Performed %d/%d chunk matches"
msgstr "%d/%d Chunk-Matches ausgeführt"
#: core\pe\matchblock.py:191
msgid "Preparing for matching"
msgstr "Bereite Matching vor"
#: core\pe\matchblock.py:244
msgid "Verified %d/%d matches"
msgstr "%d/%d verifizierte Übereinstimmungen"
#: core\pe\matchexif.py:19
msgid "Read EXIF of %d/%d pictures"
msgstr "Lese EXIF von Bild %d/%d"
#: core\pe\scanner.py:22
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "EXIF Zeitstempel" msgstr "EXIF Zeitstempel"
#: core/scanner.py:139 #: core\prioritize.py:70
msgid "None"
msgstr "Nichts"
#: core\prioritize.py:100
msgid "Ends with number"
msgstr "Endet mit Zahl"
#: core\prioritize.py:101
msgid "Doesn't end with number"
msgstr "Endet nicht mit Zahl"
#: core\prioritize.py:102
msgid "Longest"
msgstr "Längste"
#: core\prioritize.py:103
msgid "Shortest"
msgstr "Kürzeste"
#: core\prioritize.py:140
msgid "Highest"
msgstr "Höchste"
#: core\prioritize.py:140
msgid "Lowest"
msgstr "Niedrigste"
#: core\prioritize.py:169
msgid "Newest"
msgstr "Neuste"
#: core\prioritize.py:169
msgid "Oldest"
msgstr "Älterste"
#: core\results.py:142
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) Duplikate markiert."
#: core\results.py:149
msgid " filter: %s"
msgstr " Filter: %s"
#: core\scanner.py:85
msgid "Read size of %d/%d files"
msgstr "Lese Größe von %d/%d Dateien"
#: core\scanner.py:109
msgid "Read metadata of %d/%d files"
msgstr "Lese Metadaten von %d/%d Dateien"
#: core\scanner.py:147
msgid "Almost done! Fiddling with results..." msgid "Almost done! Fiddling with results..."
msgstr "Fast fertig! Arrangiere Ergebnisse..." msgstr "Fast fertig! Arrangiere Ergebnisse..."
#: core/se/scanner.py:17 #: core\se\scanner.py:18
msgid "Folders" msgid "Folders"
msgstr "Ordner" msgstr "Ordner"
#~ msgid "Sending files to the recycle bin"
#~ msgstr "Verschiebe Dateien in den Papierkorb"
#~ msgid "Grouped %d/%d matches"
#~ msgstr "%d/%d Übereinstimmungen gruppiert"
#~ msgid "Removing false matches"
#~ msgstr "Entferne falsche Übereinstimmungen"
#~ msgid "Processed %d/%d matches against the ignore list"
#~ msgstr "%d/%d Treffer mit der Ausnahmeliste abgeglichen"
#~ msgid "Doing group prioritization"
#~ msgstr "Gruppenpriorisierung"

View File

@@ -1,26 +1,34 @@
# Translators: # Translators:
# Harakiri1337, 2014 # Andrew Senetar <arsenetar@gmail.com>, 2021
# Frank Weber <frank.weber@gmail.com>, 2014 # Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2014-09-26 21:15+0000\n" "Language-Team: German (https://www.transifex.com/voltaicideas/teams/116153/de/)\n"
"Last-Translator: Frank Weber <frank.weber@gmail.com>\n" "Language: de\n"
"Language-Team: German (http://www.transifex.com/projects/p/dupeguru/language/de/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: qt/app.py:81 #: qt/app.py:81
msgid "Quit" msgid "Quit"
msgstr "Beenden" msgstr "Beenden"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Optionen"
#: qt/app.py:83 qt/ignore_list_dialog.py:32 #: qt/app.py:83 qt/ignore_list_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Ignore List" msgid "Ignore List"
msgstr "Ausnahme-Liste" msgstr "Ausnahme-Liste"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Bilder-Cache leeren"
#: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0 #: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Help" msgid "dupeGuru Help"
msgstr "dupeGuru Hilfe" msgstr "dupeGuru Hilfe"
@@ -33,6 +41,15 @@ msgstr "Über dupeGuru"
msgid "Open Debug Log" msgid "Open Debug Log"
msgstr "Debug Log öffnen" msgstr "Debug Log öffnen"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr ""
"Möchten Sie wirklich alle zwischengespeicherten Bildanalysen entfernen?"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "Bilder-Cache geleert."
#: qt/app.py:251 #: qt/app.py:251
msgid "{} file (*.{})" msgid "{} file (*.{})"
msgstr "{} Datei (*.{})" msgstr "{} Datei (*.{})"
@@ -129,6 +146,30 @@ msgstr "Hilfe"
msgid "Load Recent Results" msgid "Load Recent Results"
msgstr "Lade letztes Suchergebnis" msgstr "Lade letztes Suchergebnis"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0
msgid "Application Mode:"
msgstr "Anwendungsmodus:"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Music"
msgstr "Musik"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Picture"
msgstr "Bild"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Standard"
msgstr "Standard"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0
msgid "Scan Type:"
msgstr "Scantyp:"
#: qt/directories_dialog.py:135
msgid "More Options"
msgstr "Optionen"
#: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0 #: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0
msgid "Select folders to scan and press \"Scan\"." msgid "Select folders to scan and press \"Scan\"."
msgstr "Zu durchsuchende Ordner auswählen und \"Suche starten\" drücken." msgstr "Zu durchsuchende Ordner auswählen und \"Suche starten\" drücken."
@@ -203,9 +244,78 @@ msgstr "Liste leeren"
msgid "Close" msgid "Close"
msgstr "Schließen" msgstr "Schließen"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0 #: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
msgid "Scan Type:" #: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
msgstr "Scantyp:" #: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Details"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Folgende Tags scannen:"
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Track"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Künstler"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Album"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Titel"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Genre"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Jahr"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "Wortgewichtung"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Gleiche ähnliche Wörter ab"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Dateitypen dürfen gemischt werden"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Nutze reguläre Ausdrücke beim Filtern"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Entferne leere Ordner beim Löschen oder Verschieben"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Ignoriere Duplikate mit Hardlinks auf dieselbe Datei"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Debug Modus (Neustart nötig)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Gleiche Bilder mit unterschiedlicher Auflösung ab"
#: qt/preferences_dialog.py:43 #: qt/preferences_dialog.py:43
msgid "Filter Hardness:" msgid "Filter Hardness:"
@@ -283,12 +393,6 @@ msgstr ""
msgid "Reveal Selected" msgid "Reveal Selected"
msgstr "Zeige Markierte" msgstr "Zeige Markierte"
#: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
#: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Details"
#: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167 #: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167
#: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0
msgid "Actions" msgid "Actions"
@@ -406,86 +510,6 @@ msgstr "Zeige Delta-Werte"
msgid "Select a file to save your results to" msgid "Select a file to save your results to"
msgstr "Datei zum Speichern der Suchergebnisse auswählen" msgstr "Datei zum Speichern der Suchergebnisse auswählen"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Folgende Tags scannen:"
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Track"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Künstler"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Album"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Titel"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Genre"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Jahr"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "Wortgewichtung"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Gleiche ähnliche Wörter ab"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Dateitypen dürfen gemischt werden"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Nutze reguläre Ausdrücke beim Filtern"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Entferne leere Ordner beim Löschen oder Verschieben"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Ignoriere Duplikate mit Hardlinks auf dieselbe Datei"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Debug Modus (Neustart nötig)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Gleiche Bilder mit unterschiedlicher Auflösung ab"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Bilder-Cache leeren"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr ""
"Möchten Sie wirklich alle zwischengespeicherten Bildanalysen entfernen?"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "Bilder-Cache geleert."
#: qt/se/preferences_dialog.py:41 #: qt/se/preferences_dialog.py:41
msgid "Ignore files smaller than" msgid "Ignore files smaller than"
msgstr "Ignoriere Dateien kleiner als" msgstr "Ignoriere Dateien kleiner als"
@@ -642,11 +666,6 @@ msgstr "Mehr Suchergebnisse"
msgid "Ok" msgid "Ok"
msgstr "Ok" msgstr "Ok"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Optionen"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Paste" msgid "Paste"
msgstr "Einfügen" msgstr "Einfügen"
@@ -711,112 +730,219 @@ msgstr "Fenster"
msgid "Zoom" msgid "Zoom"
msgstr "Zoom" msgstr "Zoom"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0 #: qt\app.py:158
msgid "Application Mode:" msgid "Exclusion Filters"
msgstr "Anwendungsmodus:" msgstr "Ausschlussfilter"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\directories_dialog.py:91
msgid "Music" msgid "Scan Results"
msgstr "Musik" msgstr "Scan-Ergebnisse"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\directories_dialog.py:95
msgid "Picture" msgid "Load Directories..."
msgstr "Bild" msgstr "Verzeichnisse laden..."
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\directories_dialog.py:96
msgid "Standard" msgid "Save Directories..."
msgstr "Standard" msgstr "Verzeichnisse speichern..."
#: qt/directories_dialog.py:135 #: qt\directories_dialog.py:337
msgid "More Options" msgid "Select a directories file to load"
msgstr "Optionen" msgstr "Wählen Sie eine zu ladende Verzeichnisdatei aus"
#~ msgid "Removing dead tracks from your iTunes Library" #: qt\directories_dialog.py:338
#~ msgstr "Entferne tote Tracks aus Ihrer iTunes Bibliothek" msgid "dupeGuru Results (*.dupegurudirs)"
msgstr "dupeGuru Verzeichnisse (*.dupegurudirs)"
#~ msgid "Scanning the iTunes Library" #: qt\directories_dialog.py:347
#~ msgstr "Durchsuche die iTunes-Bibliothek" msgid "Select a file to save your directories to"
msgstr ""
"Wählen Sie eine Datei aus, in der Ihre Verzeichnisse gespeichert werden "
"sollen"
#~ msgid "Sending dupes to the Trash" #: qt\directories_dialog.py:348
#~ msgstr "Schicke Duplikate in den Papierkorb" msgid "dupeGuru Directories (*.dupegurudirs)"
msgstr "dupeGuru Verzeichnisse (*.dupegurudirs)"
#~ msgid "Talking to iTunes. Don't touch it!" #: qt\exclude_list_dialog.py:44
#~ msgstr "Kommuniziere mit iTunes. Bitte warten!" msgid "Add"
msgstr "Addieren"
#~ msgid "" #: qt\exclude_list_dialog.py:46
#~ "Your iTunes Library contains %d dead tracks ready to be removed. Continue?" msgid "Restore defaults"
#~ msgstr "" msgstr "Standardeinstellungen wiederherstellen"
#~ "Ihre iTunes-Bibliothek enthält %d tote Tracks zum Entfernen. Fortsetzen?"
#~ msgid "You have no dead tracks in your iTunes Library" #: qt\exclude_list_dialog.py:47
#~ msgstr "Sie haben keine toten Tracks in Ihrer iTunes-Bibliothek" msgid "Test string"
msgstr "Testzeichenfolge"
#~ msgid "The iTunes application couldn't be found." #: qt\exclude_list_dialog.py:83
#~ msgstr "Das iTunes-Programm konnte nicht gefunden werden." msgid "Type a python regular expression here..."
msgstr "Geben Sie hier einen regulären Python-Ausdruck ein..."
#~ msgid "Talking to iPhoto. Don't touch it!" #: qt\exclude_list_dialog.py:85
#~ msgstr "Kommuniziere mit iPhoto. Bitte warten!" msgid "Type a file system path or filename here..."
msgstr "Geben Sie hier einen Dateisystempfad oder Dateinamen ein..."
#~ msgid "Talking to Aperture. Don't touch it!" #: qt\exclude_list_dialog.py:152
#~ msgstr "Kommuniziere mit Aperture. Bitte warten!" msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happen to match one of the regular expressions.<br>For each file collected two tests are perfomed on each of them to determine whether or not to filter them out:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with no path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the test string feature by pasting a fake path in it:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
"Diese regulären Python-Ausdrücke (Groß- und Kleinschreibung beachten) filtern Dateien während des Scannens heraus.<br>Der <strong>Standardstatus</strong> von Verzeichnissen wird auf der Registerkarte \"Verzeichnisse\" auf \"Ausgeschlossen\" gesetzt, wenn ihr Name zufällig mit einem der ausgewählten regulären Ausdrücke übereinstimmt.<br>Für jede gesammelte Datei werden zwei Tests durchgeführt, um festzustellen, ob sie vollständig ignoriert werden soll oder nicht:<br><li>1. Reguläre Ausdrücke ohne Pfadtrennzeichen werden nur mit dem Dateinamen verglichen.</li>\n"
"<li>2. Reguläre Ausdrücke mit mindestens einem Pfadtrennzeichen werden mit dem vollständigen Pfad zur Datei verglichen.</li><br>\n"
"Beispiel: Wenn Sie PNG-Dateien nur aus dem Verzeichnis \"Meine Bilder\" herausfiltern möchten:<br><code>.*Meine\\sBilder\\\\.*\\.png</code><br><br>Sie können den regulären Ausdruck mit der Schaltfläche \"Testzeichenfolge\" testen, nachdem Sie einen falschen Pfad in das Testfeld eingefügt haben:<br><code>C:\\\\Nutzer\\Meine Bilder\\test.png</code><br><br>\n"
"Übereinstimmende reguläre Ausdrücke werden hervorgehoben.<br>Wenn mindestens eine Markierung vorhanden ist, wird der getestete Pfad oder Dateiname beim Scannen ignoriert.<br><br>Verzeichnisse und Dateien, die mit einem Punkt '.' Beginnen. werden standardmäßig herausgefiltert.<br><br>"
#~ msgid "Deleted Aperture photos were sent to a project called \"dupeGuru Trash\"." #: qt\exclude_list_table.py:36
#~ msgstr "" msgid "Compilation error: "
#~ "Gelöschte Aperture-Fotos wurden dem Projekt \"dupeGuru Trash\" hinzugefügt." msgstr "Kompilierungsfehler:"
#~ msgid "The iPhoto application couldn't be found." #: qt\pe\image_viewer.py:56
#~ msgstr "Das iPhoto-Programm konnte nicht gefunden werden." msgid "Increase zoom"
msgstr "Erhöhen Sie den Zoom"
#~ msgid "Preferences" #: qt\pe\image_viewer.py:66
#~ msgstr "Einstellungen" msgid "Decrease zoom"
msgstr "Verringern Sie den Zoom"
#~ msgid "Check for Update" #: qt\pe\image_viewer.py:71
#~ msgstr "Auf Updates überprüfen" msgid "Ctrl+/"
msgstr "Ctrl+/"
#~ msgid "Filename" #: qt\pe\image_viewer.py:76
#~ msgstr "Dateiname" msgid "Normal size"
msgstr "Normale Größe"
#~ msgid "Filename - Fields" #: qt\pe\image_viewer.py:81
#~ msgstr "Dateiname - Felder" msgid "Ctrl+*"
msgstr "Ctrl+*"
#~ msgid "Filename - Fields (No Order)" #: qt\pe\image_viewer.py:86
#~ msgstr "Dateiname - Felder (ohne Reihenfolge)" msgid "Best fit"
msgstr "Beste Passform"
#~ msgid "Tags" #: qt\pe\preferences_dialog.py:49
#~ msgstr "Tags" msgid "Picture cache mode:"
msgstr "Bild-Cache-Modus:"
#~ msgid "Contents" #: qt\pe\preferences_dialog.py:56
#~ msgstr "Inhalte" msgid "Override theme icons in viewer toolbar"
msgstr "Überschreiben Sie Themensymbole in der Viewer-Symbolleiste"
#~ msgid "Audio Contents" #: qt\pe\preferences_dialog.py:58
#~ msgstr "Audio Inhalte" msgid ""
"Use our own internal icons instead of those provided by the theme engine"
msgstr ""
"Verwenden Sie unsere eigenen internen Symbole anstelle der von der Theme "
"Engine bereitgestellten"
#~ msgid "EXIF Timestamp" #: qt\pe\preferences_dialog.py:66
#~ msgstr "EXIF Zeitstempel" msgid "Show scrollbars in image viewers"
msgstr "Bildlaufleisten in Bildbetrachtern anzeigen"
#~ msgid "Folders" #: qt\pe\preferences_dialog.py:68
#~ msgstr "Ordner" msgid ""
"When the image displayed doesn't fit the viewport, show scrollbars to span "
"the view around"
msgstr ""
"Wenn das angezeigte Bild nicht zum Ansichtsfenster passt, zeigen Sie "
"Bildlaufleisten an, um die Ansicht zu überspannen"
#~ msgid "Add Aperture Library" #: qt\preferences_dialog.py:156
#~ msgstr "Füge Aperture-Bibliothek hinzu" msgid "Use default position for tab bar (requires restart)"
msgstr ""
"Standardposition für Registerkartenleiste verwenden (Neustart erforderlich)"
#~ msgid "Add iPhoto Library" #: qt\preferences_dialog.py:158
#~ msgstr "Füge iPhoto-Bibliothek hinzu" msgid ""
"Place the tab bar below the main menu instead of next to it\n"
"On MacOS, the tab bar will fill up the window's width instead."
msgstr ""
"Platzieren Sie die Registerkartenleiste unter dem Hauptmenü und nicht daneben\n"
"Unter MacOS füllt die Registerkartenleiste stattdessen die Fensterbreite aus."
#~ msgid "Add iTunes Library" #: qt\preferences_dialog.py:172
#~ msgstr "Füge iTunes-Bibliothek hinzu" msgid "Use bold font for references"
msgstr "Verwenden Sie Fettdruck als Referenz"
#~ msgid "Audio Content" #: qt\preferences_dialog.py:176
#~ msgstr "Audio Inhalt" msgid "Reference foreground color:"
msgstr "Vordergrundfarbe für Referenzen:"
#~ msgid "Content" #: qt\preferences_dialog.py:179
#~ msgstr "Inhalt" msgid "Reference background color:"
msgstr "Hintergrundfarbe für Referenzen:"
#~ msgid "dupeGuru ME Preferences" #: qt\preferences_dialog.py:182 qt\preferences_dialog.py:216
#~ msgstr "dupeGuru ME Einstellungen" msgid "Delta foreground color:"
msgstr "Vordergrundfarbe für Delta:"
#~ msgid "dupeGuru PE Preferences" #: qt\preferences_dialog.py:195
#~ msgstr "dupeGuru PE Einstellungen" msgid "Show the title bar and can be docked"
msgstr "Zeigt die Titelleiste an und kann angedockt werden"
#~ msgid "Remove Dead Tracks in iTunes" #: qt\preferences_dialog.py:197
#~ msgstr "Entferne tote Tracks in iTunes" msgid ""
"While the title bar is hidden, use the modifier key to drag the floating "
"window around"
msgstr ""
"Während die Titelleiste ausgeblendet ist, ziehen Sie das schwebende Fenster "
"mit der Modifikatortaste herum"
#: qt\preferences_dialog.py:199
msgid "The title bar can only be disabled while the window is docked"
msgstr ""
"Die Titelleiste kann nur deaktiviert werden, während das Fenster angedockt "
"ist"
#: qt\preferences_dialog.py:202
msgid "Vertical title bar"
msgstr "Vertikale Titelleiste"
#: qt\preferences_dialog.py:204
msgid ""
"Change the title bar from horizontal on top, to vertical on the left side"
msgstr "Ändern Sie die Titelleiste von horizontal oben in vertikal links"
#: qt\tabbed_window.py:44
msgid "Show tab bar"
msgstr "Registerkartenleiste anzeigen"
#: qt\exclude_list_dialog.py:152
msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happens to match one of the selected regular expressions.<br>For each file collected, two tests are performed to determine whether or not to completely ignore it:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with at least one path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the \"test string\" button after pasting a fake path in the test field:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path or filename tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
"Diese regulären Python-Ausdrücke (Groß- und Kleinschreibung beachten) filtern Dateien während des Scannens heraus.<br>Der <strong>Standardstatus</strong> von Verzeichnissen wird auf der Registerkarte \"Verzeichnisse\" auf \"Ausgeschlossen\" gesetzt, wenn ihr Name zufällig mit einem der ausgewählten regulären Ausdrücke übereinstimmt.<br>Für jede gesammelte Datei werden zwei Tests durchgeführt, um festzustellen, ob sie vollständig ignoriert werden soll oder nicht:<br><li>1. Reguläre Ausdrücke ohne Pfadtrennzeichen werden nur mit dem Dateinamen verglichen.</li>\n"
"<li>2. Reguläre Ausdrücke mit mindestens einem Pfadtrennzeichen werden mit dem vollständigen Pfad zur Datei verglichen.</li><br>\n"
"Beispiel: Wenn Sie PNG-Dateien nur aus dem Verzeichnis \"Meine Bilder\" herausfiltern möchten:<br><code>.*Meine\\sBilder\\\\.*\\.png</code><br><br>Sie können den regulären Ausdruck mit der Schaltfläche \"Testzeichenfolge\" testen, nachdem Sie einen falschen Pfad in das Testfeld eingefügt haben:<br><code>C:\\\\Nutzer\\Meine Bilder\\test.png</code><br><br>\n"
"Übereinstimmende reguläre Ausdrücke werden hervorgehoben.<br>Wenn mindestens eine Markierung vorhanden ist, wird der getestete Pfad oder Dateiname beim Scannen ignoriert.<br><br>Verzeichnisse und Dateien, die mit einem Punkt '.' Beginnen. werden standardmäßig herausgefiltert.<br><br>"
#: qt\app.py:256
msgid "Results"
msgstr "Ergebnisse"
#: qt\preferences_dialog.py:150
msgid "General Interface"
msgstr "Allgemeine Schnittstelle"
#: qt\preferences_dialog.py:176
msgid "Result Table"
msgstr "Ergebnistabelle"
#: qt\preferences_dialog.py:205
msgid "Details Window"
msgstr "Detailfenster"
#: qt\preferences_dialog.py:285
msgid "General"
msgstr "Allgemeines"
#: qt\preferences_dialog.py:286
msgid "Display"
msgstr "Anzeige"

View File

@@ -1,121 +1,123 @@
# Translators: # Translators:
# Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2016-07-22 11:30+0000\n" "Language-Team: Greek (https://www.transifex.com/voltaicideas/teams/116153/el/)\n"
"Last-Translator: 1kakarot\n" "Language: el\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: el\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: core/gui/ignore_list_table.py:18 core/gui/ignore_list_table.py:19 #: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core/gui/problem_table.py:17 #: core\gui\problem_table.py:18
msgid "File Path" msgid "File Path"
msgstr "Διαδρομή αρχείου" msgstr "Διαδρομή αρχείου"
#: core/gui/problem_table.py:18 #: core\gui\problem_table.py:19
msgid "Error Message" msgid "Error Message"
msgstr "Μήνυμα σφάλματος" msgstr "Μήνυμα σφάλματος"
#: core/me/result_table.py:24 core/pe/result_table.py:21 core/prioritize.py:63 #: core\me\prioritize.py:23
#: core/se/result_table.py:21
msgid "Kind"
msgstr "Τύπος"
#: core/me/result_table.py:19 core/pe/result_table.py:19 core/prioritize.py:72
#: core/se/result_table.py:19
msgid "Folder"
msgstr "Φάκελος"
#: core/me/result_table.py:18 core/pe/result_table.py:18 core/prioritize.py:88
#: core/se/result_table.py:18
msgid "Filename"
msgstr "Όνομα αρχείου"
#: core/prioritize.py:147
msgid "Size"
msgstr "Μέγεθος-Διαστάσεις?"
#: core/me/result_table.py:25 core/pe/result_table.py:24
#: core/prioritize.py:153 core/se/result_table.py:22
msgid "Modification"
msgstr "Τροποποίηση"
#: core/me/prioritize.py:18
msgid "Duration" msgid "Duration"
msgstr "Διάρκεια" msgstr "Διάρκεια"
#: core/me/prioritize.py:24 core/me/result_table.py:22 #: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate" msgid "Bitrate"
msgstr "Bitrate" msgstr "Bitrate"
#: core/me/prioritize.py:30 #: core\me\prioritize.py:37
msgid "Samplerate" msgid "Samplerate"
msgstr "" msgstr "Ρυθμός δειγματοληψίας"
#: core/me/result_table.py:20 #: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
#: core\se\result_table.py:19
msgid "Filename"
msgstr "Όνομα αρχείου"
#: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core\se\result_table.py:20
msgid "Folder"
msgstr "Φάκελος"
#: core\me\result_table.py:21
msgid "Size (MB)" msgid "Size (MB)"
msgstr "Μέγεθος (MB)" msgstr "Μέγεθος (MB)"
#: core/me/result_table.py:21 #: core\me\result_table.py:22
msgid "Time" msgid "Time"
msgstr "Χρόνος" msgstr "Χρόνος"
#: core/me/result_table.py:23 #: core\me\result_table.py:24
msgid "Sample Rate" msgid "Sample Rate"
msgstr "Ρυθμός δειγματοληψίας" msgstr "Ρυθμός δειγματοληψίας"
#: core/me/result_table.py:26 #: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core\se\result_table.py:22
msgid "Kind"
msgstr "Τύπος"
#: core\me\result_table.py:26 core\pe\result_table.py:25
#: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification"
msgstr "Τροποποίηση"
#: core\me\result_table.py:27
msgid "Title" msgid "Title"
msgstr "Τίτλος" msgstr "Τίτλος"
#: core/me/result_table.py:27 #: core\me\result_table.py:28
msgid "Artist" msgid "Artist"
msgstr "Καλλιτέχνης" msgstr "Καλλιτέχνης"
#: core/me/result_table.py:28 #: core\me\result_table.py:29
msgid "Album" msgid "Album"
msgstr "Αλμπουμ" msgstr "Αλμπουμ"
#: core/me/result_table.py:29 #: core\me\result_table.py:30
msgid "Genre" msgid "Genre"
msgstr "Είδος" msgstr "Είδος"
#: core/me/result_table.py:30 #: core\me\result_table.py:31
msgid "Year" msgid "Year"
msgstr "Έτος" msgstr "Έτος"
#: core/me/result_table.py:31 #: core\me\result_table.py:32
msgid "Track Number" msgid "Track Number"
msgstr "Αριθμός κομματιού" msgstr "Αριθμός κομματιού"
#: core/me/result_table.py:32 #: core\me\result_table.py:33
msgid "Comment" msgid "Comment"
msgstr "Σχόλιο" msgstr "Σχόλιο"
#: core/me/result_table.py:33 core/pe/result_table.py:25 #: core\me\result_table.py:34 core\pe\result_table.py:26
#: core/se/result_table.py:23 #: core\se\result_table.py:24
msgid "Match %" msgid "Match %"
msgstr "Ταύτιση %" msgstr "Ταύτιση %"
#: core/me/result_table.py:34 core/se/result_table.py:24 #: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used" msgid "Words Used"
msgstr "Χρησιμοποιημένες λέξεις" msgstr "Χρησιμοποιημένες λέξεις"
#: core/me/result_table.py:35 core/pe/result_table.py:26 #: core\me\result_table.py:36 core\pe\result_table.py:27
#: core/se/result_table.py:25 #: core\se\result_table.py:26
msgid "Dupe Count" msgid "Dupe Count"
msgstr "Αριθμός διπλοτύπων" msgstr "Αριθμός διπλοτύπων"
#: core/pe/prioritize.py:18 core/pe/result_table.py:22 #: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions" msgid "Dimensions"
msgstr "Διαστάσεις" msgstr "Διαστάσεις"
#: core/pe/result_table.py:20 core/se/result_table.py:20 #: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)" msgid "Size (KB)"
msgstr "Μέγεθος (KB)" msgstr "Μέγεθος (KB)"
#: core/pe/result_table.py:23 #: core\pe\result_table.py:24
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "Χρονοσήμανση EXIF" msgstr "Χρονοσήμανση EXIF"
#: core\prioritize.py:156
msgid "Size"
msgstr "Μέγεθος-Διαστάσεις?"

View File

@@ -1,23 +1,25 @@
# Translators: # Translators:
# Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2016-07-22 11:30+0000\n" "Language-Team: Greek (https://www.transifex.com/voltaicideas/teams/116153/el/)\n"
"Last-Translator: 1kakarot\n" "Language: el\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: el\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: core/app.py:40 #: core\app.py:42
msgid "There are no marked duplicates. Nothing has been done." msgid "There are no marked duplicates. Nothing has been done."
msgstr "Δεν υπάρχουν μαρκαρισμένα διπλότυπα. Δεν έγινε τίποτα." msgstr "Δεν υπάρχουν μαρκαρισμένα διπλότυπα. Δεν έγινε τίποτα."
#: core/app.py:41 #: core\app.py:43
msgid "There are no selected duplicates. Nothing has been done." msgid "There are no selected duplicates. Nothing has been done."
msgstr "Δεν υπάρχουν επιλεγμένα διπλότυπα. Δεν έγινε τίποτα." msgstr "Δεν υπάρχουν επιλεγμένα διπλότυπα. Δεν έγινε τίποτα."
#: core/app.py:42 #: core\app.py:44
msgid "" msgid ""
"You're about to open many files at once. Depending on what those files are " "You're about to open many files at once. Depending on what those files are "
"opened with, doing so can create quite a mess. Continue?" "opened with, doing so can create quite a mess. Continue?"
@@ -26,27 +28,27 @@ msgstr ""
"ανοίγουν αυτάτα αρχεία, κάτι τέτοιο μπορεί να προκαλέσει ένα μικρό χάος. " "ανοίγουν αυτάτα αρχεία, κάτι τέτοιο μπορεί να προκαλέσει ένα μικρό χάος. "
"Συνέχεια;" "Συνέχεια;"
#: core/app.py:65 #: core\app.py:71
msgid "Scanning for duplicates" msgid "Scanning for duplicates"
msgstr "Σάρωση για διπλότυπα" msgstr "Σάρωση για διπλότυπα"
#: core/app.py:66 #: core\app.py:72
msgid "Loading" msgid "Loading"
msgstr "Φόρτωση" msgstr "Φόρτωση"
#: core/app.py:67 #: core\app.py:73
msgid "Moving" msgid "Moving"
msgstr "Μετακίνηση" msgstr "Μετακίνηση"
#: core/app.py:68 #: core\app.py:74
msgid "Copying" msgid "Copying"
msgstr "Αντιγραφή" msgstr "Αντιγραφή"
#: core/app.py:69 #: core\app.py:75
msgid "Sending to Trash" msgid "Sending to Trash"
msgstr "Αποστολή στα σκουπίδια" msgstr "Αποστολή στα σκουπίδια"
#: core/app.py:279 #: core\app.py:308
msgid "" msgid ""
"A previous action is still hanging in there. You can't start a new one yet. " "A previous action is still hanging in there. You can't start a new one yet. "
"Wait a few seconds, then try again." "Wait a few seconds, then try again."
@@ -54,216 +56,201 @@ msgstr ""
"Μια προηγούμενη ενέργεια είναι σε εξέλιξη. Δεν μπορείτε να ξεκινήσετε " "Μια προηγούμενη ενέργεια είναι σε εξέλιξη. Δεν μπορείτε να ξεκινήσετε "
"καινούργια ακόμα. Περιμένετε λίγα δευτερόλεπτα, έπειτα προσπαθήστε ξανά." "καινούργια ακόμα. Περιμένετε λίγα δευτερόλεπτα, έπειτα προσπαθήστε ξανά."
#: core/app.py:289 #: core\app.py:318
msgid "No duplicates found." msgid "No duplicates found."
msgstr "Δεν βρέθηκαν διπλότυπα." msgstr "Δεν βρέθηκαν διπλότυπα."
#: core/app.py:304 #: core\app.py:333
msgid "All marked files were copied successfully." msgid "All marked files were copied successfully."
msgstr "Όλα τα επιλεγμένα αρχεία αντιγράφηκαν επιτυχώς." msgstr "Όλα τα επιλεγμένα αρχεία αντιγράφηκαν επιτυχώς."
#: core/app.py:305 #: core\app.py:334
msgid "All marked files were moved successfully." msgid "All marked files were moved successfully."
msgstr "Όλα τα επιλεγμένα αρχεία μετακινήθηκαν επιτυχώς." msgstr "Όλα τα επιλεγμένα αρχεία μετακινήθηκαν επιτυχώς."
#: core/app.py:306 #: core\app.py:335
msgid "All marked files were successfully sent to Trash." msgid "All marked files were successfully sent to Trash."
msgstr "Όλα τα επιλεγμένα αρχεία στάλθηκαν με επιτυχία στον κάδο." msgstr "Όλα τα επιλεγμένα αρχεία στάλθηκαν με επιτυχία στον κάδο."
#: core/app.py:368 #: core\app.py:343
msgid "Could not load file: {}"
msgstr "Δεν ήταν δυνατή η φόρτωση του αρχείου: {}"
#: core\app.py:399
msgid "'{}' already is in the list." msgid "'{}' already is in the list."
msgstr "'{}' υπάρχει ήδη στη λίστα." msgstr "'{}' υπάρχει ήδη στη λίστα."
#: core/app.py:370 #: core\app.py:401
msgid "'{}' does not exist." msgid "'{}' does not exist."
msgstr "'{}' δεν υπάρχει." msgstr "'{}' δεν υπάρχει."
#: core/app.py:379 #: core\app.py:410
msgid "" msgid ""
"All selected %d matches are going to be ignored in all subsequent scans. " "All selected %d matches are going to be ignored in all subsequent scans. "
"Continue?" "Continue?"
msgstr "" msgstr ""
"Όλα τα επιλεγμένα %d στοιχεία θα αγνοηθούν σε μελλοντικές σαρώσεις.Συνέχεια;" "Όλα τα επιλεγμένα %d στοιχεία θα αγνοηθούν σε μελλοντικές σαρώσεις.Συνέχεια;"
#: core/app.py:450 #: core\app.py:486
msgid "copy" msgid "Select a directory to copy marked files to"
msgstr "αντιγραφή" msgstr "Επιλέξτε έναν κατάλογο για να αντιγράψετε επισημασμένα αρχεία."
#: core/app.py:450 #: core\app.py:487
msgid "move" msgid "Select a directory to move marked files to"
msgstr "μετακίνηση" msgstr "Επιλέξτε έναν κατάλογο για να μετακινήσετε τα επισημασμένα αρχεία."
#: core/app.py:451 #: core\app.py:527
msgid "Select a directory to {} marked files to"
msgstr "Επιλέξτε ένα φάκελο {} για τα μαρκαρισμένα αρχεία"
#: core/app.py:490
msgid "Select a destination for your exported CSV" msgid "Select a destination for your exported CSV"
msgstr "Επιλέξτε έναν προορισμό για το εξαγόμενο CSV σας" msgstr "Επιλέξτε έναν προορισμό για το εξαγόμενο CSV σας"
#: core/app.py:518 #: core\app.py:534 core\app.py:801 core\app.py:811
msgid "Couldn't write to file: {}"
msgstr "Δεν ήταν δυνατή η εγγραφή στο αρχείο: {}"
#: core\app.py:559
msgid "You have no custom command set up. Set it up in your preferences." msgid "You have no custom command set up. Set it up in your preferences."
msgstr "Δεν έχετε ορίσει ειδική εντολή. Ρυθμίστε τη στις προτιμήσεις σας. " msgstr "Δεν έχετε ορίσει ειδική εντολή. Ρυθμίστε τη στις προτιμήσεις σας. "
#: core/app.py:672 core/app.py:685 #: core\app.py:727 core\app.py:740
msgid "You are about to remove %d files from results. Continue?" msgid "You are about to remove %d files from results. Continue?"
msgstr "Πρόκειται να αφαιρέσετε %d αρχεία από τα αποτελέσματα. Συνέχεια;" msgstr "Πρόκειται να αφαιρέσετε %d αρχεία από τα αποτελέσματα. Συνέχεια;"
#: core/app.py:719 #: core\app.py:774
msgid "{} duplicate groups were changed by the re-prioritization." msgid "{} duplicate groups were changed by the re-prioritization."
msgstr "{} ομάδες διπλοτύπων άλλαξαν από το επαναπροσδιορισμό." msgstr "{} ομάδες διπλοτύπων άλλαξαν από το επαναπροσδιορισμό."
#: core/app.py:762 #: core\app.py:821
msgid "Collecting files to scan"
msgstr "Συλλογή αρχείων για σάρωση"
#: core/app.py:751
msgid "The selected directories contain no scannable file." msgid "The selected directories contain no scannable file."
msgstr "Οι επιλεγμένοι φάκελοι δεν περιέχουν σαρώσιμα αρχεία." msgstr "Οι επιλεγμένοι φάκελοι δεν περιέχουν σαρώσιμα αρχεία."
#: core/app.py:810 #: core\app.py:835
msgid "Collecting files to scan"
msgstr "Συλλογή αρχείων για σάρωση"
#: core\app.py:891
msgid "%s (%d discarded)" msgid "%s (%d discarded)"
msgstr "%s (%d απορρίφθηκαν)" msgstr "%s (%d απορρίφθηκαν)"
#: core/engine.py:222 core/engine.py:262 #: core\engine.py:244 core\engine.py:288
msgid "0 matches found" msgid "0 matches found"
msgstr "0 διπλότυπα βρέθηκαν" msgstr "0 διπλότυπα βρέθηκαν"
#: core/engine.py:240 core/engine.py:270 #: core\engine.py:262 core\engine.py:296
msgid "%d matches found" msgid "%d matches found"
msgstr "Βρέθηκαν %d διπλότυπα" msgstr "Βρέθηκαν %d διπλότυπα"
#: core/scanner.py:77 #: core\gui\deletion_options.py:73
msgid "Read size of %d/%d files"
msgstr "Ανάγνωση μεγέθους %d/%d αρχείων"
#: core/gui/deletion_options.py:69
msgid "You are sending {} file(s) to the Trash." msgid "You are sending {} file(s) to the Trash."
msgstr "Στέλνετε {} αρχεία στα σκουπίδια." msgstr "Στέλνετε {} αρχεία στα σκουπίδια."
#: core/gui/ignore_list_dialog.py:24 #: core\gui\exclude_list_table.py:15
msgid "Regular Expressions"
msgstr "Κανονικές εκφράσεις"
#: core\gui\ignore_list_dialog.py:25
msgid "Do you really want to remove all %d items from the ignore list?" msgid "Do you really want to remove all %d items from the ignore list?"
msgstr "Θέλετε να αφαιρέσετε όλα τα %d στοιχεία από τη λίστα αγνόησης; " msgstr "Θέλετε να αφαιρέσετε όλα τα %d στοιχεία από τη λίστα αγνόησης; "
#: core/prioritize.py:68 #: core\me\scanner.py:20 core\se\scanner.py:16
msgid "None" msgid "Filename"
msgstr "Καμμία" msgstr "Ονομα αρχείου"
#: core/prioritize.py:96 #: core\me\scanner.py:21
msgid "Ends with number" msgid "Filename - Fields"
msgstr "Λήγει με αριθμό" msgstr "Όνομα αρχείου - Πεδία"
#: core/prioritize.py:97 #: core\me\scanner.py:22
msgid "Doesn't end with number" msgid "Filename - Fields (No Order)"
msgstr "Δεν λήγει με αριθμό" msgstr "Όνομα αρχείου - Πεδία (Χωρίς παραγγελία)"
#: core/prioritize.py:98 #: core\me\scanner.py:23
msgid "Longest" msgid "Tags"
msgstr "Μεγαλύτερο" msgstr "ετικέτα"
#: core/prioritize.py:99 #: core\me\scanner.py:24 core\pe\scanner.py:21 core\se\scanner.py:17
msgid "Shortest" msgid "Contents"
msgstr "Μικρότερο" msgstr "Περιεχόμενα"
#: core/prioritize.py:132 #: core\pe\matchblock.py:72
msgid "Highest"
msgstr "Υψηλότερη"
#: core/prioritize.py:132
msgid "Lowest"
msgstr "Χαμηλότερη"
#: core/prioritize.py:159
msgid "Newest"
msgstr "Νεώτερο"
#: core/prioritize.py:159
msgid "Oldest"
msgstr "Παλαιότερο"
#: core/results.py:129
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) επιλεγμένα διπλότυπα."
#: core/results.py:136
msgid " filter: %s"
msgstr " φίλτρο: %s"
#: core/scanner.py:101
msgid "Read metadata of %d/%d files"
msgstr "Ανάγνωση μεταδεδομένων των %d/%d αρχείων"
#: core/pe/matchblock.py:61
msgid "Analyzed %d/%d pictures" msgid "Analyzed %d/%d pictures"
msgstr "Ανάλυση %d/%d εικόνων" msgstr "Ανάλυση %d/%d εικόνων"
#: core/pe/matchblock.py:156 #: core\pe\matchblock.py:181
msgid "Performed %d/%d chunk matches" msgid "Performed %d/%d chunk matches"
msgstr "Εκτέλεση %d/%d μερικής ταυτοποίησης" msgstr "Εκτέλεση %d/%d μερικής ταυτοποίησης"
#: core/pe/matchblock.py:161 #: core\pe\matchblock.py:191
msgid "Preparing for matching" msgid "Preparing for matching"
msgstr "Προετοιμασία για σύγκριση" msgstr "Προετοιμασία για σύγκριση"
#: core/pe/matchblock.py:206 #: core\pe\matchblock.py:244
msgid "Verified %d/%d matches" msgid "Verified %d/%d matches"
msgstr "Πιστοποίηση %d/%d ταυτόσημων" msgstr "Πιστοποίηση %d/%d ταυτόσημων"
#: core/pe/matchexif.py:18 #: core\pe\matchexif.py:19
msgid "Read EXIF of %d/%d pictures" msgid "Read EXIF of %d/%d pictures"
msgstr "Ανάγνωση EXIF %d/%d εικόνες" msgstr "Ανάγνωση EXIF %d/%d εικόνες"
#: core/app.py:312 #: core\pe\scanner.py:22
msgid "Could not load file: {}"
msgstr ""
#: core/app.py:496 core/app.py:742
msgid "Couldn't write to file: {}"
msgstr ""
#: core/me/scanner.py:19 core/se/scanner.py:15
msgid "Filename"
msgstr ""
#: core/me/scanner.py:20
msgid "Filename - Fields"
msgstr ""
#: core/me/scanner.py:21
msgid "Filename - Fields (No Order)"
msgstr ""
#: core/me/scanner.py:22
msgid "Tags"
msgstr ""
#: core/me/scanner.py:23 core/pe/scanner.py:20 core/se/scanner.py:16
msgid "Contents"
msgstr ""
#: core/pe/scanner.py:21
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "" msgstr "Χρονική σήμανση EXIF"
#: core/scanner.py:139 #: core\prioritize.py:70
msgid "None"
msgstr "Καμμία"
#: core\prioritize.py:100
msgid "Ends with number"
msgstr "Λήγει με αριθμό"
#: core\prioritize.py:101
msgid "Doesn't end with number"
msgstr "Δεν λήγει με αριθμό"
#: core\prioritize.py:102
msgid "Longest"
msgstr "Μεγαλύτερο"
#: core\prioritize.py:103
msgid "Shortest"
msgstr "Μικρότερο"
#: core\prioritize.py:140
msgid "Highest"
msgstr "Υψηλότερη"
#: core\prioritize.py:140
msgid "Lowest"
msgstr "Χαμηλότερη"
#: core\prioritize.py:169
msgid "Newest"
msgstr "Νεώτερο"
#: core\prioritize.py:169
msgid "Oldest"
msgstr "Παλαιότερο"
#: core\results.py:142
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) επιλεγμένα διπλότυπα."
#: core\results.py:149
msgid " filter: %s"
msgstr " φίλτρο: %s"
#: core\scanner.py:85
msgid "Read size of %d/%d files"
msgstr "Ανάγνωση μεγέθους %d/%d αρχείων"
#: core\scanner.py:109
msgid "Read metadata of %d/%d files"
msgstr "Ανάγνωση μεταδεδομένων των %d/%d αρχείων"
#: core\scanner.py:147
msgid "Almost done! Fiddling with results..." msgid "Almost done! Fiddling with results..."
msgstr "" msgstr "Σχεδόν τελείωσα! Παιχνίδι με αποτελέσματα ..."
#: core/se/scanner.py:17 #: core\se\scanner.py:18
msgid "Folders" msgid "Folders"
msgstr "" msgstr "ντοσιέ"
#~ msgid "Sending files to the recycle bin"
#~ msgstr "Αποστολή στον κάδο ανακύκλωσης"
#~ msgid "Grouped %d/%d matches"
#~ msgstr "Ομαδοποιημένα %d/%d διπλότυπα"
#~ msgid "Removing false matches"
#~ msgstr "Αφαίρεση ψευδών διπλοτύπων"
#~ msgid "Processed %d/%d matches against the ignore list"
#~ msgstr "Επεξεργάσία %d/%d διπλοτύπων σε σχέση με τη λίστα αγνόησης"
#~ msgid "Doing group prioritization"
#~ msgstr "Εργασία ομαδοποιημένης προτεραιότητας"

View File

@@ -1,27 +1,34 @@
# Translators: # Translators:
# Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2016-07-22 11:30+0000\n" "Language-Team: Greek (https://www.transifex.com/voltaicideas/teams/116153/el/)\n"
"Last-Translator: 1kakarot\n" "Language: el\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: el\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0
msgid "Application Mode:"
msgstr "Λειτουργία εφαρμογής:"
#: qt/app.py:81 #: qt/app.py:81
msgid "Quit" msgid "Quit"
msgstr "Έξοδος" msgstr "Έξοδος"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Επιλογές"
#: qt/app.py:83 qt/ignore_list_dialog.py:32 #: qt/app.py:83 qt/ignore_list_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Ignore List" msgid "Ignore List"
msgstr "Λίστα αγνόησης" msgstr "Λίστα αγνόησης"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Εκκαθάριση μνήμης cache εικόνων"
#: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0 #: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Help" msgid "dupeGuru Help"
msgstr "Βοήθεια για το dupeGuru" msgstr "Βοήθεια για το dupeGuru"
@@ -34,6 +41,15 @@ msgstr "Σχετικά με το dupeGuru"
msgid "Open Debug Log" msgid "Open Debug Log"
msgstr "Άνοιγμα αρχείου αποσφαλμάτωσης" msgstr "Άνοιγμα αρχείου αποσφαλμάτωσης"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr ""
"Θέλετε πραγματικά να αφαιρέσετε όλη την αποθηκευμένη ανάλυση εικόνων σας;"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "Μνήμη cache εικόνων εκκαθαρίστηκε."
#: qt/app.py:251 #: qt/app.py:251
msgid "{} file (*.{})" msgid "{} file (*.{})"
msgstr "{} αρχείο (*.{})" msgstr "{} αρχείο (*.{})"
@@ -56,11 +72,11 @@ msgstr ""
#: qt/deletion_options.py:44 #: qt/deletion_options.py:44
msgid "Hardlink" msgid "Hardlink"
msgstr "" msgstr "Σκληρός σύνδεσμος"
#: qt/deletion_options.py:44 #: qt/deletion_options.py:44
msgid "Symlink" msgid "Symlink"
msgstr "" msgstr "συμβολικός σύνδεσμος"
#: qt/deletion_options.py:48 #: qt/deletion_options.py:48
msgid " (unsupported)" msgid " (unsupported)"
@@ -130,6 +146,30 @@ msgstr "Βοήθεια"
msgid "Load Recent Results" msgid "Load Recent Results"
msgstr "Φόρτωση πρόσφατων αποτελεσμάτων" msgstr "Φόρτωση πρόσφατων αποτελεσμάτων"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0
msgid "Application Mode:"
msgstr "Λειτουργία εφαρμογής:"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Music"
msgstr "μουσική"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Picture"
msgstr "Εικόνα"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Standard"
msgstr "πρότυπο"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0
msgid "Scan Type:"
msgstr "Είδος σάρωσης"
#: qt/directories_dialog.py:135
msgid "More Options"
msgstr "Περισσότερες επιλογές"
#: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0 #: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0
msgid "Select folders to scan and press \"Scan\"." msgid "Select folders to scan and press \"Scan\"."
msgstr "Επιλέξτε τους φακέλους για να σαρώσετε και πατήστε το πλήκτρο \"Σάρωση\"." msgstr "Επιλέξτε τους φακέλους για να σαρώσετε και πατήστε το πλήκτρο \"Σάρωση\"."
@@ -205,9 +245,78 @@ msgstr "Αφαίρεση"
msgid "Close" msgid "Close"
msgstr "Κλείσιμο" msgstr "Κλείσιμο"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0 #: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
msgid "Scan Type:" #: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
msgstr "Είδος σάρωσης" #: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Λεπτομέρειες"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Ετικέτες προς σάρωση:"
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Κομμάτι"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Καλλιτέχνης"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Άλμπουμ"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Τίτλος"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Είδος"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Έτος"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "Στάθμιση λέξης"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Ταίριασμα παρόμοιων λέξεων"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Να περιλαμβάνουν διαφορετικούς τύπους αρχείων"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Χρήση κανονικών εκφράσεων κατά το φιλτράρισμα"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Κατάργηση κενών φακέλων για διαγραφή ή μετακίνηση"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Αγνόηση διπλοτύπων με hardlinking στο ίδιο αρχείο"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Λειτουργία αποσφαλμάτωσης(απαιτείται επανεκκίνηση)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Ταίριασμα εικόνων διαφορετικών διαστάσεων"
#: qt/preferences_dialog.py:43 #: qt/preferences_dialog.py:43
msgid "Filter Hardness:" msgid "Filter Hardness:"
@@ -289,12 +398,6 @@ msgstr ""
msgid "Reveal Selected" msgid "Reveal Selected"
msgstr "Αποκάλυψη επιλεγμένων" msgstr "Αποκάλυψη επιλεγμένων"
#: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
#: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Λεπτομέρειες"
#: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167 #: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167
#: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0
msgid "Actions" msgid "Actions"
@@ -412,86 +515,6 @@ msgstr "Τιμές διαφοράς (Delta)"
msgid "Select a file to save your results to" msgid "Select a file to save your results to"
msgstr "Επιλέξτε ένα αρχείο για να αποθηκεύσετε τα αποτελέσματα σας" msgstr "Επιλέξτε ένα αρχείο για να αποθηκεύσετε τα αποτελέσματα σας"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Ετικέτες προς σάρωση:"
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Κομμάτι"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Καλλιτέχνης"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Άλμπουμ"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Τίτλος"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Είδος"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Έτος"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "Στάθμιση λέξης"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Ταίριασμα παρόμοιων λέξεων"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Να περιλαμβάνουν διαφορετικούς τύπους αρχείων"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Χρήση κανονικών εκφράσεων κατά το φιλτράρισμα"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Κατάργηση κενών φακέλων για διαγραφή ή μετακίνηση"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Αγνόηση διπλοτύπων με hardlinking στο ίδιο αρχείο"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Λειτουργία αποσφαλμάτωσης(απαιτείται επανεκκίνηση)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Ταίριασμα εικόνων διαφορετικών διαστάσεων"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Εκκαθάριση μνήμης cache εικόνων"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr ""
"Θέλετε πραγματικά να αφαιρέσετε όλη την αποθηκευμένη ανάλυση εικόνων σας;"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "Μνήμη cache εικόνων εκκαθαρίστηκε."
#: qt/se/preferences_dialog.py:41 #: qt/se/preferences_dialog.py:41
msgid "Ignore files smaller than" msgid "Ignore files smaller than"
msgstr "Αγνόηση αρχείων μικρότερων από" msgstr "Αγνόηση αρχείων μικρότερων από"
@@ -567,7 +590,7 @@ msgstr "Φάκελοι"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru" msgid "dupeGuru"
msgstr "" msgstr "dupeGuru"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Preferences" msgid "dupeGuru Preferences"
@@ -649,11 +672,6 @@ msgstr "Περισσότερα αποτελέσματα"
msgid "Ok" msgid "Ok"
msgstr "Ok" msgstr "Ok"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Επιλογές"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Paste" msgid "Paste"
msgstr "Επικόλληση" msgstr "Επικόλληση"
@@ -718,110 +736,221 @@ msgstr "Παράθυρο"
msgid "Zoom" msgid "Zoom"
msgstr "Ζουμ" msgstr "Ζουμ"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\app.py:158
msgid "Music" msgid "Exclusion Filters"
msgstr "Φίλτρα αποκλεισμού"
#: qt\directories_dialog.py:91
msgid "Scan Results"
msgstr "Αποτελέσματα σάρωσης"
#: qt\directories_dialog.py:95
msgid "Load Directories..."
msgstr "Φόρτωση καταλόγων..."
#: qt\directories_dialog.py:96
msgid "Save Directories..."
msgstr "Αποθήκευση καταλόγων..."
#: qt\directories_dialog.py:337
msgid "Select a directories file to load"
msgstr "Επιλέξτε ένα αρχείο καταλόγων για φόρτωση"
#: qt\directories_dialog.py:338
msgid "dupeGuru Results (*.dupegurudirs)"
msgstr "καταλόγους του dupeguru (*.dupegurudirs)"
#: qt\directories_dialog.py:347
msgid "Select a file to save your directories to"
msgstr "Επιλέξτε ένα αρχείο για να αποθηκεύσετε τους καταλόγους σας"
#: qt\directories_dialog.py:348
msgid "dupeGuru Directories (*.dupegurudirs)"
msgstr "καταλόγους του dupeguru (*.dupegurudirs)"
#: qt\exclude_list_dialog.py:44
msgid "Add"
msgstr "Προσθήκη"
#: qt\exclude_list_dialog.py:46
msgid "Restore defaults"
msgstr "Επαναφέρετε τις προεπιλογές"
#: qt\exclude_list_dialog.py:47
msgid "Test string"
msgstr "Σειρά δοκιμής"
#: qt\exclude_list_dialog.py:83
msgid "Type a python regular expression here..."
msgstr "Πληκτρολογήστε μια τυπική έκφραση python εδώ..."
#: qt\exclude_list_dialog.py:85
msgid "Type a file system path or filename here..."
msgstr "Πληκτρολογήστε μια διαδρομή συστήματος ή ένα όνομα αρχείου εδώ..."
#: qt\exclude_list_dialog.py:152
msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happen to match one of the regular expressions.<br>For each file collected two tests are perfomed on each of them to determine whether or not to filter them out:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with no path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the test string feature by pasting a fake path in it:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr "" msgstr ""
"Αυτές οι τυπικές εκφράσεις python (πεζών-κεφαλαίων) θα φιλτράρουν τα αρχεία κατά τη διάρκεια των σαρώσεων.<br>Οι διευθυντές θα έχουν επίσης την <strong>προεπιλεγμένη κατάστασή</strong> τους σε Εξαίρεση στην καρτέλα Κατάλογοι εάν το όνομά τους συμβαίνει να ταιριάζει με μία από τις επιλεγμένες κανονικές εκφράσεις.<br>Για κάθε αρχείο που συλλέγεται, εκτελούνται δύο δοκιμές για να προσδιοριστεί εάν θα το αγνοηθεί πλήρως ή όχι:<br><li>1. Οι κανονικές εκφράσεις χωρίς διαχωριστικό διαδρομών σε αυτές θα συγκρίνονται μόνο με το όνομα αρχείου.</li>\n"
"<li>2. Οι κανονικές εκφράσεις με τουλάχιστον ένα διαχωριστικό διαδρομών σε αυτές θα συγκριθούν με την πλήρη διαδρομή προς το αρχείο.</li><br>\n"
"Παράδειγμα: εάν θέλετε να φιλτράρετε αρχεία .PNG μόνο από τον κατάλογο \"Οι εικόνες μου\":<br><code>.*Οι\\sεικόνες\\sμου\\\\.*\\.png</code><br><br>Μπορείτε να δοκιμάσετε την κανονική έκφραση με το κουμπί \"δοκιμαστική συμβολοσειρά\" αφού επικολλήσετε μια ψεύτικη διαδρομή στο πεδίο δοκιμής:<br><code>C:\\\\χρήστης\\Οι εικόνες μου\\test.png</code><br><br>\n"
"Θα επισημανθεί η αντιστοίχιση των τυπικών εκφράσεων.<br>Εάν υπάρχει τουλάχιστον μία επισήμανση, η διαδρομή ή το όνομα αρχείου που δοκιμάστηκε θα αγνοηθεί κατά τη διάρκεια των σαρώσεων.<br><br>Κατάλογοι και αρχεία που ξεκινούν με τελεία \".\" φιλτράρονται από προεπιλογή.<br><br>"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\exclude_list_table.py:36
msgid "Picture" msgid "Compilation error: "
msgstr "Σφάλμα συλλογής:"
#: qt\pe\image_viewer.py:56
msgid "Increase zoom"
msgstr "Αυξήστε το ζουμ"
#: qt\pe\image_viewer.py:66
msgid "Decrease zoom"
msgstr "Μείωση ζουμ"
#: qt\pe\image_viewer.py:71
msgid "Ctrl+/"
msgstr "Ctrl+/"
#: qt\pe\image_viewer.py:76
msgid "Normal size"
msgstr "Κανονικό μέγεθος"
#: qt\pe\image_viewer.py:81
msgid "Ctrl+*"
msgstr "Ctrl+*"
#: qt\pe\image_viewer.py:86
msgid "Best fit"
msgstr "ταιριάζει καλύτερα"
#: qt\pe\preferences_dialog.py:49
msgid "Picture cache mode:"
msgstr "Λειτουργία προσωρινής μνήμης εικόνας:"
#: qt\pe\preferences_dialog.py:56
msgid "Override theme icons in viewer toolbar"
msgstr "" msgstr ""
"Παράκαμψη εικονιδίων θέματος στη γραμμή εργαλείων του προγράμματος προβολής"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\pe\preferences_dialog.py:58
msgid "Standard" msgid ""
"Use our own internal icons instead of those provided by the theme engine"
msgstr "" msgstr ""
"Χρησιμοποιήστε τα δικά μας εσωτερικά εικονίδια αντί αυτών που παρέχονται από"
" τη μηχανή θέματος"
#: qt/directories_dialog.py:135 #: qt\pe\preferences_dialog.py:66
msgid "More Options" msgid "Show scrollbars in image viewers"
msgstr "Εμφάνιση γραμμών κύλισης σε προγράμματα προβολής εικόνων"
#: qt\pe\preferences_dialog.py:68
msgid ""
"When the image displayed doesn't fit the viewport, show scrollbars to span "
"the view around"
msgstr "" msgstr ""
"Όταν η εικόνα που εμφανίζεται δεν ταιριάζει στη θύρα προβολής, εμφανίστε τις"
" γραμμές κύλισης για να εκτείνετε την προβολή γύρω"
#~ msgid "Removing dead tracks from your iTunes Library" #: qt\preferences_dialog.py:156
#~ msgstr "Αφαίρεση νεκρών κομματιών από την βιβλιοθήκη σας iTunes" msgid "Use default position for tab bar (requires restart)"
msgstr ""
"Χρησιμοποιήστε την προεπιλεγμένη θέση για τη γραμμή καρτελών (απαιτείται "
"επανεκκίνηση)"
#~ msgid "Scanning the iTunes Library" #: qt\preferences_dialog.py:158
#~ msgstr "Σάρωση της βιβλιοθήκης σας iTunes" msgid ""
"Place the tab bar below the main menu instead of next to it\n"
"On MacOS, the tab bar will fill up the window's width instead."
msgstr ""
"Τοποθετήστε τη γραμμή καρτελών κάτω από το κύριο μενού και όχι δίπλα σε αυτό\n"
"Σε MacOS, η γραμμή καρτελών θα γεμίσει το πλάτος του παραθύρου."
#~ msgid "Sending dupes to the Trash" #: qt\preferences_dialog.py:172
#~ msgstr "Αποστολή διπλοτύπων στα Σκουπίδια" msgid "Use bold font for references"
msgstr "Χρησιμοποιήστε έντονη γραμματοσειρά για αναφορές"
#~ msgid "Talking to iTunes. Don't touch it!" #: qt\preferences_dialog.py:176
#~ msgstr "Μιλώντας στο iTunes. Μην το αγγίζετε!" msgid "Reference foreground color:"
msgstr "Χρώμα προσκηνίου αναφοράς:"
#~ msgid "" #: qt\preferences_dialog.py:179
#~ "Your iTunes Library contains %d dead tracks ready to be removed. Continue?" msgid "Reference background color:"
#~ msgstr "" msgstr "Χρώμα προσκηνίου αναφοράς:"
#~ "Η βιβλιοθήκη σας iTunes περιέχει %d νεκρά κομμάτια έτοιμα να αφαιρεθούν. "
#~ "Συνέχεια;"
#~ msgid "You have no dead tracks in your iTunes Library" #: qt\preferences_dialog.py:182 qt\preferences_dialog.py:216
#~ msgstr "Η βιβλιοθήκη σας iTunes δεν περιέχει νεκρά κομμάτια" msgid "Delta foreground color:"
msgstr "Χρώμα προσκηνίου δέλτα:"
#~ msgid "The iTunes application couldn't be found." #: qt\preferences_dialog.py:195
#~ msgstr "Η εφαρμογή iTunes δεν βρέθηκε." msgid "Show the title bar and can be docked"
msgstr "Εμφάνιση της γραμμής τίτλου και δυνατότητα σύνδεσης"
#~ msgid "Talking to iPhoto. Don't touch it!" #: qt\preferences_dialog.py:197
#~ msgstr "Μιλώντας στο iPhoto. Μην το αγγίζετε!" msgid ""
"While the title bar is hidden, use the modifier key to drag the floating "
"window around"
msgstr ""
"Ενώ η γραμμή τίτλου είναι κρυφή, χρησιμοποιήστε το πλήκτρο τροποποίησης για "
"να σύρετε το κυμαινόμενο παράθυρο γύρω"
#~ msgid "Talking to Aperture. Don't touch it!" #: qt\preferences_dialog.py:199
#~ msgstr "Μιλώντας στο Aperture. Μην το αγγίζετε!" msgid "The title bar can only be disabled while the window is docked"
msgstr ""
"Η γραμμή τίτλου μπορεί να απενεργοποιηθεί μόνο όταν το παράθυρο είναι "
"συνδεδεμένο"
#~ msgid "Deleted Aperture photos were sent to a project called \"dupeGuru Trash\"." #: qt\preferences_dialog.py:202
#~ msgstr "" msgid "Vertical title bar"
#~ "Οι διαγεγραμμένες φωτογραφίες από το Aperture στάλθηκαν σε ένα έργο που " msgstr "Κάθετη γραμμή τίτλου"
#~ "ονομάζεται \"dupeGuru Trash\"."
#~ msgid "The iPhoto application couldn't be found." #: qt\preferences_dialog.py:204
#~ msgstr "Η εφαρμογή iPhoto δεν βρέθηκε." msgid ""
"Change the title bar from horizontal on top, to vertical on the left side"
msgstr ""
"Αλλάξτε τη γραμμή τίτλου από οριζόντια στην κορυφή, σε κατακόρυφη στην "
"αριστερή πλευρά"
#~ msgid "Preferences" #: qt\tabbed_window.py:44
#~ msgstr "Προτιμήσεις" msgid "Show tab bar"
msgstr "Εμφάνιση γραμμής καρτελών"
#~ msgid "Check for Update" #: qt\exclude_list_dialog.py:152
#~ msgstr "Έλεγχος για αναβάθμιση" msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happens to match one of the selected regular expressions.<br>For each file collected, two tests are performed to determine whether or not to completely ignore it:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with at least one path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the \"test string\" button after pasting a fake path in the test field:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path or filename tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
"Αυτές οι τυπικές εκφράσεις python (πεζών-κεφαλαίων) θα φιλτράρουν τα αρχεία κατά τη διάρκεια των σαρώσεων.<br>Οι διευθυντές θα έχουν επίσης την <strong>προεπιλεγμένη κατάστασή</strong> τους σε Εξαίρεση στην καρτέλα Κατάλογοι εάν το όνομά τους συμβαίνει να ταιριάζει με μία από τις επιλεγμένες κανονικές εκφράσεις.<br>Για κάθε αρχείο που συλλέγεται, εκτελούνται δύο δοκιμές για να προσδιοριστεί εάν θα το αγνοηθεί πλήρως ή όχι:<br><li>1. Οι κανονικές εκφράσεις χωρίς διαχωριστικό διαδρομών σε αυτές θα συγκρίνονται μόνο με το όνομα αρχείου.</li>\n"
"<li>2. Οι κανονικές εκφράσεις με τουλάχιστον ένα διαχωριστικό διαδρομών σε αυτές θα συγκριθούν με την πλήρη διαδρομή προς το αρχείο.</li><br>\n"
"Παράδειγμα: εάν θέλετε να φιλτράρετε αρχεία .PNG μόνο από τον κατάλογο \"Οι εικόνες μου\":<br><code>.*Οι\\sεικόνες\\sμου\\\\.*\\.png</code><br><br>Μπορείτε να δοκιμάσετε την κανονική έκφραση με το κουμπί \"δοκιμαστική συμβολοσειρά\" αφού επικολλήσετε μια ψεύτικη διαδρομή στο πεδίο δοκιμής:<br><code>C:\\\\χρήστης\\Οι εικόνες μου\\test.png</code><br><br>\n"
"Θα επισημανθεί η αντιστοίχιση των τυπικών εκφράσεων.<br>Εάν υπάρχει τουλάχιστον μία επισήμανση, η διαδρομή ή το όνομα αρχείου που δοκιμάστηκε θα αγνοηθεί κατά τη διάρκεια των σαρώσεων.<br><br>Κατάλογοι και αρχεία που ξεκινούν με τελεία \".\" φιλτράρονται από προεπιλογή.<br><br>"
#~ msgid "Filename" #: qt\app.py:256
#~ msgstr "Όνομα αρχείου" msgid "Results"
msgstr "Αποτελέσματα"
#~ msgid "Filename - Fields" #: qt\preferences_dialog.py:150
#~ msgstr "Όνομα αρχείου - Πεδία" msgid "General Interface"
msgstr "Γενική διεπαφή"
#~ msgid "Filename - Fields (No Order)" #: qt\preferences_dialog.py:176
#~ msgstr "Όνομα αρχείου - Πεδία (Αταξινόμητα)" msgid "Result Table"
msgstr "Πίνακας αποτελεσμάτων"
#~ msgid "Tags" #: qt\preferences_dialog.py:205
#~ msgstr "Ετικέτες" msgid "Details Window"
msgstr "Παράθυρο λεπτομερειών"
#~ msgid "Contents" #: qt\preferences_dialog.py:285
#~ msgstr "Περιεχόμενα" msgid "General"
msgstr "Γενικός"
#~ msgid "Audio Contents" #: qt\preferences_dialog.py:286
#~ msgstr "Μουσικά περιεχόμενα" msgid "Display"
msgstr "Απεικόνιση"
#~ msgid "EXIF Timestamp"
#~ msgstr "Χρονοσήμανση EXIF"
#~ msgid "Folders"
#~ msgstr "Φάκελοι"
#~ msgid "Προσθήκη βιβλιοθήκης Aperture"
#~ msgstr ""
#~ msgid "Add iPhoto Library"
#~ msgstr "Προσθήκη βιβλιοθήκης iPhoto"
#~ msgid "Add iTunes Library"
#~ msgstr "Προσθήκη βιβλιοθήκης iTunes"
#~ msgid "Audio Content"
#~ msgstr "Μουσικό περιεχόμενο"
#~ msgid "Content"
#~ msgstr "Περιεχόμενο"
#~ msgid "dupeGuru ME Preferences"
#~ msgstr "Προτιμήσεις dupeGuru ME"
#~ msgid "dupeGuru PE Preferences"
#~ msgstr "Προτιμήσεις dupeGuru PE"
#~ msgid "Remove Dead Tracks in iTunes"
#~ msgstr "Αφαίρεση νεκρών κομματιών από το iTunes"

View File

@@ -0,0 +1,116 @@
#
msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: utf-8\n"
#: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core\gui\problem_table.py:18
msgid "File Path"
msgstr "File Path"
#: core\gui\problem_table.py:19
msgid "Error Message"
msgstr "Error Message"
#: core\me\prioritize.py:23
msgid "Duration"
msgstr "Duration"
#: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate"
msgstr "Bitrate"
#: core\me\prioritize.py:37
msgid "Samplerate"
msgstr "Samplerate"
#: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
#: core\se\result_table.py:19
msgid "Filename"
msgstr "Filename"
#: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core\se\result_table.py:20
msgid "Folder"
msgstr "Folder"
#: core\me\result_table.py:21
msgid "Size (MB)"
msgstr "Size (MB)"
#: core\me\result_table.py:22
msgid "Time"
msgstr "Time"
#: core\me\result_table.py:24
msgid "Sample Rate"
msgstr "Sample Rate"
#: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core\se\result_table.py:22
msgid "Kind"
msgstr "Kind"
#: core\me\result_table.py:26 core\pe\result_table.py:25
#: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification"
msgstr "Modification"
#: core\me\result_table.py:27
msgid "Title"
msgstr "Title"
#: core\me\result_table.py:28
msgid "Artist"
msgstr "Artist"
#: core\me\result_table.py:29
msgid "Album"
msgstr "Album"
#: core\me\result_table.py:30
msgid "Genre"
msgstr "Genre"
#: core\me\result_table.py:31
msgid "Year"
msgstr "Year"
#: core\me\result_table.py:32
msgid "Track Number"
msgstr "Track Number"
#: core\me\result_table.py:33
msgid "Comment"
msgstr "Comment"
#: core\me\result_table.py:34 core\pe\result_table.py:26
#: core\se\result_table.py:24
msgid "Match %"
msgstr "Match %"
#: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used"
msgstr "Words Used"
#: core\me\result_table.py:36 core\pe\result_table.py:27
#: core\se\result_table.py:26
msgid "Dupe Count"
msgstr "Dupe Count"
#: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions"
msgstr "Dimensions"
#: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)"
msgstr "Size (KB)"
#: core\pe\result_table.py:24
msgid "EXIF Timestamp"
msgstr "EXIF Timestamp"
#: core\prioritize.py:156
msgid "Size"
msgstr "Size"

View File

@@ -0,0 +1,249 @@
#
msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: utf-8\n"
#: core\app.py:42
msgid "There are no marked duplicates. Nothing has been done."
msgstr "There are no marked duplicates. Nothing has been done."
#: core\app.py:43
msgid "There are no selected duplicates. Nothing has been done."
msgstr "There are no selected duplicates. Nothing has been done."
#: core\app.py:44
msgid ""
"You're about to open many files at once. Depending on what those files are "
"opened with, doing so can create quite a mess. Continue?"
msgstr ""
"You're about to open many files at once. Depending on what those files are "
"opened with, doing so can create quite a mess. Continue?"
#: core\app.py:71
msgid "Scanning for duplicates"
msgstr "Scanning for duplicates"
#: core\app.py:72
msgid "Loading"
msgstr "Loading"
#: core\app.py:73
msgid "Moving"
msgstr "Moving"
#: core\app.py:74
msgid "Copying"
msgstr "Copying"
#: core\app.py:75
msgid "Sending to Trash"
msgstr "Sending to Trash"
#: core\app.py:308
msgid ""
"A previous action is still hanging in there. You can't start a new one yet. "
"Wait a few seconds, then try again."
msgstr ""
"A previous action is still hanging in there. You can't start a new one yet. "
"Wait a few seconds, then try again."
#: core\app.py:318
msgid "No duplicates found."
msgstr "No duplicates found."
#: core\app.py:333
msgid "All marked files were copied successfully."
msgstr "All marked files were copied successfully."
#: core\app.py:334
msgid "All marked files were moved successfully."
msgstr "All marked files were moved successfully."
#: core\app.py:335
msgid "All marked files were successfully sent to Trash."
msgstr "All marked files were successfully sent to Trash."
#: core\app.py:343
msgid "Could not load file: {}"
msgstr "Could not load file: {}"
#: core\app.py:399
msgid "'{}' already is in the list."
msgstr "'{}' already is in the list."
#: core\app.py:401
msgid "'{}' does not exist."
msgstr "'{}' does not exist."
#: core\app.py:410
msgid ""
"All selected %d matches are going to be ignored in all subsequent scans. "
"Continue?"
msgstr ""
"All selected %d matches are going to be ignored in all subsequent scans. "
"Continue?"
#: core\app.py:486
msgid "Select a directory to copy marked files to"
msgstr "Select a directory to copy marked files to"
#: core\app.py:487
msgid "Select a directory to move marked files to"
msgstr "Select a directory to move marked files to"
#: core\app.py:527
msgid "Select a destination for your exported CSV"
msgstr "Select a destination for your exported CSV"
#: core\app.py:534 core\app.py:801 core\app.py:811
msgid "Couldn't write to file: {}"
msgstr "Couldn't write to file: {}"
#: core\app.py:559
msgid "You have no custom command set up. Set it up in your preferences."
msgstr "You have no custom command set up. Set it up in your preferences."
#: core\app.py:727 core\app.py:740
msgid "You are about to remove %d files from results. Continue?"
msgstr "You are about to remove %d files from results. Continue?"
#: core\app.py:774
msgid "{} duplicate groups were changed by the re-prioritization."
msgstr "{} duplicate groups were changed by the re-prioritization."
#: core\app.py:821
msgid "The selected directories contain no scannable file."
msgstr "The selected directories contain no scannable file."
#: core\app.py:835
msgid "Collecting files to scan"
msgstr "Collecting files to scan"
#: core\app.py:891
msgid "%s (%d discarded)"
msgstr "%s (%d discarded)"
#: core\engine.py:244 core\engine.py:288
msgid "0 matches found"
msgstr "0 matches found"
#: core\engine.py:262 core\engine.py:296
msgid "%d matches found"
msgstr "%d matches found"
#: core\gui\deletion_options.py:73
msgid "You are sending {} file(s) to the Trash."
msgstr "You are sending {} file(s) to the Trash."
#: core\gui\exclude_list_table.py:15
msgid "Regular Expressions"
msgstr "Regular Expressions"
#: core\gui\ignore_list_dialog.py:25
msgid "Do you really want to remove all %d items from the ignore list?"
msgstr "Do you really want to remove all %d items from the ignore list?"
#: core\me\scanner.py:20 core\se\scanner.py:16
msgid "Filename"
msgstr "Filename"
#: core\me\scanner.py:21
msgid "Filename - Fields"
msgstr "Filename - Fields"
#: core\me\scanner.py:22
msgid "Filename - Fields (No Order)"
msgstr "Filename - Fields (No Order)"
#: core\me\scanner.py:23
msgid "Tags"
msgstr "Tags"
#: core\me\scanner.py:24 core\pe\scanner.py:21 core\se\scanner.py:17
msgid "Contents"
msgstr "Contents"
#: core\pe\matchblock.py:72
msgid "Analyzed %d/%d pictures"
msgstr "Analyzed %d/%d pictures"
#: core\pe\matchblock.py:181
msgid "Performed %d/%d chunk matches"
msgstr "Performed %d/%d chunk matches"
#: core\pe\matchblock.py:191
msgid "Preparing for matching"
msgstr "Preparing for matching"
#: core\pe\matchblock.py:244
msgid "Verified %d/%d matches"
msgstr "Verified %d/%d matches"
#: core\pe\matchexif.py:19
msgid "Read EXIF of %d/%d pictures"
msgstr "Read EXIF of %d/%d pictures"
#: core\pe\scanner.py:22
msgid "EXIF Timestamp"
msgstr "EXIF Timestamp"
#: core\prioritize.py:70
msgid "None"
msgstr "None"
#: core\prioritize.py:100
msgid "Ends with number"
msgstr "Ends with number"
#: core\prioritize.py:101
msgid "Doesn't end with number"
msgstr "Doesn't end with number"
#: core\prioritize.py:102
msgid "Longest"
msgstr "Longest"
#: core\prioritize.py:103
msgid "Shortest"
msgstr "Shortest"
#: core\prioritize.py:140
msgid "Highest"
msgstr "Highest"
#: core\prioritize.py:140
msgid "Lowest"
msgstr "Lowest"
#: core\prioritize.py:169
msgid "Newest"
msgstr "Newest"
#: core\prioritize.py:169
msgid "Oldest"
msgstr "Oldest"
#: core\results.py:142
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) duplicates marked."
#: core\results.py:149
msgid " filter: %s"
msgstr " filter: %s"
#: core\scanner.py:85
msgid "Read size of %d/%d files"
msgstr "Read size of %d/%d files"
#: core\scanner.py:109
msgid "Read metadata of %d/%d files"
msgstr "Read metadata of %d/%d files"
#: core\scanner.py:147
msgid "Almost done! Fiddling with results..."
msgstr "Almost done! Fiddling with results..."
#: core\se\scanner.py:18
msgid "Folders"
msgstr "Folders"

933
locale/en/LC_MESSAGES/ui.po Normal file
View File

@@ -0,0 +1,933 @@
#
msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: utf-8\n"
#: qt/app.py:81
msgid "Quit"
msgstr "Quit"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Options"
#: qt/app.py:83 qt/ignore_list_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Ignore List"
msgstr "Ignore List"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Clear Picture Cache"
#: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Help"
msgstr "dupeGuru Help"
#: qt/app.py:86 cocoa/en.lproj/Localizable.strings:0
msgid "About dupeGuru"
msgstr "About dupeGuru"
#: qt/app.py:87
msgid "Open Debug Log"
msgstr "Open Debug Log"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr "Do you really want to remove all your cached picture analysis?"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "Picture cache cleared."
#: qt/app.py:251
msgid "{} file (*.{})"
msgstr "{} file (*.{})"
#: qt/deletion_options.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Deletion Options"
msgstr "Deletion Options"
#: qt/deletion_options.py:35 cocoa/en.lproj/Localizable.strings:0
msgid "Link deleted files"
msgstr "Link deleted files"
#: qt/deletion_options.py:37 cocoa/en.lproj/Localizable.strings:0
msgid ""
"After having deleted a duplicate, place a link targeting the reference file "
"to replace the deleted file."
msgstr ""
"After having deleted a duplicate, place a link targeting the reference file "
"to replace the deleted file."
#: qt/deletion_options.py:44
msgid "Hardlink"
msgstr "Hardlink"
#: qt/deletion_options.py:44
msgid "Symlink"
msgstr "Symlink"
#: qt/deletion_options.py:48
msgid " (unsupported)"
msgstr " (unsupported)"
#: qt/deletion_options.py:49 cocoa/en.lproj/Localizable.strings:0
msgid "Directly delete files"
msgstr "Directly delete files"
#: qt/deletion_options.py:51 cocoa/en.lproj/Localizable.strings:0
msgid ""
"Instead of sending files to trash, delete them directly. This option is "
"usually used as a workaround when the normal deletion method doesn't work."
msgstr ""
"Instead of sending files to trash, delete them directly. This option is "
"usually used as a workaround when the normal deletion method doesn't work."
#: qt/deletion_options.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Proceed"
msgstr "Proceed"
#: qt/deletion_options.py:60 cocoa/en.lproj/Localizable.strings:0
msgid "Cancel"
msgstr "Cancel"
#: qt/details_table.py:16 cocoa/en.lproj/Localizable.strings:0
msgid "Attribute"
msgstr "Attribute"
#: qt/details_table.py:16 cocoa/en.lproj/Localizable.strings:0
msgid "Selected"
msgstr "Selected"
#: qt/details_table.py:16 qt/directories_model.py:24
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reference"
msgstr "Reference"
#: qt/directories_dialog.py:64 cocoa/en.lproj/Localizable.strings:0
msgid "Load Results..."
msgstr "Load Results..."
#: qt/directories_dialog.py:65 cocoa/en.lproj/Localizable.strings:0
msgid "Results Window"
msgstr "Results Window"
#: qt/directories_dialog.py:66
msgid "Add Folder..."
msgstr "Add Folder..."
#: qt/directories_dialog.py:74 qt/result_window.py:100
#: cocoa/en.lproj/Localizable.strings:0
msgid "File"
msgstr "File"
#: qt/directories_dialog.py:76 qt/result_window.py:108
msgid "View"
msgstr "View"
#: qt/directories_dialog.py:78 qt/result_window.py:110
#: cocoa/en.lproj/Localizable.strings:0
msgid "Help"
msgstr "Help"
#: qt/directories_dialog.py:80 cocoa/en.lproj/Localizable.strings:0
msgid "Load Recent Results"
msgstr "Load Recent Results"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0
msgid "Application Mode:"
msgstr "Application Mode:"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Music"
msgstr "Music"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Picture"
msgstr "Picture"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Standard"
msgstr "Standard"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0
msgid "Scan Type:"
msgstr "Scan Type:"
#: qt/directories_dialog.py:135
msgid "More Options"
msgstr "More Options"
#: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0
msgid "Select folders to scan and press \"Scan\"."
msgstr "Select folders to scan and press \"Scan\"."
#: qt/directories_dialog.py:163 cocoa/en.lproj/Localizable.strings:0
msgid "Load Results"
msgstr "Load Results"
#: qt/directories_dialog.py:166 cocoa/en.lproj/Localizable.strings:0
msgid "Scan"
msgstr "Scan"
#: qt/directories_dialog.py:230
msgid "Unsaved results"
msgstr "Unsaved results"
#: qt/directories_dialog.py:231 cocoa/en.lproj/Localizable.strings:0
msgid "You have unsaved results, do you really want to quit?"
msgstr "You have unsaved results, do you really want to quit?"
#: qt/directories_dialog.py:239 cocoa/en.lproj/Localizable.strings:0
msgid "Select a folder to add to the scanning list"
msgstr "Select a folder to add to the scanning list"
#: qt/directories_dialog.py:266 cocoa/en.lproj/Localizable.strings:0
msgid "Select a results file to load"
msgstr "Select a results file to load"
#: qt/directories_dialog.py:267
msgid "All Files (*.*)"
msgstr "All Files (*.*)"
#: qt/directories_dialog.py:267 qt/result_window.py:311
msgid "dupeGuru Results (*.dupeguru)"
msgstr "dupeGuru Results (*.dupeguru)"
#: qt/directories_dialog.py:278
msgid "Start a new scan"
msgstr "Start a new scan"
#: qt/directories_dialog.py:279 cocoa/en.lproj/Localizable.strings:0
msgid "You have unsaved results, do you really want to continue?"
msgstr "You have unsaved results, do you really want to continue?"
#: qt/directories_model.py:23 cocoa/en.lproj/Localizable.strings:0
msgid "Name"
msgstr "Name"
#: qt/directories_model.py:23 cocoa/en.lproj/Localizable.strings:0
msgid "State"
msgstr "State"
#: qt/directories_model.py:24 cocoa/en.lproj/Localizable.strings:0
msgid "Excluded"
msgstr "Excluded"
#: qt/directories_model.py:24 cocoa/en.lproj/Localizable.strings:0
msgid "Normal"
msgstr "Normal"
#: qt/ignore_list_dialog.py:45 cocoa/en.lproj/Localizable.strings:0
msgid "Remove Selected"
msgstr "Remove Selected"
#: qt/ignore_list_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Clear"
msgstr "Clear"
#: qt/ignore_list_dialog.py:47 qt/problem_dialog.py:61
#: cocoa/en.lproj/Localizable.strings:0
msgid "Close"
msgstr "Close"
#: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
#: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Details"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Tags to scan:"
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Track"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Artist"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Album"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Title"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Genre"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Year"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "Word weighting"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Match similar words"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Can mix file kind"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Use regular expressions when filtering"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Remove empty folders on delete or move"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Ignore duplicates hardlinking to the same file"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Debug mode (restart required)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Match pictures of different dimensions"
#: qt/preferences_dialog.py:43
msgid "Filter Hardness:"
msgstr "Filter Hardness:"
#: qt/preferences_dialog.py:69
msgid "More Results"
msgstr "More Results"
#: qt/preferences_dialog.py:74
msgid "Fewer Results"
msgstr "Fewer Results"
#: qt/preferences_dialog.py:81
msgid "Font size:"
msgstr "Font size:"
#: qt/preferences_dialog.py:85
msgid "Language:"
msgstr "Language:"
#: qt/preferences_dialog.py:91 cocoa/en.lproj/Localizable.strings:0
msgid "Copy and Move:"
msgstr "Copy and Move:"
#: qt/preferences_dialog.py:94 cocoa/en.lproj/Localizable.strings:0
msgid "Right in destination"
msgstr "Right in destination"
#: qt/preferences_dialog.py:95 cocoa/en.lproj/Localizable.strings:0
msgid "Recreate relative path"
msgstr "Recreate relative path"
#: qt/preferences_dialog.py:96 cocoa/en.lproj/Localizable.strings:0
msgid "Recreate absolute path"
msgstr "Recreate absolute path"
#: qt/preferences_dialog.py:99
msgid "Custom Command (arguments: %d for dupe, %r for ref):"
msgstr "Custom Command (arguments: %d for dupe, %r for ref):"
#: qt/preferences_dialog.py:174
msgid "dupeGuru has to restart for language changes to take effect."
msgstr "dupeGuru has to restart for language changes to take effect."
#: qt/prioritize_dialog.py:75 cocoa/en.lproj/Localizable.strings:0
msgid "Re-Prioritize duplicates"
msgstr "Re-Prioritize duplicates"
#: qt/prioritize_dialog.py:79 cocoa/en.lproj/Localizable.strings:0
msgid ""
"Add criteria to the right box and click OK to send the dupes that correspond"
" the best to these criteria to their respective group's reference position. "
"Read the help file for more information."
msgstr ""
"Add criteria to the right box and click OK to send the dupes that correspond"
" the best to these criteria to their respective group's reference position. "
"Read the help file for more information."
#: qt/problem_dialog.py:33 cocoa/en.lproj/Localizable.strings:0
msgid "Problems!"
msgstr "Problems!"
#: qt/problem_dialog.py:37 cocoa/en.lproj/Localizable.strings:0
msgid ""
"There were problems processing some (or all) of the files. The cause of "
"these problems are described in the table below. Those files were not "
"removed from your results."
msgstr ""
"There were problems processing some (or all) of the files. The cause of "
"these problems are described in the table below. Those files were not "
"removed from your results."
#: qt/problem_dialog.py:56
msgid "Reveal Selected"
msgstr "Reveal Selected"
#: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167
#: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0
msgid "Actions"
msgstr "Actions"
#: qt/result_window.py:58 cocoa/en.lproj/Localizable.strings:0
msgid "Show Dupes Only"
msgstr "Show Dupes Only"
#: qt/result_window.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Show Delta Values"
msgstr "Show Delta Values"
#: qt/result_window.py:60
msgid "Send Marked to Recycle Bin..."
msgstr "Send Marked to Recycle Bin..."
#: qt/result_window.py:61 cocoa/en.lproj/Localizable.strings:0
msgid "Move Marked to..."
msgstr "Move Marked to..."
#: qt/result_window.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Copy Marked to..."
msgstr "Copy Marked to..."
#: qt/result_window.py:63 cocoa/en.lproj/Localizable.strings:0
msgid "Remove Marked from Results"
msgstr "Remove Marked from Results"
#: qt/result_window.py:64 cocoa/en.lproj/Localizable.strings:0
msgid "Re-Prioritize Results..."
msgstr "Re-Prioritize Results..."
#: qt/result_window.py:67 cocoa/en.lproj/Localizable.strings:0
msgid "Remove Selected from Results"
msgstr "Remove Selected from Results"
#: qt/result_window.py:71 cocoa/en.lproj/Localizable.strings:0
msgid "Add Selected to Ignore List"
msgstr "Add Selected to Ignore List"
#: qt/result_window.py:75 cocoa/en.lproj/Localizable.strings:0
msgid "Make Selected into Reference"
msgstr "Make Selected into Reference"
#: qt/result_window.py:77 cocoa/en.lproj/Localizable.strings:0
msgid "Open Selected with Default Application"
msgstr "Open Selected with Default Application"
#: qt/result_window.py:80
msgid "Open Containing Folder of Selected"
msgstr "Open Containing Folder of Selected"
#: qt/result_window.py:82 cocoa/en.lproj/Localizable.strings:0
msgid "Rename Selected"
msgstr "Rename Selected"
#: qt/result_window.py:83 cocoa/en.lproj/Localizable.strings:0
msgid "Mark All"
msgstr "Mark All"
#: qt/result_window.py:84 cocoa/en.lproj/Localizable.strings:0
msgid "Mark None"
msgstr "Mark None"
#: qt/result_window.py:85 cocoa/en.lproj/Localizable.strings:0
msgid "Invert Marking"
msgstr "Invert Marking"
#: qt/result_window.py:86 cocoa/en.lproj/Localizable.strings:0
msgid "Mark Selected"
msgstr "Mark Selected"
#: qt/result_window.py:87
msgid "Export To HTML"
msgstr "Export To HTML"
#: qt/result_window.py:88
msgid "Export To CSV"
msgstr "Export To CSV"
#: qt/result_window.py:89 cocoa/en.lproj/Localizable.strings:0
msgid "Save Results..."
msgstr "Save Results..."
#: qt/result_window.py:90 cocoa/en.lproj/Localizable.strings:0
msgid "Invoke Custom Command"
msgstr "Invoke Custom Command"
#: qt/result_window.py:102
msgid "Mark"
msgstr "Mark"
#: qt/result_window.py:106 cocoa/en.lproj/Localizable.strings:0
msgid "Columns"
msgstr "Columns"
#: qt/result_window.py:163
msgid "Reset to Defaults"
msgstr "Reset to Defaults"
#: qt/result_window.py:185
msgid "{} Results"
msgstr "{} Results"
#: qt/result_window.py:193 cocoa/en.lproj/Localizable.strings:0
msgid "Dupes Only"
msgstr "Dupes Only"
#: qt/result_window.py:194
msgid "Delta Values"
msgstr "Delta Values"
#: qt/result_window.py:310 cocoa/en.lproj/Localizable.strings:0
msgid "Select a file to save your results to"
msgstr "Select a file to save your results to"
#: qt/se/preferences_dialog.py:41
msgid "Ignore files smaller than"
msgstr "Ignore files smaller than"
#: qt/se/preferences_dialog.py:52 cocoa/en.lproj/Localizable.strings:0
msgid "KB"
msgstr "KB"
#: cocoa/en.lproj/Localizable.strings:0
msgid "%@ Results"
msgstr "%@ Results"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Action"
msgstr "Action"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Add New Folder..."
msgstr "Add New Folder..."
#: cocoa/en.lproj/Localizable.strings:0
msgid "Advanced"
msgstr "Advanced"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Automatically check for updates"
msgstr "Automatically check for updates"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Basic"
msgstr "Basic"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Bring All to Front"
msgstr "Bring All to Front"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Check for update..."
msgstr "Check for update..."
#: cocoa/en.lproj/Localizable.strings:0
msgid "Close Window"
msgstr "Close Window"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Copy"
msgstr "Copy"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Custom command (arguments: %d for dupe, %r for ref):"
msgstr "Custom command (arguments: %d for dupe, %r for ref):"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Cut"
msgstr "Cut"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Delta"
msgstr "Delta"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details of Selected File"
msgstr "Details of Selected File"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details Panel"
msgstr "Details Panel"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Directories"
msgstr "Directories"
#: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru"
msgstr "dupeGuru"
#: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Preferences"
msgstr "dupeGuru Preferences"
#: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Results"
msgstr "dupeGuru Results"
#: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Website"
msgstr "dupeGuru Website"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Edit"
msgstr "Edit"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Export Results to CSV"
msgstr "Export Results to CSV"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Export Results to XHTML"
msgstr "Export Results to XHTML"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Fewer results"
msgstr "Fewer results"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Filter"
msgstr "Filter"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Filter hardness:"
msgstr "Filter hardness:"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Filter Results..."
msgstr "Filter Results..."
#: cocoa/en.lproj/Localizable.strings:0
msgid "Folder Selection Window"
msgstr "Folder Selection Window"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Font Size:"
msgstr "Font Size:"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Hide dupeGuru"
msgstr "Hide dupeGuru"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Hide Others"
msgstr "Hide Others"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Ignore files smaller than:"
msgstr "Ignore files smaller than:"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Load from file..."
msgstr "Load from file..."
#: cocoa/en.lproj/Localizable.strings:0
msgid "Minimize"
msgstr "Minimize"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Mode"
msgstr "Mode"
#: cocoa/en.lproj/Localizable.strings:0
msgid "More results"
msgstr "More results"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Ok"
msgstr "Ok"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Paste"
msgstr "Paste"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Preferences..."
msgstr "Preferences..."
#: cocoa/en.lproj/Localizable.strings:0
msgid "Quick Look"
msgstr "Quick Look"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Quit dupeGuru"
msgstr "Quit dupeGuru"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reset to Default"
msgstr "Reset to Default"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reset To Defaults"
msgstr "Reset To Defaults"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reveal"
msgstr "Reveal"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reveal Selected in Finder"
msgstr "Reveal Selected in Finder"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Select All"
msgstr "Select All"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Send Marked to Trash..."
msgstr "Send Marked to Trash..."
#: cocoa/en.lproj/Localizable.strings:0
msgid "Services"
msgstr "Services"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Show All"
msgstr "Show All"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Start Duplicate Scan"
msgstr "Start Duplicate Scan"
#: cocoa/en.lproj/Localizable.strings:0
msgid "The name '%@' already exists."
msgstr "The name '%@' already exists."
#: cocoa/en.lproj/Localizable.strings:0
msgid "Window"
msgstr "Window"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Zoom"
msgstr "Zoom"
#: qt\app.py:158
msgid "Exclusion Filters"
msgstr "Exclusion Filters"
#: qt\directories_dialog.py:91
msgid "Scan Results"
msgstr "Scan Results"
#: qt\directories_dialog.py:95
msgid "Load Directories..."
msgstr "Load Directories..."
#: qt\directories_dialog.py:96
msgid "Save Directories..."
msgstr "Save Directories..."
#: qt\directories_dialog.py:337
msgid "Select a directories file to load"
msgstr "Select a directories file to load"
#: qt\directories_dialog.py:338
msgid "dupeGuru Results (*.dupegurudirs)"
msgstr "dupeGuru Results (*.dupegurudirs)"
#: qt\directories_dialog.py:347
msgid "Select a file to save your directories to"
msgstr "Select a file to save your directories to"
#: qt\directories_dialog.py:348
msgid "dupeGuru Directories (*.dupegurudirs)"
msgstr "dupeGuru Directories (*.dupegurudirs)"
#: qt\exclude_list_dialog.py:44
msgid "Add"
msgstr "Add"
#: qt\exclude_list_dialog.py:46
msgid "Restore defaults"
msgstr "Restore defaults"
#: qt\exclude_list_dialog.py:47
msgid "Test string"
msgstr "Test string"
#: qt\exclude_list_dialog.py:83
msgid "Type a python regular expression here..."
msgstr "Type a python regular expression here..."
#: qt\exclude_list_dialog.py:85
msgid "Type a file system path or filename here..."
msgstr "Type a file system path or filename here..."
#: qt\exclude_list_dialog.py:152
msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happen to match one of the regular expressions.<br>For each file collected two tests are perfomed on each of them to determine whether or not to filter them out:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with no path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the test string feature by pasting a fake path in it:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happen to match one of the regular expressions.<br>For each file collected two tests are perfomed on each of them to determine whether or not to filter them out:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with no path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the test string feature by pasting a fake path in it:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
#: qt\exclude_list_table.py:36
msgid "Compilation error: "
msgstr "Compilation error: "
#: qt\pe\image_viewer.py:56
msgid "Increase zoom"
msgstr "Increase zoom"
#: qt\pe\image_viewer.py:66
msgid "Decrease zoom"
msgstr "Decrease zoom"
#: qt\pe\image_viewer.py:71
msgid "Ctrl+/"
msgstr "Ctrl+/"
#: qt\pe\image_viewer.py:76
msgid "Normal size"
msgstr "Normal size"
#: qt\pe\image_viewer.py:81
msgid "Ctrl+*"
msgstr "Ctrl+*"
#: qt\pe\image_viewer.py:86
msgid "Best fit"
msgstr "Best fit"
#: qt\pe\preferences_dialog.py:49
msgid "Picture cache mode:"
msgstr "Picture cache mode:"
#: qt\pe\preferences_dialog.py:56
msgid "Override theme icons in viewer toolbar"
msgstr "Override theme icons in viewer toolbar"
#: qt\pe\preferences_dialog.py:58
msgid ""
"Use our own internal icons instead of those provided by the theme engine"
msgstr ""
"Use our own internal icons instead of those provided by the theme engine"
#: qt\pe\preferences_dialog.py:66
msgid "Show scrollbars in image viewers"
msgstr "Show scrollbars in image viewers"
#: qt\pe\preferences_dialog.py:68
msgid ""
"When the image displayed doesn't fit the viewport, show scrollbars to span "
"the view around"
msgstr ""
"When the image displayed doesn't fit the viewport, show scrollbars to span "
"the view around"
#: qt\preferences_dialog.py:156
msgid "Use default position for tab bar (requires restart)"
msgstr "Use default position for tab bar (requires restart)"
#: qt\preferences_dialog.py:158
msgid ""
"Place the tab bar below the main menu instead of next to it\n"
"On MacOS, the tab bar will fill up the window's width instead."
msgstr ""
"Place the tab bar below the main menu instead of next to it\n"
"On MacOS, the tab bar will fill up the window's width instead."
#: qt\preferences_dialog.py:172
msgid "Use bold font for references"
msgstr "Use bold font for references"
#: qt\preferences_dialog.py:176
msgid "Reference foreground color:"
msgstr "Reference foreground color:"
#: qt\preferences_dialog.py:179
msgid "Reference background color:"
msgstr "Reference background color:"
#: qt\preferences_dialog.py:182 qt\preferences_dialog.py:216
msgid "Delta foreground color:"
msgstr "Delta foreground color:"
#: qt\preferences_dialog.py:195
msgid "Show the title bar and can be docked"
msgstr "Show the title bar and can be docked"
#: qt\preferences_dialog.py:197
msgid ""
"While the title bar is hidden, use the modifier key to drag the floating "
"window around"
msgstr ""
"While the title bar is hidden, use the modifier key to drag the floating "
"window around"
#: qt\preferences_dialog.py:199
msgid "The title bar can only be disabled while the window is docked"
msgstr "The title bar can only be disabled while the window is docked"
#: qt\preferences_dialog.py:202
msgid "Vertical title bar"
msgstr "Vertical title bar"
#: qt\preferences_dialog.py:204
msgid ""
"Change the title bar from horizontal on top, to vertical on the left side"
msgstr ""
"Change the title bar from horizontal on top, to vertical on the left side"
#: qt\tabbed_window.py:44
msgid "Show tab bar"
msgstr "Show tab bar"
#: qt\exclude_list_dialog.py:152
msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happens to match one of the selected regular expressions.<br>For each file collected, two tests are performed to determine whether or not to completely ignore it:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with at least one path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the \"test string\" button after pasting a fake path in the test field:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path or filename tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happens to match one of the selected regular expressions.<br>For each file collected, two tests are performed to determine whether or not to completely ignore it:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with at least one path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the \"test string\" button after pasting a fake path in the test field:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path or filename tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
#: qt\app.py:256
msgid "Results"
msgstr "Results"
#: qt\preferences_dialog.py:150
msgid "General Interface"
msgstr "General Interface"
#: qt\preferences_dialog.py:176
msgid "Result Table"
msgstr "Result Table"
#: qt\preferences_dialog.py:205
msgid "Details Window"
msgstr "Details Window"
#: qt\preferences_dialog.py:285
msgid "General"
msgstr "General"
#: qt\preferences_dialog.py:286
msgid "Display"
msgstr "Display"

View File

@@ -1,123 +1,122 @@
# Translators: # Translators:
# Josep <tu154m@gmail.com>, 2015 # Andrew Senetar <arsenetar@gmail.com>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Andrew Senetar <arsenetar@gmail.com>, 2021\n"
"PO-Revision-Date: 2015-04-16 22:52+0000\n" "Language-Team: Spanish (https://www.transifex.com/voltaicideas/teams/116153/es/)\n"
"Last-Translator: Josep <tu154m@gmail.com>\n" "Language: es\n"
"Language-Team: Spanish (http://www.transifex.com/p/dupeguru/language/es/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: core/gui/ignore_list_table.py:18 core/gui/ignore_list_table.py:19 #: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core/gui/problem_table.py:17 #: core\gui\problem_table.py:18
msgid "File Path" msgid "File Path"
msgstr "Ruta de Fichero" msgstr "Ruta de Fichero"
#: core/gui/problem_table.py:18 #: core\gui\problem_table.py:19
msgid "Error Message" msgid "Error Message"
msgstr "Mensaje de error" msgstr "Mensaje de error"
#: core/me/result_table.py:24 core/pe/result_table.py:21 core/prioritize.py:63 #: core\me\prioritize.py:23
#: core/se/result_table.py:21
msgid "Kind"
msgstr "Clase"
#: core/me/result_table.py:19 core/pe/result_table.py:19 core/prioritize.py:72
#: core/se/result_table.py:19
msgid "Folder"
msgstr "Carpeta"
#: core/me/result_table.py:18 core/pe/result_table.py:18 core/prioritize.py:88
#: core/se/result_table.py:18
msgid "Filename"
msgstr "Nombre de fichero"
#: core/prioritize.py:147
msgid "Size"
msgstr "Tamaño"
#: core/me/result_table.py:25 core/pe/result_table.py:24
#: core/prioritize.py:153 core/se/result_table.py:22
msgid "Modification"
msgstr "Modificación"
#: core/me/prioritize.py:18
msgid "Duration" msgid "Duration"
msgstr "Duración" msgstr "Duración"
#: core/me/prioritize.py:24 core/me/result_table.py:22 #: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate" msgid "Bitrate"
msgstr "Tasa de bits" msgstr "Tasa de bits"
#: core/me/prioritize.py:30 #: core\me\prioritize.py:37
msgid "Samplerate" msgid "Samplerate"
msgstr "Tasa de Muestreo" msgstr "Tasa de Muestreo"
#: core/me/result_table.py:20 #: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
#: core\se\result_table.py:19
msgid "Filename"
msgstr "Nombre de fichero"
#: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core\se\result_table.py:20
msgid "Folder"
msgstr "Carpeta"
#: core\me\result_table.py:21
msgid "Size (MB)" msgid "Size (MB)"
msgstr "Tamaño (MB)" msgstr "Tamaño (MB)"
#: core/me/result_table.py:21 #: core\me\result_table.py:22
msgid "Time" msgid "Time"
msgstr "Hora" msgstr "Hora"
#: core/me/result_table.py:23 #: core\me\result_table.py:24
msgid "Sample Rate" msgid "Sample Rate"
msgstr "Tasa de Muestreo" msgstr "Tasa de Muestreo"
#: core/me/result_table.py:26 #: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core\se\result_table.py:22
msgid "Kind"
msgstr "Clase"
#: core\me\result_table.py:26 core\pe\result_table.py:25
#: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification"
msgstr "Modificación"
#: core\me\result_table.py:27
msgid "Title" msgid "Title"
msgstr "Título" msgstr "Título"
#: core/me/result_table.py:27 #: core\me\result_table.py:28
msgid "Artist" msgid "Artist"
msgstr "Artista" msgstr "Artista"
#: core/me/result_table.py:28 #: core\me\result_table.py:29
msgid "Album" msgid "Album"
msgstr "Álbum" msgstr "Álbum"
#: core/me/result_table.py:29 #: core\me\result_table.py:30
msgid "Genre" msgid "Genre"
msgstr "Género" msgstr "Género"
#: core/me/result_table.py:30 #: core\me\result_table.py:31
msgid "Year" msgid "Year"
msgstr "Año" msgstr "Año"
#: core/me/result_table.py:31 #: core\me\result_table.py:32
msgid "Track Number" msgid "Track Number"
msgstr "Pista Número" msgstr "Pista Número"
#: core/me/result_table.py:32 #: core\me\result_table.py:33
msgid "Comment" msgid "Comment"
msgstr "Comentario" msgstr "Comentario"
#: core/me/result_table.py:33 core/pe/result_table.py:25 #: core\me\result_table.py:34 core\pe\result_table.py:26
#: core/se/result_table.py:23 #: core\se\result_table.py:24
msgid "Match %" msgid "Match %"
msgstr "Coincidencia %" msgstr "Coincidencia %"
#: core/me/result_table.py:34 core/se/result_table.py:24 #: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used" msgid "Words Used"
msgstr "Palabras Empleadas" msgstr "Palabras Empleadas"
#: core/me/result_table.py:35 core/pe/result_table.py:26 #: core\me\result_table.py:36 core\pe\result_table.py:27
#: core/se/result_table.py:25 #: core\se\result_table.py:26
msgid "Dupe Count" msgid "Dupe Count"
msgstr "Duplicado Número" msgstr "Duplicado Número"
#: core/pe/prioritize.py:18 core/pe/result_table.py:22 #: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions" msgid "Dimensions"
msgstr "Dimensiones" msgstr "Dimensiones"
#: core/pe/result_table.py:20 core/se/result_table.py:20 #: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)" msgid "Size (KB)"
msgstr "Tamaño (KB)" msgstr "Tamaño (KB)"
#: core/pe/result_table.py:23 #: core\pe\result_table.py:24
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "Marca horaria EXIF" msgstr "Marca horaria EXIF"
#: core\prioritize.py:156
msgid "Size"
msgstr "Tamaño"

View File

@@ -1,25 +1,25 @@
# Translators: # Translators:
# Josep <tu154m@gmail.com>, 2015 # Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2015-04-19 20:05+0000\n" "Language-Team: Spanish (https://www.transifex.com/voltaicideas/teams/116153/es/)\n"
"Last-Translator: Josep <tu154m@gmail.com>\n" "Language: es\n"
"Language-Team: Spanish (http://www.transifex.com/p/dupeguru/language/es/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: core/app.py:40 #: core\app.py:42
msgid "There are no marked duplicates. Nothing has been done." msgid "There are no marked duplicates. Nothing has been done."
msgstr "No hay duplicados marcados. No se ha hecho nada." msgstr "No hay duplicados marcados. No se ha hecho nada."
#: core/app.py:41 #: core\app.py:43
msgid "There are no selected duplicates. Nothing has been done." msgid "There are no selected duplicates. Nothing has been done."
msgstr "No hay duplicados seleccionados. No se ha hecho nada." msgstr "No hay duplicados seleccionados. No se ha hecho nada."
#: core/app.py:42 #: core\app.py:44
msgid "" msgid ""
"You're about to open many files at once. Depending on what those files are " "You're about to open many files at once. Depending on what those files are "
"opened with, doing so can create quite a mess. Continue?" "opened with, doing so can create quite a mess. Continue?"
@@ -27,27 +27,27 @@ msgstr ""
"Está a punto de abrir muchas imágenes. Dependiendo de los ficheros que se " "Está a punto de abrir muchas imágenes. Dependiendo de los ficheros que se "
"abran, abrirlos puede colgar la máquina. ¿Continuar?" "abran, abrirlos puede colgar la máquina. ¿Continuar?"
#: core/app.py:65 #: core\app.py:71
msgid "Scanning for duplicates" msgid "Scanning for duplicates"
msgstr "Buscando duplicados" msgstr "Buscando duplicados"
#: core/app.py:66 #: core\app.py:72
msgid "Loading" msgid "Loading"
msgstr "Cargando" msgstr "Cargando"
#: core/app.py:67 #: core\app.py:73
msgid "Moving" msgid "Moving"
msgstr "Moviendo" msgstr "Moviendo"
#: core/app.py:68 #: core\app.py:74
msgid "Copying" msgid "Copying"
msgstr "Copiando" msgstr "Copiando"
#: core/app.py:69 #: core\app.py:75
msgid "Sending to Trash" msgid "Sending to Trash"
msgstr "Enviando a la Papelera" msgstr "Enviando a la Papelera"
#: core/app.py:279 #: core\app.py:308
msgid "" msgid ""
"A previous action is still hanging in there. You can't start a new one yet. " "A previous action is still hanging in there. You can't start a new one yet. "
"Wait a few seconds, then try again." "Wait a few seconds, then try again."
@@ -55,32 +55,36 @@ msgstr ""
"Una acción previa sigue ejecutándose. No puede abrir una nueva todavía. " "Una acción previa sigue ejecutándose. No puede abrir una nueva todavía. "
"Espere unos segundos y vuelva a intentarlo." "Espere unos segundos y vuelva a intentarlo."
#: core/app.py:289 #: core\app.py:318
msgid "No duplicates found." msgid "No duplicates found."
msgstr "No se han encontrado duplicados." msgstr "No se han encontrado duplicados."
#: core/app.py:304 #: core\app.py:333
msgid "All marked files were copied successfully." msgid "All marked files were copied successfully."
msgstr "" msgstr ""
"Todos los ficheros seleccionados han sido copiados satisfactoriamente." "Todos los ficheros seleccionados han sido copiados satisfactoriamente."
#: core/app.py:305 #: core\app.py:334
msgid "All marked files were moved successfully." msgid "All marked files were moved successfully."
msgstr "Todos los ficheros seleccionados se han movidos satisfactoriamente." msgstr "Todos los ficheros seleccionados se han movidos satisfactoriamente."
#: core/app.py:306 #: core\app.py:335
msgid "All marked files were successfully sent to Trash." msgid "All marked files were successfully sent to Trash."
msgstr "Todo los ficheros marcados se han enviado a la papelera exitosamente." msgstr "Todo los ficheros marcados se han enviado a la papelera exitosamente."
#: core/app.py:368 #: core\app.py:343
msgid "Could not load file: {}"
msgstr "No se pudo cargar el archivo: {}"
#: core\app.py:399
msgid "'{}' already is in the list." msgid "'{}' already is in the list."
msgstr "'{}' ya está en la lista." msgstr "'{}' ya está en la lista."
#: core/app.py:370 #: core\app.py:401
msgid "'{}' does not exist." msgid "'{}' does not exist."
msgstr "'{}' no existe." msgstr "'{}' no existe."
#: core/app.py:379 #: core\app.py:410
msgid "" msgid ""
"All selected %d matches are going to be ignored in all subsequent scans. " "All selected %d matches are going to be ignored in all subsequent scans. "
"Continue?" "Continue?"
@@ -88,186 +92,167 @@ msgstr ""
"Todas las %d coincidencias seleccionadas van a ser ignoradas en las " "Todas las %d coincidencias seleccionadas van a ser ignoradas en las "
"subsiguientes exploraciones. ¿Continuar?" "subsiguientes exploraciones. ¿Continuar?"
#: core/app.py:450 #: core\app.py:486
msgid "copy" msgid "Select a directory to copy marked files to"
msgstr "copiar" msgstr "Seleccione un directorio donde desee copiar los archivos marcados"
#: core/app.py:450 #: core\app.py:487
msgid "move" msgid "Select a directory to move marked files to"
msgstr "mover" msgstr "Seleccione un directorio al que desee mover los archivos marcados"
#: core/app.py:451 #: core\app.py:527
msgid "Select a directory to {} marked files to"
msgstr "Seleccionar un directorio al que {} enviar los ficheros seleccionados"
#: core/app.py:490
msgid "Select a destination for your exported CSV" msgid "Select a destination for your exported CSV"
msgstr "Seleccionar un destino para el CSV seleccionado" msgstr "Seleccionar un destino para el CSV seleccionado"
#: core/app.py:518 #: core\app.py:534 core\app.py:801 core\app.py:811
msgid "Couldn't write to file: {}"
msgstr "No se pudo escribir en el archivo: {}"
#: core\app.py:559
msgid "You have no custom command set up. Set it up in your preferences." msgid "You have no custom command set up. Set it up in your preferences."
msgstr "No hay comandos configurados. Establézcalos en sus preferencias." msgstr "No hay comandos configurados. Establézcalos en sus preferencias."
#: core/app.py:672 core/app.py:685 #: core\app.py:727 core\app.py:740
msgid "You are about to remove %d files from results. Continue?" msgid "You are about to remove %d files from results. Continue?"
msgstr "Está a punto de eliminar %d ficheros de resultados. ¿Continuar?" msgstr "Está a punto de eliminar %d ficheros de resultados. ¿Continuar?"
#: core/app.py:719 #: core\app.py:774
msgid "{} duplicate groups were changed by the re-prioritization." msgid "{} duplicate groups were changed by the re-prioritization."
msgstr "{} grupos de duplicados han sido cambiados por la re-priorización" msgstr "{} grupos de duplicados han sido cambiados por la re-priorización"
#: core/app.py:762 #: core\app.py:821
msgid "Collecting files to scan"
msgstr "Recopilando ficheros a explorar"
#: core/app.py:751
msgid "The selected directories contain no scannable file." msgid "The selected directories contain no scannable file."
msgstr "Las carpetas seleccionadas no contienen ficheros para explorar." msgstr "Las carpetas seleccionadas no contienen ficheros para explorar."
#: core/app.py:810 #: core\app.py:835
msgid "Collecting files to scan"
msgstr "Recopilando ficheros a explorar"
#: core\app.py:891
msgid "%s (%d discarded)" msgid "%s (%d discarded)"
msgstr "%s (%d descartados)" msgstr "%s (%d descartados)"
#: core/engine.py:222 core/engine.py:262 #: core\engine.py:244 core\engine.py:288
msgid "0 matches found" msgid "0 matches found"
msgstr "0 coincidencias" msgstr "0 coincidencias"
#: core/engine.py:240 core/engine.py:270 #: core\engine.py:262 core\engine.py:296
msgid "%d matches found" msgid "%d matches found"
msgstr "%d coincidencias encontradas" msgstr "%d coincidencias encontradas"
#: core/scanner.py:77 #: core\gui\deletion_options.py:73
msgid "Read size of %d/%d files"
msgstr "Tamaño de lectura de %d/%d ficheros"
#: core/gui/deletion_options.py:69
msgid "You are sending {} file(s) to the Trash." msgid "You are sending {} file(s) to the Trash."
msgstr "Enviando {} fichero(s) a la Papelera" msgstr "Enviando {} fichero(s) a la Papelera"
#: core/gui/ignore_list_dialog.py:24 #: core\gui\exclude_list_table.py:15
msgid "Regular Expressions"
msgstr "Expresiones regulares"
#: core\gui\ignore_list_dialog.py:25
msgid "Do you really want to remove all %d items from the ignore list?" msgid "Do you really want to remove all %d items from the ignore list?"
msgstr "" msgstr ""
"¿Desea realmente eliminar todos los %d elementos de la lista de exclusión?" "¿Desea realmente eliminar todos los %d elementos de la lista de exclusión?"
#: core/prioritize.py:68 #: core\me\scanner.py:20 core\se\scanner.py:16
msgid "None" msgid "Filename"
msgstr "Ninguno" msgstr "Nombre de archivo"
#: core/prioritize.py:96 #: core\me\scanner.py:21
msgid "Ends with number" msgid "Filename - Fields"
msgstr "Termina con un número" msgstr "Nombre de archivo - Campos"
#: core/prioritize.py:97 #: core\me\scanner.py:22
msgid "Doesn't end with number" msgid "Filename - Fields (No Order)"
msgstr "No termina con un número" msgstr "Nombre de archivo - Campos (sin orden)"
#: core/prioritize.py:98 #: core\me\scanner.py:23
msgid "Longest" msgid "Tags"
msgstr "El más largo" msgstr "Etiquetas"
#: core/prioritize.py:99 #: core\me\scanner.py:24 core\pe\scanner.py:21 core\se\scanner.py:17
msgid "Shortest" msgid "Contents"
msgstr "El más corto" msgstr "Contenido"
#: core/prioritize.py:132 #: core\pe\matchblock.py:72
msgid "Highest"
msgstr "El más alto"
#: core/prioritize.py:132
msgid "Lowest"
msgstr "El más bajo"
#: core/prioritize.py:159
msgid "Newest"
msgstr "El más nuevo"
#: core/prioritize.py:159
msgid "Oldest"
msgstr "El más antiguo"
#: core/results.py:129
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) duplicados marcados."
#: core/results.py:136
msgid " filter: %s"
msgstr "filtro: %s"
#: core/scanner.py:101
msgid "Read metadata of %d/%d files"
msgstr "Leyendo metadatos de %d/%d ficheros"
#: core/pe/matchblock.py:61
msgid "Analyzed %d/%d pictures" msgid "Analyzed %d/%d pictures"
msgstr "Analizadas %d/%d imágenes" msgstr "Analizadas %d/%d imágenes"
#: core/pe/matchblock.py:156 #: core\pe\matchblock.py:181
msgid "Performed %d/%d chunk matches" msgid "Performed %d/%d chunk matches"
msgstr "Realizado %d/%d trozos coincidentes" msgstr "Realizado %d/%d trozos coincidentes"
#: core/pe/matchblock.py:161 #: core\pe\matchblock.py:191
msgid "Preparing for matching" msgid "Preparing for matching"
msgstr "Preparando para coincidencias" msgstr "Preparando para coincidencias"
#: core/pe/matchblock.py:206 #: core\pe\matchblock.py:244
msgid "Verified %d/%d matches" msgid "Verified %d/%d matches"
msgstr "Verificadas %d/%d coincidencias" msgstr "Verificadas %d/%d coincidencias"
#: core/pe/matchexif.py:18 #: core\pe\matchexif.py:19
msgid "Read EXIF of %d/%d pictures" msgid "Read EXIF of %d/%d pictures"
msgstr "Leído EXIF de %d/%d imágenes" msgstr "Leído EXIF de %d/%d imágenes"
#: core/app.py:312 #: core\pe\scanner.py:22
msgid "Could not load file: {}"
msgstr ""
#: core/app.py:496 core/app.py:742
msgid "Couldn't write to file: {}"
msgstr ""
#: core/me/scanner.py:19 core/se/scanner.py:15
msgid "Filename"
msgstr ""
#: core/me/scanner.py:20
msgid "Filename - Fields"
msgstr ""
#: core/me/scanner.py:21
msgid "Filename - Fields (No Order)"
msgstr ""
#: core/me/scanner.py:22
msgid "Tags"
msgstr ""
#: core/me/scanner.py:23 core/pe/scanner.py:20 core/se/scanner.py:16
msgid "Contents"
msgstr ""
#: core/pe/scanner.py:21
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "" msgstr "Marca horaria EXIF"
#: core/scanner.py:139 #: core\prioritize.py:70
msgid "None"
msgstr "Ninguno"
#: core\prioritize.py:100
msgid "Ends with number"
msgstr "Termina con un número"
#: core\prioritize.py:101
msgid "Doesn't end with number"
msgstr "No termina con un número"
#: core\prioritize.py:102
msgid "Longest"
msgstr "El más largo"
#: core\prioritize.py:103
msgid "Shortest"
msgstr "El más corto"
#: core\prioritize.py:140
msgid "Highest"
msgstr "El más alto"
#: core\prioritize.py:140
msgid "Lowest"
msgstr "El más bajo"
#: core\prioritize.py:169
msgid "Newest"
msgstr "El más nuevo"
#: core\prioritize.py:169
msgid "Oldest"
msgstr "El más antiguo"
#: core\results.py:142
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) duplicados marcados."
#: core\results.py:149
msgid " filter: %s"
msgstr "filtro: %s"
#: core\scanner.py:85
msgid "Read size of %d/%d files"
msgstr "Tamaño de lectura de %d/%d ficheros"
#: core\scanner.py:109
msgid "Read metadata of %d/%d files"
msgstr "Leyendo metadatos de %d/%d ficheros"
#: core\scanner.py:147
msgid "Almost done! Fiddling with results..." msgid "Almost done! Fiddling with results..."
msgstr "" msgstr "¡Casi termino! Jugando con los resultados..."
#: core/se/scanner.py:17 #: core\se\scanner.py:18
msgid "Folders" msgid "Folders"
msgstr "" msgstr "Carpetas"
#~ msgid "Sending files to the recycle bin"
#~ msgstr "Enviando ficheros a la papelera de reciclaje"
#~ msgid "Grouped %d/%d matches"
#~ msgstr "Coincidencias %d/%d agrupadas"
#~ msgid "Removing false matches"
#~ msgstr "Descartando falsas coincidencias"
#~ msgid "Processed %d/%d matches against the ignore list"
#~ msgstr "Procesadas %d/%d coincidencias de la lista de exclusión"
#~ msgid "Doing group prioritization"
#~ msgstr "Ejecutando priorización de grupo"

View File

@@ -1,25 +1,34 @@
# Translators: # Translators:
# Josep <tu154m@gmail.com>, 2015 # Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2015-04-19 20:20+0000\n" "Language-Team: Spanish (https://www.transifex.com/voltaicideas/teams/116153/es/)\n"
"Last-Translator: Josep <tu154m@gmail.com>\n" "Language: es\n"
"Language-Team: Spanish (http://www.transifex.com/p/dupeguru/language/es/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: qt/app.py:81 #: qt/app.py:81
msgid "Quit" msgid "Quit"
msgstr "Salir" msgstr "Salir"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Opciones"
#: qt/app.py:83 qt/ignore_list_dialog.py:32 #: qt/app.py:83 qt/ignore_list_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Ignore List" msgid "Ignore List"
msgstr "Lista de exclusión" msgstr "Lista de exclusión"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Limpiar el Cache de Fotos"
#: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0 #: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Help" msgid "dupeGuru Help"
msgstr "Ayuda de dupeGuru" msgstr "Ayuda de dupeGuru"
@@ -32,6 +41,14 @@ msgstr "Acerca de dupeGuru"
msgid "Open Debug Log" msgid "Open Debug Log"
msgstr "Abrir Registro de Depuración" msgstr "Abrir Registro de Depuración"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr "¿Desea realmente eliminar todo el caché de análisis de imágenes?"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "Caché de fotos limpio."
#: qt/app.py:251 #: qt/app.py:251
msgid "{} file (*.{})" msgid "{} file (*.{})"
msgstr "{} fichero (*.{})" msgstr "{} fichero (*.{})"
@@ -128,6 +145,30 @@ msgstr "Ayuda"
msgid "Load Recent Results" msgid "Load Recent Results"
msgstr "Cargar Resultados Recientes" msgstr "Cargar Resultados Recientes"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0
msgid "Application Mode:"
msgstr "Modo de aplicación:"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Music"
msgstr "Música"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Picture"
msgstr "Imagen"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Standard"
msgstr "Estándar"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0
msgid "Scan Type:"
msgstr "Tipo de Exploración:"
#: qt/directories_dialog.py:135
msgid "More Options"
msgstr "Mas Opciones"
#: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0 #: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0
msgid "Select folders to scan and press \"Scan\"." msgid "Select folders to scan and press \"Scan\"."
msgstr "Seleccionar carpetas a explorar y pulsar \"Explorar\"." msgstr "Seleccionar carpetas a explorar y pulsar \"Explorar\"."
@@ -201,9 +242,78 @@ msgstr "Limpiar"
msgid "Close" msgid "Close"
msgstr "Cerrar" msgstr "Cerrar"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0 #: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
msgid "Scan Type:" #: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
msgstr "Tipo de Exploración:" #: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Detalles"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Etiquetas a explorar:"
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Pista"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Artista"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Álbum"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Título"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Género"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Año"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "Ponderación de Palabra"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Coincidencia con palabras similares"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Puede mezclar tipos de fichero"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Use expresiones regulares cuando filtre"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Eliminar carpetas vacías al borrar o mover"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Ignorar duplicados enlazando al mismo fichero"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Mode de depuración (se requiere reinicio)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Coincidencia de imágenes de distintas dimensiones"
#: qt/preferences_dialog.py:43 #: qt/preferences_dialog.py:43
msgid "Filter Hardness:" msgid "Filter Hardness:"
@@ -283,12 +393,6 @@ msgstr ""
msgid "Reveal Selected" msgid "Reveal Selected"
msgstr "Revelar seleccionados" msgstr "Revelar seleccionados"
#: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
#: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Detalles"
#: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167 #: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167
#: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0
msgid "Actions" msgid "Actions"
@@ -406,85 +510,6 @@ msgstr "Valores Delta"
msgid "Select a file to save your results to" msgid "Select a file to save your results to"
msgstr "Seleccionar un fichero al que guardar los resultados" msgstr "Seleccionar un fichero al que guardar los resultados"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Etiquetas a explorar:"
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Pista"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Artista"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Álbum"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Título"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Género"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Año"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "Ponderación de Palabra"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Coincidencia con palabras similares"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Puede mezclar tipos de fichero"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Use expresiones regulares cuando filtre"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Eliminar carpetas vacías al borrar o mover"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Ignorar duplicados enlazando al mismo fichero"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Mode de depuración (se requiere reinicio)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Coincidencia de imágenes de distintas dimensiones"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Limpiar el Cache de Fotos"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr "¿Desea realmente eliminar todo el caché de análisis de imágenes?"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "Caché de fotos limpio."
#: qt/se/preferences_dialog.py:41 #: qt/se/preferences_dialog.py:41
msgid "Ignore files smaller than" msgid "Ignore files smaller than"
msgstr "Ignorar ficheros más pequeños de" msgstr "Ignorar ficheros más pequeños de"
@@ -641,11 +666,6 @@ msgstr "Más resultados"
msgid "Ok" msgid "Ok"
msgstr "De acuerdo" msgstr "De acuerdo"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Opciones"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Paste" msgid "Paste"
msgstr "Pegar" msgstr "Pegar"
@@ -710,114 +730,220 @@ msgstr "Ventana"
msgid "Zoom" msgid "Zoom"
msgstr "Zoom" msgstr "Zoom"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0 #: qt\app.py:158
msgid "Application Mode:" msgid "Exclusion Filters"
msgstr "Filtros de exclusión"
#: qt\directories_dialog.py:91
msgid "Scan Results"
msgstr "Resultados del Escáner"
#: qt\directories_dialog.py:95
msgid "Load Directories..."
msgstr "Cargar Carpetas..."
#: qt\directories_dialog.py:96
msgid "Save Directories..."
msgstr "Guardar Carpetas..."
#: qt\directories_dialog.py:337
msgid "Select a directories file to load"
msgstr "Seleccione un archivo de carpetas para cargar"
#: qt\directories_dialog.py:338
msgid "dupeGuru Results (*.dupegurudirs)"
msgstr "Resultados dupeGuru (*.dupeguru)"
#: qt\directories_dialog.py:347
msgid "Select a file to save your directories to"
msgstr "Seleccionar un fichero al que guardar las carpetas"
#: qt\directories_dialog.py:348
msgid "dupeGuru Directories (*.dupegurudirs)"
msgstr "Carpetas dupeGuru (*.dupegurudirs)"
#: qt\exclude_list_dialog.py:44
msgid "Add"
msgstr "Agregar"
#: qt\exclude_list_dialog.py:46
msgid "Restore defaults"
msgstr "Reiniciar a Valores por Defecto"
#: qt\exclude_list_dialog.py:47
msgid "Test string"
msgstr "Cadena de prueba"
#: qt\exclude_list_dialog.py:83
msgid "Type a python regular expression here..."
msgstr "Escriba una expresión regular de Python aquí..."
#: qt\exclude_list_dialog.py:85
msgid "Type a file system path or filename here..."
msgstr "" msgstr ""
"Escriba una ruta del sistema de archivos o un nombre de archivo aquí..."
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\exclude_list_dialog.py:152
msgid "Music" msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happen to match one of the regular expressions.<br>For each file collected two tests are perfomed on each of them to determine whether or not to filter them out:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with no path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the test string feature by pasting a fake path in it:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr "" msgstr ""
"Estas expresiones regulares de Python (sensibles a mayúsculas y minúsculas) filtrarán los archivos durante los escaneos.<br> Carpetas también tendrá su <strong>establecido en Excluido</strong> en la pestaña Carpetas si su nombre coincide con una de las expresiones regulares seleccionadas.<br>Para cada archivo recopilado, se realizan dos pruebas para determinar si se debe ignorar por completo o no.<br><li>1. Las expresiones regulares sin separador de ruta se compararán solo con el nombre del archivo.</li>\n"
"<li>2. Las expresiones regulares con al menos un separador de ruta en ellas se compararán con la ruta completa al archivo.</li><br>\n"
"Ejemplo: si desea filtrar archivos .PNG solo del directorio \"Mis imágenes\":<br><code>.*Mis\\sImágenes\\\\.*\\.png</code><br><br>Puede probar la expresión regular con el botón \"cadena de prueba\" después de pegar una ruta falsa en el campo de prueba:<br><code>C:\\\\Usario\\Mis Imágenes\\test.png</code><br><br>\n"
"Se resaltarán las expresiones regulares coincidentes.<br>Si hay al menos un resaltado, la ruta o el nombre de archivo probado se ignorará durante los escaneos.<br><br>Directorios y archivos que comienzan con un punto '.' se ignoran de forma predeterminada.<br><br>"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\exclude_list_table.py:36
msgid "Picture" msgid "Compilation error: "
msgstr "Error de compilación:"
#: qt\pe\image_viewer.py:56
msgid "Increase zoom"
msgstr "Aumentar el zoom"
#: qt\pe\image_viewer.py:66
msgid "Decrease zoom"
msgstr "Disminuir zoom"
#: qt\pe\image_viewer.py:71
msgid "Ctrl+/"
msgstr "Ctrl+/"
#: qt\pe\image_viewer.py:76
msgid "Normal size"
msgstr "Tamaño normal"
#: qt\pe\image_viewer.py:81
msgid "Ctrl+*"
msgstr "Ctrl+*"
#: qt\pe\image_viewer.py:86
msgid "Best fit"
msgstr "Mejor ajuste"
#: qt\pe\preferences_dialog.py:49
msgid "Picture cache mode:"
msgstr "Modo de caché de imágenes:"
#: qt\pe\preferences_dialog.py:56
msgid "Override theme icons in viewer toolbar"
msgstr "Anula los iconos de temas en la barra de herramientas del visor"
#: qt\pe\preferences_dialog.py:58
msgid ""
"Use our own internal icons instead of those provided by the theme engine"
msgstr "" msgstr ""
"Utilice nuestros propios iconos internos en lugar de los proporcionados por "
"el motor de temas"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\pe\preferences_dialog.py:66
msgid "Standard" msgid "Show scrollbars in image viewers"
msgstr "Mostrar barras de desplazamiento en visores de imágenes"
#: qt\pe\preferences_dialog.py:68
msgid ""
"When the image displayed doesn't fit the viewport, show scrollbars to span "
"the view around"
msgstr "" msgstr ""
"Cuando la imagen mostrada no se ajusta a la ventana gráfica, muestre barras "
"de desplazamiento para abarcar la vista"
#: qt/directories_dialog.py:135 #: qt\preferences_dialog.py:156
msgid "More Options" msgid "Use default position for tab bar (requires restart)"
msgstr "" msgstr ""
"Use la posición predeterminada para la barra de pestañas (requiere "
"reiniciar)."
#~ msgid "Removing dead tracks from your iTunes Library" #: qt\preferences_dialog.py:158
#~ msgstr "Eliminando pistas muertas de la librería iTunes" msgid ""
"Place the tab bar below the main menu instead of next to it\n"
"On MacOS, the tab bar will fill up the window's width instead."
msgstr ""
"Coloque la barra de pestañas debajo del menú principal en lugar de al lado.\n"
"En MacOS, la barra de pestañas llenará el ancho de la ventana."
#~ msgid "Scanning the iTunes Library" #: qt\preferences_dialog.py:172
#~ msgstr "Explorando la librería iTunes" msgid "Use bold font for references"
msgstr "Utilice fuente en negrita para las referencias."
#~ msgid "Sending dupes to the Trash" #: qt\preferences_dialog.py:176
#~ msgstr "Enviando duplicados a la Papelera" msgid "Reference foreground color:"
msgstr "Color del texto de referencia:"
#~ msgid "Talking to iTunes. Don't touch it!" #: qt\preferences_dialog.py:179
#~ msgstr "Conectando con iTunes. ¡No tocar!" msgid "Reference background color:"
msgstr "Color de fondo de referencia:"
#~ msgid "" #: qt\preferences_dialog.py:182 qt\preferences_dialog.py:216
#~ "Your iTunes Library contains %d dead tracks ready to be removed. Continue?" msgid "Delta foreground color:"
#~ msgstr "" msgstr "Color del texto de delta:"
#~ "Su librería iTunes contiene %d pistas muertas listas para ser eliminadas. "
#~ "¿Continuar?"
#~ msgid "You have no dead tracks in your iTunes Library" #: qt\preferences_dialog.py:195
#~ msgstr "No hay pistas muertas en la librería iTunes" msgid "Show the title bar and can be docked"
msgstr "Muestra la barra de título y se puede acoplar."
#~ msgid "The iTunes application couldn't be found." #: qt\preferences_dialog.py:197
#~ msgstr "El programa iTunes no se encuentra" msgid ""
"While the title bar is hidden, use the modifier key to drag the floating "
"window around"
msgstr ""
"Si la barra de título está ocultada, use la tecla modificadora para "
"arrastrar la ventana flotante."
#~ msgid "Talking to iPhoto. Don't touch it!" #: qt\preferences_dialog.py:199
#~ msgstr "Conectando con iPhoto. ¡No tocar!" msgid "The title bar can only be disabled while the window is docked"
msgstr ""
"La barra de título solo se puede desactivar si la ventana está acoplada."
#~ msgid "Talking to Aperture. Don't touch it!" #: qt\preferences_dialog.py:202
#~ msgstr "Conectando con Aperture. ¡No tocar!" msgid "Vertical title bar"
msgstr "Barra de título vertical"
#~ msgid "Deleted Aperture photos were sent to a project called \"dupeGuru Trash\"." #: qt\preferences_dialog.py:204
#~ msgstr "" msgid ""
#~ "Las fotos borradas de Aperture han sido envíadas a un proyecto llamado " "Change the title bar from horizontal on top, to vertical on the left side"
#~ "\"Papelera dupeGuru\"" msgstr ""
"Cambie la barra de título de horizontal en la parte superior a vertical en "
"el lado izquierdo."
#~ msgid "The iPhoto application couldn't be found." #: qt\tabbed_window.py:44
#~ msgstr "No se puede encontrar el programa iPhoto." msgid "Show tab bar"
msgstr "Mostrar barra de pestañas"
#~ msgid "Preferences" #: qt\exclude_list_dialog.py:152
#~ msgstr "Preferencias" msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happens to match one of the selected regular expressions.<br>For each file collected, two tests are performed to determine whether or not to completely ignore it:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with at least one path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the \"test string\" button after pasting a fake path in the test field:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path or filename tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
"Estas expresiones regulares de Python (sensibles a mayúsculas y minúsculas) filtrarán los archivos durante los escaneos.<br> Carpetas también tendrá su <strong>establecido en Excluido</strong> en la pestaña Carpetas si su nombre coincide con una de las expresiones regulares seleccionadas.<br>Para cada archivo recopilado, se realizan dos pruebas para determinar si se debe ignorar por completo o no.<br><li>1. Las expresiones regulares sin separador de ruta se compararán solo con el nombre del archivo.</li>\n"
"<li>2. Las expresiones regulares con al menos un separador de ruta en ellas se compararán con la ruta completa al archivo.</li><br>\n"
"Ejemplo: si desea filtrar archivos .PNG solo del directorio \"Mis imágenes\":<br><code>.*Mis\\sImágenes\\\\.*\\.png</code><br><br>Puede probar la expresión regular con el botón \"cadena de prueba\" después de pegar una ruta falsa en el campo de prueba:<br><code>C:\\\\Usario\\Mis Imágenes\\test.png</code><br><br>\n"
"Se resaltarán las expresiones regulares coincidentes.<br>Si hay al menos un resaltado, la ruta o el nombre de archivo probado se ignorará durante los escaneos.<br><br>Directorios y archivos que comienzan con un punto '.' se ignoran de forma predeterminada.<br><br>"
#~ msgid "Check for Update" #: qt\app.py:256
#~ msgstr "Comprobar Actualizaciones" msgid "Results"
msgstr "Resultados"
#~ msgid "Filename" #: qt\preferences_dialog.py:150
#~ msgstr "Nombre de fichero" msgid "General Interface"
msgstr "Interfaz general"
#~ msgid "Filename - Fields" #: qt\preferences_dialog.py:176
#~ msgstr "Nombre de fichero - Campos" msgid "Result Table"
msgstr "Tabla de resultados"
#~ msgid "Filename - Fields (No Order)" #: qt\preferences_dialog.py:205
#~ msgstr "Nombre de fichero - Campos (sin orden)" msgid "Details Window"
msgstr "Ventana de detalles"
#~ msgid "Tags" #: qt\preferences_dialog.py:285
#~ msgstr "Etiquetas" msgid "General"
msgstr "General"
#~ msgid "Contents" #: qt\preferences_dialog.py:286
#~ msgstr "Contenidos" msgid "Display"
msgstr "Visualización"
#~ msgid "Audio Contents"
#~ msgstr "Contenidos de Audio"
#~ msgid "EXIF Timestamp"
#~ msgstr "Marca horaria EXIF"
#~ msgid "Folders"
#~ msgstr "Carpetas"
#~ msgid "Add Aperture Library"
#~ msgstr "Añadir librería de Aperture"
#~ msgid "Add iPhoto Library"
#~ msgstr "Añadir librería de iPhoto"
#~ msgid "Add iTunes Library"
#~ msgstr "Añadir librería de iTunes"
#~ msgid "Audio Content"
#~ msgstr "Contenido de Audio"
#~ msgid "Content"
#~ msgstr "Contenido"
#~ msgid "dupeGuru ME Preferences"
#~ msgstr "Preferencias de dupeGuru ME"
#~ msgid "dupeGuru PE Preferences"
#~ msgstr "Preferencias de dupeGuru PE"
#~ msgid "Remove Dead Tracks in iTunes"
#~ msgstr "Quitar Pistar Muertes en iTunes"

View File

@@ -1,124 +1,123 @@
# Translators: # Translators:
# hsoft <hsoft@hardcoded.net>, 2012 # Andrew Senetar <arsenetar@gmail.com>, 2021
# hsoft <hsoft@hardcoded.net>, 2012 # Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2013-11-20 11:53+0000\n" "Language-Team: French (https://www.transifex.com/voltaicideas/teams/116153/fr/)\n"
"Last-Translator: hsoft <hsoft@hardcoded.net>\n" "Language: fr\n"
"Language-Team: French (http://www.transifex.com/projects/p/dupeguru/language/fr/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: core/gui/ignore_list_table.py:18 core/gui/ignore_list_table.py:19 #: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core/gui/problem_table.py:17 #: core\gui\problem_table.py:18
msgid "File Path" msgid "File Path"
msgstr "Chemin du fichier" msgstr "Chemin du fichier"
#: core/gui/problem_table.py:18 #: core\gui\problem_table.py:19
msgid "Error Message" msgid "Error Message"
msgstr "Message d'erreur" msgstr "Message d'erreur"
#: core/me/result_table.py:24 core/pe/result_table.py:21 core/prioritize.py:63 #: core\me\prioritize.py:23
#: core/se/result_table.py:21
msgid "Kind"
msgstr "Type"
#: core/me/result_table.py:19 core/pe/result_table.py:19 core/prioritize.py:72
#: core/se/result_table.py:19
msgid "Folder"
msgstr "Dossier"
#: core/me/result_table.py:18 core/pe/result_table.py:18 core/prioritize.py:88
#: core/se/result_table.py:18
msgid "Filename"
msgstr "Nom de fichier"
#: core/prioritize.py:147
msgid "Size"
msgstr "Taille"
#: core/me/result_table.py:25 core/pe/result_table.py:24
#: core/prioritize.py:153 core/se/result_table.py:22
msgid "Modification"
msgstr "Modification"
#: core/me/prioritize.py:18
msgid "Duration" msgid "Duration"
msgstr "Durée" msgstr "Durée"
#: core/me/prioritize.py:24 core/me/result_table.py:22 #: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate" msgid "Bitrate"
msgstr "Bitrate" msgstr "Bitrate"
#: core/me/prioritize.py:30 #: core\me\prioritize.py:37
msgid "Samplerate" msgid "Samplerate"
msgstr "Échantillonnage" msgstr "Échantillonnage"
#: core/me/result_table.py:20 #: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
#: core\se\result_table.py:19
msgid "Filename"
msgstr "Nom de fichier"
#: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core\se\result_table.py:20
msgid "Folder"
msgstr "Dossier"
#: core\me\result_table.py:21
msgid "Size (MB)" msgid "Size (MB)"
msgstr "Taille (MB)" msgstr "Taille (MB)"
#: core/me/result_table.py:21 #: core\me\result_table.py:22
msgid "Time" msgid "Time"
msgstr "Temps" msgstr "Temps"
#: core/me/result_table.py:23 #: core\me\result_table.py:24
msgid "Sample Rate" msgid "Sample Rate"
msgstr "Sample Rate" msgstr "Sample Rate"
#: core/me/result_table.py:26 #: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core\se\result_table.py:22
msgid "Kind"
msgstr "Type"
#: core\me\result_table.py:26 core\pe\result_table.py:25
#: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification"
msgstr "Modification"
#: core\me\result_table.py:27
msgid "Title" msgid "Title"
msgstr "Titre" msgstr "Titre"
#: core/me/result_table.py:27 #: core\me\result_table.py:28
msgid "Artist" msgid "Artist"
msgstr "Artiste" msgstr "Artiste"
#: core/me/result_table.py:28 #: core\me\result_table.py:29
msgid "Album" msgid "Album"
msgstr "Album" msgstr "Album"
#: core/me/result_table.py:29 #: core\me\result_table.py:30
msgid "Genre" msgid "Genre"
msgstr "Genre" msgstr "Genre"
#: core/me/result_table.py:30 #: core\me\result_table.py:31
msgid "Year" msgid "Year"
msgstr "Année" msgstr "Année"
#: core/me/result_table.py:31 #: core\me\result_table.py:32
msgid "Track Number" msgid "Track Number"
msgstr "Track" msgstr "Track"
#: core/me/result_table.py:32 #: core\me\result_table.py:33
msgid "Comment" msgid "Comment"
msgstr "Commentaire" msgstr "Commentaire"
#: core/me/result_table.py:33 core/pe/result_table.py:25 #: core\me\result_table.py:34 core\pe\result_table.py:26
#: core/se/result_table.py:23 #: core\se\result_table.py:24
msgid "Match %" msgid "Match %"
msgstr "Match %" msgstr "Match %"
#: core/me/result_table.py:34 core/se/result_table.py:24 #: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used" msgid "Words Used"
msgstr "Mots" msgstr "Mots"
#: core/me/result_table.py:35 core/pe/result_table.py:26 #: core\me\result_table.py:36 core\pe\result_table.py:27
#: core/se/result_table.py:25 #: core\se\result_table.py:26
msgid "Dupe Count" msgid "Dupe Count"
msgstr "# Doublons" msgstr "Nombre de Doublons"
#: core/pe/prioritize.py:18 core/pe/result_table.py:22 #: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions" msgid "Dimensions"
msgstr "Dimensions" msgstr "Dimensions"
#: core/pe/result_table.py:20 core/se/result_table.py:20 #: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)" msgid "Size (KB)"
msgstr "Taille (KB)" msgstr "Taille (KB)"
#: core/pe/result_table.py:23 #: core\pe\result_table.py:24
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "Date EXIF" msgstr "Date EXIF"
#: core\prioritize.py:156
msgid "Size"
msgstr "Taille"

View File

@@ -1,26 +1,25 @@
# Translators: # Translators:
# hsoft <hsoft@hardcoded.net>, 2013 # Andrew Senetar <arsenetar@gmail.com>, 2021
# hsoft <hsoft@hardcoded.net>, 2013 # Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2013-12-07 15:22+0000\n" "Language-Team: French (https://www.transifex.com/voltaicideas/teams/116153/fr/)\n"
"Last-Translator: hsoft <hsoft@hardcoded.net>\n" "Language: fr\n"
"Language-Team: French (http://www.transifex.com/projects/p/dupeguru/language/fr/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: core/app.py:40 #: core\app.py:42
msgid "There are no marked duplicates. Nothing has been done." msgid "There are no marked duplicates. Nothing has been done."
msgstr "Aucun doublon marqué. Rien à faire." msgstr "Aucun doublon marqué. Rien à faire."
#: core/app.py:41 #: core\app.py:43
msgid "There are no selected duplicates. Nothing has been done." msgid "There are no selected duplicates. Nothing has been done."
msgstr "Aucun doublon sélectionné. Rien à faire." msgstr "Aucun doublon sélectionné. Rien à faire."
#: core/app.py:42 #: core\app.py:44
msgid "" msgid ""
"You're about to open many files at once. Depending on what those files are " "You're about to open many files at once. Depending on what those files are "
"opened with, doing so can create quite a mess. Continue?" "opened with, doing so can create quite a mess. Continue?"
@@ -28,27 +27,27 @@ msgstr ""
"Beaucoup de fichiers seront ouverts en même temps. Cela peut gravement " "Beaucoup de fichiers seront ouverts en même temps. Cela peut gravement "
"encombrer votre système. Continuer?" "encombrer votre système. Continuer?"
#: core/app.py:65 #: core\app.py:71
msgid "Scanning for duplicates" msgid "Scanning for duplicates"
msgstr "Scan de doublons en cours" msgstr "Scan de doublons en cours"
#: core/app.py:66 #: core\app.py:72
msgid "Loading" msgid "Loading"
msgstr "Chargement en cours" msgstr "Chargement en cours"
#: core/app.py:67 #: core\app.py:73
msgid "Moving" msgid "Moving"
msgstr "Déplacement en cours" msgstr "Déplacement en cours"
#: core/app.py:68 #: core\app.py:74
msgid "Copying" msgid "Copying"
msgstr "Copie en cours" msgstr "Copie en cours"
#: core/app.py:69 #: core\app.py:75
msgid "Sending to Trash" msgid "Sending to Trash"
msgstr "Envoi de fichiers à la corbeille" msgstr "Envoi de fichiers à la corbeille"
#: core/app.py:279 #: core\app.py:308
msgid "" msgid ""
"A previous action is still hanging in there. You can't start a new one yet. " "A previous action is still hanging in there. You can't start a new one yet. "
"Wait a few seconds, then try again." "Wait a few seconds, then try again."
@@ -56,219 +55,204 @@ msgstr ""
"Une action précédente est encore en cours. Attendez quelques secondes avant " "Une action précédente est encore en cours. Attendez quelques secondes avant "
"d'en repartir une nouvelle." "d'en repartir une nouvelle."
#: core/app.py:289 #: core\app.py:318
msgid "No duplicates found." msgid "No duplicates found."
msgstr "Aucun doublon trouvé." msgstr "Aucun doublon trouvé."
#: core/app.py:304 #: core\app.py:333
msgid "All marked files were copied successfully." msgid "All marked files were copied successfully."
msgstr "Tous les fichiers marqués ont été copiés correctement." msgstr "Tous les fichiers marqués ont été copiés correctement."
#: core/app.py:305 #: core\app.py:334
msgid "All marked files were moved successfully." msgid "All marked files were moved successfully."
msgstr "Tous les fichiers marqués ont été déplacés correctement." msgstr "Tous les fichiers marqués ont été déplacés correctement."
#: core/app.py:306 #: core\app.py:335
msgid "All marked files were successfully sent to Trash." msgid "All marked files were successfully sent to Trash."
msgstr "" msgstr ""
"Tous les fichiers marqués ont été correctement envoyés à la corbeille." "Tous les fichiers marqués ont été correctement envoyés à la corbeille."
#: core/app.py:368 #: core\app.py:343
msgid "Could not load file: {}"
msgstr "Impossible d'ouvrir le fichier: {}"
#: core\app.py:399
msgid "'{}' already is in the list." msgid "'{}' already is in the list."
msgstr "'{}' est déjà dans la liste." msgstr "'{}' est déjà dans la liste."
#: core/app.py:370 #: core\app.py:401
msgid "'{}' does not exist." msgid "'{}' does not exist."
msgstr "'{}' n'existe pas." msgstr "'{}' n'existe pas."
#: core/app.py:379 #: core\app.py:410
msgid "" msgid ""
"All selected %d matches are going to be ignored in all subsequent scans. " "All selected %d matches are going to be ignored in all subsequent scans. "
"Continue?" "Continue?"
msgstr "%d fichiers seront ignorés des prochains scans. Continuer?" msgstr "%d fichiers seront ignorés des prochains scans. Continuer?"
#: core/app.py:450 #: core\app.py:486
msgid "copy" msgid "Select a directory to copy marked files to"
msgstr "copier" msgstr "Sélectionnez un dossier vers lequel copier les fichiers marqués."
#: core/app.py:450 #: core\app.py:487
msgid "move" msgid "Select a directory to move marked files to"
msgstr "déplacer" msgstr "Sélectionnez un dossier vers lequel déplacer les fichiers marqués."
#: core/app.py:451 #: core\app.py:527
msgid "Select a directory to {} marked files to"
msgstr "Sélectionnez un dossier vers lequel {} les fichiers marqués."
#: core/app.py:490
msgid "Select a destination for your exported CSV" msgid "Select a destination for your exported CSV"
msgstr "Choisissez une destination pour votre exportation CSV" msgstr "Choisissez une destination pour votre exportation CSV"
#: core/app.py:518 #: core\app.py:534 core\app.py:801 core\app.py:811
msgid "Couldn't write to file: {}"
msgstr "Impossible d'écrire le fichier: {}"
#: core\app.py:559
msgid "You have no custom command set up. Set it up in your preferences." msgid "You have no custom command set up. Set it up in your preferences."
msgstr "" msgstr ""
"Vous n'avez pas de commande personnalisée. Ajoutez-la dans vos préférences." "Vous n'avez pas de commande personnalisée. Ajoutez-la dans vos préférences."
#: core/app.py:672 core/app.py:685 #: core\app.py:727 core\app.py:740
msgid "You are about to remove %d files from results. Continue?" msgid "You are about to remove %d files from results. Continue?"
msgstr "%d fichiers seront retirés des résultats. Continuer?" msgstr "%d fichiers seront retirés des résultats. Continuer?"
#: core/app.py:719 #: core\app.py:774
msgid "{} duplicate groups were changed by the re-prioritization." msgid "{} duplicate groups were changed by the re-prioritization."
msgstr "{} groupes de doublons ont été modifiés par la re-prioritisation." msgstr "{} groupes de doublons ont été modifiés par la re-prioritisation."
#: core/app.py:762 #: core\app.py:821
msgid "Collecting files to scan"
msgstr "Collecte des fichiers à scanner"
#: core/app.py:751
msgid "The selected directories contain no scannable file." msgid "The selected directories contain no scannable file."
msgstr "Les dossiers sélectionnés ne contiennent pas de fichiers valides." msgstr "Les dossiers sélectionnés ne contiennent pas de fichiers valides."
#: core/app.py:810 #: core\app.py:835
msgid "Collecting files to scan"
msgstr "Collecte des fichiers à scanner"
#: core\app.py:891
msgid "%s (%d discarded)" msgid "%s (%d discarded)"
msgstr "%s (%d hors-groupe)" msgstr "%s (%d hors-groupe)"
#: core/engine.py:222 core/engine.py:262 #: core\engine.py:244 core\engine.py:288
msgid "0 matches found" msgid "0 matches found"
msgstr "0 paires trouvées" msgstr "0 paires trouvées"
#: core/engine.py:240 core/engine.py:270 #: core\engine.py:262 core\engine.py:296
msgid "%d matches found" msgid "%d matches found"
msgstr "%d paires trouvées" msgstr "%d paires trouvées"
#: core/scanner.py:77 #: core\gui\deletion_options.py:73
msgid "Read size of %d/%d files"
msgstr "Lu la taille de %d/%d fichiers"
#: core/gui/deletion_options.py:69
msgid "You are sending {} file(s) to the Trash." msgid "You are sending {} file(s) to the Trash."
msgstr "Vous envoyez {} fichier(s) à la corbeille." msgstr "Vous envoyez {} fichier(s) à la corbeille."
#: core/gui/ignore_list_dialog.py:24 #: core\gui\exclude_list_table.py:15
msgid "Regular Expressions"
msgstr "Expressions régulières"
#: core\gui\ignore_list_dialog.py:25
msgid "Do you really want to remove all %d items from the ignore list?" msgid "Do you really want to remove all %d items from the ignore list?"
msgstr "" msgstr ""
"Voulez-vous vider la liste de fichiers ignorés des %d items qu'elle " "Voulez-vous vider la liste de fichiers ignorés des %d items qu'elle "
"contient?" "contient?"
#: core/prioritize.py:68 #: core\me\scanner.py:20 core\se\scanner.py:16
msgid "None" msgid "Filename"
msgstr "Aucune" msgstr "Nom de fichier"
#: core/prioritize.py:96 #: core\me\scanner.py:21
msgid "Ends with number" msgid "Filename - Fields"
msgstr "Chiffres à la fin" msgstr "Nom de fichier - Champs"
#: core/prioritize.py:97 #: core\me\scanner.py:22
msgid "Doesn't end with number" msgid "Filename - Fields (No Order)"
msgstr "Pas de chiffres à la finr" msgstr "Nom de fichier - Champs (sans ordre)"
#: core/prioritize.py:98 #: core\me\scanner.py:23
msgid "Longest" msgid "Tags"
msgstr "Le plus long" msgstr "Tags"
#: core/prioritize.py:99 #: core\me\scanner.py:24 core\pe\scanner.py:21 core\se\scanner.py:17
msgid "Shortest" msgid "Contents"
msgstr "Le plus court" msgstr "Contenu"
#: core/prioritize.py:132 #: core\pe\matchblock.py:72
msgid "Highest"
msgstr "Plus grand"
#: core/prioritize.py:132
msgid "Lowest"
msgstr "Moins grand"
#: core/prioritize.py:159
msgid "Newest"
msgstr "Plus récent"
#: core/prioritize.py:159
msgid "Oldest"
msgstr "Moins récent"
#: core/results.py:129
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) doublons marqués."
#: core/results.py:136
msgid " filter: %s"
msgstr " filtre: %s"
#: core/scanner.py:101
msgid "Read metadata of %d/%d files"
msgstr "Lu les métadonnées de %d/%d fichiers"
#: core/pe/matchblock.py:61
msgid "Analyzed %d/%d pictures" msgid "Analyzed %d/%d pictures"
msgstr "Analyzé %d/%d images" msgstr "Analyzé %d/%d images"
#: core/pe/matchblock.py:156 #: core\pe\matchblock.py:181
msgid "Performed %d/%d chunk matches" msgid "Performed %d/%d chunk matches"
msgstr "%d/%d blocs d'images comparés" msgstr "%d/%d blocs d'images comparés"
#: core/pe/matchblock.py:161 #: core\pe\matchblock.py:191
msgid "Preparing for matching" msgid "Preparing for matching"
msgstr "Préparation pour la comparaison" msgstr "Préparation pour la comparaison"
#: core/pe/matchblock.py:206 #: core\pe\matchblock.py:244
msgid "Verified %d/%d matches" msgid "Verified %d/%d matches"
msgstr "Vérifié %d/%d paires" msgstr "Vérifié %d/%d paires"
#: core/pe/matchexif.py:18 #: core\pe\matchexif.py:19
msgid "Read EXIF of %d/%d pictures" msgid "Read EXIF of %d/%d pictures"
msgstr "Lu l'EXIF de %d/%d images" msgstr "Lu l'EXIF de %d/%d images"
#: core/app.py:312 #: core\pe\scanner.py:22
msgid "Could not load file: {}"
msgstr ""
#: core/app.py:496 core/app.py:742
msgid "Couldn't write to file: {}"
msgstr ""
#: core/me/scanner.py:19 core/se/scanner.py:15
msgid "Filename"
msgstr ""
#: core/me/scanner.py:20
msgid "Filename - Fields"
msgstr ""
#: core/me/scanner.py:21
msgid "Filename - Fields (No Order)"
msgstr ""
#: core/me/scanner.py:22
msgid "Tags"
msgstr ""
#: core/me/scanner.py:23 core/pe/scanner.py:20 core/se/scanner.py:16
msgid "Contents"
msgstr ""
#: core/pe/scanner.py:21
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "" msgstr "Date EXIF"
#: core/scanner.py:139 #: core\prioritize.py:70
msgid "None"
msgstr "Aucune"
#: core\prioritize.py:100
msgid "Ends with number"
msgstr "Chiffres à la fin"
#: core\prioritize.py:101
msgid "Doesn't end with number"
msgstr "Pas de chiffres à la finr"
#: core\prioritize.py:102
msgid "Longest"
msgstr "Le plus long"
#: core\prioritize.py:103
msgid "Shortest"
msgstr "Le plus court"
#: core\prioritize.py:140
msgid "Highest"
msgstr "Plus grand"
#: core\prioritize.py:140
msgid "Lowest"
msgstr "Moins grand"
#: core\prioritize.py:169
msgid "Newest"
msgstr "Plus récent"
#: core\prioritize.py:169
msgid "Oldest"
msgstr "Moins récent"
#: core\results.py:142
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) doublons marqués."
#: core\results.py:149
msgid " filter: %s"
msgstr " filtre: %s"
#: core\scanner.py:85
msgid "Read size of %d/%d files"
msgstr "Lu la taille de %d/%d fichiers"
#: core\scanner.py:109
msgid "Read metadata of %d/%d files"
msgstr "Lu les métadonnées de %d/%d fichiers"
#: core\scanner.py:147
msgid "Almost done! Fiddling with results..." msgid "Almost done! Fiddling with results..."
msgstr "" msgstr "Bientôt terminé! Bidouille des résultats..."
#: core/se/scanner.py:17 #: core\se\scanner.py:18
msgid "Folders" msgid "Folders"
msgstr "" msgstr "Dossiers"
#~ msgid "Sending files to the recycle bin"
#~ msgstr "Envoi de fichiers à la corbeille"
#~ msgid "Grouped %d/%d matches"
#~ msgstr "%d/%d paires groupées"
#~ msgid "Removing false matches"
#~ msgstr "Retrait des paires invalides"
#~ msgid "Processed %d/%d matches against the ignore list"
#~ msgstr "Vérification de %d/%d paires dans la ignore list"
#~ msgid "Doing group prioritization"
#~ msgstr "Prioritization des groupes"

View File

@@ -1,27 +1,34 @@
# Translators: # Translators:
# hsoft <hsoft@hardcoded.net>, 2012 # Andrew Senetar <arsenetar@gmail.com>, 2021
# hsoft <hsoft@hardcoded.net>, 2012-2013 # Fuan <jcfrt@posteo.net>, 2021
# hsoft <hsoft@hardcoded.net>, 2013 #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2013-12-07 15:22+0000\n" "Language-Team: French (https://www.transifex.com/voltaicideas/teams/116153/fr/)\n"
"Last-Translator: hsoft <hsoft@hardcoded.net>\n" "Language: fr\n"
"Language-Team: French (http://www.transifex.com/projects/p/dupeguru/language/fr/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: qt/app.py:81 #: qt/app.py:81
msgid "Quit" msgid "Quit"
msgstr "Quitter" msgstr "Quitter"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Options"
#: qt/app.py:83 qt/ignore_list_dialog.py:32 #: qt/app.py:83 qt/ignore_list_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Ignore List" msgid "Ignore List"
msgstr "Liste de doublons ignorés" msgstr "Liste de doublons ignorés"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Vider la cache d'images"
#: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0 #: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Help" msgid "dupeGuru Help"
msgstr "Aide dupeGuru" msgstr "Aide dupeGuru"
@@ -34,6 +41,14 @@ msgstr "À propos de dupeGuru"
msgid "Open Debug Log" msgid "Open Debug Log"
msgstr "Ouvrir logs de déboguage" msgstr "Ouvrir logs de déboguage"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr "Voulez-vous vraiment vider la cache de vos analyses précédentes?"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "La cache des analyses précédentes a été vidée."
#: qt/app.py:251 #: qt/app.py:251
msgid "{} file (*.{})" msgid "{} file (*.{})"
msgstr "Fichier {} (*.{})" msgstr "Fichier {} (*.{})"
@@ -64,7 +79,7 @@ msgstr "Symlink"
#: qt/deletion_options.py:48 #: qt/deletion_options.py:48
msgid " (unsupported)" msgid " (unsupported)"
msgstr "" msgstr "(non pris en charge)"
#: qt/deletion_options.py:49 cocoa/en.lproj/Localizable.strings:0 #: qt/deletion_options.py:49 cocoa/en.lproj/Localizable.strings:0
msgid "Directly delete files" msgid "Directly delete files"
@@ -129,6 +144,30 @@ msgstr "Aide"
msgid "Load Recent Results" msgid "Load Recent Results"
msgstr "Charger résultats récents" msgstr "Charger résultats récents"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0
msgid "Application Mode:"
msgstr "Mode de l'application:"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Music"
msgstr "Musique"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Picture"
msgstr "Image"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Standard"
msgstr "Standard"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0
msgid "Scan Type:"
msgstr "Type de scan:"
#: qt/directories_dialog.py:135
msgid "More Options"
msgstr "Plus d'options"
#: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0 #: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0
msgid "Select folders to scan and press \"Scan\"." msgid "Select folders to scan and press \"Scan\"."
msgstr "Sélectionnez les dossiers à scanner puis faites \"Scan\"." msgstr "Sélectionnez les dossiers à scanner puis faites \"Scan\"."
@@ -203,9 +242,78 @@ msgstr "Vider"
msgid "Close" msgid "Close"
msgstr "Fermer" msgstr "Fermer"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0 #: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
msgid "Scan Type:" #: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
msgstr "Type de scan:" #: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Détails"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Tags à scanner:"
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Track"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Artiste"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Album"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Titre"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Genre"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Année"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "Proportionalité des mots"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Comparer les mots similaires"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Comparer les fichiers de différents types"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Utiliser les expressions régulières pour les filtres"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Effacer les dossiers vides après un déplacement"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Ignorer doublons avec hardlink vers le même fichier"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Mode de déboguage (redémarrage requis)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Comparer les images de tailles différentes"
#: qt/preferences_dialog.py:43 #: qt/preferences_dialog.py:43
msgid "Filter Hardness:" msgid "Filter Hardness:"
@@ -213,11 +321,11 @@ msgstr "Seuil du filtre:"
#: qt/preferences_dialog.py:69 #: qt/preferences_dialog.py:69
msgid "More Results" msgid "More Results"
msgstr "+ de doublons" msgstr "Plus de doublons"
#: qt/preferences_dialog.py:74 #: qt/preferences_dialog.py:74
msgid "Fewer Results" msgid "Fewer Results"
msgstr "- de doublons" msgstr "Moins de doublons"
#: qt/preferences_dialog.py:81 #: qt/preferences_dialog.py:81
msgid "Font size:" msgid "Font size:"
@@ -283,12 +391,6 @@ msgstr ""
msgid "Reveal Selected" msgid "Reveal Selected"
msgstr "Révéler Fichier" msgstr "Révéler Fichier"
#: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
#: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Détails"
#: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167 #: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167
#: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0
msgid "Actions" msgid "Actions"
@@ -392,7 +494,7 @@ msgstr "Réinitialiser"
#: qt/result_window.py:185 #: qt/result_window.py:185
msgid "{} Results" msgid "{} Results"
msgstr "{} (Résultats)" msgstr "{} résultats"
#: qt/result_window.py:193 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:193 cocoa/en.lproj/Localizable.strings:0
msgid "Dupes Only" msgid "Dupes Only"
@@ -404,86 +506,7 @@ msgstr "Delta"
#: qt/result_window.py:310 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:310 cocoa/en.lproj/Localizable.strings:0
msgid "Select a file to save your results to" msgid "Select a file to save your results to"
msgstr "Sélectionnez un fichier résultats dans lequel sauvegarder" msgstr "Sélectionnez un fichier dans lequel sauvegarder les résultats"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Tags à scanner:"
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Track"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Artiste"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Album"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Titre"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Genre"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Année"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "Proportionalité des mots"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Comparer les mots similaires"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Comparer les fichiers de différents types"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Utiliser les expressions régulières pour les filtres"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Effacer les dossiers vides après un déplacement"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Ignorer doublons avec hardlink vers le même fichier"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Mode de déboguage (redémarrage requis)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Comparer les images de tailles différentes"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Vider la cache d'images"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr "Voulez-vous vraiment vider la cache de vos analyses précédentes?"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "La cache des analyses précédentes a été vidée."
#: qt/se/preferences_dialog.py:41 #: qt/se/preferences_dialog.py:41
msgid "Ignore files smaller than" msgid "Ignore files smaller than"
@@ -567,7 +590,7 @@ msgstr "Préférences de dupeGuru"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Results" msgid "dupeGuru Results"
msgstr "dupeGuru (Résultats)" msgstr "Résultats dupeGuru"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Website" msgid "dupeGuru Website"
@@ -587,7 +610,7 @@ msgstr "Exporter les résultats vers HTML"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Fewer results" msgid "Fewer results"
msgstr "- de doubles" msgstr "moins de doublons"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Filter" msgid "Filter"
@@ -635,17 +658,12 @@ msgstr "Mode"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "More results" msgid "More results"
msgstr "+ de doubles" msgstr "plus de doublons"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Ok" msgid "Ok"
msgstr "Ok" msgstr "Ok"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Options"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Paste" msgid "Paste"
msgstr "Coller" msgstr "Coller"
@@ -680,7 +698,7 @@ msgstr "Révéler sélectionné dans Finder"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Select All" msgid "Select All"
msgstr "" msgstr "Tout sélectionner"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Send Marked to Trash..." msgid "Send Marked to Trash..."
@@ -710,114 +728,217 @@ msgstr "Fenêtre"
msgid "Zoom" msgid "Zoom"
msgstr "Réduire/agrandir" msgstr "Réduire/agrandir"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0 #: qt\app.py:158
msgid "Application Mode:" msgid "Exclusion Filters"
msgstr "Filtres d'exclusion"
#: qt\directories_dialog.py:91
msgid "Scan Results"
msgstr "Résultats de scan"
#: qt\directories_dialog.py:95
msgid "Load Directories..."
msgstr "Charger dossiers..."
#: qt\directories_dialog.py:96
msgid "Save Directories..."
msgstr "Sauvegarder dossiers..."
#: qt\directories_dialog.py:337
msgid "Select a directories file to load"
msgstr "Sélectionnez un fichier de dossier à charger"
#: qt\directories_dialog.py:338
msgid "dupeGuru Results (*.dupegurudirs)"
msgstr "Dossiers dupeGuru (*.dupegurudirs)"
#: qt\directories_dialog.py:347
msgid "Select a file to save your directories to"
msgstr "Sélectionnez un fichier pour y sauvegarder vos dossiers"
#: qt\directories_dialog.py:348
msgid "dupeGuru Directories (*.dupegurudirs)"
msgstr "Dossiers dupeGuru (*.dupegurudirs)"
#: qt\exclude_list_dialog.py:44
msgid "Add"
msgstr "Ajouter"
#: qt\exclude_list_dialog.py:46
msgid "Restore defaults"
msgstr "Réinitialiser"
#: qt\exclude_list_dialog.py:47
msgid "Test string"
msgstr "Tester chaîne"
#: qt\exclude_list_dialog.py:83
msgid "Type a python regular expression here..."
msgstr "Tapez une expression régulière python ici..."
#: qt\exclude_list_dialog.py:85
msgid "Type a file system path or filename here..."
msgstr "Tapez un chemin ou un nom de fichier ici..."
#: qt\exclude_list_dialog.py:152
msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happen to match one of the regular expressions.<br>For each file collected two tests are perfomed on each of them to determine whether or not to filter them out:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with no path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the test string feature by pasting a fake path in it:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr "" msgstr ""
"Ces expressions régulières python (sensible aux majuscules) peuvent ignorer les fichiers pendant les scans. Les dossiers auront également leur <strong>état par défaut</strong> mis sur Exclus dans l'onglet Dossiers si leur nom correspond à une des expressions régulières sélectionnées<br>Pour chaque fichier collecté, deux tests sont faits pour déterminer s'il doit être totalement ignoré:<br><li>1. Les expressions régulières sans séparateur de chemin sont comparées au nom de fichier seul.</li>\n"
"<li>2. Les expressions régulières avec au moins un séparateur de chemin sont comparées au chemin complet vers le fichier.</li><br>\n"
"Exemple: si vous voulez uniquement ignorer les fichiers .PNG du dossier \"Mes Images\":<br><code>.*Mes\\sImages\\\\.*\\.png</code><br><br>Vous pouvez tester l'expression régulière via le bouton \"Tester la chaîne de caractères\" après avoir tapé un faux chemin de fichier dans le champs correspondant:<br><code>C:\\\\Utilisateur\\Mes Images\\test.png</code><br><br>\n"
"Les expressions régulières qui fonctionnent seront surlignées.<br>S'il y a au moins un surlignage, le chemin ou nom de fichier testé sera ignoré durant les scans.<br><br>Les dossiers et fichiers commençant par un point '.' sont ignorés par défaut.<br><br>"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\exclude_list_table.py:36
msgid "Music" msgid "Compilation error: "
msgstr "Erreur de compilation:"
#: qt\pe\image_viewer.py:56
msgid "Increase zoom"
msgstr "Accroître zoom"
#: qt\pe\image_viewer.py:66
msgid "Decrease zoom"
msgstr "Décroître zoom"
#: qt\pe\image_viewer.py:71
msgid "Ctrl+/"
msgstr "Ctrl+/"
#: qt\pe\image_viewer.py:76
msgid "Normal size"
msgstr "Taille normale"
#: qt\pe\image_viewer.py:81
msgid "Ctrl+*"
msgstr "Ctrl+*"
#: qt\pe\image_viewer.py:86
msgid "Best fit"
msgstr "Meilleur ajustement"
#: qt\pe\preferences_dialog.py:49
msgid "Picture cache mode:"
msgstr "Mode de cache d'images:"
#: qt\pe\preferences_dialog.py:56
msgid "Override theme icons in viewer toolbar"
msgstr "Outrepasser le thème dicônes dans le visualiseur"
#: qt\pe\preferences_dialog.py:58
msgid ""
"Use our own internal icons instead of those provided by the theme engine"
msgstr "" msgstr ""
"Utiliser nos propres icônes plutôt que celles fournies par le moteur du "
"thème"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\pe\preferences_dialog.py:66
msgid "Picture" msgid "Show scrollbars in image viewers"
msgstr "Afficher les barres de défilement dans visualiseur d'images"
#: qt\pe\preferences_dialog.py:68
msgid ""
"When the image displayed doesn't fit the viewport, show scrollbars to span "
"the view around"
msgstr "" msgstr ""
"Si l'image affichée ne rentre par dans la fenêtre, afficher les barres de "
"défilement pour faire glisser la vue"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\preferences_dialog.py:156
msgid "Standard" msgid "Use default position for tab bar (requires restart)"
msgstr "Position par défaut pour la barre d'onglets (redémarrage requis)"
#: qt\preferences_dialog.py:158
msgid ""
"Place the tab bar below the main menu instead of next to it\n"
"On MacOS, the tab bar will fill up the window's width instead."
msgstr "" msgstr ""
"Placer la barre d'onglets sous le menu principal plutôt qu'à côté.\n"
"Sur MacOS, cette barre remplira la fenêtre en largeur."
#: qt/directories_dialog.py:135 #: qt\preferences_dialog.py:172
msgid "More Options" msgid "Use bold font for references"
msgstr "Utiliser police en gras pour les références"
#: qt\preferences_dialog.py:176
msgid "Reference foreground color:"
msgstr "Couleur du texte des référénces:"
#: qt\preferences_dialog.py:179
msgid "Reference background color:"
msgstr "Couleur de fond pour les références:"
#: qt\preferences_dialog.py:182 qt\preferences_dialog.py:216
msgid "Delta foreground color:"
msgstr "Couleur du texte des delta:"
#: qt\preferences_dialog.py:195
msgid "Show the title bar and can be docked"
msgstr "Affiche barre de titre et peut être ancrée"
#: qt\preferences_dialog.py:197
msgid ""
"While the title bar is hidden, use the modifier key to drag the floating "
"window around"
msgstr "" msgstr ""
"Quand la barre de titre est cachée, utilisez la touche méta pour déplacer la"
" fenêtre flottante"
#~ msgid "Removing dead tracks from your iTunes Library" #: qt\preferences_dialog.py:199
#~ msgstr "Retrait des tracks mortes de votre librairie iTunes" msgid "The title bar can only be disabled while the window is docked"
msgstr ""
"La barre de titre ne peut être désactivée que quand la fenêtre est ancrée"
#~ msgid "Scanning the iTunes Library" #: qt\preferences_dialog.py:202
#~ msgstr "Scan de la librairie iTunes en cours" msgid "Vertical title bar"
msgstr "Barre de titre verticale"
#~ msgid "Sending dupes to the Trash" #: qt\preferences_dialog.py:204
#~ msgstr "Envoi de doublons à la corbeille en cours" msgid ""
"Change the title bar from horizontal on top, to vertical on the left side"
msgstr ""
"Placer la barre de titre à la verticale côté gauche plutôt que à "
"l'horizontale en haut"
#~ msgid "Talking to iTunes. Don't touch it!" #: qt\tabbed_window.py:44
#~ msgstr "En communication avec iTunes. N'y touchez pas!" msgid "Show tab bar"
msgstr "Afficher la barre d'onglets"
#~ msgid "" #: qt\exclude_list_dialog.py:152
#~ "Your iTunes Library contains %d dead tracks ready to be removed. Continue?" msgid ""
#~ msgstr "" "These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happens to match one of the selected regular expressions.<br>For each file collected, two tests are performed to determine whether or not to completely ignore it:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
#~ "Votre librairie iTunes contient %d tracks mortes qui seront retirées. " "<li>2. Regular expressions with at least one path separator in them will be compared to the full path to the file.</li><br>\n"
#~ "Continuer?" "Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the \"test string\" button after pasting a fake path in the test field:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path or filename tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
"Ces expressions régulières python (sensible aux majuscules) peuvent ignorer les fichiers pendant les scans. Les dossiers auront également leur <strong>état par défaut</strong> mis sur Exclus dans l'onglet Dossiers si leur nom correspond à une des expressions régulières sélectionnées<br>Pour chaque fichier collecté, deux tests sont faits pour déterminer s'il doit être totalement ignoré:<br><li>1. Les expressions régulières sans séparateur de chemin sont comparées au nom de fichier seul.</li>\n"
"<li>2. Les expressions régulières avec au moins un séparateur de chemin sont comparées au chemin complet vers le fichier.</li><br>\n"
"Exemple: si vous voulez uniquement ignorer les fichiers .PNG du dossier \"Mes Images\":<br><code>.*Mes\\sImages\\\\.*\\.png</code><br><br>Vous pouvez tester l'expression régulière via le bouton \"Tester la chaîne de caractères\" après avoir tapé un faux chemin de fichier dans le champs correspondant:<br><code>C:\\\\Utilisateur\\Mes Images\\test.png</code><br><br>\n"
"Les expressions régulières qui fonctionnent seront surlignées.<br>S'il y a au moins un surlignage, le chemin ou nom de fichier testé sera ignoré durant les scans.<br><br>Les dossiers et fichiers commençant par un point '.' sont ignorés par défaut.<br><br>"
#~ msgid "You have no dead tracks in your iTunes Library" #: qt\app.py:256
#~ msgstr "Votre librairie iTunes ne contient aucune track morte." msgid "Results"
msgstr "Résultats"
#~ msgid "The iTunes application couldn't be found." #: qt\preferences_dialog.py:150
#~ msgstr "L'application iTunes n'a pas pu être trouvée" msgid "General Interface"
msgstr "Interface générale"
#~ msgid "Talking to iPhoto. Don't touch it!" #: qt\preferences_dialog.py:176
#~ msgstr "En communication avec iPhoto. N'y touchez pas!" msgid "Result Table"
msgstr "Tableau de résultats"
#~ msgid "Talking to Aperture. Don't touch it!" #: qt\preferences_dialog.py:205
#~ msgstr "En communication avec Aperture. N'y touchez pas!" msgid "Details Window"
msgstr "Fenêtre de détails"
#~ msgid "Deleted Aperture photos were sent to a project called \"dupeGuru Trash\"." #: qt\preferences_dialog.py:285
#~ msgstr "" msgid "General"
#~ "Les photos supprimés d'Aperture sont dans le projet nommé \"dupeGuru " msgstr "Général"
#~ "Trash\"."
#~ msgid "The iPhoto application couldn't be found." #: qt\preferences_dialog.py:286
#~ msgstr "iPhoto n'a pas pu être trouvée dans vos applications." msgid "Display"
msgstr "Affichage"
#~ msgid "Preferences"
#~ msgstr "Préférences"
#~ msgid "Check for Update"
#~ msgstr "Vérifier les mises à jour"
#~ msgid "Filename"
#~ msgstr "Nom de fichier"
#~ msgid "Filename - Fields"
#~ msgstr "Nom de fichier (Champs)"
#~ msgid "Filename - Fields (No Order)"
#~ msgstr "Nom de fichier (Champs sans ordre)"
#~ msgid "Tags"
#~ msgstr "Tags"
#~ msgid "Contents"
#~ msgstr "Contenu"
#~ msgid "Audio Contents"
#~ msgstr "Contenu Audio"
#~ msgid "EXIF Timestamp"
#~ msgstr "EXIF Timestamp"
#~ msgid "Folders"
#~ msgstr "Dossiers"
#~ msgid "Add Aperture Library"
#~ msgstr "Ajouter librairie Aperture"
#~ msgid "Add iPhoto Library"
#~ msgstr "Ajouter librairie iPhoto"
#~ msgid "Add iTunes Library"
#~ msgstr "Ajouter librairie iTunes"
#~ msgid "Audio Content"
#~ msgstr "Contenu Audio"
#~ msgid "Content"
#~ msgstr "Contenu"
#~ msgid "dupeGuru ME Preferences"
#~ msgstr "Préférences de dupeGuru ME"
#~ msgid "dupeGuru PE Preferences"
#~ msgstr "Préférences de dupeGuru PE"
#~ msgid "Remove Dead Tracks in iTunes"
#~ msgstr "Retirer les tracks mortes dans iTunes"

View File

@@ -1,122 +1,123 @@
# Translators: # Translators:
# Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2013-11-20 11:53+0000\n" "Language-Team: Armenian (https://www.transifex.com/voltaicideas/teams/116153/hy/)\n"
"Last-Translator: hsoft <hsoft@hardcoded.net>\n" "Language: hy\n"
"Language-Team: Armenian (http://www.transifex.com/projects/p/dupeguru/language/hy/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: hy\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: core/gui/ignore_list_table.py:18 core/gui/ignore_list_table.py:19 #: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core/gui/problem_table.py:17 #: core\gui\problem_table.py:18
msgid "File Path" msgid "File Path"
msgstr "Ֆայլի ճ-ը" msgstr "Ֆայլի ճ-ը"
#: core/gui/problem_table.py:18 #: core\gui\problem_table.py:19
msgid "Error Message" msgid "Error Message"
msgstr "Սխալի գրությունը" msgstr "Սխալի գրությունը"
#: core/me/result_table.py:24 core/pe/result_table.py:21 core/prioritize.py:63 #: core\me\prioritize.py:23
#: core/se/result_table.py:21
msgid "Kind"
msgstr "Տեսակ"
#: core/me/result_table.py:19 core/pe/result_table.py:19 core/prioritize.py:72
#: core/se/result_table.py:19
msgid "Folder"
msgstr "Թղթապանակ"
#: core/me/result_table.py:18 core/pe/result_table.py:18 core/prioritize.py:88
#: core/se/result_table.py:18
msgid "Filename"
msgstr "Ֆայլի անունը"
#: core/prioritize.py:147
msgid "Size"
msgstr "Չափը"
#: core/me/result_table.py:25 core/pe/result_table.py:24
#: core/prioritize.py:153 core/se/result_table.py:22
msgid "Modification"
msgstr "Փոփոխությունը"
#: core/me/prioritize.py:18
msgid "Duration" msgid "Duration"
msgstr "Տևողությունը" msgstr "Տևողությունը"
#: core/me/prioritize.py:24 core/me/result_table.py:22 #: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate" msgid "Bitrate"
msgstr "Բիթրեյթը" msgstr "Բիթրեյթը"
#: core/me/prioritize.py:30 #: core\me\prioritize.py:37
msgid "Samplerate" msgid "Samplerate"
msgstr "Սիմպլրեյթը" msgstr "Սիմպլրեյթը"
#: core/me/result_table.py:20 #: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
#: core\se\result_table.py:19
msgid "Filename"
msgstr "Ֆայլի անունը"
#: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core\se\result_table.py:20
msgid "Folder"
msgstr "Թղթապանակ"
#: core\me\result_table.py:21
msgid "Size (MB)" msgid "Size (MB)"
msgstr "Չափը (ՄԲ)" msgstr "Չափը (ՄԲ)"
#: core/me/result_table.py:21 #: core\me\result_table.py:22
msgid "Time" msgid "Time"
msgstr "Ժամանակը" msgstr "Ժամանակը"
#: core/me/result_table.py:23 #: core\me\result_table.py:24
msgid "Sample Rate" msgid "Sample Rate"
msgstr "Սեմփլրեյթը" msgstr "Սեմփլրեյթը"
#: core/me/result_table.py:26 #: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core\se\result_table.py:22
msgid "Kind"
msgstr "Տեսակ"
#: core\me\result_table.py:26 core\pe\result_table.py:25
#: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification"
msgstr "Փոփոխությունը"
#: core\me\result_table.py:27
msgid "Title" msgid "Title"
msgstr "Անունը" msgstr "Անունը"
#: core/me/result_table.py:27 #: core\me\result_table.py:28
msgid "Artist" msgid "Artist"
msgstr "Կատարողը" msgstr "Կատարողը"
#: core/me/result_table.py:28 #: core\me\result_table.py:29
msgid "Album" msgid "Album"
msgstr "Ալբոմը" msgstr "Ալբոմը"
#: core/me/result_table.py:29 #: core\me\result_table.py:30
msgid "Genre" msgid "Genre"
msgstr "Ժանրը" msgstr "Ժանրը"
#: core/me/result_table.py:30 #: core\me\result_table.py:31
msgid "Year" msgid "Year"
msgstr "Տարին" msgstr "Տարին"
#: core/me/result_table.py:31 #: core\me\result_table.py:32
msgid "Track Number" msgid "Track Number"
msgstr "Շավիղի համարը" msgstr "Շավիղի համարը"
#: core/me/result_table.py:32 #: core\me\result_table.py:33
msgid "Comment" msgid "Comment"
msgstr "Մեկնաբանություն" msgstr "Մեկնաբանություն"
#: core/me/result_table.py:33 core/pe/result_table.py:25 #: core\me\result_table.py:34 core\pe\result_table.py:26
#: core/se/result_table.py:23 #: core\se\result_table.py:24
msgid "Match %" msgid "Match %"
msgstr "Համընկնում %-ին" msgstr "Համընկնում %-ին"
#: core/me/result_table.py:34 core/se/result_table.py:24 #: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used" msgid "Words Used"
msgstr "Բառ է օգտ." msgstr "Բառ է օգտ."
#: core/me/result_table.py:35 core/pe/result_table.py:26 #: core\me\result_table.py:36 core\pe\result_table.py:27
#: core/se/result_table.py:25 #: core\se\result_table.py:26
msgid "Dupe Count" msgid "Dupe Count"
msgstr "Խաբկանքի ք-ը" msgstr "Խաբկանքի ք-ը"
#: core/pe/prioritize.py:18 core/pe/result_table.py:22 #: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions" msgid "Dimensions"
msgstr "Չափերը" msgstr "Չափերը"
#: core/pe/result_table.py:20 core/se/result_table.py:20 #: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)" msgid "Size (KB)"
msgstr "Չափը (ԿԲ)" msgstr "Չափը (ԿԲ)"
#: core/pe/result_table.py:23 #: core\pe\result_table.py:24
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "" msgstr "EXIF Timestamp"
#: core\prioritize.py:156
msgid "Size"
msgstr "Չափը"

View File

@@ -1,50 +1,54 @@
# Translators: # Translators:
# Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2013-12-07 15:22+0000\n" "Language-Team: Armenian (https://www.transifex.com/voltaicideas/teams/116153/hy/)\n"
"Last-Translator: hsoft <hsoft@hardcoded.net>\n" "Language: hy\n"
"Language-Team: Armenian (http://www.transifex.com/projects/p/dupeguru/language/hy/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: hy\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: core/app.py:40 #: core\app.py:42
msgid "There are no marked duplicates. Nothing has been done." msgid "There are no marked duplicates. Nothing has been done."
msgstr "" msgstr "Նշված կրկնօրինակներ չկան: Ոչինչ չի արվել."
#: core/app.py:41 #: core\app.py:43
msgid "There are no selected duplicates. Nothing has been done." msgid "There are no selected duplicates. Nothing has been done."
msgstr "" msgstr "Ընտրված կրկնօրինակներ չկան: Ոչինչ չի արվել."
#: core/app.py:42 #: core\app.py:44
msgid "" msgid ""
"You're about to open many files at once. Depending on what those files are " "You're about to open many files at once. Depending on what those files are "
"opened with, doing so can create quite a mess. Continue?" "opened with, doing so can create quite a mess. Continue?"
msgstr "" msgstr ""
"Դուք պատրաստվում եք միանգամից շատ ֆայլեր բացել: Կախված այն բանից, թե ինչով "
"են բացվում այդ ֆայլերը, դա անելը կարող է բավականին խառնաշփոթ ստեղծել: "
"Շարունակել?"
#: core/app.py:65 #: core\app.py:71
msgid "Scanning for duplicates" msgid "Scanning for duplicates"
msgstr "Ստուգվում են կրկնօրինակները" msgstr "Ստուգվում են կրկնօրինակները"
#: core/app.py:66 #: core\app.py:72
msgid "Loading" msgid "Loading"
msgstr "Բացվում է" msgstr "Բացվում է"
#: core/app.py:67 #: core\app.py:73
msgid "Moving" msgid "Moving"
msgstr "Տեղափոխվում է" msgstr "Տեղափոխվում է"
#: core/app.py:68 #: core\app.py:74
msgid "Copying" msgid "Copying"
msgstr "Պատճենվում է" msgstr "Պատճենվում է"
#: core/app.py:69 #: core\app.py:75
msgid "Sending to Trash" msgid "Sending to Trash"
msgstr "Ուղարկվում է Աղբարկղ" msgstr "Ուղարկվում է Աղբարկղ"
#: core/app.py:279 #: core\app.py:308
msgid "" msgid ""
"A previous action is still hanging in there. You can't start a new one yet. " "A previous action is still hanging in there. You can't start a new one yet. "
"Wait a few seconds, then try again." "Wait a few seconds, then try again."
@@ -52,216 +56,202 @@ msgstr ""
"Նախորդ գործողությունը դեռևս ձեռադրում է այստեղ: Չեք կարող սկսել մեկ ուրիշը: " "Նախորդ գործողությունը դեռևս ձեռադրում է այստեղ: Չեք կարող սկսել մեկ ուրիշը: "
"Սպասեք մի քանի վայրկյան և կրկին փորձեք:" "Սպասեք մի քանի վայրկյան և կրկին փորձեք:"
#: core/app.py:289 #: core\app.py:318
msgid "No duplicates found." msgid "No duplicates found."
msgstr "Կրկնօրինակներ չկան:" msgstr "Կրկնօրինակներ չկան:"
#: core/app.py:304 #: core\app.py:333
msgid "All marked files were copied successfully." msgid "All marked files were copied successfully."
msgstr "Բոլոր նշված ֆայլերը հաջողությամբ պատճենվել են:" msgstr "Բոլոր նշված ֆայլերը հաջողությամբ պատճենվել են:"
#: core/app.py:305 #: core\app.py:334
msgid "All marked files were moved successfully." msgid "All marked files were moved successfully."
msgstr "Բոլոր նշված ֆայլերը հաջողությամբ տեղափոխվել են:" msgstr "Բոլոր նշված ֆայլերը հաջողությամբ տեղափոխվել են:"
#: core/app.py:306 #: core\app.py:335
msgid "All marked files were successfully sent to Trash." msgid "All marked files were successfully sent to Trash."
msgstr "Բոլոր նշված ֆայլերը հաջողությամբ Ջնջվել են:" msgstr "Բոլոր նշված ֆայլերը հաջողությամբ Ջնջվել են:"
#: core/app.py:368 #: core\app.py:343
msgid "Could not load file: {}"
msgstr "Հնարավոր չէ բեռնել ֆայլը: {}"
#: core\app.py:399
msgid "'{}' already is in the list." msgid "'{}' already is in the list."
msgstr "'{}'-ը արդեն առկա է ցանկում:" msgstr "'{}'-ը արդեն առկա է ցանկում:"
#: core/app.py:370 #: core\app.py:401
msgid "'{}' does not exist." msgid "'{}' does not exist."
msgstr "'{}'-ը գոյություն չունի:" msgstr "'{}'-ը գոյություն չունի:"
#: core/app.py:379 #: core\app.py:410
msgid "" msgid ""
"All selected %d matches are going to be ignored in all subsequent scans. " "All selected %d matches are going to be ignored in all subsequent scans. "
"Continue?" "Continue?"
msgstr "" msgstr ""
"Ընտրված %d համընկնումները կանտեսվեն հետագա բոլոր ստուգումներից: Շարունակե՞լ:" "Ընտրված %d համընկնումները կանտեսվեն հետագա բոլոր ստուգումներից: Շարունակե՞լ:"
#: core/app.py:450 #: core\app.py:486
msgid "copy" msgid "Select a directory to copy marked files to"
msgstr "պատճենել" msgstr "Ընտրեք գրացուցակ, որտեղ ցանկանում եք պատճենել նշված ֆայլերը"
#: core/app.py:450 #: core\app.py:487
msgid "move" msgid "Select a directory to move marked files to"
msgstr "տեղափոխել"
#: core/app.py:451
msgid "Select a directory to {} marked files to"
msgstr "Ընտրել թղթապանակ՝ {} նշված ֆայլերի համար"
#: core/app.py:490
msgid "Select a destination for your exported CSV"
msgstr "" msgstr ""
"Խնդրում ենք ընտրել գրացուցակ, որտեղ ցանկանում եք տեղափոխել նշված ֆայլերը"
#: core/app.py:518 #: core\app.py:527
msgid "Select a destination for your exported CSV"
msgstr "Ընտրեք նպատակակետ ձեր արտահանված CSV- ի համար"
#: core\app.py:534 core\app.py:801 core\app.py:811
msgid "Couldn't write to file: {}"
msgstr "Չէր կարող գրել է ֆայլը: {}"
#: core\app.py:559
msgid "You have no custom command set up. Set it up in your preferences." msgid "You have no custom command set up. Set it up in your preferences."
msgstr "Դուք չեք կատարել Հրամանի ընտրություն: Կատարեք այն կարգավորումներում:" msgstr "Դուք չեք կատարել Հրամանի ընտրություն: Կատարեք այն կարգավորումներում:"
#: core/app.py:672 core/app.py:685 #: core\app.py:727 core\app.py:740
msgid "You are about to remove %d files from results. Continue?" msgid "You are about to remove %d files from results. Continue?"
msgstr "Դուք պատրաստվում եք ջնջելու %d ֆայլեր: Շարունակե՞լ:" msgstr "Դուք պատրաստվում եք ջնջելու %d ֆայլեր: Շարունակե՞լ:"
#: core/app.py:719 #: core\app.py:774
msgid "{} duplicate groups were changed by the re-prioritization." msgid "{} duplicate groups were changed by the re-prioritization."
msgstr "" msgstr "{} կրկնօրինակ խմբերը փոխվել են առաջնահերթության կարգով:"
#: core/app.py:762 #: core\app.py:821
msgid "Collecting files to scan"
msgstr "Հավաքվում են ֆայլեր՝ ստուգելու համար"
#: core/app.py:751
msgid "The selected directories contain no scannable file." msgid "The selected directories contain no scannable file."
msgstr "Ընտրված թղթապանակները պարունակում են չստուգվող ֆայլ:" msgstr "Ընտրված թղթապանակները պարունակում են չստուգվող ֆայլ:"
#: core/app.py:810 #: core\app.py:835
msgid "Collecting files to scan"
msgstr "Հավաքվում են ֆայլեր՝ ստուգելու համար"
#: core\app.py:891
msgid "%s (%d discarded)" msgid "%s (%d discarded)"
msgstr "%s (%d անպիտան)" msgstr "%s (%d անպիտան)"
#: core/engine.py:222 core/engine.py:262 #: core\engine.py:244 core\engine.py:288
msgid "0 matches found" msgid "0 matches found"
msgstr "0 համընկնում է գտնվել" msgstr "0 համընկնում է գտնվել"
#: core/engine.py:240 core/engine.py:270 #: core\engine.py:262 core\engine.py:296
msgid "%d matches found" msgid "%d matches found"
msgstr "%d համընկնում է գտնվել" msgstr "%d համընկնում է գտնվել"
#: core/scanner.py:77 #: core\gui\deletion_options.py:73
msgid "Read size of %d/%d files"
msgstr "Կարդալ %d/%d ֆայլերի չափը"
#: core/gui/deletion_options.py:69
msgid "You are sending {} file(s) to the Trash." msgid "You are sending {} file(s) to the Trash."
msgstr "" msgstr "Դուք {} ֆայլ եք ուղարկում աղբարկղ:"
#: core/gui/ignore_list_dialog.py:24 #: core\gui\exclude_list_table.py:15
msgid "Regular Expressions"
msgstr "Կանոնավոր արտահայտություններ"
#: core\gui\ignore_list_dialog.py:25
msgid "Do you really want to remove all %d items from the ignore list?" msgid "Do you really want to remove all %d items from the ignore list?"
msgstr "Ցանկանու՞մ եք հեռացնել բոլոր %d ֆայլերը անտեսումների ցանկից:" msgstr "Ցանկանու՞մ եք հեռացնել բոլոր %d ֆայլերը անտեսումների ցանկից:"
#: core/prioritize.py:68 #: core\me\scanner.py:20 core\se\scanner.py:16
msgid "None" msgid "Filename"
msgstr "Ոչինչ" msgstr "Ֆայլի անունը"
#: core/prioritize.py:96 #: core\me\scanner.py:21
msgid "Ends with number" msgid "Filename - Fields"
msgstr "Ավարտվում է թվով" msgstr "Ֆայլի անվանումը - Դաշտեր"
#: core/prioritize.py:97 #: core\me\scanner.py:22
msgid "Doesn't end with number" msgid "Filename - Fields (No Order)"
msgstr "Չի ավարտվում է թվով" msgstr "Ֆայլի անուն - դաշտեր (պատվեր չկա)"
#: core/prioritize.py:98 #: core\me\scanner.py:23
msgid "Longest" msgid "Tags"
msgstr "" msgstr "Tags"
#: core/prioritize.py:99 #: core\me\scanner.py:24 core\pe\scanner.py:21 core\se\scanner.py:17
msgid "Shortest" msgid "Contents"
msgstr "" msgstr "Բովանդակություն"
#: core/prioritize.py:132 #: core\pe\matchblock.py:72
msgid "Highest"
msgstr "Ամենաբարձրը"
#: core/prioritize.py:132
msgid "Lowest"
msgstr "Ամենացածրը"
#: core/prioritize.py:159
msgid "Newest"
msgstr "Նորագույնը"
#: core/prioritize.py:159
msgid "Oldest"
msgstr "Ամենահինը"
#: core/results.py:129
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) նշված կրկնօրինակներ:"
#: core/results.py:136
msgid " filter: %s"
msgstr "ֆիլտր. %s"
#: core/scanner.py:101
msgid "Read metadata of %d/%d files"
msgstr "Կարդալ %d/%d ֆայլերի մետատվյալները"
#: core/pe/matchblock.py:61
msgid "Analyzed %d/%d pictures" msgid "Analyzed %d/%d pictures"
msgstr "Ստուգվում է %d/%d նկարները" msgstr "Ստուգվում է %d/%d նկարները"
#: core/pe/matchblock.py:156 #: core\pe\matchblock.py:181
msgid "Performed %d/%d chunk matches" msgid "Performed %d/%d chunk matches"
msgstr "Կատարվում է %d/%d տվյալի համընկնում" msgstr "Կատարվում է %d/%d տվյալի համընկնում"
#: core/pe/matchblock.py:161 #: core\pe\matchblock.py:191
msgid "Preparing for matching" msgid "Preparing for matching"
msgstr "Նախապատրաստեցվում է համընկնումը" msgstr "Նախապատրաստեցվում է համընկնումը"
#: core/pe/matchblock.py:206 #: core\pe\matchblock.py:244
msgid "Verified %d/%d matches" msgid "Verified %d/%d matches"
msgstr "Ստուգում է %d/%d համընկնումները" msgstr "Ստուգում է %d/%d համընկնումները"
#: core/pe/matchexif.py:18 #: core\pe\matchexif.py:19
msgid "Read EXIF of %d/%d pictures" msgid "Read EXIF of %d/%d pictures"
msgstr "Կարդալ EXIF-ը d/%d նկարներից" msgstr "Կարդալ EXIF-ը d/%d նկարներից"
#: core/app.py:312 #: core\pe\scanner.py:22
msgid "Could not load file: {}"
msgstr ""
#: core/app.py:496 core/app.py:742
msgid "Couldn't write to file: {}"
msgstr ""
#: core/me/scanner.py:19 core/se/scanner.py:15
msgid "Filename"
msgstr ""
#: core/me/scanner.py:20
msgid "Filename - Fields"
msgstr ""
#: core/me/scanner.py:21
msgid "Filename - Fields (No Order)"
msgstr ""
#: core/me/scanner.py:22
msgid "Tags"
msgstr ""
#: core/me/scanner.py:23 core/pe/scanner.py:20 core/se/scanner.py:16
msgid "Contents"
msgstr ""
#: core/pe/scanner.py:21
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "" msgstr "EXIF Timestamp"
#: core/scanner.py:139 #: core\prioritize.py:70
msgid "None"
msgstr "Ոչինչ"
#: core\prioritize.py:100
msgid "Ends with number"
msgstr "Ավարտվում է թվով"
#: core\prioritize.py:101
msgid "Doesn't end with number"
msgstr "Չի ավարտվում է թվով"
#: core\prioritize.py:102
msgid "Longest"
msgstr "Ամենաերկար"
#: core\prioritize.py:103
msgid "Shortest"
msgstr "Ամենակարճը"
#: core\prioritize.py:140
msgid "Highest"
msgstr "Ամենաբարձրը"
#: core\prioritize.py:140
msgid "Lowest"
msgstr "Ամենացածրը"
#: core\prioritize.py:169
msgid "Newest"
msgstr "Նորագույնը"
#: core\prioritize.py:169
msgid "Oldest"
msgstr "Ամենահինը"
#: core\results.py:142
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) նշված կրկնօրինակներ:"
#: core\results.py:149
msgid " filter: %s"
msgstr "ֆիլտր. %s"
#: core\scanner.py:85
msgid "Read size of %d/%d files"
msgstr "Կարդալ %d/%d ֆայլերի չափը"
#: core\scanner.py:109
msgid "Read metadata of %d/%d files"
msgstr "Կարդալ %d/%d ֆայլերի մետատվյալները"
#: core\scanner.py:147
msgid "Almost done! Fiddling with results..." msgid "Almost done! Fiddling with results..."
msgstr "" msgstr "Գրեթե արված է! Արդյունքների կազմակերպում..."
#: core/se/scanner.py:17 #: core\se\scanner.py:18
msgid "Folders" msgid "Folders"
msgstr "" msgstr "Թղթապանակներ"
#~ msgid "Sending files to the recycle bin"
#~ msgstr "Ֆայլերը ուղարկվում են Աղբարկղ"
#~ msgid "Grouped %d/%d matches"
#~ msgstr "Խմբավորվել է %d/%d համընկնում"
#~ msgid "Removing false matches"
#~ msgstr "Սխալ համընկնումների հեռացում"
#~ msgid "Processed %d/%d matches against the ignore list"
#~ msgstr "Ընթացքում է %d/%d համընկնումները ընդդեմ անտեսվող ցանկի"
#~ msgid "Doing group prioritization"
#~ msgstr "Խմբի առաջնայնացում"

View File

@@ -1,23 +1,33 @@
# Translators: # Translators:
# Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2013-12-07 15:22+0000\n" "Language-Team: Armenian (https://www.transifex.com/voltaicideas/teams/116153/hy/)\n"
"Last-Translator: hsoft <hsoft@hardcoded.net>\n" "Language: hy\n"
"Language-Team: Armenian (http://www.transifex.com/projects/p/dupeguru/language/hy/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: hy\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: qt/app.py:81 #: qt/app.py:81
msgid "Quit" msgid "Quit"
msgstr "Փակել" msgstr "Փակել"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Ընտրանքներ"
#: qt/app.py:83 qt/ignore_list_dialog.py:32 #: qt/app.py:83 qt/ignore_list_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Ignore List" msgid "Ignore List"
msgstr "" msgstr "անտեսել ցուցակ"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Մաքրել նկարի պահոցը"
#: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0 #: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Help" msgid "dupeGuru Help"
@@ -31,49 +41,62 @@ msgstr "dupeGuru-ի մասին"
msgid "Open Debug Log" msgid "Open Debug Log"
msgstr "Բացել Սխալների մատյանը" msgstr "Բացել Սխալների մատյանը"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr "Ցանկանու՞մ եք հեռացնել բոլոր պահված նկարները ստուգելուց:"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "Նկարի պահոցը մաքրվել է:"
#: qt/app.py:251 #: qt/app.py:251
msgid "{} file (*.{})" msgid "{} file (*.{})"
msgstr "" msgstr "{} ֆայլ (*.{})"
#: qt/deletion_options.py:30 cocoa/en.lproj/Localizable.strings:0 #: qt/deletion_options.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Deletion Options" msgid "Deletion Options"
msgstr "" msgstr "Ջնջումների Ընտրանքներ"
#: qt/deletion_options.py:35 cocoa/en.lproj/Localizable.strings:0 #: qt/deletion_options.py:35 cocoa/en.lproj/Localizable.strings:0
msgid "Link deleted files" msgid "Link deleted files"
msgstr "" msgstr "Կապել ջնջված ֆայլերը"
#: qt/deletion_options.py:37 cocoa/en.lproj/Localizable.strings:0 #: qt/deletion_options.py:37 cocoa/en.lproj/Localizable.strings:0
msgid "" msgid ""
"After having deleted a duplicate, place a link targeting the reference file " "After having deleted a duplicate, place a link targeting the reference file "
"to replace the deleted file." "to replace the deleted file."
msgstr "" msgstr ""
"րկնօրինակը ջնջելուց հետո տեղադրեք հղում, տեղադրել հղում նպատակային հղվող "
"ֆայլը փոխարինել ջնջված ֆայլը."
#: qt/deletion_options.py:44 #: qt/deletion_options.py:44
msgid "Hardlink" msgid "Hardlink"
msgstr "" msgstr "Hardlink"
#: qt/deletion_options.py:44 #: qt/deletion_options.py:44
msgid "Symlink" msgid "Symlink"
msgstr "" msgstr "Symlink"
#: qt/deletion_options.py:48 #: qt/deletion_options.py:48
msgid " (unsupported)" msgid " (unsupported)"
msgstr "" msgstr " (չաջակցվող)"
#: qt/deletion_options.py:49 cocoa/en.lproj/Localizable.strings:0 #: qt/deletion_options.py:49 cocoa/en.lproj/Localizable.strings:0
msgid "Directly delete files" msgid "Directly delete files"
msgstr "" msgstr "Ուղղակիորեն ջնջեք ֆայլերը"
#: qt/deletion_options.py:51 cocoa/en.lproj/Localizable.strings:0 #: qt/deletion_options.py:51 cocoa/en.lproj/Localizable.strings:0
msgid "" msgid ""
"Instead of sending files to trash, delete them directly. This option is " "Instead of sending files to trash, delete them directly. This option is "
"usually used as a workaround when the normal deletion method doesn't work." "usually used as a workaround when the normal deletion method doesn't work."
msgstr "" msgstr ""
"Ֆայլերը աղբարկղ ուղարկելու փոխարեն, դրանք ուղղակիորեն ջնջեք: Այս տարբերակը "
"սովորաբար օգտագործվում է որպես լուծում, երբ ջնջման սովորական մեթոդը չի "
"գործում:"
#: qt/deletion_options.py:59 cocoa/en.lproj/Localizable.strings:0 #: qt/deletion_options.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Proceed" msgid "Proceed"
msgstr "" msgstr "Շարունակել"
#: qt/deletion_options.py:60 cocoa/en.lproj/Localizable.strings:0 #: qt/deletion_options.py:60 cocoa/en.lproj/Localizable.strings:0
msgid "Cancel" msgid "Cancel"
@@ -122,6 +145,30 @@ msgstr "Օգնություն"
msgid "Load Recent Results" msgid "Load Recent Results"
msgstr "Բացել Վերջին արդյունքները" msgstr "Բացել Վերջին արդյունքները"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0
msgid "Application Mode:"
msgstr "Դիմումի ռեժիմ"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Music"
msgstr "Երաժշտություն"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Picture"
msgstr "Նկար"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Standard"
msgstr "Ստանդարտ"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0
msgid "Scan Type:"
msgstr "Ստուգելու տեսակը."
#: qt/directories_dialog.py:135
msgid "More Options"
msgstr "Լրացուցիչ ընտրանքներ"
#: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0 #: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0
msgid "Select folders to scan and press \"Scan\"." msgid "Select folders to scan and press \"Scan\"."
msgstr "Ընտրեք ստուգելու թղթապանակները և սեղմեք \"Ստուգել\":" msgstr "Ընտրեք ստուգելու թղթապանակները և սեղմեք \"Ստուգել\":"
@@ -184,20 +231,89 @@ msgstr "Նորմալ"
#: qt/ignore_list_dialog.py:45 cocoa/en.lproj/Localizable.strings:0 #: qt/ignore_list_dialog.py:45 cocoa/en.lproj/Localizable.strings:0
msgid "Remove Selected" msgid "Remove Selected"
msgstr "" msgstr "Հեռացնել ընտրվածը"
#: qt/ignore_list_dialog.py:46 cocoa/en.lproj/Localizable.strings:0 #: qt/ignore_list_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Clear" msgid "Clear"
msgstr "" msgstr "Մաքրել"
#: qt/ignore_list_dialog.py:47 qt/problem_dialog.py:61 #: qt/ignore_list_dialog.py:47 qt/problem_dialog.py:61
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Close" msgid "Close"
msgstr "Փակել" msgstr "Փակել"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0 #: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
msgid "Scan Type:" #: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
msgstr "Ստուգելու տեսակը." #: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Մանրամասն"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Ստուգվող կցապիտակները."
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Շավիղը"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Կատարողը"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Ալբոմը"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Վերնագիրը"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Ժանրը"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Տարին"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "Բառի չափը"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Ըստ նման բառերի համընկնման"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Կարող է խառը տեսակի"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Օգտ. կանոնավոր սահմանումներ ֆիլտրելիս"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Հեռացնել"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Անտեսել կրկնօրինակները հարդ նույն ֆայլը"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Սխալի եղանակը (պահանջում է վերագործարկում)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Նկարների համընկնում տարբեր չափերով"
#: qt/preferences_dialog.py:43 #: qt/preferences_dialog.py:43
msgid "Filter Hardness:" msgid "Filter Hardness:"
@@ -274,12 +390,6 @@ msgstr ""
msgid "Reveal Selected" msgid "Reveal Selected"
msgstr "Ցուցադրել ընտրվածը" msgstr "Ցուցադրել ընտրվածը"
#: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
#: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Մանրամասն"
#: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167 #: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167
#: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0
msgid "Actions" msgid "Actions"
@@ -323,7 +433,7 @@ msgstr "Ավելացնել ընտրվածը Անտեսումների ցանկ"
#: qt/result_window.py:75 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:75 cocoa/en.lproj/Localizable.strings:0
msgid "Make Selected into Reference" msgid "Make Selected into Reference"
msgstr "" msgstr "Ընտրված նյութը դարձրեք տեղեկատու նյութ:"
#: qt/result_window.py:77 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:77 cocoa/en.lproj/Localizable.strings:0
msgid "Open Selected with Default Application" msgid "Open Selected with Default Application"
@@ -359,7 +469,7 @@ msgstr "Արտածել HTML-ով"
#: qt/result_window.py:88 #: qt/result_window.py:88
msgid "Export To CSV" msgid "Export To CSV"
msgstr "" msgstr "Արտահանել CSV"
#: qt/result_window.py:89 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:89 cocoa/en.lproj/Localizable.strings:0
msgid "Save Results..." msgid "Save Results..."
@@ -391,91 +501,12 @@ msgstr "Միայն կրկ."
#: qt/result_window.py:194 #: qt/result_window.py:194
msgid "Delta Values" msgid "Delta Values"
msgstr "" msgstr "Դելտա արժեքներ"
#: qt/result_window.py:310 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:310 cocoa/en.lproj/Localizable.strings:0
msgid "Select a file to save your results to" msgid "Select a file to save your results to"
msgstr "Ընտրեք ֆայլը՝ պահպանելու արդյունքները՝" msgstr "Ընտրեք ֆայլը՝ պահպանելու արդյունքները՝"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Ստուգվող կցապիտակները."
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Շավիղը"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Կատարողը"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Ալբոմը"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Վերնագիրը"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Ժանրը"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Տարին"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "Բառի չափը"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Ըստ նման բառերի համընկնման"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Կարող է խառը տեսակի"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Օգտ. կանոնավոր սահմանումներ ֆիլտրելիս"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Հեռացնել"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Անտեսել կրկնօրինակները հարդ նույն ֆայլը"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Սխալի եղանակը (պահանջում է վերագործարկում)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Նկարների համընկնում տարբեր չափերով"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Մաքրել նկարի պահոցը"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr "Ցանկանու՞մ եք հեռացնել բոլոր պահված նկարները ստուգելուց:"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "Նկարի պահոցը մաքրվել է:"
#: qt/se/preferences_dialog.py:41 #: qt/se/preferences_dialog.py:41
msgid "Ignore files smaller than" msgid "Ignore files smaller than"
msgstr "Անտեսել ֆայլերը, որոնք փոքր են՝" msgstr "Անտեսել ֆայլերը, որոնք փոքր են՝"
@@ -486,7 +517,7 @@ msgstr "ԿԲ"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "%@ Results" msgid "%@ Results"
msgstr "" msgstr "%@ Արդյունքներ"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Action" msgid "Action"
@@ -550,7 +581,7 @@ msgstr "Թղթապանակներ"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru" msgid "dupeGuru"
msgstr "" msgstr "dupeGuru"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Preferences" msgid "dupeGuru Preferences"
@@ -570,7 +601,7 @@ msgstr "Խմբագրել"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Export Results to CSV" msgid "Export Results to CSV"
msgstr "" msgstr "Արտահանել արդյունքները CSV ձևաչափով:"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Export Results to XHTML" msgid "Export Results to XHTML"
@@ -590,7 +621,7 @@ msgstr "Ֆիլտրի կարգը."
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Filter Results..." msgid "Filter Results..."
msgstr "" msgstr "Զտել արդյունքները:"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Folder Selection Window" msgid "Folder Selection Window"
@@ -598,7 +629,7 @@ msgstr "Թղթապանակը ընտրելու պատուհանը"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Font Size:" msgid "Font Size:"
msgstr "" msgstr "Տառատեսակի չափը ՝"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Hide dupeGuru" msgid "Hide dupeGuru"
@@ -632,11 +663,6 @@ msgstr "Լր. արդյունքներ"
msgid "Ok" msgid "Ok"
msgstr "ԼԱՎ" msgstr "ԼԱՎ"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Ընտրանքներ"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Paste" msgid "Paste"
msgstr "Տեղադրել" msgstr "Տեղադրել"
@@ -647,7 +673,7 @@ msgstr "Կարգավորումներ..."
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Quick Look" msgid "Quick Look"
msgstr "" msgstr "Quick Look"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Quit dupeGuru" msgid "Quit dupeGuru"
@@ -659,11 +685,11 @@ msgstr "Ետարկել ծրագրայինի"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Reset To Defaults" msgid "Reset To Defaults"
msgstr "" msgstr "Զրոյացնել լռելյայն"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Reveal" msgid "Reveal"
msgstr "" msgstr "Բացահայտել"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Reveal Selected in Finder" msgid "Reveal Selected in Finder"
@@ -671,7 +697,7 @@ msgstr "Ցուցադրել ընտրվածը Գտնվածում"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Select All" msgid "Select All"
msgstr "" msgstr "Ընտրել բոլորը"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Send Marked to Trash..." msgid "Send Marked to Trash..."
@@ -679,7 +705,7 @@ msgstr "Ուղարկել նշվածները Աղբարկղ..."
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Services" msgid "Services"
msgstr "" msgstr "Առայություններ"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Show All" msgid "Show All"
@@ -701,112 +727,198 @@ msgstr "Պատուհանը"
msgid "Zoom" msgid "Zoom"
msgstr "Չափը" msgstr "Չափը"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0 #: qt\app.py:158
msgid "Application Mode:" msgid "Exclusion Filters"
msgstr "Բացառման ֆիլտրեր"
#: qt\directories_dialog.py:91
msgid "Scan Results"
msgstr "Սկան արդյունքներ"
#: qt\directories_dialog.py:95
msgid "Load Directories..."
msgstr "բեռնվածքի տեղեկագրքեր..."
#: qt\directories_dialog.py:96
msgid "Save Directories..."
msgstr "Պահել գրացուցակները..."
#: qt\directories_dialog.py:337
msgid "Select a directories file to load"
msgstr "Ընտրեք գրացուցակների ֆայլ `բեռնելու համար"
#: qt\directories_dialog.py:338
msgid "dupeGuru Results (*.dupegurudirs)"
msgstr "dupeGuru տեղեկատուներ (*.dupegurudirs)"
#: qt\directories_dialog.py:347
msgid "Select a file to save your directories to"
msgstr "Ընտրեք ֆայլ, ձեր գրացուցակները պահելու համար"
#: qt\directories_dialog.py:348
msgid "dupeGuru Directories (*.dupegurudirs)"
msgstr "dupeGuru տեղեկատուներ (*.dupegurudirs)"
#: qt\exclude_list_dialog.py:44
msgid "Add"
msgstr "Ավելացնել"
#: qt\exclude_list_dialog.py:46
msgid "Restore defaults"
msgstr "Վերականգնել Նախնականը"
#: qt\exclude_list_dialog.py:47
msgid "Test string"
msgstr "Թեստային լարային"
#: qt\exclude_list_dialog.py:83
msgid "Type a python regular expression here..."
msgstr "" msgstr ""
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\exclude_list_dialog.py:85
msgid "Music" msgid "Type a file system path or filename here..."
msgstr "" msgstr ""
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\exclude_list_dialog.py:152
msgid "Picture" msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happen to match one of the regular expressions.<br>For each file collected two tests are perfomed on each of them to determine whether or not to filter them out:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with no path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the test string feature by pasting a fake path in it:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr "" msgstr ""
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\exclude_list_table.py:36
msgid "Standard" msgid "Compilation error: "
msgstr "" msgstr ""
#: qt/directories_dialog.py:135 #: qt\pe\image_viewer.py:56
msgid "More Options" msgid "Increase zoom"
msgstr "" msgstr ""
#~ msgid "Removing dead tracks from your iTunes Library" #: qt\pe\image_viewer.py:66
#~ msgstr "Հեռացվում են վնասված շավիղները iTunes-ի Շտեմարանից" msgid "Decrease zoom"
msgstr ""
#~ msgid "Scanning the iTunes Library" #: qt\pe\image_viewer.py:71
#~ msgstr "Ստուգվում է iTunes-ի Շտեմարանը" msgid "Ctrl+/"
msgstr ""
#~ msgid "Sending dupes to the Trash" #: qt\pe\image_viewer.py:76
#~ msgstr "Խաբկանքները տեղափոխվում են Աղբարկղ" msgid "Normal size"
msgstr ""
#~ msgid "Talking to iTunes. Don't touch it!" #: qt\pe\image_viewer.py:81
#~ msgstr "" msgid "Ctrl+*"
msgstr ""
#~ msgid "" #: qt\pe\image_viewer.py:86
#~ "Your iTunes Library contains %d dead tracks ready to be removed. Continue?" msgid "Best fit"
#~ msgstr "" msgstr ""
#~ "Ձեր iTunes- Շտեմարանը պարունակում է %d մահացած շավիղներ, որոնք կարող են "
#~ "ջնջվել: Շարունակե՞լ:"
#~ msgid "You have no dead tracks in your iTunes Library" #: qt\pe\preferences_dialog.py:49
#~ msgstr "Դուք չունեք շավիղներ Ձեր iTunes Շտեմարանում" msgid "Picture cache mode:"
msgstr "Նկարի քեշի ռեժիմ:"
#~ msgid "The iTunes application couldn't be found." #: qt\pe\preferences_dialog.py:56
#~ msgstr "" msgid "Override theme icons in viewer toolbar"
msgstr ""
#~ msgid "Talking to iPhoto. Don't touch it!" #: qt\pe\preferences_dialog.py:58
#~ msgstr "Զրույց iPhoto-ի հետ: Մի կպեք! " msgid ""
"Use our own internal icons instead of those provided by the theme engine"
msgstr ""
#~ msgid "Talking to Aperture. Don't touch it!" #: qt\pe\preferences_dialog.py:66
#~ msgstr "" msgid "Show scrollbars in image viewers"
msgstr ""
#~ msgid "Deleted Aperture photos were sent to a project called \"dupeGuru Trash\"." #: qt\pe\preferences_dialog.py:68
#~ msgstr "" msgid ""
"When the image displayed doesn't fit the viewport, show scrollbars to span "
"the view around"
msgstr ""
#~ msgid "The iPhoto application couldn't be found." #: qt\preferences_dialog.py:156
#~ msgstr "iPhoto ծրագիրը չի գտնվել:" msgid "Use default position for tab bar (requires restart)"
msgstr ""
#~ msgid "Preferences" #: qt\preferences_dialog.py:158
#~ msgstr "Կարգավորումներ" msgid ""
"Place the tab bar below the main menu instead of next to it\n"
"On MacOS, the tab bar will fill up the window's width instead."
msgstr ""
#~ msgid "Check for Update" #: qt\preferences_dialog.py:172
#~ msgstr "Ստուգել թարմացումները" msgid "Use bold font for references"
msgstr ""
#~ msgid "Filename" #: qt\preferences_dialog.py:176
#~ msgstr "Ֆայլի անունը" msgid "Reference foreground color:"
msgstr ""
#~ msgid "Filename - Fields" #: qt\preferences_dialog.py:179
#~ msgstr "Ֆայլի անունը - Դաշտերը" msgid "Reference background color:"
msgstr ""
#~ msgid "Filename - Fields (No Order)" #: qt\preferences_dialog.py:182 qt\preferences_dialog.py:216
#~ msgstr "Ֆայլի անունը - Դաշտերը (անկարգ)" msgid "Delta foreground color:"
msgstr ""
#~ msgid "Tags" #: qt\preferences_dialog.py:195
#~ msgstr "Կցապիտակներ" msgid "Show the title bar and can be docked"
msgstr ""
#~ msgid "Contents" #: qt\preferences_dialog.py:197
#~ msgstr "Բովանդակությունը" msgid ""
"While the title bar is hidden, use the modifier key to drag the floating "
"window around"
msgstr ""
#~ msgid "Audio Contents" #: qt\preferences_dialog.py:199
#~ msgstr "Ձայնային բովանդակությունը" msgid "The title bar can only be disabled while the window is docked"
msgstr ""
#~ msgid "EXIF Timestamp" #: qt\preferences_dialog.py:202
#~ msgstr "EXIF Timestamp" msgid "Vertical title bar"
msgstr ""
#~ msgid "Folders" #: qt\preferences_dialog.py:204
#~ msgstr "Թղթապանակներ" msgid ""
"Change the title bar from horizontal on top, to vertical on the left side"
msgstr ""
#~ msgid "Add Aperture Library" #: qt\tabbed_window.py:44
#~ msgstr "" msgid "Show tab bar"
msgstr ""
#~ msgid "Add iPhoto Library" #: qt\exclude_list_dialog.py:152
#~ msgstr "Ավելացնել iPhoto-ի Շտեմարանին" msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happens to match one of the selected regular expressions.<br>For each file collected, two tests are performed to determine whether or not to completely ignore it:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with at least one path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the \"test string\" button after pasting a fake path in the test field:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path or filename tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
#~ msgid "Add iTunes Library" #: qt\app.py:256
#~ msgstr "Ավելացնել iTunes թղթապանակ" msgid "Results"
msgstr "Արդյունքներ"
#~ msgid "Audio Content" #: qt\preferences_dialog.py:150
#~ msgstr "Ձայնային բովանդակությունը" msgid "General Interface"
msgstr "Ընդհանուր միջերես"
#~ msgid "Content" #: qt\preferences_dialog.py:176
#~ msgstr "Բովանդակությունը" msgid "Result Table"
msgstr "Արդյունքների աղյուսակ"
#~ msgid "dupeGuru ME Preferences" #: qt\preferences_dialog.py:205
#~ msgstr "dupeGuru-ի ME կարգավորումները" msgid "Details Window"
msgstr "Մանրամասներ Պատուհան"
#~ msgid "dupeGuru PE Preferences" #: qt\preferences_dialog.py:285
#~ msgstr "dupeGuru PE կարգավորումները" msgid "General"
msgstr "Գեներալ"
#~ msgid "Remove Dead Tracks in iTunes" #: qt\preferences_dialog.py:286
#~ msgstr "Հեռացնել մահացած շավիղները iTunes-ից" msgid "Display"
msgstr "Ցուցադրման"

View File

@@ -1,122 +1,122 @@
# Translators: # Translators:
# Andrew Senetar <arsenetar@gmail.com>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Andrew Senetar <arsenetar@gmail.com>, 2021\n"
"PO-Revision-Date: 2013-11-20 11:53+0000\n" "Language-Team: Italian (https://www.transifex.com/voltaicideas/teams/116153/it/)\n"
"Last-Translator: hsoft <hsoft@hardcoded.net>\n" "Language: it\n"
"Language-Team: Italian (http://www.transifex.com/projects/p/dupeguru/language/it/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: core/gui/ignore_list_table.py:18 core/gui/ignore_list_table.py:19 #: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core/gui/problem_table.py:17 #: core\gui\problem_table.py:18
msgid "File Path" msgid "File Path"
msgstr "Percorso del file" msgstr "Percorso del file"
#: core/gui/problem_table.py:18 #: core\gui\problem_table.py:19
msgid "Error Message" msgid "Error Message"
msgstr "Messaggio di errore" msgstr "Messaggio di errore"
#: core/me/result_table.py:24 core/pe/result_table.py:21 core/prioritize.py:63 #: core\me\prioritize.py:23
#: core/se/result_table.py:21
msgid "Kind"
msgstr "Tipo"
#: core/me/result_table.py:19 core/pe/result_table.py:19 core/prioritize.py:72
#: core/se/result_table.py:19
msgid "Folder"
msgstr "Cartella"
#: core/me/result_table.py:18 core/pe/result_table.py:18 core/prioritize.py:88
#: core/se/result_table.py:18
msgid "Filename"
msgstr "Nome del file"
#: core/prioritize.py:147
msgid "Size"
msgstr "Dimensione"
#: core/me/result_table.py:25 core/pe/result_table.py:24
#: core/prioritize.py:153 core/se/result_table.py:22
msgid "Modification"
msgstr "Modificato"
#: core/me/prioritize.py:18
msgid "Duration" msgid "Duration"
msgstr "Durata" msgstr "Durata"
#: core/me/prioritize.py:24 core/me/result_table.py:22 #: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate" msgid "Bitrate"
msgstr "Bitrate" msgstr "Bitrate"
#: core/me/prioritize.py:30 #: core\me\prioritize.py:37
msgid "Samplerate" msgid "Samplerate"
msgstr "Campionamento" msgstr "Campionamento"
#: core/me/result_table.py:20 #: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
#: core\se\result_table.py:19
msgid "Filename"
msgstr "Nome del file"
#: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core\se\result_table.py:20
msgid "Folder"
msgstr "Cartella"
#: core\me\result_table.py:21
msgid "Size (MB)" msgid "Size (MB)"
msgstr "Dimensione (MB)" msgstr "Dimensione (MB)"
#: core/me/result_table.py:21 #: core\me\result_table.py:22
msgid "Time" msgid "Time"
msgstr "Tempo" msgstr "Tempo"
#: core/me/result_table.py:23 #: core\me\result_table.py:24
msgid "Sample Rate" msgid "Sample Rate"
msgstr "Campionamento" msgstr "Campionamento"
#: core/me/result_table.py:26 #: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core\se\result_table.py:22
msgid "Kind"
msgstr "Tipo"
#: core\me\result_table.py:26 core\pe\result_table.py:25
#: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification"
msgstr "Modificato"
#: core\me\result_table.py:27
msgid "Title" msgid "Title"
msgstr "Titolo" msgstr "Titolo"
#: core/me/result_table.py:27 #: core\me\result_table.py:28
msgid "Artist" msgid "Artist"
msgstr "Artista" msgstr "Artista"
#: core/me/result_table.py:28 #: core\me\result_table.py:29
msgid "Album" msgid "Album"
msgstr "Album" msgstr "Album"
#: core/me/result_table.py:29 #: core\me\result_table.py:30
msgid "Genre" msgid "Genre"
msgstr "Genere" msgstr "Genere"
#: core/me/result_table.py:30 #: core\me\result_table.py:31
msgid "Year" msgid "Year"
msgstr "Anno" msgstr "Anno"
#: core/me/result_table.py:31 #: core\me\result_table.py:32
msgid "Track Number" msgid "Track Number"
msgstr "Numero traccia" msgstr "Numero traccia"
#: core/me/result_table.py:32 #: core\me\result_table.py:33
msgid "Comment" msgid "Comment"
msgstr "Commento" msgstr "Commento"
#: core/me/result_table.py:33 core/pe/result_table.py:25 #: core\me\result_table.py:34 core\pe\result_table.py:26
#: core/se/result_table.py:23 #: core\se\result_table.py:24
msgid "Match %" msgid "Match %"
msgstr "Somiglianza %" msgstr "Somiglianza %"
#: core/me/result_table.py:34 core/se/result_table.py:24 #: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used" msgid "Words Used"
msgstr "Parole usate" msgstr "Parole usate"
#: core/me/result_table.py:35 core/pe/result_table.py:26 #: core\me\result_table.py:36 core\pe\result_table.py:27
#: core/se/result_table.py:25 #: core\se\result_table.py:26
msgid "Dupe Count" msgid "Dupe Count"
msgstr "Conteggio duplicati" msgstr "Conteggio duplicati"
#: core/pe/prioritize.py:18 core/pe/result_table.py:22 #: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions" msgid "Dimensions"
msgstr "Dimensioni" msgstr "Dimensioni"
#: core/pe/result_table.py:20 core/se/result_table.py:20 #: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)" msgid "Size (KB)"
msgstr "Dimensione (KB)" msgstr "Dimensione (KB)"
#: core/pe/result_table.py:23 #: core\pe\result_table.py:24
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "Data EXIF" msgstr "Data EXIF"
#: core\prioritize.py:156
msgid "Size"
msgstr "Dimensione"

View File

@@ -1,51 +1,54 @@
# Translators: # Translators:
# Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2013-12-07 15:22+0000\n" "Language-Team: Italian (https://www.transifex.com/voltaicideas/teams/116153/it/)\n"
"Last-Translator: auanasgheps\n" "Language: it\n"
"Language-Team: Italian (http://www.transifex.com/projects/p/dupeguru/language/it/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: core/app.py:40 #: core\app.py:42
msgid "There are no marked duplicates. Nothing has been done." msgid "There are no marked duplicates. Nothing has been done."
msgstr "Non ci sono duplicati marcati. Nessuna operazione è stata completata." msgstr "Non ci sono duplicati marcati. Nessuna operazione è stata completata."
#: core/app.py:41 #: core\app.py:43
msgid "There are no selected duplicates. Nothing has been done." msgid "There are no selected duplicates. Nothing has been done."
msgstr "Non ci sono duplicati selezionati. Nessuna operazione è stata completata." msgstr ""
"Non ci sono duplicati selezionati. Nessuna operazione è stata completata."
#: core/app.py:42 #: core\app.py:44
msgid "" msgid ""
"You're about to open many files at once. Depending on what those files are " "You're about to open many files at once. Depending on what those files are "
"opened with, doing so can create quite a mess. Continue?" "opened with, doing so can create quite a mess. Continue?"
msgstr "Stai per aprire molti file contemporaneamente. A seconda di quale programma " msgstr ""
"Stai per aprire molti file contemporaneamente. A seconda di quale programma "
"li aprirà, potrebbe crearsi un bel casino. Vuoi continuare?" "li aprirà, potrebbe crearsi un bel casino. Vuoi continuare?"
#: core/app.py:65 #: core\app.py:71
msgid "Scanning for duplicates" msgid "Scanning for duplicates"
msgstr "Scansione per i duplicati" msgstr "Scansione per i duplicati"
#: core/app.py:66 #: core\app.py:72
msgid "Loading" msgid "Loading"
msgstr "Caricamento" msgstr "Caricamento"
#: core/app.py:67 #: core\app.py:73
msgid "Moving" msgid "Moving"
msgstr "Spostamento" msgstr "Spostamento"
#: core/app.py:68 #: core\app.py:74
msgid "Copying" msgid "Copying"
msgstr "Copia in corso" msgstr "Copia in corso"
#: core/app.py:69 #: core\app.py:75
msgid "Sending to Trash" msgid "Sending to Trash"
msgstr "Spostamento nel cestino" msgstr "Spostamento nel cestino"
#: core/app.py:279 #: core\app.py:308
msgid "" msgid ""
"A previous action is still hanging in there. You can't start a new one yet. " "A previous action is still hanging in there. You can't start a new one yet. "
"Wait a few seconds, then try again." "Wait a few seconds, then try again."
@@ -53,31 +56,35 @@ msgstr ""
"Un'azione precedente è ancora in corso. Non puoi cominciarne una nuova. " "Un'azione precedente è ancora in corso. Non puoi cominciarne una nuova. "
"Aspetta qualche secondo e quindi riprova." "Aspetta qualche secondo e quindi riprova."
#: core/app.py:289 #: core\app.py:318
msgid "No duplicates found." msgid "No duplicates found."
msgstr "Non sono stati trovati dei duplicati." msgstr "Non sono stati trovati dei duplicati."
#: core/app.py:304 #: core\app.py:333
msgid "All marked files were copied successfully." msgid "All marked files were copied successfully."
msgstr "Tutti i file marcati sono stati copiati correttamente." msgstr "Tutti i file marcati sono stati copiati correttamente."
#: core/app.py:305 #: core\app.py:334
msgid "All marked files were moved successfully." msgid "All marked files were moved successfully."
msgstr "Tutti i file marcati sono stati spostati correttamente." msgstr "Tutti i file marcati sono stati spostati correttamente."
#: core/app.py:306 #: core\app.py:335
msgid "All marked files were successfully sent to Trash." msgid "All marked files were successfully sent to Trash."
msgstr "Tutti i file marcati sono stati spostati nel cestino." msgstr "Tutti i file marcati sono stati spostati nel cestino."
#: core/app.py:368 #: core\app.py:343
msgid "Could not load file: {}"
msgstr "Impossibile caricare il file: {}"
#: core\app.py:399
msgid "'{}' already is in the list." msgid "'{}' already is in the list."
msgstr "'{}' è già nella lista." msgstr "'{}' è già nella lista."
#: core/app.py:370 #: core\app.py:401
msgid "'{}' does not exist." msgid "'{}' does not exist."
msgstr "'{}' non esiste." msgstr "'{}' non esiste."
#: core/app.py:379 #: core\app.py:410
msgid "" msgid ""
"All selected %d matches are going to be ignored in all subsequent scans. " "All selected %d matches are going to be ignored in all subsequent scans. "
"Continue?" "Continue?"
@@ -85,190 +92,171 @@ msgstr ""
"Tutti i %d elementi che coincidono verranno ignorati in tutte le scansioni " "Tutti i %d elementi che coincidono verranno ignorati in tutte le scansioni "
"successive. Continuare?" "successive. Continuare?"
#: core/app.py:450 #: core\app.py:486
msgid "copy" msgid "Select a directory to copy marked files to"
msgstr "copiare" msgstr "Seleziona una directory in cui desideri copiare i file contrassegnati"
#: core/app.py:450 #: core\app.py:487
msgid "move" msgid "Select a directory to move marked files to"
msgstr "spostare" msgstr ""
"Seleziona una directory in cui desideri spostare i file contrassegnati"
#: core/app.py:451 #: core\app.py:527
msgid "Select a directory to {} marked files to"
msgstr "Seleziona una cartella per {} in essa i file marcati"
#: core/app.py:490
msgid "Select a destination for your exported CSV" msgid "Select a destination for your exported CSV"
msgstr "Seleziona una destinazione per il file CSV" msgstr "Seleziona una destinazione per il file CSV"
#: core/app.py:518 #: core\app.py:534 core\app.py:801 core\app.py:811
msgid "Couldn't write to file: {}"
msgstr "Impossibile modificare il file: {}"
#: core\app.py:559
msgid "You have no custom command set up. Set it up in your preferences." msgid "You have no custom command set up. Set it up in your preferences."
msgstr "" msgstr ""
"Non hai impostato nessun comando personalizzato. Impostalo nelle tue " "Non hai impostato nessun comando personalizzato. Impostalo nelle tue "
"preferenze." "preferenze."
#: core/app.py:672 core/app.py:685 #: core\app.py:727 core\app.py:740
msgid "You are about to remove %d files from results. Continue?" msgid "You are about to remove %d files from results. Continue?"
msgstr "Stai per rimuovere %d file dai risultati. Continuare?" msgstr "Stai per rimuovere %d file dai risultati. Continuare?"
#: core/app.py:719 #: core\app.py:774
msgid "{} duplicate groups were changed by the re-prioritization." msgid "{} duplicate groups were changed by the re-prioritization."
msgstr "{} gruppi duplicati sono stati cambiati dalla nuova priorirità" msgstr "{} gruppi duplicati sono stati cambiati dalla nuova priorirità"
#: core/app.py:762 #: core\app.py:821
msgid "Collecting files to scan"
msgstr "Raccolta file da scansionare"
#: core/app.py:751
msgid "The selected directories contain no scannable file." msgid "The selected directories contain no scannable file."
msgstr "Le cartelle selezionate non contengono file da scansionare." msgstr "Le cartelle selezionate non contengono file da scansionare."
#: core/app.py:810 #: core\app.py:835
msgid "Collecting files to scan"
msgstr "Raccolta file da scansionare"
#: core\app.py:891
msgid "%s (%d discarded)" msgid "%s (%d discarded)"
msgstr "%s (%d scartati)" msgstr "%s (%d scartati)"
#: core/engine.py:222 core/engine.py:262 #: core\engine.py:244 core\engine.py:288
msgid "0 matches found" msgid "0 matches found"
msgstr "Nessun duplicato trovato" msgstr "Nessun duplicato trovato"
#: core/engine.py:240 core/engine.py:270 #: core\engine.py:262 core\engine.py:296
msgid "%d matches found" msgid "%d matches found"
msgstr "Trovato/i %d duplicato/i" msgstr "Trovato/i %d duplicato/i"
#: core/scanner.py:77 #: core\gui\deletion_options.py:73
msgid "Read size of %d/%d files"
msgstr "Lettura dimensione di %d/%d file"
#: core/gui/deletion_options.py:69
msgid "You are sending {} file(s) to the Trash." msgid "You are sending {} file(s) to the Trash."
msgstr "Stai spostando {} file al Cestino." msgstr "Stai spostando {} file al Cestino."
#: core/gui/ignore_list_dialog.py:24 #: core\gui\exclude_list_table.py:15
msgid "Regular Expressions"
msgstr "Espressioni regolari"
#: core\gui\ignore_list_dialog.py:25
msgid "Do you really want to remove all %d items from the ignore list?" msgid "Do you really want to remove all %d items from the ignore list?"
msgstr "" msgstr ""
"Vuoi veramente rimuovere tutti i %d elementi dalla lista dei file da " "Vuoi veramente rimuovere tutti i %d elementi dalla lista dei file da "
"ignorare?" "ignorare?"
#: core/prioritize.py:68 #: core\me\scanner.py:20 core\se\scanner.py:16
msgid "None"
msgstr "Nessuno"
#: core/prioritize.py:96
msgid "Ends with number"
msgstr "Termina con un numero"
#: core/prioritize.py:97
msgid "Doesn't end with number"
msgstr "Non termina con un numero"
#: core/prioritize.py:98
msgid "Longest"
msgstr "Più lungo"
#: core/prioritize.py:99
msgid "Shortest"
msgstr "Più corto"
#: core/prioritize.py:132
msgid "Highest"
msgstr "Il più alto"
#: core/prioritize.py:132
msgid "Lowest"
msgstr "Il più basso"
#: core/prioritize.py:159
msgid "Newest"
msgstr "Il più nuovo"
#: core/prioritize.py:159
msgid "Oldest"
msgstr "Il più vecchio"
#: core/results.py:129
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) duplicati marcati."
#: core/results.py:136
msgid " filter: %s"
msgstr " filtro: %s"
#: core/scanner.py:101
msgid "Read metadata of %d/%d files"
msgstr "Lettura metadata di %d/%d files"
#: core/pe/matchblock.py:61
msgid "Analyzed %d/%d pictures"
msgstr "Analizzate %d/%d immagini"
#: core/pe/matchblock.py:156
msgid "Performed %d/%d chunk matches"
msgstr "Effettuate %d/%d comparazioni sui sottogruppi di immagini"
#: core/pe/matchblock.py:161
msgid "Preparing for matching"
msgstr "Preparazione per la comparazione"
#: core/pe/matchblock.py:206
msgid "Verified %d/%d matches"
msgstr "Verificate %d/%d somiglianze"
#: core/pe/matchexif.py:18
msgid "Read EXIF of %d/%d pictures"
msgstr "Leggi dati EXIF da %d/%d immagini"
#: core/app.py:312
msgid "Could not load file: {}"
msgstr "Impossibile caricare il file: {}"
#: core/app.py:496 core/app.py:742
msgid "Couldn't write to file: {}"
msgstr "Impossibile modificare il file: {}"
#: core/me/scanner.py:19 core/se/scanner.py:15
msgid "Filename" msgid "Filename"
msgstr "Nome del file" msgstr "Nome del file"
#: core/me/scanner.py:20 #: core\me\scanner.py:21
msgid "Filename - Fields" msgid "Filename - Fields"
msgstr "Nome file - Campi" msgstr "Nome file - Campi"
#: core/me/scanner.py:21 #: core\me\scanner.py:22
msgid "Filename - Fields (No Order)" msgid "Filename - Fields (No Order)"
msgstr "Nome file - Campi (Nessun Ordine)" msgstr "Nome file - Campi (Nessun Ordine)"
#: core/me/scanner.py:22 #: core\me\scanner.py:23
msgid "Tags" msgid "Tags"
msgstr "Tag" msgstr "Tag"
#: core/me/scanner.py:23 core/pe/scanner.py:20 core/se/scanner.py:16 #: core\me\scanner.py:24 core\pe\scanner.py:21 core\se\scanner.py:17
msgid "Contents" msgid "Contents"
msgstr "Contenuti" msgstr "Contenuti"
#: core/pe/scanner.py:21 #: core\pe\matchblock.py:72
msgid "Analyzed %d/%d pictures"
msgstr "Analizzate %d/%d immagini"
#: core\pe\matchblock.py:181
msgid "Performed %d/%d chunk matches"
msgstr "Effettuate %d/%d comparazioni sui sottogruppi di immagini"
#: core\pe\matchblock.py:191
msgid "Preparing for matching"
msgstr "Preparazione per la comparazione"
#: core\pe\matchblock.py:244
msgid "Verified %d/%d matches"
msgstr "Verificate %d/%d somiglianze"
#: core\pe\matchexif.py:19
msgid "Read EXIF of %d/%d pictures"
msgstr "Leggi dati EXIF da %d/%d immagini"
#: core\pe\scanner.py:22
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "Timestamp EXIF" msgstr "Timestamp EXIF"
#: core/scanner.py:139 #: core\prioritize.py:70
msgid "None"
msgstr "Nessuno"
#: core\prioritize.py:100
msgid "Ends with number"
msgstr "Termina con un numero"
#: core\prioritize.py:101
msgid "Doesn't end with number"
msgstr "Non termina con un numero"
#: core\prioritize.py:102
msgid "Longest"
msgstr "Più lungo"
#: core\prioritize.py:103
msgid "Shortest"
msgstr "Più corto"
#: core\prioritize.py:140
msgid "Highest"
msgstr "Il più alto"
#: core\prioritize.py:140
msgid "Lowest"
msgstr "Il più basso"
#: core\prioritize.py:169
msgid "Newest"
msgstr "Il più nuovo"
#: core\prioritize.py:169
msgid "Oldest"
msgstr "Il più vecchio"
#: core\results.py:142
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) duplicati marcati."
#: core\results.py:149
msgid " filter: %s"
msgstr " filtro: %s"
#: core\scanner.py:85
msgid "Read size of %d/%d files"
msgstr "Lettura dimensione di %d/%d file"
#: core\scanner.py:109
msgid "Read metadata of %d/%d files"
msgstr "Lettura metadata di %d/%d files"
#: core\scanner.py:147
msgid "Almost done! Fiddling with results..." msgid "Almost done! Fiddling with results..."
msgstr "Quasi finito! Sto organizzando i risultati..." msgstr "Quasi finito! Sto organizzando i risultati..."
#: core/se/scanner.py:17 #: core\se\scanner.py:18
msgid "Folders" msgid "Folders"
msgstr "Cartelle" msgstr "Cartelle"
#~ msgid "Sending files to the recycle bin"
#~ msgstr "Spostamento nel cestino"
#~ msgid "Grouped %d/%d matches"
#~ msgstr "Raggruppati %d/%d duplicati"
#~ msgid "Removing false matches"
#~ msgstr "Rimozione dei falsi positivi"
#~ msgid "Processed %d/%d matches against the ignore list"
#~ msgstr ""
#~ "Processati %d/%d duplicati applicando le regole della lista da ignorare"
#~ msgid "Doing group prioritization"
#~ msgstr "Applicazione delle priorità di gruppo"

View File

@@ -1,24 +1,34 @@
# Translators: # Translators:
# Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2013-12-07 15:22+0000\n" "Language-Team: Italian (https://www.transifex.com/voltaicideas/teams/116153/it/)\n"
"Last-Translator: auanasgheps\n" "Language: it\n"
"Language-Team: Italian (http://www.transifex.com/projects/p/dupeguru/language/it/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: qt/app.py:81 #: qt/app.py:81
msgid "Quit" msgid "Quit"
msgstr "Esci" msgstr "Esci"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Opzioni"
#: qt/app.py:83 qt/ignore_list_dialog.py:32 #: qt/app.py:83 qt/ignore_list_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Ignore List" msgid "Ignore List"
msgstr "Lista elementi ignorati" msgstr "Lista elementi ignorati"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Cancella la cache delle immagini"
#: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0 #: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Help" msgid "dupeGuru Help"
msgstr "Aiuto di dupeGuru" msgstr "Aiuto di dupeGuru"
@@ -31,6 +41,16 @@ msgstr "Informazioni su dupeGuru"
msgid "Open Debug Log" msgid "Open Debug Log"
msgstr "Apri registro eventi" msgstr "Apri registro eventi"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr ""
"Vuoi veramente rimuovere tutte le analisi delle immagini memorizzate nella "
"cache?"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "La cache delle immagini è stata cancellata."
#: qt/app.py:251 #: qt/app.py:251
msgid "{} file (*.{})" msgid "{} file (*.{})"
msgstr "{} file (*.{})" msgstr "{} file (*.{})"
@@ -48,8 +68,8 @@ msgid ""
"After having deleted a duplicate, place a link targeting the reference file " "After having deleted a duplicate, place a link targeting the reference file "
"to replace the deleted file." "to replace the deleted file."
msgstr "" msgstr ""
"Dopo aver selezionato un duplicato, per sostituire il file eliminato posiziona un collegamento " "Dopo aver selezionato un duplicato, per sostituire il file eliminato "
"che ha come destinazione i file di referenza." "posiziona un collegamento che ha come destinazione i file di referenza."
#: qt/deletion_options.py:44 #: qt/deletion_options.py:44
msgid "Hardlink" msgid "Hardlink"
@@ -73,8 +93,8 @@ msgid ""
"usually used as a workaround when the normal deletion method doesn't work." "usually used as a workaround when the normal deletion method doesn't work."
msgstr "" msgstr ""
"Invece di spostare file nel cestino, eliminali direttamente. Questa opzione " "Invece di spostare file nel cestino, eliminali direttamente. Questa opzione "
"di solito è usata come alternativa al sistema di eliminazione standard quando " "di solito è usata come alternativa al sistema di eliminazione standard "
"non funziona." "quando non funziona."
#: qt/deletion_options.py:59 cocoa/en.lproj/Localizable.strings:0 #: qt/deletion_options.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Proceed" msgid "Proceed"
@@ -127,6 +147,30 @@ msgstr "Aiuto"
msgid "Load Recent Results" msgid "Load Recent Results"
msgstr "Carica i risultati recenti" msgstr "Carica i risultati recenti"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0
msgid "Application Mode:"
msgstr "Modalità applicazione:"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Music"
msgstr "Musica"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Picture"
msgstr "Foto"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Standard"
msgstr "Standard"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0
msgid "Scan Type:"
msgstr "Tipo di scansione:"
#: qt/directories_dialog.py:135
msgid "More Options"
msgstr "Più Opzioni"
#: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0 #: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0
msgid "Select folders to scan and press \"Scan\"." msgid "Select folders to scan and press \"Scan\"."
msgstr "Seleziona le cartelle da scansionare e premi \"Scansiona\"." msgstr "Seleziona le cartelle da scansionare e premi \"Scansiona\"."
@@ -149,7 +193,9 @@ msgstr "Hai dei risultati non salvati. Vuoi veramente chiudere?"
#: qt/directories_dialog.py:239 cocoa/en.lproj/Localizable.strings:0 #: qt/directories_dialog.py:239 cocoa/en.lproj/Localizable.strings:0
msgid "Select a folder to add to the scanning list" msgid "Select a folder to add to the scanning list"
msgstr "Seleziona una cartella da aggiungere alla lista delle cartelle da scansionare" msgstr ""
"Seleziona una cartella da aggiungere alla lista delle cartelle da "
"scansionare"
#: qt/directories_dialog.py:266 cocoa/en.lproj/Localizable.strings:0 #: qt/directories_dialog.py:266 cocoa/en.lproj/Localizable.strings:0
msgid "Select a results file to load" msgid "Select a results file to load"
@@ -200,9 +246,78 @@ msgstr "Deseleziona"
msgid "Close" msgid "Close"
msgstr "Chiudi" msgstr "Chiudi"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0 #: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
msgid "Scan Type:" #: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
msgstr "Tipo di scansione:" #: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Dettagli"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Etichette da scansionare:"
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Traccia"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Artista"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Album"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Titolo"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Genere"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Anno"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "'Peso' della parola"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Fai coincidere parole simili"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Includi tipi diversi di file"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Usa le espressioni regolari per filtrare"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Rimuovi le cartelle vuote dopo aver cancellato o spostato"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Non considerare gli hardlink come duplicati"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Modalità 'Debug'(è richiesta la riapertura del programma)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Includi immagini di dimensione differente"
#: qt/preferences_dialog.py:43 #: qt/preferences_dialog.py:43
msgid "Filter Hardness:" msgid "Filter Hardness:"
@@ -281,12 +396,6 @@ msgstr ""
msgid "Reveal Selected" msgid "Reveal Selected"
msgstr "Mostra i selezionati" msgstr "Mostra i selezionati"
#: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
#: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "Dettagli"
#: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167 #: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167
#: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0
msgid "Actions" msgid "Actions"
@@ -330,7 +439,7 @@ msgstr "Aggiungi gli elementi selezionati alla lista da ignorare"
#: qt/result_window.py:75 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:75 cocoa/en.lproj/Localizable.strings:0
msgid "Make Selected into Reference" msgid "Make Selected into Reference"
msgstr "" msgstr "Rendi selezionato un Riferimento"
#: qt/result_window.py:77 cocoa/en.lproj/Localizable.strings:0 #: qt/result_window.py:77 cocoa/en.lproj/Localizable.strings:0
msgid "Open Selected with Default Application" msgid "Open Selected with Default Application"
@@ -404,87 +513,6 @@ msgstr "Valori Delta"
msgid "Select a file to save your results to" msgid "Select a file to save your results to"
msgstr "Seleziona un file dove salvare i tuoi risultati" msgstr "Seleziona un file dove salvare i tuoi risultati"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "Etichette da scansionare:"
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "Traccia"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "Artista"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "Album"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "Titolo"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "Genere"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "Anno"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "'Peso' della parola"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "Fai coincidere parole simili"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "Includi tipi diversi di file"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "Usa le espressioni regolari per filtrare"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "Rimuovi le cartelle vuote dopo aver cancellato o spostato"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "Non creare gli hardlink per i duplicati verso il medesimo file"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "Modalità 'Debug'(è richiesta la riapertura del programma)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "Includi immagini di dimensione differente"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "Cancella la cache delle immagini"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr ""
"Vuoi veramente rimuovere tutte le analisi delle immagini memorizzate nella "
"cache?"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr ""
#: qt/se/preferences_dialog.py:41 #: qt/se/preferences_dialog.py:41
msgid "Ignore files smaller than" msgid "Ignore files smaller than"
msgstr "Ignora file più piccoli di" msgstr "Ignora file più piccoli di"
@@ -642,11 +670,6 @@ msgstr "Più risultati"
msgid "Ok" msgid "Ok"
msgstr "Ok" msgstr "Ok"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "Opzioni"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Paste" msgid "Paste"
msgstr "Incolla" msgstr "Incolla"
@@ -673,7 +696,7 @@ msgstr "Imposta prefefinite"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Reveal" msgid "Reveal"
msgstr "" msgstr "Rivelare"
#: cocoa/en.lproj/Localizable.strings:0 #: cocoa/en.lproj/Localizable.strings:0
msgid "Reveal Selected in Finder" msgid "Reveal Selected in Finder"
@@ -711,112 +734,220 @@ msgstr "Finestra"
msgid "Zoom" msgid "Zoom"
msgstr "Zoom" msgstr "Zoom"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0 #: qt\app.py:158
msgid "Application Mode:" msgid "Exclusion Filters"
msgstr "Modalità applicazione:" msgstr "Filtri di esclusione"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\directories_dialog.py:91
msgid "Music" msgid "Scan Results"
msgstr "Musica" msgstr "Risultati della scansione"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\directories_dialog.py:95
msgid "Picture" msgid "Load Directories..."
msgstr "Foto" msgstr "Carica cartelle..."
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0 #: qt\directories_dialog.py:96
msgid "Standard" msgid "Save Directories..."
msgstr "Standard" msgstr "Salva cartelle..."
#: qt/directories_dialog.py:135 #: qt\directories_dialog.py:337
msgid "More Options" msgid "Select a directories file to load"
msgstr "Più Opzioni" msgstr "Seleziona un file delle cartelle da caricare"
#~ msgid "Removing dead tracks from your iTunes Library" #: qt\directories_dialog.py:338
#~ msgstr "Rimozione delle tracce insistenti dalla libreria di iTunes" msgid "dupeGuru Results (*.dupegurudirs)"
msgstr "cartelle di dupeGuru (*.dupegurudirs)"
#~ msgid "Scanning the iTunes Library" #: qt\directories_dialog.py:347
#~ msgstr "Scansione della libreria di iTunes" msgid "Select a file to save your directories to"
msgstr "Seleziona un file in cui salvare le cartelle"
#~ msgid "Sending dupes to the Trash" #: qt\directories_dialog.py:348
#~ msgstr "Spostamento dei duplicati nel cestino" msgid "dupeGuru Directories (*.dupegurudirs)"
msgstr "cartelle di dupeGuru (*.dupegurudirs)"
#~ msgid "Talking to iTunes. Don't touch it!" #: qt\exclude_list_dialog.py:44
#~ msgstr "" msgid "Add"
msgstr "Addizionare"
#~ msgid "" #: qt\exclude_list_dialog.py:46
#~ "Your iTunes Library contains %d dead tracks ready to be removed. Continue?" msgid "Restore defaults"
#~ msgstr "" msgstr "Ripristina i valori predefiniti"
#~ "La tua libreria di iTunes contiene %d tracce inesistenti pronte per essere "
#~ "rimosse. Continuare?"
#~ msgid "You have no dead tracks in your iTunes Library" #: qt\exclude_list_dialog.py:47
#~ msgstr "La tua libreria di iTunes non contiene tracce inesistenti" msgid "Test string"
msgstr "Stringa di prova"
#~ msgid "The iTunes application couldn't be found." #: qt\exclude_list_dialog.py:83
#~ msgstr "" msgid "Type a python regular expression here..."
msgstr "Digita qui un'espressione regolare Python..."
#~ msgid "Talking to iPhoto. Don't touch it!" #: qt\exclude_list_dialog.py:85
#~ msgstr "" msgid "Type a file system path or filename here..."
msgstr "Digitare un percorso del file system o un nome file qui..."
#~ msgid "Talking to Aperture. Don't touch it!" #: qt\exclude_list_dialog.py:152
#~ msgstr "" msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happen to match one of the regular expressions.<br>For each file collected two tests are perfomed on each of them to determine whether or not to filter them out:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with no path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the test string feature by pasting a fake path in it:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>I direttori avranno anche il loro <strong>stato predefinito</strong> impostato su Escluso nella scheda Directory se il loro nome corrisponde a una delle espressioni regolari selezionate.<br>Per ogni file raccolto vengono eseguiti due test per determinare se ignorarlo o meno completamente:<br><li>1. Le espressioni regolari prive di separatori di percorso verranno confrontate solo con il nome del file.</li>\n"
"<li>2. Le espressioni regolari contenenti almeno un separatore di percorso verranno confrontate con il percorso completo del file.</li><br>\n"
"Esempio: se desideri filtrare i file .PNG solo dalla directory \"Mie Immagini\":<br><code>.*Mie\\sImmagini\\\\.*\\.png</code><br><br>Puoi testare l'espressione regolare con il pulsante \"stringa di prova\" dopo aver incollato un percorso falso nel campo di prova:<br><code>C:\\\\Utente\\Mie Immagini\\test.png</code><br><br>\n"
"Verranno evidenziate le espressioni regolari corrispondenti.<br>Se è presente almeno un'evidenziazione, il percorso o il nome del file testato verrà ignorato durante le scansioni.<br><br>Directory e file che iniziano con un punto \".\" vengono filtrati per impostazione predefinita.<br><br>"
#~ msgid "Deleted Aperture photos were sent to a project called \"dupeGuru Trash\"." #: qt\exclude_list_table.py:36
#~ msgstr "" msgid "Compilation error: "
msgstr "Errore di compilazione:"
#~ msgid "The iPhoto application couldn't be found." #: qt\pe\image_viewer.py:56
#~ msgstr "Non trovo l'applicazione iPhoto." msgid "Increase zoom"
msgstr "Aumenta lo zoom"
#~ msgid "Preferences" #: qt\pe\image_viewer.py:66
#~ msgstr "Impostazioni" msgid "Decrease zoom"
msgstr "Diminuisci lo zoom"
#~ msgid "Check for Update" #: qt\pe\image_viewer.py:71
#~ msgstr "Controlla aggiornamenti" msgid "Ctrl+/"
msgstr "Ctrl+/"
#~ msgid "Filename" #: qt\pe\image_viewer.py:76
#~ msgstr "Nome del file" msgid "Normal size"
msgstr "Dimensione normale"
#~ msgid "Filename - Fields" #: qt\pe\image_viewer.py:81
#~ msgstr "Nome del file - Campi" msgid "Ctrl+*"
msgstr "Ctrl+*"
#~ msgid "Filename - Fields (No Order)" #: qt\pe\image_viewer.py:86
#~ msgstr "Nome del file - Campi (senza ordine)" msgid "Best fit"
msgstr "Il più adatto"
#~ msgid "Tags" #: qt\pe\preferences_dialog.py:49
#~ msgstr "Tags" msgid "Picture cache mode:"
msgstr "Modalità cache immagini:"
#~ msgid "Contents" #: qt\pe\preferences_dialog.py:56
#~ msgstr "Contenuti" msgid "Override theme icons in viewer toolbar"
msgstr ""
"Ignora le icone del tema nella barra degli strumenti del visualizzatore"
#~ msgid "Audio Contents" #: qt\pe\preferences_dialog.py:58
#~ msgstr "Contenuti Audio" msgid ""
"Use our own internal icons instead of those provided by the theme engine"
msgstr ""
"Usa le nostre icone interne invece di quelle fornite dal motore del tema"
#~ msgid "EXIF Timestamp" #: qt\pe\preferences_dialog.py:66
#~ msgstr "Data e ora EXIF" msgid "Show scrollbars in image viewers"
msgstr "Mostra le barre di scorrimento nei visualizzatori di immagini"
#~ msgid "Folders" #: qt\pe\preferences_dialog.py:68
#~ msgstr "Cartelle" msgid ""
"When the image displayed doesn't fit the viewport, show scrollbars to span "
"the view around"
msgstr ""
"Quando l'immagine visualizzata non si adatta alla visualizzazione, mostra le"
" barre di scorrimento per estendere la visualizzazione"
#~ msgid "Add Aperture Library" #: qt\preferences_dialog.py:156
#~ msgstr "" msgid "Use default position for tab bar (requires restart)"
msgstr ""
"Usa la posizione predefinita per la barra di tabulazione (richiede il "
"riavvio)"
#~ msgid "Add iPhoto Library" #: qt\preferences_dialog.py:158
#~ msgstr "Aggiungi alla libreria di iPhoto" msgid ""
"Place the tab bar below the main menu instead of next to it\n"
"On MacOS, the tab bar will fill up the window's width instead."
msgstr ""
"Posiziona la barra di tabulazione sotto il menu principale anziché accanto ad esso\n"
"Su MacOS, la barra delle schede riempirà invece la larghezza della finestra."
#~ msgid "Add iTunes Library" #: qt\preferences_dialog.py:172
#~ msgstr "Aggiungi alla lista di iTunes" msgid "Use bold font for references"
msgstr "Usa caratteri in grassetto per i riferimenti"
#~ msgid "Audio Content" #: qt\preferences_dialog.py:176
#~ msgstr "Contenuto audio" msgid "Reference foreground color:"
msgstr "Colore di primo piano per i riferimenti:"
#~ msgid "Content" #: qt\preferences_dialog.py:179
#~ msgstr "Contenuto" msgid "Reference background color:"
msgstr "Colore di sfondo per i riferimenti:"
#~ msgid "dupeGuru ME Preferences" #: qt\preferences_dialog.py:182 qt\preferences_dialog.py:216
#~ msgstr "Preferenze di dupeGuru ME" msgid "Delta foreground color:"
msgstr "colore di primo piano per i delta:"
#~ msgid "dupeGuru PE Preferences" #: qt\preferences_dialog.py:195
#~ msgstr "Preferenze di dupeGuru PE" msgid "Show the title bar and can be docked"
msgstr "Mostra la barra del titolo e può essere agganciata"
#~ msgid "Remove Dead Tracks in iTunes" #: qt\preferences_dialog.py:197
#~ msgstr "Rimuovi le tracce inesistenti da iTunes" msgid ""
"While the title bar is hidden, use the modifier key to drag the floating "
"window around"
msgstr ""
"Mentre la barra del titolo è nascosta, usa il tasto modificatore per "
"trascinare la finestra mobile"
#: qt\preferences_dialog.py:199
msgid "The title bar can only be disabled while the window is docked"
msgstr ""
"La barra del titolo può essere disabilitata solo mentre la finestra è "
"agganciata"
#: qt\preferences_dialog.py:202
msgid "Vertical title bar"
msgstr "Barra del titolo verticale"
#: qt\preferences_dialog.py:204
msgid ""
"Change the title bar from horizontal on top, to vertical on the left side"
msgstr ""
"Cambia la barra del titolo da orizzontale in alto a verticale sul lato "
"sinistro"
#: qt\tabbed_window.py:44
msgid "Show tab bar"
msgstr "Mostra la barra di tabulazione"
#: qt\exclude_list_dialog.py:152
msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happens to match one of the selected regular expressions.<br>For each file collected, two tests are performed to determine whether or not to completely ignore it:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with at least one path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the \"test string\" button after pasting a fake path in the test field:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path or filename tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>I direttori avranno anche il loro <strong>stato predefinito</strong> impostato su Escluso nella scheda Directory se il loro nome corrisponde a una delle espressioni regolari selezionate.<br>Per ogni file raccolto vengono eseguiti due test per determinare se ignorarlo o meno completamente:<br><li>1. Le espressioni regolari prive di separatori di percorso verranno confrontate solo con il nome del file.</li>\n"
"<li>2. Le espressioni regolari contenenti almeno un separatore di percorso verranno confrontate con il percorso completo del file.</li><br>\n"
"Esempio: se desideri filtrare i file .PNG solo dalla directory \"Mie Immagini\":<br><code>.*Mie\\sImmagini\\\\.*\\.png</code><br><br>Puoi testare l'espressione regolare con il pulsante \"stringa di prova\" dopo aver incollato un percorso falso nel campo di prova:<br><code>C:\\\\Utente\\Mie Immagini\\test.png</code><br><br>\n"
"Verranno evidenziate le espressioni regolari corrispondenti.<br>Se è presente almeno un'evidenziazione, il percorso o il nome del file testato verrà ignorato durante le scansioni.<br><br>Directory e file che iniziano con un punto \".\" vengono filtrati per impostazione predefinita.<br><br>"
#: qt\app.py:256
msgid "Results"
msgstr "Risultati"
#: qt\preferences_dialog.py:150
msgid "General Interface"
msgstr "Interfaccia generale"
#: qt\preferences_dialog.py:176
msgid "Result Table"
msgstr "Tabella dei risultati"
#: qt\preferences_dialog.py:205
msgid "Details Window"
msgstr "Finestra Dettagli"
#: qt\preferences_dialog.py:285
msgid "General"
msgstr "Generale"
#: qt\preferences_dialog.py:286
msgid "Display"
msgstr "Schermo"

View File

@@ -0,0 +1,122 @@
# Translators:
# Fuan <jcfrt@posteo.net>, 2021
#
msgid ""
msgstr ""
"Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"Language-Team: Japanese (https://www.transifex.com/voltaicideas/teams/116153/ja/)\n"
"Language: ja\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core\gui\problem_table.py:18
msgid "File Path"
msgstr "ファイルパス"
#: core\gui\problem_table.py:19
msgid "Error Message"
msgstr "エラーメッセージ"
#: core\me\prioritize.py:23
msgid "Duration"
msgstr "デュレーション"
#: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate"
msgstr "ビットレート"
#: core\me\prioritize.py:37
msgid "Samplerate"
msgstr "サンプルレート"
#: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
#: core\se\result_table.py:19
msgid "Filename"
msgstr "ファイル名"
#: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core\se\result_table.py:20
msgid "Folder"
msgstr "フォルダ"
#: core\me\result_table.py:21
msgid "Size (MB)"
msgstr "サイズMB"
#: core\me\result_table.py:22
msgid "Time"
msgstr "デュレーション"
#: core\me\result_table.py:24
msgid "Sample Rate"
msgstr "サンプルレート"
#: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core\se\result_table.py:22
msgid "Kind"
msgstr "種類"
#: core\me\result_table.py:26 core\pe\result_table.py:25
#: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification"
msgstr "変更"
#: core\me\result_table.py:27
msgid "Title"
msgstr "タイトル"
#: core\me\result_table.py:28
msgid "Artist"
msgstr "アーティスト"
#: core\me\result_table.py:29
msgid "Album"
msgstr "アルバム"
#: core\me\result_table.py:30
msgid "Genre"
msgstr "ジャンル"
#: core\me\result_table.py:31
msgid "Year"
msgstr "年"
#: core\me\result_table.py:32
msgid "Track Number"
msgstr "トラック番号"
#: core\me\result_table.py:33
msgid "Comment"
msgstr "コメント"
#: core\me\result_table.py:34 core\pe\result_table.py:26
#: core\se\result_table.py:24
msgid "Match %"
msgstr "一致率"
#: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used"
msgstr "使用した単語"
#: core\me\result_table.py:36 core\pe\result_table.py:27
#: core\se\result_table.py:26
msgid "Dupe Count"
msgstr "重複カウント"
#: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions"
msgstr "寸法"
#: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)"
msgstr "サイズKB"
#: core\pe\result_table.py:24
msgid "EXIF Timestamp"
msgstr "EXIFタイムスタンプ"
#: core\prioritize.py:156
msgid "Size"
msgstr "サイズ"

View File

@@ -0,0 +1,249 @@
# Translators:
# Fuan <jcfrt@posteo.net>, 2021
#
msgid ""
msgstr ""
"Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"Language-Team: Japanese (https://www.transifex.com/voltaicideas/teams/116153/ja/)\n"
"Language: ja\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: core\app.py:42
msgid "There are no marked duplicates. Nothing has been done."
msgstr "マークされた重複はありません。 何も行われていません。"
#: core\app.py:43
msgid "There are no selected duplicates. Nothing has been done."
msgstr "選択された重複はありません。 何も行われていません。"
#: core\app.py:44
msgid ""
"You're about to open many files at once. Depending on what those files are "
"opened with, doing so can create quite a mess. Continue?"
msgstr "一度に多くのファイルを開こうとしています。 これらのファイルを開く対象によっては、これを行うとかなり混乱する可能性があります。 継続する?"
#: core\app.py:71
msgid "Scanning for duplicates"
msgstr "重複のスキャン"
#: core\app.py:72
msgid "Loading"
msgstr "読み込み中"
#: core\app.py:73
msgid "Moving"
msgstr "移動します"
#: core\app.py:74
msgid "Copying"
msgstr "コピー中"
#: core\app.py:75
msgid "Sending to Trash"
msgstr "ごみ箱に送信します"
#: core\app.py:308
msgid ""
"A previous action is still hanging in there. You can't start a new one yet. "
"Wait a few seconds, then try again."
msgstr "前のアクションはまだそこにぶら下がっています。 まだ新しいものを始めることはできません。 数秒待ってから、再試行してください。"
#: core\app.py:318
msgid "No duplicates found."
msgstr "重複は見つかりませんでした。"
#: core\app.py:333
msgid "All marked files were copied successfully."
msgstr "マークされたファイルはすべて正常にコピーされました。"
#: core\app.py:334
msgid "All marked files were moved successfully."
msgstr "マークされたファイルはすべて正常に移動されました。"
#: core\app.py:335
msgid "All marked files were successfully sent to Trash."
msgstr "マークされたファイルはすべてごみ箱に正常に送信されました。"
#: core\app.py:343
msgid "Could not load file: {}"
msgstr "ファイルを読み込めませんでした:{}"
#: core\app.py:399
msgid "'{}' already is in the list."
msgstr "「{}」既にリストに含まれています。"
#: core\app.py:401
msgid "'{}' does not exist."
msgstr "'{}' 存在しません。"
#: core\app.py:410
msgid ""
"All selected %d matches are going to be ignored in all subsequent scans. "
"Continue?"
msgstr "選択した%d個の一致は、以降のすべてのスキャンで無視されます。 継続する?"
#: core\app.py:486
msgid "Select a directory to copy marked files to"
msgstr "マークされたファイルをコピーするディレクトリを選択してください"
#: core\app.py:487
msgid "Select a directory to move marked files to"
msgstr "マークされたファイルを移動するディレクトリを選択してください"
#: core\app.py:527
msgid "Select a destination for your exported CSV"
msgstr "エクスポートしたCSVの宛先を選択します。"
#: core\app.py:534 core\app.py:801 core\app.py:811
msgid "Couldn't write to file: {}"
msgstr "ファイルに書き込めませんでした:{}"
#: core\app.py:559
msgid "You have no custom command set up. Set it up in your preferences."
msgstr "カスタムコマンドは設定されていません。 お好みで設定してください。"
#: core\app.py:727 core\app.py:740
msgid "You are about to remove %d files from results. Continue?"
msgstr "結果から%d個のファイルを削除しようとしています。 継続する?"
#: core\app.py:774
msgid "{} duplicate groups were changed by the re-prioritization."
msgstr "{}重複するグループは、再優先順位付けによって変更されました。"
#: core\app.py:821
msgid "The selected directories contain no scannable file."
msgstr "選択したディレクトリにはスキャン可能なファイルが含まれていません。"
#: core\app.py:835
msgid "Collecting files to scan"
msgstr "スキャンするファイルを収集しています"
#: core\app.py:891
msgid "%s (%d discarded)"
msgstr "%s (%d 廃棄)"
#: core\engine.py:244 core\engine.py:288
msgid "0 matches found"
msgstr "一致するものが見つかりません"
#: core\engine.py:262 core\engine.py:296
msgid "%d matches found"
msgstr "%d の一致が見つかりました"
#: core\gui\deletion_options.py:73
msgid "You are sending {} file(s) to the Trash."
msgstr "{}個のファイルをゴミ箱に送信しています"
#: core\gui\exclude_list_table.py:15
msgid "Regular Expressions"
msgstr "正規表現"
#: core\gui\ignore_list_dialog.py:25
msgid "Do you really want to remove all %d items from the ignore list?"
msgstr "本当に除外リストから%d個の項目を削除しますか"
#: core\me\scanner.py:20 core\se\scanner.py:16
msgid "Filename"
msgstr "ファイル名"
#: core\me\scanner.py:21
msgid "Filename - Fields"
msgstr "ファイル名 - フィールド"
#: core\me\scanner.py:22
msgid "Filename - Fields (No Order)"
msgstr "ファイル名 - フィールド(順序なし)"
#: core\me\scanner.py:23
msgid "Tags"
msgstr "タグ"
#: core\me\scanner.py:24 core\pe\scanner.py:21 core\se\scanner.py:17
msgid "Contents"
msgstr "内容"
#: core\pe\matchblock.py:72
msgid "Analyzed %d/%d pictures"
msgstr "%d/%d 枚の写真を分析しました"
#: core\pe\matchblock.py:181
msgid "Performed %d/%d chunk matches"
msgstr "チャンクマッチを%d/%d回実行しました"
#: core\pe\matchblock.py:191
msgid "Preparing for matching"
msgstr "マッチングの準備"
#: core\pe\matchblock.py:244
msgid "Verified %d/%d matches"
msgstr "%d/%d件の一致を確認"
#: core\pe\matchexif.py:19
msgid "Read EXIF of %d/%d pictures"
msgstr "%d/%d枚の写真のEXIFを読みました"
#: core\pe\scanner.py:22
msgid "EXIF Timestamp"
msgstr "EXIFタイムスタンプ"
#: core\prioritize.py:70
msgid "None"
msgstr "無し"
#: core\prioritize.py:100
msgid "Ends with number"
msgstr "番号で終わっている"
#: core\prioritize.py:101
msgid "Doesn't end with number"
msgstr "数字で終わっていない"
#: core\prioritize.py:102
msgid "Longest"
msgstr "最長"
#: core\prioritize.py:103
msgid "Shortest"
msgstr "最短"
#: core\prioritize.py:140
msgid "Highest"
msgstr "最高"
#: core\prioritize.py:140
msgid "Lowest"
msgstr "最低"
#: core\prioritize.py:169
msgid "Newest"
msgstr "最新"
#: core\prioritize.py:169
msgid "Oldest"
msgstr "最古"
#: core\results.py:142
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s)マークされた重複。"
#: core\results.py:149
msgid " filter: %s"
msgstr "フィルタ: %s"
#: core\scanner.py:85
msgid "Read size of %d/%d files"
msgstr "%d/%dファイルのサイズを読み取った"
#: core\scanner.py:109
msgid "Read metadata of %d/%d files"
msgstr "%d/%dファイルのメタデータを読み取った"
#: core\scanner.py:147
msgid "Almost done! Fiddling with results..."
msgstr "ほぼ完了しました! 結果をいじっています..."
#: core\se\scanner.py:18
msgid "Folders"
msgstr "フォルダー"

927
locale/ja/LC_MESSAGES/ui.po Normal file
View File

@@ -0,0 +1,927 @@
# Translators:
# Fuan <jcfrt@posteo.net>, 2021
#
msgid ""
msgstr ""
"Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"Language-Team: Japanese (https://www.transifex.com/voltaicideas/teams/116153/ja/)\n"
"Language: ja\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: qt/app.py:81
msgid "Quit"
msgstr "終了"
#: qt/app.py:82 qt/preferences_dialog.py:116
#: cocoa/en.lproj/Localizable.strings:0
msgid "Options"
msgstr "オプション"
#: qt/app.py:83 qt/ignore_list_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Ignore List"
msgstr "無視リスト"
#: qt/app.py:84 qt/app.py:179 cocoa/en.lproj/Localizable.strings:0
msgid "Clear Picture Cache"
msgstr "画像キャッシュをクリア"
#: qt/app.py:85 cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Help"
msgstr "dupeGuruヘルプ"
#: qt/app.py:86 cocoa/en.lproj/Localizable.strings:0
msgid "About dupeGuru"
msgstr "dupeGuruついて"
#: qt/app.py:87
msgid "Open Debug Log"
msgstr "デバッグログを開く"
#: qt/app.py:180 cocoa/en.lproj/Localizable.strings:0
msgid "Do you really want to remove all your cached picture analysis?"
msgstr "キャッシュされた画像分析をすべて削除しますか?"
#: qt/app.py:184
msgid "Picture cache cleared."
msgstr "画像キャッシュがクリアされました。"
#: qt/app.py:251
msgid "{} file (*.{})"
msgstr "{} ファイル (*.{})"
#: qt/deletion_options.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Deletion Options"
msgstr "削除オプション"
#: qt/deletion_options.py:35 cocoa/en.lproj/Localizable.strings:0
msgid "Link deleted files"
msgstr "削除されたファイルをリンクする"
#: qt/deletion_options.py:37 cocoa/en.lproj/Localizable.strings:0
msgid ""
"After having deleted a duplicate, place a link targeting the reference file "
"to replace the deleted file."
msgstr "重複を削除した後、参照ファイルをターゲットとするリンクを配置して、削除されたファイルを置き換えます。"
#: qt/deletion_options.py:44
msgid "Hardlink"
msgstr "ハードリンク"
#: qt/deletion_options.py:44
msgid "Symlink"
msgstr "シンボリックリンク"
#: qt/deletion_options.py:48
msgid " (unsupported)"
msgstr "(非対応)"
#: qt/deletion_options.py:49 cocoa/en.lproj/Localizable.strings:0
msgid "Directly delete files"
msgstr "ファイルを直接削除する"
#: qt/deletion_options.py:51 cocoa/en.lproj/Localizable.strings:0
msgid ""
"Instead of sending files to trash, delete them directly. This option is "
"usually used as a workaround when the normal deletion method doesn't work."
msgstr ""
"ファイルを直接削除するファイルをゴミ箱に送る代わりに、直接削除します。 このオプションは通常、通常の削除方法が機能しない場合の回避策として使用されます。"
#: qt/deletion_options.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Proceed"
msgstr "続行"
#: qt/deletion_options.py:60 cocoa/en.lproj/Localizable.strings:0
msgid "Cancel"
msgstr "キャンセル"
#: qt/details_table.py:16 cocoa/en.lproj/Localizable.strings:0
msgid "Attribute"
msgstr "アトリビュート"
#: qt/details_table.py:16 cocoa/en.lproj/Localizable.strings:0
msgid "Selected"
msgstr "選択した"
#: qt/details_table.py:16 qt/directories_model.py:24
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reference"
msgstr "参照"
#: qt/directories_dialog.py:64 cocoa/en.lproj/Localizable.strings:0
msgid "Load Results..."
msgstr "結果をロード..."
#: qt/directories_dialog.py:65 cocoa/en.lproj/Localizable.strings:0
msgid "Results Window"
msgstr "結果ウィンドウ"
#: qt/directories_dialog.py:66
msgid "Add Folder..."
msgstr "フォルダーを追加"
#: qt/directories_dialog.py:74 qt/result_window.py:100
#: cocoa/en.lproj/Localizable.strings:0
msgid "File"
msgstr "ファイル"
#: qt/directories_dialog.py:76 qt/result_window.py:108
msgid "View"
msgstr "ビュー"
#: qt/directories_dialog.py:78 qt/result_window.py:110
#: cocoa/en.lproj/Localizable.strings:0
msgid "Help"
msgstr "ヘルプ"
#: qt/directories_dialog.py:80 cocoa/en.lproj/Localizable.strings:0
msgid "Load Recent Results"
msgstr "最近の結果を読み込む"
#: qt/directories_dialog.py:116 cocoa/en.lproj/Localizable.strings:0
msgid "Application Mode:"
msgstr "アプリケーションモード:"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Music"
msgstr "音楽"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Picture"
msgstr "画像"
#: qt/directories_dialog.py:121 cocoa/en.lproj/Localizable.strings:0
msgid "Standard"
msgstr "標準"
#: qt/directories_dialog.py:128 cocoa/en.lproj/Localizable.strings:0
msgid "Scan Type:"
msgstr "スキャンの種類:"
#: qt/directories_dialog.py:135
msgid "More Options"
msgstr "もっとオプション"
#: qt/directories_dialog.py:139 cocoa/en.lproj/Localizable.strings:0
msgid "Select folders to scan and press \"Scan\"."
msgstr "スキャンするフォルダを選択し、「スキャン」を押してください。"
#: qt/directories_dialog.py:163 cocoa/en.lproj/Localizable.strings:0
msgid "Load Results"
msgstr "結果を読み込む"
#: qt/directories_dialog.py:166 cocoa/en.lproj/Localizable.strings:0
msgid "Scan"
msgstr "スキャン"
#: qt/directories_dialog.py:230
msgid "Unsaved results"
msgstr "保存されていない結果"
#: qt/directories_dialog.py:231 cocoa/en.lproj/Localizable.strings:0
msgid "You have unsaved results, do you really want to quit?"
msgstr "保存されていない結果がありますが、本当に終了しますか?"
#: qt/directories_dialog.py:239 cocoa/en.lproj/Localizable.strings:0
msgid "Select a folder to add to the scanning list"
msgstr "スキャンリストに追加するフォルダを選択してください"
#: qt/directories_dialog.py:266 cocoa/en.lproj/Localizable.strings:0
msgid "Select a results file to load"
msgstr "ロードする結果ファイルを選択してください"
#: qt/directories_dialog.py:267
msgid "All Files (*.*)"
msgstr "すべてのファイル (*.*)"
#: qt/directories_dialog.py:267 qt/result_window.py:311
msgid "dupeGuru Results (*.dupeguru)"
msgstr "dupeGuruの結果 (*.dupeguru)"
#: qt/directories_dialog.py:278
msgid "Start a new scan"
msgstr "新しいスキャンを開始"
#: qt/directories_dialog.py:279 cocoa/en.lproj/Localizable.strings:0
msgid "You have unsaved results, do you really want to continue?"
msgstr "保存されていない結果がありますが、本当に続行しますか?"
#: qt/directories_model.py:23 cocoa/en.lproj/Localizable.strings:0
msgid "Name"
msgstr "名"
#: qt/directories_model.py:23 cocoa/en.lproj/Localizable.strings:0
msgid "State"
msgstr "状態"
#: qt/directories_model.py:24 cocoa/en.lproj/Localizable.strings:0
msgid "Excluded"
msgstr "除外"
#: qt/directories_model.py:24 cocoa/en.lproj/Localizable.strings:0
msgid "Normal"
msgstr "正常"
#: qt/ignore_list_dialog.py:45 cocoa/en.lproj/Localizable.strings:0
msgid "Remove Selected"
msgstr "選択を削除"
#: qt/ignore_list_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Clear"
msgstr "クリアー"
#: qt/ignore_list_dialog.py:47 qt/problem_dialog.py:61
#: cocoa/en.lproj/Localizable.strings:0
msgid "Close"
msgstr "閉じる"
#: qt/me/details_dialog.py:18 qt/pe/details_dialog.py:24
#: qt/result_window.py:56 qt/result_window.py:192 qt/se/details_dialog.py:18
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details"
msgstr "詳細"
#: qt/me/preferences_dialog.py:30 cocoa/en.lproj/Localizable.strings:0
msgid "Tags to scan:"
msgstr "スキャンするタグ:"
#: qt/me/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Track"
msgstr "トラック"
#: qt/me/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Artist"
msgstr "アーティスト"
#: qt/me/preferences_dialog.py:40 cocoa/en.lproj/Localizable.strings:0
msgid "Album"
msgstr "アルバム"
#: qt/me/preferences_dialog.py:42 cocoa/en.lproj/Localizable.strings:0
msgid "Title"
msgstr "タイトル"
#: qt/me/preferences_dialog.py:44 cocoa/en.lproj/Localizable.strings:0
msgid "Genre"
msgstr "ジャンル"
#: qt/me/preferences_dialog.py:46 cocoa/en.lproj/Localizable.strings:0
msgid "Year"
msgstr "年"
#: qt/me/preferences_dialog.py:50 qt/se/preferences_dialog.py:30
#: cocoa/en.lproj/Localizable.strings:0
msgid "Word weighting"
msgstr "単語の重み付け"
#: qt/me/preferences_dialog.py:52 qt/se/preferences_dialog.py:32
#: cocoa/en.lproj/Localizable.strings:0
msgid "Match similar words"
msgstr "類似の単語に一致する"
#: qt/me/preferences_dialog.py:54 qt/pe/preferences_dialog.py:21
#: qt/se/preferences_dialog.py:34 cocoa/en.lproj/Localizable.strings:0
msgid "Can mix file kind"
msgstr "ファイルの種類を混在させることができる"
#: qt/me/preferences_dialog.py:56 qt/pe/preferences_dialog.py:23
#: qt/se/preferences_dialog.py:36 cocoa/en.lproj/Localizable.strings:0
msgid "Use regular expressions when filtering"
msgstr "フィルタリング時に正規表現を使用する"
#: qt/me/preferences_dialog.py:58 qt/pe/preferences_dialog.py:25
#: qt/se/preferences_dialog.py:38 cocoa/en.lproj/Localizable.strings:0
msgid "Remove empty folders on delete or move"
msgstr "削除または移動時に空のフォルダを削除する"
#: qt/me/preferences_dialog.py:60 qt/pe/preferences_dialog.py:27
#: qt/se/preferences_dialog.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Ignore duplicates hardlinking to the same file"
msgstr "同じファイルへの重複ハードリンクを無視する"
#: qt/me/preferences_dialog.py:62 qt/pe/preferences_dialog.py:29
#: qt/se/preferences_dialog.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Debug mode (restart required)"
msgstr "デバッグモード(再起動が必要)"
#: qt/pe/preferences_dialog.py:19 cocoa/en.lproj/Localizable.strings:0
msgid "Match pictures of different dimensions"
msgstr "異なる寸法の写真を一致させる"
#: qt/preferences_dialog.py:43
msgid "Filter Hardness:"
msgstr "フィルター硬度:"
#: qt/preferences_dialog.py:69
msgid "More Results"
msgstr "より多くの結果"
#: qt/preferences_dialog.py:74
msgid "Fewer Results"
msgstr "より少ない結果"
#: qt/preferences_dialog.py:81
msgid "Font size:"
msgstr "フォントサイズ:"
#: qt/preferences_dialog.py:85
msgid "Language:"
msgstr "言語:"
#: qt/preferences_dialog.py:91 cocoa/en.lproj/Localizable.strings:0
msgid "Copy and Move:"
msgstr "コピーと移動:"
#: qt/preferences_dialog.py:94 cocoa/en.lproj/Localizable.strings:0
msgid "Right in destination"
msgstr "目的地で直接"
#: qt/preferences_dialog.py:95 cocoa/en.lproj/Localizable.strings:0
msgid "Recreate relative path"
msgstr "相対パスを再作成"
#: qt/preferences_dialog.py:96 cocoa/en.lproj/Localizable.strings:0
msgid "Recreate absolute path"
msgstr "絶対パスを再作成"
#: qt/preferences_dialog.py:99
msgid "Custom Command (arguments: %d for dupe, %r for ref):"
msgstr "カスタムコマンド (引数重複の場合はd、参照の場合はr:"
#: qt/preferences_dialog.py:174
msgid "dupeGuru has to restart for language changes to take effect."
msgstr "言語の変更を有効にするには、dupeGuruを再起動する必要があります。"
#: qt/prioritize_dialog.py:75 cocoa/en.lproj/Localizable.strings:0
msgid "Re-Prioritize duplicates"
msgstr "重複を再優先する"
#: qt/prioritize_dialog.py:79 cocoa/en.lproj/Localizable.strings:0
msgid ""
"Add criteria to the right box and click OK to send the dupes that correspond"
" the best to these criteria to their respective group's reference position. "
"Read the help file for more information."
msgstr ""
"右側のボックスに基準を追加し、[OK]をクリックして、これらの基準に最もよく対応する複製をそれぞれのグループの参照位置に送信します。 "
"詳細については、ヘルプファイルをお読みください。"
#: qt/problem_dialog.py:33 cocoa/en.lproj/Localizable.strings:0
msgid "Problems!"
msgstr "問題!"
#: qt/problem_dialog.py:37 cocoa/en.lproj/Localizable.strings:0
msgid ""
"There were problems processing some (or all) of the files. The cause of "
"these problems are described in the table below. Those files were not "
"removed from your results."
msgstr ""
"一部(またはすべて)のファイルの処理に問題がありました。 これらの問題の原因を次の表に示します。 これらのファイルは結果から削除されませんでした。"
#: qt/problem_dialog.py:56
msgid "Reveal Selected"
msgstr "選択したものを明らかにする"
#: qt/result_window.py:57 qt/result_window.py:104 qt/result_window.py:167
#: qt/result_window.py:191 cocoa/en.lproj/Localizable.strings:0
msgid "Actions"
msgstr "作用"
#: qt/result_window.py:58 cocoa/en.lproj/Localizable.strings:0
msgid "Show Dupes Only"
msgstr "複製のみを表示"
#: qt/result_window.py:59 cocoa/en.lproj/Localizable.strings:0
msgid "Show Delta Values"
msgstr "デルタ値を表示"
#: qt/result_window.py:60
msgid "Send Marked to Recycle Bin..."
msgstr "マークされたものをごみ箱に送る..."
#: qt/result_window.py:61 cocoa/en.lproj/Localizable.strings:0
msgid "Move Marked to..."
msgstr "マークされたものを移動..."
#: qt/result_window.py:62 cocoa/en.lproj/Localizable.strings:0
msgid "Copy Marked to..."
msgstr "マークされたものをコピー..."
#: qt/result_window.py:63 cocoa/en.lproj/Localizable.strings:0
msgid "Remove Marked from Results"
msgstr "結果からマークされたものを削除"
#: qt/result_window.py:64 cocoa/en.lproj/Localizable.strings:0
msgid "Re-Prioritize Results..."
msgstr "結果を再優先する..."
#: qt/result_window.py:67 cocoa/en.lproj/Localizable.strings:0
msgid "Remove Selected from Results"
msgstr "結果から選択したアイテムを削除"
#: qt/result_window.py:71 cocoa/en.lproj/Localizable.strings:0
msgid "Add Selected to Ignore List"
msgstr "選択したアイテムを無視リストに追加"
#: qt/result_window.py:75 cocoa/en.lproj/Localizable.strings:0
msgid "Make Selected into Reference"
msgstr "選択したアイテムを参照にする"
#: qt/result_window.py:77 cocoa/en.lproj/Localizable.strings:0
msgid "Open Selected with Default Application"
msgstr "デフォルトのアプリケーションで選択を開く"
#: qt/result_window.py:80
msgid "Open Containing Folder of Selected"
msgstr "選択したアイテムのコンテナフォルダを開く"
#: qt/result_window.py:82 cocoa/en.lproj/Localizable.strings:0
msgid "Rename Selected"
msgstr "選択したアイテムの名前を変更する"
#: qt/result_window.py:83 cocoa/en.lproj/Localizable.strings:0
msgid "Mark All"
msgstr "すべてのアイテムをマークする"
#: qt/result_window.py:84 cocoa/en.lproj/Localizable.strings:0
msgid "Mark None"
msgstr "何もマークしない"
#: qt/result_window.py:85 cocoa/en.lproj/Localizable.strings:0
msgid "Invert Marking"
msgstr "マーキングを反転"
#: qt/result_window.py:86 cocoa/en.lproj/Localizable.strings:0
msgid "Mark Selected"
msgstr "選択したアイテムにマークを付け"
#: qt/result_window.py:87
msgid "Export To HTML"
msgstr "HTMLにエクスポート"
#: qt/result_window.py:88
msgid "Export To CSV"
msgstr "CSVにエクスポート"
#: qt/result_window.py:89 cocoa/en.lproj/Localizable.strings:0
msgid "Save Results..."
msgstr "結果を保存する"
#: qt/result_window.py:90 cocoa/en.lproj/Localizable.strings:0
msgid "Invoke Custom Command"
msgstr "カスタムコマンドを呼び出す"
#: qt/result_window.py:102
msgid "Mark"
msgstr "マーク"
#: qt/result_window.py:106 cocoa/en.lproj/Localizable.strings:0
msgid "Columns"
msgstr "コラム"
#: qt/result_window.py:163
msgid "Reset to Defaults"
msgstr "既定値にリセット"
#: qt/result_window.py:185
msgid "{} Results"
msgstr "{}結果"
#: qt/result_window.py:193 cocoa/en.lproj/Localizable.strings:0
msgid "Dupes Only"
msgstr "複製のみ"
#: qt/result_window.py:194
msgid "Delta Values"
msgstr "デルタ値"
#: qt/result_window.py:310 cocoa/en.lproj/Localizable.strings:0
msgid "Select a file to save your results to"
msgstr "結果を保存するファイルを選択してください"
#: qt/se/preferences_dialog.py:41
msgid "Ignore files smaller than"
msgstr "より小さいファイルは無視"
#: qt/se/preferences_dialog.py:52 cocoa/en.lproj/Localizable.strings:0
msgid "KB"
msgstr "KB"
#: cocoa/en.lproj/Localizable.strings:0
msgid "%@ Results"
msgstr "%@ 結果"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Action"
msgstr "作用"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Add New Folder..."
msgstr "新しいフォルダを追加..."
#: cocoa/en.lproj/Localizable.strings:0
msgid "Advanced"
msgstr "高度"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Automatically check for updates"
msgstr "更新を自動的にチェック"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Basic"
msgstr "基本"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Bring All to Front"
msgstr "すべてを前面に出す"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Check for update..."
msgstr "更新を確認..."
#: cocoa/en.lproj/Localizable.strings:0
msgid "Close Window"
msgstr "ウィンドウを閉じる"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Copy"
msgstr "コピー"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Custom command (arguments: %d for dupe, %r for ref):"
msgstr "カスタムコマンド (引数重複の場合はd、参照の場合はr:"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Cut"
msgstr "カット"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Delta"
msgstr "デルタ"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details of Selected File"
msgstr "選択したファイルの詳細"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Details Panel"
msgstr "詳細パネル"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Directories"
msgstr "ディレクトリ"
#: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru"
msgstr "dupeGuru"
#: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Preferences"
msgstr "dupeGuruの設定"
#: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Results"
msgstr "dupeGuruの結果"
#: cocoa/en.lproj/Localizable.strings:0
msgid "dupeGuru Website"
msgstr "dupeGuruウェブサイト"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Edit"
msgstr "編集"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Export Results to CSV"
msgstr "結果をCSVにエクスポート"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Export Results to XHTML"
msgstr "結果をXHTMLにエクスポート"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Fewer results"
msgstr "より少ない結果"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Filter"
msgstr "フィルタ"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Filter hardness:"
msgstr "フィルター硬度:"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Filter Results..."
msgstr "結果のフィルタリング"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Folder Selection Window"
msgstr "フォルダ選択ウィンドウ"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Font Size:"
msgstr "フォントサイズ"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Hide dupeGuru"
msgstr "dupeGuruを隠す"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Hide Others"
msgstr "他を隠す"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Ignore files smaller than:"
msgstr "以下よりも小さいファイルは無視:"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Load from file..."
msgstr "ファイルからロード..."
#: cocoa/en.lproj/Localizable.strings:0
msgid "Minimize"
msgstr "最小化する"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Mode"
msgstr "モード"
#: cocoa/en.lproj/Localizable.strings:0
msgid "More results"
msgstr "より多くの結果"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Ok"
msgstr "Ok"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Paste"
msgstr "ペースト"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Preferences..."
msgstr "環境設定"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Quick Look"
msgstr "クイックルック"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Quit dupeGuru"
msgstr "dupeGuruを終了"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reset to Default"
msgstr "デフォルトにリセット"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reset To Defaults"
msgstr "既定値にリセット"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reveal"
msgstr "表す"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Reveal Selected in Finder"
msgstr "Finderで選択したものを表示"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Select All"
msgstr "すべて選択"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Send Marked to Trash..."
msgstr "マークされたアイテムをゴミ箱に送る..."
#: cocoa/en.lproj/Localizable.strings:0
msgid "Services"
msgstr "サービス"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Show All"
msgstr "すべて表示"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Start Duplicate Scan"
msgstr "重複スキャンを開始"
#: cocoa/en.lproj/Localizable.strings:0
msgid "The name '%@' already exists."
msgstr "'@'名はすでに存在します。"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Window"
msgstr "ウィンドウ"
#: cocoa/en.lproj/Localizable.strings:0
msgid "Zoom"
msgstr "ズーム"
#: qt\app.py:158
msgid "Exclusion Filters"
msgstr "除外フィルター"
#: qt\directories_dialog.py:91
msgid "Scan Results"
msgstr "スキャン結果"
#: qt\directories_dialog.py:95
msgid "Load Directories..."
msgstr "ディレクトリをロード..."
#: qt\directories_dialog.py:96
msgid "Save Directories..."
msgstr "ディレクトリを保存..."
#: qt\directories_dialog.py:337
msgid "Select a directories file to load"
msgstr "ロードするディレクトリファイルを選択してください"
#: qt\directories_dialog.py:338
msgid "dupeGuru Results (*.dupegurudirs)"
msgstr "dupeGuruのディレクトリファイル (*.dupegurudirs)"
#: qt\directories_dialog.py:347
msgid "Select a file to save your directories to"
msgstr "ディレクトリを保存するファイルを選択してください。"
#: qt\directories_dialog.py:348
msgid "dupeGuru Directories (*.dupegurudirs)"
msgstr "dupeGuruのディレクトリファイル (*.dupegurudirs)"
#: qt\exclude_list_dialog.py:44
msgid "Add"
msgstr "追加"
#: qt\exclude_list_dialog.py:46
msgid "Restore defaults"
msgstr "デフォルトに戻す"
#: qt\exclude_list_dialog.py:47
msgid "Test string"
msgstr "テスト文字列"
#: qt\exclude_list_dialog.py:83
msgid "Type a python regular expression here..."
msgstr "ここではPythonの正規表現を入力して..."
#: qt\exclude_list_dialog.py:85
msgid "Type a file system path or filename here..."
msgstr "ここにファイルシステムのパスまたはファイル名を入力してください..."
#: qt\exclude_list_dialog.py:152
msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happen to match one of the regular expressions.<br>For each file collected two tests are perfomed on each of them to determine whether or not to filter them out:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with no path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the test string feature by pasting a fake path in it:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
"これらの大文字と小文字を区別するPython正規表現は、スキャン中にファイルを除外します。 <br>ディレクターの名前が正規表現の1つと一致する場合、ディレクトリの<strong>デフォルト状態</strong>は[ディレクトリ]タブで[除外]に設定されます。 <br>収集されたファイルごとに、2つのテストがそれぞれに対して実行され、それらをフィルターで除外するかどうかが決定されます:<br><li>1.パス区切り文字が含まれていない正規表現は、ファイル名のみと比較されます。</li>\n"
"<li>2.パス区切り文字が含まれていない正規表現は、ファイルへのフルパスと比較されます。</li>\n"
"例「My Pictures」ディレクトリからのみ.PNGファイルを除外する場合<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>偽のパスを貼り付けることで、テスト文字列機能を使用して正規表現をテストできます:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"一致する正規表現が強調表示されます。<br>ハイライトが少なくとも1つある場合、テストされたパスはスキャン中に無視されます。<br><br>ピリオド「。」で始まるディレクトリとファイル デフォルトでは除外されます。<br><br>"
#: qt\exclude_list_table.py:36
msgid "Compilation error: "
msgstr "コンパイルエラー:"
#: qt\pe\image_viewer.py:56
msgid "Increase zoom"
msgstr "ズーム増やす"
#: qt\pe\image_viewer.py:66
msgid "Decrease zoom"
msgstr "ズームを小さく"
#: qt\pe\image_viewer.py:71
msgid "Ctrl+/"
msgstr "Ctrl+/"
#: qt\pe\image_viewer.py:76
msgid "Normal size"
msgstr "通常サイズ"
#: qt\pe\image_viewer.py:81
msgid "Ctrl+*"
msgstr "Ctrl+*"
#: qt\pe\image_viewer.py:86
msgid "Best fit"
msgstr "最適"
#: qt\pe\preferences_dialog.py:49
msgid "Picture cache mode:"
msgstr "画像キャッシュモード:"
#: qt\pe\preferences_dialog.py:56
msgid "Override theme icons in viewer toolbar"
msgstr "ビューアツールバーのテーマアイコンを上書きする"
#: qt\pe\preferences_dialog.py:58
msgid ""
"Use our own internal icons instead of those provided by the theme engine"
msgstr "テーマエンジンによって提供されるアイコンの代わりに、独自の内部アイコンを使用します。"
#: qt\pe\preferences_dialog.py:66
msgid "Show scrollbars in image viewers"
msgstr "画像ビューアにスクロールバーを表示する"
#: qt\pe\preferences_dialog.py:68
msgid ""
"When the image displayed doesn't fit the viewport, show scrollbars to span "
"the view around"
msgstr "表示された画像がビューポートに適合しない場合に、ビュー全体にスクロールバーを表示する。"
#: qt\preferences_dialog.py:156
msgid "Use default position for tab bar (requires restart)"
msgstr "タブバーのデフォルトの位置を使用する(再起動が必要)"
#: qt\preferences_dialog.py:158
msgid ""
"Place the tab bar below the main menu instead of next to it\n"
"On MacOS, the tab bar will fill up the window's width instead."
msgstr ""
"タブバーをメインメニューの横ではなく下に配置する。\n"
"MacOSでは、代わりにタブバーがウィンドウの幅を埋める。"
#: qt\preferences_dialog.py:172
msgid "Use bold font for references"
msgstr "参照のために太字を使用する"
#: qt\preferences_dialog.py:176
msgid "Reference foreground color:"
msgstr "参照の前景色:"
#: qt\preferences_dialog.py:179
msgid "Reference background color:"
msgstr "参照の背景色:"
#: qt\preferences_dialog.py:182 qt\preferences_dialog.py:216
msgid "Delta foreground color:"
msgstr "デルタ値の背景色:"
#: qt\preferences_dialog.py:195
msgid "Show the title bar and can be docked"
msgstr "タイトルバーを表示し、ドッキングできます。"
#: qt\preferences_dialog.py:197
msgid ""
"While the title bar is hidden, use the modifier key to drag the floating "
"window around"
msgstr "タイトルバーが非表示になっているときに、修飾キーを使用してフローティングウィンドウをドラッグできます。"
#: qt\preferences_dialog.py:199
msgid "The title bar can only be disabled while the window is docked"
msgstr "タイトルバーは、ウィンドウがドッキングされている間のみ無効にできます。"
#: qt\preferences_dialog.py:202
msgid "Vertical title bar"
msgstr "垂直タイトルバー"
#: qt\preferences_dialog.py:204
msgid ""
"Change the title bar from horizontal on top, to vertical on the left side"
msgstr "タイトルバーを上部の水平から左側の垂直に変更する"
#: qt\tabbed_window.py:44
msgid "Show tab bar"
msgstr "タブバーを表示"
#: qt\exclude_list_dialog.py:152
msgid ""
"These (case sensitive) python regular expressions will filter out files during scans.<br>Directores will also have their <strong>default state</strong> set to Excluded in the Directories tab if their name happens to match one of the selected regular expressions.<br>For each file collected, two tests are performed to determine whether or not to completely ignore it:<br><li>1. Regular expressions with no path separator in them will be compared to the file name only.</li>\n"
"<li>2. Regular expressions with at least one path separator in them will be compared to the full path to the file.</li><br>\n"
"Example: if you want to filter out .PNG files from the \"My Pictures\" directory only:<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>You can test the regular expression with the \"test string\" button after pasting a fake path in the test field:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"Matching regular expressions will be highlighted.<br>If there is at least one highlight, the path or filename tested will be ignored during scans.<br><br>Directories and files starting with a period '.' are filtered out by default.<br><br>"
msgstr ""
"これらの大文字と小文字を区別するPython正規表現は、スキャン中にファイルを除外します。 <br>また、ディレクトリの名前が選択した正規表現の1つと一致する場合、ディレクトリの<strong>デフォルト状態</strong>は[ディレクトリ]タブで「除外」に設定されます。<br>収集された各ファイルのために、二つの試験は完全にそれを無視するか否かを決定するために実行される:<br><li>1.パス区切り文字が含まれていない正規表現は、ファイル名のみと比較されます。</li>\n"
"<li>2.少なくとも1つのパス区切り文字を含む正規表現は、ファイルへのフルパスと比較されます。</li>\n"
"<br>例「My Pictures」ディレクトリからのみ.PNGファイルを除外する場合<br><code>.*My\\sPictures\\\\.*\\.png</code><br><br>テストフィールドに偽のパスを貼り付けた後、[テスト文字列]ボタンを使用して正規表現をテストできます:<br><code>C:\\\\User\\My Pictures\\test.png</code><br><br>\n"
"一致する正規表現が強調表示されます。<br>ハイライトが少なくとも1つある場合、テストされたパスまたはファイル名はスキャン中に無視されます。<br><br>ピリオド「.」で始まるディレクトリとファイル デフォルトでは除外されます。<br><br>"
#: qt\app.py:256
msgid "Results"
msgstr "結果"
#: qt\preferences_dialog.py:150
msgid "General Interface"
msgstr "一般的なインターフェイス"
#: qt\preferences_dialog.py:176
msgid "Result Table"
msgstr "結果表"
#: qt\preferences_dialog.py:205
msgid "Details Window"
msgstr "詳細ウィンドウ"
#: qt\preferences_dialog.py:285
msgid "General"
msgstr "一般"
#: qt\preferences_dialog.py:286
msgid "Display"
msgstr "表示"

View File

@@ -1,123 +1,122 @@
# Translators: # Translators:
# woosuk park <bjh13579@gmail.com>, 2015 # Andrew Senetar <arsenetar@gmail.com>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Andrew Senetar <arsenetar@gmail.com>, 2021\n"
"PO-Revision-Date: 2015-01-24 07:43+0000\n" "Language-Team: Korean (https://www.transifex.com/voltaicideas/teams/116153/ko/)\n"
"Last-Translator: woosuk park <bjh13579@gmail.com>\n" "Language: ko\n"
"Language-Team: Korean (http://www.transifex.com/projects/p/dupeguru/language/ko/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: ko\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
#: core/gui/ignore_list_table.py:18 core/gui/ignore_list_table.py:19 #: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core/gui/problem_table.py:17 #: core\gui\problem_table.py:18
msgid "File Path" msgid "File Path"
msgstr "파일 경로" msgstr "파일 경로"
#: core/gui/problem_table.py:18 #: core\gui\problem_table.py:19
msgid "Error Message" msgid "Error Message"
msgstr "에러 메시지" msgstr "에러 메시지"
#: core/me/result_table.py:24 core/pe/result_table.py:21 core/prioritize.py:63 #: core\me\prioritize.py:23
#: core/se/result_table.py:21
msgid "Kind"
msgstr "종류"
#: core/me/result_table.py:19 core/pe/result_table.py:19 core/prioritize.py:72
#: core/se/result_table.py:19
msgid "Folder"
msgstr "폴더"
#: core/me/result_table.py:18 core/pe/result_table.py:18 core/prioritize.py:88
#: core/se/result_table.py:18
msgid "Filename"
msgstr "폴더명"
#: core/prioritize.py:147
msgid "Size"
msgstr "크기"
#: core/me/result_table.py:25 core/pe/result_table.py:24
#: core/prioritize.py:153 core/se/result_table.py:22
msgid "Modification"
msgstr "수정날짜"
#: core/me/prioritize.py:18
msgid "Duration" msgid "Duration"
msgstr "길이" msgstr "길이"
#: core/me/prioritize.py:24 core/me/result_table.py:22 #: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate" msgid "Bitrate"
msgstr "비트레이트" msgstr "비트레이트"
#: core/me/prioritize.py:30 #: core\me\prioritize.py:37
msgid "Samplerate" msgid "Samplerate"
msgstr "샘플레이트" msgstr "샘플레이트"
#: core/me/result_table.py:20 #: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
#: core\se\result_table.py:19
msgid "Filename"
msgstr "폴더명"
#: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core\se\result_table.py:20
msgid "Folder"
msgstr "폴더"
#: core\me\result_table.py:21
msgid "Size (MB)" msgid "Size (MB)"
msgstr "크기 (MB)" msgstr "크기 (MB)"
#: core/me/result_table.py:21 #: core\me\result_table.py:22
msgid "Time" msgid "Time"
msgstr "시간" msgstr "시간"
#: core/me/result_table.py:23 #: core\me\result_table.py:24
msgid "Sample Rate" msgid "Sample Rate"
msgstr "샘플레이트" msgstr "샘플레이트"
#: core/me/result_table.py:26 #: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core\se\result_table.py:22
msgid "Kind"
msgstr "종류"
#: core\me\result_table.py:26 core\pe\result_table.py:25
#: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification"
msgstr "수정날짜"
#: core\me\result_table.py:27
msgid "Title" msgid "Title"
msgstr "곡명" msgstr "곡명"
#: core/me/result_table.py:27 #: core\me\result_table.py:28
msgid "Artist" msgid "Artist"
msgstr "아티스트" msgstr "아티스트"
#: core/me/result_table.py:28 #: core\me\result_table.py:29
msgid "Album" msgid "Album"
msgstr "앨범" msgstr "앨범"
#: core/me/result_table.py:29 #: core\me\result_table.py:30
msgid "Genre" msgid "Genre"
msgstr "장르" msgstr "장르"
#: core/me/result_table.py:30 #: core\me\result_table.py:31
msgid "Year" msgid "Year"
msgstr "년도" msgstr "년도"
#: core/me/result_table.py:31 #: core\me\result_table.py:32
msgid "Track Number" msgid "Track Number"
msgstr "트랙 번호" msgstr "트랙 번호"
#: core/me/result_table.py:32 #: core\me\result_table.py:33
msgid "Comment" msgid "Comment"
msgstr "주석" msgstr "주석"
#: core/me/result_table.py:33 core/pe/result_table.py:25 #: core\me\result_table.py:34 core\pe\result_table.py:26
#: core/se/result_table.py:23 #: core\se\result_table.py:24
msgid "Match %" msgid "Match %"
msgstr "일치정도" msgstr "일치정도"
#: core/me/result_table.py:34 core/se/result_table.py:24 #: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used" msgid "Words Used"
msgstr "사용된 단어수" msgstr "사용된 단어수"
#: core/me/result_table.py:35 core/pe/result_table.py:26 #: core\me\result_table.py:36 core\pe\result_table.py:27
#: core/se/result_table.py:25 #: core\se\result_table.py:26
msgid "Dupe Count" msgid "Dupe Count"
msgstr "중복파일 갯수" msgstr "중복파일 갯수"
#: core/pe/prioritize.py:18 core/pe/result_table.py:22 #: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions" msgid "Dimensions"
msgstr "치수" msgstr "치수"
#: core/pe/result_table.py:20 core/se/result_table.py:20 #: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)" msgid "Size (KB)"
msgstr "크기 (KB)" msgstr "크기 (KB)"
#: core/pe/result_table.py:23 #: core\pe\result_table.py:24
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "EXIF 타임스태프" msgstr "EXIF 타임스태프"
#: core\prioritize.py:156
msgid "Size"
msgstr "크기"

View File

@@ -1,265 +1,250 @@
# Translators: # Translators:
# woosuk park <bjh13579@gmail.com>, 2015 # Andrew Senetar <arsenetar@gmail.com>, 2021
# Fuan <jcfrt@posteo.net>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Fuan <jcfrt@posteo.net>, 2021\n"
"PO-Revision-Date: 2015-01-24 07:38+0000\n" "Language-Team: Korean (https://www.transifex.com/voltaicideas/teams/116153/ko/)\n"
"Last-Translator: woosuk park <bjh13579@gmail.com>\n" "Language: ko\n"
"Language-Team: Korean (http://www.transifex.com/projects/p/dupeguru/language/ko/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: ko\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
#: core/app.py:40 #: core\app.py:42
msgid "There are no marked duplicates. Nothing has been done." msgid "There are no marked duplicates. Nothing has been done."
msgstr "" msgstr "표시된 중복 항목이 없습니다. 아무것도하지 않았습니다."
#: core/app.py:41 #: core\app.py:43
msgid "There are no selected duplicates. Nothing has been done." msgid "There are no selected duplicates. Nothing has been done."
msgstr "" msgstr "선택한 중복 항목이 없습니다. 아무것도하지 않았습니다."
#: core/app.py:42 #: core\app.py:44
msgid "" msgid ""
"You're about to open many files at once. Depending on what those files are " "You're about to open many files at once. Depending on what those files are "
"opened with, doing so can create quite a mess. Continue?" "opened with, doing so can create quite a mess. Continue?"
msgstr "" msgstr "한 번에 많은 파일을 열려고합니다. 그 파일을 여는 것에 따라 그렇게하면 꽤 엉망이 될 수 있습니다. 계속하다?"
#: core/app.py:65 #: core\app.py:71
msgid "Scanning for duplicates" msgid "Scanning for duplicates"
msgstr "" msgstr "중복 검색"
#: core/app.py:66 #: core\app.py:72
msgid "Loading" msgid "Loading"
msgstr "불러오는중" msgstr "불러오는중"
#: core/app.py:67 #: core\app.py:73
msgid "Moving" msgid "Moving"
msgstr "이동중" msgstr "이동중"
#: core/app.py:68 #: core\app.py:74
msgid "Copying" msgid "Copying"
msgstr "복사중" msgstr "복사중"
#: core/app.py:69 #: core\app.py:75
msgid "Sending to Trash" msgid "Sending to Trash"
msgstr "휴지통으로 보내기" msgstr "휴지통으로 보내기"
#: core/app.py:279 #: core\app.py:308
msgid "" msgid ""
"A previous action is still hanging in there. You can't start a new one yet. " "A previous action is still hanging in there. You can't start a new one yet. "
"Wait a few seconds, then try again." "Wait a few seconds, then try again."
msgstr "" msgstr "이전 작업이 여전히 거기에 걸려 있습니다. 아직 새로운 것을 시작할 수 없습니다. 몇 초 후에 다시 시도하십시오."
#: core/app.py:289 #: core\app.py:318
msgid "No duplicates found." msgid "No duplicates found."
msgstr "중복 파일이 없습니다." msgstr "중복 파일이 없습니다."
#: core/app.py:304 #: core\app.py:333
msgid "All marked files were copied successfully." msgid "All marked files were copied successfully."
msgstr "" msgstr "표시된 모든 파일이 성공적으로 복사되었습니다."
#: core/app.py:305 #: core\app.py:334
msgid "All marked files were moved successfully." msgid "All marked files were moved successfully."
msgstr "" msgstr "표시된 모든 파일이 성공적으로 이동되었습니다."
#: core/app.py:306 #: core\app.py:335
msgid "All marked files were successfully sent to Trash." msgid "All marked files were successfully sent to Trash."
msgstr "" msgstr "표시된 모든 파일이 성공적으로 휴지통으로 전송되었습니다."
#: core/app.py:368 #: core\app.py:343
msgid "Could not load file: {}"
msgstr "파일을로드 할 수 없습니다 : {}"
#: core\app.py:399
msgid "'{}' already is in the list." msgid "'{}' already is in the list."
msgstr "'{}' 는 이미 목록에 있습니다." msgstr "'{}' 는 이미 목록에 있습니다."
#: core/app.py:370 #: core\app.py:401
msgid "'{}' does not exist." msgid "'{}' does not exist."
msgstr "'{}' 가 존재하지 않습니다." msgstr "'{}' 가 존재하지 않습니다."
#: core/app.py:379 #: core\app.py:410
msgid "" msgid ""
"All selected %d matches are going to be ignored in all subsequent scans. " "All selected %d matches are going to be ignored in all subsequent scans. "
"Continue?" "Continue?"
msgstr "" msgstr "선택된 %d개의 일치 항목은 모든 후속 검색에서 무시됩니다. 계속하다?"
#: core/app.py:450 #: core\app.py:486
msgid "copy" msgid "Select a directory to copy marked files to"
msgstr "복사" msgstr "표시된 파일을 복사 할 디렉토리를 선택하십시오"
#: core/app.py:450 #: core\app.py:487
msgid "move" msgid "Select a directory to move marked files to"
msgstr "이동" msgstr "표시된 파일을 이동할 디렉토리를 선택하십시오"
#: core/app.py:451 #: core\app.py:527
msgid "Select a directory to {} marked files to"
msgstr ""
#: core/app.py:490
msgid "Select a destination for your exported CSV" msgid "Select a destination for your exported CSV"
msgstr "" msgstr "내 보낸 CSV의 대상을 선택하십시오"
#: core/app.py:518 #: core\app.py:534 core\app.py:801 core\app.py:811
msgid "You have no custom command set up. Set it up in your preferences."
msgstr ""
#: core/app.py:672 core/app.py:685
msgid "You are about to remove %d files from results. Continue?"
msgstr ""
#: core/app.py:719
msgid "{} duplicate groups were changed by the re-prioritization."
msgstr ""
#: core/app.py:762
msgid "Collecting files to scan"
msgstr ""
#: core/app.py:751
msgid "The selected directories contain no scannable file."
msgstr ""
#: core/app.py:810
msgid "%s (%d discarded)"
msgstr ""
#: core/engine.py:222 core/engine.py:262
msgid "0 matches found"
msgstr ""
#: core/engine.py:240 core/engine.py:270
msgid "%d matches found"
msgstr ""
#: core/scanner.py:77
msgid "Read size of %d/%d files"
msgstr ""
#: core/gui/deletion_options.py:69
msgid "You are sending {} file(s) to the Trash."
msgstr ""
#: core/gui/ignore_list_dialog.py:24
msgid "Do you really want to remove all %d items from the ignore list?"
msgstr ""
#: core/prioritize.py:68
msgid "None"
msgstr ""
#: core/prioritize.py:96
msgid "Ends with number"
msgstr ""
#: core/prioritize.py:97
msgid "Doesn't end with number"
msgstr ""
#: core/prioritize.py:98
msgid "Longest"
msgstr ""
#: core/prioritize.py:99
msgid "Shortest"
msgstr ""
#: core/prioritize.py:132
msgid "Highest"
msgstr ""
#: core/prioritize.py:132
msgid "Lowest"
msgstr ""
#: core/prioritize.py:159
msgid "Newest"
msgstr ""
#: core/prioritize.py:159
msgid "Oldest"
msgstr ""
#: core/results.py:129
msgid "%d / %d (%s / %s) duplicates marked."
msgstr ""
#: core/results.py:136
msgid " filter: %s"
msgstr ""
#: core/scanner.py:101
msgid "Read metadata of %d/%d files"
msgstr ""
#: core/pe/matchblock.py:61
msgid "Analyzed %d/%d pictures"
msgstr ""
#: core/pe/matchblock.py:156
msgid "Performed %d/%d chunk matches"
msgstr ""
#: core/pe/matchblock.py:161
msgid "Preparing for matching"
msgstr ""
#: core/pe/matchblock.py:206
msgid "Verified %d/%d matches"
msgstr ""
#: core/pe/matchexif.py:18
msgid "Read EXIF of %d/%d pictures"
msgstr ""
#: core/app.py:312
msgid "Could not load file: {}"
msgstr ""
#: core/app.py:496 core/app.py:742
msgid "Couldn't write to file: {}" msgid "Couldn't write to file: {}"
msgstr "" msgstr "파일에 쓸 수 없습니다 : {}"
#: core/me/scanner.py:19 core/se/scanner.py:15 #: core\app.py:559
msgid "You have no custom command set up. Set it up in your preferences."
msgstr "사용자 지정 명령을 설정하지 않았습니다. 기본 설정에서 설정하십시오."
#: core\app.py:727 core\app.py:740
msgid "You are about to remove %d files from results. Continue?"
msgstr "결과에서 %d 개의 파일을 제거하려고합니다. 계속하다?"
#: core\app.py:774
msgid "{} duplicate groups were changed by the re-prioritization."
msgstr "{} 개의 중복 그룹이 우선 순위 재 지정으로 변경되었습니다."
#: core\app.py:821
msgid "The selected directories contain no scannable file."
msgstr "선택한 디렉토리에 스캔 가능한 파일이 없습니다."
#: core\app.py:835
msgid "Collecting files to scan"
msgstr "스캔 할 파일 수집"
#: core\app.py:891
msgid "%s (%d discarded)"
msgstr "%s (%d 폐기)"
#: core\engine.py:244 core\engine.py:288
msgid "0 matches found"
msgstr "일치하는 항목이 없습니다"
#: core\engine.py:262 core\engine.py:296
msgid "%d matches found"
msgstr "%d개의 일치 항목을 찾았습니다."
#: core\gui\deletion_options.py:73
msgid "You are sending {} file(s) to the Trash."
msgstr "{}개의 파일을 휴지통으로 보내고 있습니다."
#: core\gui\exclude_list_table.py:15
msgid "Regular Expressions"
msgstr "정규식"
#: core\gui\ignore_list_dialog.py:25
msgid "Do you really want to remove all %d items from the ignore list?"
msgstr "무시 목록에서 항목 %d개를 정말로 제거 하시겠습니까?"
#: core\me\scanner.py:20 core\se\scanner.py:16
msgid "Filename" msgid "Filename"
msgstr "" msgstr "파일 이름"
#: core/me/scanner.py:20 #: core\me\scanner.py:21
msgid "Filename - Fields" msgid "Filename - Fields"
msgstr "" msgstr "파일 이름 - 필드"
#: core/me/scanner.py:21 #: core\me\scanner.py:22
msgid "Filename - Fields (No Order)" msgid "Filename - Fields (No Order)"
msgstr "" msgstr "파일 이름 - 필드 (주문 없음)"
#: core/me/scanner.py:22 #: core\me\scanner.py:23
msgid "Tags" msgid "Tags"
msgstr "" msgstr "태그"
#: core/me/scanner.py:23 core/pe/scanner.py:20 core/se/scanner.py:16 #: core\me\scanner.py:24 core\pe\scanner.py:21 core\se\scanner.py:17
msgid "Contents" msgid "Contents"
msgstr "" msgstr "내용"
#: core/pe/scanner.py:21 #: core\pe\matchblock.py:72
msgid "Analyzed %d/%d pictures"
msgstr "%d/%d 사진 분석"
#: core\pe\matchblock.py:181
msgid "Performed %d/%d chunk matches"
msgstr "%d/%d 청크 매치 수행"
#: core\pe\matchblock.py:191
msgid "Preparing for matching"
msgstr "매칭 준비"
#: core\pe\matchblock.py:244
msgid "Verified %d/%d matches"
msgstr "%d/%d 일치 확인"
#: core\pe\matchexif.py:19
msgid "Read EXIF of %d/%d pictures"
msgstr "%d/%d 사진의 EXIF 읽기"
#: core\pe\scanner.py:22
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "" msgstr "EXIF 타임 스탬프"
#: core/scanner.py:139 #: core\prioritize.py:70
msgid "None"
msgstr "없음"
#: core\prioritize.py:100
msgid "Ends with number"
msgstr "숫자로 끝남"
#: core\prioritize.py:101
msgid "Doesn't end with number"
msgstr "숫자로 끝나지 않음"
#: core\prioritize.py:102
msgid "Longest"
msgstr "최장"
#: core\prioritize.py:103
msgid "Shortest"
msgstr "최단"
#: core\prioritize.py:140
msgid "Highest"
msgstr "제일 높은"
#: core\prioritize.py:140
msgid "Lowest"
msgstr "최저"
#: core\prioritize.py:169
msgid "Newest"
msgstr "최신"
#: core\prioritize.py:169
msgid "Oldest"
msgstr "가장 오래된"
#: core\results.py:142
msgid "%d / %d (%s / %s) duplicates marked."
msgstr "%d / %d (%s / %s) 개의 중복이 표시되었습니다."
#: core\results.py:149
msgid " filter: %s"
msgstr "필터: %s"
#: core\scanner.py:85
msgid "Read size of %d/%d files"
msgstr "%d/%d 개의 파일을 읽을 수 있습니다."
#: core\scanner.py:109
msgid "Read metadata of %d/%d files"
msgstr "%d/%d 개 파일의 메타 데이터를 읽었습니다."
#: core\scanner.py:147
msgid "Almost done! Fiddling with results..." msgid "Almost done! Fiddling with results..."
msgstr "" msgstr "거의 완료되었습니다! 결과를 만지작 거리는 중..."
#: core/se/scanner.py:17 #: core\se\scanner.py:18
msgid "Folders" msgid "Folders"
msgstr "" msgstr "폴더"
#~ msgid "Sending files to the recycle bin"
#~ msgstr "휴지통으로 보내기"
#~ msgid "Grouped %d/%d matches"
#~ msgstr ""
#~ msgid "Removing false matches"
#~ msgstr ""
#~ msgid "Processed %d/%d matches against the ignore list"
#~ msgstr ""
#~ msgid "Doing group prioritization"
#~ msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -1,123 +1,123 @@
# Translators: # Translators:
# Kees Duvekot, 2015 # Andrew Senetar <arsenetar@gmail.com>, 2021
# Bas <duvel3@gmail.com>, 2021
#
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dupeGuru\n" "Last-Translator: Bas <duvel3@gmail.com>, 2021\n"
"PO-Revision-Date: 2015-07-11 12:36+0000\n" "Language-Team: Dutch (https://www.transifex.com/voltaicideas/teams/116153/nl/)\n"
"Last-Translator: Kees Duvekot\n" "Language: nl\n"
"Language-Team: Dutch (http://www.transifex.com/p/dupeguru/language/nl/)\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n" "Content-Transfer-Encoding: utf-8\n"
"Language: nl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: core/gui/ignore_list_table.py:18 core/gui/ignore_list_table.py:19 #: core\gui\ignore_list_table.py:19 core\gui\ignore_list_table.py:20
#: core/gui/problem_table.py:17 #: core\gui\problem_table.py:18
msgid "File Path" msgid "File Path"
msgstr "Bestand locatie" msgstr "Bestandspad"
#: core/gui/problem_table.py:18 #: core\gui\problem_table.py:19
msgid "Error Message" msgid "Error Message"
msgstr "Fout Melding" msgstr "Foutmelding"
#: core/me/result_table.py:24 core/pe/result_table.py:21 core/prioritize.py:63 #: core\me\prioritize.py:23
#: core/se/result_table.py:21
msgid "Kind"
msgstr "Kind"
#: core/me/result_table.py:19 core/pe/result_table.py:19 core/prioritize.py:72
#: core/se/result_table.py:19
msgid "Folder"
msgstr "Folder"
#: core/me/result_table.py:18 core/pe/result_table.py:18 core/prioritize.py:88
#: core/se/result_table.py:18
msgid "Filename"
msgstr "Bestandsnaam"
#: core/prioritize.py:147
msgid "Size"
msgstr "Grote"
#: core/me/result_table.py:25 core/pe/result_table.py:24
#: core/prioritize.py:153 core/se/result_table.py:22
msgid "Modification"
msgstr "Aanpassing"
#: core/me/prioritize.py:18
msgid "Duration" msgid "Duration"
msgstr "Tijdsduur" msgstr "Tijdsduur"
#: core/me/prioritize.py:24 core/me/result_table.py:22 #: core\me\prioritize.py:30 core\me\result_table.py:23
msgid "Bitrate" msgid "Bitrate"
msgstr "Bitrate" msgstr "Bitrate"
#: core/me/prioritize.py:30 #: core\me\prioritize.py:37
msgid "Samplerate" msgid "Samplerate"
msgstr "Sample frequentie" msgstr "Sample frequentie"
#: core/me/result_table.py:20 #: core\me\result_table.py:19 core\pe\result_table.py:19 core\prioritize.py:92
msgid "Size (MB)" #: core\se\result_table.py:19
msgstr "Grote (MB)" msgid "Filename"
msgstr "Bestandsnaam"
#: core/me/result_table.py:21 #: core\me\result_table.py:20 core\pe\result_table.py:20 core\prioritize.py:75
#: core\se\result_table.py:20
msgid "Folder"
msgstr "Map"
#: core\me\result_table.py:21
msgid "Size (MB)"
msgstr "Grootte (MB)"
#: core\me\result_table.py:22
msgid "Time" msgid "Time"
msgstr "Tijd" msgstr "Tijd"
#: core/me/result_table.py:23 #: core\me\result_table.py:24
msgid "Sample Rate" msgid "Sample Rate"
msgstr "Sample Frequentie" msgstr "Sample Frequentie"
#: core/me/result_table.py:26 #: core\me\result_table.py:25 core\pe\result_table.py:22 core\prioritize.py:65
#: core\se\result_table.py:22
msgid "Kind"
msgstr "Soort"
#: core\me\result_table.py:26 core\pe\result_table.py:25
#: core\prioritize.py:163 core\se\result_table.py:23
msgid "Modification"
msgstr "Aanpassing"
#: core\me\result_table.py:27
msgid "Title" msgid "Title"
msgstr "Titel" msgstr "Titel"
#: core/me/result_table.py:27 #: core\me\result_table.py:28
msgid "Artist" msgid "Artist"
msgstr "Artiest" msgstr "Artiest"
#: core/me/result_table.py:28 #: core\me\result_table.py:29
msgid "Album" msgid "Album"
msgstr "Album" msgstr "Album"
#: core/me/result_table.py:29 #: core\me\result_table.py:30
msgid "Genre" msgid "Genre"
msgstr "Genre" msgstr "Genre"
#: core/me/result_table.py:30 #: core\me\result_table.py:31
msgid "Year" msgid "Year"
msgstr "Jaar" msgstr "Jaar"
#: core/me/result_table.py:31 #: core\me\result_table.py:32
msgid "Track Number" msgid "Track Number"
msgstr "Track nummer" msgstr "Track nummer"
#: core/me/result_table.py:32 #: core\me\result_table.py:33
msgid "Comment" msgid "Comment"
msgstr "Commentaar" msgstr "Commentaar"
#: core/me/result_table.py:33 core/pe/result_table.py:25 #: core\me\result_table.py:34 core\pe\result_table.py:26
#: core/se/result_table.py:23 #: core\se\result_table.py:24
msgid "Match %" msgid "Match %"
msgstr "Zekerheid %" msgstr "Zekerheid %"
#: core/me/result_table.py:34 core/se/result_table.py:24 #: core\me\result_table.py:35 core\se\result_table.py:25
msgid "Words Used" msgid "Words Used"
msgstr "Woorden gebruikt" msgstr "Woorden gebruikt"
#: core/me/result_table.py:35 core/pe/result_table.py:26 #: core\me\result_table.py:36 core\pe\result_table.py:27
#: core/se/result_table.py:25 #: core\se\result_table.py:26
msgid "Dupe Count" msgid "Dupe Count"
msgstr "Dubbel telling" msgstr "Dubbel telling"
#: core/pe/prioritize.py:18 core/pe/result_table.py:22 #: core\pe\prioritize.py:23 core\pe\result_table.py:23
msgid "Dimensions" msgid "Dimensions"
msgstr "Afmetingen" msgstr "Afmetingen"
#: core/pe/result_table.py:20 core/se/result_table.py:20 #: core\pe\result_table.py:21 core\se\result_table.py:21
msgid "Size (KB)" msgid "Size (KB)"
msgstr "Grote (KB)" msgstr "Grootte (KB)"
#: core/pe/result_table.py:23 #: core\pe\result_table.py:24
msgid "EXIF Timestamp" msgid "EXIF Timestamp"
msgstr "EXIF Tijdstip" msgstr "EXIF Tijdstip"
#: core\prioritize.py:156
msgid "Size"
msgstr "Grootte"

Some files were not shown because too many files have changed in this diff Show More