diff --git a/CHANGELOG.md b/CHANGELOG.md
index c7b2198476..b92f921d69 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - The Interact button can be used on campfires to sit
 - Made map icons fade out when near the edge of the map display
 - Roughly doubled the speed of entity vs terrain physics checks
+- Updated client facing error messages to be localizable strings
 
 ### Removed
 
diff --git a/assets/voxygen/i18n/en/main.ron b/assets/voxygen/i18n/en/main.ron
index fe0822df17..35a8830591 100644
--- a/assets/voxygen/i18n/en/main.ron
+++ b/assets/voxygen/i18n/en/main.ron
@@ -60,7 +60,11 @@ https://veloren.net/account/."#,
         "main.login.select_language": "Select a language",
         "main.login.client_version": "Client Version",
         "main.login.server_version": "Server Version",
+        "main.login.client_init_failed": "Client failed to initialize.",
+        "main.login.username_bad_characters": "Username contains invalid characters! (Only alphanumeric, '_' and '-' are allowed)",
+        "main.login.username_too_long": "Username is too long! Max length is: {max_len}",
         "main.servers.select_server": "Select a server",
+        "main.servers.singleplayer_error": "Failed to connect to internal server.",
 
         // Credits screen
         "main.credits": "Credits",
diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs
index 2a602efe17..12575c6d71 100644
--- a/common/src/comp/mod.rs
+++ b/common/src/comp/mod.rs
@@ -90,7 +90,7 @@ pub use self::{
         Scale, Sticky, Vel,
     },
     player::DisconnectReason,
-    player::Player,
+    player::{AliasError, Player, MAX_ALIAS_LEN},
     poise::{Poise, PoiseState},
     projectile::{Projectile, ProjectileConstructor},
     shockwave::{Shockwave, ShockwaveHitEntities},
diff --git a/common/src/comp/player.rs b/common/src/comp/player.rs
index 8eecf6b90d..7236096e68 100644
--- a/common/src/comp/player.rs
+++ b/common/src/comp/player.rs
@@ -5,7 +5,7 @@ use uuid::Uuid;
 
 use crate::resources::{BattleMode, Time};
 
-const MAX_ALIAS_LEN: usize = 32;
+pub const MAX_ALIAS_LEN: usize = 32;
 
 #[derive(Debug)]
 pub enum DisconnectReason {
diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs
index 5914cd5f1f..c0be40a378 100644
--- a/voxygen/src/menu/main/mod.rs
+++ b/voxygen/src/menu/main/mod.rs
@@ -88,6 +88,9 @@ impl PlayState for MainMenuState {
     fn tick(&mut self, global_state: &mut GlobalState, events: Vec<Event>) -> PlayStateResult {
         span!(_guard, "tick", "<MainMenuState as PlayState>::tick");
 
+        // Pull in localizations
+        let localized_strings = &global_state.i18n.read();
+
         // Poll server creation
         #[cfg(feature = "singleplayer")]
         {
@@ -102,6 +105,7 @@ impl PlayState for MainMenuState {
                             ConnectionArgs::Mpsc(14004),
                             &mut self.init,
                             &global_state.tokio_runtime,
+                            &global_state.i18n,
                         );
                     },
                     Ok(Err(e)) => {
@@ -109,7 +113,11 @@ impl PlayState for MainMenuState {
                         global_state.singleplayer = None;
                         self.init = InitState::None;
                         self.main_menu_ui.cancel_connection();
-                        self.main_menu_ui.show_info(format!("Error: {:?}", e));
+                        global_state.info_message = Some(
+                            localized_strings
+                                .get("main.servers.singleplayer_error")
+                                .to_owned(),
+                        );
                     },
                     Err(_) => (),
                 }
@@ -143,7 +151,11 @@ impl PlayState for MainMenuState {
                 // Log error for possible additional use later or incase that the error
                 // displayed is cut of.
                 error!(?e, "Client Init failed");
-                global_state.info_message = Some(e);
+                global_state.info_message = Some(
+                    localized_strings
+                        .get("main.login.client_init_failed")
+                        .to_owned(),
+                );
             },
             Some(InitMsg::IsAuthTrusted(auth_server)) => {
                 if global_state
@@ -163,7 +175,6 @@ impl PlayState for MainMenuState {
         }
 
         // Tick the client to keep the connection alive if we are waiting on pipelines
-        let localized_strings = &global_state.i18n.read();
         if let InitState::Pipeline(client) = &mut self.init {
             match client.tick(
                 comp::ControllerInputs::default(),
@@ -262,6 +273,7 @@ impl PlayState for MainMenuState {
                         connection_args,
                         &mut self.init,
                         &global_state.tokio_runtime,
+                        &global_state.i18n,
                     );
                 },
                 MainMenuEvent::CancelLoginAttempt => {
@@ -451,9 +463,27 @@ fn attempt_login(
     connection_args: ConnectionArgs,
     init: &mut InitState,
     runtime: &Arc<runtime::Runtime>,
+    localized_strings: &LocalizationHandle,
 ) {
+    let localization = localized_strings.read();
     if let Err(err) = comp::Player::alias_validate(&username) {
-        *info_message = Some(err.to_string());
+        match err {
+            comp::AliasError::ForbiddenCharacters => {
+                *info_message = Some(
+                    localization
+                        .get("main.login.username_bad_characters")
+                        .to_owned(),
+                );
+            },
+            comp::AliasError::TooLong => {
+                *info_message = Some(
+                    localization
+                        .get("main.login.username_too_long")
+                        .to_owned()
+                        .replace("{max_len}", comp::MAX_ALIAS_LEN.to_string().as_str()),
+                );
+            },
+        }
         return;
     }