aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/camera.cpp23
-rw-r--r--src/client/camera.h3
-rw-r--r--src/client/game.cpp37
-rw-r--r--src/gettext.h29
-rw-r--r--src/unittest/CMakeLists.txt1
-rw-r--r--src/unittest/test_gettext.cpp47
6 files changed, 95 insertions, 45 deletions
diff --git a/src/client/camera.cpp b/src/client/camera.cpp
index 1ce92f196..3712d77ea 100644
--- a/src/client/camera.cpp
+++ b/src/client/camera.cpp
@@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "constants.h"
#include "fontengine.h"
#include "script/scripting_client.h"
+#include "gettext.h"
#define CAMERA_OFFSET_STEP 200
#define WIELDMESH_OFFSET_X 55.0f
@@ -133,28 +134,6 @@ void Camera::notifyFovChange()
}
}
-bool Camera::successfullyCreated(std::string &error_message)
-{
- if (!m_playernode) {
- error_message = "Failed to create the player scene node";
- } else if (!m_headnode) {
- error_message = "Failed to create the head scene node";
- } else if (!m_cameranode) {
- error_message = "Failed to create the camera scene node";
- } else if (!m_wieldmgr) {
- error_message = "Failed to create the wielded item scene manager";
- } else if (!m_wieldnode) {
- error_message = "Failed to create the wielded item scene node";
- } else {
- error_message.clear();
- }
-
- if (m_client->modsLoaded())
- m_client->getScript()->on_camera_ready(this);
-
- return error_message.empty();
-}
-
// Returns the fractional part of x
inline f32 my_modf(f32 x)
{
diff --git a/src/client/camera.h b/src/client/camera.h
index bea9ab333..3e1cb4fdf 100644
--- a/src/client/camera.h
+++ b/src/client/camera.h
@@ -136,9 +136,6 @@ public:
// Notify about new server-sent FOV and initialize smooth FOV transition
void notifyFovChange();
- // Checks if the constructor was able to create the scene nodes
- bool successfullyCreated(std::string &error_message);
-
// Step the camera: updates the viewing range and view bobbing.
void step(f32 dtime);
diff --git a/src/client/game.cpp b/src/client/game.cpp
index 7f0aff49c..fb993d92f 100644
--- a/src/client/game.cpp
+++ b/src/client/game.cpp
@@ -1282,9 +1282,8 @@ bool Game::createSingleplayerServer(const std::string &map_dir,
}
if (bind_addr.isIPv6() && !g_settings->getBool("enable_ipv6")) {
- *error_message = "Unable to listen on " +
- bind_addr.serializeString() +
- " because IPv6 is disabled";
+ *error_message = fmtgettext("Unable to listen on %s because IPv6 is disabled",
+ bind_addr.serializeString().c_str());
errorstream << *error_message << std::endl;
return false;
}
@@ -1317,7 +1316,7 @@ bool Game::createClient(const GameStartData &start_data)
if (!could_connect) {
if (error_message->empty() && !connect_aborted) {
// Should not happen if error messages are set properly
- *error_message = "Connection failed for unknown reason";
+ *error_message = gettext("Connection failed for unknown reason");
errorstream << *error_message << std::endl;
}
return false;
@@ -1326,7 +1325,7 @@ bool Game::createClient(const GameStartData &start_data)
if (!getServerContent(&connect_aborted)) {
if (error_message->empty() && !connect_aborted) {
// Should not happen if error messages are set properly
- *error_message = "Connection failed for unknown reason";
+ *error_message = gettext("Connection failed for unknown reason");
errorstream << *error_message << std::endl;
}
return false;
@@ -1342,8 +1341,8 @@ bool Game::createClient(const GameStartData &start_data)
/* Camera
*/
camera = new Camera(*draw_control, client, m_rendering_engine);
- if (!camera->successfullyCreated(*error_message))
- return false;
+ if (client->modsLoaded())
+ client->getScript()->on_camera_ready(camera);
client->setCamera(camera);
/* Clouds
@@ -1456,15 +1455,14 @@ bool Game::connectToServer(const GameStartData &start_data,
local_server_mode = true;
}
} catch (ResolveError &e) {
- *error_message = std::string("Couldn't resolve address: ") + e.what();
+ *error_message = fmtgettext("Couldn't resolve address: %s", e.what());
+
errorstream << *error_message << std::endl;
return false;
}
if (connect_address.isIPv6() && !g_settings->getBool("enable_ipv6")) {
- *error_message = "Unable to connect to " +
- connect_address.serializeString() +
- " because IPv6 is disabled";
+ *error_message = fmtgettext("Unable to connect to %s because IPv6 is disabled", connect_address.serializeString().c_str());
errorstream << *error_message << std::endl;
return false;
}
@@ -1518,8 +1516,7 @@ bool Game::connectToServer(const GameStartData &start_data,
break;
if (client->accessDenied()) {
- *error_message = "Access denied. Reason: "
- + client->accessDeniedReason();
+ *error_message = fmtgettext("Access denied. Reason: %s", client->accessDeniedReason().c_str());
*reconnect_requested = client->reconnectRequested();
errorstream << *error_message << std::endl;
break;
@@ -1545,7 +1542,7 @@ bool Game::connectToServer(const GameStartData &start_data,
wait_time += dtime;
// Only time out if we aren't waiting for the server we started
if (!start_data.address.empty() && wait_time > 10) {
- *error_message = "Connection timed out.";
+ *error_message = gettext("Connection timed out.");
errorstream << *error_message << std::endl;
break;
}
@@ -1593,7 +1590,7 @@ bool Game::getServerContent(bool *aborted)
return false;
if (client->getState() < LC_Init) {
- *error_message = "Client disconnected";
+ *error_message = gettext("Client disconnected");
errorstream << *error_message << std::endl;
return false;
}
@@ -1675,8 +1672,7 @@ inline void Game::updateInteractTimers(f32 dtime)
inline bool Game::checkConnection()
{
if (client->accessDenied()) {
- *error_message = "Access denied. Reason: "
- + client->accessDeniedReason();
+ *error_message = fmtgettext("Access denied. Reason: %s", client->accessDeniedReason().c_str());
*reconnect_requested = client->reconnectRequested();
errorstream << *error_message << std::endl;
return false;
@@ -4351,14 +4347,15 @@ void the_game(bool *kill,
}
} catch (SerializationError &e) {
- error_message = std::string("A serialization error occurred:\n")
- + e.what() + "\n\nThe server is probably "
- " running a different version of " PROJECT_NAME_C ".";
+ const std::string ver_err = fmtgettext("The server is probably running a different version of %s.", PROJECT_NAME_C);
+ error_message = strgettext("A serialization error occurred:") +"\n"
+ + e.what() + "\n\n" + ver_err;
errorstream << error_message << std::endl;
} catch (ServerError &e) {
error_message = e.what();
errorstream << "ServerError: " << error_message << std::endl;
} catch (ModError &e) {
+ // DO NOT TRANSLATE the `ModError`, it's used by ui.lua
error_message = std::string("ModError: ") + e.what() +
strgettext("\nCheck debug.txt for details.");
errorstream << error_message << std::endl;
diff --git a/src/gettext.h b/src/gettext.h
index 5a3654be4..67fd9244f 100644
--- a/src/gettext.h
+++ b/src/gettext.h
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "config.h" // for USE_GETTEXT
#include <string>
+#include "porting.h"
#if USE_GETTEXT
#include <libintl.h>
@@ -77,3 +78,31 @@ inline std::wstring fwgettext(const char *src, Args&&... args)
delete[] str;
return std::wstring(buf);
}
+
+/**
+ * Returns translated string with format args applied
+ *
+ * @tparam Args Template parameter for format args
+ * @param format Translation source string
+ * @param args Variable format args
+ * @return translated string.
+ */
+template <typename ...Args>
+inline std::string fmtgettext(const char *format, Args&&... args)
+{
+ std::string buf;
+ std::size_t buf_size = 256;
+ buf.resize(buf_size);
+
+ format = gettext(format);
+
+ int len = porting::mt_snprintf(&buf[0], buf_size, format, std::forward<Args>(args)...);
+ if (len <= 0) throw std::runtime_error("gettext format error: " + std::string(format));
+ if ((size_t)len >= buf.size()) {
+ buf.resize(len+1); // extra null byte
+ porting::mt_snprintf(&buf[0], buf.size(), format, std::forward<Args>(args)...);
+ }
+ buf.resize(len); // remove null bytes
+
+ return buf;
+}
diff --git a/src/unittest/CMakeLists.txt b/src/unittest/CMakeLists.txt
index 52f870901..4d295e4ed 100644
--- a/src/unittest/CMakeLists.txt
+++ b/src/unittest/CMakeLists.txt
@@ -33,6 +33,7 @@ set (UNITTEST_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/test_voxelarea.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_voxelalgorithms.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_voxelmanipulator.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test_gettext.cpp
PARENT_SCOPE)
set (UNITTEST_CLIENT_SRCS
diff --git a/src/unittest/test_gettext.cpp b/src/unittest/test_gettext.cpp
new file mode 100644
index 000000000..98f73ec62
--- /dev/null
+++ b/src/unittest/test_gettext.cpp
@@ -0,0 +1,47 @@
+#include "test.h"
+#include "porting.h"
+#include "gettext.h"
+
+class TestGettext : public TestBase
+{
+public:
+ TestGettext() {
+ TestManager::registerTestModule(this);
+ }
+
+ const char *getName() { return "TestGettext"; }
+
+ void runTests(IGameDef *gamedef);
+
+ void testSnfmtgettext();
+ void testFmtgettext();
+};
+
+static TestGettext g_test_instance;
+
+void TestGettext::runTests(IGameDef *gamedef)
+{
+ TEST(testFmtgettext);
+}
+
+void TestGettext::testFmtgettext()
+{
+ std::string buf = fmtgettext("Viewing range changed to %d", 12);
+ UASSERTEQ(std::string, buf, "Viewing range changed to 12");
+ buf = fmtgettext(
+ "You are about to join this server with the name \"%s\" for the "
+ "first time.\n"
+ "If you proceed, a new account using your credentials will be "
+ "created on this server.\n"
+ "Please retype your password and click 'Register and Join' to "
+ "confirm account creation, or click 'Cancel' to abort."
+ , "A");
+ UASSERTEQ(std::string, buf,
+ "You are about to join this server with the name \"A\" for the "
+ "first time.\n"
+ "If you proceed, a new account using your credentials will be "
+ "created on this server.\n"
+ "Please retype your password and click 'Register and Join' to "
+ "confirm account creation, or click 'Cancel' to abort."
+ );
+}