mirror of
https://github.com/transmission/transmission
synced 2025-02-20 13:16:53 +00:00
fix: use user-preferred locale (#5444)
* Use user-preferred locale Previous fix adding `L` format specifier was correct but only fixed half of the problem, as C++ locale is set up to be "C" by default. GTK client used to call `setlocale(LC_ALL, "")` to set up user-preferred locale which only affected C functions and `std::locale` (used by libfmt) was unaware of those changes. Apply the fix to all the binaries since they're all doing some sort of output to the user and calling libtransmission helpers, as well as using libfmt directly. * Improve libtransmission's json-test Set the locale C++ way to avoid any sort of inconsistencies, and also restore it to the old one once finished testing. * Improve transmission-show test runner script Quote outputs to avoid CMake error about `message()` being called with no arguments. Capture stderr to the same output file. Fallback to `git diff` if `diff` wasn't found. A few other minor changes.
This commit is contained in:
parent
02b8535aa1
commit
411b66cf88
13 changed files with 78 additions and 14 deletions
|
@ -197,6 +197,8 @@ static std::string getConfigDir(int argc, char const** argv)
|
|||
|
||||
int tr_main(int argc, char* argv[])
|
||||
{
|
||||
tr_locale_set_global("");
|
||||
|
||||
tr_variant settings;
|
||||
|
||||
tr_formatter_mem_init(MemK, MemKStr, MemMStr, MemGStr, MemTStr);
|
||||
|
|
|
@ -939,6 +939,8 @@ void tr_daemon::handle_error(tr_error* error) const
|
|||
|
||||
int tr_main(int argc, char* argv[])
|
||||
{
|
||||
tr_locale_set_global("");
|
||||
|
||||
int ret;
|
||||
tr_daemon daemon;
|
||||
bool foreground;
|
||||
|
|
|
@ -27,10 +27,8 @@
|
|||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <clocale>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -53,7 +51,7 @@ Glib::OptionEntry create_option_entry(Glib::ustring const& long_name, gchar shor
|
|||
int main(int argc, char** argv)
|
||||
{
|
||||
/* init i18n */
|
||||
std::ignore = std::setlocale(LC_ALL, "");
|
||||
tr_locale_set_global("");
|
||||
bindtextdomain(AppTranslationDomainName, TRANSMISSIONLOCALEDIR);
|
||||
bind_textdomain_codeset(AppTranslationDomainName, "UTF-8");
|
||||
textdomain(AppTranslationDomainName);
|
||||
|
|
|
@ -14,11 +14,14 @@
|
|||
#include <cstdlib> // getenv()
|
||||
#include <cstring> /* strerror() */
|
||||
#include <ctime> // nanosleep()
|
||||
#include <iostream>
|
||||
#include <iterator> // for std::back_inserter
|
||||
#include <locale>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -60,6 +63,23 @@ time_t libtransmission::detail::tr_time::current_time = {};
|
|||
|
||||
// ---
|
||||
|
||||
void tr_locale_set_global(char const* locale_name) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
std::ignore = std::locale::global(std::locale{ locale_name });
|
||||
|
||||
std::ignore = std::cout.imbue(std::locale{});
|
||||
std::ignore = std::cerr.imbue(std::locale{});
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
// Ignore.
|
||||
}
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
bool tr_loadFile(std::string_view filename, std::vector<char>& contents, tr_error** error)
|
||||
{
|
||||
auto const szfilename = tr_pathbuf{ filename };
|
||||
|
|
|
@ -56,6 +56,8 @@ struct tr_error;
|
|||
#define tr_ngettext(singular, plural, count) ((count) == 1 ? (singular) : (plural))
|
||||
#endif
|
||||
|
||||
void tr_locale_set_global(char const* locale_name) noexcept;
|
||||
|
||||
// ---
|
||||
|
||||
[[nodiscard]] std::string_view tr_get_mime_type_for_filename(std::string_view filename);
|
||||
|
|
|
@ -4,7 +4,13 @@
|
|||
|
||||
@import AppKit;
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
|
||||
#include <libtransmission/utils.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
tr_locale_set_global("");
|
||||
|
||||
return NSApplicationMain(argc, (char const**)argv);
|
||||
}
|
||||
|
|
|
@ -667,6 +667,8 @@ FaviconCache& Application::faviconCache()
|
|||
|
||||
int tr_main(int argc, char** argv)
|
||||
{
|
||||
tr_locale_set_global("");
|
||||
|
||||
InteropHelper::initialize();
|
||||
|
||||
Application const app(argc, argv);
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
|
||||
#define LIBTRANSMISSION_VARIANT_MODULE
|
||||
|
||||
#include <clocale> // setlocale()
|
||||
#include <locale>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/variant.h>
|
||||
|
@ -23,11 +25,26 @@ protected:
|
|||
void SetUp() override
|
||||
{
|
||||
auto const* locale_str = GetParam();
|
||||
if (setlocale(LC_NUMERIC, locale_str) == nullptr)
|
||||
try
|
||||
{
|
||||
old_locale_ = std::locale::global(std::locale{ {}, new std::numpunct_byname<char>{ locale_str } });
|
||||
}
|
||||
catch (std::runtime_error const&)
|
||||
{
|
||||
GTEST_SKIP();
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
if (old_locale_)
|
||||
{
|
||||
std::ignore = std::locale::global(*old_locale_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<std::locale> old_locale_;
|
||||
};
|
||||
|
||||
TEST_P(JSONTest, testElements)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
if(CMAKE_VERSION VERSION_LESS 3.14)
|
||||
# --ignore-eol was introduced in CMake 3.14
|
||||
message(status "skipping transmission-show test; cmake version too old")
|
||||
message(STATUS "skipping transmission-show test; cmake version too old")
|
||||
else()
|
||||
get_filename_component(torrent_basename "${torrent_file}" NAME)
|
||||
set(output_file ${CMAKE_CURRENT_BINARY_DIR}/${torrent_basename}.out)
|
||||
|
@ -23,7 +23,8 @@ else()
|
|||
|
||||
execute_process(
|
||||
COMMAND ${transmission_show} ${torrent_file}
|
||||
OUTPUT_FILE ${output_file})
|
||||
OUTPUT_FILE ${output_file}
|
||||
ERROR_FILE ${output_file})
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E compare_files --ignore-eol ${reference_file} ${output_file}
|
||||
|
@ -31,23 +32,29 @@ else()
|
|||
|
||||
if(STATUS AND NOT STATUS EQUAL 0)
|
||||
file(READ ${reference_file} CONTENTS)
|
||||
message("EXPECTED CONTENTS (${reference_file}):")
|
||||
message(${CONTENTS})
|
||||
message(STATUS "EXPECTED CONTENTS (${reference_file}):")
|
||||
message("${CONTENTS}")
|
||||
|
||||
file(READ ${output_file} CONTENTS)
|
||||
message("RECEIVED CONTENTS (${output_file}):")
|
||||
message(${CONTENTS})
|
||||
message(STATUS "RECEIVED CONTENTS (${output_file}):")
|
||||
message("${CONTENTS}")
|
||||
|
||||
find_program(DIFF_EXEC diff)
|
||||
if(NOT DIFF_EXEC)
|
||||
find_program(GIT_EXEC git)
|
||||
if(GIT_EXEC)
|
||||
set(DIFF_EXEC "${GIT_EXEC}" diff --no-index)
|
||||
endif()
|
||||
endif()
|
||||
if(DIFF_EXEC)
|
||||
message("DIFF:")
|
||||
execute_process(COMMAND ${DIFF_EXEC} -u ${output_file} ${reference_file})
|
||||
message(STATUS "DIFF:")
|
||||
execute_process(COMMAND ${DIFF_EXEC} --unified ${reference_file} ${output_file})
|
||||
endif()
|
||||
|
||||
file(REMOVE ${output_file})
|
||||
message(FATAL_ERROR "failed: files '${reference_file}' and '${output_file}' do not match")
|
||||
else()
|
||||
file(REMOVE ${output_file})
|
||||
message("passed")
|
||||
message(STATUS "passed")
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -143,6 +143,8 @@ std::string tr_getcwd()
|
|||
|
||||
int tr_main(int argc, char* argv[])
|
||||
{
|
||||
tr_locale_set_global("");
|
||||
|
||||
tr_logSetLevel(TR_LOG_ERROR);
|
||||
tr_formatter_mem_init(MemK, MemKStr, MemMStr, MemGStr, MemTStr);
|
||||
tr_formatter_size_init(DiskK, DiskKStr, DiskMStr, DiskGStr, DiskTStr);
|
||||
|
|
|
@ -322,6 +322,8 @@ static bool setSource(tr_variant* metainfo, char const* source_value)
|
|||
|
||||
int tr_main(int argc, char* argv[])
|
||||
{
|
||||
tr_locale_set_global("");
|
||||
|
||||
int changedCount = 0;
|
||||
|
||||
tr_logSetLevel(TR_LOG_ERROR);
|
||||
|
|
|
@ -3271,6 +3271,8 @@ static void getHostAndPortAndRpcUrl(int* argc, char** argv, std::string* host, i
|
|||
|
||||
int tr_main(int argc, char* argv[])
|
||||
{
|
||||
tr_locale_set_global("");
|
||||
|
||||
auto config = Config{};
|
||||
auto port = DefaultPort;
|
||||
auto host = std::string{};
|
||||
|
|
|
@ -399,6 +399,8 @@ void doScrape(tr_torrent_metainfo const& metainfo)
|
|||
|
||||
int tr_main(int argc, char* argv[])
|
||||
{
|
||||
tr_locale_set_global("");
|
||||
|
||||
tr_logSetQueueEnabled(false);
|
||||
tr_logSetLevel(TR_LOG_ERROR);
|
||||
tr_formatter_mem_init(MemK, MemKStr, MemMStr, MemGStr, MemTStr);
|
||||
|
|
Loading…
Reference in a new issue