Merge branch 'fix-26903' into 'master'

cli tar: support encoding specifying

Closes #26903

See merge request cmake/cmake!11601
This commit is contained in:
Alex Overchenko 2026-01-17 13:26:06 -05:00
commit 120d53ffd0
35 changed files with 356 additions and 36 deletions

View File

@ -217,3 +217,40 @@ CPack generators which are essentially archives at their core. These include:
It is selected automatically by the archive library backend and
not directly set by CMake itself. The default compression level
may vary between archive formats, platforms, etc.
.. variable:: CPACK_ARCHIVE_ENCODING
.. versionadded:: 4.3
The encoding to be used for file names & paths when archive creation.
:Default: ``UTF-8`` or ``OEM``, see next description
The value is directly passed to the libarchive,
except the ``OEM`` value.
The value is silently ignored for ``7zip`` format, which only supports
``UTF-16LE``.
Possible encoding values:
* ``UTF-8``
Use the UTF-8 codepage.
It manages the same way as ``OEM`` value for non-Windows platforms.
This is the default since CMake 4.3.
* ``OEM``
Use the original equipment manufacturer (OEM) code page.
This value is platform-dependent and not managed by CMake directly -
libarchive internally selects the headers encoding.
This was the default in CMake 4.2 and older.
* ``...``
Any other codepage, directly supported by libarchive.
Such as ``UTF-16LE`` or ``UTF-16BE`` or ``CP932`` for some formats.

View File

@ -1580,6 +1580,40 @@ Available commands are:
not directly set by CMake itself. The default compression level
may vary between archive formats, platforms, etc.
.. option:: --cmake-tar-encoding=<encoding>
.. versionadded:: 4.3
Specify the encoding for header reading.
The value is directly passed to the libarchive,
except the ``OEM`` value.
The value is silently ignored for ``7zip`` format, which only supports
``UTF-16LE``.
Possible encoding values:
* ``UTF-8``
Use the UTF-8 codepage.
It manages the same way as ``OEM`` value for non-Windows platforms.
This is the default since CMake 4.3.
* ``OEM``
Use the original equipment manufacturer (OEM) code page.
This value is platform-dependent and not managed by CMake directly -
libarchive internally selects the headers encoding.
This was the default in CMake 4.2 and older.
* ``...``
Any other codepage, directly supported by libarchive. Such as ``UTF-16LE`` or ``UTF-16BE`` or ``CP932`` for some formats.
.. option:: --cmake-tar-threads=<number>
.. versionadded:: 4.3

View File

@ -0,0 +1,8 @@
cli-tar-encoding
-------------------
* The :manual:`cmake(1)` ``-E tar`` tool supports headers encoding change
via ``--cmake-tar-encoding`` option
* The :cpack_gen:`CPack Archive Generator` gained a new variable
:variable:`CPACK_ARCHIVE_ENCODING` to control the
file names encoding used when creating archive packages.

View File

@ -393,7 +393,7 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
return 0; \
} \
cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat, \
this->GetCompressionLevel(), \
this->GetEncoding(), this->GetCompressionLevel(), \
this->GetThreadCount()); \
if (this->UID >= 0 && this->GID >= 0) { \
archive.SetUIDAndGID(this->UID, this->GID); \
@ -610,3 +610,14 @@ int cmCPackArchiveGenerator::GetCompressionLevel() const
return level;
}
std::string cmCPackArchiveGenerator::GetEncoding() const
{
std::string encoding = "UTF-8";
if (cmValue v = this->GetOptionIfSet("CPACK_ARCHIVE_ENCODING")) {
encoding = *v;
}
return encoding;
}

View File

@ -106,6 +106,7 @@ private:
int GetThreadCount() const;
int GetCompressionLevel() const;
std::string GetEncoding() const;
private:
cmArchiveWrite::Compress Compress;

View File

