[#32] Internationalized the core and localized it to french.

This commit is contained in:
Virgil Dupras 2011-01-18 17:33:33 +01:00
parent 04d7880a0c
commit 42cff20710
17 changed files with 153 additions and 37 deletions

View File

@ -0,0 +1,29 @@
"Collecting files to scan" = "Collecting files to scan";
"%s (%d discarded)" = "%s (%d discarded)";
"Scanning for duplicates" = "Scanning for duplicates";
"Loading" = "Loading";
"Moving" = "Moving";
"Copying" = "Copying";
"Sending to Trash" = "Sending to Trash";
"0 matches found" = "0 matches found";
"%d matches found" = "%d matches found";
"Read size of %d/%d files" = "Read size of %d/%d files";
"Grouped %d/%d matches" = "Grouped %d/%d matches";
"%d / %d (%s / %s) duplicates marked." = "%d / %d (%s / %s) duplicates marked.";
" filter: %s" = " filter: %s";
"Read size of %d/%d files" = "Read size of %d/%d files";
"Read metadata of %d/%d files" = "Read metadata of %d/%d files";
"Removing false matches" = "Removing false matches";
"Processed %d/%d matches against the ignore list" = "Processed %d/%d matches against the ignore list";
"Doing group prioritization" = "Doing group prioritization";
"Analyzed %d/%d pictures" = "Analyzed %d/%d pictures";
"Preparing for matching" = "Preparing for matching";
"Matched %d/%d pictures" = "Matched %d/%d pictures";
"Verified %d/%d matches" = "Verified %d/%d matches";
"Removing dead tracks from your iTunes Library" = "Removing dead tracks from your iTunes Library";
"Scanning the iTunes Library" = "Scanning the iTunes Library";
"Probing iPhoto. Don't touch it during the operation!" = "Probing iPhoto. Don't touch it during the operation!";
"Sending dupes to the Trash" = "Sending dupes to the Trash";

View File

@ -0,0 +1,28 @@
"Collecting files to scan" = "Collecte des fichiers à scanner";
"%s (%d discarded)" = "%s (%d hors-groupe)";
"Scanning for duplicates" = "Scan de doublons en cours";
"Loading" = "Chargement en cours";
"Moving" = "Déplacement en cours";
"Copying" = "Copie en cours";
"Sending to Trash" = "Envoi vers corbeille";
"0 matches found" = "0 paires trouvées";
"%d matches found" = "%d paires trouvées";
"Read size of %d/%d files" = "Lu la taille de %d/%d fichiers";
"Grouped %d/%d matches" = "%d/%d paires groupées";
"%d / %d (%s / %s) duplicates marked." = "%d / %d (%s / %s) doublons marqués.";
" filter: %s" = " filtre: %s";
"Read metadata of %d/%d files" = "Lu les métadonnées de %d/%d fichiers";
"Removing false matches" = "Retrait des paires invalides";
"Processed %d/%d matches against the ignore list" = "Vérification de %d/%d paires dans la ignore list";
"Doing group prioritization" = "Prioritization des groupes";
"Analyzed %d/%d pictures" = "Analyzé %d/%d images";
"Preparing for matching" = "Préparation pour la comparaison";
"Matched %d/%d pictures" = "Comparé %d/%d images";
"Verified %d/%d matches" = "Vérifié %d/%d paires";
"Removing dead tracks from your iTunes Library" = "Retrait des tracks mortes de votre librairie iTunes";
"Scanning the iTunes Library" = "Scan de la librairie iTunes en cours";
"Probing iPhoto. Don't touch it during the operation!" = "Communication avec iPhoto en cours. N'y touchez pas!";
"Sending dupes to the Trash" = "Envoi de doublons à la corbeille en cours";

View File

@ -4,6 +4,9 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
from hscommon.trans import install_cocoa_trans
install_cocoa_trans()
from hscommon.cocoa import signature
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel

View File

@ -45,6 +45,7 @@
CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; };
CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9A09914ADF003581CE /* ResultWindow.m */; };
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */ = {isa = PBXBuildFile; fileRef = CE381CF509915304003581CE /* dg_cocoa.plugin */; };
CE45274F12E5F62D00005A15 /* core.strings in Resources */ = {isa = PBXBuildFile; fileRef = CE45274D12E5F62D00005A15 /* core.strings */; };
CE49DEF60FDFEB810098617B /* BRSingleLineFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = CE49DEF30FDFEB810098617B /* BRSingleLineFormatter.m */; };
CE4B59C81119919700C06C9E /* ErrorReportWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE4B59C51119919700C06C9E /* ErrorReportWindow.xib */; };
CE4B59C91119919700C06C9E /* progress.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE4B59C61119919700C06C9E /* progress.xib */; };
@ -142,6 +143,8 @@
CE381C9A09914ADF003581CE /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = SOURCE_ROOT; };
CE381C9B09914ADF003581CE /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = SOURCE_ROOT; };
CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dg_cocoa.plugin; sourceTree = SOURCE_ROOT; };
CE45274E12E5F62D00005A15 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = ../base/en.lproj/core.strings; sourceTree = SOURCE_ROOT; };
CE45275012E5F63900005A15 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = ../base/fr.lproj/core.strings; sourceTree = SOURCE_ROOT; };
CE49DEF20FDFEB810098617B /* BRSingleLineFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BRSingleLineFormatter.h; path = ../../cocoalib/brsinglelineformatter/BRSingleLineFormatter.h; sourceTree = SOURCE_ROOT; };
CE49DEF30FDFEB810098617B /* BRSingleLineFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BRSingleLineFormatter.m; path = ../../cocoalib/brsinglelineformatter/BRSingleLineFormatter.m; sourceTree = SOURCE_ROOT; };
CE4B59C51119919700C06C9E /* ErrorReportWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ErrorReportWindow.xib; sourceTree = "<group>"; };
@ -270,6 +273,7 @@
CE05330C12E5D3D70029EF25 /* xib */,
CEEB135109C837A2004D2330 /* dupeguru.icns */,
CE05332D12E5D6100029EF25 /* Localizable.strings */,
CE45274D12E5F62D00005A15 /* core.strings */,
8D1107310486CEB800E47090 /* Info.plist */,
CE6E0E9E1054EB97008D9390 /* dsa_pub.pem */,
);
@ -503,6 +507,7 @@
CE05331B12E5D3ED0029EF25 /* ResultWindow.xib in Resources */,
CE05332312E5D4100029EF25 /* Preferences.xib in Resources */,
CE05332F12E5D6100029EF25 /* Localizable.strings in Resources */,
CE45274F12E5F62D00005A15 /* core.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -612,6 +617,15 @@
name = Localizable.strings;
sourceTree = "<group>";
};
CE45274D12E5F62D00005A15 /* core.strings */ = {
isa = PBXVariantGroup;
children = (
CE45274E12E5F62D00005A15 /* en */,
CE45275012E5F63900005A15 /* fr */,
);
name = core.strings;
sourceTree = SOURCE_ROOT;
};
CE74A12512537F2E008A8DF0 /* FairwareReminder.xib */ = {
isa = PBXVariantGroup;
children = (

View File

@ -4,6 +4,9 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
from hscommon.trans import install_cocoa_trans
install_cocoa_trans()
from core.app_cocoa_inter import PyDupeGuruBase, PyDetailsPanel
from core_pe import app_cocoa as app_pe_cocoa

View File

@ -26,6 +26,7 @@
CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; };
CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9A09914ADF003581CE /* ResultWindow.m */; };
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */ = {isa = PBXBuildFile; fileRef = CE381CF509915304003581CE /* dg_cocoa.plugin */; };
CE4527AC12E5F6E700005A15 /* core.strings in Resources */ = {isa = PBXBuildFile; fileRef = CE4527AA12E5F6E700005A15 /* core.strings */; };
CE60180812DF3EA900236FDC /* HSRecentFiles.m in Sources */ = {isa = PBXBuildFile; fileRef = CE60180712DF3EA900236FDC /* HSRecentFiles.m */; };
CE6044EC0FE6796200B71262 /* DetailsPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6044EB0FE6796200B71262 /* DetailsPanel.m */; };
CE68EE6809ABC48000971085 /* DirectoryPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = CE68EE6609ABC48000971085 /* DirectoryPanel.m */; };
@ -119,6 +120,8 @@
CE381C9A09914ADF003581CE /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = SOURCE_ROOT; };
CE381C9B09914ADF003581CE /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = SOURCE_ROOT; };
CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dg_cocoa.plugin; sourceTree = SOURCE_ROOT; };
CE4527AB12E5F6E700005A15 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = ../base/en.lproj/core.strings; sourceTree = SOURCE_ROOT; };
CE4527B012E5F72600005A15 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = ../base/fr.lproj/core.strings; sourceTree = SOURCE_ROOT; };
CE60180612DF3EA900236FDC /* HSRecentFiles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HSRecentFiles.h; path = ../../cocoalib/HSRecentFiles.h; sourceTree = SOURCE_ROOT; };
CE60180712DF3EA900236FDC /* HSRecentFiles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HSRecentFiles.m; path = ../../cocoalib/HSRecentFiles.m; sourceTree = SOURCE_ROOT; };
CE6044EA0FE6796200B71262 /* DetailsPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetailsPanel.h; path = ../base/DetailsPanel.h; sourceTree = SOURCE_ROOT; };
@ -272,6 +275,7 @@
CEEB135109C837A2004D2330 /* dupeguru.icns */,
8D1107310486CEB800E47090 /* Info.plist */,
CE0533A912E5DA6A0029EF25 /* Localizable.strings */,
CE4527AA12E5F6E700005A15 /* core.strings */,
CE6E0F3C1054EC62008D9390 /* dsa_pub.pem */,
);
name = Resources;
@ -507,6 +511,7 @@
CE0533A712E5DA4D0029EF25 /* DetailsPanel.xib in Resources */,
CE0533A812E5DA4D0029EF25 /* Preferences.xib in Resources */,
CE0533AB12E5DA6A0029EF25 /* Localizable.strings in Resources */,
CE4527AC12E5F6E700005A15 /* core.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -629,6 +634,15 @@
path = ../../cocoalib/xib;
sourceTree = SOURCE_ROOT;
};
CE4527AA12E5F6E700005A15 /* core.strings */ = {
isa = PBXVariantGroup;
children = (
CE4527AB12E5F6E700005A15 /* en */,
CE4527B012E5F72600005A15 /* fr */,
);
name = core.strings;
sourceTree = SOURCE_ROOT;
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */

View File

@ -4,6 +4,9 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
from hscommon.trans import install_cocoa_trans
install_cocoa_trans()
from hscommon.cocoa import signature
from core.scanner import ScanType

View File

@ -17,6 +17,7 @@
CE381C9609914ACE003581CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9409914ACE003581CE /* AppDelegate.m */; };
CE381C9C09914ADF003581CE /* ResultWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CE381C9A09914ADF003581CE /* ResultWindow.m */; };
CE381D0509915304003581CE /* dg_cocoa.plugin in Resources */ = {isa = PBXBuildFile; fileRef = CE381CF509915304003581CE /* dg_cocoa.plugin */; };
CE4526F212E5F55F00005A15 /* core.strings in Resources */ = {isa = PBXBuildFile; fileRef = CE4526F012E5F55F00005A15 /* core.strings */; };
CE45579B0AE3BC2B005A9546 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE45579A0AE3BC2B005A9546 /* Sparkle.framework */; };
CE4557B40AE3BC50005A9546 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CE45579A0AE3BC2B005A9546 /* Sparkle.framework */; };
CE647E571173024A006D28BA /* ProblemDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CE647E551173024A006D28BA /* ProblemDialog.m */; };
@ -90,6 +91,8 @@
CE381C9A09914ADF003581CE /* ResultWindow.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = ResultWindow.m; sourceTree = SOURCE_ROOT; };
CE381C9B09914ADF003581CE /* ResultWindow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = ResultWindow.h; sourceTree = SOURCE_ROOT; };
CE381CF509915304003581CE /* dg_cocoa.plugin */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dg_cocoa.plugin; sourceTree = SOURCE_ROOT; };
CE4526F112E5F55F00005A15 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = ../base/en.lproj/core.strings; sourceTree = SOURCE_ROOT; };
CE4526F312E5F57000005A15 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = ../base/fr.lproj/core.strings; sourceTree = SOURCE_ROOT; };
CE45579A0AE3BC2B005A9546 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = /Library/Frameworks/Sparkle.framework; sourceTree = "<absolute>"; };
CE647E541173024A006D28BA /* ProblemDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProblemDialog.h; path = ../base/ProblemDialog.h; sourceTree = SOURCE_ROOT; };
CE647E551173024A006D28BA /* ProblemDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProblemDialog.m; path = ../base/ProblemDialog.m; sourceTree = SOURCE_ROOT; };
@ -249,6 +252,7 @@
CEEB135109C837A2004D2330 /* dupeguru.icns */,
8D1107310486CEB800E47090 /* Info.plist */,
CE8113E912E5CE9A00A36C80 /* Localizable.strings */,
CE4526F012E5F55F00005A15 /* core.strings */,
CE6E0DFD1054E9EF008D9390 /* dsa_pub.pem */,
);
name = Resources;
@ -482,6 +486,7 @@
CE81135012E5CE4D00A36C80 /* ResultWindow.xib in Resources */,
CE81135812E5CE6D00A36C80 /* Preferences.xib in Resources */,
CE8113EB12E5CE9A00A36C80 /* Localizable.strings in Resources */,
CE4526F212E5F55F00005A15 /* core.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -527,6 +532,15 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
CE4526F012E5F55F00005A15 /* core.strings */ = {
isa = PBXVariantGroup;
children = (
CE4526F112E5F55F00005A15 /* en */,
CE4526F312E5F57000005A15 /* fr */,
);
name = core.strings;
sourceTree = SOURCE_ROOT;
};
CE79638412536C94008D405B /* FairwareReminder.xib */ = {
isa = PBXVariantGroup;
children = (

View File

@ -290,7 +290,7 @@
<reference key="NSControlView" ref="637819333"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<object class="NSCustomResource" key="NSNormalImage" id="466498619">
<object class="NSCustomResource" key="NSNormalImage" id="751058253">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">NSSwitch</string>
</object>
@ -317,7 +317,7 @@
<reference key="NSControlView" ref="1067721243"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSNormalImage" ref="466498619"/>
<reference key="NSNormalImage" ref="751058253"/>
<reference key="NSAlternateImage" ref="589920880"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
@ -339,7 +339,7 @@
<reference key="NSControlView" ref="290008886"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSNormalImage" ref="466498619"/>
<reference key="NSNormalImage" ref="751058253"/>
<reference key="NSAlternateImage" ref="589920880"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
@ -361,7 +361,7 @@
<reference key="NSControlView" ref="551239185"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSNormalImage" ref="466498619"/>
<reference key="NSNormalImage" ref="751058253"/>
<reference key="NSAlternateImage" ref="589920880"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
@ -383,7 +383,7 @@
<reference key="NSControlView" ref="208488736"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSNormalImage" ref="466498619"/>
<reference key="NSNormalImage" ref="751058253"/>
<reference key="NSAlternateImage" ref="589920880"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
@ -405,7 +405,7 @@
<reference key="NSControlView" ref="427690895"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSNormalImage" ref="466498619"/>
<reference key="NSNormalImage" ref="751058253"/>
<reference key="NSAlternateImage" ref="589920880"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
@ -621,7 +621,7 @@
<reference key="NSControlView" ref="724127338"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSNormalImage" ref="466498619"/>
<reference key="NSNormalImage" ref="751058253"/>
<reference key="NSAlternateImage" ref="589920880"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
@ -643,7 +643,7 @@
<reference key="NSControlView" ref="647216699"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSNormalImage" ref="466498619"/>
<reference key="NSNormalImage" ref="751058253"/>
<reference key="NSAlternateImage" ref="589920880"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>

View File

@ -19,6 +19,7 @@ from hscommon.notify import Broadcaster
from hscommon.path import Path
from hscommon.conflict import smart_move, smart_copy
from hscommon.util import delete_if_empty, first, escape
from hscommon.trans import tr
from . import directories, results, scanner, export, fs
@ -328,7 +329,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
def start_scanning(self):
def do(j):
j.set_progress(0, 'Collecting files to scan')
j.set_progress(0, tr("Collecting files to scan"))
files = list(self.directories.get_files())
if self.options['ignore_hardlink_matches']:
files = self._remove_hardlink_dupes(files)
@ -354,6 +355,6 @@ class DupeGuru(RegistrableApplication, Broadcaster):
def stat_line(self):
result = self.results.stat_line
if self.scanner.discarded_file_count:
result = '%s (%d discarded)' % (result, self.scanner.discarded_file_count)
result = tr("%s (%d discarded)") % (result, self.scanner.discarded_file_count)
return result

View File

@ -15,15 +15,16 @@ from hscommon.cocoa import install_exception_hook
from hscommon.cocoa.objcmin import (NSNotificationCenter, NSUserDefaults,
NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask,
NSWorkspace)
from hscommon.trans import tr
from . import app
JOBID2TITLE = {
app.JOB_SCAN: "Scanning for duplicates",
app.JOB_LOAD: "Loading",
app.JOB_MOVE: "Moving",
app.JOB_COPY: "Copying",
app.JOB_DELETE: "Sending to Trash",
app.JOB_SCAN: tr("Scanning for duplicates"),
app.JOB_LOAD: tr("Loading"),
app.JOB_MOVE: tr("Moving"),
app.JOB_COPY: tr("Copying"),
app.JOB_DELETE: tr("Sending to Trash"),
}
class DupeGuru(app.DupeGuru):

View File

@ -6,7 +6,6 @@
# which should be included with this package. The terms are also available at
# http://www.hardcoded.net/licenses/bsd_license
import difflib
import itertools
import logging
@ -15,6 +14,7 @@ from collections import defaultdict, namedtuple
from unicodedata import normalize
from hscommon.util import flatten, multi_replace
from hscommon.trans import tr
from jobprogress import job
(WEIGHT_WORDS,
@ -25,6 +25,7 @@ JOB_REFRESH_RATE = 100
def getwords(s):
if isinstance(s, str):
# XXX is this really needed?
s = normalize('NFD', s)
s = multi_replace(s, "-_&+():;\\[]{}.,<>/?~!@#$*", ' ').lower()
s = ''.join(c for c in s if c in string.ascii_letters + string.digits + string.whitespace)
@ -175,7 +176,7 @@ def getmatches(objects, min_match_percentage=0, match_similar_words=False, weigh
match_flags.append(MATCH_SIMILAR_WORDS)
if no_field_order:
match_flags.append(NO_FIELD_ORDER)
j.start_job(len(word_dict), '0 matches found')
j.start_job(len(word_dict), tr("0 matches found"))
compared = defaultdict(set)
result = []
try:
@ -193,7 +194,7 @@ def getmatches(objects, min_match_percentage=0, match_similar_words=False, weigh
result.append(m)
if len(result) >= LIMIT:
return result
j.add_progress(desc='%d matches found' % len(result))
j.add_progress(desc=tr("%d matches found") % len(result))
except MemoryError:
# 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.
@ -205,14 +206,14 @@ def getmatches(objects, min_match_percentage=0, match_similar_words=False, weigh
def getmatches_by_contents(files, sizeattr='size', partial=False, j=job.nulljob):
j = j.start_subjob([2, 8])
size2files = defaultdict(set)
for file in j.iter_with_progress(files, 'Read size of %d/%d files'):
for file in j.iter_with_progress(files, tr("Read size of %d/%d files")):
filesize = getattr(file, sizeattr)
if filesize:
size2files[filesize].add(file)
possible_matches = [files for files in size2files.values() if len(files) > 1]
del size2files
result = []
j.start_job(len(possible_matches), '0 matches found')
j.start_job(len(possible_matches), tr("0 matches found"))
for group in possible_matches:
for first, second in itertools.combinations(group, 2):
if first.is_ref and second.is_ref:
@ -220,7 +221,7 @@ def getmatches_by_contents(files, sizeattr='size', partial=False, j=job.nulljob)
if first.md5partial == second.md5partial:
if partial or first.md5 == second.md5:
result.append(Match(first, second, 100))
j.add_progress(desc='%d matches found' % len(result))
j.add_progress(desc=tr("%d matches found") % len(result))
return result
class Group(object):
@ -349,7 +350,7 @@ def get_groups(matches, j=job.nulljob):
dupe2group = {}
groups = []
try:
for match in j.iter_with_progress(matches, 'Grouped %d/%d matches', JOB_REFRESH_RATE):
for match in j.iter_with_progress(matches, tr("Grouped %d/%d matches"), JOB_REFRESH_RATE):
first, second, _ = match
first_group = dupe2group.get(first)
second_group = dupe2group.get(second)

View File

@ -14,6 +14,7 @@ from . import engine
from jobprogress.job import nulljob
from hscommon.markable import Markable
from hscommon.util import flatten, nonone, FileOrPath, format_size
from hscommon.trans import tr
class Results(Markable):
#---Override
@ -87,14 +88,14 @@ class Results(Markable):
total_size = sum(dupe.size for dupe in self.__filtered_dupes if self.is_markable(dupe))
if self.mark_inverted:
marked_size = self.__total_size - marked_size
result = '%d / %d (%s / %s) duplicates marked.' % (
result = tr("%d / %d (%s / %s) duplicates marked.") % (
mark_count,
total_count,
format_size(marked_size, 2),
format_size(total_size, 2),
)
if self.__filters:
result += ' filter: %s' % ' --> '.join(self.__filters)
result += tr(" filter: %s") % ' --> '.join(self.__filters)
return result
def __recalculate_stats(self):

View File

@ -12,6 +12,7 @@ import re
from jobprogress import job
from hscommon import io
from hscommon.util import dedupe, rem_file_ext, get_file_ext
from hscommon.trans import tr
from . import engine
from .ignore import IgnoreList
@ -44,7 +45,7 @@ class Scanner:
def _getmatches(self, files, j):
if self.size_threshold:
j = j.start_subjob([2, 8])
for f in j.iter_with_progress(files, 'Read size of %d/%d files'):
for f in j.iter_with_progress(files, tr("Read size of %d/%d files")):
f.size # pre-read, makes a smoother progress if read here (especially for bundles)
files = [f for f in files if f.size >= self.size_threshold]
if self.scan_type in (ScanType.Contents, ScanType.ContentsAudio):
@ -64,7 +65,7 @@ class Scanner:
ScanType.Fields: lambda f: engine.getfields(rem_file_ext(f.name)),
ScanType.Tag: lambda f: [engine.getwords(str(getattr(f, attrname))) for attrname in SCANNABLE_TAGS if attrname in self.scanned_tags],
}[self.scan_type]
for f in j.iter_with_progress(files, 'Read metadata of %d/%d files'):
for f in j.iter_with_progress(files, tr("Read metadata of %d/%d files")):
f.words = func(f)
return engine.getmatches(files, j=j, **kw)
@ -93,13 +94,13 @@ class Scanner:
logging.info('Getting matches')
matches = self._getmatches(files, j)
logging.info('Found %d matches' % len(matches))
j.set_progress(100, 'Removing false matches')
j.set_progress(100, tr("Removing false matches"))
if not self.mix_file_kind:
matches = [m for m in matches if get_file_ext(m.first.name) == get_file_ext(m.second.name)]
matches = [m for m in matches if io.exists(m.first.path) and io.exists(m.second.path)]
if self.ignore_list:
j = j.start_subjob(2)
iter_matches = j.iter_with_progress(matches, 'Processed %d/%d matches against the ignore list')
iter_matches = j.iter_with_progress(matches, tr("Processed %d/%d matches against the ignore list"))
matches = [m for m in iter_matches
if not self.ignore_list.AreIgnored(str(m.first.path), str(m.second.path))]
logging.info('Grouping matches')
@ -108,7 +109,7 @@ class Scanner:
self.discarded_file_count = len(matched_files) - sum(len(g) for g in groups)
groups = [g for g in groups if any(not f.is_ref for f in g)]
logging.info('Created %d groups' % len(groups))
j.set_progress(100, 'Doing group prioritization')
j.set_progress(100, tr("Doing group prioritization"))
for g in groups:
g.prioritize(self._key_func, self._tie_breaker)
return groups

View File

@ -11,6 +11,7 @@ from appscript import app, k, CommandError
import time
from hscommon.cocoa import as_fetch
from hscommon.trans import tr
from core.app_cocoa import JOBID2TITLE, DupeGuru as DupeGuruBase
@ -20,8 +21,8 @@ JOB_REMOVE_DEAD_TRACKS = 'jobRemoveDeadTracks'
JOB_SCAN_DEAD_TRACKS = 'jobScanDeadTracks'
JOBID2TITLE.update({
JOB_REMOVE_DEAD_TRACKS: "Removing dead tracks from your iTunes Library",
JOB_SCAN_DEAD_TRACKS: "Scanning the iTunes Library",
JOB_REMOVE_DEAD_TRACKS: tr("Removing dead tracks from your iTunes Library"),
JOB_SCAN_DEAD_TRACKS: tr("Scanning the iTunes Library"),
})
class DupeGuruME(DupeGuruBase):

View File

@ -18,6 +18,7 @@ from hscommon.util import get_file_ext, remove_invalid_xml
from hscommon.path import Path
from hscommon.cocoa import as_fetch
from hscommon.cocoa.objcmin import NSUserDefaults, NSURL
from hscommon.trans import tr
from core import fs
from core import app_cocoa, directories
@ -152,7 +153,7 @@ class DupeGuruPE(app_cocoa.DupeGuru):
marked = [dupe for dupe in self.results.dupes if self.results.is_marked(dupe)]
self.path2iphoto = {}
if any(isinstance(dupe, IPhoto) for dupe in marked):
j = j.start_subjob([6, 4], "Probing iPhoto. Don\'t touch it during the operation!")
j = j.start_subjob([6, 4], tr("Probing iPhoto. Don't touch it during the operation!"))
try:
a = app('iPhoto')
a.activate(timeout=0)
@ -165,7 +166,7 @@ class DupeGuruPE(app_cocoa.DupeGuru):
pass
except (CommandError, RuntimeError, ApplicationNotFoundError):
pass
j.start_job(self.results.mark_count, "Sending dupes to the Trash")
j.start_job(self.results.mark_count, tr("Sending dupes to the Trash"))
self.results.perform_on_marked(op, True)
del self.path2iphoto

View File

@ -10,6 +10,7 @@ import logging
import multiprocessing
from collections import defaultdict, deque
from hscommon.trans import tr
from jobprogress import job
from core.engine import Match
@ -32,7 +33,7 @@ def prepare_pictures(pictures, cache_path, j=job.nulljob):
cache = Cache(cache_path)
prepared = [] # only pictures for which there was no error getting blocks
try:
for picture in j.iter_with_progress(pictures, 'Analyzed %d/%d pictures'):
for picture in j.iter_with_progress(pictures, tr("Analyzed %d/%d pictures")):
picture.dimensions
picture.unicode_path = str(picture.path)
try:
@ -76,7 +77,7 @@ def async_compare(ref_id, other_ids, dbname, threshold):
def getmatches(pictures, cache_path, threshold=75, match_scaled=False, j=job.nulljob):
j = j.start_subjob([3, 7])
pictures = prepare_pictures(pictures, cache_path, j)
j = j.start_subjob([9, 1], 'Preparing for matching')
j = j.start_subjob([9, 1], tr("Preparing for matching"))
cache = Cache(cache_path)
id2picture = {}
dimensions2pictures = defaultdict(set)
@ -94,7 +95,7 @@ def getmatches(pictures, cache_path, threshold=75, match_scaled=False, j=job.nul
async_results = deque()
matches = []
pictures_copy = set(pictures)
for ref in j.iter_with_progress(pictures, 'Matched %d/%d pictures'):
for ref in j.iter_with_progress(pictures, tr("Matched %d/%d pictures")):
others = pictures_copy if match_scaled else dimensions2pictures[ref.dimensions]
others.remove(ref)
if ref.is_ref:
@ -118,7 +119,7 @@ def getmatches(pictures, cache_path, threshold=75, match_scaled=False, j=job.nul
matches.extend(result.get())
result = []
for ref_id, other_id, percentage in j.iter_with_progress(matches, 'Verified %d/%d matches', every=10):
for ref_id, other_id, percentage in j.iter_with_progress(matches, tr("Verified %d/%d matches"), every=10):
ref = id2picture[ref_id]
other = id2picture[other_id]
if percentage == 100 and ref.md5 != other.md5: