Index: src/OFLocale.h ================================================================== --- src/OFLocale.h +++ src/OFLocale.h @@ -181,16 +181,16 @@ * @note Generally, you want to use @ref OF_LOCALIZED instead, which also takes * care of the `nil` sentinel automatically. * * @param ID The ID for the localized string * @param fallback The fallback to use in case the localized string cannot be - * looked up or is missing + * looked up or is missing. This can also be an array and use + * plural scripting, just like with the JSON language files. * @return The localized string */ - (OFString *)localizedStringForID: (OFConstantString *)ID - fallback: (OFConstantString *)fallback, ... - OF_SENTINEL; + fallback: (id)fallback, ... OF_SENTINEL; /*! * @brief Returns the localized string for the specified ID, using the fallback * string if it cannot be looked up or is missing. * @@ -203,17 +203,18 @@ * @note Generally, you want to use @ref OF_LOCALIZED instead, which also takes * care of the `nil` sentinel automatically. * * @param ID The ID for the localized string * @param fallback The fallback to use in case the localized string cannot be - * looked up or is missing + * looked up or is missing. This can also be an array and use + * plural scripting, just like with the JSON language files. * @param arguments A va_list of arguments, consisting of pairs of variable * names and values to replace in the localized string, * terminated with `nil` * @return The localized string */ - (OFString *)localizedStringForID: (OFConstantString *)ID - fallback: (OFConstantString *)fallback + fallback: (id)fallback arguments: (va_list)arguments; @end OF_ASSUME_NONNULL_END Index: src/OFLocale.m ================================================================== --- src/OFLocale.m +++ src/OFLocale.m @@ -544,11 +544,11 @@ objc_autoreleasePoolPop(pool); } #endif - (OFString *)localizedStringForID: (OFConstantString *)ID - fallback: (OFConstantString *)fallback, ... + fallback: (id)fallback, ... { OFString *ret; va_list args; va_start(args, fallback); @@ -559,11 +559,11 @@ return ret; } - (OFString *)localizedStringForID: (OFConstantString *)ID - fallback: (OFConstantString *)fallback + fallback: (id)fallback arguments: (va_list)arguments { OFMutableString *ret = [OFMutableString string]; void *pool = objc_autoreleasePoolPush(); OFMutableDictionary *variables; @@ -590,12 +590,15 @@ UTF8StringLength = [string UTF8StringLength]; break; } if (UTF8String == NULL) { - UTF8String = fallback.UTF8String; - UTF8StringLength = fallback.UTF8StringLength; + if ([fallback isKindOfClass: [OFArray class]]) + fallback = evaluateArray(fallback, variables); + + UTF8String = [fallback UTF8String]; + UTF8StringLength = [fallback UTF8StringLength]; } state = 0; last = 0; for (size_t i = 0; i < UTF8StringLength; i++) { Index: utils/ofarc/LHAArchive.m ================================================================== --- utils/ofarc/LHAArchive.m +++ utils/ofarc/LHAArchive.m @@ -119,16 +119,28 @@ @"%04" PRIX16, entry.CRC16]; [of_stdout writeString: @"\t"]; [of_stdout writeLine: OF_LOCALIZED( @"list_compressed_size", - @"Compressed: %[size] bytes", + [@"[" + @" 'Compressed: '," + @" [" + @" {'size == 1': '1 byte'}," + @" {'': '%[size] bytes'}" + @" ]" + @"]" JSONValue], @"size", compressedSize)]; [of_stdout writeString: @"\t"]; [of_stdout writeLine: OF_LOCALIZED( @"list_uncompressed_size", - @"Uncompressed: %[size] bytes", + [@"[" + @" 'Uncompressed: '," + @" [" + @" {'size == 1': '1 byte'}," + @" {'': '%[size] bytes'}" + @" ]" + @"]" JSONValue], @"size", uncompressedSize)]; [of_stdout writeString: @"\t"]; [of_stdout writeLine: OF_LOCALIZED( @"list_compression_method", @"Compression method: %[method]", Index: utils/ofarc/TarArchive.m ================================================================== --- utils/ofarc/TarArchive.m +++ utils/ofarc/TarArchive.m @@ -108,11 +108,17 @@ OFString *GID = [OFString stringWithFormat: @"%u", entry.GID]; [of_stdout writeString: @"\t"]; [of_stdout writeLine: OF_LOCALIZED(@"list_size", - @"Size: %[size] bytes", + [@"[" + @" 'Size: '," + @" [" + @" {'size == 1': '1 byte'}," + @" {'': '%[size] bytes'}" + @" ]" + @"]" JSONValue], @"size", size)]; [of_stdout writeString: @"\t"]; [of_stdout writeLine: OF_LOCALIZED(@"list_mode", @"Mode: %[mode]", @"mode", mode)]; Index: utils/ofarc/ZIPArchive.m ================================================================== --- utils/ofarc/ZIPArchive.m +++ utils/ofarc/ZIPArchive.m @@ -120,16 +120,28 @@ localDateStringWithFormat: @"%Y-%m-%d %H:%M:%S"]; [of_stdout writeString: @"\t"]; [of_stdout writeLine: OF_LOCALIZED( @"list_compressed_size", - @"Compressed: %[size] bytes", + [@"[" + @" 'Compressed: '," + @" [" + @" {'size == 1': '1 byte'}," + @" {'': '%[size] bytes'}" + @" ]" + @"]" JSONValue], @"size", compressedSize)]; [of_stdout writeString: @"\t"]; [of_stdout writeLine: OF_LOCALIZED( @"list_uncompressed_size", - @"Uncompressed: %[size] bytes", + [@"[" + @" 'Uncompressed: '," + @" [" + @" {'size == 1': '1 byte'}," + @" {'': '%[size] bytes'}" + @" ]" + @"]" JSONValue], @"size", uncompressedSize)]; [of_stdout writeString: @"\t"]; [of_stdout writeLine: OF_LOCALIZED( @"list_compression_method", @"Compression method: %[method]", Index: utils/ofhttp/OFHTTP.m ================================================================== --- utils/ofhttp/OFHTTP.m +++ utils/ofhttp/OFHTTP.m @@ -810,11 +810,16 @@ @"num", lengthString); } else { lengthString = [OFString stringWithFormat: @"%jd", _resumedFrom + _length]; lengthString = OF_LOCALIZED(@"size_bytes", - @"%[num] bytes", + [@"[" + @" [" + @" {'num == 1': '1 byte'}," + @" {'': '%[num] bytes'}" + @" ]" + @"]" JSONValue], @"num", lengthString); } } else lengthString = OF_LOCALIZED(@"size_unknown", @"unknown"); Index: utils/ofhttp/ProgressBar.m ================================================================== --- utils/ofhttp/ProgressBar.m +++ utils/ofhttp/ProgressBar.m @@ -202,11 +202,16 @@ @"num", num)]; } else { OFString *num = [OFString stringWithFormat: @"%jd", _resumedFrom + _received]; [of_stdout writeString: OF_LOCALIZED(@"progress_bytes", - @"%[num] bytes", + [@"[" + @" [" + @" {'num == 1': '1 byte '}," + @" {'': '%[num] bytes'}" + @" ]" + @"]" JSONValue], @"num", num)]; } [of_stdout writeString: @" "]; Index: utils/ofhttp/lang/de.json ================================================================== --- utils/ofhttp/lang/de.json +++ utils/ofhttp/lang/de.json @@ -95,10 +95,10 @@ "%[prog]: Kann Datei %[filename] nicht öffnen: %[exception]" ], "eta_days": "%[num] t ", "progress_bytes": [ [ - {"num == 1": "1 Byte"}, + {"num == 1": "1 Byte "}, {"": "%[num] Bytes"} ] ] }