@ -206,9 +206,9 @@ bool DebGenerator::generateDataTar() const
<< filename_data_tar << "\" for writing" << std::endl);
return false;
}
cmArchiveWrite data_tar(fileStream_data_tar, this->TarCompressionType,
this->DebianArchiveType, this->CompressionLevel,
static_cast<int>(this->NumThreads));
cmArchiveWrite data_tar(
fileStream_data_tar, this->TarCompressionType, this->DebianArchiveType,
"UTF-8", this->CompressionLevel, static_cast<int>(this->NumThreads));
if (!data_tar.Open()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error opening the archive \""
@ -339,7 +339,8 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
return false;
}
cmArchiveWrite control_tar(fileStream_control_tar, this->TarCompressionType,
this->DebianArchiveType, this->CompressionLevel);
this->DebianArchiveType, "UTF-8",
this->CompressionLevel);
if (!control_tar.Open()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error opening the archive \""

View File

@ -79,8 +79,9 @@ struct cmArchiveWrite::Callback
};
cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
std::string const& format, int compressionLevel,
int numThreads)
std::string const& format,
std::string const& encoding,
int compressionLevel, int numThreads)
: Stream(os)
, Archive(archive_write_new())
, Disk(archive_read_disk_new())
@ -209,6 +210,28 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
}
}
#ifdef _WIN32
constexpr bool isWindows = true;
#else
constexpr bool isWindows = false;
#endif
// 7zip always uses UTF16-LE for the headers and doesn't support
// header encoding specification.
//
// Non-Windows encodings are UTF-8 by default - force them to use OEM
// We have no embedded iconv support to truly assume OEM is UTF-8
if (!is7zip && encoding != "OEM" && (isWindows || encoding != "UTF-8")) {
char const* formatForOptions = format == "paxr" ? "pax" : format.c_str();
if (archive_write_set_format_option(this->Archive, formatForOptions,
"hdrcharset",
encoding.c_str()) != ARCHIVE_OK) {
this->Error = cmStrCat("archive_write_set_format_option(hdrcharset): ",
cm_archive_error_string(this->Archive));
return;
}
}
if (isFormatSupportsCompressionNatively || compressionLevel != 0) {
std::string compressionLevelStr = std::to_string(compressionLevel);
std::string archiveFilterName;

View File

@ -55,8 +55,9 @@ public:
/** Construct with output stream to which to write archive. */
cmArchiveWrite(std::ostream& os, Compress c = CompressNone,
std::string const& format = "paxr", int compressionLevel = 0,
int numThreads = 1);
std::string const& format = "paxr",
std::string const& encoding = "UTF-8",
int compressionLevel = 0, int numThreads = 1);
~cmArchiveWrite();

View File

