Index: utils/ofzip/GZIPArchive.m ================================================================== --- utils/ofzip/GZIPArchive.m +++ utils/ofzip/GZIPArchive.m @@ -17,10 +17,11 @@ #include "config.h" #import "OFApplication.h" #import "OFFileManager.h" #import "OFStdIOStream.h" +#import "OFLocalization.h" #import "GZIPArchive.h" #import "OFZIP.h" static OFZIP *app; @@ -73,11 +74,12 @@ [super dealloc]; } - (void)listFiles { - [of_stderr writeLine: @"Cannot list files of a .gz archive!"]; + [of_stderr writeLine: OF_LOCALIZED(@"cannot_list_gz", + @"Cannot list files of a .gz archive!")]; app->_exitStatus = 1; } - (void)extractFiles: (OFArray OF_GENERIC(OFString*)*)files { @@ -84,20 +86,23 @@ OFString *fileName; OFFile *output; if ([files count] != 0) { [of_stderr writeLine: - @"Cannot extract a specific file of a .gz archive!"]; + OF_LOCALIZED(@"cannot_extract_specific_file_from_gz", + @"Cannot extract a specific file of a .gz archive!")]; app->_exitStatus = 1; return; } fileName = [[app->_archivePath lastPathComponent] stringByDeletingPathExtension]; if (app->_outputLevel >= 0) - [of_stdout writeFormat: @"Extracting %@...", fileName]; + [of_stdout writeString: OF_LOCALIZED(@"extracting_file", + @"Extracting %[file]...", + @"file", fileName)]; if (![app shouldExtractFile: fileName outFileName: fileName]) return; @@ -114,22 +119,27 @@ app->_exitStatus = 1; return; } } - if (app->_outputLevel >= 0) - [of_stdout writeFormat: @"\rExtracting %@... done\n", fileName]; + if (app->_outputLevel >= 0) { + [of_stdout writeString: @"\r"]; + [of_stdout writeLine: OF_LOCALIZED(@"extracting_file_done", + @"Extracting %[file]... done", + @"file", fileName)]; + } } - (void)printFiles: (OFArray OF_GENERIC(OFString*)*)files { OFString *fileName = [[app->_archivePath lastPathComponent] stringByDeletingPathExtension]; if ([files count] > 0) { - [of_stderr writeLine: - @"Cannot specify a file to print for .gz archives!"]; + [of_stderr writeLine: OF_LOCALIZED( + @"cannot_print_specific_file_from_gz", + @"Cannot print a specific file of a .gz archive!")]; app->_exitStatus = 1; return; } while (![_stream isAtEndOfStream]) { Index: utils/ofzip/Makefile ================================================================== --- utils/ofzip/Makefile +++ utils/ofzip/Makefile @@ -3,14 +3,22 @@ PROG = ofzip${PROG_SUFFIX} SRCS = GZIPArchive.m \ OFZIP.m \ TarArchive.m \ ZIPArchive.m +DATA = lang/de.json \ + lang/languages.json include ../../buildsys.mk + +PACKAGE_NAME = ofzip ${PROG}: ${LIBOBJFW_DEP_LVL2} -CPPFLAGS += -I../../src -I../../src/runtime -I../../src/exceptions -I../.. +CPPFLAGS += -I../../src \ + -I../../src/runtime \ + -I../../src/exceptions \ + -I../.. \ + -DLANGUAGE_DIR=\"${datadir}/ofzip/lang\" LIBS := -L../../src -lobjfw ${LIBS} LD = ${OBJC} LDFLAGS += ${LDFLAGS_RPATH} Index: utils/ofzip/OFZIP.m ================================================================== --- utils/ofzip/OFZIP.m +++ utils/ofzip/OFZIP.m @@ -22,10 +22,11 @@ #import "OFArray.h" #import "OFFile.h" #import "OFFileManager.h" #import "OFOptionsParser.h" #import "OFStdIOStream.h" +#import "OFLocalization.h" #import "OFZIP.h" #import "GZIPArchive.h" #import "TarArchive.h" #import "ZIPArchive.h" @@ -42,17 +43,18 @@ OF_APPLICATION_DELEGATE(OFZIP) static void help(OFStream *stream, bool full, int status) { - [stream writeFormat: - @"Usage: %@ -[fhlnpqtvx] archive.zip [file1 file2 ...]\n", - [OFApplication programName]]; + [stream writeLine: OF_LOCALIZED(@"usage", + @"Usage: %[prog] -[fhlnpqtvx] archive.zip [file1 file2 ...]", + @"prog", [OFApplication programName])]; - if (full) - [stream writeString: - @"\nOptions:\n" + if (full) { + [stream writeString: @"\n"]; + [stream writeLine: OF_LOCALIZED(@"full_usage", + @"Options:\n" @" -f --force Force / overwrite files\n" @" -h --help Show this help\n" @" -l --list List all files in the archive\n" @" -n --no-clober Never overwrite files\n" @" -p --print Print one or more files from the " @@ -59,34 +61,58 @@ @"archive\n" @" -q --quiet Quiet mode (no output, except " @"errors)\n" @" -t --type Archive type (gz, tar, tgz, zip)\n" @" -v --verbose Verbose output for file list\n" - @" -x --extract Extract files\n"]; + @" -x --extract Extract files")]; + } [OFApplication terminateWithStatus: status]; } static void mutuallyExclusiveError(of_unichar_t shortOption1, OFString *longOption1, of_unichar_t shortOption2, OFString *longOption2) { - [of_stderr writeFormat: - @"Error: -%C / --%@ and -%C / --%@ are mutually exclusive!\n", - shortOption1, longOption1, shortOption2, longOption2]; + OFString *shortOption1Str = [OFString stringWithFormat: @"%C", + shortOption1]; + OFString *shortOption2Str = [OFString stringWithFormat: @"%C", + shortOption2]; + + [of_stderr writeLine: OF_LOCALIZED(@"2_options_mutually_exclusive", + @"Error: -%[shortopt1] / --%[longopt1] and " + @"-%[shortopt2] / --%[longopt2] " + @"are mutually exclusive!", + @"shortopt1", shortOption1Str, + @"longopt1", longOption1, + @"shortopt2", shortOption2Str, + @"longopt2", longOption2)]; [OFApplication terminateWithStatus: 1]; } static void mutuallyExclusiveError3(of_unichar_t shortOption1, OFString *longOption1, of_unichar_t shortOption2, OFString *longOption2, of_unichar_t shortOption3, OFString *longOption3) { - [of_stderr writeFormat: - @"Error: -%C / --%@, -%C / --%@ and -%C / --%@ are mutually " - @"exclusive!\n", shortOption1, longOption1, shortOption2, - longOption2, shortOption3, longOption3]; + OFString *shortOption1Str = [OFString stringWithFormat: @"%C", + shortOption1]; + OFString *shortOption2Str = [OFString stringWithFormat: @"%C", + shortOption2]; + OFString *shortOption3Str = [OFString stringWithFormat: @"%C", + shortOption3]; + + [of_stderr writeLine: OF_LOCALIZED(@"3_options_mutually_exclusive", + @"Error: -%[shortopt1] / --%[longopt1], " + @"-%[shortopt2] / --%[longopt2] and -%[shortopt3] / --%[longopt3] " + @"are mutually exclusive!", + @"shortopt1", shortOption1Str, + @"longopt1", longOption1, + @"shortopt2", shortOption2Str, + @"longopt2", longOption2, + @"shortopt3", shortOption3Str, + @"longopt3", longOption3)]; [OFApplication terminateWithStatus: 1]; } @implementation OFZIP - (void)applicationDidFinishLaunching @@ -107,10 +133,12 @@ OFOptionsParser *optionsParser = [OFOptionsParser parserWithOptions: options]; of_unichar_t option, mode = '\0'; OFArray OF_GENERIC(OFString*) *remainingArguments, *files; id archive; + + [OFLocalization addLanguageDirectory: @LANGUAGE_DIR]; while ((option = [optionsParser nextOption]) != '\0') { switch (option) { case 'f': if (_overwrite < 0) @@ -152,28 +180,35 @@ break; case 'h': help(of_stdout, true, 0); break; case '=': - [of_stderr writeFormat: @"%@: Option --%@ takes no " - @"argument!\n", - [OFApplication programName], - [optionsParser lastLongOption]]; + [of_stderr writeLine: OF_LOCALIZED( + @"option_takes_no_argument", + @"%[prog]: Option --%[opt] takes no argument", + @"prog", [OFApplication programName], + @"opt", [optionsParser lastLongOption])]; [OFApplication terminateWithStatus: 1]; break; case '?': if ([optionsParser lastLongOption] != nil) - [of_stderr writeFormat: - @"%@: Unknown option: --%@\n", - [OFApplication programName], - [optionsParser lastLongOption]]; - else - [of_stderr writeFormat: - @"%@: Unknown option: -%C\n", - [OFApplication programName], + [of_stderr writeLine: OF_LOCALIZED( + @"unknown_long_option", + @"%[prog]: Unknown option: --%[opt]", + @"prog", [OFApplication programName], + @"opt", [optionsParser lastLongOption])]; + else { + OFString *optStr = [OFString + stringWithFormat: @"%c", [optionsParser lastOption]]; + [of_stderr writeLine: OF_LOCALIZED( + @"unknown_option", + @"%[prog]: Unknown option: -%[opt]", + @"prog", [OFApplication programName], + @"opt", optStr)]; + } [OFApplication terminateWithStatus: 1]; } } @@ -196,18 +231,30 @@ of_range(1, [remainingArguments count] - 1)]; @try { [archive extractFiles: files]; } @catch (OFCreateDirectoryFailedException *e) { - [of_stderr writeFormat: - @"\rFailed to create directory %@: %s\n", - [e path], strerror([e errNo])]; + OFString *error = [OFString + stringWithCString: strerror([e errNo]) + encoding: [OFLocalization encoding]]; + [of_stderr writeString: @"\r"]; + [of_stderr writeLine: OF_LOCALIZED( + @"failed_to_create_directory", + @"Failed to create directory %[dir]: %[error]", + @"dir", [e path], + @"error", error)]; _exitStatus = 1; } @catch (OFOpenItemFailedException *e) { - [of_stderr writeFormat: - @"\rFailed to open file %@: %s\n", - [e path], strerror([e errNo])]; + OFString *error = [OFString + stringWithCString: strerror([e errNo]) + encoding: [OFLocalization encoding]]; + [of_stderr writeString: @"\r"]; + [of_stderr writeLine: OF_LOCALIZED( + @"failed_to_open_file", + @"Failed to open file %[file]: %[error]", + @"file", [e path], + @"error", error)]; _exitStatus = 1; } break; case 'p': @@ -241,12 +288,19 @@ @try { file = [OFFile fileWithPath: path mode: @"rb"]; } @catch (OFOpenItemFailedException *e) { - [of_stderr writeFormat: @"Failed to open file %@: %s\n", - [e path], strerror([e errNo])]; + OFString *error = [OFString + stringWithCString: strerror([e errNo]) + encoding: [OFLocalization encoding]]; + [of_stderr writeString: @"\r"]; + [of_stderr writeLine: OF_LOCALIZED( + @"failed_to_open_file", + @"Failed to open file %[file]: %[error]", + @"file", [e path], + @"error", error)]; [OFApplication terminateWithStatus: 1]; } if (type == nil || [type isEqual: @"auto"]) { /* This one has to be first for obvious reasons */ @@ -270,25 +324,39 @@ archive = [TarArchive archiveWithStream: [OFGZIPStream streamWithStream: file]]; else if ([type isEqual: @"zip"]) archive = [ZIPArchive archiveWithStream: file]; else { - [of_stderr writeFormat: @"Unknown archive type: %@!\n", - type]; + [of_stderr writeLine: OF_LOCALIZED( + @"unknown_archive_type", + @"Unknown archive type: %[type]", + @"type", type)]; [OFApplication terminateWithStatus: 1]; } } @catch (OFReadFailedException *e) { - [of_stderr writeFormat: @"Failed to read file %@: %s\n", - path, strerror([e errNo])]; + OFString *error = [OFString + stringWithCString: strerror([e errNo]) + encoding: [OFLocalization encoding]]; + [of_stderr writeLine: OF_LOCALIZED(@"failed_to_read_file", + @"Failed to read file %[file]: %[error]", + @"file", path, + @"error", error)]; [OFApplication terminateWithStatus: 1]; } @catch (OFSeekFailedException *e) { - [of_stderr writeFormat: @"Failed to seek in file %@: %s\n", - path, strerror([e errNo])]; + OFString *error = [OFString + stringWithCString: strerror([e errNo]) + encoding: [OFLocalization encoding]]; + [of_stderr writeLine: OF_LOCALIZED(@"failed_to_seek_in_file", + @"Failed to seek in file %[file]: %[error]", + @"file", path, + @"error", error)]; [OFApplication terminateWithStatus: 1]; } @catch (OFInvalidFormatException *e) { - [of_stderr writeFormat: @"File %@ is not a valid archive!\n", - path]; + [of_stderr writeLine: OF_LOCALIZED( + @"file_is_not_a_valid_archive", + @"File %[file] is not a valid archive!", + @"file", path)]; [OFApplication terminateWithStatus: 1]; } return archive; } @@ -300,27 +368,35 @@ if (_overwrite == 1 || ![[OFFileManager defaultManager] fileExistsAtPath: outFileName]) return true; - if (_overwrite == -1) { - if (_outputLevel >= 0) - [of_stdout writeLine: @" skipped"]; + if (_outputLevel >= 0) { + [of_stdout writeString: @" "]; + [of_stdout writeLine: + OF_LOCALIZED(@"file_skipped", @"skipped")]; + } return false; } do { - [of_stderr writeFormat: @"\rOverwrite %@? [ynAN?] ", fileName]; + [of_stderr writeString: @"\r"]; + [of_stderr writeString: OF_LOCALIZED(@"ask_overwrite", + @"Overwrite %[file]? [ynAN?]", + @"file", fileName)]; + [of_stderr writeString: @" "]; line = [of_stdin readLine]; if ([line isEqual: @"?"]) - [of_stderr writeString: @" y: yes\n" - @" n: no\n" - @" A: always\n" - @" N: never\n"]; + [of_stderr writeLine: OF_LOCALIZED( + @"ask_overwrite_help", + @" y: yes\n" + @" n: no\n" + @" A: always\n" + @" N: never")]; } while (![line isEqual: @"y"] && ![line isEqual: @"n"] && ![line isEqual: @"N"] && ![line isEqual: @"A"]); if ([line isEqual: @"A"]) _overwrite = 1; @@ -327,16 +403,20 @@ else if ([line isEqual: @"N"]) _overwrite = -1; if ([line isEqual: @"n"] || [line isEqual: @"N"]) { if (_outputLevel >= 0) - [of_stdout writeFormat: @"Skipping %@...\n", fileName]; + [of_stdout writeLine: OF_LOCALIZED(@"skipping_file", + @"Skipping %[file]...", + @"file", fileName)]; return false; } if (_outputLevel >= 0) - [of_stdout writeFormat: @"Extracting %@...", fileName]; + [of_stdout writeString: OF_LOCALIZED(@"extracting_file", + @"Extracting %[file]...", + @"file", fileName)]; return true; } - (ssize_t)copyBlockFromStream: (OFStream*)input @@ -348,22 +428,34 @@ @try { length = [input readIntoBuffer: buffer length: BUFFER_SIZE]; } @catch (OFReadFailedException *e) { - [of_stderr writeFormat: @"\rFailed to read file %@: %s\n", - fileName, strerror([e errNo])]; + OFString *error = [OFString + stringWithCString: strerror([e errNo]) + encoding: [OFLocalization encoding]]; + [of_stdout writeString: @"\r"]; + [of_stderr writeLine: OF_LOCALIZED(@"failed_to_read_file", + @"Failed to read file %[file]: %[error]", + @"file", fileName, + @"error", error)]; return -1; } @try { [output writeBuffer: buffer length: length]; } @catch (OFWriteFailedException *e) { - [of_stderr writeFormat: @"\rFailed to write file %@: %s\n", - fileName, strerror([e errNo])]; + OFString *error = [OFString + stringWithCString: strerror([e errNo]) + encoding: [OFLocalization encoding]]; + [of_stdout writeString: @"\r"]; + [of_stderr writeLine: OF_LOCALIZED(@"failed_to_write_file", + @"Failed to write file %[file]: %[error]", + @"file", fileName, + @"error", error)]; return -1; } return length; } @end Index: utils/ofzip/TarArchive.m ================================================================== --- utils/ofzip/TarArchive.m +++ utils/ofzip/TarArchive.m @@ -21,10 +21,11 @@ #import "OFDate.h" #import "OFSet.h" #import "OFApplication.h" #import "OFFileManager.h" #import "OFStdIOStream.h" +#import "OFLocalization.h" #import "TarArchive.h" #import "OFZIP.h" #ifndef S_IRWXG @@ -94,72 +95,140 @@ [of_stdout writeLine: [entry fileName]]; if (app->_outputLevel >= 1) { OFString *date = [[entry modificationDate] localDateStringWithFormat: @"%Y-%m-%d %H:%M:%S"]; - - [of_stdout writeFormat: - @"\tSize: %" PRIu64 @" bytes\n" - @"\tMode: %06o\n", - [entry size], [entry mode]]; - - if ([entry owner] != nil) - [of_stdout writeFormat: @"\tOwner: %@\n", - [entry owner]]; - if ([entry group] != nil) - [of_stdout writeFormat: @"\tGroup: %@\n", - [entry group]]; - - [of_stdout writeFormat: @"\tModification date: %@\n", - date]; + OFString *size = [OFString stringWithFormat: + @"%" PRIu64, [entry size]]; + OFString *mode = [OFString stringWithFormat: + @"%06o", [entry mode]]; + + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED(@"list_size", + @"Size: %[size] bytes", + @"size", size)]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED(@"list_mode", + @"Mode: %[mode]", + @"mode", mode)]; + + if ([entry owner] != nil) { + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_owner", + @"Owner: %[owner]", + @"owner", [entry owner])]; + } + if ([entry group] != nil) { + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_group", + @"Group: %[group]", + @"group", [entry group])]; + } + + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_modification_date", + @"Modification date: %[date]", + @"date", date)]; } if (app->_outputLevel >= 2) { + [of_stdout writeString: @"\t"]; + switch ([entry type]) { case OF_TAR_ARCHIVE_ENTRY_TYPE_FILE: - [of_stdout writeLine: @"\tType: Normal file"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_type_normal", + @"Type: Normal file")]; break; case OF_TAR_ARCHIVE_ENTRY_TYPE_LINK: - [of_stdout writeLine: @"\tType: Hard link"]; - [of_stdout writeFormat: - @"\tTarget file name: %@\n", - [entry targetFileName]]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_type_hardlink", + @"Type: Hard link")]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_link_target", + @"Target file name: %[target]", + @"target", [entry targetFileName])]; break; case OF_TAR_ARCHIVE_ENTRY_TYPE_SYMLINK: - [of_stdout writeLine: @"\tType: Symbolic link"]; - [of_stdout writeFormat: - @"\tTarget file name: %@\n", - [entry targetFileName]]; - break; - case OF_TAR_ARCHIVE_ENTRY_TYPE_CHARACTER_DEVICE: - [of_stdout writeLine: - @"\tType: Character device"]; - [of_stdout writeFormat: @"\tDevice major: %d\n" - @"\tDevice minor: %d\n", - [entry deviceMajor], - [entry deviceMinor]]; - break; - case OF_TAR_ARCHIVE_ENTRY_TYPE_BLOCK_DEVICE: - [of_stdout writeLine: - @"\tType: Block device"]; - [of_stdout writeFormat: @"\tDevice major: %d\n" - @"\tDevice minor: %d\n", - [entry deviceMajor], - [entry deviceMinor]]; - break; - case OF_TAR_ARCHIVE_ENTRY_TYPE_DIRECTORY: - [of_stdout writeLine: @"\tType: Directory"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_type_symlink", + @"Type: Symbolic link")]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_link_target", + @"Target file name: %[target]", + @"target", [entry targetFileName])]; + break; + case OF_TAR_ARCHIVE_ENTRY_TYPE_CHARACTER_DEVICE: { + OFString *majorString = [OFString + stringWithFormat: @"%d", + [entry deviceMajor]]; + OFString *minorString = [OFString + stringWithFormat: @"%d", + [entry deviceMinor]]; + + [of_stdout writeLine: OF_LOCALIZED( + @"list_type_character_device", + @"Type: Character device")]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_device_major", + @"Device major: %[major]", + @"major", majorString)]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_device_minor", + @"Device minor: %[minor]", + @"minor", minorString)]; + break; + } + case OF_TAR_ARCHIVE_ENTRY_TYPE_BLOCK_DEVICE: { + OFString *majorString = [OFString + stringWithFormat: @"%d", + [entry deviceMajor]]; + OFString *minorString = [OFString + stringWithFormat: @"%d", + [entry deviceMinor]]; + + [of_stdout writeLine: OF_LOCALIZED( + @"list_type_block_device", + @"Type: Block device")]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_device_major", + @"Device major: %[major]", + @"major", majorString)]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_device_minor", + @"Device minor: %[minor]", + @"minor", minorString)]; + break; + } + case OF_TAR_ARCHIVE_ENTRY_TYPE_DIRECTORY: + [of_stdout writeLine: OF_LOCALIZED( + @"list_type_directory", + @"Type: Directory")]; break; case OF_TAR_ARCHIVE_ENTRY_TYPE_FIFO: - [of_stdout writeLine: @"\tType: FIFO"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_type_fifo", + @"Type: FIFO")]; break; case OF_TAR_ARCHIVE_ENTRY_TYPE_CONTIGUOUS_FILE: - [of_stdout writeLine: - @"\tType: Contiguous file"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_type_contiguous_file", + @"Type: Contiguous file")]; break; default: - [of_stdout writeLine: @"\tType: Unknown"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_type_unknown", + @"Type: Unknown")]; break; } } objc_autoreleasePoolPop(pool); @@ -187,12 +256,14 @@ if (!all && ![files containsObject: fileName]) continue; if ([entry type] != OF_TAR_ARCHIVE_ENTRY_TYPE_FILE) { if (app->_outputLevel >= 0) - [of_stdout writeFormat: @"Skipping %@...\n", - fileName]; + [of_stdout writeLine: OF_LOCALIZED( + @"skipping_file", + @"Skipping %[file]...", + @"file", fileName)]; continue; } [missing removeObject: fileName]; @@ -200,39 +271,50 @@ if ([outFileName hasPrefix: @"/"]) { #else if ([outFileName hasPrefix: @"/"] || [outFileName containsString: @":"]) { #endif - [of_stderr writeFormat: @"Refusing to extract %@!\n", - fileName]; + [of_stderr writeLine: OF_LOCALIZED( + @"refusing_to_extract_file", + @"Refusing to extract %[file]!", + @"file", fileName)]; app->_exitStatus = 1; goto outer_loop_end; } pathComponents = [outFileName pathComponents]; for (OFString *component in pathComponents) { if ([component isEqual: OF_PATH_PARENT_DIRECTORY]) { - [of_stderr writeFormat: - @"Refusing to extract %@!\n", fileName]; + [of_stderr writeLine: OF_LOCALIZED( + @"refusing_to_extract_file", + @"Refusing to extract %[file]!", + @"file", fileName)]; app->_exitStatus = 1; goto outer_loop_end; } } outFileName = [OFString pathWithComponents: pathComponents]; if (app->_outputLevel >= 0) - [of_stdout writeFormat: @"Extracting %@...", fileName]; + [of_stdout writeString: OF_LOCALIZED(@"extracting_file", + @"Extracting %[file]...", + @"file", fileName)]; if ([fileName hasSuffix: @"/"]) { [fileManager createDirectoryAtPath: outFileName createParents: true]; setPermissions(outFileName, entry); - if (app->_outputLevel >= 0) - [of_stdout writeLine: @" done"]; + if (app->_outputLevel >= 0) { + [of_stdout writeString: @"\r"]; + [of_stdout writeLine: OF_LOCALIZED( + @"extracting_file_done", + @"Extracting %[file]... done", + @"file", fileName)]; + } goto outer_loop_end; } directory = [outFileName stringByDeletingLastPathComponent]; @@ -261,30 +343,43 @@ written += length; newPercent = (written == size ? 100 : (int8_t)(written * 100 / size)); if (app->_outputLevel >= 0 && percent != newPercent) { + OFString *percentString; + percent = newPercent; + percentString = [OFString stringWithFormat: + @"%3u", percent]; - [of_stdout writeFormat: - @"\rExtracting %@... %3u%%", - fileName, percent]; + [of_stdout writeString: @"\r"]; + [of_stdout writeString: OF_LOCALIZED( + @"extracting_file_percent", + @"Extracting %[file]... %[percent]%", + @"file", fileName, + @"percent", percentString)]; } } - if (app->_outputLevel >= 0) - [of_stdout writeFormat: @"\rExtracting %@... done\n", - fileName]; + if (app->_outputLevel >= 0) { + [of_stdout writeString: @"\r"]; + [of_stdout writeLine: OF_LOCALIZED( + @"extracting_file_done", + @"Extracting %[file]... done", + @"file", fileName)]; + } outer_loop_end: objc_autoreleasePoolPop(pool); } if ([missing count] > 0) { for (OFString *file in missing) - [of_stderr writeFormat: - @"File %@ is not in the archive!\n", file]; + [of_stderr writeLine: OF_LOCALIZED( + @"file_not_in_archive", + @"File %[file] is not in the archive!", + @"file", file)]; app->_exitStatus = 1; } } @@ -292,11 +387,12 @@ { OFMutableSet *files; OFTarArchiveEntry *entry; if ([files_ count] < 1) { - [of_stderr writeLine: @"Need one or more files to print!"]; + [of_stderr writeLine: OF_LOCALIZED(@"print_no_file_specified", + @"Need one or more files to print!")]; app->_exitStatus = 1; return; } files = [OFMutableSet setWithArray: files_]; @@ -320,12 +416,13 @@ [files removeObject: fileName]; [entry close]; } - for (OFString *path in files) { - [of_stderr writeFormat: @"File %@ is not in the archive!\n", - path]; + for (OFString *file in files) { + [of_stderr writeLine: OF_LOCALIZED(@"file_not_in_archive", + @"File %[file] is not in the archive!", + @"file", file)]; app->_exitStatus = 1; } } @end Index: utils/ofzip/ZIPArchive.m ================================================================== --- utils/ofzip/ZIPArchive.m +++ utils/ofzip/ZIPArchive.m @@ -22,10 +22,11 @@ #import "OFDate.h" #import "OFSet.h" #import "OFApplication.h" #import "OFFileManager.h" #import "OFStdIOStream.h" +#import "OFLocalization.h" #import "ZIPArchive.h" #import "OFZIP.h" #import "OFInvalidFormatException.h" @@ -91,52 +92,97 @@ void *pool = objc_autoreleasePoolPush(); [of_stdout writeLine: [entry fileName]]; if (app->_outputLevel >= 1) { - OFString *date = [[entry modificationDate] + OFString *compressedSize = [OFString + stringWithFormat: @"%" PRIu64, + [entry compressedSize]]; + OFString *uncompressedSize = [OFString + stringWithFormat: @"%" PRIu64, + [entry uncompressedSize]]; + OFString *CRC32 = [OFString + stringWithFormat: @"%08X", [entry CRC32]]; + OFString *modificationDate = [[entry modificationDate] localDateStringWithFormat: @"%Y-%m-%d %H:%M:%S"]; - [of_stdout writeFormat: - @"\tCompressed: %" PRIu64 @" bytes\n" - @"\tUncompressed: %" PRIu64 @" bytes\n" - @"\tCRC32: %08X\n" - @"\tModification date: %@\n", - [entry compressedSize], [entry uncompressedSize], - [entry CRC32], date]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_compressed_size", + @"Compressed: %[size] bytes", + @"size", compressedSize)]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_uncompressed_size", + @"Uncompressed: %[size] bytes", + @"size", uncompressedSize)]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED(@"list_crc32", + @"CRC32: %[crc32]", + @"crc32", CRC32)]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_modification_date", + @"Modification date: %[date]", + @"date", modificationDate)]; if (app->_outputLevel >= 2) { uint16_t versionMadeBy = [entry versionMadeBy]; - [of_stdout writeFormat: - @"\tVersion made by: %@\n" - @"\tMinimum version needed: %@\n", + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_version_made_by", + @"Version made by: %[version]", + @"version", + of_zip_archive_entry_version_to_string( + versionMadeBy))]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_min_version_needed", + @"Minimum version needed: %[version]", + @"version", of_zip_archive_entry_version_to_string( - versionMadeBy), - of_zip_archive_entry_version_to_string( - [entry minVersionNeeded])]; + [entry minVersionNeeded]))]; if ((versionMadeBy >> 8) == OF_ZIP_ARCHIVE_ENTRY_ATTR_COMPAT_UNIX) { uint32_t mode = [entry versionSpecificAttributes] >> 16; - [of_stdout writeFormat: - @"\tMode: %06o\n", mode]; + OFString *modeString = [OFString + stringWithFormat: @"%06o", mode]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_mode", + @"Mode: %[mode]", + @"mode", modeString)]; } } - if (app->_outputLevel >= 3) - [of_stdout writeFormat: - @"\tGeneral purpose bit flag: " - @"%04" PRIx16 "\n" - @"\tExtra field: %@\n", - [entry generalPurposeBitFlag], - [entry extraField]]; - - if ([[entry fileComment] length] > 0) - [of_stdout writeFormat: @"\tComment: %@\n", - [entry fileComment]]; + if (app->_outputLevel >= 3) { + OFString *GPBF = [OFString stringWithFormat: + @"%04" PRIx16, + [entry generalPurposeBitFlag]]; + + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_general_purpose_bit_flag", + @"General purpose bit flag: %[gpbf]", + @"gpbf", GPBF)]; + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_extra_field", + @"Extra field: %[extra]", + @"extra", [entry extraField])]; + } + + if ([[entry fileComment] length] > 0) { + [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_comment", + @"Comment: %[comment]", + @"comment", [entry fileComment])]; + } } objc_autoreleasePoolPop(pool); } } @@ -168,39 +214,50 @@ if ([outFileName hasPrefix: @"/"]) { #else if ([outFileName hasPrefix: @"/"] || [outFileName containsString: @":"]) { #endif - [of_stderr writeFormat: @"Refusing to extract %@!\n", - fileName]; + [of_stderr writeLine: OF_LOCALIZED( + @"refusing_to_extract_file", + @"Refusing to extract %[file]!", + @"file", fileName)]; app->_exitStatus = 1; goto outer_loop_end; } pathComponents = [outFileName pathComponents]; for (OFString *component in pathComponents) { if ([component isEqual: OF_PATH_PARENT_DIRECTORY]) { - [of_stderr writeFormat: - @"Refusing to extract %@!\n", fileName]; + [of_stderr writeLine: OF_LOCALIZED( + @"refusing_to_extract_file", + @"Refusing to extract %[file]!", + @"file", fileName)]; app->_exitStatus = 1; goto outer_loop_end; } } outFileName = [OFString pathWithComponents: pathComponents]; if (app->_outputLevel >= 0) - [of_stdout writeFormat: @"Extracting %@...", fileName]; + [of_stdout writeString: OF_LOCALIZED(@"extracting_file", + @"Extracting %[file]...", + @"file", fileName)]; if ([fileName hasSuffix: @"/"]) { [fileManager createDirectoryAtPath: outFileName createParents: true]; setPermissions(outFileName, entry); - if (app->_outputLevel >= 0) - [of_stdout writeLine: @" done"]; + if (app->_outputLevel >= 0) { + [of_stdout writeString: @"\r"]; + [of_stdout writeLine: OF_LOCALIZED( + @"extracting_file_done", + @"Extracting %[file]... done", + @"file", fileName)]; + } goto outer_loop_end; } directory = [outFileName stringByDeletingLastPathComponent]; @@ -230,30 +287,43 @@ written += length; newPercent = (written == size ? 100 : (int8_t)(written * 100 / size)); if (app->_outputLevel >= 0 && percent != newPercent) { + OFString *percentString; + percent = newPercent; + percentString = [OFString stringWithFormat: + @"%3u", percent]; - [of_stdout writeFormat: - @"\rExtracting %@... %3u%%", - fileName, percent]; + [of_stdout writeString: @"\r"]; + [of_stdout writeString: OF_LOCALIZED( + @"extracting_file_percent", + @"Extracting %[file]... %[percent]%", + @"file", fileName, + @"percent", percentString)]; } } - if (app->_outputLevel >= 0) - [of_stdout writeFormat: @"\rExtracting %@... done\n", - fileName]; + if (app->_outputLevel >= 0) { + [of_stdout writeString: @"\r"]; + [of_stdout writeLine: OF_LOCALIZED( + @"extracting_file_done", + @"Extracting %[file]... done\n", + @"file", fileName)]; + } outer_loop_end: objc_autoreleasePoolPop(pool); } if ([missing count] > 0) { for (OFString *file in missing) - [of_stderr writeFormat: - @"File %@ is not in the archive!\n", file]; + [of_stderr writeLine: OF_LOCALIZED( + @"file_not_in_archive", + @"File %[file] is not in the archive!", + @"file", file)]; app->_exitStatus = 1; } } @@ -260,23 +330,25 @@ - (void)printFiles: (OFArray OF_GENERIC(OFString*)*)files { OFStream *stream; if ([files count] < 1) { - [of_stderr writeLine: @"Need one or more files to print!"]; + [of_stderr writeLine: OF_LOCALIZED(@"print_no_file_specified", + @"Need one or more files to print!")]; app->_exitStatus = 1; return; } for (OFString *path in files) { @try { stream = [_archive streamForReadingFile: path]; } @catch (OFOpenItemFailedException *e) { if ([e errNo] == ENOENT) { - [of_stderr writeFormat: - @"File %@ is not in the archive!\n", - [e path]]; + [of_stderr writeLine: OF_LOCALIZED( + @"file_not_in_archive", + @"File %[file] is not in the archive!", + @"file", [e path])]; app->_exitStatus = 1; continue; } @throw e; ADDED utils/ofzip/lang/de.json Index: utils/ofzip/lang/de.json ================================================================== --- utils/ofzip/lang/de.json +++ utils/ofzip/lang/de.json @@ -0,0 +1,85 @@ +{ + "usage": [ + "Benutzung: %[prog] -[fhlnpqtvx] archiv.zip [datei1 datei2 ...]" + ], + "full_usage": [ + "Optionen:\n", + " -f --force Existierende Dateien überschreiben\n", + " -h --help Diese Hilfe anzeigen\n", + " -l --list Alle Dateien im Archiv auflisten\n", + " -n --no-clober Dateien niemals überschreiben\n", + " -p --print Eine oder mehr Dateien aus dem Archiv ausgeben\n", + " -q --quiet Ruhiger Modus (keine Ausgabe außer Fehler)\n", + " -t --type Archiv-Typ (gz, tar, tgz, zip)\n", + " -v --verbose Ausführlicher Modus für Datei-Liste\n", + " -x --extract Dateien entpacken" + ], + "2_options_mutually_exclusive": [ + "Fehler: -%[shortopt1] / --%[longopt1] und ", + "-%[shortopt2] / --%[longopt2] schließen sich gegenseitig aus!" + ], + "3_options_mutually_exclusive": [ + "Fehler: -%[shortopt1] / --%[longopt1], -%[shortopt2] / --%[longopt2] ", + "und -%[shortopt3] / --%[longopt3] schließen sich gegenseitig aus!" + ], + "option_takes_no_argument": "%[prog]: Option --%[opt] nimmt kein Argument", + "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]", + "unknown_option": "%[prog]: Unbekannte Option: -%[opt]", + "failed_to_create_directory": [ + "Fehler beim Erstellen des Verzeichnis %[dir]: %[error]" + ], + "failed_to_open_file": "Fehler beim Öffnen der Datei %[file]: %[error]", + "unknown_archive_type": "Unbekannter Archivtyp: %[type]", + "failed_to_read_file": "Fehler beim Lesen von Datei %[file]: %[error]", + "failed_to_write_file": "Fehler beim Schreiben Datei %[file]: %[error]", + "failed_to_seek_in_file": "Fehler beim Suchen in Datei %[file]: %[error]", + "file_is_not_a_valid_archiv": "Datei %[file] ist kein gültiges Archiv!", + "file_skipped": "übersprungen", + "ask_overwrite": "%[file] überschreiben? [ynAN?]", + "ask_overwrite_help": [ + " y: Ja\n", + " n: Nein\n", + " A: Immer\n", + " N: Nie" + ], + "skipping_file": "Überspringe %[file]...", + "extracting_file": "Entpacke %[file]...", + "extracting_file_percent": "Entpacke %[file]... %[percent]%", + "extracting_file_done": "Entpacke %[file]... fertig", + "cannot_list_gz": "Kann Dateien eines .gz-Archivs nicht auflisten!", + "cannot_extract_specific_file_from_gz": [ + "Kann keine spezifische Datei aus einem .gz-Archiv entpacken!" + ], + "cannot_print_specific_file_from_gz": [ + "Kann keine spezifische Datei aus einem .gz-Archiv ausgeben!" + ], + "list_size": "Größe: %[size] Bytes", + "list_mode": "Modus: %[mode]", + "list_owner": "Besitzer: %[owner]", + "list_group": "Gruppe: %[group]", + "list_modification_date": "Änderungsdatum: %[date]", + "list_type_normal": "Typ: Normale Datei", + "list_type_hardlink": "Typ: Harter Link", + "list_type_symlink": "Typ: Symbolischer Link", + "list_link_target": "Zieldateiname: %[target]", + "list_type_character_device": "Typ: Zeichenorientiertes Gerät", + "list_type_block_device": "Typ: Blockorientiertes Gerät", + "list_device_major": "Major-Nummer des Geräts: %[major]", + "list_device_minor": "Minor-Nummer des Geräts: %[minor]", + "list_type_directory": "Typ: Verzeichnis", + "list_type_fifo": "Typ: FIFO", + "list_type_contiguous_file": "Typ: Zusammenhängende Datei", + "list_type_unknown": "Typ: Unbekannt", + "list_compressed_size": "Komprimierte Größe: %[size] Bytes", + "list_uncompressed_size": "Unkomprimierte Größe: %[size] Bytes", + "list_version_made_by": "Erstellt mit Version: %[version]", + "list_min_version_needed": "Mindestens benötigte Version: %[version]", + "list_general_purpose_bit_flag": "General Purpose Bit Flag: %[gpbf]", + "list_extra_field": "Extra-Feld: %[extra]", + "list_comment": "Kommentar: %[comment]", + "refusing_to_extract_file": "Verweigere Entpacken von %[file]!", + "file_not_in_archive": "Datei %[file] ist nicht im Archiv!", + "print_no_file_specified": [ + "Benötige eine oder mehrere Dateien zum Ausgeben!" + ] +} ADDED utils/ofzip/lang/languages.json Index: utils/ofzip/lang/languages.json ================================================================== --- utils/ofzip/lang/languages.json +++ utils/ofzip/lang/languages.json @@ -0,0 +1,8 @@ +{ + "de": { + "": "de" + }, + "german": { + "": "de" + } +}