isn't there some universal way to work in both cases?
Not that I know of. The u16string and u32string from c++11 and especially the u8string from c++20 looked promising to store strings while being explicitly about the encoding (while std::string and std::wstring depend on the platform). But you can only use them to store strings in, as soon as you need to do something with it (like printing to to the screen) you need to manually convert them again anyway.
Using std::wstring sounded like the most universal ways to me. But I just tried and on manjaro with cinnamon it printed "?" in the terminal when using wstring and wcout in both XTerm and GNOME Terminal.
So if you want to print the text to the command line on both Windows and Linux then you might need some platform dependent code (unless there is some way that I don't know about yet, keep in mind that I never actually developed a program that uses unicode characters).
Using std::wstring will allow easier interaction with sf::String as you won't need to use code like the String::fromUtf8 to correctly display the characters, you would just be able to convert the std::wstring to an sf::String implicitly.
Then to output to the screen, instead of doing cout or wcout you would call a function that will call either one depending on the platform. As you can see, I don't know a very efficient way to go from sf::String to an UTF-8 std::string (the toAnsiString() function can't be used because it removed all non-ansi characters), but at least this method works. I didn't test the Windows implementation.
void output(const sf::String& str)
{
#ifdef SFML_SYSTEM_LINUX
const std::basic_string<sf::Uint8>& tmpBuffer1 = str.toUtf8();
const std::string tmpBuffer2(tmpBuffer1.begin(), tmpBuffer1.end());
std::cout << tmpBuffer2;
#else // Assuming Windows is the only other platform
std::wcout << str.toWideString();
#endif
}
(You might need some changes if you want to add a newline behind it or if you mix it with other cout statements in your code)
Update:
I looked up how to use std::wcout on linux. It turns out you can use wcout on linux if you add something like the following line at the start of your code (whether you want to actually do so is up to you, this might fail if the locale is not installed + going this route will likely also result in platform dependent code).
std::locale::global (std::locale ("en_US.UTF-8"));