diff options
Diffstat (limited to 'Swift/Controllers')
-rw-r--r-- | Swift/Controllers/Chat/ChatController.cpp | 27 | ||||
-rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.cpp | 50 | ||||
-rw-r--r-- | Swift/Controllers/Chat/MUCController.cpp | 123 | ||||
-rw-r--r-- | Swift/Controllers/Chat/MUCSearchController.h | 1 | ||||
-rw-r--r-- | Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp | 16 | ||||
-rw-r--r-- | Swift/Controllers/Intl.h | 12 | ||||
-rw-r--r-- | Swift/Controllers/MainController.cpp | 69 | ||||
-rw-r--r-- | Swift/Controllers/PresenceNotifier.cpp | 3 | ||||
-rw-r--r-- | Swift/Controllers/Roster/RosterController.cpp | 10 | ||||
-rw-r--r-- | Swift/Controllers/SConscript | 2 | ||||
-rw-r--r-- | Swift/Controllers/StatusUtil.cpp | 25 | ||||
-rw-r--r-- | Swift/Controllers/StatusUtil.h | 16 | ||||
-rw-r--r-- | Swift/Controllers/Translator.cpp | 28 | ||||
-rw-r--r-- | Swift/Controllers/Translator.h | 27 |
14 files changed, 291 insertions, 118 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index e4ad9c8..6e7825f 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -9,6 +9,8 @@ #include <boost/bind.hpp> #include <stdio.h> +#include <Swift/Controllers/Intl.h> +#include <Swiften/Base/format.h> #include "Swiften/Avatars/AvatarManager.h" #include "Swiften/Chat/ChatStateNotifier.h" #include "Swiften/Chat/ChatStateTracker.h" @@ -18,6 +20,7 @@ #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h" #include "Swiften/Client/NickResolver.h" #include "Swift/Controllers/XMPPEvents/EventController.h" +#include <Swift/Controllers/StatusUtil.h> namespace Swift { @@ -37,16 +40,16 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ nickResolver_->onNickChanged.connect(boost::bind(&ChatController::handleContactNickChanged, this, _1, _2)); std::string nick = nickResolver_->jidToNick(toJID_); chatWindow_->setName(nick); - std::string startMessage("Starting chat with " + nick); + std::string startMessage; Presence::ref theirPresence; if (isInMUC) { - startMessage += " in chatroom " + contact.toBare().toString(); + startMessage = str(format(QT_TRANSLATE_NOOP("", "Starting chat with %1% in chatroom %2%")) % nick % contact.toBare().toString()); theirPresence = presenceOracle->getLastPresence(contact); } else { - startMessage += " - " + contact.toBare().toString(); + startMessage = str(format(QT_TRANSLATE_NOOP("", "Starting chat with %1% - %2%")) % nick % contact.toBare().toString()); theirPresence = contact.isBare() ? presenceOracle->getHighestPriorityPresence(contact.toBare()) : presenceOracle->getLastPresence(contact); } - startMessage += ": " + StatusShow::typeToFriendlyName(theirPresence ? theirPresence->getShow() : StatusShow::None); + startMessage += ": " + statusShowTypeToFriendlyName(theirPresence ? theirPresence->getShow() : StatusShow::None); if (theirPresence && !theirPresence->getStatus().empty()) { startMessage += " (" + theirPresence->getStatus() + ")"; } @@ -109,7 +112,7 @@ void ChatController::preSendMessageRequest(boost::shared_ptr<Message> message) { } void ChatController::postSendMessage(const std::string& body, boost::shared_ptr<Stanza> sentStanza) { - std::string id = addMessage(body, "me", true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel() : boost::optional<SecurityLabel>(), std::string(avatarManager_->getAvatarPath(selfJID_).string()), boost::posix_time::microsec_clock::universal_time()); + std::string id = addMessage(body, QT_TRANSLATE_NOOP("", "me"), true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel() : boost::optional<SecurityLabel>(), std::string(avatarManager_->getAvatarPath(selfJID_).string()), boost::posix_time::microsec_clock::universal_time()); if (stanzaChannel_->getStreamManagementEnabled()) { chatWindow_->setAckState(id, ChatWindow::Pending); unackedStanzas_[sentStanza] = id; @@ -148,19 +151,23 @@ std::string ChatController::senderDisplayNameFromMessage(const JID& from) { std::string ChatController::getStatusChangeString(boost::shared_ptr<Presence> presence) { std::string nick = senderDisplayNameFromMessage(presence->getFrom()); - std::string response = nick; + std::string response; if (!presence || presence->getType() == Presence::Unavailable || presence->getType() == Presence::Error) { - response += " has gone offline"; + response = QT_TRANSLATE_NOOP("", "%1% has gone offline"); } else if (presence->getType() == Presence::Available) { StatusShow::Type show = presence->getShow(); if (show == StatusShow::Online || show == StatusShow::FFC) { - response += " has become available"; + response = QT_TRANSLATE_NOOP("", "%1% has become available"); } else if (show == StatusShow::Away || show == StatusShow::XA) { - response += " has gone away"; + response = QT_TRANSLATE_NOOP("", "%1% has gone away"); } else if (show == StatusShow::DND) { - response += " is now busy"; + response = QT_TRANSLATE_NOOP("", "%1% is now busy"); } } + if (!response.empty()) { + response = str(format(response) % nick); + } + if (!presence->getStatus().empty()) { response += " (" + presence->getStatus() + ")"; } diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index f70ec81..a970d88 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -13,6 +13,8 @@ #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/algorithm/string.hpp> +#include <Swift/Controllers/Intl.h> +#include <Swiften/Base/format.h> #include "Swiften/Base/String.h" #include "Swiften/Client/StanzaChannel.h" #include "Swiften/Elements/Delay.h" @@ -51,7 +53,7 @@ void ChatControllerBase::createDayChangeTimer() { void ChatControllerBase::handleDayChangeTick() { dateChangeTimer_->stop(); boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); - chatWindow_->addSystemMessage("The day is now " + std::string(boost::posix_time::to_iso_extended_string(now)).substr(0,10)); + chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "The day is now %1%")) % std::string(boost::posix_time::to_iso_extended_string(now)).substr(0,10))); dayTicked(); createDayChangeTimer(); } @@ -188,34 +190,34 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m } std::string ChatControllerBase::getErrorMessage(boost::shared_ptr<ErrorPayload> error) { - std::string defaultMessage = "Error sending message"; + std::string defaultMessage = QT_TRANSLATE_NOOP("", "Error sending message"); if (!error->getText().empty()) { return error->getText(); } else { switch (error->getCondition()) { - case ErrorPayload::BadRequest: return "Bad request"; break; - case ErrorPayload::Conflict: return "Conflict"; break; - case ErrorPayload::FeatureNotImplemented: return "This feature is not implemented"; break; - case ErrorPayload::Forbidden: return "Forbidden"; break; - case ErrorPayload::Gone: return "Recipient can no longer be contacted"; break; - case ErrorPayload::InternalServerError: return "Internal server error"; break; - case ErrorPayload::ItemNotFound: return "Item not found"; break; - case ErrorPayload::JIDMalformed: return "JID Malformed"; break; - case ErrorPayload::NotAcceptable: return "Message was rejected"; break; - case ErrorPayload::NotAllowed: return "Not allowed"; break; - case ErrorPayload::NotAuthorized: return "Not authorized"; break; - case ErrorPayload::PaymentRequired: return "Payment is required"; break; - case ErrorPayload::RecipientUnavailable: return "Recipient is unavailable."; break; - case ErrorPayload::Redirect: return "Redirect"; break; - case ErrorPayload::RegistrationRequired: return "Registration required"; break; - case ErrorPayload::RemoteServerNotFound: return "Recipient's server not found."; break; - case ErrorPayload::RemoteServerTimeout: return "Remote server timeout"; break; - case ErrorPayload::ResourceConstraint: return "The server is low on resources"; break; - case ErrorPayload::ServiceUnavailable: return "The service is unavailable"; break; - case ErrorPayload::SubscriptionRequired: return "A subscription is required"; break; - case ErrorPayload::UndefinedCondition: return "Undefined condition"; break; - case ErrorPayload::UnexpectedRequest: return "Unexpected request"; break; + case ErrorPayload::BadRequest: return QT_TRANSLATE_NOOP("", "Bad request"); break; + case ErrorPayload::Conflict: return QT_TRANSLATE_NOOP("", "Conflict"); break; + case ErrorPayload::FeatureNotImplemented: return QT_TRANSLATE_NOOP("", "This feature is not implemented"); break; + case ErrorPayload::Forbidden: return QT_TRANSLATE_NOOP("", "Forbidden"); break; + case ErrorPayload::Gone: return QT_TRANSLATE_NOOP("", "Recipient can no longer be contacted"); break; + case ErrorPayload::InternalServerError: return QT_TRANSLATE_NOOP("", "Internal server error"); break; + case ErrorPayload::ItemNotFound: return QT_TRANSLATE_NOOP("", "Item not found"); break; + case ErrorPayload::JIDMalformed: return QT_TRANSLATE_NOOP("", "JID Malformed"); break; + case ErrorPayload::NotAcceptable: return QT_TRANSLATE_NOOP("", "Message was rejected"); break; + case ErrorPayload::NotAllowed: return QT_TRANSLATE_NOOP("", "Not allowed"); break; + case ErrorPayload::NotAuthorized: return QT_TRANSLATE_NOOP("", "Not authorized"); break; + case ErrorPayload::PaymentRequired: return QT_TRANSLATE_NOOP("", "Payment is required"); break; + case ErrorPayload::RecipientUnavailable: return QT_TRANSLATE_NOOP("", "Recipient is unavailable"); break; + case ErrorPayload::Redirect: return QT_TRANSLATE_NOOP("", "Redirect"); break; + case ErrorPayload::RegistrationRequired: return QT_TRANSLATE_NOOP("", "Registration required"); break; + case ErrorPayload::RemoteServerNotFound: return QT_TRANSLATE_NOOP("", "Recipient's server not found"); break; + case ErrorPayload::RemoteServerTimeout: return QT_TRANSLATE_NOOP("", "Remote server timeout"); break; + case ErrorPayload::ResourceConstraint: return QT_TRANSLATE_NOOP("", "The server is low on resources"); break; + case ErrorPayload::ServiceUnavailable: return QT_TRANSLATE_NOOP("", "The service is unavailable"); break; + case ErrorPayload::SubscriptionRequired: return QT_TRANSLATE_NOOP("", "A subscription is required"); break; + case ErrorPayload::UndefinedCondition: return QT_TRANSLATE_NOOP("", "Undefined condition"); break; + case ErrorPayload::UnexpectedRequest: return QT_TRANSLATE_NOOP("", "Unexpected request"); break; } } return defaultMessage; diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index 765c49d..ce8c946 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -10,6 +10,8 @@ #include <boost/regex.hpp> #include <boost/algorithm/string.hpp> +#include <Swift/Controllers/Intl.h> +#include <Swiften/Base/format.h> #include "Swiften/Network/Timer.h" #include "Swiften/Network/TimerFactory.h" #include "Swiften/Base/foreach.h" @@ -109,7 +111,7 @@ void MUCController::rejoin() { void MUCController::handleJoinTimeoutTick() { receivedActivity(); - chatWindow_->addSystemMessage("Room " + toJID_.toString() + " is not responding. This operation may never complete"); + chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "Room %1% is not responding. This operation may never complete.")) % toJID_.toString())); } void MUCController::receivedActivity() { @@ -120,17 +122,38 @@ void MUCController::receivedActivity() { void MUCController::handleJoinFailed(boost::shared_ptr<ErrorPayload> error) { receivedActivity(); - std::string errorMessage = "Unable to join this room"; + std::string errorMessage = QT_TRANSLATE_NOOP("", "Unable to join this room"); std::string rejoinNick; if (error) { switch (error->getCondition()) { - case ErrorPayload::Conflict: rejoinNick = nick_ + "_"; errorMessage += " as " + nick_ + ", retrying as " + rejoinNick; break; - case ErrorPayload::JIDMalformed: errorMessage += ", no nickname specified";break; - case ErrorPayload::NotAuthorized: errorMessage += ", a password needed";break; - case ErrorPayload::RegistrationRequired: errorMessage += ", only members may join"; break; - case ErrorPayload::Forbidden: errorMessage += ", you are banned from the room"; break; - case ErrorPayload::ServiceUnavailable: errorMessage += ", the room is full";break; - case ErrorPayload::ItemNotFound: errorMessage += ", the room does not exist";break; + case ErrorPayload::Conflict: + rejoinNick = nick_ + "_"; + errorMessage = str(format(QT_TRANSLATE_NOOP("", "Unable to join this room as %1%, retrying as %2%")) % nick_ % rejoinNick); + break; + case ErrorPayload::JIDMalformed: + errorMessage += ": "; + errorMessage += QT_TRANSLATE_NOOP("", "No nickname specified"); + break; + case ErrorPayload::NotAuthorized: + errorMessage += ": "; + errorMessage += QT_TRANSLATE_NOOP("", "A password needed"); + break; + case ErrorPayload::RegistrationRequired: + errorMessage += ": "; + errorMessage += QT_TRANSLATE_NOOP("", "Only members may join"); + break; + case ErrorPayload::Forbidden: + errorMessage += ": "; + errorMessage += QT_TRANSLATE_NOOP("", "You are banned from the room"); + break; + case ErrorPayload::ServiceUnavailable: + errorMessage += ": "; + errorMessage += QT_TRANSLATE_NOOP("", "The room is full"); + break; + case ErrorPayload::ItemNotFound: + errorMessage += ": "; + errorMessage += QT_TRANSLATE_NOOP("", "The room does not exist"); + break; default: break; } @@ -147,7 +170,7 @@ void MUCController::handleJoinFailed(boost::shared_ptr<ErrorPayload> error) { void MUCController::handleJoinComplete(const std::string& nick) { receivedActivity(); joined_ = true; - std::string joinMessage = "You have joined room " + toJID_.toString() + " as " + nick; + std::string joinMessage = str(format(QT_TRANSLATE_NOOP("", "You have joined room %1% as %2%")) % toJID_.toString() % nick); nick_ = nick; chatWindow_->addSystemMessage(joinMessage); clearPresenceQueue(); @@ -185,13 +208,14 @@ void MUCController::handleOccupantJoined(const MUCOccupant& occupant) { appendToJoinParts(joinParts_, event); roster_->addContact(jid, realJID, occupant.getNick(), roleToGroupName(occupant.getRole()), avatarManager_->getAvatarPath(jid).string()); if (joined_) { - std::string joinString = occupant.getNick() + " has joined the room"; + std::string joinString; MUCOccupant::Role role = occupant.getRole(); if (role != MUCOccupant::NoRole && role != MUCOccupant::Participant) { - joinString += " as a " + roleToFriendlyName(role); - + joinString = str(format(QT_TRANSLATE_NOOP("", "%1% has joined the room as a %2%.")) % occupant.getNick() % roleToFriendlyName(role)); + } + else { + joinString = str(format(QT_TRANSLATE_NOOP("", "%1% has joined the room.")) % occupant.getNick()); } - joinString += "."; if (shouldUpdateJoinParts()) { updateJoinParts(); } else { @@ -216,9 +240,9 @@ void MUCController::clearPresenceQueue() { std::string MUCController::roleToFriendlyName(MUCOccupant::Role role) { switch (role) { - case MUCOccupant::Moderator: return "moderator"; - case MUCOccupant::Participant: return "participant"; - case MUCOccupant::Visitor: return "visitor"; + case MUCOccupant::Moderator: return QT_TRANSLATE_NOOP("", "moderator"); + case MUCOccupant::Participant: return QT_TRANSLATE_NOOP("", "participant"); + case MUCOccupant::Visitor: return QT_TRANSLATE_NOOP("", "visitor"); case MUCOccupant::NoRole: return ""; } return ""; @@ -257,7 +281,7 @@ void MUCController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> mes joined_ = true; if (!message->getSubject().empty() && message->getBody().empty()) { - chatWindow_->addSystemMessage("The room subject is now: " + message->getSubject()); + chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "The room subject is now: %1%")) % message->getSubject()));; doneGettingHistory_ = true; } @@ -280,16 +304,16 @@ void MUCController::handleOccupantRoleChanged(const std::string& nick, const MUC realJID = occupant.getRealJID().get(); } roster_->addContact(jid, realJID, nick, roleToGroupName(occupant.getRole()), avatarManager_->getAvatarPath(jid).string()); - chatWindow_->addSystemMessage(nick + " is now a " + roleToFriendlyName(occupant.getRole())); + chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "%1% is now a %2%")) % nick % roleToFriendlyName(occupant.getRole()))); } std::string MUCController::roleToGroupName(MUCOccupant::Role role) { std::string result; switch (role) { - case MUCOccupant::Moderator: result = "Moderators"; break; - case MUCOccupant::Participant: result = "Participants"; break; - case MUCOccupant::Visitor: result = "Visitors"; break; - case MUCOccupant::NoRole: result = "Occupants"; break; + case MUCOccupant::Moderator: result = QT_TRANSLATE_NOOP("", "Moderators"); break; + case MUCOccupant::Participant: result = QT_TRANSLATE_NOOP("", "Participants"); break; + case MUCOccupant::Visitor: result = QT_TRANSLATE_NOOP("", "Visitors"); break; + case MUCOccupant::NoRole: result = QT_TRANSLATE_NOOP("", "Occupants"); break; default: assert(false); } return result; @@ -303,7 +327,7 @@ void MUCController::setOnline(bool online) { processUserPart(); } else { if (shouldJoinOnReconnect_) { - chatWindow_->addSystemMessage("Trying to join room " + toJID_.toString()); + chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "Trying to join room %1%")) % toJID_.toString())); if (loginCheckTimer_) { loginCheckTimer_->start(); } @@ -332,7 +356,7 @@ void MUCController::handleOccupantLeft(const MUCOccupant& occupant, MUC::Leaving appendToJoinParts(joinParts_, event); currentOccupants_.erase(occupant.getNick()); completer_->removeWord(occupant.getNick()); - std::string partMessage = (occupant.getNick() != nick_) ? occupant.getNick() + " has left the room" : "You have left the room"; + std::string partMessage = (occupant.getNick() != nick_) ? str(format(QT_TRANSLATE_NOOP("", "%1% has left the room")) % occupant.getNick()) : QT_TRANSLATE_NOOP("", "You have left the room"); if (!reason.empty()) { partMessage += " (" + reason + ")"; } @@ -406,7 +430,7 @@ std::string MUCController::concatenateListOfNames(const std::vector<NickJoinPart if (i < joinParts.size() - 1) { result += ", "; } else { - result += " and "; + result += QT_TRANSLATE_NOOP("", " and "); } } NickJoinPart event = joinParts[i]; @@ -424,17 +448,45 @@ std::string MUCController::generateJoinPartString(const std::vector<NickJoinPart std::string result; std::vector<JoinPart> populatedEvents; for (size_t i = 0; i < 4; i++) { - std::string eventString = concatenateListOfNames(sorted[i]); - if (!eventString.empty()) { - std::string haveHas = sorted[i].size() > 1 ? " have" : " has"; + std::string names = concatenateListOfNames(sorted[i]); + if (!names.empty()) { + std::string eventString; switch (i) { - case Join: eventString += haveHas + " joined";break; - case Part: eventString += haveHas + " left";break; - case JoinThenPart: eventString += " joined then left";break; - case PartThenJoin: eventString += " left then rejoined";break; + case Join: + if (sorted[i].size() > 1) { + eventString = QT_TRANSLATE_NOOP("", "%1% have joined the room"); + } + else { + eventString = QT_TRANSLATE_NOOP("", "%1% has joined the room"); + } + break; + case Part: + if (sorted[i].size() > 1) { + eventString = QT_TRANSLATE_NOOP("", "%1% have left the room"); + } + else { + eventString = QT_TRANSLATE_NOOP("", "%1% has left the room"); + } + break; + case JoinThenPart: + if (sorted[i].size() > 1) { + eventString = QT_TRANSLATE_NOOP("", "%1% have joined then left the room"); + } + else { + eventString = QT_TRANSLATE_NOOP("", "%1% has joined then left the room"); + } + break; + case PartThenJoin: + if (sorted[i].size() > 1) { + eventString = QT_TRANSLATE_NOOP("", "%1% have left then rejoined the room"); + } + else { + eventString = QT_TRANSLATE_NOOP("", "%1% has left then rejoined the room"); + } + break; } populatedEvents.push_back(static_cast<JoinPart>(i)); - eventStrings[i] = eventString; + eventStrings[i] = str(boost::format(eventString) % names); } } for (size_t i = 0; i < populatedEvents.size(); i++) { @@ -442,12 +494,11 @@ std::string MUCController::generateJoinPartString(const std::vector<NickJoinPart if (i < populatedEvents.size() - 1) { result += ", "; } else { - result += " and "; + result += QT_TRANSLATE_NOOP("", " and "); } } result += eventStrings[populatedEvents[i]]; } - result += " the room."; return result; } diff --git a/Swift/Controllers/Chat/MUCSearchController.h b/Swift/Controllers/Chat/MUCSearchController.h index b348886..c8040ed 100644 --- a/Swift/Controllers/Chat/MUCSearchController.h +++ b/Swift/Controllers/Chat/MUCSearchController.h @@ -16,7 +16,6 @@ #include "Swiften/JID/JID.h" #include "Swift/Controllers/UIEvents/UIEvent.h" -#include "Swift/Controllers/Chat/MUCSearchController.h" #include "Swift/Controllers/Settings/SettingsProvider.h" #include "Swiften/Elements/DiscoInfo.h" #include "Swiften/Elements/DiscoItems.h" diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp index 7c7a8b9..e66fa9e 100644 --- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp @@ -200,25 +200,25 @@ public: void testJoinPartStringContructionSimple() { std::vector<NickJoinPart> list; list.push_back(NickJoinPart("Kev", Join)); - CPPUNIT_ASSERT_EQUAL(std::string("Kev has joined the room."), MUCController::generateJoinPartString(list)); + CPPUNIT_ASSERT_EQUAL(std::string("Kev has joined the room"), MUCController::generateJoinPartString(list)); list.push_back(NickJoinPart("Remko", Part)); - CPPUNIT_ASSERT_EQUAL(std::string("Kev has joined and Remko has left the room."), MUCController::generateJoinPartString(list)); + CPPUNIT_ASSERT_EQUAL(std::string("Kev has joined the room and Remko has left the room"), MUCController::generateJoinPartString(list)); list.push_back(NickJoinPart("Bert", Join)); - CPPUNIT_ASSERT_EQUAL(std::string("Kev and Bert have joined and Remko has left the room."), MUCController::generateJoinPartString(list)); + CPPUNIT_ASSERT_EQUAL(std::string("Kev and Bert have joined the room and Remko has left the room"), MUCController::generateJoinPartString(list)); list.push_back(NickJoinPart("Ernie", Join)); - CPPUNIT_ASSERT_EQUAL(std::string("Kev, Bert and Ernie have joined and Remko has left the room."), MUCController::generateJoinPartString(list)); + CPPUNIT_ASSERT_EQUAL(std::string("Kev, Bert and Ernie have joined the room and Remko has left the room"), MUCController::generateJoinPartString(list)); } void testJoinPartStringContructionMixed() { std::vector<NickJoinPart> list; list.push_back(NickJoinPart("Kev", JoinThenPart)); - CPPUNIT_ASSERT_EQUAL(std::string("Kev joined then left the room."), MUCController::generateJoinPartString(list)); + CPPUNIT_ASSERT_EQUAL(std::string("Kev has joined then left the room"), MUCController::generateJoinPartString(list)); list.push_back(NickJoinPart("Remko", Part)); - CPPUNIT_ASSERT_EQUAL(std::string("Remko has left and Kev joined then left the room."), MUCController::generateJoinPartString(list)); + CPPUNIT_ASSERT_EQUAL(std::string("Remko has left the room and Kev has joined then left the room"), MUCController::generateJoinPartString(list)); list.push_back(NickJoinPart("Bert", PartThenJoin)); - CPPUNIT_ASSERT_EQUAL(std::string("Remko has left, Kev joined then left and Bert left then rejoined the room."), MUCController::generateJoinPartString(list)); + CPPUNIT_ASSERT_EQUAL(std::string("Remko has left the room, Kev has joined then left the room and Bert has left then rejoined the room"), MUCController::generateJoinPartString(list)); list.push_back(NickJoinPart("Ernie", JoinThenPart)); - CPPUNIT_ASSERT_EQUAL(std::string("Remko has left, Kev and Ernie joined then left and Bert left then rejoined the room."), MUCController::generateJoinPartString(list)); + CPPUNIT_ASSERT_EQUAL(std::string("Remko has left the room, Kev and Ernie have joined then left the room and Bert has left then rejoined the room"), MUCController::generateJoinPartString(list)); } private: diff --git a/Swift/Controllers/Intl.h b/Swift/Controllers/Intl.h new file mode 100644 index 0000000..3ed664d --- /dev/null +++ b/Swift/Controllers/Intl.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swift/Controllers/Translator.h> + +#define QT_TRANSLATE_NOOP(context, text) \ + Swift::Translator::getInstance()->translate(text, context) diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 1257845..6263636 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -10,8 +10,11 @@ #include <boost/lexical_cast.hpp> #include <boost/shared_ptr.hpp> #include <boost/smart_ptr/make_shared.hpp> +#include <string> #include <stdlib.h> +#include <Swiften/Base/format.h> +#include <Swift/Controllers/Intl.h> #include <Swift/Controllers/UIInterfaces/UIFactory.h> #include "Swiften/Network/TimerFactory.h" #include "Swift/Controllers/BuildVersion.h" @@ -41,7 +44,6 @@ #include "SwifTools/Dock/Dock.h" #include "SwifTools/Notifier/TogglableNotifier.h" #include "Swiften/Base/foreach.h" -#include <string> #include "Swiften/Client/Client.h" #include "Swiften/Presence/PresenceSender.h" #include "Swiften/Elements/ChatState.h" @@ -432,36 +434,35 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro std::string message; std::string certificateErrorMessage; switch(error->getType()) { - case ClientError::UnknownError: message = "Unknown Error"; break; - case ClientError::DomainNameResolveError: message = "Unable to find server"; break; - case ClientError::ConnectionError: message = "Error connecting to server"; break; - case ClientError::ConnectionReadError: message = "Error while receiving server data"; break; - case ClientError::ConnectionWriteError: message = "Error while sending data to the server"; break; - case ClientError::XMLError: message = "Error parsing server data"; break; - case ClientError::AuthenticationFailedError: message = "Login/password invalid"; break; - case ClientError::CompressionFailedError: message = "Error while compressing stream"; break; - case ClientError::ServerVerificationFailedError: message = "Server verification failed"; break; - case ClientError::NoSupportedAuthMechanismsError: message = "Authentication mechanisms not supported"; break; - case ClientError::UnexpectedElementError: message = "Unexpected response"; break; - case ClientError::ResourceBindError: message = "Error binding resource"; break; - case ClientError::SessionStartError: message = "Error starting session"; break; - case ClientError::StreamError: message = "Stream error"; break; - case ClientError::TLSError: message = "Encryption error"; break; - case ClientError::ClientCertificateLoadError: message = "Error loading certificate (Invalid password?)"; break; - case ClientError::ClientCertificateError: message = "Certificate not authorized"; break; - - case ClientError::UnknownCertificateError: certificateErrorMessage = "Unknown certificate"; break; - case ClientError::CertificateExpiredError: certificateErrorMessage = "Certificate has expired"; break; - case ClientError::CertificateNotYetValidError: certificateErrorMessage = "Certificate is not yet valid"; break; - case ClientError::CertificateSelfSignedError: certificateErrorMessage = "Certificate is self-signed"; break; - case ClientError::CertificateRejectedError: certificateErrorMessage = "Certificate has been rejected"; break; - case ClientError::CertificateUntrustedError: certificateErrorMessage = "Certificate is not trusted"; break; - case ClientError::InvalidCertificatePurposeError: certificateErrorMessage = "Certificate cannot be used for encryptig your connection"; break; - case ClientError::CertificatePathLengthExceededError: certificateErrorMessage = "Certificate path length constraint exceeded"; break; - case ClientError::InvalidCertificateSignatureError: certificateErrorMessage = "Invalid certificate signature"; break; - case ClientError::InvalidCAError: certificateErrorMessage = "Invalid Certificate Authority"; break; - case ClientError::InvalidServerIdentityError: certificateErrorMessage = "Certificate does not match the host identity"; break; - + case ClientError::UnknownError: message = QT_TRANSLATE_NOOP("", "Unknown Error"); break; + case ClientError::DomainNameResolveError: message = QT_TRANSLATE_NOOP("", "Unable to find server"); break; + case ClientError::ConnectionError: message = QT_TRANSLATE_NOOP("", "Error connecting to server"); break; + case ClientError::ConnectionReadError: message = QT_TRANSLATE_NOOP("", "Error while receiving server data"); break; + case ClientError::ConnectionWriteError: message = QT_TRANSLATE_NOOP("", "Error while sending data to the server"); break; + case ClientError::XMLError: message = QT_TRANSLATE_NOOP("", "Error parsing server data"); break; + case ClientError::AuthenticationFailedError: message = QT_TRANSLATE_NOOP("", "Login/password invalid"); break; + case ClientError::CompressionFailedError: message = QT_TRANSLATE_NOOP("", "Error while compressing stream"); break; + case ClientError::ServerVerificationFailedError: message = QT_TRANSLATE_NOOP("", "Server verification failed"); break; + case ClientError::NoSupportedAuthMechanismsError: message = QT_TRANSLATE_NOOP("", "Authentication mechanisms not supported"); break; + case ClientError::UnexpectedElementError: message = QT_TRANSLATE_NOOP("", "Unexpected response"); break; + case ClientError::ResourceBindError: message = QT_TRANSLATE_NOOP("", "Error binding resource"); break; + case ClientError::SessionStartError: message = QT_TRANSLATE_NOOP("", "Error starting session"); break; + case ClientError::StreamError: message = QT_TRANSLATE_NOOP("", "Stream error"); break; + case ClientError::TLSError: message = QT_TRANSLATE_NOOP("", "Encryption error"); break; + case ClientError::ClientCertificateLoadError: message = QT_TRANSLATE_NOOP("", "Error loading certificate (Invalid password?)"); break; + case ClientError::ClientCertificateError: message = QT_TRANSLATE_NOOP("", "Certificate not authorized"); break; + + case ClientError::UnknownCertificateError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Unknown certificate"); break; + case ClientError::CertificateExpiredError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate has expired"); break; + case ClientError::CertificateNotYetValidError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate is not yet valid"); break; + case ClientError::CertificateSelfSignedError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate is self-signed"); break; + case ClientError::CertificateRejectedError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate has been rejected"); break; + case ClientError::CertificateUntrustedError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate is not trusted"); break; + case ClientError::InvalidCertificatePurposeError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate cannot be used for encryptig your connection"); break; + case ClientError::CertificatePathLengthExceededError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate path length constraint exceeded"); break; + case ClientError::InvalidCertificateSignatureError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Invalid certificate signature"); break; + case ClientError::InvalidCAError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Invalid Certificate Authority"); break; + case ClientError::InvalidServerIdentityError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate does not match the host identity"); break; } bool forceReconnectAfterCertificateTrust = false; if (!certificateErrorMessage.empty()) { @@ -471,7 +472,7 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro forceReconnectAfterCertificateTrust = true; } else { - message = "Certificate error"; + message = QT_TRANSLATE_NOOP("", "Certificate error"); } } @@ -485,10 +486,10 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro logout(); setReconnectTimer(); if (lastDisconnectError_) { - message = "Reconnect to " + jid_.getDomain() + " failed: " + message + ". Will retry in " + boost::lexical_cast<std::string>(timeBeforeNextReconnect_) + " seconds."; + message = str(format(QT_TRANSLATE_NOOP("", "Reconnect to %1% failed: %2%. Will retry in %3% seconds.")) % jid_.getDomain() % message % boost::lexical_cast<std::string>(timeBeforeNextReconnect_)); lastDisconnectError_->conclude(); } else { - message = "Disconnected from " + jid_.getDomain() + ": " + message; + message = str(format(QT_TRANSLATE_NOOP("", "Disconnected from %1%: %2%.")) % jid_.getDomain() % message); } lastDisconnectError_ = boost::shared_ptr<ErrorEvent>(new ErrorEvent(JID(jid_.getDomain()), message)); eventController_->handleIncomingEvent(lastDisconnectError_); diff --git a/Swift/Controllers/PresenceNotifier.cpp b/Swift/Controllers/PresenceNotifier.cpp index 3d5d71e..e7b25bf 100644 --- a/Swift/Controllers/PresenceNotifier.cpp +++ b/Swift/Controllers/PresenceNotifier.cpp @@ -15,6 +15,7 @@ #include "Swiften/Presence/PresenceOracle.h" #include "Swiften/Network/TimerFactory.h" #include "Swiften/Client/NickResolver.h" +#include <Swift/Controllers/StatusUtil.h> namespace Swift { @@ -98,7 +99,7 @@ void PresenceNotifier::handleNotificationActivated(JID jid) { std::string PresenceNotifier::getStatusType(const JID& jid) const { Presence::ref presence = presenceOracle->getLastPresence(jid); if (presence) { - return StatusShow::typeToFriendlyName(presence->getShow()); + return statusShowTypeToFriendlyName(presence->getShow()); } else { return "Unavailable"; diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp index e03a8d4..8a0fd53 100644 --- a/Swift/Controllers/Roster/RosterController.cpp +++ b/Swift/Controllers/Roster/RosterController.cpp @@ -37,6 +37,8 @@ #include "Swift/Controllers/UIEvents/RenameGroupUIEvent.h" #include "Swift/Controllers/UIEvents/ToggleShowOfflineUIEvent.h" #include <Swiften/Client/NickManager.h> +#include <Swift/Controllers/Intl.h> +#include <Swiften/Base/format.h> namespace Swift { @@ -121,7 +123,7 @@ void RosterController::handleOnJIDAdded(const JID& jid) { } } else { - roster_->addContact(jid, jid, name, "Contacts", avatarManager_->getAvatarPath(jid).string()); + roster_->addContact(jid, jid, name, QT_TRANSLATE_NOOP("", "Contacts"), avatarManager_->getAvatarPath(jid).string()); } applyAllPresenceTo(jid); } @@ -147,7 +149,7 @@ void RosterController::handleOnJIDUpdated(const JID& jid, const std::string& old std::vector<std::string> groups = xmppRoster_->getGroupsForJID(jid); std::vector<std::string> oldGroups = passedOldGroups; std::string name = nickResolver_->jidToNick(jid); - std::string contactsGroup = "Contacts"; + std::string contactsGroup = QT_TRANSLATE_NOOP("", "Contacts"); if (oldGroups.empty()) { oldGroups.push_back(contactsGroup); } @@ -208,7 +210,7 @@ void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) { std::vector<XMPPRosterItem> items = xmppRoster_->getItems(); std::string group = renameGroupEvent->getGroup(); // FIXME: We should handle contacts groups specially to avoid clashes - if (group == "Contacts") { + if (group == QT_TRANSLATE_NOOP("", "Contacts")) { group = ""; } foreach(XMPPRosterItem& item, items) { @@ -245,7 +247,7 @@ void RosterController::handleRosterSetError(ErrorPayload::ref error, boost::shar if (!error) { return; } - std::string text = "Server " + myJID_.getDomain() + " rejected roster change to item '" + rosterPayload->getItems()[0].getJID().toString() + "'"; + std::string text = str(format(QT_TRANSLATE_NOOP("", "Server %1% rejected roster change to item '%2%'")) % myJID_.getDomain() % rosterPayload->getItems()[0].getJID().toString()); if (!error->getText().empty()) { text += ": " + error->getText(); } diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript index c563c7b..61da9fb 100644 --- a/Swift/Controllers/SConscript +++ b/Swift/Controllers/SConscript @@ -52,6 +52,8 @@ if env["SCONS_STAGE"] == "build" : "CertificateStorageFactory.cpp", "CertificateStorage.cpp", "CertificateFileStorage.cpp", + "StatusUtil.cpp", + "Translator.cpp", ]) env.Append(UNITTEST_SOURCES = [ diff --git a/Swift/Controllers/StatusUtil.cpp b/Swift/Controllers/StatusUtil.cpp new file mode 100644 index 0000000..fd1fea3 --- /dev/null +++ b/Swift/Controllers/StatusUtil.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swift/Controllers/StatusUtil.h> + +#include <Swift/Controllers/Intl.h> + +namespace Swift { + +std::string statusShowTypeToFriendlyName(StatusShow::Type type) { + switch (type) { + case StatusShow::Online: return QT_TRANSLATE_NOOP("", "Available"); + case StatusShow::FFC: return QT_TRANSLATE_NOOP("", "Available"); + case StatusShow::Away: return QT_TRANSLATE_NOOP("", "Away"); + case StatusShow::XA: return QT_TRANSLATE_NOOP("", "Away"); + case StatusShow::DND: return QT_TRANSLATE_NOOP("", "Busy"); + case StatusShow::None: return QT_TRANSLATE_NOOP("", "Offline"); + } + return ""; +} + +} diff --git a/Swift/Controllers/StatusUtil.h b/Swift/Controllers/StatusUtil.h new file mode 100644 index 0000000..dddee92 --- /dev/null +++ b/Swift/Controllers/StatusUtil.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <string> + +#include <Swiften/Elements/StatusShow.h> + +namespace Swift { + std::string statusShowTypeToFriendlyName(StatusShow::Type type); +} + diff --git a/Swift/Controllers/Translator.cpp b/Swift/Controllers/Translator.cpp new file mode 100644 index 0000000..82fc46e --- /dev/null +++ b/Swift/Controllers/Translator.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swift/Controllers/Translator.h> + +#include <cassert> + +namespace Swift { + +struct DefaultTranslator : public Translator { + virtual std::string translate(const std::string& text, const std::string&) { + return text; + } +} defaultTranslator; + +Translator* Translator::translator = &defaultTranslator; + +Translator::~Translator() { +} + +void Translator::setInstance(Translator* t) { + translator = t; +} + +} diff --git a/Swift/Controllers/Translator.h b/Swift/Controllers/Translator.h new file mode 100644 index 0000000..ac4407d --- /dev/null +++ b/Swift/Controllers/Translator.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <string> + +namespace Swift { + class Translator { + public: + virtual ~Translator(); + + virtual std::string translate(const std::string& text, const std::string& context) = 0; + + static void setInstance(Translator* translator); + + static Translator* getInstance() { + return translator; + } + + private: + static Translator* translator; + }; +} |