<Nexus>
Traveler of the Multiverse
In fact the picture is to show russian support ! The main screen is downloadable in the creative thread
I've got that. Good job
It was just shocking new for me. Is it animated? (No, I can't wait to try it )
In fact the picture is to show russian support ! The main screen is downloadable in the creative thread
Duolingo?Je parle français. I speak english. Yo hablo un poco español. Ich lerne Deutsch. Yeg studerer bokmål.
CvWString convertWString(CvWString wszTextVal)
{
wchar caNewChar[2];
caNewChar[1] = 0;
CvWString &wszNewString;
wszNewString.clear();
unsigned int iCharset = GetACP();
// The input is a string as it is written in XML, where it is UTF-8 encoded.
// The output is the same content, but the character values have been changed to match those used in GameFont.
for (unsigned i = 0; i < wszTextVal.length(); ++i)
{
char cOld = wszTextVal.data()[i];
wchar cNew = 0;
unsigned int iID = cOld;
iID &= 0xFF; // ensure we only get the 8 bytes and no sign extension
if (cOld >= 0 && cOld <= 0x7F)
{
// single byte char. No conversion needed
cNew = cOld;
}
else
{
unsigned char cMask = 0x40;
iID &= 0x7F;
while (iID & cMask)
{
iID &= ~cMask;
cMask >>= 1;
}
cMask = 0x40;
// the number of bytes in an UTF-8 character is the same as the number of 1s before the first 0 in the first byte (1 byte starts with 0 for backward compatibility)
// read all bytes for the current character using this info
while (cMask & cOld)
{
cMask >>= 1;
i++;
iID <<= 6;
int iChar = wszTextVal.data()[i] & 0xFF;
iID |= (iChar & 0x3F);
FAssertMsg((iChar & 0xC0) == 0x80, CvString::format("Not UTF-8 encoded: %s %s", GC.getCurrentXMLFile().GetCString(), wszTextVal.data()));
}
// at this point iID contains the unicode value of the character.
// cNew is the index in GameFont, which should be used for the character in question.
for (int iIndex = 0; iIndex < 0x80; iIndex++)
{
if (iID == conversion_table_unicode[iIndex])
{
cNew = iIndex + 0x80;
break;
}
}
}
if (cNew == 0)
{
//FAssertMsg(cNew != 0, CvString::format("UTF-8 fail: %X %s %s", iID, GC.getCurrentXMLFile().GetCString(), (szTextVal.data() + i)));
cNew = '?';
}
caNewChar[0] = cNew;
wszNewString.append(caNewChar);
}
return wszNewString;
}
It doesn't anymore and I have no idea why.Do you have any tip ? May i use the wrong code as you've mentionned previously on this thread that your computer forces 1250 ?
That is just plain stupid. It would appear that Windows has at least 3 versions of Russian (1251, 866, 855). Which one you get appears to be decided by your hardware and/or software. There are 11 single byte CodePages and I guess it would be good to add iconv code for all of them. That way we have the best chance of people being able to play regardless of their local settings.EDIT: I've managed to change the locale to Russian while still using my native language but the codepage in use is 866 and not 1251
That is just plain stupid. It would appear that Windows has at least 3 versions of Russian (1251, 866, 855). Which one you get appears to be decided by your hardware and/or software. There are 11 single byte CodePages and I guess it would be good to add iconv code for all of them. That way we have the best chance of people being able to play regardless of their local settings.
void CvGameText::setText(const wchar* szText)
{
m_szText = szText;
}
Ich habe kein gespräch jetzt noch. Ich gebrauche Assimil (viel gut) für lernen Deutsch und Norweger.
The & means it's a reference to the variable. For instance if we haveI've added this modified function in the hope that i can bypass Gamefont rendering but it doesn't work. I don't think i understand the relation between a wchar and a &wchar.
int FuncA(int& A)
{
A++;
return A*A;
}
void FuncB()
{
int myInt = 4;
FuncA(&myInt); // can't remember if this is the precise reference syntax
printf("%d\n", myInt);
}
Quite possibly, but I haven't seen any evidence to support that claim. If it is language learning or coding skills, which makes you say that, then I must be a complete lunaticMan, you are crazy!
Einmal musste ich nach Deutschland fahren (kein Uhrlaub ) und entdeckte das viele Leute in Deutschland kein Englisch sprechen. Das was kein große Problem und heute brauchen ich nickt Deutsch zu lernenIch lerne Deutsch auch
Sadly that's a two byte CodePage and I haven't managed to get it to work. I have tried though.私は日本語を習っているだけです (watashi wa nihongo wo naratteiru dake desu)
Thank you. That is much more clear now.The & means it's a reference to the variable. For instance if we have...
No. None of these strings are hardcoded, but they are referenced directly into the code:One thing I have run into though is lazy programmers writing the English string in the code rather than using the TXT_KEY_ system. That results in hardcoded English, which the translators can't do anything about. I don't know if that is the case with the English strings in the screenshot.
if (kBuilding.getMaxDomesticConnectedCommerce() <= 0)
{
szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_DOMESTIC_CONNECTED_COMMERCE_EACH_CITY", kBuilding.getDomesticConnectedCommerce()));
}
<TEXT>
<Tag>TXT_KEY_BUILDING_DOMESTIC_CONNECTED_COMMERCE_EACH_CITY</Tag>
<English>[ICON_BULLET]+%d1[ICON_COMMERCE] from each connected domestic city</English>
<French>[ICON_BULLET]+%d1[ICON_COMMERCE] de chaque ville connectée.</French>
</TEXT>
@NightinggaleQuite possibly, but I haven't seen any evidence to support that claim. If it is language learning or coding skills, which makes you say that, then I must be a complete lunatic
I need to figure out if there is another way to bypass getText to send unicode sentences to the game. You may have any idea ?
EDIT: Another thought: Isn't it possible to directly read the xml cached file and to extract sentence in UTF to replace "gDll->getText" ?
EDIT2: I'm convinced that bypassing gDll->getText() is the key, but i don't know if it's possible.
m_szText is a member variable in CvGameText and szText is the argument. It simply copies the argument into the member variable, effectively telling the text what it is.EDIT3: What is the purpose of this function ?
Code:void CvGameText::setText(const wchar* szText) { m_szText = szText; }
Oh man, I missed that. I just read that it was Hungarian and assumed it to be just a regular translation. It's brilliant and looks like something I could have come up with@Nightinggale
I was referring to dbkblk's screenshot on Hungarian support (I am Hungarian)
He changed the main menu to say:
Hello Sogroon
I don't speak Hungarian
But Google does
Every Hungarian character too
When I saw it I had to LOL - which may be dangerous in a workplace
The point is that whenever the game writes a regular string using a normal font, it uses standardized numbers for each character. GameFont.tga however gives us little choice of numbers meaning we can't place characters at to give the the correct ID. As a result the same character has one ID in the string (font) and another in GameFont. I wrote a function to look up the "right" ID and then figure out what the GameFont ID is for the same character.EDIT: I miss the point, getGameFontString(getGameFontString(pCity->getName())) get the correct name in Russian. No need to rewrite it.
Bypassing getText isn't the issue. The issue is that we gain nothing from doing so. It looks like the limitation lies in the font writing part of the exe, not the getText part meaning even if we write our own code, we still call something in the exe to actually put the text on the screen and that part is broken in regards to supporting multiple languages.Even if we can't bypass getText, we might write a new function and replace the calls in the code, it's not that much of work.
And you managed to get the city billboards to write Russian without GameFont? I haven't been able to write anything other than GameFont icons on billboards.I haven't yet included Russian into GameFont as i want to try to avoid that (to be able to theorically add any language out there!).
No the game uses ? too. I actually started using ¿, but then I realized that only some of the CodePages uses that character. The problem is that if there is a unicode character, which isn't present in the CodePage, the character still needs to be added and it just have to be some character. I picked ? as it sort of make sense, but we could use any ASCII character, such as _ or :EDIT: Question: In your code, you force to put the "?" char to unknown chars. Is your function the lonely one to do that ? I mean, when billboard gets unknown chars, it puts only "????" in names.
I don't think so. We need to distinguish two different factors:Bypassing getText isn't the issue. The issue is that we gain nothing from doing so. It looks like the limitation lies in the font writing part of the exe, not the getText part meaning even if we write our own code, we still call something in the exe to actually put the text on the screen and that part is broken in regards to supporting multiple languages.
unsigned int iCharset = GetACP();
FAssertMsg(false, "Codepage in use is %d\n", iCharset);
"my" ? is when a character isn't present in the CodePage. The game ? is when you try to write an invalid GameFont ID. Those two are totally different.- The game seems to use GameFont to render city billboard, no matter what we define. I've tried to change ? to . in your code and i still gets ? into billboard. Maybe that part isn't "fixable" and we need to use transliteration or something smarter.
We always have English characters available for the Billboards. We could make a conversion table from Russian to English, which would result in Russian being written with latin characters. I'm not sure I would advice that as we have the Russian characters to add.EDIT: Another solution for city billboard is to fallback to english strings. Do you think it's possible ?
<TEXT>
<Tag>TXT_KEY_BUILDING_FREE_IN_CITY</Tag>
<!-- %s1_Name = TXT_KEY_BUILDING_ -->
<English>[ICON_BULLET]Free [COLOR_BUILDING_TEXT][LINK=literal]%s1_Name[\LINK][COLOR_REVERT] in Every City</English>
<French>[ICON_BULLET]1 [COLOR_BUILDING_TEXT][LINK=literal]%s1_Name[\LINK][COLOR_REVERT] dans chaque ville</French>
<German>[ICON_BULLET]Freies Gebäude [COLOR_BUILDING_TEXT][LINK=literal]%s1_Name[\LINK][COLOR_REVERT] in jeder Stadt</German>
<Italian>[ICON_BULLET][COLOR_BUILDING_TEXT][LINK=literal]%s1_Name[\LINK][COLOR_REVERT] [NUM1:gratuito:gratuita:gratuiti:gratuite] in ogni città</Italian>
<Spanish>[ICON_BULLET][NUM1:Un:Una:Unos:Unas] [COLOR_BUILDING_TEXT][LINK=literal]%s1:1_Name[\LINK][COLOR_REVERT] gratis en todas las ciudades.</Spanish>
</TEXT>
szBuffer.append(gDLL->getText("TXT_KEY_BUILDING_FREE_IN_CITY", GC.getBuildingInfo(eFreeBuilding).getTextKeyWide()));
<TEXT>
<Tag>TXT_KEY_BUILDING_DOMESTIC_CONNECTED_COMMERCE_EACH_CITY</Tag>
<English>[ICON_BULLET]+%d1[ICON_COMMERCE] from each connected domestic city</English>
<French>[ICON_BULLET]+%d1[ICON_COMMERCE] de chaque ville connectée.</French>
</TEXT>
szBuffer.append(convertWString(gDLL->getText("TXT_KEY_BUILDING_FOREIGN_CONNECTED_COMMERCE_CITY", kBuilding.getForeignConnectedCommerce(), iCities)));