@ -1250,8 +1250,8 @@ std::string cmCTest::Base64GzipEncodeFile(std::string const& file)
std::vector<std::string> files;
files.push_back(file);
if (!cmSystemTools::CreateTar(tarFile, files, {},
cmSystemTools::TarCompressGZip, false)) {
if (!cmSystemTools::CreateTar(
tarFile, files, {}, cmSystemTools::TarCompressGZip, "UTF-8", false)) {
cmCTestLog(this, ERROR_MESSAGE,
"Error creating tar while "
"encoding file: "

View File

@ -3813,8 +3813,8 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
if (!cmSystemTools::CreateTar(
parsedArgs.Output, parsedArgs.Paths, parsedArgs.WorkingDirectory,
compress, parsedArgs.Verbose, parsedArgs.MTime, parsedArgs.Format,
compressionLevel, threads)) {
compress, "OEM", parsedArgs.Verbose, parsedArgs.MTime,
parsedArgs.Format, compressionLevel, threads)) {
status.SetError(cmStrCat("failed to compress: ", parsedArgs.Output));
cmSystemTools::SetFatalErrorOccurred();
return false;
@ -3862,7 +3862,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
std::string inFile = parsedArgs.Input;
if (parsedArgs.ListOnly) {
if (!cmSystemTools::ListTar(inFile, parsedArgs.Patterns,
if (!cmSystemTools::ListTar(inFile, parsedArgs.Patterns, "OEM",
parsedArgs.Verbose)) {
status.SetError(cmStrCat("failed to list: ", inFile));
cmSystemTools::SetFatalErrorOccurred();
@ -3900,7 +3900,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
inFile, parsedArgs.Patterns,
parsedArgs.Touch ? cmSystemTools::cmTarExtractTimestamps::No
: cmSystemTools::cmTarExtractTimestamps::Yes,
parsedArgs.Verbose)) {
"OEM", parsedArgs.Verbose)) {
status.SetError(cmStrCat("failed to extract: ", inFile));
cmSystemTools::SetFatalErrorOccurred();
return false;

View File

@ -2368,13 +2368,11 @@ bool cmSystemTools::IsPathToMacOSSharedLibrary(std::string const& path)
cmHasLiteralSuffix(path, ".dylib"));
}
bool cmSystemTools::CreateTar(std::string const& outFileName,
std::vector<std::string> const& files,
std::string const& workingDirectory,
cmTarCompression compressType, bool verbose,
std::string const& mtime,
std::string const& format, int compressionLevel,
int numThreads)
bool cmSystemTools::CreateTar(
std::string const& outFileName, std::vector<std::string> const& files,
std::string const& workingDirectory, cmTarCompression compressType,
std::string const& encoding, bool verbose, std::string const& mtime,
std::string const& format, int compressionLevel, int numThreads)
{
#if !defined(CMAKE_BOOTSTRAP)
cmWorkingDirectory workdir(cmSystemTools::GetLogicalWorkingDirectory());
@ -2425,7 +2423,7 @@ bool cmSystemTools::CreateTar(std::string const& outFileName,
break;
}
cmArchiveWrite a(fout, compress, format.empty() ? "paxr" : format,
cmArchiveWrite a(fout, compress, format.empty() ? "paxr" : format, encoding,
compressionLevel, numThreads);
if (!a.Open()) {
@ -2449,6 +2447,7 @@ bool cmSystemTools::CreateTar(std::string const& outFileName,
#else
(void)outFileName;
(void)files;
(void)encoding;
(void)verbose;
return false;
#endif
@ -2628,7 +2627,8 @@ bool copy_data(struct archive* ar, struct archive* aw)
}
bool extract_tar(std::string const& outFileName,
std::vector<std::string> const& files, bool verbose,
std::vector<std::string> const& files,
std::string const& encoding, bool verbose,
cmSystemTools::cmTarExtractTimestamps extractTimestamps,
bool extract)
{
@ -2638,6 +2638,22 @@ bool extract_tar(std::string const& outFileName,
struct archive* ext = archive_write_disk_new();
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
# ifdef _WIN32
constexpr bool isWindows = true;
# else
constexpr bool isWindows = false;
# endif
// Non-Windows encodings are UTF-8 by default - force them to use OEM
// We have no embedded iconv support to truly assume OEM is UTF-8
if (encoding != "OEM" && (isWindows || encoding != "UTF-8")) {
if (archive_read_set_options(
a, cmStrCat("hdrcharset=", encoding).c_str()) != ARCHIVE_OK) {
cmSystemTools::Error("Cannot set archive sencoding: " + encoding);
return false;
}
}
struct archive_entry* entry;
struct archive* matching = archive_match_new();
@ -2753,14 +2769,16 @@ bool extract_tar(std::string const& outFileName,
bool cmSystemTools::ExtractTar(std::string const& outFileName,
std::vector<std::string> const& files,
cmTarExtractTimestamps extractTimestamps,
bool verbose)
std::string const& encoding, bool verbose)
{
#if !defined(CMAKE_BOOTSTRAP)
return extract_tar(outFileName, files, verbose, extractTimestamps, true);
return extract_tar(outFileName, files, encoding, verbose, extractTimestamps,
true);
#else
(void)outFileName;
(void)files;
(void)extractTimestamps;
(void)encoding;
(void)verbose;
return false;
#endif
@ -2768,14 +2786,15 @@ bool cmSystemTools::ExtractTar(std::string const& outFileName,
bool cmSystemTools::ListTar(std::string const& outFileName,
std::vector<std::string> const& files,
bool verbose)
std::string const& encoding, bool verbose)
{
#if !defined(CMAKE_BOOTSTRAP)
return extract_tar(outFileName, files, verbose, cmTarExtractTimestamps::Yes,
false);
return extract_tar(outFileName, files, encoding, verbose,
cmTarExtractTimestamps::Yes, false);
#else
(void)outFileName;
(void)files;
(void)encoding;
(void)verbose;
return false;
#endif

View File

@ -560,18 +560,20 @@ public:
};
static bool ListTar(std::string const& outFileName,
std::vector<std::string> const& files, bool verbose);
std::vector<std::string> const& files,
std::string const& encoding, bool verbose);
static bool CreateTar(std::string const& outFileName,
std::vector<std::string> const& files,
std::string const& workingDirectory,
cmTarCompression compressType, bool verbose,
cmTarCompression compressType,
std::string const& encoding, bool verbose,
std::string const& mtime = std::string(),
std::string const& format = std::string(),
int compressionLevel = 0, int numThreads = 1);
static bool ExtractTar(std::string const& inFileName,
std::vector<std::string> const& files,
cmTarExtractTimestamps extractTimestamps,
bool verbose);
std::string const& encoding, bool verbose);
/** Random number generation. */
static unsigned int RandomSeed();

View File

@ -1593,6 +1593,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
cmSystemTools::TarCompressAuto;
int nCompress = 0;
bool doing_options = true;
std::string encoding = "UTF-8";
for (auto const& arg : cmMakeRange(args).advance(4)) {
if (doing_options && cmHasLiteralPrefix(arg, "--")) {
if (arg == "--") {
@ -1630,6 +1631,13 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
}
numThreads = static_cast<decltype(numThreads)>(numThreadsLong);
} else if (cmHasLiteralPrefix(arg, "--cmake-tar-encoding=")) {
encoding = arg.substr(21);
if (encoding.empty()) {
cmSystemTools::Error(
"Encoding value is empty - it must be filled if passed");
return 1;
}
} else if (cmHasLiteralPrefix(arg,
"--cmake-tar-compression-level=")) {
std::string const& compressionLevelStr = arg.substr(30);
@ -1779,7 +1787,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
}
if (action == cmSystemTools::TarActionList) {
if (!cmSystemTools::ListTar(outFile, files, verbose)) {
if (!cmSystemTools::ListTar(outFile, files, encoding, verbose)) {
cmSystemTools::Error("Problem listing tar: " + outFile);
return 1;
}
@ -1787,15 +1795,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
if (files.empty()) {
std::cerr << "tar: No files or directories specified\n";
}
if (!cmSystemTools::CreateTar(outFile, files, {}, compress, verbose,
mtime, format, compressionLevel,
if (!cmSystemTools::CreateTar(outFile, files, {}, compress, encoding,
verbose, mtime, format, compressionLevel,
numThreads)) {
cmSystemTools::Error("Problem creating tar: " + outFile);
return 1;
}
} else if (action == cmSystemTools::TarActionExtract) {
if (!cmSystemTools::ExtractTar(outFile, files, extractTimestamps,
verbose)) {
encoding, verbose)) {
cmSystemTools::Error("Problem extracting tar: " + outFile);
return 1;
}

View File

@ -1 +1,2 @@
set(CPACK_ARCHIVE_COMPONENT_INSTALL "ON")
set(CPACK_ARCHIVE_ENCODING "OEM")

View File

@ -1 +1,2 @@
set(CPACK_ARCHIVE_COMPONENT_INSTALL "ON")
set(CPACK_ARCHIVE_ENCODING "OEM")

View File

@ -1,2 +1,3 @@
set(CPACK_ARCHIVE_COMPONENT_INSTALL "ON")
set(CPACK_ARCHIVE_COMPRESSION_LEVEL 4)
set(CPACK_ARCHIVE_ENCODING "UTF-8")

View File

@ -119,6 +119,25 @@ run_cmake(compression-method-lzma)
run_cmake(compression-method-zstd)
run_cmake(compression-method-ppmd)
# Encoding
if (WIN32)
run_cmake(bad-encoding-oem-gnutar)
run_cmake(bad-encoding-oem-zip)
else()
run_cmake(encoding-oem-gnutar)
run_cmake(encoding-oem-zip)
endif()
run_cmake(encoding-oem-7zip)
run_cmake(encoding-oem-pax)
run_cmake(encoding-oem-paxr)
run_cmake(encoding-utf-8-7zip)
run_cmake(encoding-utf-8-gnutar)
run_cmake(encoding-utf-8-pax)
run_cmake(encoding-utf-8-paxr)
run_cmake(encoding-utf-8-zip)
# Extracting only selected files or directories
run_cmake(zip-filtered)

View File

@ -0,0 +1,4 @@
^CMake Error: archive_write_header: Can't translate [Pp]athname '.*\.txt' to .*
CMake Error: Problem creating tar: [^
]*/bad\.tar
CMake Error at roundtrip\.cmake:[0-9]+ \(message\):

View File

@ -0,0 +1,11 @@
set(OUTPUT_NAME "bad.tar")
set(COMPRESSION_FLAGS cvf)
set(COMPRESSION_OPTIONS --format=gnutar --cmake-tar-encoding=OEM)
include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
set(DECOMPRESSION_FLAGS xvf)
include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
^CMake Error: archive_write_header: Can't translate [Pp]athname '.*\.txt' to .*
CMake Error: Problem creating tar: [^
]*/bad\.zip
CMake Error at roundtrip\.cmake:[0-9]+ \(message\):

View File

@ -0,0 +1,11 @@
set(OUTPUT_NAME "bad.zip")
set(COMPRESSION_FLAGS cvf)
set(COMPRESSION_OPTIONS --format=zip --cmake-tar-encoding=OEM)
include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
set(DECOMPRESSION_FLAGS xvf)
include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
check_magic("504b0304" LIMIT 4 HEX)

View File

@ -0,0 +1,11 @@
set(OUTPUT_NAME "test.7z")
set(COMPRESSION_FLAGS cvf)
set(COMPRESSION_OPTIONS --format=7zip --cmake-tar-encoding=OEM)
include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
set(DECOMPRESSION_FLAGS xvf)
include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
check_magic("377abcaf271c" LIMIT 6 HEX)

View File

@ -0,0 +1,11 @@
set(OUTPUT_NAME "test.tar")
set(COMPRESSION_FLAGS cvf)
set(COMPRESSION_OPTIONS --format=gnutar --cmake-tar-encoding=OEM)
include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
set(DECOMPRESSION_FLAGS xvf)
include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX)

View File

@ -0,0 +1,11 @@
set(OUTPUT_NAME "test.tar")
set(COMPRESSION_FLAGS cvf)
set(COMPRESSION_OPTIONS --format=pax --cmake-tar-encoding=OEM)
include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
set(DECOMPRESSION_FLAGS xvf)
include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX)

View File

@ -0,0 +1,11 @@
set(OUTPUT_NAME "test.tar")
set(COMPRESSION_FLAGS cvf)
set(COMPRESSION_OPTIONS --format=paxr --cmake-tar-encoding=OEM)
include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
set(DECOMPRESSION_FLAGS xvf)
include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX)

View File

@ -0,0 +1,11 @@
set(OUTPUT_NAME "test.zip")
set(COMPRESSION_FLAGS cvf)
set(COMPRESSION_OPTIONS --format=zip --cmake-tar-encoding=OEM)
include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
set(DECOMPRESSION_FLAGS xvf)
include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
check_magic("504b0304" LIMIT 4 HEX)

View File

@ -0,0 +1,11 @@
set(OUTPUT_NAME "test.7z")
set(COMPRESSION_FLAGS cvf)
set(COMPRESSION_OPTIONS --format=7zip --cmake-tar-encoding=UTF-8)
include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
set(DECOMPRESSION_FLAGS xvf)
include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
check_magic("377abcaf271c" LIMIT 6 HEX)

View File

@ -0,0 +1,11 @@
set(OUTPUT_NAME "test.tar")
set(COMPRESSION_FLAGS cvf)
set(COMPRESSION_OPTIONS --format=gnutar --cmake-tar-encoding=UTF-8)
include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
set(DECOMPRESSION_FLAGS xvf)
include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX)

View File

@ -0,0 +1,11 @@
set(OUTPUT_NAME "test.tar")
set(COMPRESSION_FLAGS cvf)
set(COMPRESSION_OPTIONS --format=pax --cmake-tar-encoding=UTF-8)
include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
set(DECOMPRESSION_FLAGS xvf)
include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX)

View File

@ -0,0 +1,11 @@
set(OUTPUT_NAME "test.tar")
set(COMPRESSION_FLAGS cvf)
set(COMPRESSION_OPTIONS --format=paxr --cmake-tar-encoding=UTF-8)
include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
set(DECOMPRESSION_FLAGS xvf)
include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX)

View File

@ -0,0 +1,11 @@
set(OUTPUT_NAME "test.zip")
set(COMPRESSION_FLAGS cvf)
set(COMPRESSION_OPTIONS --format=zip --cmake-tar-encoding=UTF-8)
include(${CMAKE_CURRENT_LIST_DIR}/utf-8-paths.cmake)
set(DECOMPRESSION_FLAGS xvf)
include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake)
check_magic("504b0304" LIMIT 4 HEX)

View File

@ -31,6 +31,7 @@ set(CHECK_FILES
"d_4/f1.txt"
"d-4/f1.txt"
"My Special Directory/f1.txt"
${COMPRESSION_ADDITIONAL_FILE_NAMES}
)
foreach(file ${CHECK_FILES})

View File

@ -0,0 +1,10 @@
list(APPEND COMPRESSION_ADDITIONAL_FILE_NAMES
"arabic-نَسِيج.txt"
"armenian-Բարեւ ձեզ.txt"
"chinese-.txt"
"cyrillic-привет.txt"
"greek-Γεια.txt"
"hungarian-hűtő.txt"
"japanese-.txt"
"korean-.txt"
)