Hi!
How to resolve a problem with russian characters?
For example I want something like
TextButton* installButton = new TextButton(“Установить”);
But I get incorrect, unreadable characters on the button.
My system is - Win7 64 english. Other localized programs display correctly.
I think the font you are using doesn’t have Russian glyphs present. There is no font fallback with standard text rendering so if the font you chose doesn’t have the glyphs you’ll just get boxes.
You have two choices:
Switch to a font that has Russian glyphs. “Arial Unicode MS” will definitely contain it.
Render your text using TextLayout/AttributedString classes. This will let you use complex text rendering which does have font fallback support.
Font f(String("Arial Unicode MS"), 20,1 );
g.setFont(f);
g.drawText("Привет", 6, 15, getWidth(), 10, juce::Justification::left, 2);
Can you show me please how to use TextLayout/AttributedString with labels, buttons?
This sucessfully draws russian characters to the top left of my screen, both on Mac and iPad.
I think your problem is that you try to put these CharPointer_UTF8 into a StringArray, which I think converts those into juce::String and that doesn’t work. Try if rendering the text directly like in my example works, if so then it’s just about the way you store these string literals.
No clue if this is the best idea, but you could store them like this:
No, that should definitely work! String is entirely designed to interoperate with the character pointer classes. Underneath the hood it even stores the data as a character pointer (which can be configured as storage in UTF8 (the default), UTF16, or UTF32).
No, please don’t do that! This is definitely not necessary. Something else is going wrong but without test code or a test example, it’s not obvious where OP’s code can go wrong.
It will work if you add your strings by the add method. It does not work when StringArray is initialised using curly braces (probably due to CharPointer_ASCII used internally).
If you have a raw buffer of UTF8 there’s a slightly more concise way to do it with String::fromUTF8 rather than the CharPointer_UTF8 stuff.
Right… and when you actually go and look at that assertion, this is what you see:
/* If you get an assertion here, then you're trying to create a string from 8-bit data
that contains values greater than 127. These can NOT be correctly converted to unicode
because there's no way for the String class to know what encoding was used to
create them. The source data could be UTF-8, ASCII or one of many local code-pages.
To get around this problem, you must be more explicit when you pass an ambiguous 8-bit
string to the String class - so for example if your source data is actually UTF-8,
you'd call String (CharPointer_UTF8 ("my utf8 string..")), and it would be able to
correctly convert the multi-byte characters to unicode. It's *highly* recommended that
you use UTF-8 with escape characters in your source code to represent extended characters,
because there's no other way to represent these strings in a way that isn't dependent on
the compiler, source code editor and platform.
Note that the Projucer has a handy string literal generator utility that will convert
any unicode string to a valid C++ string literal, creating ascii escape sequences that will
work in any compiler.
*/
jassert (t == nullptr || CharPointer_ASCII::isValidString (t, std::numeric_limits<int>::max()));
Did you read that? If so, what else could we have said there that would have saved you having to ask about it? It’d be good to know because this is such a common misunderstanding, it’d be great to be able to just stop people getting confused about it.
Maybe the verbosity of the comment is what’s throwing people off, or how it’s structured? It’s not that it’s not containing important information.
What if it were organised as:
//Do this if UTF8 literal
//Here’s why
//…and the rest
Instead, the present flow smushes all of those details together on the assumption the user/developer understands all of it at once and has the foundation to do that already.
Did I read that? Yes, and I followed the instructions. I posted relevant code in my previous posts showing I followed the instructions. Or did I not? I don’t see what I’m doing wrong according to the instructions.
Edit: Ok, I read the additional replies. Going to try the suggestion.
Edit: Ok, so for StringArray, when using curly braces, you need to have String(CharPointer_UTF8("")), and when using .add method you just need .add(CharPointer_UTF8(""))
Edit: Ok, I see the directions say String (CharPointer_UTF8 ("my utf8 string..")). My suggestion is to remove the space between String(CharPointer because I thought “String” was just to make the instructions clear that the output is a String, especially in the case of StringArray, I never would have thought you needed String(CharPointer(
Make a more clear example:
/*
If you get an assertion here, then you're trying to create a string from 8-bit data
that contains values greater than 127. These can NOT be correctly converted to unicode
because there's no way for the String class to know what encoding was used to
create them. The source data could be UTF-8, ASCII or one of many local code-pages.
To get around this problem, you must be more explicit when you pass an ambiguous 8-bit
string to the String class - so for example if your source data is actually UTF-8,
you'd call:
String(CharPointer_UTF8("my utf8 string.."));
and it would be able to
correctly convert the multi-byte characters to unicode. It's *highly* recommended that
you use UTF-8 with escape characters in your source code to represent extended characters,
because there's no other way to represent these strings in a way that isn't dependent on the compiler,
source code editor and platform.
Note that the Projucer has a handy string literal generator utility that will convert
any unicode string to a valid C++ string literal, creating ascii escape sequences that will
work in any compiler.
If you've followed these instructions and still get an assertion error, double check that
your CharPointer_UTF8 is inside String:
String(CharPointer_UTF8(""))
*/