1
0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-06-24 13:38:29 +02:00

Add support for string cases in strings.xml (gendered Rescued/Missing)

I wanted to not complicate the system with different string cases (like
cgettext) if possible, and I have been able to keep the main strings a
simple English=Translation mapping thus far, but apparently strings
like "Rescued!" (which are one string in English), have to be
translated for the correct gender in some languages. So this was a good
time to add support for string cases anyway.

It's a number that can be given to a string to specify the specific
case it's used, to disambiguate identical English keys. In the case of
"Rescued!" and "Missing...", male versions of the string are case 1,
female versions are case 2, and Viridian being missing is case 3. Of
course, if a language doesn't need to use different variants, it can
simply fill in the same string for the different cases.

If any other string needs to switch to different cases: distinguish
them in the English strings.xml with the case="N" attribute (N=1 and
higher), sync language files from the translator menu (existing
translations for the uncased string will simply be copied to all cases)
and change loc::gettext("...") to loc::gettext_case("...", 1),
loc::gettext_case("...", 2), etc.
This commit is contained in:
Dav999-v 2022-12-01 01:27:30 +01:00 committed by Misa Elizabeth Kai
parent d147206c54
commit 795bdf886b
11 changed files with 137 additions and 34 deletions

View File

@ -445,8 +445,11 @@
<string english="[ GRAVITRON ]" translation="" explanation="in-game menu" max="40"/>
<string english="NO SIGNAL" translation="" explanation="map screen. So like a TV/computer monitor" max="29"/>
<string english="Press ACTION to warp to the ship." translation="" explanation="spaceship. Warp = teleport" max="38*7"/>
<string english="Missing..." translation="" explanation="this crew member is missing" max="15"/>
<string english="Rescued!" translation="" explanation="this crew member is not missing anymore" max="15"/>
<string english="Missing..." translation="" case="1" explanation="this male crew member is missing" max="15"/>
<string english="Missing..." translation="" case="2" explanation="this female crew member is missing" max="15"/>
<string english="Missing..." translation="" case="3" explanation="Viridian is missing (final level). You could even fill in something like `Uh-oh...` here if you really have to specify gender otherwise - everyone else is rescued, but the player is missing" max="15"/>
<string english="Rescued!" translation="" case="1" explanation="this male crew member is not missing anymore" max="15"/>
<string english="Rescued!" translation="" case="2" explanation="this female crew member is not missing anymore" max="15"/>
<string english="(that&apos;s you!)" translation="" explanation="this crew member is you (Viridian)" max="15"/>
<string english="Cannot Save in Level Replay" translation="" explanation="in-game menu" max="38*7"/>
<string english="Cannot Save in No Death Mode" translation="" explanation="in-game menu" max="38*7"/>

View File

@ -445,8 +445,11 @@
<string english="[ GRAVITRON ]" translation="[ GRAVITRONO ]" explanation="in-game menu" max="40"/>
<string english="NO SIGNAL" translation="SENSIGNALE" explanation="map screen. So like a TV/computer monitor" max="29"/>
<string english="Press ACTION to warp to the ship." translation="Premu AGBUTONON por teleportiĝi al la ŝipo." explanation="spaceship. Warp = teleport" max="38*7"/>
<string english="Missing..." translation="Mankas..." explanation="this crew member is missing" max="15"/>
<string english="Rescued!" translation="Savita!" explanation="this crew member is not missing anymore" max="15"/>
<string english="Missing..." translation="Mankas..." case="1" explanation="this male crew member is missing" max="15"/>
<string english="Missing..." translation="Mankas..." case="2" explanation="this female crew member is missing" max="15"/>
<string english="Missing..." translation="Mankas..." case="3" explanation="Viridian is missing (final level). You could even fill in something like `Uh-oh...` here if you really have to specify gender otherwise - everyone else is rescued, but the player is missing" max="15"/>
<string english="Rescued!" translation="Savita!" case="1" explanation="this male crew member is not missing anymore" max="15"/>
<string english="Rescued!" translation="Savita!" case="2" explanation="this female crew member is not missing anymore" max="15"/>
<string english="(that&apos;s you!)" translation="(jen vi!)" explanation="this crew member is you (Viridian)" max="15"/>
<string english="Cannot Save in Level Replay" translation="Ne eblas konservi en nivel-reludado" explanation="in-game menu" max="38*7"/>
<string english="Cannot Save in No Death Mode" translation="Ne eblas konservi en mortula reĝimo" explanation="in-game menu" max="38*7"/>

