langen: Handle repeated strings better.

If a translation file contains two copies of the same English string,
with the same translation, then we don't care at all; just throw out
the second copy.

If a translation file contains two copies of the same English string,
with DIFFERENT translations, then (according to how the game does
translation) one of those translations must be inappropriate. Give
a warning in that case; and again, throw out the second copy because
we are forced to pick ONE translation for use within the game.

Also fix some minor typos I noticed in the strings.
This commit is contained in:
Arthur O'Dwyer 2020-03-31 14:56:45 -04:00
parent 6c4ca2254c
commit 8564e53d08
8 changed files with 48 additions and 50 deletions

View File

@ -875,13 +875,13 @@ EX vector<geometryinfo> ginf = {
{"{4,3,5}","none", "{4,3,5} hyperbolic honeycomb", "435", 6, 5, 0, giHyperb3, 0x31600, {{7, 2}}, eVariation::pure},
{"{3,3,3}","none", "{3,3,3} 5-cell", "333", 4, 3, qsSMALLB, giSphere3, 0x38000, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{3,3,4}","none", "{3,3,4} 16-cell", "334", 4, 4, qsSMALLB, giSphere3, 0x38200, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{3,3,4}","elliptic","{3,3,4} 16-cell (elliptic)", "e334", 4, 4, qsSMALLBE, giSphere3, 0x39200, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{3,3,4}","elliptic","{3,3,4} 16-cell (elliptic space)", "e334", 4, 4, qsSMALLBE, giSphere3, 0x39200, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{4,3,3}","none", "{4,3,3} 8-cell", "433", 6, 4, qsSMALLB, giSphere3, 0x38400, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{4,3,3}","elliptic","{4,3,3} 8-cell (elliptic)", "e433", 6, 4, qsSMALLBE, giSphere3, 0x39400, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{4,3,3}","elliptic","{4,3,3} 8-cell (elliptic space)", "e433", 6, 4, qsSMALLBE, giSphere3, 0x39400, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{3,4,3}","none", "{3,4,3} 24-cell", "343", 8, 3, qsSMALLB, giSphere3, 0x38600, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{3,4,3}","elliptic","{3,4,3} 24-cell (elliptic)", "e343", 8, 3, qsSMALLBE, giSphere3, 0x39600, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{3,4,3}","elliptic","{3,4,3} 24-cell (elliptic space)", "e343", 8, 3, qsSMALLBE, giSphere3, 0x39600, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{3,3,5}","none", "{3,3,5} 600-cell", "335", 4, 3, qsSMALLB, giSphere3, 0x41000, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{3,3,5}","elliptic","{3,3,5} 600-cell (elliptic)", "e335", 4, 3, qsSMALLBE, giSphere3, 0x41200, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{3,3,5}","elliptic","{3,3,5} 600-cell (elliptic space)", "e335", 4, 3, qsSMALLBE, giSphere3, 0x41200, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"bin{3,6}", "none", "{3,6} on horospheres", "bin36", 8, 3, qBINARY, giHyperb3, 0x40000, {{7, 3}}, eVariation::pure},
{"bin-rect", "none", "rectangles on horospheres", "bin44/2", 7, 3, qBINARY, giHyperb3, 0x40200, {{7, 3}}, eVariation::pure},
{"bin{6,3}", "none", "{6,3} on horospheres", "bin63", 14, 3, qBINARY, giHyperb3, 0x40400, {{7, 3}}, eVariation::pure},

View File

@ -322,7 +322,7 @@ MONSTER( 'Y', 0xFF8000, "Yendorian Researcher", moResearcher, ZERO, RESERVED, mo
"They have no special features, other than wearing a strange hat."
)
MONSTER( 'K', 0xA8A8A8, "Sparrowhawk", moSparrowhawk, CF_FACE_SIDE | CF_BIRD | CF_FLYING | CF_IGNORE_PLATE, RESERVED, moEagle,
"A bird who hunts in the treetops of Yendorian Forest."
"A bird who hunts in the treetops of the Yendorian Forest."
)
MONSTER( 'K', 0xD0A0A0, "Kraken", moKrakenH, ZERO | CF_NOGHOST | CF_NOBLOW | CF_MULTITILE | CF_KRAKEN | CF_FACING, RESERVED, moNone, krakendesc)
MONSTER( 'K', 0xC07070, "Kraken Tentacle", moKrakenT, ZERO | CF_NOGHOST | CF_NOBLOW | CF_PART | CF_MULTITILE | CF_KRAKEN, RESERVED, moNone, krakendesc)
@ -398,7 +398,7 @@ MONSTER( 'W', 0x202020, "Hunting Dog (regrouping)", moHunterChanging, ZERO, RESE
"When your plan has clearly failed, it is better to abandon it and go to a safe place, to have a chance of succeeding next time. This dog clearly knows this.")
MONSTER( 'B', 0xC00000, "North Pole", moNorthPole, ZERO | CF_MAGNETIC | CF_FACING, RESERVED, moYeti, NODESCYET)
MONSTER( 'B', 0x0000C0, "South Pole", moSouthPole, ZERO | CF_MAGNETIC | CF_FACING, RESERVED, moYeti, NODESCYET)
MONSTER( 'P', 0xC03000, "Red Raider", moPair, CF_FACE_UP | CF_RAIDER | CF_FACING, RESERVED, moYeti, "Red Raiders travel in pairs. They have promised to always watch another one's back. They are able to destroy walls on their way.")
MONSTER( 'P', 0xC03000, "Red Raider", moPair, CF_FACE_UP | CF_RAIDER | CF_FACING, RESERVED, moYeti, "Red Raiders travel in pairs. They have promised to always watch each other's backs. They are able to destroy walls on their way.")
MONSTER( 'H', 0xC0C0C0, "Gray Raider", moHexDemon, CF_FACE_UP | CF_RAIDER, RESERVED, moHexDemon, "Gray Raiders never step on gray cells.")
MONSTER( 'A', 0x80B080, "Green Raider", moAltDemon, CF_FACE_UP | CF_RAIDER, RESERVED, moAltDemon, "Green Raiders never step from one green cell to another.")
MONSTER( 'M', 0x904000, "Brown Raider", moMonk, CF_FACE_UP | CF_RAIDER, RESERVED, moMonk, "Brown Raiders never move adjacent to an item.")
@ -665,7 +665,7 @@ ITEM( '%', 0x606060, "Black Lotus", itLotus, IC_TREASURE, ZERO, RESERVED, osNone
"without preparation.\n"
)
ITEM( 'o', 0x505050, "Orb of Undeath", itOrbUndeath, IC_ORB, ZERO | IF_EMPATHY | IF_SHMUPLIFE | IF_REVIVAL, RESERVED, osFriend,
"Monsters slain by you in melee are turned into friendly ghosts, "
"Monsters slain by you in melee are turned into friendly ghosts. "
"Does not affect plants and friends."
)
ITEM( '*', 0x8080FF, "White Dove Feather", itWindstone, IC_TREASURE, ZERO, RESERVED, osNone,
@ -733,7 +733,7 @@ ITEM( 'o', 0x900000, "Orb of Domination", itOrbDomination, IC_ORB, ZERO | IF_RAN
"Simply move onto such a creature to ride them; while riding, you are protected from dangerous terrains "
"and partially from attacks (they cause you to lose half of your Domination power), "
"but you cannot collect items.\n\n"
/*When only one charge is left, "
/*"When only one charge is left, "
"you have to dismount this turn -- be very careful to make this possible, "
"as your mount could attack you immediately!\n\n" */
"While riding, "
@ -849,7 +849,7 @@ ITEM( '*', 0xFFA860, "Tiger's Eye", itBrownian, IC_TREASURE, ZERO, RESERVED, osN
ITEM( '$', 0xF0C0C0, "Meteorite", itWest, IC_TREASURE, ZERO, RESERVED, osNone,
"These rocks falling from the sky have been captured to fall forever in the artificial gravity. Meteorite iron is believed to be a valuable material for magical weapons.")
ITEM( '*', 0x30FF30, "Torbernite", itVarTreasure, IC_TREASURE, ZERO, RESERVED, osNone,
"Crystals emiting magical radiation.")
"Crystals emitting magical radiation.")
ITEM( 'o', 0x703800, "Orb of Intensity", itOrbIntensity, IC_ORB, ZERO, RESERVED, osNone,
"When you have this, initial and maximal charge amounts of all Orbs are increased by 20%."
)

View File

@ -810,7 +810,7 @@ EX void showEuclideanMenu() {
dialog::add_action([] {
dialog::editNumber(rots::underlying_scale, 0, 1, 0.05, 0.25, XLAT("view the underlying geometry"),
XLAT(
geometry == gRotSpace ? "The space you are currently in the space of rotations of the underlying hyperbolic or spherical geometry. "
geometry == gRotSpace ? "The space you are currently in is the space of rotations of the underlying hyperbolic or spherical geometry. "
: "You are currently in a product space.") +
XLAT(
"This option lets you see the underlying space. Lands and some walls (e.g. in the Graveyard) are based on "

View File

@ -31,8 +31,13 @@ const char *escape(std::string s, const std::string& dft);
template<class T> struct dictionary {
std::map<std::string, T> m;
void add(const std::string& s, T val) {
if(m.count(s)) add(s + " [repeat]", std::move(val));
else m[s] = std::move(val);
auto it = m.find(s);
if (it == m.end()) {
m.emplace(s, std::move(val));
}
else if (val != it->second) {
printf("// #warning Two translations for %s\n", escape(s, s));
}
}
T& operator [] (const std::string& s) { return m[s]; }
int count(const std::string& s) const { return m.count(s); }
@ -53,6 +58,12 @@ struct noun {
std::string nom, nomp, acc, abl;
noun() = default;
noun(const noun2& n) : genus(n.genus), nom(n.nom), nomp(n.nomp), acc(n.acc), abl(n.abl) {}
friend bool operator==(const noun& a, const noun& b) {
return std::tie(a.genus, a.nom, a.nomp, a.acc, a.abl) == std::tie(b.genus, b.nom, b.nomp, b.acc, b.abl);
}
friend bool operator!=(const noun& a, const noun& b) {
return std::tie(a.genus, a.nom, a.nomp, a.acc, a.abl) != std::tie(b.genus, b.nom, b.nomp, b.acc, b.abl);
}
};
dictionary<noun> nouns[NUMLAN];
@ -93,14 +104,7 @@ typedef unsigned hashcode;
hashcode hashval;
bool isrepeat(const std::string& s) {
return s.find(" [repeat]") != std::string::npos;
}
hashcode langhash(const std::string& s) {
if(isrepeat(s)) {
return langhash(s.substr(0, s.size() - 9)) + 1;
}
hashcode r = 0;
for (char ch : s) r = hashval * r + ch;
return r;
@ -265,13 +269,11 @@ void compute_completeness(const T& dict)
else
mis1 += which;
}
if(mis != "" && !isrepeat(elt))
if(mis != "")
printf("// #warning Missing [%s/%s]: %s\n", mis.c_str(), mis1.c_str(), escape(elt, "?"));
if(!isrepeat(elt)) {
completeness[0]++;
for(int i=1; i<NUMLAN; i++) if(dict[i].count(elt)) completeness[i]++;
}
completeness[0]++;
for(int i=1; i<NUMLAN; i++) if(dict[i].count(elt)) completeness[i]++;
}
}
@ -389,11 +391,9 @@ int main() {
for(auto&& elt : ms) {
const std::string& s = elt.second;
if(isrepeat(s)) printf("#if REPEATED\n");
printf(" {0x%x, { // %s\n", elt.first, escape(s, s));
for(int i=1; i<NUMLAN; i++) printf(" %s,\n", escape(d[i][s], s));
printf(" }},\n");
if(isrepeat(s)) printf("#endif\n");
}
printf(" };\n\n");
@ -401,7 +401,6 @@ int main() {
for(auto&& elt : mn) {
const std::string& s = elt.second;
if(isrepeat(s)) printf("#if REPEATED\n");
printf(" {0x%x, %d, { // \"%s\"\n", elt.first,
(nothe.count(s) ? 1:0) + (plural.count(s) ? 2:0),
escape(s, s));
@ -415,7 +414,6 @@ int main() {
}
printf(" }},\n");
if(isrepeat(s)) printf("#endif\n");
}
printf(" };\n");

View File

@ -4587,11 +4587,11 @@ S(
"are not about points on the ground level, but "
"about the matching points on the plane P -- "
"divide them by the factor above to get actual "
"distances.",
"distances.)",
"(Vzdálenosti v editoru vektorové "
"grafiky nejsou vzdálenosti bodů na úrovni země, ale odpovídajících bodů v rovině "
"P -- skutečné vzdálenosti získáte jejich vydělením výše zmíněným faktorem.")
"P -- skutečné vzdálenosti získáte jejich vydělením výše zmíněným faktorem.)")
S( "If we are viewing an equidistant g absolute units below a plane, "
"from a point c absolute units above the plane, this corresponds "
@ -6146,7 +6146,7 @@ S("would be destroyed in %the1", "by%l1by zničen%1 %abl1")
S(" to go cold", " vychladnout")
S("%The1 is destroyed by lava!", "Láva zničila %a1!")
S("%The1 is killed by lava!", "Láva zabila %a1!")
S("Run away from the lava!", "Utíkej od lávy!")
S("Run away from the magma!", "Utíkej od lávy!")
// Terracotta Army
//-----------------
@ -6693,7 +6693,7 @@ N("Chrysoberyl", GEN_O, "Chryzoberyl", "Chryzoberyly", "Chryzoberyl", "Chryzober
S("Fragment of the past glory.", "Fragment minulé slávy.")
N("Red Raider", GEN_M, "Èervený nájezdník", "Èervení nájezdníci", "Èerveného nájezdníka", "Èerveným nájezdníkem")
S("Red Raiders travel in pairs. They have promised to always watch another one's back. They are able to destroy walls on their way",
S("Red Raiders travel in pairs. They have promised to always watch each other's backs. They are able to destroy walls on their way.",
"Èervení nájezdníci cestují ve dvojicích. Slíbili si, že si vždycky budou navzájem "
"hlídat záda. Po cestì mohou nièit zdi.")
@ -7682,7 +7682,7 @@ S("A large bug native to the Brown Islands. Cannot be killed easily due to their
N("Acid Gull", GEN_M, "Kyselinoracek", "Kyselinorackové", "Kyselinoracka", "Kyselinorackem")
S("Where did this strange bird come from?...\n\n Acid Gulls dissolve the land on which they fall when they die. ",
S("Where did this strange bird come from?...\n\nAcid Gulls dissolve the land on which they fall when they die. ",
"Kde se tu vzal tenhle podivný pták...?\n\nKdyž Kyselinoracek zemře, rozpustí terén, na který dopadne.")
@ -7767,7 +7767,7 @@ S("These guys look a bit strange, but they have no special properties.",
N("Torbernite", GEN_O, "Torbernit", "Torbernity", "Torbernit", "Torbernitem")
S("Crystals emiting magical radiation.", "Drahokamy vyzařující prospěšnou magickou radiaci.")
S("Crystals emitting magical radiation.", "Drahokamy vyzařující prospěšnou magickou radiaci.")
N("fire trap", GEN_F, "ohnivá past", "ohnivé pasti", "ohnivou past", "ohnivou pastí")
@ -7845,7 +7845,7 @@ S(
N("Torbernite", GEN_O, "Torbernit", "Torbernity", "Torbernit", "Torbernitem")
S("Crystals emiting magical radiation.", "Krystaly vyzařující magickou radiaci.")
S("Crystals emitting magical radiation.", "Krystaly vyzařující magickou radiaci.")
// other things:
@ -7936,7 +7936,7 @@ S("Crystal", "Krystal")
#define Cell(x) \
S(x "-cell", x "-nadstěn") \
S(x "-cell (elliptic space", x "-nadstěn (eliptický prostor)")
S(x "-cell (elliptic space)", x "-nadstěn (eliptický prostor)")
Cell("{3,3,3} 5") Cell("{4,3,3} 8") Cell("{3,3,4} 16") Cell("{3,4,3} 24") Cell("{5,3,3} 120") Cell("{3,3,5} 600")
#undef Cell
@ -8408,7 +8408,7 @@ S("Hint: this is more playable with pure {7,3} or pure {5,4}", "Nápověda: toto
S("view the underlying geometry", "zobraz základní geometrii")
S("The space you are currently in the space of rotations of the underlying hyperbolic or spherical geometry. ",
S("The space you are currently in is the space of rotations of the underlying hyperbolic or spherical geometry. ",
"Prostor, ve kterém se právě nacházíš, je prostorem rotací základní hyperbolické nebo sférické geometrie. ")
S("This option lets you see the underlying space. Lands and some walls (e.g. in the Graveyard) are based on "

View File

@ -4501,10 +4501,10 @@ S("(Distances reported by the vector graphics editor "
"are not about points on the ground level, but "
"about the matching points on the plane P -- "
"divide them by the factor above to get actual "
"distances.",
"distances.)",
"(Odległości wyświetlane przez edytor grafiki "
"dotyczą odległości między odpowiednimi punktami na płaszczyźnie P.")
"dotyczą odległości między odpowiednimi punktami na płaszczyźnie P.)")
S( "If we are viewing an equidistant g absolute units below a plane, "
"from a point c absolute units above the plane, this corresponds "
@ -5057,7 +5057,7 @@ S("firewall lines: Palace", "linie ścian ognia: Pałac")
S("firewall lines: Power", "linie ścian ognia: Moc")
S("(ESC) tour menu", "(ESC) menu ucznia")
S("Try the Guided tour to help with understanding the "
S("Try the Guided Tour to help with understanding the "
"geometry of HyperRogue (menu -> special modes).\n\n",
"Uruchom Wycieczkę, by zrozumieć geometrię HyperRogue (menu -> tryby specjalne).\n\n")
@ -6037,7 +6037,7 @@ S("would be destroyed in %the1", "by%ł1by zniszczon%y1 %abl1")
S(" to go cold", " by ostygnąć")
S("%The1 is destroyed by lava!", "%The1 jest zniszczon%y1 przez lawę!")
S("%The1 is killed by lava!", "%The1 jest zabit%y1 przez lawę!")
S("Run away from the lava!", "Uciekaj od lawy!")
S("Run away from the magma!", "Uciekaj od lawy!")
// Terracotta Army
//-----------------
@ -6535,7 +6535,7 @@ N("Chrysoberyl", GEN_O, "Chryzoberyl", "Chryzoberyle", "Chryzoberyl", "Chryzober
S("Fragment of the past glory.", "Fragment dawnej chwały.")
N("Red Raider", GEN_M, "Czerwony Najeźdźca", "Czerwoni Najeźdźcy", "Czerwonego Najeźdźcę", "Czerwonym Najeźdźcą")
S("Red Raiders travel in pairs. They have promised to always watch another one's back. They are able to destroy walls on their way",
S("Red Raiders travel in pairs. They have promised to always watch each other's backs. They are able to destroy walls on their way.",
"Czerwoni Najeźdźcy podróżują parami. Obiecali sobie nawzajem, że zawsze będą chronić swoje tyły. Mogą niszczyć ściany na swojej drodze.")
N("Gray Raider", GEN_M, "Szary Najeźdźca", "Szarzy Najeźdźcy", "Szarego Najeźdźcę", "Szarym Najeźdźcą")
@ -7429,7 +7429,7 @@ S("A large bug native to the Brown Islands. Cannot be killed easily due to their
N("Acid Gull", GEN_F, "Kwaśna Mewa", "Kwaśne Mewy", "Kwaśną Mewę", "Kwaśną Mewą")
S("Where did this strange bird come from?...\n\n Acid Gulls dissolve the land on which they fall when they die. ",
S("Where did this strange bird come from?...\n\nAcid Gulls dissolve the land on which they fall when they die. ",
"Skąd się wziął ten dziwny ptak?...\n\nKwaśne Mewy rozpuszczają ląd, na który spadają, gdy zostaną zabite. ")
@ -7572,7 +7572,7 @@ S(
N("Torbernite", GEN_O, "Torbernit", "Torbernity", "Torbernit", "Torbernitem")
S("Crystals emiting magical radiation.", "Te kryształy emitują magiczne promieniowanie.")
S("Crystals emitting magical radiation.", "Te kryształy emitują magiczne promieniowanie.")
// other things:
@ -7661,7 +7661,7 @@ S("Crystal", "Kryształ")
#define Cell(x) \
S(x "-cell", x "-komórka") \
S(x "-cell (elliptic space", x "-komórka (przestrzeń eliptyczna)")
S(x "-cell (elliptic space)", x "-komórka (przestrzeń eliptyczna)")
Cell("{3,3,3} 5") Cell("{4,3,3} 8") Cell("{3,3,4} 16") Cell("{3,4,3} 24") Cell("{5,3,3} 120") Cell("{3,3,5} 600")
#undef Cell

View File

@ -4579,7 +4579,7 @@ S("Ground level is actually an equidistant surface, "
"are not about points on the ground level, but "
"about the matching points on the plane P -- "
"divide them by the factor above to get actual "
"distances.",
"distances.)",
"Poziom podłoża jest w rzeczywistości ekwidystantną powierzchnią "
"%1 jednostek pod płaszczyzną P. Teoretycznie, ta wartość "
@ -4587,7 +4587,7 @@ S("Ground level is actually an equidistant surface, "
"szybciej latając powyżej poziomu podłoża, na wysokości płaszczyzny "
"P -- ale nie wpływa to na mechanikę gry w żaden sposób. "
"(Odległości wyświetlane przez edytor grafiki "
"dotyczą odległości między odpowiednimi punktami na płaszczyźnie P.")
"dotyczą odległości między odpowiednimi punktami na płaszczyźnie P.)")
S( "If we are viewing an equidistant g absolute units below a plane, "
"from a point c absolute units above the plane, this corresponds "

View File

@ -4676,7 +4676,7 @@ S("(Distances reported by the vector graphics editor "
"are not about points on the ground level, but "
"about the matching points on the plane P -- "
"divide them by the factor above to get actual "
"distances.",
"distances.)",
"(Расстояния в редакторе векторной графики относятся"
"не к точкам на поверхности, а к их проекциям на плоскость P.)")
@ -6220,7 +6220,7 @@ S("would be destroyed in %the1", "будет уничтожено %abl1")
S(" to go cold", " чтобы остыть")
S("%The1 is destroyed by lava!", "%1 уничтожен%E1 лавой!")
S("%The1 is killed by lava!", "%1 убит%E1 лавой!")
S("Run away from the lava!", "Беги из лавы!")
S("Run away from the magma!", "Беги из лавы!")
// Terracotta Army
//-----------------
@ -6760,7 +6760,7 @@ N("Chrysoberyl", GEN_O, "Хризоберилл", "Хризобериллы", "
S("Fragment of the past glory.", "Фрагмент былой славы.")
N("Red Raider", GEN_M, "Красный Рейдер", "Красные Рейдеры", "Красного Рейдера", "Красным Рейдером")
S("Red Raiders travel in pairs. They have promised to always watch another one's back. They are able to destroy walls on their way",
S("Red Raiders travel in pairs. They have promised to always watch each other's backs. They are able to destroy walls on their way.",
"Красные рейдеры путешествуют парами. Они обещали, что будут защищать спины друг друга. Они могут разрушать стены на своем пути.")
N("Gray Raider", GEN_M, "Серый Рейдер", "Серые Рейдеры", "Серого Рейдера", "Серым Рейдером")