Browse Source

[i18n] translate HTTP proxy

Signed-off-by: R4SAS <r4sas@i2pmail.org>
pull/1657/head
R4SAS 4 years ago
parent
commit
df66c2d2dc
Signed by: r4sas
GPG Key ID: 66F6C87B98EBCFE2
  1. 16
      i18n/I18N.h
  2. 34
      i18n/I18N_langs.h
  3. 43
      i18n/russian.cpp
  4. 2
      libi2pd/HTTP.cpp
  5. 6
      libi2pd/RouterContext.h
  6. 75
      libi2pd_client/HTTPProxy.cpp

16
i18n/I18N.h

@ -11,20 +11,11 @@
#include "RouterContext.h" #include "RouterContext.h"
namespace i2p { namespace i2p {
namespace i18n { namespace i18n {
namespace english { inline std::string translate (std::string arg)
std::string GetString (std::string arg);
std::string GetPlural (std::string arg, int n);
}
namespace russian {
std::string GetString (std::string arg);
std::string GetPlural (std::string arg, int n);
}
std::string translate (std::string arg)
{ {
switch (i2p::context.GetLanguage ()) switch (i2p::context.GetLanguage ())
{ {
@ -49,7 +40,8 @@ namespace i18n {
} // i2p } // i2p
template<typename... TArgs> template<typename... TArgs>
std::string tr (TArgs&&... args) { std::string tr (TArgs&&... args)
{
return i2p::i18n::translate(std::forward<TArgs>(args)...); return i2p::i18n::translate(std::forward<TArgs>(args)...);
} }

34
i18n/I18N_langs.h

@ -0,0 +1,34 @@
/*
* Copyright (c) 2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#ifndef __I18N_LANGS_H__
#define __I18N_LANGS_H__
namespace i2p {
enum Lang {
eEnglish = 0,
eRussian
};
namespace i18n {
namespace english {
std::string GetString (std::string arg);
std::string GetPlural (std::string arg, int n);
}
namespace russian {
std::string GetString (std::string arg);
std::string GetPlural (std::string arg, int n);
}
} // i18n
} // i2p
#endif // __I18N_LANGS_H__

43
i18n/russian.cpp

@ -16,8 +16,44 @@ namespace russian { // language
static std::map<std::string, std::string> strings static std::map<std::string, std::string> strings
{ {
{"Enabled", "Включено"}, // HTTP Proxy
{"Disabled", "Выключено"} {"Proxy error", "Ошибка прокси"},
{"Proxy info", "Информация прокси"},
{"Proxy error: Host not found", "Ошибка прокси: Адрес не найден"},
{"Remote host not found in router's addressbook", "Запрошенный адрес не найден в адресной книге роутера"},
{"You may try to find this host on jump services below", "Вы можете попробовать найти адрес на джамп сервисах ниже"},
{"Invalid request", "Некорректный запрос"},
{"Proxy unable to parse your request", "Прокси не может разобрать ваш запрос"},
{"addresshelper is not supported", "addresshelper не поддерживается"},
{"Host", "Адрес"},
{"added to router's addressbook from helper", "добавлен в адресную книгу роутера через хелпер"},
{"already in router's addressbook", "уже а адресной книге роутера"},
{"Click", "Нажмите"},
{"here", "здесь"},
{"to proceed", "чтобы продолжить"},
{"to update record", "чтобы обновить запись"},
{"Addresshelper found", "Найден addresshelper"},
{"invalid request uri", "некорректный URI запроса"},
{"Can't detect destination host from request", "Не удалось определить адрес назначения из запроса"},
{"Outproxy failure", "Ошибка внешнего прокси"},
{"bad outproxy settings", "некорректные настройки внешнего прокси"},
{"not inside I2P network, but outproxy is not enabled", "не в I2P сети, но внешний прокси не включен"},
{"unknown outproxy url", "неизвестный URL внешнего прокси"},
{"cannot resolve upstream proxy", "не удается определить внешний прокси"},
{"hostname too long", "имя хоста слишком длинное"},
{"cannot connect to upstream socks proxy", "не удается подключиться к вышестоящему SOCKS прокси"},
{"Cannot negotiate with socks proxy", "Не удается договориться с вышестоящим SOCKS прокси"},
{"CONNECT error", "Ошибка CONNECT запроса"},
{"Failed to Connect", "Не удалось подключиться"},
{"socks proxy error", "ошибка SOCKS прокси"},
{"failed to send request to upstream", "не удалось отправить запрос вышестоящему прокси"},
{"No Reply From socks proxy", "Нет ответа от SOCKS прокси сервера"},
{"cannot connect", "не удалось подключиться"},
{"http out proxy not implemented", "поддержка внешнего HTTP прокси сервера не реализована"},
{"cannot connect to upstream http proxy", "не удалось подключиться к вышестоящему HTTP прокси серверу"},
{"Host is down", "Адрес недоступен"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Не удалось установить соединение к запрошенному адресу, возможно он не в сети. Попробуйте повторить запрос позже."},
{"", ""},
}; };
static std::map<std::string, std::vector<std::string>> plurals static std::map<std::string, std::vector<std::string>> plurals
@ -25,7 +61,8 @@ namespace russian { // language
{"days", {"день", "дня", "дней"}}, {"days", {"день", "дня", "дней"}},
{"hours", {"час", "часа", "часов"}}, {"hours", {"час", "часа", "часов"}},
{"minutes", {"минута", "минуты", "минут"}}, {"minutes", {"минута", "минуты", "минут"}},
{"seconds", {"секунда", "секунды", "секунд"}} {"seconds", {"секунда", "секунды", "секунд"}},
{"", {"", ""}},
}; };
std::string GetString (std::string arg) std::string GetString (std::string arg)

2
libi2pd/HTTP.cpp

@ -187,6 +187,8 @@ namespace http
params.clear(); params.clear();
for (const auto& it : tokens) { for (const auto& it : tokens) {
if (!it.length()) // empty
continue;
std::size_t eq = it.find ('='); std::size_t eq = it.find ('=');
if (eq != std::string::npos) { if (eq != std::string::npos) {
auto e = std::pair<std::string, std::string>(it.substr(0, eq), it.substr(eq + 1)); auto e = std::pair<std::string, std::string>(it.substr(0, eq), it.substr(eq + 1));

6
libi2pd/RouterContext.h

@ -18,6 +18,7 @@
#include "Identity.h" #include "Identity.h"
#include "RouterInfo.h" #include "RouterInfo.h"
#include "Garlic.h" #include "Garlic.h"
#include "I18N_langs.h"
namespace i2p namespace i2p
{ {
@ -50,11 +51,6 @@ namespace garlic
eRouterErrorSymmetricNAT = 3 eRouterErrorSymmetricNAT = 3
}; };
enum Lang {
eEnglish = 0,
eRussian
};
class RouterContext: public i2p::garlic::GarlicDestination class RouterContext: public i2p::garlic::GarlicDestination
{ {
private: private:

75
libi2pd_client/HTTPProxy.cpp

@ -28,6 +28,7 @@
#include "I2PTunnel.h" #include "I2PTunnel.h"
#include "Config.h" #include "Config.h"
#include "HTTP.h" #include "HTTP.h"
#include "I18N.h"
namespace i2p { namespace i2p {
namespace proxy { namespace proxy {
@ -71,8 +72,8 @@ namespace proxy {
void SentHTTPFailed(const boost::system::error_code & ecode); void SentHTTPFailed(const boost::system::error_code & ecode);
void HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream); void HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream);
/* error helpers */ /* error helpers */
void GenericProxyError(const char *title, const char *description); void GenericProxyError(const std::string& title, const std::string& description);
void GenericProxyInfo(const char *title, const char *description); void GenericProxyInfo(const std::string& title, const std::string& description);
void HostNotFound(std::string & host); void HostNotFound(std::string & host);
void SendProxyError(std::string & content); void SendProxyError(std::string & content);
@ -151,17 +152,17 @@ namespace proxy {
Done(shared_from_this()); Done(shared_from_this());
} }
void HTTPReqHandler::GenericProxyError(const char *title, const char *description) { void HTTPReqHandler::GenericProxyError(const std::string& title, const std::string& description) {
std::stringstream ss; std::stringstream ss;
ss << "<h1>Proxy error: " << title << "</h1>\r\n"; ss << "<h1>" << tr("Proxy error") << ": " << title << "</h1>\r\n";
ss << "<p>" << description << "</p>\r\n"; ss << "<p>" << description << "</p>\r\n";
std::string content = ss.str(); std::string content = ss.str();
SendProxyError(content); SendProxyError(content);
} }
void HTTPReqHandler::GenericProxyInfo(const char *title, const char *description) { void HTTPReqHandler::GenericProxyInfo(const std::string& title, const std::string& description) {
std::stringstream ss; std::stringstream ss;
ss << "<h1>Proxy info: " << title << "</h1>\r\n"; ss << "<h1>" << tr("Proxy info") << ": " << title << "</h1>\r\n";
ss << "<p>" << description << "</p>\r\n"; ss << "<p>" << description << "</p>\r\n";
std::string content = ss.str(); std::string content = ss.str();
SendProxyError(content); SendProxyError(content);
@ -169,9 +170,9 @@ namespace proxy {
void HTTPReqHandler::HostNotFound(std::string & host) { void HTTPReqHandler::HostNotFound(std::string & host) {
std::stringstream ss; std::stringstream ss;
ss << "<h1>Proxy error: Host not found</h1>\r\n" ss << "<h1>" << tr("Proxy error: Host not found") << "</h1>\r\n"
<< "<p>Remote host not found in router's addressbook</p>\r\n" << "<p>" << tr("Remote host not found in router's addressbook") << "</p>\r\n"
<< "<p>You may try to find this host on jump services below:</p>\r\n" << "<p>" << tr("You may try to find this host on jump services below") << ":</p>\r\n"
<< "<ul>\r\n"; << "<ul>\r\n";
for (const auto& js : jumpservices) { for (const auto& js : jumpservices) {
ss << " <li><a href=\"" << js.second << host << "\">" << js.first << "</a></li>\r\n"; ss << " <li><a href=\"" << js.second << host << "\">" << js.first << "</a></li>\r\n";
@ -216,7 +217,7 @@ namespace proxy {
b64 = i2p::http::UrlDecode(value); b64 = i2p::http::UrlDecode(value);
// if we need update exists, request formed with update param // if we need update exists, request formed with update param
if (params["update"] == "true") { len += std::strlen("&update=true"); confirm = true; } if (params["update"] == "true") { len += std::strlen("&update=true"); confirm = true; }
url.query.replace(pos, len, ""); url.query.replace(pos - 1, len + 1, ""); // +-1 for taking ? and & before parameter
return true; return true;
} }
@ -268,7 +269,7 @@ namespace proxy {
if (m_req_len < 0) { if (m_req_len < 0) {
LogPrint(eLogError, "HTTPProxy: unable to parse request"); LogPrint(eLogError, "HTTPProxy: unable to parse request");
GenericProxyError("Invalid request", "Proxy unable to parse your request"); GenericProxyError(tr("Invalid request"), tr("Proxy unable to parse your request"));
return true; /* parse error */ return true; /* parse error */
} }
@ -283,7 +284,7 @@ namespace proxy {
if (!m_Addresshelper) if (!m_Addresshelper)
{ {
LogPrint(eLogWarning, "HTTPProxy: addresshelper request rejected"); LogPrint(eLogWarning, "HTTPProxy: addresshelper request rejected");
GenericProxyError("Invalid request", "addresshelper is not supported"); GenericProxyError(tr("Invalid request"), tr("addresshelper is not supported"));
return true; return true;
} }
if (!i2p::client::context.GetAddressBook ().FindAddress (m_RequestURL.host) || m_Confirm) if (!i2p::client::context.GetAddressBook ().FindAddress (m_RequestURL.host) || m_Confirm)
@ -292,17 +293,19 @@ namespace proxy {
LogPrint (eLogInfo, "HTTPProxy: added address from addresshelper for ", m_RequestURL.host); LogPrint (eLogInfo, "HTTPProxy: added address from addresshelper for ", m_RequestURL.host);
std::string full_url = m_RequestURL.to_string(); std::string full_url = m_RequestURL.to_string();
std::stringstream ss; std::stringstream ss;
ss << "Host " << m_RequestURL.host << " added to router's addressbook from helper. " ss << tr("Host") <<" " << m_RequestURL.host << " " << tr("added to router's addressbook from helper") << ". ";
<< "Click <a href=\"" << full_url << "\">here</a> to proceed."; ss << tr("Click") << " <a href=\"" << full_url << "\">" << tr("here") << "</a> " << tr("to proceed") << ".";
GenericProxyInfo("Addresshelper found", ss.str().c_str()); GenericProxyInfo(tr("Addresshelper found"), ss.str());
return true; /* request processed */ return true; /* request processed */
} }
else else
{ {
std::string full_url = m_RequestURL.to_string();
std::stringstream ss; std::stringstream ss;
ss << "Host " << m_RequestURL.host << " <font color=red>already in router's addressbook</font>. " ss << tr("Host") << " " << m_RequestURL.host << " <font color=red>" << tr("already in router's addressbook") << "</font>. ";
<< "Click <a href=\"" << m_RequestURL.query << "?i2paddresshelper=" << jump << "&update=true\">here</a> to update record."; ss << tr("Click") << " <a href=\"" << full_url << (full_url.find('?') != std::string::npos ? "&i2paddresshelper=" : "?i2paddresshelper=");
GenericProxyInfo("Addresshelper found", ss.str().c_str()); ss << jump << "&update=true\">" << tr("here") << "</a> " << tr("to update record") << ".";
GenericProxyInfo(tr("Addresshelper found"), ss.str());
return true; /* request processed */ return true; /* request processed */
} }
} }
@ -315,7 +318,7 @@ namespace proxy {
auto pos = uri.find(":"); auto pos = uri.find(":");
if(pos == std::string::npos || pos == uri.size() - 1) if(pos == std::string::npos || pos == uri.size() - 1)
{ {
GenericProxyError("Invalid Request", "invalid request uri"); GenericProxyError(tr("Invalid Request"), tr("invalid request uri"));
return true; return true;
} }
else else
@ -358,7 +361,7 @@ namespace proxy {
else else
{ {
/* relative url and missing 'Host' header */ /* relative url and missing 'Host' header */
GenericProxyError("Invalid request", "Can't detect destination host from request"); GenericProxyError(tr("Invalid request"), tr("Can't detect destination host from request"));
return true; return true;
} }
} }
@ -375,11 +378,11 @@ namespace proxy {
if(m_ProxyURL.parse(m_OutproxyUrl)) if(m_ProxyURL.parse(m_OutproxyUrl))
ForwardToUpstreamProxy(); ForwardToUpstreamProxy();
else else
GenericProxyError("Outproxy failure", "bad outproxy settings"); GenericProxyError(tr("Outproxy failure"), tr("bad outproxy settings"));
} else { } else {
LogPrint (eLogWarning, "HTTPProxy: outproxy failure for ", dest_host, ": no outproxy enabled"); LogPrint (eLogWarning, "HTTPProxy: outproxy failure for ", dest_host, ": no outproxy enabled");
std::string message = "Host " + dest_host + " not inside I2P network, but outproxy is not enabled"; std::stringstream ss; ss << tr("Host") << " " << dest_host << " " << tr("not inside I2P network, but outproxy is not enabled");
GenericProxyError("Outproxy failure", message.c_str()); GenericProxyError(tr("Outproxy failure"), ss.str());
} }
return true; return true;
} }
@ -467,13 +470,13 @@ namespace proxy {
else else
{ {
// unknown type, complain // unknown type, complain
GenericProxyError("unknown outproxy url", m_ProxyURL.to_string().c_str()); GenericProxyError(tr("unknown outproxy url"), m_ProxyURL.to_string());
} }
} }
void HTTPReqHandler::HandleUpstreamProxyResolved(const boost::system::error_code & ec, boost::asio::ip::tcp::resolver::iterator it, ProxyResolvedHandler handler) void HTTPReqHandler::HandleUpstreamProxyResolved(const boost::system::error_code & ec, boost::asio::ip::tcp::resolver::iterator it, ProxyResolvedHandler handler)
{ {
if(ec) GenericProxyError("cannot resolve upstream proxy", ec.message().c_str()); if(ec) GenericProxyError(tr("cannot resolve upstream proxy"), ec.message());
else handler(*it); else handler(*it);
} }
@ -481,7 +484,7 @@ namespace proxy {
{ {
if(!ec) { if(!ec) {
if(m_RequestURL.host.size() > 255) { if(m_RequestURL.host.size() > 255) {
GenericProxyError("hostname too long", m_RequestURL.host.c_str()); GenericProxyError(tr("hostname too long"), m_RequestURL.host);
return; return;
} }
uint16_t port = m_RequestURL.port; uint16_t port = m_RequestURL.port;
@ -508,13 +511,13 @@ namespace proxy {
reqsize += host.size(); reqsize += host.size();
m_socks_buf[++reqsize] = 0; m_socks_buf[++reqsize] = 0;
boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_socks_buf, reqsize), boost::asio::transfer_all(), std::bind(&HTTPReqHandler::HandleSocksProxySendHandshake, this, std::placeholders::_1, std::placeholders::_2)); boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_socks_buf, reqsize), boost::asio::transfer_all(), std::bind(&HTTPReqHandler::HandleSocksProxySendHandshake, this, std::placeholders::_1, std::placeholders::_2));
} else GenericProxyError("cannot connect to upstream socks proxy", ec.message().c_str()); } else GenericProxyError(tr("cannot connect to upstream socks proxy"), ec.message());
} }
void HTTPReqHandler::HandleSocksProxySendHandshake(const boost::system::error_code & ec, std::size_t bytes_transferred) void HTTPReqHandler::HandleSocksProxySendHandshake(const boost::system::error_code & ec, std::size_t bytes_transferred)
{ {
LogPrint(eLogDebug, "HTTPProxy: upstream socks handshake sent"); LogPrint(eLogDebug, "HTTPProxy: upstream socks handshake sent");
if(ec) GenericProxyError("Cannot negotiate with socks proxy", ec.message().c_str()); if(ec) GenericProxyError(tr("Cannot negotiate with socks proxy"), ec.message());
else m_proxysock->async_read_some(boost::asio::buffer(m_socks_buf, 8), std::bind(&HTTPReqHandler::HandleSocksProxyReply, this, std::placeholders::_1, std::placeholders::_2)); else m_proxysock->async_read_some(boost::asio::buffer(m_socks_buf, 8), std::bind(&HTTPReqHandler::HandleSocksProxyReply, this, std::placeholders::_1, std::placeholders::_2));
} }
@ -556,7 +559,7 @@ namespace proxy {
} }
else else
{ {
GenericProxyError("CONNECT error", "Failed to Connect"); GenericProxyError(tr("CONNECT error"), tr("Failed to Connect"));
} }
} }
@ -567,7 +570,7 @@ namespace proxy {
m_send_buf = m_ClientResponse.to_string(); m_send_buf = m_ClientResponse.to_string();
boost::asio::async_write(*m_sock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&] (const boost::system::error_code & ec, std::size_t transferred) boost::asio::async_write(*m_sock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&] (const boost::system::error_code & ec, std::size_t transferred)
{ {
if(ec) GenericProxyError("socks proxy error", ec.message().c_str()); if(ec) GenericProxyError(tr("socks proxy error"), ec.message());
else HandoverToUpstreamProxy(); else HandoverToUpstreamProxy();
}); });
} else { } else {
@ -575,7 +578,7 @@ namespace proxy {
LogPrint(eLogDebug, "HTTPProxy: send ", m_send_buf.size(), " bytes"); LogPrint(eLogDebug, "HTTPProxy: send ", m_send_buf.size(), " bytes");
boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&](const boost::system::error_code & ec, std::size_t transferred) boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&](const boost::system::error_code & ec, std::size_t transferred)
{ {
if(ec) GenericProxyError("failed to send request to upstream", ec.message().c_str()); if(ec) GenericProxyError(tr("failed to send request to upstream"), ec.message());
else HandoverToUpstreamProxy(); else HandoverToUpstreamProxy();
}); });
} }
@ -593,18 +596,18 @@ namespace proxy {
ss << "error code: "; ss << "error code: ";
ss << (int) m_socks_buf[1]; ss << (int) m_socks_buf[1];
std::string msg = ss.str(); std::string msg = ss.str();
GenericProxyError("Socks Proxy error", msg.c_str()); GenericProxyError(tr("socks proxy error"), msg);
} }
} }
else GenericProxyError("No Reply From socks proxy", ec.message().c_str()); else GenericProxyError(tr("No Reply From socks proxy"), ec.message());
} }
void HTTPReqHandler::HandleUpstreamHTTPProxyConnect(const boost::system::error_code & ec) void HTTPReqHandler::HandleUpstreamHTTPProxyConnect(const boost::system::error_code & ec)
{ {
if(!ec) { if(!ec) {
LogPrint(eLogDebug, "HTTPProxy: connected to http upstream"); LogPrint(eLogDebug, "HTTPProxy: connected to http upstream");
GenericProxyError("cannot connect", "http out proxy not implemented"); GenericProxyError(tr("cannot connect"), tr("http out proxy not implemented"));
} else GenericProxyError("cannot connect to upstream http proxy", ec.message().c_str()); } else GenericProxyError(tr("cannot connect to upstream http proxy"), ec.message());
} }
/* will be called after some data received from client */ /* will be called after some data received from client */
@ -637,7 +640,7 @@ namespace proxy {
{ {
if (!stream) { if (!stream) {
LogPrint (eLogError, "HTTPProxy: error when creating the stream, check the previous warnings for more info"); LogPrint (eLogError, "HTTPProxy: error when creating the stream, check the previous warnings for more info");
GenericProxyError("Host is down", "Can't create connection to requested host, it may be down. Please try again later."); GenericProxyError(tr("Host is down"), tr("Can't create connection to requested host, it may be down. Please try again later."));
return; return;
} }
if (Kill()) if (Kill())

Loading…
Cancel
Save