View File

@ -445,8 +445,11 @@
<string english="[ GRAVITRON ]" translation="[ GRAVITRON ]" explanation="in-game menu" max="40"/>
<string english="NO SIGNAL" translation="SIN SEÑAL" explanation="map screen. So like a TV/computer monitor" max="29"/>
<string english="Press ACTION to warp to the ship." translation="Presiona ACCIÓN para transportar la nave." explanation="spaceship. Warp = teleport" max="38*7"/>
<string english="Missing..." translation="Faltando..." explanation="this crew member is missing" max="15"/>
<string english="Rescued!" translation="" explanation="this crew member is not missing anymore" max="15"/>
<string english="Missing..." translation="" case="1" explanation="this male crew member is missing" max="15"/>
<string english="Missing..." translation="" case="2" explanation="this female crew member is missing" max="15"/>
<string english="Missing..." translation="" case="3" explanation="Viridian is missing (final level). You could even fill in something like `Uh-oh...` here if you really have to specify gender otherwise - everyone else is rescued, but the player is missing" max="15"/>
<string english="Rescued!" translation="" case="1" explanation="this male crew member is not missing anymore" max="15"/>
<string english="Rescued!" translation="" case="2" explanation="this female crew member is not missing anymore" max="15"/>
<string english="(that&apos;s you!)" translation="" explanation="this crew member is you (Viridian)" max="15"/>
<string english="Cannot Save in Level Replay" translation="No puedes guardar en una repeticion de nivel" explanation="in-game menu" max="38*7"/>
<string english="Cannot Save in No Death Mode" translation="No puedes guardar en el Modo Sin Muertes" explanation="in-game menu" max="38*7"/>

View File

@ -445,8 +445,11 @@
<string english="[ GRAVITRON ]" translation="[ GRAVITRON ]" explanation="in-game menu" max="40"/>
<string english="NO SIGNAL" translation="GEEN SIGNAAL" explanation="map screen. So like a TV/computer monitor" max="29"/>
<string english="Press ACTION to warp to the ship." translation="Druk op ACTIE om naar het schip te teleporteren." explanation="spaceship. Warp = teleport" max="38*7"/>
<string english="Missing..." translation="Vermist..." explanation="this crew member is missing" max="15"/>
<string english="Rescued!" translation="Gered!" explanation="this crew member is not missing anymore" max="15"/>
<string english="Missing..." translation="Vermist..." case="1" explanation="this male crew member is missing" max="15"/>
<string english="Missing..." translation="Vermist..." case="2" explanation="this female crew member is missing" max="15"/>
<string english="Missing..." translation="Vermist..." case="3" explanation="Viridian is missing (final level). You could even fill in something like `Uh-oh...` here if you really have to specify gender otherwise - everyone else is rescued, but the player is missing" max="15"/>
<string english="Rescued!" translation="Gered!" case="1" explanation="this male crew member is not missing anymore" max="15"/>
<string english="Rescued!" translation="Gered!" case="2" explanation="this female crew member is not missing anymore" max="15"/>
<string english="(that&apos;s you!)" translation="(dat ben jij!)" explanation="this crew member is you (Viridian)" max="15"/>
<string english="Cannot Save in Level Replay" translation="Kan niet opslaan tijdens opnieuw spelen van een level" explanation="in-game menu" max="38*7"/>
<string english="Cannot Save in No Death Mode" translation="Kan niet opslaan in éénlevenmodus" explanation="in-game menu" max="38*7"/>

View File

