diff --git a/conf/bnetd.conf.in b/conf/bnetd.conf.in
index 52250d9..e8f1872 100644
--- a/conf/bnetd.conf.in
+++ b/conf/bnetd.conf.in
@@ -128,6 +128,9 @@ newsfile    = news.txt
 helpfile    = bnhelp.conf
 tosfile 	= termsofservice.txt
 
+# Do localization by a game language or by user country?
+localize_by_country = true
+
 #                                                                            #
 ##############################################################################
 
diff --git a/conf/bnetd.conf.win32 b/conf/bnetd.conf.win32
index c65a56b..b6bce9e 100644
--- a/conf/bnetd.conf.win32
+++ b/conf/bnetd.conf.win32
@@ -106,6 +106,9 @@ newsfile    = news.txt
 helpfile    = bnhelp.conf
 tosfile 	= termsofservice.txt
 
+# Do localization by a game language or by user country?
+localize_by_country = true
+
 #                                                                            #
 ##############################################################################
 
diff --git a/src/bnetd/channel.cpp b/src/bnetd/channel.cpp
index 57d8792..d8caa47 100644
--- a/src/bnetd/channel.cpp
+++ b/src/bnetd/channel.cpp
@@ -762,7 +762,7 @@ namespace pvpgn
 			if ((conn_get_wol(me) == 0))
 			{
 				if (!heard && (type == message_type_talk || type == message_type_emote))
-					message_send_text(me, message_type_info, me, "No one hears you.");
+					message_send_text(me, message_type_info, me, localize(c, "No one hears you."));
 			}
 
 #ifdef WITH_LUA
diff --git a/src/bnetd/command.cpp b/src/bnetd/command.cpp
index 6be2cf5..e68a1b1 100644
--- a/src/bnetd/command.cpp
+++ b/src/bnetd/command.cpp
@@ -4633,7 +4633,7 @@ namespace pvpgn
 			char const * filename;
 			std::FILE *       fp;
 
-			filename = i18n_filename(prefs_get_motdfile(), conn_get_gamelang(c));
+			filename = i18n_filename(prefs_get_motdfile(), conn_get_gamelang_localized(c));
 
 			if (fp = std::fopen(filename, "r"))
 			{
@@ -4656,7 +4656,7 @@ namespace pvpgn
 			const char * filename = NULL;
 			std::FILE * fp;
 
-			filename = i18n_filename(prefs_get_tosfile(), conn_get_gamelang(c));
+			filename = i18n_filename(prefs_get_tosfile(), conn_get_gamelang_localized(c));
 
 			/* FIXME: if user enters relative path to tos file in config,
 			   above routine will fail */
diff --git a/src/bnetd/connection.cpp b/src/bnetd/connection.cpp
index 0ffd930..65cdca1 100644
--- a/src/bnetd/connection.cpp
+++ b/src/bnetd/connection.cpp
@@ -128,8 +128,7 @@ namespace pvpgn
 				return;
 			}
 			if (filename = prefs_get_motdfile()) {
-				t_tag gamelang = conn_get_gamelang(c);
-				std::string lang_filename = i18n_filename(filename, gamelang);
+				std::string lang_filename = i18n_filename(filename, conn_get_gamelang_localized(c));
 
 				if (fp = std::fopen(lang_filename.c_str(), "r")) {
 					message_send_file(c, fp);
diff --git a/src/bnetd/file.cpp b/src/bnetd/file.cpp
index 1094c11..0c02197 100644
--- a/src/bnetd/file.cpp
+++ b/src/bnetd/file.cpp
@@ -51,7 +51,7 @@ namespace pvpgn
 	namespace bnetd
 	{
 
-		static char const * file_get_info(char const * rawname, unsigned int * len, bn_long * modtime);
+		static char const * file_get_info(t_connection * c, char const * rawname, unsigned int * len, bn_long * modtime);
 
 		/* Requested files aliases */
 		const char * requestfiles[] = {
@@ -64,7 +64,7 @@ namespace pvpgn
 			NULL, NULL };
 
 
-		static const char * file_find_localized(const char *rawname)
+		static const char * file_find_localized(t_connection * c, const char *rawname)
 		{
 			const char ** pattern, **alias;
 
@@ -74,20 +74,25 @@ namespace pvpgn
 				if (!std::strncmp(rawname, *pattern, std::strlen(*pattern)))
 				{
 					t_gamelang lang;
-					// when file transferring by bnftp protofol client doesn't provide a language
-					// but we can extract it from the filename
+					if (lang = conn_get_gamelang_localized(c))
+						return i18n_filename(*alias, lang);
+
+					// FIXME: when file is transferring by bnftp protofol client doesn't provide a language
+					// but we can extract it from the filename, so do it in next code
 
 					// if there is no country tag in the file (just in case to prevent crash from invalid filename)
 					if ((strlen(*pattern) + 4) > strlen(rawname))
 						return NULL;
 
-					// get language tag from the file name
+					// get language tag from the file name (like "termsofservice-ruRU.txt")
+					// (it used in War3)
 					char langstr[5];
 					strncpy(langstr, rawname + std::strlen(*pattern), 4);
 					langstr[4] = 0;
 					lang = tag_str_to_uint(langstr);
 
-					// if language is invalid then try find it by code
+					// if language is invalid then try find it by country (like "tos_USA.txt")
+					// (it used in D1, SC, War2)
 					if (!tag_check_gamelang(lang))
 					{
 						strncpy(langstr, rawname + std::strlen(*pattern), 3);
@@ -101,7 +106,7 @@ namespace pvpgn
 			return NULL;
 		}
 
-		static char const * file_get_info(char const * rawname, unsigned int * len, bn_long * modtime)
+		static char const * file_get_info(t_connection * c, char const * rawname, unsigned int * len, bn_long * modtime)
 		{
 			const char *filename;
 			t_bnettime   bt;
@@ -128,7 +133,7 @@ namespace pvpgn
 			}
 
 
-			filename = file_find_localized(rawname);
+			filename = file_find_localized(c, rawname);
 			// if localized file not found in "i18n"
 			if (!filename || stat(filename, &sfile) < 0)
 			{
@@ -148,7 +153,7 @@ namespace pvpgn
 		}
 
 
-		extern int file_to_mod_time(char const * rawname, bn_long * modtime)
+		extern int file_to_mod_time(t_connection * c, char const * rawname, bn_long * modtime)
 		{
 			char const * filename;
 			unsigned int len;
@@ -164,7 +169,7 @@ namespace pvpgn
 				return -1;
 			}
 
-			if (!(filename = file_get_info(rawname, &len, modtime)))
+			if (!(filename = file_get_info(c, rawname, &len, modtime)))
 				return -1;
 
 			xfree((void *)filename); /* avoid warning */
@@ -204,7 +209,7 @@ namespace pvpgn
 			packet_set_size(rpacket, sizeof(t_server_file_reply));
 			packet_set_type(rpacket, SERVER_FILE_REPLY);
 
-			if ((filename = file_get_info(rawname, &filelen, &rpacket->u.server_file_reply.timestamp)))
+			if ((filename = file_get_info(c, rawname, &filelen, &rpacket->u.server_file_reply.timestamp)))
 			{
 				if (!(fp = std::fopen(filename, "rb")))
 				{
diff --git a/src/bnetd/file.h b/src/bnetd/file.h
index f878013..23f13c3 100644
--- a/src/bnetd/file.h
+++ b/src/bnetd/file.h
@@ -33,7 +33,7 @@ namespace pvpgn
 	namespace bnetd
 	{
 
-		extern int file_to_mod_time(char const * rawname, bn_long * modtime);
+		extern int file_to_mod_time(t_connection * c, char const * rawname, bn_long * modtime);
 		extern int file_send(t_connection * c, char const * rawname, unsigned int adid, unsigned int etag, unsigned int startoffset, int need_header);
 
 	}
diff --git a/src/bnetd/handle_bnet.cpp b/src/bnetd/handle_bnet.cpp
index 6456edc..a0a0015 100644
--- a/src/bnetd/handle_bnet.cpp
+++ b/src/bnetd/handle_bnet.cpp
@@ -582,7 +582,7 @@ namespace pvpgn
 
 					bn_int_set(&rpacket->u.server_authreq_109.sessionkey, conn_get_sessionkey(c));
 					bn_int_set(&rpacket->u.server_authreq_109.sessionnum, conn_get_sessionnum(c));
-					file_to_mod_time(versioncheck_get_mpqfile(vc), &rpacket->u.server_authreq_109.timestamp);
+					file_to_mod_time(c, versioncheck_get_mpqfile(vc), &rpacket->u.server_authreq_109.timestamp);
 					packet_append_string(rpacket, versioncheck_get_mpqfile(vc));
 					packet_append_string(rpacket, versioncheck_get_eqn(vc));
 					eventlog(eventlog_level_debug, __FUNCTION__, "[%d] selected \"%s\" \"%s\"", conn_get_socket(c), versioncheck_get_mpqfile(vc), versioncheck_get_eqn(vc));
@@ -649,7 +649,7 @@ namespace pvpgn
 				if ((rpacket = packet_create(packet_class_bnet))) {
 					packet_set_size(rpacket, sizeof(t_server_authreq1));
 					packet_set_type(rpacket, SERVER_AUTHREQ1);
-					file_to_mod_time(versioncheck_get_mpqfile(vc), &rpacket->u.server_authreq1.timestamp);
+					file_to_mod_time(c, versioncheck_get_mpqfile(vc), &rpacket->u.server_authreq1.timestamp);
 					packet_append_string(rpacket, versioncheck_get_mpqfile(vc));
 					packet_append_string(rpacket, versioncheck_get_eqn(vc));
 					eventlog(eventlog_level_debug, __FUNCTION__, "[%d] selected \"%s\" \"%s\"", conn_get_socket(c), versioncheck_get_mpqfile(vc), versioncheck_get_eqn(vc));
@@ -1219,7 +1219,7 @@ namespace pvpgn
 			if ((rpacket = packet_create(packet_class_bnet))) {
 				packet_set_size(rpacket, sizeof(t_server_iconreply));
 				packet_set_type(rpacket, SERVER_ICONREPLY);
-				file_to_mod_time(prefs_get_iconfile(), &rpacket->u.server_iconreply.timestamp);
+				file_to_mod_time(c, prefs_get_iconfile(), &rpacket->u.server_iconreply.timestamp);
 
 				/* battle.net sends different file on iconreq for WAR3 and W3XP [Omega] */
 				if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT))
@@ -1397,7 +1397,7 @@ namespace pvpgn
 					 * timestamp doesn't work correctly and starcraft
 					 * needs name in client locale or displays hostname
 					 */
-					file_to_mod_time(tosfile, &rpacket->u.server_fileinforeply.timestamp);
+					file_to_mod_time(c, tosfile, &rpacket->u.server_fileinforeply.timestamp);
 					packet_append_string(rpacket, tosfile);
 					conn_push_outqueue(c, rpacket);
 					packet_del_ref(rpacket);
@@ -2770,7 +2770,7 @@ namespace pvpgn
 			char * buff, *line;
 			std::FILE *       fp;
 
-			filename = i18n_filename(prefs_get_motdw3file(), conn_get_gamelang(c));
+			filename = i18n_filename(prefs_get_motdw3file(), conn_get_gamelang_localized(c));
 
 			if (fp = std::fopen(filename, "r"))
 			{
@@ -3211,7 +3211,7 @@ namespace pvpgn
 					packet_set_type(rpacket, SERVER_ADREPLY);
 					bn_int_set(&rpacket->u.server_adreply.adid, ad->getId());
 					bn_int_set(&rpacket->u.server_adreply.extensiontag, ad->getExtensionTag());
-					file_to_mod_time(ad->getFilename(), &rpacket->u.server_adreply.timestamp);
+					file_to_mod_time(c, ad->getFilename(), &rpacket->u.server_adreply.timestamp);
 					packet_append_string(rpacket, ad->getFilename());
 					packet_append_string(rpacket, ad->getLink());
 					conn_push_outqueue(c, rpacket);
diff --git a/src/bnetd/helpfile.cpp b/src/bnetd/helpfile.cpp
index 64c6154..14a36af 100644
--- a/src/bnetd/helpfile.cpp
+++ b/src/bnetd/helpfile.cpp
@@ -49,16 +49,15 @@ namespace pvpgn
 
 		static std::FILE* get_hfd(t_connection * c)
 		{
-			if (t_gamelang lang = conn_get_gamelang(c))
+			t_gamelang lang = conn_get_gamelang_localized(c);
+
+			std::map<t_gamelang, std::FILE*>::iterator it = hfd_list.find(lang);
+			if (it != hfd_list.end())
 			{
-				std::map<t_gamelang, std::FILE*>::iterator it = hfd_list.find(lang);
-				if (it != hfd_list.end())
-				{
-					return it->second;
-				}
-				// return enUS if language is not specified in language list
-				return hfd_list[languages[0]];
+				return it->second;
 			}
+			// return enUS if language is not specified in language list
+			return hfd_list[languages[0]];
 		}
 
 		extern int helpfile_init(char const *filename)
diff --git a/src/bnetd/i18n.cpp b/src/bnetd/i18n.cpp
index 8679756..e50fc3b 100644
--- a/src/bnetd/i18n.cpp
+++ b/src/bnetd/i18n.cpp
@@ -269,7 +269,7 @@ namespace pvpgn
 			{
 				format = fmt;
 
-				if (t_gamelang lang = conn_get_gamelang(c))
+				if (t_gamelang lang = conn_get_gamelang_localized(c))
 				if (!(format = _find_string(fmt, lang)))
 					format = fmt;
 			
@@ -326,11 +326,21 @@ namespace pvpgn
 
 			for (int i = 0; i < (sizeof(countries) / sizeof(*countries)); i++)
 			if (strcasecmp(code, countries[i][0]) == 0)
-				return tag_str_to_uint(countries[i][0]);
+				return tag_str_to_uint(countries[i][1]);
 
-			return tag_str_to_uint(countries[0][0]); // default
+			return tag_str_to_uint(countries[0][1]); // default
 		}
 
+		extern t_gamelang conn_get_gamelang_localized(t_connection * c)
+		{
+			t_gamelang lang = conn_get_gamelang(c);
+
+			if (prefs_get_localize_by_country())
+			if (const char * country = conn_get_country(c))
+				lang = lang_find_by_country(country);
+
+			return lang;
+		}
 
 	}
 }
diff --git a/src/bnetd/i18n.h b/src/bnetd/i18n.h
index a2f2f9b..5047bf6 100644
--- a/src/bnetd/i18n.h
+++ b/src/bnetd/i18n.h
@@ -48,6 +48,7 @@ namespace pvpgn
 
 		extern const char * i18n_filename(const char * filename, t_tag gamelang);
 		extern t_gamelang lang_find_by_country(const char * code);
+		extern t_gamelang conn_get_gamelang_localized(t_connection * c);
 
 		extern std::string _localize(t_connection * c, const char * func, const char *fmt, const fmt::ArgList &args);
 		FMT_VARIADIC(std::string, _localize, t_connection *, const char *, const char *)
diff --git a/src/bnetd/prefs.cpp b/src/bnetd/prefs.cpp
index 3d0731c..8f3202b 100644
--- a/src/bnetd/prefs.cpp
+++ b/src/bnetd/prefs.cpp
@@ -163,6 +163,7 @@ namespace pvpgn
 			unsigned int max_connections;
 			unsigned int sync_on_logoff;
 			char const * irc_network_name;
+			unsigned int localize_by_country;
 
 			char const * apiregaddrs;
 			char const * wolv1addrs;
@@ -664,6 +665,11 @@ namespace pvpgn
 		static int conf_set_irc_network_name(const char *valstr);
 		static const char *conf_get_irc_network_name(void);
 
+		static int conf_set_localize_by_country(const char *valstr);
+		static const char *conf_get_localize_by_country(void);
+		static int conf_setdef_localize_by_country(void);
+
+
 		static int conf_setdef_apireg_addrs(void);
 		static int conf_set_apireg_addrs(const char *valstr);
 		static const char *conf_get_apireg_addrs(void);
@@ -829,6 +835,7 @@ namespace pvpgn
 			{ "sync_on_logoff", conf_set_sync_on_logoff, conf_get_sync_on_logoff, conf_setdef_sync_on_logoff },
 			{ "ladder_prefix", conf_set_ladder_prefix, conf_get_ladder_prefix, conf_setdef_ladder_prefix },
 			{ "irc_network_name", conf_set_irc_network_name, conf_get_irc_network_name, conf_setdef_irc_network_name },
+			{ "localize_by_country", conf_set_localize_by_country, conf_get_localize_by_country, conf_setdef_localize_by_country },
 
 			{ "apiregaddrs", conf_set_apireg_addrs, conf_get_apireg_addrs, conf_setdef_apireg_addrs },
 			{ "wgameresaddrs", conf_set_wgameres_addrs, conf_get_wgameres_addrs, conf_setdef_wgameres_addrs },
@@ -3478,6 +3485,28 @@ namespace pvpgn
 			return prefs_runtime_config.irc_network_name;
 		}
 
+
+		extern unsigned int prefs_get_localize_by_country(void)
+		{
+			return prefs_runtime_config.localize_by_country;
+		}
+
+		static int conf_set_localize_by_country(const char *valstr)
+		{
+			return conf_set_bool(&prefs_runtime_config.localize_by_country, valstr, 0);
+		}
+
+		static int conf_setdef_localize_by_country(void)
+		{
+			return conf_set_bool(&prefs_runtime_config.localize_by_country, NULL, 0);
+		}
+
+		static const char* conf_get_localize_by_country(void)
+		{
+			return conf_get_bool(prefs_runtime_config.localize_by_country);
+		}
+
+
 		/**
 		*  Westwood Online Extensions
 		*/
diff --git a/src/bnetd/prefs.h b/src/bnetd/prefs.h
index b5855d0..f9dfbdc 100644
--- a/src/bnetd/prefs.h
+++ b/src/bnetd/prefs.h
@@ -179,6 +179,7 @@ namespace pvpgn
 		extern unsigned int prefs_get_max_connections(void);
 		extern unsigned int prefs_get_sync_on_logoff(void);
 		extern char const * prefs_get_irc_network_name(void);
+		extern unsigned int prefs_get_localize_by_country(void);
 
 		/**
 		*  Westwood Online Extensions