mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-20 23:23:30 +02:00
Labels: - every button, field, tooltip and message of the editor reread for a beginner: short nouns for the fields with the sentence in the tooltip, the less used options under More settings, one glossary (field of work, template, track, grade), sides told from directions, degrees and per mille as signs, messages built from one format string - plural forms through STR_P; the last entry of a po file is read too, and the Polish plural rule is in the header - lang/editor_pl.po: the code pass entries merged, 391 entries no code uses and 3 duplicates dropped - roads: the notes and errors naming a road translated; the build options and the layout fold the texture length, kerb sizes, traffic share, roundabout part, height over the ground and junction speed limit under More settings, the lanes start folded Grade lines fitted to the terrain model (NMT), a line or the whole scenery at once: - fit_ground: a robust fit on nodes 5 m apart; the ground parting from the line (a bridge, a viaduct, a wall) is gone past rather than followed, the bends keep off the switches as far as their curves reach, a run of bends the same way is one point of intersection, a curve with no room is as sharp as the room lets it be - the ends of the line and the other paths of its switches leading into lines fitted already bound the line by what the tracks between can climb; ends meeting in the plan, laid apart in height by hand, are joined before the run - apply_profile: the paths are split where split_path takes the parameter (a straight was cut in the wrong place, into pieces of a few centimetres the game takes for zero length), no piece shorter than the margin; the paths off the ends of the route are brought to its height - Bytom: 1600 lines, grade breaks at the joints 89 -> 20; Tarnowskie Gory: 848 lines, 223 -> 3; no step over 2 cm
434 lines
15 KiB
C++
434 lines
15 KiB
C++
/*
|
|
This Source Code Form is subject to the
|
|
terms of the Mozilla Public License, v.
|
|
2.0. If a copy of the MPL was not
|
|
distributed with this file, You can
|
|
obtain one at
|
|
http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
/*
|
|
MaSzyna EU07 locomotive simulator
|
|
Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "utilities/translation.h"
|
|
#include "utilities/Logs.h"
|
|
#include "utilities/Globals.h"
|
|
#include "MOVER.h"
|
|
|
|
void locale::init()
|
|
{
|
|
std::fstream stream("lang/" + Global.asLang + ".po", std::ios_base::in | std::ios_base::binary);
|
|
|
|
if (!stream.is_open()) {
|
|
WriteLog("translation: cannot open lang file: lang/" + Global.asLang + ".po");
|
|
return;
|
|
}
|
|
|
|
crashreport_add_info("translation", Global.asLang);
|
|
|
|
while (parse_translation(stream));
|
|
|
|
// texts of the scenery editor, kept apart from the translation of the simulator
|
|
std::fstream editor("lang/editor_" + Global.asLang + ".po", std::ios_base::in | std::ios_base::binary);
|
|
if (editor.is_open())
|
|
while (parse_translation(editor));
|
|
|
|
WriteLog("translation: " + std::to_string(lang_mapping.size()) + " strings and " + std::to_string(plural_mapping.size()) + " plural strings loaded");
|
|
}
|
|
|
|
const std::string& locale::lookup_s(const std::string &msg, bool constant)
|
|
{
|
|
if (constant) {
|
|
auto it = pointer_cache.find(&msg);
|
|
if (it != pointer_cache.end())
|
|
return *(const std::string *)it->second;
|
|
}
|
|
|
|
auto it = lang_mapping.find(msg);
|
|
if (it != lang_mapping.end()) {
|
|
if (constant)
|
|
pointer_cache.emplace(&msg, &it->second);
|
|
return it->second;
|
|
}
|
|
|
|
if (constant)
|
|
pointer_cache.emplace(&msg, &msg);
|
|
return msg;
|
|
}
|
|
|
|
const char* locale::lookup_c(const char *msg, bool constant)
|
|
{
|
|
if (constant) {
|
|
auto it = pointer_cache.find(msg);
|
|
if (it != pointer_cache.end())
|
|
return (const char*)it->second;
|
|
}
|
|
|
|
auto it = lang_mapping.find(std::string(msg));
|
|
if (it != lang_mapping.end()) {
|
|
if (constant)
|
|
pointer_cache.emplace(msg, it->second.c_str());
|
|
return it->second.c_str();
|
|
}
|
|
|
|
if (constant)
|
|
pointer_cache.emplace(msg, msg);
|
|
return msg;
|
|
}
|
|
|
|
const char* locale::lookup_n(const char *singular, const char *plural, long long n)
|
|
{
|
|
auto cached = plural_cache.find(singular);
|
|
if (cached == plural_cache.end()) {
|
|
auto it = plural_mapping.find(std::string(singular));
|
|
cached = plural_cache.emplace(singular, it != plural_mapping.end() ? &it->second : nullptr).first;
|
|
}
|
|
|
|
if (cached->second == nullptr)
|
|
return n == 1 ? singular : plural;
|
|
|
|
auto const &forms = *cached->second;
|
|
auto const form = std::min(plural_form(n), forms.size() - 1);
|
|
return forms[form].empty() ? (n == 1 ? singular : plural) : forms[form].c_str();
|
|
}
|
|
|
|
std::size_t locale::plural_form(long long n) const
|
|
{
|
|
n = std::llabs(n);
|
|
if (Global.asLang.compare(0, 2, "pl") == 0) {
|
|
if (n == 1)
|
|
return 0;
|
|
auto const units = n % 10;
|
|
auto const tens = n % 100;
|
|
return units >= 2 && units <= 4 && (tens < 10 || tens >= 20) ? 1 : 2;
|
|
}
|
|
return n == 1 ? 0 : 1;
|
|
}
|
|
|
|
bool locale::parse_translation(std::istream &stream)
|
|
{
|
|
std::string line;
|
|
|
|
std::string msgid;
|
|
std::string msgstr;
|
|
std::string msgctxt;
|
|
std::vector<std::string> forms;
|
|
char last = 'x';
|
|
|
|
auto const commit = [&]() {
|
|
if (!msgid.empty() && !forms.empty())
|
|
plural_mapping.emplace(msgid, std::move(forms));
|
|
else if (!msgid.empty() && !msgstr.empty()) {
|
|
// TODO: context support is incomplete
|
|
if (!msgctxt.empty())
|
|
lang_mapping.emplace(msgctxt + "\x1d" + msgid, msgstr);
|
|
else
|
|
lang_mapping.emplace(msgid, msgstr);
|
|
}
|
|
};
|
|
|
|
while (std::getline(stream, line)) {
|
|
if (line.size() > 0 && line[0] == '#')
|
|
continue;
|
|
|
|
if (line.starts_with("msgid_plural"))
|
|
last = 'p';
|
|
else if (line.starts_with("msgid"))
|
|
last = 'i';
|
|
else if (line.starts_with("msgstr[")) {
|
|
last = 'n';
|
|
forms.resize(std::max<std::size_t>(forms.size(), std::atoi(line.c_str() + 7) + 1));
|
|
}
|
|
else if (line.starts_with("msgstr"))
|
|
last = 's';
|
|
else if (line.starts_with("msgctxt"))
|
|
last = 'c';
|
|
|
|
if (line.size() > 1 && last != 'x') {
|
|
if (last == 'i')
|
|
msgid += parse_c_literal(line);
|
|
else if (last == 's')
|
|
msgstr += parse_c_literal(line);
|
|
else if (last == 'n')
|
|
forms.back() += parse_c_literal(line);
|
|
else if (last == 'c')
|
|
msgctxt += parse_c_literal(line);
|
|
}
|
|
else {
|
|
commit();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (!msgid.empty()) {
|
|
commit();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::string locale::parse_c_literal(const std::string &str)
|
|
{
|
|
std::istringstream stream(str);
|
|
std::string out;
|
|
|
|
bool active = false;
|
|
bool escape = false;
|
|
|
|
char c;
|
|
while ((c = stream.get()) != std::char_traits<char>::eof()) {
|
|
if (!escape && c == '"')
|
|
active = !active;
|
|
else if (active && !escape && c == '\\')
|
|
escape = true;
|
|
else if (active && escape) {
|
|
if (c == 'r')
|
|
out += '\r';
|
|
else if (c == 'n')
|
|
out += '\n';
|
|
else if (c == 't')
|
|
out += '\t';
|
|
else if (c == '\\')
|
|
out += '\\';
|
|
else if (c == '?')
|
|
out += '?';
|
|
else if (c == '\'')
|
|
out += '\'';
|
|
else if (c == '"')
|
|
out += '"';
|
|
else if (c == 'x') {
|
|
char n1 = stream.get() - 48;
|
|
char n2 = stream.get() - 48;
|
|
if (n1 > 9)
|
|
n1 -= 7;
|
|
if (n1 > 16)
|
|
n1 -= 32;
|
|
if (n2 > 9)
|
|
n2 -= 7;
|
|
if (n2 > 16)
|
|
n2 -= 32;
|
|
out += n1 << 4 | n2;
|
|
}
|
|
escape = false;
|
|
}
|
|
else if (active)
|
|
out += c;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
std::string locale::label_cab_control(std::string const &Label)
|
|
{
|
|
if( Label.empty() ) { return ""; }
|
|
|
|
static std::unordered_map<std::string, std::string> cabcontrols_labels = {
|
|
{ "mainctrl:", STRN("master controller") },
|
|
{ "jointctrl:", STRN("master controller") },
|
|
{ "scndctrl:", STRN("second controller") },
|
|
{ "shuntmodepower:", STRN("shunt mode power") },
|
|
{ "tempomat_sw:", STRN("cruise control") },
|
|
{ "tempomatoff_sw:", STRN("cruise control") },
|
|
{ "speedinc_bt:", STRN("cruise control (speed)") },
|
|
{ "speeddec_bt:", STRN("cruise control (speed)") },
|
|
{ "speedctrlpowerinc_bt:", STRN("cruise control (power)") },
|
|
{ "speedctrlpowerdec_bt:", STRN("cruise control (power)") },
|
|
{ "speedbutton0:", STRN("cruise control (speed)") },
|
|
{ "speedbutton1:", STRN("cruise control (speed)") },
|
|
{ "speedbutton2:", STRN("cruise control (speed)") },
|
|
{ "speedbutton3:", STRN("cruise control (speed)") },
|
|
{ "speedbutton4:", STRN("cruise control (speed)") },
|
|
{ "speedbutton5:", STRN("cruise control (speed)") },
|
|
{ "speedbutton6:", STRN("cruise control (speed)") },
|
|
{ "speedbutton7:", STRN("cruise control (speed)") },
|
|
{ "speedbutton8:", STRN("cruise control (speed)") },
|
|
{ "speedbutton9:", STRN("cruise control (speed)") },
|
|
{ "distancecounter_sw:", STRN("distance counter") },
|
|
{ "dirkey:", STRN("reverser") },
|
|
{ "dirbackward_bt:", STRN("reverser") },
|
|
{ "dirforward_bt:", STRN("reverser") },
|
|
{ "dirneutral_bt:", STRN("reverser") },
|
|
{ "brakectrl:", STRN("train brake") },
|
|
{ "localbrake:", STRN("independent brake") },
|
|
{ "manualbrake:", STRN("manual brake") },
|
|
{ "alarmchain:", STRN("emergency brake") },
|
|
{ "brakeprofile_sw:", STRN("brake acting speed") },
|
|
{ "brakeprofileg_sw:", STRN("brake acting speed: cargo") },
|
|
{ "brakeprofiler_sw:", STRN("brake acting speed: rapid") },
|
|
{ "brakeopmode_sw", STRN("brake operation mode") },
|
|
{ "maxcurrent_sw:", STRN("motor overload relay threshold") },
|
|
{ "waterpump_sw:", STRN("water pump") },
|
|
{ "waterpumpbreaker_sw:", STRN("water pump breaker") },
|
|
{ "waterheater_sw:", STRN("water heater") },
|
|
{ "waterheaterbreaker_sw:", STRN("water heater breaker") },
|
|
{ "watercircuitslink_sw:", STRN("water circuits link") },
|
|
{ "fuelpump_sw:", STRN("fuel pump") },
|
|
{ "oilpump_sw:", STRN("oil pump") },
|
|
{ "motorblowersfront_sw:", STRN("motor blowers A") },
|
|
{ "motorblowersrear_sw:", STRN("motor blowers B") },
|
|
{ "motorblowersalloff_sw:", STRN("all motor blowers") },
|
|
{ "coolingfans_sw:", STRN("cooling fans") },
|
|
{ "main_off_bt:", STRN("line breaker") },
|
|
{ "main_on_bt:", STRN("line breaker") },
|
|
{ "security_reset_bt:", STRN("alerter") },
|
|
{ "shp_reset_bt:", STRN("shp") },
|
|
{ "releaser_bt:", STRN("independent brake releaser") },
|
|
{ "sand_bt:", STRN("sandbox") },
|
|
{ "antislip_bt:", STRN("wheelspin brake") },
|
|
{ "horn_bt:", STRN("horn") },
|
|
{ "hornlow_bt:", STRN("low tone horn") },
|
|
{ "hornhigh_bt:", STRN("high tone horn") },
|
|
{ "whistle_bt:", STRN("whistle") },
|
|
{ "fuse_bt:", STRN("motor overload relay reset") },
|
|
{ "converterfuse_bt:", STRN("converter overload relay reset") },
|
|
{ "stlinoff_bt:", STRN("motor connectors") },
|
|
{ "doorleftpermit_sw:", STRN("left door (permit)") },
|
|
{ "doorrightpermit_sw:", STRN("right door (permit)") },
|
|
{ "doorpermitpreset_sw:", STRN("door (permit)") },
|
|
{ "door_left_sw:", STRN("left door") },
|
|
{ "door_right_sw:", STRN("right door") },
|
|
{ "doorlefton_sw:", STRN("left door (open)") },
|
|
{ "doorrighton_sw:", STRN("right door (open)") },
|
|
{ "doorleftoff_sw:", STRN("left door (close)") },
|
|
{ "doorrightoff_sw:", STRN("right door (close)") },
|
|
{ "doorallon_sw:", STRN("all doors (open)") },
|
|
{ "dooralloff_sw:", STRN("all doors (close)") },
|
|
{ "doorstep_sw:", STRN("doorstep") },
|
|
{ "doormode_sw", STRN("door control mode") },
|
|
{ "departure_signal_bt:", STRN("departure signal") },
|
|
{ "upperlight_sw:", STRN("upper headlight") },
|
|
{ "leftlight_sw:", STRN("left headlight") },
|
|
{ "rightlight_sw:", STRN("right headlight") },
|
|
{ "dimheadlights_sw:", STRN("headlights dimmer") },
|
|
{ "moderndimmer_sw:", STRN("headlights dimmer") },
|
|
{ "leftend_sw:", STRN("left marker light") },
|
|
{ "rightend_sw:", STRN("right marker light") },
|
|
{ "lights_sw:", STRN("light pattern") },
|
|
{ "rearupperlight_sw:", STRN("rear upper headlight") },
|
|
{ "rearleftlight_sw:", STRN("rear left headlight") },
|
|
{ "rearrightlight_sw:", STRN("rear right headlight") },
|
|
{ "rearleftend_sw:", STRN("rear left marker light") },
|
|
{ "rearrightend_sw:", STRN("rear right marker light") },
|
|
{ "compressor_sw:", STRN("compressor") },
|
|
{ "compressorlocal_sw:", STRN("local compressor") },
|
|
{ "converter_sw:", STRN("converter") },
|
|
{ "converterlocal_sw:", STRN("local converter") },
|
|
{ "converteroff_sw:", STRN("converter") },
|
|
{ "main_sw:", STRN("line breaker") },
|
|
{ "radio_sw:", STRN("radio") },
|
|
{ "radiochannel_sw:", STRN("radio channel") },
|
|
{ "radiochannelprev_sw:", STRN("radio channel") },
|
|
{ "radiochannelnext_sw:", STRN("radio channel") },
|
|
{ "radiotest_sw:", STRN("radiostop test") },
|
|
{ "radiostop_sw:", STRN("radiostop") },
|
|
{ "radiocall3_sw:", STRN("radio call 3") },
|
|
{ "radiovolume_sw:", STRN("radio volume") },
|
|
{ "radiovolumenext_sw:", STRN("radio volume") },
|
|
{ "radiovolumeprev_sw:", STRN("radio volume") },
|
|
{ "pantfront_sw:", STRN("pantograph A") },
|
|
{ "pantrear_sw:", STRN("pantograph B") },
|
|
{ "pantfrontoff_sw:", STRN("pantograph A") },
|
|
{ "pantrearoff_sw:", STRN("pantograph B") },
|
|
{ "pantalloff_sw:", STRN("all pantographs") },
|
|
{ "pantselected_sw:", STRN("selected pantograph") },
|
|
{ "pantselectedoff_sw:", STRN("selected pantograph") },
|
|
{ "pantselect_sw:", STRN("selected pantograph") },
|
|
{ "pantvalves_sw:", STRN("selected pantograph") },
|
|
{ "pantvalvesoff_bt:", STRN("all pantographs down") },
|
|
{ "pantvalvesupdate_bt:", STRN("selected pantographs up") },
|
|
{ "pantcompressor_sw:", STRN("pantograph compressor") },
|
|
{ "pantcompressorvalve_sw:", STRN("pantograph 3 way valve") },
|
|
{ "trainheating_sw:", STRN("heating") },
|
|
{ "signalling_sw:", STRN("braking indicator") },
|
|
{ "door_signalling_sw:", STRN("door locking") },
|
|
{ "nextcurrent_sw:", STRN("current indicator source") },
|
|
{ "instrumentlight_sw:", STRN("instrument light") },
|
|
{ "dashboardlight_sw:", STRN("dashboard light") },
|
|
{ "timetablelight_sw:", STRN("timetable light") },
|
|
{ "cablight_sw:", STRN("interior light") },
|
|
{ "cablightdim_sw:", STRN("interior light dimmer") },
|
|
{ "compartmentlights_sw:", STRN("compartment lights") },
|
|
{ "compartmentlightsoff_sw:", STRN("compartment lights") },
|
|
{ "compartmentlightson_sw:", STRN("compartment lights") },
|
|
{ "couplingdisconnect_sw:", STRN("coupling") },
|
|
{ "battery_sw:", STRN("battery") },
|
|
{ "batteryon_sw:", STRN("battery") },
|
|
{ "batteryoff_sw:", STRN("battery") },
|
|
{ "epbrake_bt:", STRN("ep brake") },
|
|
{ "relayreset1_bt:", STRN("relay reset") },
|
|
{ "relayreset2_bt:", STRN("relay reset") },
|
|
{ "relayreset3_bt:", STRN("relay reset") },
|
|
{ "springbrakeoff_bt:", STRN("spring brake") },
|
|
{ "springbrakeon_bt:", STRN("spring brake") },
|
|
{ "springbraketoggle_bt:", STRN("spring brake") },
|
|
{ "universalbrake1_bt:", STRN("train brake") },
|
|
{ "universalbrake2_bt:", STRN("train brake") },
|
|
{ "universalbrake3_bt:", STRN("train brake") },
|
|
{"universal0:", STRN("interactive part")},
|
|
{"universal1:", STRN("interactive part")},
|
|
{"universal2:", STRN("interactive part")},
|
|
{"universal3:", STRN("interactive part")},
|
|
{"universal4:", STRN("interactive part")},
|
|
{"universal5:", STRN("interactive part")},
|
|
{"universal6:", STRN("interactive part")},
|
|
{"universal7:", STRN("interactive part")},
|
|
{"universal8:", STRN("interactive part")},
|
|
{"universal9:", STRN("interactive part")},
|
|
{"universal10:", STRN("interactive part")},
|
|
{"universal11:", STRN("interactive part")},
|
|
{"universal12:", STRN("interactive part")},
|
|
{"universal13:", STRN("interactive part")},
|
|
{"universal14:", STRN("interactive part")},
|
|
{"universal15:", STRN("interactive part")},
|
|
{"universal16:", STRN("interactive part")},
|
|
{"universal17:", STRN("interactive part")},
|
|
{"universal18:", STRN("interactive part")},
|
|
{"universal19:", STRN("interactive part")},
|
|
{"universal20:", STRN("interactive part")},
|
|
{"universal21:", STRN("interactive part")},
|
|
{"universal22:", STRN("interactive part")},
|
|
{"universal23:", STRN("interactive part")},
|
|
{"universal24:", STRN("interactive part")},
|
|
{"universal25:", STRN("interactive part")},
|
|
{"universal26:", STRN("interactive part")},
|
|
{"universal27:", STRN("interactive part")},
|
|
{"universal28:", STRN("interactive part")},
|
|
{"universal29:", STRN("interactive part")},
|
|
{ "wipers_sw:", STRN("wipers mode selector") },
|
|
};
|
|
|
|
auto const it = cabcontrols_labels.find( Label );
|
|
return it != cabcontrols_labels.end() ? lookup_s(it->second) : "";
|
|
}
|
|
|
|
const std::string& locale::coupling_name(int c)
|
|
{
|
|
static std::unordered_map<coupling, std::string> coupling_names =
|
|
{
|
|
{ coupling::faux, STRN("faux") },
|
|
{ coupling::coupler, STRN("coupler") },
|
|
{ coupling::brakehose, STRN("brake hose") },
|
|
{ coupling::control, STRN("control") },
|
|
{ coupling::highvoltage, STRN("high voltage") },
|
|
{ coupling::gangway, STRN("gangway") },
|
|
{ coupling::mainhose, STRN("main hose") },
|
|
{ coupling::heating, STRN("heating") },
|
|
{ coupling::permanent, STRN("permanent") },
|
|
{ coupling::power24v, STRN("power 24V") },
|
|
{ coupling::power110v, STRN("power 110V") },
|
|
{ coupling::power3x400v, STRN("power 3x400V") },
|
|
};
|
|
|
|
static std::string unknown(STRN("unknown"));
|
|
|
|
auto it = coupling_names.find(static_cast<coupling>(c));
|
|
if (it != coupling_names.end())
|
|
return lookup_s(it->second);
|
|
else
|
|
return lookup_s(unknown);
|
|
}
|
|
|
|
locale Translations;
|