@ -966,30 +966,58 @@ void Graphics::printcrewnamedark( int x, int y, int t )
}
}
void Graphics::printcrewnamestatus( int x, int y, int t )
void Graphics::printcrewnamestatus( int x, int y, int t, bool rescued )
{
//Print the status of crew member t in the right colour
int r, g, b;
char gender;
switch(t)
{
case 0:
Print(x, y, loc::gettext("(that's you!)"), 12, 140, 140,false);
r=12; g=140, b=140;
gender = 3;
break;
case 1:
Print(x, y, loc::gettext("Rescued!"), 140, 12, 140,false);
r=140; g=12; b=140;
gender = 2;
break;
case 2:
Print(x, y, loc::gettext("Rescued!"), 140, 140, 12,false);
r=140; g=140; b=12;
gender = 1;
break;
case 3:
Print(x, y, loc::gettext("Rescued!"), 140, 12, 12,false);
r=140; g=12; b=12;
gender = 1;
break;
case 4:
Print(x, y, loc::gettext("Rescued!"), 12, 140, 12,false);
r=12; g=140; b=12;
gender = 1;
break;
case 5:
Print(x, y, loc::gettext("Rescued!"), 12, 12, 140,false);
r=12; g=12; b=140;
gender = 2;
break;
default:
return;
}
const char* status_text;
if (gender == 3 && rescued)
{
status_text = loc::gettext("(that's you!)");
}
else if (rescued)
{
status_text = loc::gettext_case("Rescued!", gender);
}
else
{
r=64; g=64; b=64;
status_text = loc::gettext_case("Missing...", gender);
}
Print(x, y, status_text, r, g, b, false);
}
void Graphics::drawsprite( int x, int y, int t, int r, int g, int b )

View File

@ -144,11 +144,10 @@ public:
void drawsprite(int x, int y, int t, Uint32 c);
void printcrewname(int x, int y, int t);
void printcrewnamestatus(int x, int y, int t);
void printcrewnamedark(int x, int y, int t);
void printcrewnamestatus(int x, int y, int t, bool rescued);
void map_tab(int opt, const char* text, bool selected = false);
void map_option(int opt, int num_opts, const std::string& text, bool selected = false);

View File

@ -50,6 +50,28 @@ const char* gettext(const char* eng)
return map_lookup_text(map_translation, eng, eng);
}
const char* gettext_case(const char* eng, char textcase)
{
if (lang == "en")
{
return eng;
}
if (textcase == 0)
{
return gettext(eng);
}
char* eng_prefixed = add_disambiguator(textcase, eng, NULL);
if (eng_prefixed == NULL)
{
return eng;
}
const char* tra = map_lookup_text(map_translation, eng_prefixed, eng);
SDL_free(eng_prefixed);
return tra;
}
static const char* gettext_plural_english(const char* eng_plural, const char* eng_singular, int n)
{
/* Do be consistent with negative number handling for other languages... */

View File

@ -74,6 +74,7 @@ extern int n_untranslated[COUNT_UNTRANSLATED_INDEX];
const LangMeta* get_langmeta(void);
const char* gettext(const char* eng);
const char* gettext_case(const char* eng, char textcase);
const char* gettext_plural(const char* eng_plural, const char* eng_singular, int count);
void gettext_plural_fill(char* buf, size_t buf_len, const char* eng_plural, const char* eng_singular, const char* args_index, ...);
std::string getnumber(int n);

View File

@ -88,7 +88,31 @@ static void sync_lang_file(const std::string& langcode)
const char* eng = pElem->Attribute("english");
if (eng != NULL)
{
pElem->SetAttribute("translation", map_lookup_text(map_translation, eng, ""));
char textcase = pElem->UnsignedAttribute("case", 0);
const char* tra;
if (textcase == 0)
{
tra = map_lookup_text(map_translation, eng, "");
}
else
{
char* eng_prefixed = add_disambiguator(textcase, eng, NULL);
if (eng_prefixed == NULL)
{
/* Are we out of memory? Stop, don't blank our language files... */
return;
}
/* Note the fallback: if this string used to not be cased and now it is,
* simply fill in the old single variant we already had. */
tra = map_lookup_text(
map_translation,
eng_prefixed,
map_lookup_text(map_translation, eng, "")
);
SDL_free(eng_prefixed);
}
pElem->SetAttribute("translation", tra);
}
}
@ -125,7 +149,7 @@ static void sync_lang_file(const std::string& langcode)
char* key = add_disambiguator(form_id+1, eng_plural, NULL);
if (key == NULL)
{
/* Are we out of memory? Stop, don't blank our language files... */
/* Out of memory or something, stop */
return;
}

