From 42cff207100915df9020bdd3821ed2e9e1d75d22 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Tue, 18 Jan 2011 17:33:33 +0100 Subject: [PATCH] [#32] Internationalized the core and localized it to french. --- cocoa/base/en.lproj/core.strings | 29 +++++++++++++++++++++ cocoa/base/fr.lproj/core.strings | 28 ++++++++++++++++++++ cocoa/me/dg_cocoa.py | 3 +++ cocoa/me/dupeguru.xcodeproj/project.pbxproj | 14 ++++++++++ cocoa/pe/dg_cocoa.py | 3 +++ cocoa/pe/dupeguru.xcodeproj/project.pbxproj | 14 ++++++++++ cocoa/se/dg_cocoa.py | 3 +++ cocoa/se/dupeguru.xcodeproj/project.pbxproj | 14 ++++++++++ cocoa/se/fr.lproj/Preferences.xib | 16 ++++++------ core/app.py | 5 ++-- core/app_cocoa.py | 11 ++++---- core/engine.py | 15 ++++++----- core/results.py | 5 ++-- core/scanner.py | 11 ++++---- core_me/app_cocoa.py | 5 ++-- core_pe/app_cocoa.py | 5 ++-- core_pe/matchbase.py | 9 ++++--- 17 files changed, 153 insertions(+), 37 deletions(-) create mode 100644 cocoa/base/en.lproj/core.strings create mode 100644 cocoa/base/fr.lproj/core.strings diff --git a/cocoa/base/en.lproj/core.strings b/cocoa/base/en.lproj/core.strings new file mode 100644 index 00000000..ed27a88c --- /dev/null +++ b/cocoa/base/en.lproj/core.strings @@ -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"; \ No newline at end of file diff --git a/cocoa/base/fr.lproj/core.strings b/cocoa/base/fr.lproj/core.strings new file mode 100644 index 00000000..34edbe6e --- /dev/null +++ b/cocoa/base/fr.lproj/core.strings @@ -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"; \ No newline at end of file diff --git a/cocoa/me/dg_cocoa.py b/cocoa/me/dg_cocoa.py index 78ea0778..5fdad6f2 100644 --- a/cocoa/me/dg_cocoa.py +++ b/cocoa/me/dg_cocoa.py @@ -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 diff --git a/cocoa/me/dupeguru.xcodeproj/project.pbxproj b/cocoa/me/dupeguru.xcodeproj/project.pbxproj index 41541b90..61a05c66 100644 --- a/cocoa/me/dupeguru.xcodeproj/project.pbxproj +++ b/cocoa/me/dupeguru.xcodeproj/project.pbxproj @@ -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 = ""; }; @@ -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 = ""; }; + CE45274D12E5F62D00005A15 /* core.strings */ = { + isa = PBXVariantGroup; + children = ( + CE45274E12E5F62D00005A15 /* en */, + CE45275012E5F63900005A15 /* fr */, + ); + name = core.strings; + sourceTree = SOURCE_ROOT; + }; CE74A12512537F2E008A8DF0 /* FairwareReminder.xib */ = { isa = PBXVariantGroup; children = ( diff --git a/cocoa/pe/dg_cocoa.py b/cocoa/pe/dg_cocoa.py index 9166b2fc..3281fb76 100644 --- a/cocoa/pe/dg_cocoa.py +++ b/cocoa/pe/dg_cocoa.py @@ -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 diff --git a/cocoa/pe/dupeguru.xcodeproj/project.pbxproj b/cocoa/pe/dupeguru.xcodeproj/project.pbxproj index 41b01d3a..879c8d9d 100644 --- a/cocoa/pe/dupeguru.xcodeproj/project.pbxproj +++ b/cocoa/pe/dupeguru.xcodeproj/project.pbxproj @@ -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 */ diff --git a/cocoa/se/dg_cocoa.py b/cocoa/se/dg_cocoa.py index 3cc59c91..294db0aa 100644 --- a/cocoa/se/dg_cocoa.py +++ b/cocoa/se/dg_cocoa.py @@ -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 diff --git a/cocoa/se/dupeguru.xcodeproj/project.pbxproj b/cocoa/se/dupeguru.xcodeproj/project.pbxproj index be37487e..11d4792f 100644 --- a/cocoa/se/dupeguru.xcodeproj/project.pbxproj +++ b/cocoa/se/dupeguru.xcodeproj/project.pbxproj @@ -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 = ""; }; 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 = ( diff --git a/cocoa/se/fr.lproj/Preferences.xib b/cocoa/se/fr.lproj/Preferences.xib index d4a4aaa8..1642b928 100644 --- a/cocoa/se/fr.lproj/Preferences.xib +++ b/cocoa/se/fr.lproj/Preferences.xib @@ -290,7 +290,7 @@ 1211912703 2 - + NSImage NSSwitch @@ -317,7 +317,7 @@ 1211912703 2 - + @@ -339,7 +339,7 @@ 1211912703 2 - + @@ -361,7 +361,7 @@ 1211912703 2 - + @@ -383,7 +383,7 @@ 1211912703 2 - + @@ -405,7 +405,7 @@ 1211912703 2 - + @@ -621,7 +621,7 @@ 1211912703 2 - + @@ -643,7 +643,7 @@ 1211912703 2 - + diff --git a/core/app.py b/core/app.py index 3eb94d07..a1e280fc 100644 --- a/core/app.py +++ b/core/app.py @@ -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 diff --git a/core/app_cocoa.py b/core/app_cocoa.py index e5b4acec..7a8838c0 100644 --- a/core/app_cocoa.py +++ b/core/app_cocoa.py @@ -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): diff --git a/core/engine.py b/core/engine.py index 14dead52..8e3cca05 100644 --- a/core/engine.py +++ b/core/engine.py @@ -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) diff --git a/core/results.py b/core/results.py index 33381da6..587c941b 100644 --- a/core/results.py +++ b/core/results.py @@ -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): diff --git a/core/scanner.py b/core/scanner.py index af353c8b..3d192a0c 100644 --- a/core/scanner.py +++ b/core/scanner.py @@ -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 diff --git a/core_me/app_cocoa.py b/core_me/app_cocoa.py index 24adde5d..f32db8a7 100644 --- a/core_me/app_cocoa.py +++ b/core_me/app_cocoa.py @@ -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): diff --git a/core_pe/app_cocoa.py b/core_pe/app_cocoa.py index 723687ae..17c739cc 100644 --- a/core_pe/app_cocoa.py +++ b/core_pe/app_cocoa.py @@ -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 diff --git a/core_pe/matchbase.py b/core_pe/matchbase.py index 68675c49..87eb43b2 100644 --- a/core_pe/matchbase.py +++ b/core_pe/matchbase.py @@ -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: