[i18n] translate HTTP proxy

Signed-off-by: R4SAS <r4sas@i2pmail.org>
This commit is contained in:
R4SAS 2021-05-23 06:06:04 +03:00
parent 80b44fc9a9
commit df66c2d2dc
No known key found for this signature in database
GPG Key ID: 66F6C87B98EBCFE2
6 changed files with 120 additions and 56 deletions

View File

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

34
i18n/I18N_langs.h Normal file
View File

@ -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__

View File

@ -16,8 +16,44 @@ namespace russian { // language
static std::map<std::string, std::string> strings
{
{"Enabled", "Включено"},
{"Disabled", "Выключено"}
// HTTP Proxy
{"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
@ -25,7 +61,8 @@ namespace russian { // language
{"days", {"день", "дня", "дней"}},
{"hours", {"час", "часа", "часов"}},
{"minutes", {"минута", "минуты", "минут"}},
{"seconds", {"секунда", "секунды", "секунд"}}
{"seconds", {"секунда", "секунды", "секунд"}},
{"", {"", ""}},
};
std::string GetString (std::string arg)

View File

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

View File

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

View File

@ -28,6 +28,7 @@
#include "I2PTunnel.h"
#include "Config.h"
#include "HTTP.h"
#include "I18N.h"
namespace i2p {
namespace proxy {
@ -71,8 +72,8 @@ namespace proxy {
void SentHTTPFailed(const boost::system::error_code & ecode);
void HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream);
/* error helpers */
void GenericProxyError(const char *title, const char *description);
void GenericProxyInfo(const char *title, const char *description);
void GenericProxyError(const std::string& title, const std::string& description);
void GenericProxyInfo(const std::string& title, const std::string& description);
void HostNotFound(std::string & host);
void SendProxyError(std::string & content);
@ -151,17 +152,17 @@ namespace proxy {
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;
ss << "<h1>Proxy error: " << title << "</h1>\r\n";
ss << "<h1>" << tr("Proxy error") << ": " << title << "</h1>\r\n";
ss << "<p>" << description << "</p>\r\n";
std::string content = ss.str();
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;
ss << "<h1>Proxy info: " << title << "</h1>\r\n";
ss << "<h1>" << tr("Proxy info") << ": " << title << "</h1>\r\n";
ss << "<p>" << description << "</p>\r\n";
std::string content = ss.str();
SendProxyError(content);
@ -169,9 +170,9 @@ namespace proxy {
void HTTPReqHandler::HostNotFound(std::string & host) {
std::stringstream ss;
ss << "<h1>Proxy error: Host not found</h1>\r\n"
<< "<p>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"
ss << "<h1>" << tr("Proxy error: Host not found") << "</h1>\r\n"
<< "<p>" << tr("Remote host not found in router's addressbook") << "</p>\r\n"
<< "<p>" << tr("You may try to find this host on jump services below") << ":</p>\r\n"
<< "<ul>\r\n";
for (const auto& js : jumpservices) {
ss << " <li><a href=\"" << js.second << host << "\">" << js.first << "</a></li>\r\n";
@ -216,7 +217,7 @@ namespace proxy {
b64 = i2p::http::UrlDecode(value);
// if we need update exists, request formed with update param
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;
}
@ -268,7 +269,7 @@ namespace proxy {
if (m_req_len < 0) {
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 */
}
@ -283,7 +284,7 @@ namespace proxy {
if (!m_Addresshelper)
{
LogPrint(eLogWarning, "HTTPProxy: addresshelper request rejected");
GenericProxyError("Invalid request", "addresshelper is not supported");
GenericProxyError(tr("Invalid request"), tr("addresshelper is not supported"));
return true;
}
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);
std::string full_url = m_RequestURL.to_string();
std::stringstream ss;
ss << "Host " << m_RequestURL.host << " added to router's addressbook from helper. "
<< "Click <a href=\"" << full_url << "\">here</a> to proceed.";
GenericProxyInfo("Addresshelper found", ss.str().c_str());
ss << tr("Host") <<" " << m_RequestURL.host << " " << tr("added to router's addressbook from helper") << ". ";
ss << tr("Click") << " <a href=\"" << full_url << "\">" << tr("here") << "</a> " << tr("to proceed") << ".";
GenericProxyInfo(tr("Addresshelper found"), ss.str());
return true; /* request processed */
}
else
{
std::string full_url = m_RequestURL.to_string();
std::stringstream ss;
ss << "Host " << m_RequestURL.host << " <font color=red>already in router's addressbook</font>. "
<< "Click <a href=\"" << m_RequestURL.query << "?i2paddresshelper=" << jump << "&update=true\">here</a> to update record.";
GenericProxyInfo("Addresshelper found", ss.str().c_str());
ss << tr("Host") << " " << m_RequestURL.host << " <font color=red>" << tr("already in router's addressbook") << "</font>. ";
ss << tr("Click") << " <a href=\"" << full_url << (full_url.find('?') != std::string::npos ? "&i2paddresshelper=" : "?i2paddresshelper=");
ss << jump << "&update=true\">" << tr("here") << "</a> " << tr("to update record") << ".";
GenericProxyInfo(tr("Addresshelper found"), ss.str());
return true; /* request processed */
}
}
@ -315,7 +318,7 @@ namespace proxy {
auto pos = uri.find(":");
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;
}
else
@ -358,7 +361,7 @@ namespace proxy {
else
{
/* 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;
}
}
@ -375,11 +378,11 @@ namespace proxy {
if(m_ProxyURL.parse(m_OutproxyUrl))
ForwardToUpstreamProxy();
else
GenericProxyError("Outproxy failure", "bad outproxy settings");
GenericProxyError(tr("Outproxy failure"), tr("bad outproxy settings"));
} else {
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";
GenericProxyError("Outproxy failure", message.c_str());
std::stringstream ss; ss << tr("Host") << " " << dest_host << " " << tr("not inside I2P network, but outproxy is not enabled");
GenericProxyError(tr("Outproxy failure"), ss.str());
}
return true;
}
@ -467,13 +470,13 @@ namespace proxy {
else
{
// 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)
{
if(ec) GenericProxyError("cannot resolve upstream proxy", ec.message().c_str());
if(ec) GenericProxyError(tr("cannot resolve upstream proxy"), ec.message());
else handler(*it);
}
@ -481,7 +484,7 @@ namespace proxy {
{
if(!ec) {
if(m_RequestURL.host.size() > 255) {
GenericProxyError("hostname too long", m_RequestURL.host.c_str());
GenericProxyError(tr("hostname too long"), m_RequestURL.host);
return;
}
uint16_t port = m_RequestURL.port;
@ -508,13 +511,13 @@ namespace proxy {
reqsize += host.size();
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));
} 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)
{
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));
}
@ -556,7 +559,7 @@ namespace proxy {
}
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();
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 {
@ -575,7 +578,7 @@ namespace proxy {
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)
{
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();
});
}
@ -593,18 +596,18 @@ namespace proxy {
ss << "error code: ";
ss << (int) m_socks_buf[1];
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)
{
if(!ec) {
LogPrint(eLogDebug, "HTTPProxy: connected to http upstream");
GenericProxyError("cannot connect", "http out proxy not implemented");
} else GenericProxyError("cannot connect to upstream http proxy", ec.message().c_str());
GenericProxyError(tr("cannot connect"), tr("http out proxy not implemented"));
} else GenericProxyError(tr("cannot connect to upstream http proxy"), ec.message());
}
/* will be called after some data received from client */
@ -637,7 +640,7 @@ namespace proxy {
{
if (!stream) {
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;
}
if (Kill())