View File

@ -416,12 +416,33 @@ static void loadtext_strings(bool check_max)
const char* eng = pElem->Attribute("english");
const char* tra = pElem->Attribute("translation");
map_store_translation(
&textbook_main,
map_translation,
eng,
tra
);
char textcase = pElem->UnsignedAttribute("case", 0);
if (textcase == 0)
{
map_store_translation(
&textbook_main,
map_translation,
eng,
tra
);
}
else
{
/* Only prefix with a disambiguator if a specific case number is set */
char* eng_prefixed = add_disambiguator(textcase, eng, NULL);
if (eng_prefixed == NULL)
{
continue;
}
map_store_translation(
&textbook_main,
map_translation,
eng_prefixed,
tra
);
SDL_free(eng_prefixed);
}
/* Only tally an untranslated string if English isn't blank */
if (eng != NULL && eng[0] != '\0')

View File

@ -2579,25 +2579,23 @@ void maprender(void)
if (game.crewstats[(2-i)])
{
graphics.printcrewname(44, 32 + (i * 64)+4+10, 2-i);
graphics.printcrewnamestatus(44, 32 + (i * 64)+4, 2-i);
}
else
{
graphics.printcrewnamedark(44, 32 + (i * 64)+4+10, 2-i);
graphics.Print(44, 32 + (i * 64) + 4, loc::gettext("Missing..."), 64,64,64);
}
graphics.printcrewnamestatus(44, 32 + (i * 64)+4, 2-i, game.crewstats[(2-i)]);
graphics.drawcrewman(16+160, 32 + (i * 64), (2-i)+3, game.crewstats[(2-i)+3]);
if (game.crewstats[(2-i)+3])
{
graphics.printcrewname(44+160, 32 + (i * 64)+4+10, (2-i)+3);
graphics.printcrewnamestatus(44+160, 32 + (i * 64)+4, (2-i)+3);
}
else
{
graphics.printcrewnamedark(44+160, 32 + (i * 64)+4+10, (2-i)+3);
graphics.Print(44+160, 32 + (i * 64) + 4, loc::gettext("Missing..."), 64,64,64);
}
graphics.printcrewnamestatus(44+160, 32 + (i * 64)+4, (2-i)+3, game.crewstats[(2-i)+3]);
}
}
else
@ -2608,25 +2606,23 @@ void maprender(void)
if (game.crewstats[i])
{
graphics.printcrewname(44, 32 + (i * 64)+4, i);
graphics.printcrewnamestatus(44, 32 + (i * 64)+4+10, i);
}
else
{
graphics.printcrewnamedark(44, 32 + (i * 64)+4, i);
graphics.Print(44, 32 + (i * 64) + 4 + 10, loc::gettext("Missing..."), 64,64,64);
}
graphics.printcrewnamestatus(44, 32 + (i * 64)+4+10, i, game.crewstats[i]);
graphics.drawcrewman(16+160, 32 + (i * 64), i+3, game.crewstats[i+3]);
if (game.crewstats[i+3])
{
graphics.printcrewname(44+160, 32 + (i * 64)+4, i+3);
graphics.printcrewnamestatus(44+160, 32 + (i * 64)+4+10, i+3);
}
else
{
graphics.printcrewnamedark(44+160, 32 + (i * 64)+4, i+3);
graphics.Print(44+160, 32 + (i * 64) + 4 + 10, loc::gettext("Missing..."), 64,64,64);
}
graphics.printcrewnamestatus(44+160, 32 + (i * 64)+4+10, i+3, game.crewstats[i+3]);
}
}
}