--- a/QTfrontend/binds.cpp Mon Aug 20 22:38:14 2018 +0200
+++ b/QTfrontend/binds.cpp Tue Aug 21 18:35:19 2018 +0200
@@ -56,8 +56,8 @@
{"zoomin", "wheelup", QT_TRANSLATE_NOOP("binds", "zoom in"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Modify the camera's zoom level:")},
{"zoomout", "wheeldown", QT_TRANSLATE_NOOP("binds", "zoom out"), NULL, NULL},
{"zoomreset", "mousem", QT_TRANSLATE_NOOP("binds", "reset zoom"), NULL, NULL},
- {"chat", "t", QT_TRANSLATE_NOOP("binds", "chat"), QT_TRANSLATE_NOOP("binds (categories)", "Miscellaneous"), QT_TRANSLATE_NOOP("binds (descriptions)", "Talk to your team or all participants:")},
- {"chat team", "u", QT_TRANSLATE_NOOP("binds", "team chat"), NULL, NULL},
+ {"chat", "t", QT_TRANSLATE_NOOP("binds", "chat"), QT_TRANSLATE_NOOP("binds (categories)", "Miscellaneous"), QT_TRANSLATE_NOOP("binds (descriptions)", "Talk to your clan or all participants:")},
+ {"chat team", "u", QT_TRANSLATE_NOOP("binds", "clan chat"), NULL, NULL},
{"history", "`", QT_TRANSLATE_NOOP("binds", "chat history"), NULL, NULL},
{"pause", "p", QT_TRANSLATE_NOOP("binds", "pause / auto skip"),NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Pause, continue or leave your game:")},
{"quit", "escape", QT_TRANSLATE_NOOP("binds", "quit"), NULL, NULL},
--- a/QTfrontend/hwform.cpp Mon Aug 20 22:38:14 2018 +0200
+++ b/QTfrontend/hwform.cpp Tue Aug 21 18:35:19 2018 +0200
@@ -1672,7 +1672,8 @@
}
if (pnetserver)
return; // we have server - let it care of all things
- if (hwnet) {
+ if (hwnet && (reason != "bye") && (!reason.startsWith("User quit: ")))
+ {
QString errorStr = QMessageBox::tr("The connection to the server is lost.") + (reason.isEmpty()?"":("\n\n" + HWNewNet::tr("Reason:") + "\n" + reason));
MessageDialog::ShowErrorMessage(errorStr, this);
}
--- a/QTfrontend/model/netserverslist.cpp Mon Aug 20 22:38:14 2018 +0200
+++ b/QTfrontend/model/netserverslist.cpp Tue Aug 21 18:35:19 2018 +0200
@@ -45,8 +45,10 @@
case 0:
return tr("Title");
case 1:
+ //: short for "IP address" (Internet Protocol), part of server address
return tr("IP");
case 2:
+ //: short for "port number", part of server address
return tr("Port");
default:
return QVariant();
--- a/QTfrontend/net/newnetclient.cpp Mon Aug 20 22:38:14 2018 +0200
+++ b/QTfrontend/net/newnetclient.cpp Tue Aug 21 18:35:19 2018 +0200
@@ -74,7 +74,7 @@
{
if (m_game_connected)
{
- RawSendNet(QString("QUIT%1%2").arg(delimiter).arg("User quit"));
+ RawSendNet(QString("QUIT%1").arg(delimiter));
emit disconnected(tr("User quit"));
}
NetSocket.flush();
@@ -91,7 +91,7 @@
void HWNewNet::Disconnect()
{
if (m_game_connected)
- RawSendNet(QString("QUIT%1%2").arg(delimiter).arg("User quit"));
+ RawSendNet(QString("QUIT%1").arg(delimiter));
m_game_connected = false;
NetSocket.disconnectFromHost();
@@ -870,7 +870,21 @@
if (lst.size() < 3)
emit chatStringFromNet(tr("%1 *** %2 has left").arg('\x03').arg(lst[1]));
else
- emit chatStringFromNet(tr("%1 *** %2 has left (%3)").arg('\x03').arg(lst[1], lst[2]));
+ {
+ QString leaveMsg = QString(lst[2]);
+ if (leaveMsg.startsWith("User quit: "))
+ {
+ leaveMsg.remove(0, 11);
+ emit chatStringFromNet(tr("%1 *** %2 has left (message: \"%3\")").arg('\x03').arg(lst[1]).arg(leaveMsg));
+ }
+ else if (leaveMsg.startsWith("part: "))
+ {
+ leaveMsg.remove(0, 6);
+ emit chatStringFromNet(tr("%1 *** %2 has left (%3)").arg('\x03').arg(lst[1]).arg(leaveMsg));
+ }
+ else
+ emit chatStringFromNet(tr("%1 *** %2 has left (%3)").arg('\x03').arg(lst[1]).arg(HWApplication::translate("server", leaveMsg.toLatin1().constData())));
+ }
m_playersModel->playerLeftRoom(lst[1]);
return;
}
--- a/QTfrontend/ui/page/pageadmin.cpp Mon Aug 20 22:38:14 2018 +0200
+++ b/QTfrontend/ui/page/pageadmin.cpp Tue Aug 21 18:35:19 2018 +0200
@@ -73,6 +73,7 @@
// 4
QLabel * lblPreview = new QLabel(this);
+ //: MOTD = Message Of The Day, the message which is shown to players joining the server
lblPreview->setText(tr("MOTD preview:"));
tab1Layout->addWidget(lblPreview, 4, 0);
@@ -94,6 +95,7 @@
twBans = new QTableWidget(this);
twBans->setColumnCount(3);
twBans->setHorizontalHeaderLabels(QStringList()
+ //: IP = short for "IP address" (Internet Protocol). Nick = short for "nick name"
<< tr("IP/Nick")
<< tr("Expiration")
<< tr("Reason")
--- a/QTfrontend/ui/page/pageoptions.cpp Mon Aug 20 22:38:14 2018 +0200
+++ b/QTfrontend/ui/page/pageoptions.cpp Tue Aug 21 18:35:19 2018 +0200
@@ -512,6 +512,7 @@
// Dampen
CBDampenAudio = new QCheckBox(groupGame);
+ //: Checkbox text. If checked, the in-game audio volume is reduced (=dampened) when the game window loses its focus
CBDampenAudio->setText(QCheckBox::tr("Dampen when losing focus"));
CBDampenAudio->setWhatsThis(QCheckBox::tr("Reduce the game audio volume if the game window has lost its focus"));
groupGame->layout()->addWidget(CBDampenAudio, 2, 1, 1, 3, Qt::AlignLeft);
--- a/QTfrontend/ui/widget/chatwidget.cpp Mon Aug 20 22:38:14 2018 +0200
+++ b/QTfrontend/ui/widget/chatwidget.cpp Tue Aug 21 18:35:19 2018 +0200
@@ -539,10 +539,28 @@
emit nickCountUpdate(chatNicks->model()->rowCount());
- if (message.isEmpty())
+ // Normal quit
+ if (message.isEmpty() || message == "bye")
printChatString(nick, QString("*** ") + tr("%1 has left").arg(linkedNick(nick)), "Leave", false);
+ // Quit with custom player message
+ else if (message.startsWith("User quit: ") && message.length() > 11)
+ {
+ QString playerMessage = QString(message);
+ playerMessage.remove(0, 11);
+ printChatString(nick, QString("*** ") + tr("%1 has left (message: \"%2\")").arg(linkedNick(nick)).arg(playerMessage.toHtmlEscaped()), "Leave", false);
+ }
+ // Quit with special PART message
+ else if (message.startsWith("part: ") && message.length() > 6)
+ {
+ QString playerMessage = QString(message);
+ playerMessage.remove(0, 6);
+ printChatString(nick, QString("*** ") + tr("%1 has left (%2)").arg(linkedNick(nick).arg(playerMessage.toHtmlEscaped())), "Leave", false);
+ }
+ // Quit with additional server message (i.e. ping timeout)
else
- printChatString(nick, QString("*** ") + tr("%1 has left (%2)").arg(linkedNick(nick)).arg(messageToHTML(message)), "Leave", false);
+ {
+ printChatString(nick, QString("*** ") + tr("%1 has left (%2)").arg(linkedNick(nick)).arg(HWApplication::translate("server", message.toLatin1().constData()).toHtmlEscaped()), "Leave", false);
+ }
}
void HWChatWidget::clear()
--- a/QTfrontend/ui/widget/mapContainer.cpp Mon Aug 20 22:38:14 2018 +0200
+++ b/QTfrontend/ui/widget/mapContainer.cpp Tue Aug 21 18:35:19 2018 +0200
@@ -154,6 +154,7 @@
/* Seed button */
btnSeed = new QPushButton(parentWidget()->parentWidget());
+ //: Refers to the "random seed"; the source of randomness in the game
btnSeed->setText(tr("Seed"));
btnSeed->setWhatsThis(tr("View and edit the seed, the source of randomness in the game"));
btnSeed->setStyleSheet("padding: 5px;");
--- a/QTfrontend/ui/widget/seedprompt.cpp Mon Aug 20 22:38:14 2018 +0200
+++ b/QTfrontend/ui/widget/seedprompt.cpp Tue Aug 21 18:35:19 2018 +0200
@@ -31,6 +31,7 @@
setModal(true);
setWindowFlags(Qt::Sheet);
setWindowModality(Qt::WindowModal);
+ //: Refers to the "random seed"; the source of randomness in the game
setWindowTitle(tr("Seed"));
setMinimumSize(360, 160);
resize(360, 160);
--- a/README.md Mon Aug 20 22:38:14 2018 +0200
+++ b/README.md Tue Aug 21 18:35:19 2018 +0200
@@ -67,7 +67,7 @@
* P: Pause, when playing offline, toggle automatic turn skipping when online
* Esc: Quit with prompt
* T: Chat
-* U: Team chat
+* U: Clan chat
### Default controller controls
Hedgewars also supports controllers. By default, Hedgewars sets up a few
--- a/gameServer/Actions.hs Mon Aug 20 22:38:14 2018 +0200
+++ b/gameServer/Actions.hs Tue Aug 21 18:35:19 2018 +0200
@@ -117,7 +117,7 @@
loggedIn <- client's isVisible
when (ri /= lobbyId) $ do
- processAction $ MoveToLobby ("quit: " `B.append` msg)
+ processAction $ (MoveToLobby msg)
return ()
clientsChans <- liftM (Prelude.map sendChan . Prelude.filter isVisible) $! allClientsS
--- a/gameServer/ClientIO.hs Mon Aug 20 22:38:14 2018 +0200
+++ b/gameServer/ClientIO.hs Tue Aug 21 18:35:19 2018 +0200
@@ -96,6 +96,7 @@
where
killReciever = Exception.throwTo tId . ShutdownThreadException
+ -- intentionally not localized
quitMessage ["BYE"] = "bye"
quitMessage ("BYE":msg:_) = msg
quitMessage _ = error "quitMessage"
--- a/gameServer/HWProtoCore.hs Mon Aug 20 22:38:14 2018 +0200
+++ b/gameServer/HWProtoCore.hs Tue Aug 21 18:35:19 2018 +0200
@@ -40,7 +40,10 @@
handleCmd ("QUIT" : xs) = return [ByeClient msg]
where
- msg = if not $ null xs then "User quit: " `B.append` (head xs) else loc "bye"
+ -- "User quit: " is a special string parsed by frontend, do not localize.
+ -- It denotes when the /quit command has been used with message parameter.
+ -- "bye" is also a special string.
+ msg = if not $ null xs then "User quit: " `B.append` (head xs) else "bye"
handleCmd ["PONG"] = do
--- a/gameServer/HWProtoInRoomState.hs Mon Aug 20 22:38:14 2018 +0200
+++ b/gameServer/HWProtoInRoomState.hs Tue Aug 21 18:35:19 2018 +0200
@@ -74,7 +74,10 @@
s <- roomOthersChans
return [AnswerClients s ["CHAT", n, msg]]
-handleCmd_inRoom ["PART"] = return [MoveToLobby "part"]
+-- Leave room normally
+handleCmd_inRoom ["PART"] = return [MoveToLobby ""]
+-- Leave room with custom quit message by player
+-- "part: " is a special marker string to be detected by the frontend. Not translated for obvious reasons
handleCmd_inRoom ["PART", msg] = return [MoveToLobby $ "part: " `B.append` msg]
--- a/gameServer/HWProtoNEState.hs Mon Aug 20 22:38:14 2018 +0200
+++ b/gameServer/HWProtoNEState.hs Tue Aug 21 18:35:19 2018 +0200
@@ -65,6 +65,7 @@
if clientProto cl < 48 && passwd == webPassword cl then
return $ JoinLobby : [AnswerClients [sendChan cl] ["ADMIN_ACCESS"] | isAdministrator cl]
else
+ -- String is parsed by frontend, do not localize!
return [ByeClient "Authentication failed"]
@@ -81,6 +82,7 @@
, JoinLobby
]
else
+ -- String is parsed by frontend, do not localize!
return [ByeClient "Authentication failed"]
where
h = B.pack . showDigest . sha1 . BL.fromChunks
--- a/gameServer/Utils.hs Mon Aug 20 22:38:14 2018 +0200
+++ b/gameServer/Utils.hs Tue Aug 21 18:35:19 2018 +0200
@@ -233,6 +233,9 @@
AnswerClients [clChan] ["HH_NUM", teamname team, showB $ hhnum team]]
+-- Locale function to localize strings.
+-- loc is just the identity functions, but it will be collected by scripts
+-- for localization. Use loc to mark a string for translation.
loc :: B.ByteString -> B.ByteString
loc = id
--- a/hedgewars/uChat.pas Mon Aug 20 22:38:14 2018 +0200
+++ b/hedgewars/uChat.pas Tue Aug 21 18:35:19 2018 +0200
@@ -35,7 +35,7 @@
procedure TextInput(var event: TSDL_TextInputEvent);
implementation
-uses uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils;
+uses uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils, uLocale;
const MaxStrIndex = 27;
MaxInputStrLen = 200;
@@ -1113,7 +1113,7 @@
if copy(s, 1, 4) = '/me ' then
s:= #2 + '* ' + UserNick + ' ' + copy(s, 5, Length(s) - 4)
else
- s:= #1 + UserNick + ': ' + s;
+ s:= #1 + Format(trmsg[sidChat], [UserNick, s]);
AddChatString(s)
end;
@@ -1122,7 +1122,7 @@
begin
SendIPC('b' + s);
- s:= #4 + '[Team] ' + UserNick + ': ' + s;
+ s:= #4 + Format(trmsg[sidChatTeam], [UserNick, s]);
AddChatString(s)
end;
--- a/hedgewars/uGearsHedgehog.pas Mon Aug 20 22:38:14 2018 +0200
+++ b/hedgewars/uGearsHedgehog.pas Tue Aug 21 18:35:19 2018 +0200
@@ -579,7 +579,7 @@
speech^.Text:= SpeechText;
speech^.Hedgehog:= Gear^.Hedgehog;
speech^.FrameTicks:= SpeechType;
- AddChatString(#9+'[' + Gear^.Hedgehog^.Name + '] '+SpeechText);
+ AddChatString(#9+FormatA(trmsg[sidChatHog], [Gear^.Hedgehog^.Name, SpeechText]));
end;
SpeechText:= ''
end;
--- a/hedgewars/uScript.pas Mon Aug 20 22:38:14 2018 +0200
+++ b/hedgewars/uScript.pas Tue Aug 21 18:35:19 2018 +0200
@@ -86,6 +86,7 @@
uVisualGearsList,
uGearsHandlersMess,
uPhysFSLayer,
+ uLocale,
SDLh
{$IFNDEF PAS2C}
, typinfo
@@ -1628,7 +1629,7 @@
vgear^.Text:= lua_tostring(L, 2);
if Gear^.Kind = gtHedgehog then
begin
- AddChatString(#9+'[' + gear^.Hedgehog^.Name + '] '+vgear^.text);
+ AddChatString(#9+FormatA(trmsg[sidChatHog], [gear^.Hedgehog^.Name, vgear^.text]));
vgear^.Hedgehog:= gear^.Hedgehog
end
else vgear^.Frame:= gear^.uid;
--- a/hedgewars/uTypes.pas Mon Aug 20 22:38:14 2018 +0200
+++ b/hedgewars/uTypes.pas Tue Aug 21 18:35:19 2018 +0200
@@ -481,7 +481,7 @@
sidWinner2, sidWinner3, sidWinner4, sidWinner5, sidWinner6,
sidWinner7, sidWinnerAll, sidTeamGone, sidTeamBack, sidAutoSkip,
sidFPS, sidLuaParsingOff, sidLuaParsingOn, sidLuaParsingDenied,
- sidAmmoCount);
+ sidAmmoCount, sidChat, sidChatTeam, sidChatHog);
TCmdHelpStrId = (
sidCmdHeaderBasic, sidCmdTogglechat, sidCmdTeam, sidCmdMe,
--- a/share/hedgewars/Data/Locale/en.txt Mon Aug 20 22:38:14 2018 +0200
+++ b/share/hedgewars/Data/Locale/en.txt Tue Aug 21 18:35:19 2018 +0200
@@ -110,6 +110,12 @@
01:43=Lua parsing is not allowed in online games!
; Ammo count in ammo menu
01:44=%1×
+; Chat. %1 = player, %2 = message
+01:45=%1: %2
+; Clan chat. %1 = player, %2 = message
+01:46=[Clan] %1: %2
+; Hedgehog chat. %1 = hog name, %2 = message
+01:47=[%1]: %2
; Event messages
; Normal hog (%1) died (0 health)