diff --git a/Application/API/EventAPI.cs b/Application/API/EventAPI.cs
index 34c43fe6c..cc8f0a2d0 100644
--- a/Application/API/EventAPI.cs
+++ b/Application/API/EventAPI.cs
@@ -46,7 +46,7 @@ namespace IW4MAdmin.Application.API
FlaggedMessageCount = 0;
- E.Owner.Broadcast("If you suspect someone of ^5CHEATING ^7use the ^5!report ^7command").Wait();
+ E.Owner.Broadcast(Utilities.CurrentLocalization.LocalizationSet["GLOBAL_REPORT"]).Wait();
Events.Enqueue(new EventInfo(
EventInfo.EventType.ALERT,
EventInfo.EventVersion.IW4MAdmin,
diff --git a/Application/Application.csproj b/Application/Application.csproj
index 5ee1fef5e..7522fd4d0 100644
--- a/Application/Application.csproj
+++ b/Application/Application.csproj
@@ -58,6 +58,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
diff --git a/Application/BuildScripts/PostPublish.bat b/Application/BuildScripts/PostPublish.bat
index 8b8f091fc..8c0803d45 100644
--- a/Application/BuildScripts/PostPublish.bat
+++ b/Application/BuildScripts/PostPublish.bat
@@ -3,6 +3,8 @@ set ProjectDir=%2
set TargetDir=%3
echo Deleting extra language files
+
+if exist "%SolutionDir%Publish\Windows\en-US\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\Windows\en-US'
if exist "%SolutionDir%Publish\Windows\de\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\Windows\de'
if exist "%SolutionDir%Publish\Windows\es\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\Windows\es'
if exist "%SolutionDir%Publish\Windows\fr\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\Windows\fr'
@@ -13,6 +15,17 @@ if exist "%SolutionDir%Publish\Windows\ru\" powershell Remove-Item -Force -Recur
if exist "%SolutionDir%Publish\Windows\zh-Hans\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\Windows\zh-Hans'
if exist "%SolutionDir%Publish\Windows\zh-Hant\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\Windows\zh-Hant'
+if exist "%SolutionDir%Publish\WindowsPrerelease\en-US\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\en-US'
+if exist "%SolutionDir%Publish\WindowsPrerelease\de\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\de'
+if exist "%SolutionDir%Publish\WindowsPrerelease\es\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\es'
+if exist "%SolutionDir%Publish\WindowsPrerelease\fr\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\fr'
+if exist "%SolutionDir%Publish\WindowsPrerelease\it\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\it'
+if exist "%SolutionDir%Publish\WindowsPrerelease\ja\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\ja'
+if exist "%SolutionDir%Publish\WindowsPrerelease\ko\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\ko'
+if exist "%SolutionDir%Publish\WindowsPrerelease\ru\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\ru'
+if exist "%SolutionDir%Publish\WindowsPrerelease\zh-Hans\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\zh-Hans'
+if exist "%SolutionDir%Publish\WindowsPrerelease\zh-Hant\" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\zh-Hant'
+
echo Deleting extra runtime files
if exist "%SolutionDir%Publish\Windows\runtimes\linux-arm" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\Windows\runtimes\linux-arm'
if exist "%SolutionDir%Publish\Windows\runtimes\linux-arm64" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\Windows\runtimes\linux-arm64'
@@ -24,6 +37,19 @@ if exist "%SolutionDir%Publish\Windows\runtimes\osx-x64" powershell Remove-Item
if exist "%SolutionDir%Publish\Windows\runtimes\win-arm" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\Windows\runtimes\win-arm'
if exist "%SolutionDir%Publish\Windows\runtimes\win-arm64" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\Windows\runtimes\win-arm64'
+if exist "%SolutionDir%Publish\WindowsPrerelease\runtimes\linux-arm" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\runtimes\linux-arm'
+if exist "%SolutionDir%Publish\WindowsPrerelease\runtimes\linux-arm64" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\runtimes\linux-arm64'
+if exist "%SolutionDir%Publish\WindowsPrerelease\runtimes\linux-armel" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\runtimes\linux-armel'
+
+if exist "%SolutionDir%Publish\WindowsPrerelease\runtimes\osx" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\runtimes\osx'
+if exist "%SolutionDir%Publish\WindowsPrerelease\runtimes\osx-x64" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\runtimes\osx-x64'
+
+if exist "%SolutionDir%Publish\WindowsPrerelease\runtimes\win-arm" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\runtimes\win-arm'
+if exist "%SolutionDir%Publish\WindowsPrerelease\runtimes\win-arm64" powershell Remove-Item -Force -Recurse '%SolutionDir%Publish\WindowsPrerelease\runtimes\win-arm64'
+
echo Deleting misc files
if exist "%SolutionDir%Publish\Windows\web.config" del "%SolutionDir%Publish\Windows\web.config"
del "%SolutionDir%Publish\Windows\*pdb"
+
+if exist "%SolutionDir%Publish\WindowsPrerelease\web.config" del "%SolutionDir%Publish\WindowsPrerelease\web.config"
+del "%SolutionDir%Publish\WindowsPrerelease\*pdb"
diff --git a/Application/EventParsers/IW4EventParser.cs b/Application/EventParsers/IW4EventParser.cs
index d9cccdfa2..3bf836007 100644
--- a/Application/EventParsers/IW4EventParser.cs
+++ b/Application/EventParsers/IW4EventParser.cs
@@ -75,11 +75,6 @@ namespace Application.EventParsers
if (cleanedEventLine.Contains("InitGame"))
{
string dump = cleanedEventLine.Replace("InitGame: ", "");
- string[] values = dump.Split('\\', StringSplitOptions.RemoveEmptyEntries);
- var dict = new Dictionary();
-
- for (int i = 0; i < values.Length; i += 2)
- dict.Add(values[i], values[i + 1]);
return new GameEvent()
{
@@ -93,8 +88,8 @@ namespace Application.EventParsers
{
ClientId = 1
},
- Owner = server,
- Extra = dict
+ Owner = server,
+ Extra = dump.DictionaryFromKeyValue()
};
}
diff --git a/Application/EventParsers/T6MEventParser.cs b/Application/EventParsers/T6MEventParser.cs
index 07b6a4ceb..b26f5985e 100644
--- a/Application/EventParsers/T6MEventParser.cs
+++ b/Application/EventParsers/T6MEventParser.cs
@@ -73,11 +73,6 @@ namespace Application.EventParsers
if (lineSplit[0].Contains("InitGame"))
{
string dump = cleanedEventLine.Replace("InitGame: ", "");
- string[] values = dump.Split('\\', StringSplitOptions.RemoveEmptyEntries);
- var dict = new Dictionary();
-
- for (int i = 0; i < values.Length; i += 2)
- dict.Add(values[i], values[i + 1]);
return new GameEvent()
{
@@ -92,7 +87,7 @@ namespace Application.EventParsers
ClientId = 1
},
Owner = server,
- Extra = dict
+ Extra = dump.DictionaryFromKeyValue()
};
}
diff --git a/Application/Localization/Configure.cs b/Application/Localization/Configure.cs
index 77c7a40cb..78e7c7c64 100644
--- a/Application/Localization/Configure.cs
+++ b/Application/Localization/Configure.cs
@@ -11,16 +11,17 @@ namespace IW4MAdmin.Application.Localization
{
public static void Initialize()
{
- string currentLocal = CultureInfo.CurrentCulture.Name;
+ string currentLocale = Program.ServerManager.GetApplicationSettings().Configuration().CustomLocale ??
+ CultureInfo.CurrentCulture.Name.Substring(0, 2);
#if DEBUG
// currentLocal = "ru-RU";
#endif
- string localizationFile = $"Localization{Path.DirectorySeparatorChar}IW4MAdmin.{currentLocal}.json";
+ string localizationFile = $"Localization{Path.DirectorySeparatorChar}IW4MAdmin.{currentLocale}-{currentLocale.ToUpper()}.json";
string localizationContents;
if (File.Exists(localizationFile))
{
- localizationContents = File.ReadAllText(localizationFile, Encoding.UTF8);
+ localizationContents = File.ReadAllText(localizationFile, Encoding.UTF8);
}
else
diff --git a/Application/Localization/IW4MAdmin.en-US.json b/Application/Localization/IW4MAdmin.en-US.json
index b9ad8c23a..84dd43c9b 100644
--- a/Application/Localization/IW4MAdmin.en-US.json
+++ b/Application/Localization/IW4MAdmin.en-US.json
@@ -7,6 +7,9 @@
"MANAGER_VERSION_SUCCESS": "IW4MAdmin is up to date",
"MANAGER_INIT_FAIL": "Fatal error during initialization",
"MANAGER_EXIT": "Press any key to exit...",
+ "MANAGER_SHUTDOWN_SUCCESS": "Shutdown complete",
+ "MANAGER_MONITORING_TEXT": "Now monitoring",
+ "MANAGER_CONNECTION_REST": "Connection has been reestablished with",
"SETUP_ENABLE_WEBFRONT": "Enable webfront",
"SETUP_ENABLE_MULTIOWN": "Enable multiple owners",
"SETUP_ENABLE_STEPPEDPRIV": "Enable stepped privilege hierarchy",
@@ -18,11 +21,25 @@
"SETUP_IPHUB_KEY": "Enter iphub.info api key",
"SETUP_DISPLAY_DISCORD": "Display discord link on webfront",
"SETUP_DISCORD_INVITE": "Enter discord invite link",
- "SETUP_SERVER_USET6M": "Use T6M parser",
+ "SETUP_SERVER_USET6M": "Use Pluto T6 parser",
+ "SETUP_SERVER_USEIW5M": "Use Pluto IW5 Parser",
+ "SETUP_SERVER_MANUALLOG": "Enter manual log file path",
"SETUP_SERVER_IP": "Enter server IP Address",
"SETUP_SERVER_PORT": "Enter server port",
"SETUP_SERVER_RCON": "Enter server RCon password",
"SETUP_SERVER_SAVE": "Configuration saved, add another",
+ "SERVER_ERROR_DNE": "does not exist",
+ "SERVER_ERROR_LOG": "Invalid game log file",
+ "SERVER_ERROR_COMMAND_INGAME": "An internal error occured while processing your command",
+ "SERVER_ERROR_COMMAND_LOG": "command generated an error",
+ "SERVER_ERROR_UNFIXABLE": "Not monitoring server due to uncorrectable errors",
+ "SERVER_ERROR_DVAR": "Could not get the dvar value for",
+ "SERVER_ERROR_DVAR_HELP": "ensure the server has a map loaded",
+ "SERVER_ERROR_PLUGIN": "An error occured loading plugin",
+ "SERVER_ERROR_ADDPLAYER": "Unable to add player",
+ "SERVER_ERROR_POLLING": "reducing polling rate",
+ "SERVER_ERROR_COMMUNICATION": "Could not communicate with",
+ "SERVER_ERROR_EXCEPTION": "Unexpected exception on",
"SERVER_KICK_VPNS_NOTALLOWED": "VPNs are not allowed on this server",
"SERVER_KICK_TEXT": "You were kicked",
"SERVER_KICK_MINNAME": "Your name must contain at least 3 characters",
@@ -36,7 +53,7 @@
"SERVER_BAN_APPEAL": "appeal at",
"SERVER_REPORT_COUNT": "There are ^5{0} ^7recent reports",
"SERVER_WARNLIMT_REACHED": "Too many warnings",
- "SERVER_WARNING": "Warning",
+ "SERVER_WARNING": "WARNING",
"SERVER_WEBSITE_GENERIC": "this server's website",
"BROADCAST_ONLINE": "^5IW4MADMIN ^7is now ^2ONLINE",
"BROADCAST_OFFLINE": "IW4MAdmin is going offline",
@@ -104,6 +121,77 @@
"COMMANDS_PASSWORD_FAIL": "Your password must be at least 5 characters long",
"COMMANDS_PASSWORD_SUCCESS": "Your password has been set successfully",
"COMMANDS_PING_TARGET": "ping is",
- "COMMANDS_PING_SELF": "Your ping is"
+ "COMMANDS_PING_SELF": "Your ping is",
+ "COMMANDS_QUIT_DESC": "quit IW4MAdmin",
+ "COMMANDS_OWNER_DESC": "claim ownership of the server",
+ "COMMANDS_WARN_DESC": "warn client for infringing rules",
+ "COMMANDS_WARNCLEAR_DESC": "remove all warnings for a client",
+ "COMMANDS_KICK_DESC": "kick a client by name",
+ "COMMANDS_SAY_DESC": "broadcast message to all clients",
+ "COMMANDS_TEMPBAN_DESC": "temporarily ban a client for specified time (defaults to 1 hour)",
+ "COMMANDS_BAN_DESC": "permanently ban a client from the server",
+ "COMMANDS_UNBAN_DESC": "unban client by client id",
+ "COMMANDS_WHO_DESC": "give information about yourself",
+ "COMMANDS_LIST_DESC": "list active clients",
+ "COMMANDS_HELP_DESC": "list all available commands",
+ "COMMANDS_FASTRESTART_DESC": "fast restart current map",
+ "COMMANDS_MAPROTATE_DESC": "cycle to the next map in rotation",
+ "COMMANDS_SETLEVEL_DESC": "set client to specified privilege level",
+ "COMMANDS_USAGE_DESC": "get application memory usage",
+ "COMMANDS_USAGE_TEXT": "is using",
+ "COMMANDS_UPTIME_DESC": "get current application running time",
+ "COMMANDS_UPTIME_TEXT": "has been online for",
+ "COMMANDS_ADMINS_DESC": "list currently connected privileged clients",
+ "COMMANDS_MAP_DESC": "change to specified map",
+ "COMMANDS_FIND_DESC": "find client in database",
+ "COMMANDS_RULES_DESC": "list server rules",
+ "COMMANDS_PM_DESC": "send message to other client",
+ "COMMANDS_FLAG_DESC": "flag a suspicious client and announce to admins on join",
+ "COMMANDS_REPORT_DESC": "report a client for suspicious behavior",
+ "COMMANDS_REPORTS_DESC": "get or clear recent reports",
+ "COMMANDS_MASK_DESC": "hide your presence as a privileged client",
+ "COMMANDS_BANINFO_DESC": "get information about a ban for a client",
+ "COMMANDS_ALIAS_DESC": "get past aliases and ips of a client",
+ "COMMANDS_RCON_DESC": "send rcon command to server",
+ "COMMANDS_PLUGINS_DESC": "view all loaded plugins",
+ "COMMANDS_IP_DESC": "view your external IP address",
+ "COMMANDS_PRUNE_DESC": "demote any privileged clients that have not connected recently (defaults to 30 days)",
+ "COMMANDS_SETPASSWORD_DESC": "set your authentication password",
+ "COMMANDS_PING_DESC": "get client's ping",
+ "COMMANDS_ARGS_PLAYER": "player",
+ "COMMANDS_ARGS_REASON": "reason",
+ "COMMANDS_ARGS_MESSAGE": "message",
+ "COMMANDS_ARGS_DURATION": "duration (m|h|d|w|y)",
+ "COMMANDS_ARGS_CLIENTID": "client id",
+ "COMMANDS_ARGS_COMMANDS": "commands",
+ "COMMANDS_ARGS_LEVEL": "level",
+ "COMMANDS_ARGS_MAP": "map",
+ "COMMANDS_ARGS_CLEAR": "clear",
+ "COMMANDS_ARGS_INACTIVE": "inactive days",
+ "COMMANDS_ARGS_PASSWORD": "password",
+ "PLUGINS_LOGIN_COMMANDS_LOGIN_DESC": "login using password",
+ "PLUGINS_LOGIN_COMMANDS_LOGIN_SUCCESS": "You are now logged in",
+ "PLUGINS_LOGIN_COMMANDS_LOGIN_FAIL": "Your password is incorrect",
+ "PLUGINS_STATS_COMMANDS_RESET_DESC": "reset your stats to factory-new",
+ "PLUGINS_STATS_COMMANDS_RESET_SUCCESS": "Your stats for this server have been reset",
+ "PLUGINS_STATS_COMMANDS_RESET_FAIL": "You must be connected to a server to reset your stats",
+ "PLUGINS_STATS_COMMANDS_VIEW_DESC": "view your stats",
+ "PLUGINS_STATS_COMMANDS_VIEW_FAIL_INGAME": "The specified player must be ingame",
+ "PLUGINS_STATS_COMMANDS_VIEW_FAIL_INGAME_SELF": "You must be ingame to view your stats",
+ "PLUGINS_STATS_COMMANDS_VIEW_FAIL": "Cannot find the player you specified",
+ "PLUGINS_STATS_COMMANDS_VIEW_SUCCESS": "Stats for",
+ "PLUGINS_STATS_COMMANDS_TOP_DESC": "view the top 5 players in this server",
+ "PLUGINS_STATS_COMMANDS_TOP_TEXT": "Top Players",
+ "PLUGINS_STATS_TEXT_KILLS": "KILLS",
+ "PLUGINS_STATS_TEXT_DEATHS": "DEATHS",
+ "PLUGINS_STATS_TEXT_SKILL": "SKILL",
+ "GLOBAL_DAYS": "days",
+ "GLOBAL_HOURS": "hours",
+ "GLOBAL_MINUTES": "minutes",
+ "GLOBAL_REPORT": "If you suspect someone of ^5CHEATING ^7use the ^5!report ^7command",
+ "GLOBAL_ERROR": "Error",
+ "GLOBAL_WARNING": "Warning",
+ "GLOBAL_INFO": "Info",
+ "GLOBAL_VERBOSE": "Verbose"
}
}
\ No newline at end of file
diff --git a/Application/Localization/IW4MAdmin.es-ES.json b/Application/Localization/IW4MAdmin.es-ES.json
new file mode 100644
index 000000000..490a50582
--- /dev/null
+++ b/Application/Localization/IW4MAdmin.es-ES.json
@@ -0,0 +1,197 @@
+{
+ "LocalizationName": "es-ES",
+ "LocalizationSet": {
+ "MANAGER_VERSION_FAIL": "No se ha podido conseguir la última versión de IW4MAdmin",
+ "MANAGER_VERSION_UPDATE": "tiene una actualización. La última versión es",
+ "MANAGER_VERSION_CURRENT": "Tu versión es",
+ "MANAGER_VERSION_SUCCESS": "IW4MAdmin está actualizado",
+ "MANAGER_INIT_FAIL": "Error fatal durante la inicialización",
+ "MANAGER_EXIT": "Presione cualquier tecla para salir...",
+ "MANAGER_SHUTDOWN_SUCCESS": "Apagado completo",
+ "MANAGER_MONITORING_TEXT": "Ahora monitoreando",
+ "MANAGER_CONNECTION_REST": "La conexión ha sido restablecida con",
+ "SETUP_ENABLE_WEBFRONT": "Habilitar frente de la web",
+ "SETUP_ENABLE_MULTIOWN": "Habilitar múltiples propietarios",
+ "SETUP_ENABLE_STEPPEDPRIV": "Habilitar jerarquía de privilegios por escalones",
+ "SETUP_ENABLE_CUSTOMSAY": "Habilitar nombre a decir personalizado",
+ "SETUP_SAY_NAME": "Ingresar nombre a decir personalizado",
+ "SETUP_USE_CUSTOMENCODING": "Usar analizador de codificación personalizado",
+ "SETUP_ENCODING_STRING": "Ingresar cadena de codificación",
+ "SETUP_ENABLE_VPNS": "Habilitar VPNs clientes",
+ "SETUP_IPHUB_KEY": "Ingresar clave api de iphub.info",
+ "SETUP_DISPLAY_DISCORD": "Mostrar link de Discord en frente de la web",
+ "SETUP_DISCORD_INVITE": "Ingresar link de invitación a discord",
+ "SETUP_SERVER_USET6M": "Usar analizador Pluto T6",
+ "SETUP_SERVER_USEIW5M": "Usar analizador Pluto IW5",
+ "SETUP_SERVER_MANUALLOG": "Ingresar manualmente la ruta del archivo de registro",
+ "SETUP_SERVER_IP": "Ingresar Dirección IP del servidor",
+ "SETUP_SERVER_PORT": "Ingresar puerto del servidor",
+ "SETUP_SERVER_RCON": "Ingresar contraseña RCon del servidor",
+ "SETUP_SERVER_SAVE": "Configuración guardada, añadir otra",
+ "SERVER_ERROR_DNE": "No existe",
+ "SERVER_ERROR_LOG": "Archivo de registro del juego invalido",
+ "SERVER_ERROR_COMMAND_INGAME": "Un error interno ocurrió mientras se procesaba tu comando",
+ "SERVER_ERROR_COMMAND_LOG": "Comando generó error",
+ "SERVER_ERROR_UNFIXABLE": "No se está supervisando el servidor debido a errores incorregibles",
+ "SERVER_ERROR_DVAR": "No se pudo obtener el valor dvar",
+ "SERVER_ERROR_DVAR_HELP": "asegúrate de que el servidor tenga un mapa cargado",
+ "SERVER_ERROR_PLUGIN": "Un error ocurrió mientras se cargaba el complemente",
+ "SERVER_ERROR_ADDPLAYER": "Incapaz de añadir al jugador",
+ "SERVER_ERROR_POLLING": "reduciendo la tasa de sondeo",
+ "SERVER_ERROR_COMMUNICATION": "No se ha podido comunicar con",
+ "SERVER_ERROR_EXCEPTION": "Excepción inesperada en",
+ "SERVER_KICK_VPNS_NOTALLOWED": "Las VPNs no están permitidas en este servidor",
+ "SERVER_KICK_TEXT": "Fuiste expulsado",
+ "SERVER_KICK_MINNAME": "Tu nombre debe contener al menos 3 caracteres",
+ "SERVER_KICK_NAME_INUSE": "Tu nombre está siendo usado por alguien más",
+ "SERVER_KICK_GENERICNAME": "Por favor cambia tu nombre usando /name",
+ "SERVER_KICK_CONTROLCHARS": "Tu nombre no puede contener caracteres de control",
+ "SERVER_TB_TEXT": "Estás temporalmente baneado",
+ "SERVER_TB_REMAIN": "Tú estás temporalmente baneado",
+ "SERVER_BAN_TEXT": "Estás baneado",
+ "SERVER_BAN_PREV": "Baneado anteriormente por",
+ "SERVER_BAN_APPEAL": "apela en",
+ "SERVER_REPORT_COUNT": "Hay ^5{0} ^7reportes recientes",
+ "SERVER_WARNLIMT_REACHED": "Muchas advertencias",
+ "SERVER_WARNING": "ADVERTENCIA",
+ "SERVER_WEBSITE_GENERIC": "el sitio web de este servidor",
+ "BROADCAST_ONLINE": "^5IW4MADMIN ^7está ahora ^2en línea",
+ "BROADCAST_OFFLINE": "IW4MAdmin está desconectado",
+ "COMMAND_HELP_SYNTAX": "sintaxis:",
+ "COMMAND_HELP_OPTIONAL": "opcional",
+ "COMMAND_UNKNOWN": "Has ingresado un comando desconocido",
+ "COMMAND_NOACCESS": "Tú no tienes acceso a ese comando",
+ "COMMAND_NOTAUTHORIZED": "Tú no estás autorizado para ejecutar ese comando",
+ "COMMAND_MISSINGARGS": "No se han proporcionado suficientes argumentos",
+ "COMMAND_TARGET_MULTI": "Múltiples jugadores coinciden con ese nombre",
+ "COMMAND_TARGET_NOTFOUND": "No se puede encontrar el jugador especificado",
+ "PLUGIN_IMPORTER_NOTFOUND": "No se encontraron complementos para cargar",
+ "PLUGIN_IMPORTER_REGISTERCMD": "Comando registrado",
+ "COMMANDS_OWNER_SUCCESS": "¡Felicidades, has reclamado la propiedad de este servidor!",
+ "COMMANDS_OWNER_FAIL": "Este servidor ya tiene un propietario",
+ "COMMANDS_WARN_FAIL": "No tiene los privilegios necesarios para advertir a",
+ "COMMANDS_WARNCLEAR_SUCCESS": "Todas las advertencias borradas para",
+ "COMMANDS_KICK_SUCCESS": "ha sido expulsado",
+ "COMMANDS_KICK_FAIL": "No tienes los privilegios necesarios para expulsar a",
+ "COMMANDS_TEMPBAN_SUCCESS": "ha sido baneado temporalmente por",
+ "COMMANDS_TEMPBAN_FAIL": "Tú no puedes banear temporalmente",
+ "COMMANDS_BAN_SUCCESS": "ha sido baneado permanentemente",
+ "COMMANDS_BAN_FAIL": "Tú no puedes banear",
+ "COMMANDS_UNBAN_SUCCESS": "Exitosamente desbaneado",
+ "COMMANDS_UNBAN_FAIL": "no está baneado",
+ "COMMANDS_HELP_NOTFOUND": "No se ha podido encontrar ese comando",
+ "COMMANDS_HELP_MOREINFO": "Escribe !help para obtener la sintaxis de uso del comando",
+ "COMMANDS_FASTRESTART_UNMASKED": "ha dado rápido reinicio al mapa",
+ "COMMANDS_FASTRESTART_MASKED": "Al mapa se le ha dado un reinicio rápido",
+ "COMMANDS_MAPROTATE": "Rotación de mapa en ^55 ^7segundos",
+ "COMMANDS_SETLEVEL_SELF": "No puedes cambiar tu propio nivel",
+ "COMMANDS_SETLEVEL_OWNER": "Solo puede haber un propietario. Modifica tu configuración si múltiples propietarios son requeridos",
+ "COMMANDS_SETLEVEL_STEPPEDDISABLED": "Este servidor no te permite promover",
+ "COMMANDS_SETLEVEL_LEVELTOOHIGH": "Tú solo puedes promover ^5{0} ^7a ^5{1} ^7o menor privilegio",
+ "COMMANDS_SETLEVEL_SUCCESS_TARGET": "¡Felicitaciones! has ha sido promovido a",
+ "COMMANDS_SETLEVEL_SUCCESS": "fue promovido con éxito",
+ "COMMANDS_SETLEVEL_FAIL": "Grupo inválido especificado",
+ "COMMANDS_ADMINS_NONE": "No hay administradores visibles en línea",
+ "COMMANDS_MAP_SUCCESS": "Cambiando al mapa",
+ "COMMANDS_MAP_UKN": "Intentando cambiar a un mapa desconocido",
+ "COMMANDS_FIND_MIN": "Por Favor introduzca al menos 3 caracteres",
+ "COMMANDS_FIND_EMPTY": "No se encontraron jugadores",
+ "COMMANDS_RULES_NONE": "El propietario del servidor no ha establecido ninguna regla",
+ "COMMANDS_FLAG_SUCCESS": "Has marcado a",
+ "COMMANDS_FLAG_UNFLAG": "Has desmarcado a",
+ "COMMANDS_FLAG_FAIL": "Tú no puedes marcar",
+ "COMMANDS_REPORT_FAIL_CAMP": "No puedes reportar a un jugador por campear",
+ "COMMANDS_REPORT_FAIL_DUPLICATE": "Ya has reportado a este jugador",
+ "COMMANDS_REPORT_FAIL_SELF": "No puedes reportarte a ti mismo",
+ "COMMANDS_REPORT_FAIL": "Tú no puedes reportar",
+ "COMMANDS_REPORT_SUCCESS": "Gracias por su reporte, un administrador ha sido notificado",
+ "COMMANDS_REPORTS_CLEAR_SUCCESS": "Reportes borrados con éxito",
+ "COMMANDS_REPORTS_NONE": "No hay jugadores reportados aun",
+ "COMMANDS_MASK_ON": "Ahora estás enmascarado",
+ "COMMANDS_MASK_OFF": "Ahora estás desenmascarado",
+ "COMMANDS_BANINFO_NONE": "No se encontró ban activo para ese jugador",
+ "COMMANDS_BANINO_SUCCESS": "fue baneado por ^5{0} ^7debido a:",
+ "COMMANDS_ALIAS_ALIASES": "Aliases",
+ "COMMANDS_ALIAS_IPS": "IPs",
+ "COMMANDS_RCON_SUCCESS": "Exitosamente enviado el comando RCon",
+ "COMMANDS_PLUGINS_LOADED": "Complementos cargados",
+ "COMMANDS_IP_SUCCESS": "Tu IP externa es",
+ "COMMANDS_PRUNE_FAIL": "Número inválido de días inactivos",
+ "COMMANDS_PRUNE_SUCCESS": "los usuarios privilegiados inactivos fueron podados",
+ "COMMANDS_PASSWORD_FAIL": "Tu contraseña debe tener al menos 5 caracteres de largo",
+ "COMMANDS_PASSWORD_SUCCESS": "Su contraseña ha sido establecida con éxito",
+ "COMMANDS_PING_TARGET": "ping es",
+ "COMMANDS_PING_SELF": "Tu ping es",
+ "COMMANDS_QUIT_DESC": "salir de IW4MAdmin",
+ "COMMANDS_OWNER_DESC": "reclamar la propiedad del servidor",
+ "COMMANDS_WARN_DESC": "advertir al cliente por infringir las reglas",
+ "COMMANDS_WARNCLEAR_DESC": "eliminar todas las advertencias de un cliente",
+ "COMMANDS_KICK_DESC": "expulsar a un cliente por su nombre",
+ "COMMANDS_SAY_DESC": "transmitir el mensaje a todos los clientes",
+ "COMMANDS_TEMPBAN_DESC": "banear temporalmente a un cliente por el tiempo especificado (predeterminado en 1 hora)",
+ "COMMANDS_BAN_DESC": "banear permanentemente un cliente del servidor",
+ "COMMANDS_UNBAN_DESC": "desbanear al cliente por ID",
+ "COMMANDS_WHO_DESC": "da información sobre ti",
+ "COMMANDS_LIST_DESC": "enlistar clientes activos",
+ "COMMANDS_HELP_DESC": "enlistar todos los comandos disponibles",
+ "COMMANDS_FASTRESTART_DESC": "dar reinicio rápido al mapa actial",
+ "COMMANDS_MAPROTATE_DESC": "pasar al siguiente mapa en rotación",
+ "COMMANDS_SETLEVEL_DESC": "establecer el cliente al nivel de privilegio especificado",
+ "COMMANDS_USAGE_DESC": "obtener uso de la memoria de la aplicación",
+ "COMMANDS_USAGE_TEXT": "está usando",
+ "COMMANDS_UPTIME_DESC": "obtener el tiempo de ejecución de la aplicación actual",
+ "COMMANDS_UPTIME_TEXT": "ha estado en línea por",
+ "COMMANDS_ADMINS_DESC": "enlistar clientes privilegiados actualmente conectados",
+ "COMMANDS_MAP_DESC": "cambiar al mapa especificado",
+ "COMMANDS_FIND_DESC": "encontrar cliente en la base de datos",
+ "COMMANDS_RULES_DESC": "enlistar reglas del servidor",
+ "COMMANDS_PM_DESC": "enviar mensaje a otro cliente",
+ "COMMANDS_FLAG_DESC": "marcar un cliente sospechoso y anunciar a los administradores al unirse",
+ "COMMANDS_REPORT_DESC": "reportar un cliente por comportamiento sospechoso",
+ "COMMANDS_REPORTS_DESC": "obtener o borrar informes recientes",
+ "COMMANDS_MASK_DESC": "esconde tu presencia como un cliente privilegiado",
+ "COMMANDS_BANINFO_DESC": "obtener información sobre el ban de un cliente",
+ "COMMANDS_ALIAS_DESC": "obtener alias e ips anteriores de un cliente",
+ "COMMANDS_RCON_DESC": "enviar el comando rcon al servidor",
+ "COMMANDS_PLUGINS_DESC": "ver todos los complementos cargados",
+ "COMMANDS_IP_DESC": "ver tu dirección IP externa",
+ "COMMANDS_PRUNE_DESC": "degradar a los clientes con privilegios que no se hayan conectado recientemente (el valor predeterminado es 30 días)",
+ "COMMANDS_SETPASSWORD_DESC": "configura tu contraseña de autenticación",
+ "COMMANDS_PING_DESC": "obtener ping del cliente",
+ "COMMANDS_ARGS_PLAYER": "jugador",
+ "COMMANDS_ARGS_REASON": "razón",
+ "COMMANDS_ARGS_MESSAGE": "mensaje",
+ "COMMANDS_ARGS_DURATION": "duración (m|h|d|w|y)",
+ "COMMANDS_ARGS_CLIENTID": "id del cliente",
+ "COMMANDS_ARGS_COMMANDS": "comandos",
+ "COMMANDS_ARGS_LEVEL": "nivel",
+ "COMMANDS_ARGS_MAP": "mapa",
+ "COMMANDS_ARGS_CLEAR": "borrar",
+ "COMMANDS_ARGS_INACTIVE": "días inactivo",
+ "COMMANDS_ARGS_PASSWORD": "contraseña",
+ "PLUGINS_LOGIN_COMMANDS_LOGIN_DESC": "iniciar sesión usando la contraseña",
+ "PLUGINS_LOGIN_COMMANDS_LOGIN_SUCCESS": "Ahora está conectado",
+ "PLUGINS_LOGIN_COMMANDS_LOGIN_FAIL": "tu contraseña es incorrecta",
+ "PLUGINS_STATS_COMMANDS_RESET_DESC": "restablece tus estadísticas a las nuevas de fábrica",
+ "PLUGINS_STATS_COMMANDS_RESET_SUCCESS": "Tus estadísticas para este servidor se han restablecido",
+ "PLUGINS_STATS_COMMANDS_RESET_FAIL": "Debes estar conectado a un servidor para restablecer tus estadísticas",
+ "PLUGINS_STATS_COMMANDS_VIEW_DESC": "ver tus estadísticas",
+ "PLUGINS_STATS_COMMANDS_VIEW_FAIL_INGAME": "El jugador especificado debe estar dentro del juego",
+ "PLUGINS_STATS_COMMANDS_VIEW_FAIL_INGAME_SELF": "Debes estar dentro del juego para ver tus estadísticas",
+ "PLUGINS_STATS_COMMANDS_VIEW_FAIL": "No se puede encontrar el jugador que especificó",
+ "PLUGINS_STATS_COMMANDS_VIEW_SUCCESS": "Estadísticas para",
+ "PLUGINS_STATS_COMMANDS_TOP_DESC": "ver los 5 mejores jugadores en este servidor",
+ "PLUGINS_STATS_COMMANDS_TOP_TEXT": "Mejores Jugadores",
+ "PLUGINS_STATS_TEXT_KILLS": "Asesinatos",
+ "PLUGINS_STATS_TEXT_DEATHS": "Muertes",
+ "PLUGINS_STATS_TEXT_SKILL": "Habilidad",
+ "GLOBAL_DAYS": "días",
+ "GLOBAL_HOURS": "horas",
+ "GLOBAL_MINUTES": "minutos",
+ "GLOBAL_REPORT": "Si sospechas que alguien ^5usa cheats ^7usa el comando ^5!report",
+ "GLOBAL_ERROR": "Error",
+ "GLOBAL_WARNING": "Advertencia",
+ "GLOBAL_INFO": "Información",
+ "GLOBAL_VERBOSE": "Detallado"
+ }
+}
\ No newline at end of file
diff --git a/Application/Localization/IW4MAdmin.ru-RU.json b/Application/Localization/IW4MAdmin.ru-RU.json
index 01b5f9663..da10739e1 100644
--- a/Application/Localization/IW4MAdmin.ru-RU.json
+++ b/Application/Localization/IW4MAdmin.ru-RU.json
@@ -2,29 +2,31 @@
"LocalizationName": "ru-RU",
"LocalizationSet": {
"MANAGER_VERSION_FAIL": "Не удалось получить последнюю версию IW4MAdmin",
- "MANAGER_VERSION_UPDATE": "имеет обновление. Последняя версия",
- "MANAGER_VERSION_CURRENT": "Ваша версия",
+ "MANAGER_VERSION_UPDATE": "- есть обновление. Последняя версия:",
+ "MANAGER_VERSION_CURRENT": "Ваша версия:",
"MANAGER_VERSION_SUCCESS": "IW4MAdmin обновлен",
- "MANAGER_INIT_FAIL": "Неустранимая ошибка при инициализации",
- "MANAGER_EXIT": "Нажмите любую клавишу чтобы выйти ...",
+ "MANAGER_INIT_FAIL": "Критическая ошибка во время инициализации",
+ "MANAGER_EXIT": "Нажмите любую клавишу, чтобы выйти...",
"SETUP_ENABLE_WEBFRONT": "Включить веб-интерфейс",
"SETUP_ENABLE_MULTIOWN": "Включить поддержку нескольких владельцев",
"SETUP_ENABLE_STEPPEDPRIV": "Включить последовательную иерархию прав",
- "SETUP_ENABLE_CUSTOMSAY": "Включить серверное имя для чата",
- "SETUP_SAY_NAME": "Введите серверное имя для чата",
- "SETUP_USE_CUSTOMENCODING": "Использовать иную кодировку текста",
- "SETUP_ENCODING_STRING": "Введите желаемую кодировку",
- "SETUP_ENABLE_VPNS": "Разрешить игрокам подключаться с VPN",
+ "SETUP_ENABLE_CUSTOMSAY": "Включить кастомное имя для чата",
+ "SETUP_SAY_NAME": "Введите кастомное имя для чата",
+ "SETUP_USE_CUSTOMENCODING": "Использовать кастомную кодировку парсера",
+ "SETUP_ENCODING_STRING": "Введите кодировку",
+ "SETUP_ENABLE_VPNS": "Включить поддержку VPN у игроков",
"SETUP_IPHUB_KEY": "Введите iphub.info api-ключ",
"SETUP_DISPLAY_DISCORD": "Отображать ссылку на Discord в веб-интерфейсе",
"SETUP_DISCORD_INVITE": "Введите ссылку-приглашение в Discord",
- "SETUP_SERVER_USET6M": "Использовать T6M парсер для Black Ops 2",
+ "SETUP_SERVER_USET6M": "Использовать Pluto T6 парсер",
+ "SETUP_SERVER_USEIW5M": "Использовать парсер Pluto IW5",
+ "SETUP_SERVER_MANUALLOG": "Введите путь для лог-файла",
"SETUP_SERVER_IP": "Введите IP-адрес сервера",
- "SETUP_SERVER_PORT": "введите порт сервера",
+ "SETUP_SERVER_PORT": "Введите порт сервера",
"SETUP_SERVER_RCON": "Введите RCon пароль сервера",
- "SETUP_SERVER_SAVE": "Конфигурация сохранена, добавить еще?",
+ "SETUP_SERVER_SAVE": "Настройки сохранены, добавить",
"SERVER_KICK_VPNS_NOTALLOWED": "Использование VPN не разрешено на этом сервере",
- "SERVER_KICK_TEXT": "Вы исключены",
+ "SERVER_KICK_TEXT": "Вы были исключены",
"SERVER_KICK_MINNAME": "Ваше имя должно содержать хотя бы 3 символа",
"SERVER_KICK_NAME_INUSE": "Ваше имя используется кем-то другим",
"SERVER_KICK_GENERICNAME": "Пожалуйста, смените ваше имя, используя /name",
@@ -36,42 +38,42 @@
"SERVER_BAN_APPEAL": "оспорить:",
"SERVER_REPORT_COUNT": "Имеется ^5{0} ^7жалоб за последнее время",
"SERVER_WARNLIMT_REACHED": "Слишком много предупреждений",
- "SERVER_WARNING": "предупреждение",
+ "SERVER_WARNING": "Предупреждение",
"SERVER_WEBSITE_GENERIC": "веб-сайт этого сервера",
- "BROADCAST_ONLINE": "^5IW4MADMIN ^7сейчас ^2ОНЛАЙН",
+ "BROADCAST_ONLINE": "^5IW4MADMIN ^7сейчас ^В СЕТИ",
"BROADCAST_OFFLINE": "IW4MAdmin отключается",
"COMMAND_HELP_SYNTAX": "синтаксис:",
"COMMAND_HELP_OPTIONAL": "опционально",
"COMMAND_UNKNOWN": "Вы ввели неизвестную команду",
"COMMAND_NOACCESS": "У вас нет доступа к этой команде",
- "COMMAND_NOTAUTHORIZED": "У вас нет разрешения выполнить эту команду",
- "COMMAND_MISSINGARGS": "Приведено недостаточно аргументов",
- "COMMAND_TARGET_MULTI": "Это имя использует не один игрок",
+ "COMMAND_NOTAUTHORIZED": "Вы не авторизованы для исполнения этой команды",
+ "COMMAND_MISSINGARGS": "Недостаточно аргументов приведено",
+ "COMMAND_TARGET_MULTI": "Несколько игроков соответствуют этому имени",
"COMMAND_TARGET_NOTFOUND": "Невозможно найти указанного игрока",
- "PLUGIN_IMPORTER_NOTFOUND": "Нет загружаемых плагинов",
+ "PLUGIN_IMPORTER_NOTFOUND": "Не найдено плагинов для загрузки",
"PLUGIN_IMPORTER_REGISTERCMD": "Зарегистрированная команда",
- "COMMANDS_OWNER_SUCCESS": "Поздравляем, Вы стали владельцем этого сервера!",
+ "COMMANDS_OWNER_SUCCESS": "Поздравления, вы утвердили владение этим сервером!",
"COMMANDS_OWNER_FAIL": "Этот сервер уже имеет владельца",
- "COMMANDS_WARN_FAIL": "У вас недостаточно прав чтобы предупреждать!",
+ "COMMANDS_WARN_FAIL": "У вас недостаточно прав, чтобы выносить предупреждения",
"COMMANDS_WARNCLEAR_SUCCESS": "Все предупреждения очищены за",
"COMMANDS_KICK_SUCCESS": "был исключен",
- "COMMANDS_KICK_FAIL": "У вас недостаточно прав чтобы исключать!",
+ "COMMANDS_KICK_FAIL": "У вас нет достаточных прав, чтобы исключать",
"COMMANDS_TEMPBAN_SUCCESS": "был временно забанен за",
- "COMMANDS_TEMPBAN_FAIL": "Вы не можете временно банить!",
+ "COMMANDS_TEMPBAN_FAIL": "Вы не можете выдавать временный бан",
"COMMANDS_BAN_SUCCESS": "был забанен навсегда",
- "COMMANDS_BAN_FAIL": "Вы не можете банить!",
+ "COMMANDS_BAN_FAIL": "Вы не можете выдавать бан",
"COMMANDS_UNBAN_SUCCESS": "Успешно разбанен",
"COMMANDS_UNBAN_FAIL": "не забанен",
"COMMANDS_HELP_NOTFOUND": "Не удалось найти эту команду",
- "COMMANDS_HELP_MOREINFO": "Введите !help <имя команды>, чтобы узнать синтаксис команды",
- "COMMANDS_FASTRESTART_UNMASKED": "перезапуск карты",
- "COMMANDS_FASTRESTART_MASKED": "Карта перезапущена",
+ "COMMANDS_HELP_MOREINFO": "Введите !help <имя команды>, чтобы узнать синтаксис для использования команды",
+ "COMMANDS_FASTRESTART_UNMASKED": "перезапустил карту",
+ "COMMANDS_FASTRESTART_MASKED": "Карта была перезапущена",
"COMMANDS_MAPROTATE": "Смена карты через ^55 ^7секунд",
"COMMANDS_SETLEVEL_SELF": "Вы не можете изменить свой уровень",
- "COMMANDS_SETLEVEL_OWNER": "Возможен только 1 владелец. Включите возможность нескольких владельцев!",
+ "COMMANDS_SETLEVEL_OWNER": "Может быть только 1 владелец. Измените настройки, если требуется несколько владельцов",
"COMMANDS_SETLEVEL_STEPPEDDISABLED": "Этот сервер не разрешает вам повыситься",
"COMMANDS_SETLEVEL_LEVELTOOHIGH": "Вы только можете повысить ^5{0} ^7до ^5{1} ^7или понизиться в правах",
- "COMMANDS_SETLEVEL_SUCCESS_TARGET": "Поздравляем! Вы были повышены до",
+ "COMMANDS_SETLEVEL_SUCCESS_TARGET": "Поздравления! Вы были повышены до",
"COMMANDS_SETLEVEL_SUCCESS": "был успешно повышен",
"COMMANDS_SETLEVEL_FAIL": "Указана неверная группа",
"COMMANDS_ADMINS_NONE": "Нет администраторов в сети",
@@ -88,22 +90,108 @@
"COMMANDS_REPORT_FAIL_SELF": "Вы не можете пожаловаться на самого себя",
"COMMANDS_REPORT_FAIL": "Вы не можете пожаловаться",
"COMMANDS_REPORT_SUCCESS": "Спасибо за вашу жалобу, администратор оповещен",
- "COMMANDS_REPORTS_CLEAR_SUCCESS": "Жалобы полностью очищены",
+ "COMMANDS_REPORTS_CLEAR_SUCCESS": "Жалобы успешно очищены",
"COMMANDS_REPORTS_NONE": "Пока нет жалоб на игроков",
- "COMMANDS_MASK_ON": "Вы замаскированы",
- "COMMANDS_MASK_OFF": "Маскировка снята",
- "COMMANDS_BANINFO_NONE": "Нет активного запрета для этого игрока",
- "COMMANDS_BANINO_SUCCESS": "был забанен ^5{0} ^7на:",
- "COMMANDS_ALIAS_ALIASES": "Псевдонимы",
+ "COMMANDS_MASK_ON": "Вы теперь замаскированы",
+ "COMMANDS_MASK_OFF": "Вы теперь демаскированы",
+ "COMMANDS_BANINFO_NONE": "Не найдено действующего бана для этого игрока",
+ "COMMANDS_BANINO_SUCCESS": "был забанен игроком ^5{0} ^7на:",
+ "COMMANDS_ALIAS_ALIASES": "Имена",
"COMMANDS_ALIAS_IPS": "IP",
- "COMMANDS_RCON_SUCCESS": " RCon команда успешно отправлена",
+ "COMMANDS_RCON_SUCCESS": "Успешно отправлена команда RCon",
"COMMANDS_PLUGINS_LOADED": "Загруженные плагины",
- "COMMANDS_IP_SUCCESS": "Ваш внешний IP-адрес",
- "COMMANDS_PRUNE_FAIL": "Недопустимое количество неактивных дней",
- "COMMANDS_PRUNE_SUCCESS": "неактивные привилегированные пользователи были разжалованы",
- "COMMANDS_PASSWORD_FAIL": "Ваш пароль должен содержать не менее 5 символов",
- "COMMANDS_PASSWORD_SUCCESS": "Ваш пароль успешно установлен",
- "COMMANDS_PING_TARGET": "пинг",
- "COMMANDS_PING_SELF": "Ваш пинг"
+ "COMMANDS_IP_SUCCESS": "Ваш внешний IP:",
+ "COMMANDS_PRUNE_FAIL": "Неверное количество дней бездействия",
+ "COMMANDS_PRUNE_SUCCESS": "бездействующих пользователей с правами было сокращено",
+ "COMMANDS_PASSWORD_FAIL": "Ваш пароль должен быть хотя бы 5 символов в длину",
+ "COMMANDS_PASSWORD_SUCCESS": "Ваш пароль был успешно установлен",
+ "COMMANDS_PING_TARGET": "пинг:",
+ "COMMANDS_PING_SELF": "Ваш пинг:",
+ "MANAGER_SHUTDOWN_SUCCESS": "Выключение завершено",
+ "MANAGER_MONITORING_TEXT": "Идет мониторинг",
+ "MANAGER_CONNECTION_REST": "Соединение было восстановлено с помощью",
+ "SERVER_ERROR_DNE": "не существует",
+ "SERVER_ERROR_LOG": "Неверный файл игрового лога",
+ "SERVER_ERROR_COMMAND_INGAME": "Произошла внутренняя ошибка при обработке вашей команды",
+ "SERVER_ERROR_COMMAND_LOG": "команда сгенерировала ошибку",
+ "SERVER_ERROR_UNFIXABLE": "Мониторинг сервера выключен из-за неисправимых ошибок",
+ "SERVER_ERROR_DVAR": "Не удалось получить значение dvar:",
+ "SERVER_ERROR_DVAR_HELP": "убедитесь, что на сервере загружена карта",
+ "SERVER_ERROR_PLUGIN": "Произошла ошибка загрузки плагина",
+ "SERVER_ERROR_ADDPLAYER": "Не удалось добавить игрока",
+ "SERVER_ERROR_POLLING": "снижение частоты обновления данных",
+ "SERVER_ERROR_COMMUNICATION": "Не удалось связаться с",
+ "SERVER_ERROR_EXCEPTION": "Неожиданное исключение на",
+ "COMMANDS_QUIT_DESC": "покинуть IW4MAdmin",
+ "COMMANDS_OWNER_DESC": "утверить владение сервером",
+ "COMMANDS_WARN_DESC": "предупредить игрока за нарушение правил",
+ "COMMANDS_WARNCLEAR_DESC": "удалить все предупреждения у игрока",
+ "COMMANDS_KICK_DESC": "исключить игрока по имени",
+ "COMMANDS_SAY_DESC": "транслировать сообщения всем игрокам",
+ "COMMANDS_TEMPBAN_DESC": "временно забанить игрока на определенное время (по умолчанию: 1 час)",
+ "COMMANDS_BAN_DESC": "навсегда забанить игрока на сервере",
+ "COMMANDS_UNBAN_DESC": "разбанить игрока по ID игрока",
+ "COMMANDS_WHO_DESC": "предоставить информацию о себе",
+ "COMMANDS_LIST_DESC": "перечислить действующих игроков",
+ "COMMANDS_HELP_DESC": "перечислить все доступные команды",
+ "COMMANDS_FASTRESTART_DESC": "перезапустить нынешнюю карту",
+ "COMMANDS_MAPROTATE_DESC": "переключиться на следующую карту в ротации",
+ "COMMANDS_SETLEVEL_DESC": "установить особый уровень прав игроку",
+ "COMMANDS_USAGE_DESC": "узнать о потреблении памяти приложением",
+ "COMMANDS_USAGE_TEXT": "используется",
+ "COMMANDS_UPTIME_DESC": "получить время с начала запуска текущего приложения",
+ "COMMANDS_UPTIME_TEXT": "был в сети",
+ "COMMANDS_ADMINS_DESC": "перечислить присоединенных на данный момент игроков с правами",
+ "COMMANDS_MAP_DESC": "сменить на определенную карту",
+ "COMMANDS_FIND_DESC": "найти игрока в базе данных",
+ "COMMANDS_RULES_DESC": "перечислить правила сервера",
+ "COMMANDS_PM_DESC": "отправить сообщение другому игроку",
+ "COMMANDS_FLAG_DESC": "отметить подозрительного игрока и сообщить администраторам, чтобы присоединились",
+ "COMMANDS_REPORT_DESC": "пожаловаться на игрока за подозрительное поведение",
+ "COMMANDS_REPORTS_DESC": "получить или очистить последние жалобы",
+ "COMMANDS_MASK_DESC": "скрыть свое присутствие как игрока с правами",
+ "COMMANDS_BANINFO_DESC": "получить информацию о бане игрока",
+ "COMMANDS_ALIAS_DESC": "получить прошлые имена и IP игрока",
+ "COMMANDS_RCON_DESC": "отправить RCon команду на сервер",
+ "COMMANDS_PLUGINS_DESC": "просмотреть все загруженные плагины",
+ "COMMANDS_IP_DESC": "просмотреть ваш внешний IP-адрес",
+ "COMMANDS_PRUNE_DESC": "понизить любых игроков с правами, которые не подключались за последнее время (по умолчанию: 30 дней)",
+ "COMMANDS_SETPASSWORD_DESC": "установить свой пароль аутентификации",
+ "COMMANDS_PING_DESC": "получить пинг игрока",
+ "COMMANDS_ARGS_PLAYER": "игрок",
+ "COMMANDS_ARGS_REASON": "причина",
+ "COMMANDS_ARGS_MESSAGE": "сообщение",
+ "COMMANDS_ARGS_DURATION": "длительность (m|h|d|w|y)",
+ "COMMANDS_ARGS_CLIENTID": "ID игрока",
+ "COMMANDS_ARGS_COMMANDS": "команды",
+ "COMMANDS_ARGS_LEVEL": "уровень",
+ "COMMANDS_ARGS_MAP": "карта",
+ "COMMANDS_ARGS_CLEAR": "очистить",
+ "COMMANDS_ARGS_INACTIVE": "дни бездействия",
+ "COMMANDS_ARGS_PASSWORD": "пароль",
+ "PLUGINS_LOGIN_COMMANDS_LOGIN_DESC": "войти, используя пароль",
+ "PLUGINS_LOGIN_COMMANDS_LOGIN_SUCCESS": "Вы теперь вошли",
+ "PLUGINS_LOGIN_COMMANDS_LOGIN_FAIL": "Ваш пароль неверный",
+ "PLUGINS_STATS_COMMANDS_RESET_DESC": "сбросить вашу статистику под ноль",
+ "PLUGINS_STATS_COMMANDS_RESET_SUCCESS": "Ваша статистика на этом сервере была сброшена",
+ "PLUGINS_STATS_COMMANDS_RESET_FAIL": "Вы должны быть подключены к серверу, чтобы сбросить свою статистику",
+ "PLUGINS_STATS_COMMANDS_VIEW_DESC": "просмотреть свою статистику",
+ "PLUGINS_STATS_COMMANDS_VIEW_FAIL_INGAME": "Указанный игрок должен быть в игре",
+ "PLUGINS_STATS_COMMANDS_VIEW_FAIL_INGAME_SELF": "Вы должны быть в игре, чтобы просмотреть свою статистику",
+ "PLUGINS_STATS_COMMANDS_VIEW_FAIL": "Не удается найти игрока, которого вы указали.",
+ "PLUGINS_STATS_COMMANDS_VIEW_SUCCESS": "Статистика",
+ "PLUGINS_STATS_COMMANDS_TOP_DESC": "показать топ-5 лучших игроков на этом сервере",
+ "PLUGINS_STATS_COMMANDS_TOP_TEXT": "Лучшие игроки",
+ "PLUGINS_STATS_TEXT_KILLS": "УБИЙСТВ",
+ "PLUGINS_STATS_TEXT_DEATHS": "СМЕРТЕЙ",
+ "PLUGINS_STATS_TEXT_SKILL": "МАСТЕРСТВО",
+ "GLOBAL_DAYS": "дней",
+ "GLOBAL_HOURS": "часов",
+ "GLOBAL_MINUTES": "минут",
+ "GLOBAL_REPORT": "Если вы подозреваете кого-то в ^5ЧИТЕРСТВЕ^7, используйте команду ^5!report",
+ "GLOBAL_ERROR": "Ошибка",
+ "GLOBAL_WARNING": "Предупреждение",
+ "GLOBAL_INFO": "Информация",
+ "GLOBAL_VERBOSE": "Подробно"
}
}
\ No newline at end of file
diff --git a/Application/Logger.cs b/Application/Logger.cs
index 88de9b5cb..9f0f1c694 100644
--- a/Application/Logger.cs
+++ b/Application/Logger.cs
@@ -1,4 +1,6 @@
-using System;
+using SharedLibraryCore;
+using System;
+using System.Collections.Generic;
using System.IO;
namespace IW4MAdmin.Application
@@ -28,7 +30,19 @@ namespace IW4MAdmin.Application
void Write(string msg, LogType type)
{
- string LogLine = $"[{DateTime.Now.ToString("HH:mm:ss")}] - {type}: {msg}";
+ string stringType;
+
+ try
+ {
+ stringType = Utilities.CurrentLocalization.LocalizationSet[$"GLOBAL_{type.ToString().ToUpper()}"];
+ }
+
+ catch(KeyNotFoundException)
+ {
+ stringType = type.ToString();
+ }
+
+ string LogLine = $"[{DateTime.Now.ToString("HH:mm:ss")}] - {stringType}: {msg}";
lock (ThreadLock)
{
#if DEBUG
diff --git a/Application/Main.cs b/Application/Main.cs
index a4209269b..9be847d1b 100644
--- a/Application/Main.cs
+++ b/Application/Main.cs
@@ -130,7 +130,7 @@ namespace IW4MAdmin.Application
}
ServerManager.Start();
- ServerManager.Logger.WriteVerbose("Shutdown complete");
+ ServerManager.Logger.WriteVerbose(loc["MANAGER_SHUTDOWN_SUCCESS"]);
}
diff --git a/Application/Manager.cs b/Application/Manager.cs
index c42f6ff31..4be917e9b 100644
--- a/Application/Manager.cs
+++ b/Application/Manager.cs
@@ -184,7 +184,7 @@ namespace IW4MAdmin.Application
catch (Exception e)
{
- Logger.WriteError($"An error occured loading plugin {Plugin.Name}");
+ Logger.WriteError($"{Utilities.CurrentLocalization.LocalizationSet["SERVER_ERROR_PLUGIN"]} {Plugin.Name}");
Logger.WriteDebug($"Exception: {e.Message}");
Logger.WriteDebug($"Stack Trace: {e.StackTrace}");
}
@@ -226,7 +226,7 @@ namespace IW4MAdmin.Application
Commands.Add(new CIP());
Commands.Add(new CMask());
Commands.Add(new CPruneAdmins());
- Commands.Add(new CKillServer());
+ //Commands.Add(new CKillServer());
Commands.Add(new CSetPassword());
Commands.Add(new CPing());
@@ -247,7 +247,7 @@ namespace IW4MAdmin.Application
_servers.Add(ServerInstance);
}
- Logger.WriteVerbose($"Now monitoring {ServerInstance.Hostname}");
+ Logger.WriteVerbose($"{Utilities.CurrentLocalization.LocalizationSet["MANAGER_MONITORING_TEXT"]} {ServerInstance.Hostname}");
// this way we can keep track of execution time and see if problems arise.
var Status = new AsyncStatus(ServerInstance, UPDATE_FREQUENCY);
@@ -259,9 +259,9 @@ namespace IW4MAdmin.Application
catch (ServerException e)
{
- Logger.WriteError($"Not monitoring server {Conf.IPAddress}:{Conf.Port} due to uncorrectable errors");
+ Logger.WriteError($"{Utilities.CurrentLocalization.LocalizationSet["SERVER_ERROR_UNFIXABLE"]} [{Conf.IPAddress}:{Conf.Port}]");
if (e.GetType() == typeof(DvarException))
- Logger.WriteDebug($"Could not get the dvar value for {(e as DvarException).Data["dvar_name"]} (ensure the server has a map loaded)");
+ Logger.WriteDebug($"{Utilities.CurrentLocalization.LocalizationSet["SERVER_ERROR_DVAR"]} {(e as DvarException).Data["dvar_name"]} ({Utilities.CurrentLocalization.LocalizationSet["SERVER_ERROR_DVAR_HELP"]})");
else if (e.GetType() == typeof(NetworkException))
{
Logger.WriteDebug(e.Message);
diff --git a/Application/RconParsers/IW4RConParser.cs b/Application/RconParsers/IW4RConParser.cs
index df7d275eb..ca9caf0af 100644
--- a/Application/RconParsers/IW4RConParser.cs
+++ b/Application/RconParsers/IW4RConParser.cs
@@ -103,7 +103,7 @@ namespace Application.RconParsers
IPAddress = cIP,
Ping = Ping,
Score = score,
- IsBot = npID == -1
+ IsBot = npID == 0
};
StatusPlayers.Add(P);
}
diff --git a/Application/RconParsers/IW5MRConParser.cs b/Application/RconParsers/IW5MRConParser.cs
index 31a88fc61..ef5c42d26 100644
--- a/Application/RconParsers/IW5MRConParser.cs
+++ b/Application/RconParsers/IW5MRConParser.cs
@@ -155,7 +155,7 @@ namespace Application.RconParsers
IPAddress = ipAddress,
Ping = Ping,
Score = score,
- IsBot = networkId < 1
+ IsBot = networkId == 0
});
}
}
diff --git a/Application/RconParsers/T6MRConParser.cs b/Application/RconParsers/T6MRConParser.cs
index 54204830f..7ef408549 100644
--- a/Application/RconParsers/T6MRConParser.cs
+++ b/Application/RconParsers/T6MRConParser.cs
@@ -186,7 +186,7 @@ namespace Application.RconParsers
IPAddress = ipAddress,
Ping = Ping,
Score = score,
- IsBot = networkId < 1
+ IsBot = networkId == 0
});
}
}
diff --git a/Application/Server.cs b/Application/Server.cs
index 3c0d778f3..9f62a9a79 100644
--- a/Application/Server.cs
+++ b/Application/Server.cs
@@ -195,7 +195,7 @@ namespace IW4MAdmin
catch (Exception E)
{
- Manager.GetLogger().WriteError($"Unable to add player {polledPlayer.Name}::{polledPlayer.NetworkId}");
+ Manager.GetLogger().WriteError($"{loc["SERVER_ERROR_ADDPLAYER"]} {polledPlayer.Name}::{polledPlayer.NetworkId}");
Manager.GetLogger().WriteDebug(E.StackTrace);
return false;
}
@@ -466,7 +466,7 @@ namespace IW4MAdmin
if (ConnectionErrors > 0)
{
- Logger.WriteVerbose($"Connection has been reestablished with {IP}:{Port}");
+ Logger.WriteVerbose($"{loc["MANAGER_CONNECTION_REST"]} {IP}:{Port}");
Throttled = false;
}
ConnectionErrors = 0;
@@ -479,7 +479,7 @@ namespace IW4MAdmin
ConnectionErrors++;
if (ConnectionErrors == 1)
{
- Logger.WriteError($"{e.Message} {IP}:{Port}, reducing polling rate");
+ Logger.WriteError($"{e.Message} {IP}:{Port}, {loc["SERVER_ERROR_POLLING"]}");
Logger.WriteDebug($"Internal Exception: {e.Data["internal_exception"]}");
Throttled = true;
}
@@ -569,7 +569,7 @@ namespace IW4MAdmin
//#if !DEBUG
catch (NetworkException)
{
- Logger.WriteError($"Could not communicate with {IP}:{Port}");
+ Logger.WriteError($"{loc["SERVER_ERROR_COMMUNICATION"]} {IP}:{Port}");
return false;
}
@@ -582,7 +582,7 @@ namespace IW4MAdmin
catch (Exception E)
{
- Logger.WriteError($"Encountered error on {IP}:{Port}");
+ Logger.WriteError($"{loc["SERVER_ERROR_EXCEPTION"]} {IP}:{Port}");
Logger.WriteDebug("Error Message: " + E.Message);
Logger.WriteDebug("Error Trace: " + E.StackTrace);
return false;
@@ -680,9 +680,9 @@ namespace IW4MAdmin
if (!File.Exists(logPath))
{
- Logger.WriteError($"Gamelog {logPath} does not exist!");
+ Logger.WriteError($"{logPath} {loc["SERVER_ERROR_DNE"]}");
#if !DEBUG
- throw new ServerException($"Invalid gamelog file {logPath}");
+ throw new ServerException($"{loc["SERVER_ERROR_LOG"]} {logPath}");
#endif
}
else
@@ -796,10 +796,10 @@ namespace IW4MAdmin
catch (Exception Except)
{
- Logger.WriteError(String.Format("A command request \"{0}\" generated an error.", C.Name));
+ Logger.WriteError(String.Format($"\"{0}\" {loc["SERVER_ERROR_COMMAND_LOG"]}", C.Name));
Logger.WriteDebug(String.Format("Error Message: {0}", Except.Message));
Logger.WriteDebug(String.Format("Error Trace: {0}", Except.StackTrace));
- await E.Origin.Tell("^1An internal error occured while processing your command^7");
+ await E.Origin.Tell($"^1{loc["SERVER_ERROR_COMMAND_INGAME"]}");
#if DEBUG
await E.Origin.Tell(Except.Message);
#endif
@@ -824,12 +824,29 @@ namespace IW4MAdmin
{
Logger.WriteInfo($"New map loaded - {ClientNum} active players");
- var dict = (Dictionary)E.Extra;
- Gametype = dict["g_gametype"].StripColors();
- Hostname = dict["sv_hostname"].StripColors();
+ // iw4 doesn't log the game info
+ if (E.Extra == null)
+ {
+ var dict = await this.GetInfoAsync();
+
+ Gametype = dict["gametype"].StripColors();
+ Hostname = dict["hostname"].StripColors();
+
+ string mapname = dict["mapname"].StripColors();
+ CurrentMap = Maps.Find(m => m.Name == mapname) ?? new Map() { Alias = mapname, Name = mapname };
+ }
+
+ else
+
+ {
+ var dict = (Dictionary)E.Extra;
+ Gametype = dict["g_gametype"].StripColors();
+ Hostname = dict["sv_hostname"].StripColors();
+
+ string mapname = dict["mapname"].StripColors();
+ CurrentMap = Maps.Find(m => m.Name == mapname) ?? new Map() { Alias = mapname, Name = mapname };
+ }
- string mapname = dict["mapname"].StripColors();
- CurrentMap = Maps.Find(m => m.Name == mapname) ?? new Map() { Alias = mapname, Name = mapname };
}
if (E.Type == GameEvent.EventType.MapEnd)
diff --git a/Master/master/config/master.json b/Master/master/config/master.json
index 53bc048de..c23b10ed7 100644
--- a/Master/master/config/master.json
+++ b/Master/master/config/master.json
@@ -1,4 +1,4 @@
{
"current-version-stable": 2.0,
- "current-version-prerelease": 2.0
+ "current-version-prerelease": 2.1
}
\ No newline at end of file
diff --git a/Master/master/resources/history_graph.py b/Master/master/resources/history_graph.py
index 8bf4e280b..6fc903848 100644
--- a/Master/master/resources/history_graph.py
+++ b/Master/master/resources/history_graph.py
@@ -11,18 +11,18 @@ class HistoryGraph(Resource):
custom_style = Style(
background='transparent',
plot_background='transparent',
- foreground='rgba(109, 118, 126, 0.3)',
- foreground_strong='rgba(109, 118, 126, 0.3)',
- foreground_subtle='rgba(109, 118, 126, 0.3)',
+ foreground='#6c757d',
+ foreground_strong='#6c757d',
+ foreground_subtle='#6c757d',
opacity='0.1',
opacity_hover='0.2',
- transition='100ms ease-in',
- colors=('#007acc', '#749363')
+ transition='0ms',
+ colors=('#749363','#007acc'),
)
- graph = pygal.StackedLine(
+ graph = pygal.Line(
stroke_style={'width': 0.4},
- show_dots=False,
+ #show_dots=False,
show_legend=False,
fill=True,
style=custom_style,
@@ -36,9 +36,9 @@ class HistoryGraph(Resource):
instance_counts = [history['count'] for history in ctx.history.instance_history][-history_count:]
client_counts = [history['count'] for history in ctx.history.client_history][-history_count:]
- graph.add('Instance Count', instance_counts)
graph.add('Client Count', client_counts)
- return { 'message' : graph.render(),
+ graph.add('Instance Count', instance_counts)
+ return { 'message' : graph.render().replace("Pygal", ""),
'data_points' : len(instance_count),
'instance_count' : 0 if len(instance_counts) is 0 else instance_counts[-1],
'client_count' : 0 if len(client_counts) is 0 else client_counts[-1]
diff --git a/Master/master/templates/index.html b/Master/master/templates/index.html
index db8d27356..a427f0d75 100644
--- a/Master/master/templates/index.html
+++ b/Master/master/templates/index.html
@@ -14,42 +14,50 @@
— {{client_count}} clients
-
+
-
+
{% endblock %}
{% block scripts %}
-
-
+
+
{% endblock %}
diff --git a/Master/master/templates/layout.html b/Master/master/templates/layout.html
index ddc75d238..2526a533a 100644
--- a/Master/master/templates/layout.html
+++ b/Master/master/templates/layout.html
@@ -14,6 +14,18 @@
.oi:hover {
color: #fff !important;
}
+ .dot {
+ opacity: 0;
+ padding: 5px;
+ }
+
+ .dot:hover {
+ opacity: 1;
+ }
+
+ .tooltip-box {
+ fill: #343a40 !important;
+ }
diff --git a/Plugins/Login/Commands/CLogin.cs b/Plugins/Login/Commands/CLogin.cs
index 332bbbfc3..61fdbb2a4 100644
--- a/Plugins/Login/Commands/CLogin.cs
+++ b/Plugins/Login/Commands/CLogin.cs
@@ -8,7 +8,7 @@ namespace IW4MAdmin.Plugins.Login.Commands
{
public class CLogin : Command
{
- public CLogin() : base("login", "login using password", "l", Player.Permission.Trusted, false, new CommandArgument[]
+ public CLogin() : base("login", Utilities.CurrentLocalization.LocalizationSet["PLUGINS_LOGIN_COMMANDS_LOGIN_DESC"], "l", Player.Permission.Trusted, false, new CommandArgument[]
{
new CommandArgument()
{
@@ -25,12 +25,12 @@ namespace IW4MAdmin.Plugins.Login.Commands
if (hashedPassword[0] == client.Password)
{
Plugin.AuthorizedClients[E.Origin.ClientId] = true;
- await E.Origin.Tell("You are now logged in");
+ await E.Origin.Tell(Utilities.CurrentLocalization.LocalizationSet["PLUGINS_LOGIN_COMMANDS_LOGIN_SUCCESS"]);
}
else
{
- await E.Origin.Tell("Your password is incorrect");
+ await E.Origin.Tell(Utilities.CurrentLocalization.LocalizationSet["PLUGINS_LOGIN_COMMANDS_LOGIN_FAIL"]);
}
}
}
diff --git a/Plugins/Stats/Commands/ResetStats.cs b/Plugins/Stats/Commands/ResetStats.cs
index 018bd56f1..8ec347ad8 100644
--- a/Plugins/Stats/Commands/ResetStats.cs
+++ b/Plugins/Stats/Commands/ResetStats.cs
@@ -11,7 +11,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
{
public class ResetStats : Command
{
- public ResetStats() : base("resetstats", "reset your stats to factory-new", "rs", Player.Permission.User, false) { }
+ public ResetStats() : base("resetstats", Utilities.CurrentLocalization.LocalizationSet["PLUGINS_STATS_COMMANDS_RESET_DESC"], "rs", Player.Permission.User, false) { }
public override async Task ExecuteAsync(GameEvent E)
{
@@ -31,12 +31,12 @@ namespace IW4MAdmin.Plugins.Stats.Commands
// fixme: this doesn't work properly when another context exists
await svc.SaveChangesAsync();
- await E.Origin.Tell("Your stats for this server have been reset");
+ await E.Origin.Tell(Utilities.CurrentLocalization.LocalizationSet["PLUGINS_STATS_COMMANDS_RESET_SUCCESS"]);
}
else
{
- await E.Origin.Tell("You must be connected to a server to reset your stats");
+ await E.Origin.Tell(Utilities.CurrentLocalization.LocalizationSet["PLUGINS_STATS_COMMANDS_RESET_FAIL"]);
}
}
}
diff --git a/Plugins/Stats/Commands/TopStats.cs b/Plugins/Stats/Commands/TopStats.cs
index 225b3a475..ef1daf48d 100644
--- a/Plugins/Stats/Commands/TopStats.cs
+++ b/Plugins/Stats/Commands/TopStats.cs
@@ -12,7 +12,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
{
class TopStats : Command
{
- public TopStats() : base("topstats", "view the top 5 players on this server", "ts", Player.Permission.User, false) { }
+ public TopStats() : base("topstats", Utilities.CurrentLocalization.LocalizationSet["PLUGINS_STATS_COMMANDS_TOP_DESC"], "ts", Player.Permission.User, false) { }
public override async Task ExecuteAsync(GameEvent E)
{
@@ -43,17 +43,17 @@ namespace IW4MAdmin.Plugins.Stats.Commands
if (!E.Message.IsBroadcastCommand())
{
- await E.Origin.Tell("^5--Top Players--");
+ await E.Origin.Tell($"^5--{Utilities.CurrentLocalization.LocalizationSet["PLUGINS_STATS_COMMANDS_TOP_TEXT"]}--");
foreach (var stat in topStats)
- await E.Origin.Tell($"^3{stat.Name}^7 - ^5{stat.KDR} ^7KDR | ^5{stat.Skill} ^7SKILL");
+ await E.Origin.Tell($"^3{stat.Name}^7 - ^5{stat.KDR} ^7KDR | ^5{stat.Skill} ^7{Utilities.CurrentLocalization.LocalizationSet["PLUGINS_STATS_TEXT_SKILL"]}");
}
else
{
- await E.Owner.Broadcast("^5--Top Players--");
+ await E.Owner.Broadcast($"^5--{Utilities.CurrentLocalization.LocalizationSet["PLUGINS_STATS_COMMANDS_TOP_TEXT"]}--");
foreach (var stat in topStats)
- await E.Owner.Broadcast($"^3{stat.Name}^7 - ^5{stat.KDR} ^7KDR | ^5{stat.Skill} ^7SKILL");
+ await E.Owner.Broadcast($"^3{stat.Name}^7 - ^5{stat.KDR} ^7KDR | ^5{stat.Skill} ^7{Utilities.CurrentLocalization.LocalizationSet["PLUGINS_STATS_TEXT_SKILL"]}");
}
}
}
diff --git a/Plugins/Stats/Commands/ViewStats.cs b/Plugins/Stats/Commands/ViewStats.cs
index 7da9cb60e..8053674b8 100644
--- a/Plugins/Stats/Commands/ViewStats.cs
+++ b/Plugins/Stats/Commands/ViewStats.cs
@@ -12,7 +12,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
{
public class CViewStats : Command
{
- public CViewStats() : base("stats", "view your stats", "xlrstats", Player.Permission.User, false, new CommandArgument[]
+ public CViewStats() : base("stats", Utilities.CurrentLocalization.LocalizationSet["PLUGINS_STATS_COMMANDS_VIEW_DESC"], "xlrstats", Player.Permission.User, false, new CommandArgument[]
{
new CommandArgument()
{
@@ -24,15 +24,17 @@ namespace IW4MAdmin.Plugins.Stats.Commands
public override async Task ExecuteAsync(GameEvent E)
{
+ var loc = Utilities.CurrentLocalization.LocalizationSet;
+
if (E.Target?.ClientNumber < 0)
{
- await E.Origin.Tell("The specified player must be ingame");
+ await E.Origin.Tell(loc["PLUGINS_STATS_COMMANDS_VIEW_FAIL_INGAME"]);
return;
}
if (E.Origin.ClientNumber < 0 && E.Target == null)
{
- await E.Origin.Tell("You must be ingame to view your stats");
+ await E.Origin.Tell(loc["PLUGINS_STATS_COMMANDS_VIEW_FAIL_INGAME_SELF"]);
return;
}
@@ -41,7 +43,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
if (E.Data.Length > 0 && E.Target == null)
{
- await E.Origin.Tell("Cannot find the player you specified");
+ await E.Origin.Tell(loc["PLUGINS_STATS_COMMANDS_VIEW_FAIL"]);
return;
}
@@ -51,26 +53,26 @@ namespace IW4MAdmin.Plugins.Stats.Commands
if (E.Target != null)
{
pStats = clientStats.Find(c => c.ServerId == serverId && c.ClientId == E.Target.ClientId).First();
- statLine = String.Format("^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", pStats.Kills, pStats.Deaths, pStats.KDR, pStats.Skill);
+ statLine = $"^5{pStats.Kills} ^7{loc["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{loc["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Skill} ^7{loc["PLUGINS_STATS_TEXT_SKILL"]}";
}
else
{
pStats = pStats = clientStats.Find(c => c.ServerId == serverId && c.ClientId == E.Origin.ClientId).First();
- statLine = String.Format("^5{0} ^7KILLS | ^5{1} ^7DEATHS | ^5{2} ^7KDR | ^5{3} ^7SKILL", pStats.Kills, pStats.Deaths, pStats.KDR, pStats.Skill);
+ statLine = $"^5{pStats.Kills} ^7{loc["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{loc["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Skill} ^7{loc["PLUGINS_STATS_TEXT_SKILL"]}";
}
if (E.Message.IsBroadcastCommand())
{
string name = E.Target == null ? E.Origin.Name : E.Target.Name;
- await E.Owner.Broadcast($"Stats for ^5{name}^7");
+ await E.Owner.Broadcast($"{loc["PLUGINS_STATS_COMMANDS_VIEW_SUCCESS"]} ^5{name}^7");
await E.Owner.Broadcast(statLine);
}
else
{
if (E.Target != null)
- await E.Origin.Tell($"Stats for ^5{E.Target.Name}^7");
+ await E.Origin.Tell($"{loc["PLUGINS_STATS_COMMANDS_VIEW_SUCCESS"]} ^5{E.Target.Name}^7");
await E.Origin.Tell(statLine);
}
}
diff --git a/README.md b/README.md
index dbba21dd0..689c8ef2b 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
### Version 2.1
_______
### About
-**IW4MAdmin** is an administration tool for [IW4x](https://iw4xcachep26muba.onion.link/), [Pluto T6](https://forum.plutonium.pw/category/33/plutonium-t6) [Pluto IW5](https://forum.plutonium.pw/category/5/plutonium-iw5), and most Call of Duty dedicated servers. It allows complete control of your server; from changing maps, to banning players, **IW4MAdmin** monitors and records activity on your server(s). With plugin support, extending its functionality is a breeze.
+**IW4MAdmin** is an administration tool for [IW4x](https://iw4xcachep26muba.onion.link/), [Pluto T6](https://forum.plutonium.pw/category/33/plutonium-t6), [Pluto IW5](https://forum.plutonium.pw/category/5/plutonium-iw5), and most Call of Duty dedicated servers. It allows complete control of your server; from changing maps, to banning players, **IW4MAdmin** monitors and records activity on your server(s). With plugin support, extending its functionality is a breeze.
### Setup
**IW4MAdmin** requires minimal configuration to run. There is only one prerequisite.
diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs
index 868f2ec9d..dd1accd45 100644
--- a/SharedLibraryCore/Commands/NativeCommands.cs
+++ b/SharedLibraryCore/Commands/NativeCommands.cs
@@ -15,7 +15,7 @@ namespace SharedLibraryCore.Commands
public class CQuit : Command
{
public CQuit() :
- base("quit", "quit IW4MAdmin", "q", Player.Permission.Owner, false)
+ base("quit", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_QUIT_DESC"], "q", Player.Permission.Owner, false)
{ }
public override Task ExecuteAsync(GameEvent E)
@@ -27,7 +27,7 @@ namespace SharedLibraryCore.Commands
public class COwner : Command
{
public COwner() :
- base("owner", "claim ownership of the server", "o", Player.Permission.User, false)
+ base("owner", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_OWNER_DESC"], "o", Player.Permission.User, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
@@ -46,16 +46,16 @@ namespace SharedLibraryCore.Commands
public class CWarn : Command
{
public CWarn() :
- base("warn", "warn player for infringing rules", "w", Player.Permission.Trusted, true, new CommandArgument[]
+ base("warn", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_WARN_DESC"], "w", Player.Permission.Trusted, true, new CommandArgument[]
{
new CommandArgument()
{
- Name = "player",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = true
},
new CommandArgument()
{
- Name = "reason",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_REASON"],
Required = true
}
})
@@ -73,11 +73,11 @@ namespace SharedLibraryCore.Commands
public class CWarnClear : Command
{
public CWarnClear() :
- base("warnclear", "remove all warning for a player", "wc", Player.Permission.Trusted, true, new CommandArgument[]
+ base("warnclear", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_WARNCLEAR_DESC"], "wc", Player.Permission.Trusted, true, new CommandArgument[]
{
new CommandArgument()
{
- Name = "player",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = true
}
})
@@ -94,17 +94,17 @@ namespace SharedLibraryCore.Commands
public class CKick : Command
{
public CKick() :
- base("kick", "kick a player by name", "k", Player.Permission.Trusted, true, new CommandArgument[]
+ base("kick", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_KICK_DESC"], "k", Player.Permission.Trusted, true, new CommandArgument[]
{
new CommandArgument()
{
- Name = "player",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = true
},
new CommandArgument()
{
- Name = "reason",
- Required = true
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_REASON"],
+ Required = true
}
})
{ }
@@ -125,11 +125,11 @@ namespace SharedLibraryCore.Commands
public class CSay : Command
{
public CSay() :
- base("say", "broadcast message to all players", "s", Player.Permission.Moderator, false, new CommandArgument[]
+ base("say", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_SAY_DESC"], "s", Player.Permission.Moderator, false, new CommandArgument[]
{
new CommandArgument()
{
- Name = "message",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_MESSAGE"],
Required = true
}
})
@@ -144,21 +144,21 @@ namespace SharedLibraryCore.Commands
public class CTempBan : Command
{
public CTempBan() :
- base("tempban", "temporarily ban a player for specified time (defaults to 1 hour)", "tb", Player.Permission.Moderator, true, new CommandArgument[]
+ base("tempban", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_TEMPBAN_DESC"], "tb", Player.Permission.Moderator, true, new CommandArgument[]
{
new CommandArgument()
{
- Name = "player",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = true
},
new CommandArgument()
{
- Name = "duration (m|h|d|w|y)",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_DURATION"],
Required = true,
},
new CommandArgument()
{
- Name = "reason",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_REASON"],
Required = true
}
})
@@ -184,16 +184,16 @@ namespace SharedLibraryCore.Commands
public class CBan : Command
{
public CBan() :
- base("ban", "permanently ban a player from the server", "b", Player.Permission.SeniorAdmin, true, new CommandArgument[]
+ base("ban", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_BAN_DESC"], "b", Player.Permission.SeniorAdmin, true, new CommandArgument[]
{
new CommandArgument()
{
- Name = "player",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = true
},
new CommandArgument()
{
- Name = "reason",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_REASON"],
Required = true
}
})
@@ -214,16 +214,16 @@ namespace SharedLibraryCore.Commands
public class CUnban : Command
{
public CUnban() :
- base("unban", "unban player by client id", "ub", Player.Permission.SeniorAdmin, true, new CommandArgument[]
+ base("unban", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_UNBAN_DESC"], "ub", Player.Permission.SeniorAdmin, true, new CommandArgument[]
{
new CommandArgument()
{
- Name = "client id",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_CLIENTID"],
Required = true,
},
new CommandArgument()
{
- Name = "reason",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_REASON"],
Required = true
}
})
@@ -247,7 +247,7 @@ namespace SharedLibraryCore.Commands
public class CWhoAmI : Command
{
public CWhoAmI() :
- base("whoami", "give information about yourself.", "who", Player.Permission.User, false)
+ base("whoami", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_WHO_DESC"], "who", Player.Permission.User, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
@@ -260,7 +260,7 @@ namespace SharedLibraryCore.Commands
public class CList : Command
{
public CList() :
- base("list", "list active clients", "l", Player.Permission.Moderator, false)
+ base("list", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_LIST_DESC"], "l", Player.Permission.Moderator, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
@@ -295,11 +295,11 @@ namespace SharedLibraryCore.Commands
public class CHelp : Command
{
public CHelp() :
- base("help", "list all available commands", "h", Player.Permission.User, false, new CommandArgument[]
+ base("help", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_HELP_DESC"], "h", Player.Permission.User, false, new CommandArgument[]
{
new CommandArgument()
{
- Name = "command",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_COMMANDS"],
Required = false
}
})
@@ -359,7 +359,7 @@ namespace SharedLibraryCore.Commands
public class CFastRestart : Command
{
public CFastRestart() :
- base("fastrestart", "fast restart current map", "fr", Player.Permission.Moderator, false)
+ base("fastrestart", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_FASTRESTART_DESC"], "fr", Player.Permission.Moderator, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
@@ -376,7 +376,7 @@ namespace SharedLibraryCore.Commands
public class CMapRotate : Command
{
public CMapRotate() :
- base("maprotate", "cycle to the next map in rotation", "mr", Player.Permission.Administrator, false)
+ base("maprotate", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_MAPROTATE_DESC"], "mr", Player.Permission.Administrator, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
@@ -393,16 +393,16 @@ namespace SharedLibraryCore.Commands
public class CSetLevel : Command
{
public CSetLevel() :
- base("setlevel", "set player to specified administration level", "sl", Player.Permission.Moderator, true, new CommandArgument[]
+ base("setlevel", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_SETLEVEL_DESC"], "sl", Player.Permission.Moderator, true, new CommandArgument[]
{
new CommandArgument()
{
- Name = "player",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = true
},
new CommandArgument()
{
- Name = "level",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_LEVEL"],
Required = true
}
})
@@ -437,7 +437,6 @@ namespace SharedLibraryCore.Commands
if (E.Origin.Level < Player.Permission.Owner)
{
await E.Origin.Tell(string.Format(Utilities.CurrentLocalization.LocalizationSet["COMMANDS_SETLEVEL_LEVELTOOHIGH"], E.Target.Name, (E.Origin.Level - 1).ToString()));
- await E.Origin.Tell($"You can only promote ^5{E.Target.Name} ^7to ^5{(E.Origin.Level - 1)} ^7or lower privilege");
return;
}
}
@@ -480,32 +479,33 @@ namespace SharedLibraryCore.Commands
public class CUsage : Command
{
public CUsage() :
- base("usage", "get current application memory usage", "us", Player.Permission.Moderator, false)
+ base("usage", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_USAGE_DESC"], "us", Player.Permission.Moderator, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
{
- await E.Origin.Tell("IW4M Admin is using " + Math.Round(((System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 / 2048f) / 1200f), 1) + "MB");
+ await E.Origin.Tell($"IW4MAdmin {Utilities.CurrentLocalization.LocalizationSet["COMMANDS_USAGE_TEXT"]}" + Math.Round(((System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 / 2048f) / 1200f), 1) + "MB");
}
}
public class CUptime : Command
{
public CUptime() :
- base("uptime", "get current application running time", "up", Player.Permission.Moderator, false)
+ base("uptime", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_UPTIME_DESC"], "up", Player.Permission.Moderator, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
{
TimeSpan uptime = DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime;
- await E.Origin.Tell(String.Format("IW4M Admin has been up for {0} days, {1} hours, and {2} minutes", uptime.Days, uptime.Hours, uptime.Minutes));
+ var loc = Utilities.CurrentLocalization.LocalizationSet;
+ await E.Origin.Tell($"IW4M Admin {loc["COMMANDS_UPTIME_TEXT"]} {uptime.Days} {loc["GLOBAL_DAYS"]}, {uptime.Hours} {loc["GLOBAL_HOURS"]}, {uptime.Minutes} {loc["GLOBAL_MINUTES"]}");
}
}
public class CListAdmins : Command
{
public CListAdmins() :
- base("admins", "list currently connected admins", "a", Player.Permission.User, false)
+ base("admins", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ADMINS_DESC"], "a", Player.Permission.User, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
@@ -532,11 +532,11 @@ namespace SharedLibraryCore.Commands
public class CLoadMap : Command
{
public CLoadMap() :
- base("map", "change to specified map", "m", Player.Permission.Administrator, false, new CommandArgument[]
+ base("map", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_MAP_DESC"], "m", Player.Permission.Administrator, false, new CommandArgument[]
{
new CommandArgument()
{
- Name = "map",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_MAP"],
Required = true
}
})
@@ -565,11 +565,11 @@ namespace SharedLibraryCore.Commands
public class CFindPlayer : Command
{
public CFindPlayer() :
- base("find", "find player in database", "f", Player.Permission.Administrator, false, new CommandArgument[]
+ base("find", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_FIND_DESC"], "f", Player.Permission.Administrator, false, new CommandArgument[]
{
new CommandArgument()
{
- Name = "player",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = true
}
})
@@ -608,7 +608,7 @@ namespace SharedLibraryCore.Commands
public class CListRules : Command
{
public CListRules() :
- base("rules", "list server rules", "r", Player.Permission.User, false)
+ base("rules", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_RULES_DESC"], "r", Player.Permission.User, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
@@ -643,16 +643,16 @@ namespace SharedLibraryCore.Commands
public class CPrivateMessage : Command
{
public CPrivateMessage() :
- base("privatemessage", "send message to other player", "pm", Player.Permission.User, true, new CommandArgument[]
+ base("privatemessage", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_PM_DESC"], "pm", Player.Permission.User, true, new CommandArgument[]
{
new CommandArgument()
{
- Name = "player",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = true
},
new CommandArgument()
{
- Name = "message",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_MESSAGE"],
Required = true
}
})
@@ -668,16 +668,16 @@ namespace SharedLibraryCore.Commands
public class CFlag : Command
{
public CFlag() :
- base("flag", "flag a suspicious player and announce to admins on join", "fp", Player.Permission.Moderator, true, new CommandArgument[]
+ base("flag", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_FLAG_DESC"], "fp", Player.Permission.Moderator, true, new CommandArgument[]
{
new CommandArgument()
{
- Name = "player",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = true
},
new CommandArgument()
{
- Name = "reason",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_REASON"],
Required = true
}
})
@@ -726,16 +726,16 @@ namespace SharedLibraryCore.Commands
public class CReport : Command
{
public CReport() :
- base("report", "report a player for suspicious behavior", "rep", Player.Permission.User, true, new CommandArgument[]
+ base("report", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_REPORT_DESC"], "rep", Player.Permission.User, true, new CommandArgument[]
{
new CommandArgument()
{
- Name = "player",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = true
},
new CommandArgument()
{
- Name = "reason",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_REASON"],
Required = true
}
})
@@ -778,11 +778,11 @@ namespace SharedLibraryCore.Commands
public class CListReports : Command
{
public CListReports() :
- base("reports", "get or clear recent reports", "reps", Player.Permission.Moderator, false, new CommandArgument[]
+ base("reports", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_REPORTS_DESC"], "reps", Player.Permission.Moderator, false, new CommandArgument[]
{
new CommandArgument()
{
- Name = "clear",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_CLEAR"],
Required = false
}
})
@@ -790,7 +790,7 @@ namespace SharedLibraryCore.Commands
public override async Task ExecuteAsync(GameEvent E)
{
- if (E.Data != null && E.Data.ToLower().Contains("clear"))
+ if (E.Data != null && E.Data.ToLower().Contains(Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_CLEAR"]))
{
E.Owner.Reports = new List();
await E.Origin.Tell(Utilities.CurrentLocalization.LocalizationSet["COMMANDS_REPORTS_CLEAR_SUCCESS"]);
@@ -811,7 +811,7 @@ namespace SharedLibraryCore.Commands
public class CMask : Command
{
public CMask() :
- base("mask", "hide your presence as an administrator", "hide", Player.Permission.Moderator, false)
+ base("mask", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_MASK_DESC"], "hide", Player.Permission.Moderator, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
@@ -834,11 +834,11 @@ namespace SharedLibraryCore.Commands
public class CListBanInfo : Command
{
public CListBanInfo() :
- base("baninfo", "get information about a ban for a player", "bi", Player.Permission.Moderator, true, new CommandArgument[]
+ base("baninfo", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_BANINFO_DESC"], "bi", Player.Permission.Moderator, true, new CommandArgument[]
{
new CommandArgument()
{
- Name = "player",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = true
}
})
@@ -861,17 +861,17 @@ namespace SharedLibraryCore.Commands
await E.Origin.Tell($"^1{E.Target.Name} ^7{string.Format(success, penalty.Punisher.Name)} {penalty.Punisher.Name} {timeRemaining}");
}
-
+
}
public class CListAlias : Command
{
public CListAlias() :
- base("alias", "get past aliases and ips of a player", "known", Player.Permission.Moderator, true, new CommandArgument[]
+ base("alias", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ALIAS_DESC"], "known", Player.Permission.Moderator, true, new CommandArgument[]
{
new CommandArgument()
{
- Name = "player",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = true,
}
})
@@ -899,11 +899,11 @@ namespace SharedLibraryCore.Commands
public class CExecuteRCON : Command
{
public CExecuteRCON() :
- base("rcon", "send rcon command to server", "rcon", Player.Permission.Owner, false, new CommandArgument[]
+ base("rcon", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_RCON_DESC"], "rcon", Player.Permission.Owner, false, new CommandArgument[]
{
new CommandArgument()
{
- Name = "command",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_COMMANDS"],
Required = true
}
})
@@ -922,12 +922,12 @@ namespace SharedLibraryCore.Commands
public class CPlugins : Command
{
public CPlugins() :
- base("plugins", "view all loaded plugins", "p", Player.Permission.Administrator, false)
+ base("plugins", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_PLUGINS_DESC"], "p", Player.Permission.Administrator, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
{
- await E.Origin.Tell(Utilities.CurrentLocalization.LocalizationSet["COMMANDS_PLUGINS_LOADE"]);
+ await E.Origin.Tell(Utilities.CurrentLocalization.LocalizationSet["COMMANDS_PLUGINS_LOADED"]);
foreach (var P in Plugins.PluginImporter.ActivePlugins)
{
await E.Origin.Tell(String.Format("^3{0} ^7[v^3{1}^7] by ^5{2}^7", P.Name, P.Version, P.Author));
@@ -938,7 +938,7 @@ namespace SharedLibraryCore.Commands
public class CIP : Command
{
public CIP() :
- base("getexternalip", "view your external IP address", "ip", Player.Permission.User, false)
+ base("getexternalip", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_IP_DESC"], "ip", Player.Permission.User, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
@@ -949,11 +949,11 @@ namespace SharedLibraryCore.Commands
public class CPruneAdmins : Command
{
- public CPruneAdmins() : base("prune", "demote any admins that have not connected recently (defaults to 30 days)", "pa", Player.Permission.Owner, false, new CommandArgument[]
+ public CPruneAdmins() : base("prune", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_PRUNE_DESC"], "pa", Player.Permission.Owner, false, new CommandArgument[]
{
new CommandArgument()
{
- Name = "inactive days",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_INACTIVE"],
Required = false
}
})
@@ -975,7 +975,7 @@ namespace SharedLibraryCore.Commands
catch (FormatException)
{
- await E.Origin.Tell("Invalid number of inactive days");
+ await E.Origin.Tell(Utilities.CurrentLocalization.LocalizationSet["COMMANDS_PRUNE_FAIL"]);
return;
}
@@ -999,11 +999,11 @@ namespace SharedLibraryCore.Commands
public class CSetPassword : Command
{
- public CSetPassword() : base("setpassword", "set your authentication password", "sp", Player.Permission.Moderator, false, new CommandArgument[]
+ public CSetPassword() : base("setpassword", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_SETPASSWORD_DESC"], "sp", Player.Permission.Moderator, false, new CommandArgument[]
{
new CommandArgument()
{
- Name = "password",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PASSWORD"],
Required = true
}
})
@@ -1030,6 +1030,7 @@ namespace SharedLibraryCore.Commands
}
}
+ /*
public class CKillServer : Command
{
public CKillServer() : base("killserver", "kill the game server", "kill", Player.Permission.Administrator, false)
@@ -1081,19 +1082,20 @@ namespace SharedLibraryCore.Commands
}
}
}
- }
+ }*/
public class CPing : Command
{
- public CPing() : base("ping", "get client's ping", "pi", Player.Permission.User, false, new CommandArgument[]
+ public CPing() : base("ping", Utilities.CurrentLocalization.LocalizationSet["COMMANDS_PING_DESC"], "pi", Player.Permission.User, false, new CommandArgument[]
{
new CommandArgument()
{
- Name = "client",
+ Name = Utilities.CurrentLocalization.LocalizationSet["COMMANDS_ARGS_PLAYER"],
Required = false
}
- }){}
+ })
+ { }
public override async Task ExecuteAsync(GameEvent E)
{
diff --git a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs
index b697107aa..6114bce2c 100644
--- a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs
+++ b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs
@@ -18,6 +18,7 @@ namespace SharedLibraryCore.Configuration
public string IPHubAPIKey { get; set; }
public string WebfrontBindUrl { get; set; }
public string CustomParserEncoding { get; set; }
+ public string CustomLocale { get; set; }
public string Id { get; set; }
public List Servers { get; set; }
public int AutoMessagePeriod { get; set; }
diff --git a/SharedLibraryCore/RCon/Connection.cs b/SharedLibraryCore/RCon/Connection.cs
index 1644d387b..7059b2e05 100644
--- a/SharedLibraryCore/RCon/Connection.cs
+++ b/SharedLibraryCore/RCon/Connection.cs
@@ -171,7 +171,6 @@ namespace SharedLibraryCore.RCon
OnSent.Reset();
OnReceived.Reset();
- string queryString = "";
byte[] payload = null;
switch (type)
@@ -186,10 +185,11 @@ namespace SharedLibraryCore.RCon
case StaticHelpers.QueryType.GET_STATUS:
payload = "ÿÿÿÿgetstatus".Select(Convert.ToByte).ToArray();
break;
+ case StaticHelpers.QueryType.GET_INFO:
+ payload = "ÿÿÿÿgetinfo".Select(Convert.ToByte).ToArray();
+ break;
}
- // byte[] payload = Utilities.EncodingType.GetBytes(queryString); // queryString.Select(Convert.ToByte).ToArray();
-
retrySend:
try
{
diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs
index f051c02c9..70e892631 100644
--- a/SharedLibraryCore/Utilities.cs
+++ b/SharedLibraryCore/Utilities.cs
@@ -182,8 +182,9 @@ namespace SharedLibraryCore
public static long ConvertLong(this string str)
{
- Int64.TryParse(str, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out long id);
- return id;
+ if (Int64.TryParse(str, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out long id))
+ return id;
+ return 0;
}
public static int ConvertToIP(this string str)
@@ -357,6 +358,22 @@ namespace SharedLibraryCore
return pID;
}
+ public static Dictionary DictionaryFromKeyValue(this string eventLine)
+ {
+ string[] values = eventLine.Substring(1).Split('\\');
+
+ Dictionary dict = null;
+
+ if (values.Length % 2 == 0 && values.Length > 1)
+ {
+ dict = new Dictionary();
+ for (int i = 0; i < values.Length; i += 2)
+ dict.Add(values[i], values[i + 1]);
+ }
+
+ return dict;
+ }
+
public static Task> GetDvarAsync(this Server server, string dvarName) => server.RconParser.GetDvarAsync(server.RemoteConnection, dvarName);
public static Task SetDvarAsync(this Server server, string dvarName, object dvarValue) => server.RconParser.SetDvarAsync(server.RemoteConnection, dvarName, dvarValue);
@@ -365,5 +382,11 @@ namespace SharedLibraryCore
public static Task> GetStatusAsync(this Server server) => server.RconParser.GetStatusAsync(server.RemoteConnection);
+ public static async Task> GetInfoAsync(this Server server)
+ {
+ var response = await server.RemoteConnection.SendQueryAsync(RCon.StaticHelpers.QueryType.GET_INFO);
+ return response.FirstOrDefault(r => r[0] == '\\')?.DictionaryFromKeyValue();
+ }
+
}
}
diff --git a/WebfrontCore/bower.json b/WebfrontCore/bower.json
index a9d85da5f..7993c6ff9 100644
--- a/WebfrontCore/bower.json
+++ b/WebfrontCore/bower.json
@@ -2,14 +2,14 @@
"name": "asp.net",
"private": true,
"dependencies": {
- "bootstrap": "v4.0.0",
+ "bootstrap": "v4.1.0",
"jquery": "3.3.1",
"popper.js": "v1.12.9",
"open-iconic": "1.1.1",
"moment-timezone": "0.5.14"
},
"resolutions": {
- "bootstrap": "v4.0.0",
+ "bootstrap": "v4.1.0",
"jquery": "3.3.1"
}
}
diff --git a/WebfrontCore/bundleconfig.json b/WebfrontCore/bundleconfig.json
index 38588e925..b234f2d48 100644
--- a/WebfrontCore/bundleconfig.json
+++ b/WebfrontCore/bundleconfig.json
@@ -14,9 +14,9 @@
"outputFileName": "wwwroot/js/global.min.js",
"inputFiles": [
"wwwroot/lib/jQuery/dist/jquery.min.js",
+ "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js",
"wwwroot/lib/moment/min/moment.min.js",
"wwwroot/lib/moment-timezone/builds/moment-timezone.min.js",
- "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js",
"wwwroot/js/action.js",
"wwwroot/js/console.js",
"wwwroot/js/penalty.js",
diff --git a/WebfrontCore/wwwroot/lib/bootstrap/scss/_variables.scss b/WebfrontCore/wwwroot/lib/bootstrap/scss/_variables.scss
index 98a19807b..23253eb70 100644
--- a/WebfrontCore/wwwroot/lib/bootstrap/scss/_variables.scss
+++ b/WebfrontCore/wwwroot/lib/bootstrap/scss/_variables.scss
@@ -9,7 +9,7 @@
//
// stylelint-disable
-$white: #fff !default;
+$white: #fff !default;
$gray-100: #f8f9fa !default;
$gray-200: #e9ecef !default;
$gray-300: #dee2e6 !default;
@@ -19,73 +19,40 @@ $gray-600: #6c757d !default;
$gray-700: #495057 !default;
$gray-800: #343a40 !default;
$gray-900: #212529 !default;
-$black: #000 !default;
+$black: #000 !default;
$grays: () !default;
-$grays: map-merge((
- "100": $gray-100,
- "200": $gray-200,
- "300": $gray-300,
- "400": $gray-400,
- "500": $gray-500,
- "600": $gray-600,
- "700": $gray-700,
- "800": $gray-800,
- "900": $gray-900
-), $grays);
+$grays: map-merge(( "100": $gray-100, "200": $gray-200, "300": $gray-300, "400": $gray-400, "500": $gray-500, "600": $gray-600, "700": $gray-700, "800": $gray-800, "900": $gray-900 ), $grays);
-$blue: #007ACC !default;
-$indigo: #6610f2 !default;
-$purple: #6f42c1 !default;
-$pink: #e83e8c !default;
-$red: rgba(255, 69, 69, 0.85) !default;
-$orange: #fd7e14 !default;
-$yellow: #ffc107 !default;
-$green: rgba(116,147,99, 1) !default;
-$teal: #20c997 !default;
-$cyan: #17a2b8 !default;
+$blue: #007ACC !default;
+$indigo: #6610f2 !default;
+$purple: #6f42c1 !default;
+$pink: #e83e8c !default;
+$red: rgba(255, 69, 69, 0.85) !default;
+$orange: #fd7e14 !default;
+$yellow: #ffc107 !default;
+$green: rgba(116,147,99, 1) !default;
+$teal: #20c997 !default;
+$cyan: #17a2b8 !default;
$colors: () !default;
-$colors: map-merge((
- "blue": rgb(0, 122, 204),
- "indigo": $indigo,
- "purple": $purple,
- "pink": $pink,
- "red": $red,
- "orange": rgb(255, 102, 51),
- "yellow": $yellow,
- "green": $green,
- "teal": $teal,
- "cyan": $cyan,
- "white": $white,
- "gray": $gray-600,
- "gray-dark": $gray-800
-), $colors);
+$colors: map-merge(( "blue": rgb(0, 122, 204), "indigo": $indigo, "purple": $purple, "pink": $pink, "red": $red, "orange": rgb(255, 102, 51), "yellow": $yellow, "green": $green, "teal": $teal, "cyan": $cyan, "white": $white, "gray": $gray-600, "gray-dark": $gray-800 ), $colors);
-$primary: $blue !default;
-$secondary: $orange !default;
-$success: $green !default;
-$info: $cyan !default;
-$warning: $yellow !default;
-$danger: $red !default;
-$light: rgb(204, 204, 204) !default;
-$dark: rgb(24, 24, 24) !default;
+$primary: $blue !default;
+$secondary: $orange !default;
+$success: $green !default;
+$info: $cyan !default;
+$warning: $yellow !default;
+$danger: $red !default;
+$light: rgb(204, 204, 204) !default;
+$dark: rgb(24, 24, 24) !default;
$theme-colors: () !default;
-$theme-colors: map-merge((
- "primary": $primary,
- "secondary": $secondary,
- "success": $success,
- "info": $info,
- "warning": $warning,
- "danger": $danger,
- "light": $light,
- "dark": $dark
-), $theme-colors);
+$theme-colors: map-merge(( "primary": $primary, "secondary": $secondary, "success": $success, "info": $info, "warning": $warning, "danger": $danger, "light": $light, "dark": $dark ), $theme-colors);
// stylelint-enable
// Set a specific jump point for requesting color jumps
-$theme-color-interval: 8% !default;
+$theme-color-interval: 8% !default;
// The yiq lightness value that determines when the lightness of color changes from "dark" to "light". Acceptable values are between 0 and 255.
$yiq-contrasted-threshold: 150 !default;
@@ -98,14 +65,14 @@ $yiq-text-light: $white !default;
//
// Quickly modify global styling by enabling or disabling optional features.
-$enable-caret: true !default;
-$enable-rounded: true !default;
-$enable-shadows: false !default;
-$enable-gradients: false !default;
-$enable-transitions: true !default;
-$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS
-$enable-grid-classes: true !default;
-$enable-print-styles: true !default;
+$enable-caret: true !default;
+$enable-rounded: true !default;
+$enable-shadows: false !default;
+$enable-gradients: false !default;
+$enable-transitions: true !default;
+$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS
+$enable-grid-classes: true !default;
+$enable-print-styles: true !default;
// Spacing
@@ -117,46 +84,34 @@ $enable-print-styles: true !default;
// stylelint-disable
$spacer: 1rem !default;
$spacers: () !default;
-$spacers: map-merge((
- 0: 0,
- 1: ($spacer * .25),
- 2: ($spacer * .5),
- 3: $spacer,
- 4: ($spacer * 1.5),
- 5: ($spacer * 3)
-), $spacers);
+$spacers: map-merge(( 0: 0, 1: ($spacer * .25), 2: ($spacer * .5), 3: $spacer, 4: ($spacer * 1.5), 5: ($spacer * 3) ), $spacers);
// This variable affects the `.h-*` and `.w-*` classes.
$sizes: () !default;
-$sizes: map-merge((
- 25: 25%,
- 50: 50%,
- 75: 75%,
- 100: 100%
-), $sizes);
+$sizes: map-merge(( 25: 25%, 50: 50%, 75: 75%, 100: 100% ), $sizes);
// stylelint-enable
// Body
//
// Settings for the `` element.
-$body-bg: rgb(34,34,34) !default;
-$body-color: $white !default;
+$body-bg: rgb(34,34,34) !default;
+$body-color: $white !default;
// Links
//
// Style anchor elements.
-$link-color: $white !default;
-$link-decoration: none !default;
-$link-hover-color: $primary !default;
-$link-hover-decoration: none !default;
+$link-color: $white !default;
+$link-decoration: none !default;
+$link-hover-color: $primary !default;
+$link-hover-decoration: none !default;
// Paragraphs
//
// Style p element.
-$paragraph-margin-bottom: 1rem !default;
+$paragraph-margin-bottom: 1rem !default;
// Grid breakpoints
@@ -164,13 +119,7 @@ $paragraph-margin-bottom: 1rem !default;
// Define the minimum dimensions at which your layout will change,
// adapting to different screen sizes, for use in media queries.
-$grid-breakpoints: (
- xs: 0,
- sm: 576px,
- md: 768px,
- lg: 992px,
- xl: 1200px
-) !default;
+$grid-breakpoints: ( xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px ) !default;
@include _assert-ascending($grid-breakpoints, "$grid-breakpoints");
@include _assert-starts-at-zero($grid-breakpoints);
@@ -180,12 +129,7 @@ $grid-breakpoints: (
//
// Define the maximum width of `.container` for different screen sizes.
-$container-max-widths: (
- sm: 540px,
- md: 720px,
- lg: 960px,
- xl: 1140px
-) !default;
+$container-max-widths: ( sm: 540px, md: 720px, lg: 960px, xl: 1140px ) !default;
@include _assert-ascending($container-max-widths, "$container-max-widths");
@@ -194,31 +138,31 @@ $container-max-widths: (
//
// Set the number of columns and specify the width of the gutters.
-$grid-columns: 12 !default;
-$grid-gutter-width: 30px !default;
+$grid-columns: 12 !default;
+$grid-gutter-width: 30px !default;
// Components
//
// Define common padding and border radius sizes and more.
-$line-height-lg: 1.5 !default;
-$line-height-sm: 1.5 !default;
+$line-height-lg: 1.5 !default;
+$line-height-sm: 1.5 !default;
-$border-width: 1px !default;
-$border-color: $gray-300 !default;
+$border-width: 1px !default;
+$border-color: $gray-300 !default;
-$border-radius: .25rem !default;
-$border-radius-lg: .3rem !default;
-$border-radius-sm: .2rem !default;
+$border-radius: .25rem !default;
+$border-radius-lg: .3rem !default;
+$border-radius-sm: .2rem !default;
-$component-active-color: $white !default;
-$component-active-bg: theme-color("primary") !default;
+$component-active-color: $white !default;
+$component-active-bg: theme-color("primary") !default;
-$caret-width: .3em !default;
+$caret-width: .3em !default;
-$transition-base: all .2s ease-in-out !default;
-$transition-fade: opacity .15s linear !default;
-$transition-collapse: height .35s ease !default;
+$transition-base: all .2s ease-in-out !default;
+$transition-fade: opacity .15s linear !default;
+$transition-collapse: height .35s ease !default;
// Fonts
@@ -226,332 +170,330 @@ $transition-collapse: height .35s ease !default;
// Font, line-height, and color for body text, headings, and more.
// stylelint-disable value-keyword-case
-$font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Open Sans", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;
-$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default;
-$font-family-base: $font-family-sans-serif !default;
+$font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Open Sans", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;
+$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default;
+$font-family-base: $font-family-sans-serif !default;
// stylelint-enable value-keyword-case
-$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`
-$font-size-lg: ($font-size-base * 1.25) !default;
-$font-size-sm: ($font-size-base * .875) !default;
+$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`
+$font-size-lg: ($font-size-base * 1.25) !default;
+$font-size-sm: ($font-size-base * .875) !default;
-$font-weight-light: 300 !default;
-$font-weight-normal: 400 !default;
-$font-weight-bold: 700 !default;
+$font-weight-light: 300 !default;
+$font-weight-normal: 400 !default;
+$font-weight-bold: 700 !default;
-$font-weight-base: $font-weight-normal !default;
-$line-height-base: 1.5 !default;
+$font-weight-base: $font-weight-normal !default;
+$line-height-base: 1.5 !default;
-$h1-font-size: $font-size-base * 2.5 !default;
-$h2-font-size: $font-size-base * 2 !default;
-$h3-font-size: $font-size-base * 1.75 !default;
-$h4-font-size: $font-size-base * 1.5 !default;
-$h5-font-size: $font-size-base * 1.25 !default;
-$h6-font-size: $font-size-base !default;
+$h1-font-size: $font-size-base * 2.5 !default;
+$h2-font-size: $font-size-base * 2 !default;
+$h3-font-size: $font-size-base * 1.75 !default;
+$h4-font-size: $font-size-base * 1.5 !default;
+$h5-font-size: $font-size-base * 1.25 !default;
+$h6-font-size: $font-size-base !default;
-$headings-margin-bottom: ($spacer / 2) !default;
-$headings-font-family: inherit !default;
-$headings-font-weight: 500 !default;
-$headings-line-height: 1.2 !default;
-$headings-color: inherit !default;
+$headings-margin-bottom: ($spacer / 2) !default;
+$headings-font-family: inherit !default;
+$headings-font-weight: 500 !default;
+$headings-line-height: 1.2 !default;
+$headings-color: inherit !default;
-$display1-size: 6rem !default;
-$display2-size: 5.5rem !default;
-$display3-size: 4.5rem !default;
-$display4-size: 3.5rem !default;
+$display1-size: 6rem !default;
+$display2-size: 5.5rem !default;
+$display3-size: 4.5rem !default;
+$display4-size: 3.5rem !default;
-$display1-weight: 300 !default;
-$display2-weight: 300 !default;
-$display3-weight: 300 !default;
-$display4-weight: 300 !default;
-$display-line-height: $headings-line-height !default;
+$display1-weight: 300 !default;
+$display2-weight: 300 !default;
+$display3-weight: 300 !default;
+$display4-weight: 300 !default;
+$display-line-height: $headings-line-height !default;
-$lead-font-size: ($font-size-base * 1.25) !default;
-$lead-font-weight: 300 !default;
+$lead-font-size: ($font-size-base * 1.25) !default;
+$lead-font-weight: 300 !default;
-$small-font-size: 80% !default;
+$small-font-size: 80% !default;
-$text-muted: $gray-600 !default;
+$text-muted: $gray-600 !default;
-$blockquote-small-color: $gray-600 !default;
-$blockquote-font-size: ($font-size-base * 1.25) !default;
+$blockquote-small-color: $gray-600 !default;
+$blockquote-font-size: ($font-size-base * 1.25) !default;
-$hr-border-color: rgba($black, .1) !default;
-$hr-border-width: $border-width !default;
+$hr-border-color: rgba($black, .1) !default;
+$hr-border-width: $border-width !default;
-$mark-padding: .2em !default;
+$mark-padding: .2em !default;
-$dt-font-weight: $font-weight-bold !default;
+$dt-font-weight: $font-weight-bold !default;
-$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;
-$nested-kbd-font-weight: $font-weight-bold !default;
+$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;
+$nested-kbd-font-weight: $font-weight-bold !default;
-$list-inline-padding: .5rem !default;
+$list-inline-padding: .5rem !default;
-$mark-bg: #fcf8e3 !default;
+$mark-bg: #fcf8e3 !default;
-$hr-margin-y: $spacer !default;
+$hr-margin-y: $spacer !default;
// Tables
//
// Customizes the `.table` component with basic values, each used across all table variations.
-$table-cell-padding: .75rem !default;
-$table-cell-padding-sm: .3rem !default;
+$table-cell-padding: .75rem !default;
+$table-cell-padding-sm: .3rem !default;
-$table-bg: transparent !default;
-$table-accent-bg: rgba($black, .05) !default;
-$table-hover-bg: rgba($black, .075) !default;
-$table-active-bg: $table-hover-bg !default;
+$table-bg: transparent !default;
+$table-accent-bg: rgba($black, .05) !default;
+$table-hover-bg: rgba($black, .075) !default;
+$table-active-bg: $table-hover-bg !default;
-$table-border-width: $border-width !default;
-$table-border-color: $gray-300 !default;
+$table-border-width: $border-width !default;
+$table-border-color: $gray-300 !default;
-$table-head-bg: $gray-200 !default;
-$table-head-color: $gray-700 !default;
+$table-head-bg: $gray-200 !default;
+$table-head-color: $gray-700 !default;
-$table-dark-bg: $gray-900 !default;
-$table-dark-accent-bg: rgba($white, .05) !default;
-$table-dark-hover-bg: rgba($white, .075) !default;
-$table-dark-border-color: lighten($gray-900, 7.5%) !default;
-$table-dark-color: $body-bg !default;
+$table-dark-bg: $gray-900 !default;
+$table-dark-accent-bg: rgba($white, .05) !default;
+$table-dark-hover-bg: rgba($white, .075) !default;
+$table-dark-border-color: lighten($gray-900, 7.5%) !default;
+$table-dark-color: $body-bg !default;
// Buttons + Forms
//
// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.
-$input-btn-padding-y: .375rem !default;
-$input-btn-padding-x: .75rem !default;
-$input-btn-line-height: $line-height-base !default;
+$input-btn-padding-y: .375rem !default;
+$input-btn-padding-x: .75rem !default;
+$input-btn-line-height: $line-height-base !default;
-$input-btn-focus-width: .2rem !default;
-$input-btn-focus-color: rgba($component-active-bg, .25) !default;
-$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;
+$input-btn-focus-width: .2rem !default;
+$input-btn-focus-color: rgba($component-active-bg, .25) !default;
+$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;
-$input-btn-padding-y-sm: .25rem !default;
-$input-btn-padding-x-sm: .5rem !default;
-$input-btn-line-height-sm: $line-height-sm !default;
+$input-btn-padding-y-sm: .25rem !default;
+$input-btn-padding-x-sm: .5rem !default;
+$input-btn-line-height-sm: $line-height-sm !default;
-$input-btn-padding-y-lg: .5rem !default;
-$input-btn-padding-x-lg: 1rem !default;
-$input-btn-line-height-lg: $line-height-lg !default;
+$input-btn-padding-y-lg: .5rem !default;
+$input-btn-padding-x-lg: 1rem !default;
+$input-btn-line-height-lg: $line-height-lg !default;
-$input-btn-border-width: $border-width !default;
+$input-btn-border-width: $border-width !default;
// Buttons
//
// For each of Bootstrap's buttons, define text, background, and border color.
-$btn-padding-y: $input-btn-padding-y !default;
-$btn-padding-x: $input-btn-padding-x !default;
-$btn-line-height: $input-btn-line-height !default;
+$btn-padding-y: $input-btn-padding-y !default;
+$btn-padding-x: $input-btn-padding-x !default;
+$btn-line-height: $input-btn-line-height !default;
-$btn-padding-y-sm: $input-btn-padding-y-sm !default;
-$btn-padding-x-sm: $input-btn-padding-x-sm !default;
-$btn-line-height-sm: $input-btn-line-height-sm !default;
+$btn-padding-y-sm: $input-btn-padding-y-sm !default;
+$btn-padding-x-sm: $input-btn-padding-x-sm !default;
+$btn-line-height-sm: $input-btn-line-height-sm !default;
-$btn-padding-y-lg: $input-btn-padding-y-lg !default;
-$btn-padding-x-lg: $input-btn-padding-x-lg !default;
-$btn-line-height-lg: $input-btn-line-height-lg !default;
+$btn-padding-y-lg: $input-btn-padding-y-lg !default;
+$btn-padding-x-lg: $input-btn-padding-x-lg !default;
+$btn-line-height-lg: $input-btn-line-height-lg !default;
-$btn-border-width: $input-btn-border-width !default;
+$btn-border-width: $input-btn-border-width !default;
-$btn-font-weight: $font-weight-normal !default;
-$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;
-$btn-focus-width: $input-btn-focus-width !default;
-$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;
-$btn-disabled-opacity: .65 !default;
-$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;
+$btn-font-weight: $font-weight-normal !default;
+$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;
+$btn-focus-width: $input-btn-focus-width !default;
+$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;
+$btn-disabled-opacity: .65 !default;
+$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;
-$btn-link-disabled-color: $gray-600 !default;
+$btn-link-disabled-color: $gray-600 !default;
-$btn-block-spacing-y: .5rem !default;
+$btn-block-spacing-y: .5rem !default;
// Allows for customizing button radius independently from global border radius
-$btn-border-radius: $border-radius !default;
-$btn-border-radius-lg: $border-radius-lg !default;
-$btn-border-radius-sm: $border-radius-sm !default;
+$btn-border-radius: $border-radius !default;
+$btn-border-radius-lg: $border-radius-lg !default;
+$btn-border-radius-sm: $border-radius-sm !default;
-$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
+$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
// Forms
-$input-padding-y: $input-btn-padding-y !default;
-$input-padding-x: $input-btn-padding-x !default;
-$input-line-height: $input-btn-line-height !default;
+$input-padding-y: $input-btn-padding-y !default;
+$input-padding-x: $input-btn-padding-x !default;
+$input-line-height: $input-btn-line-height !default;
-$input-padding-y-sm: $input-btn-padding-y-sm !default;
-$input-padding-x-sm: $input-btn-padding-x-sm !default;
-$input-line-height-sm: $input-btn-line-height-sm !default;
+$input-padding-y-sm: $input-btn-padding-y-sm !default;
+$input-padding-x-sm: $input-btn-padding-x-sm !default;
+$input-line-height-sm: $input-btn-line-height-sm !default;
-$input-padding-y-lg: $input-btn-padding-y-lg !default;
-$input-padding-x-lg: $input-btn-padding-x-lg !default;
-$input-line-height-lg: $input-btn-line-height-lg !default;
+$input-padding-y-lg: $input-btn-padding-y-lg !default;
+$input-padding-x-lg: $input-btn-padding-x-lg !default;
+$input-line-height-lg: $input-btn-line-height-lg !default;
-$input-bg: $white !default;
-$input-disabled-bg: $gray-200 !default;
+$input-bg: $white !default;
+$input-disabled-bg: $gray-200 !default;
-$input-color: $gray-700 !default;
-$input-border-color: $gray-400 !default;
-$input-border-width: $input-btn-border-width !default;
-$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;
+$input-color: $gray-700 !default;
+$input-border-color: $gray-400 !default;
+$input-border-width: $input-btn-border-width !default;
+$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;
-$input-border-radius: $border-radius !default;
-$input-border-radius-lg: $border-radius-lg !default;
-$input-border-radius-sm: $border-radius-sm !default;
+$input-border-radius: $border-radius !default;
+$input-border-radius-lg: $border-radius-lg !default;
+$input-border-radius-sm: $border-radius-sm !default;
-$input-focus-bg: $input-bg !default;
-$input-focus-border-color: lighten($component-active-bg, 25%) !default;
-$input-focus-color: $input-color !default;
-$input-focus-width: $input-btn-focus-width !default;
-$input-focus-box-shadow: $input-btn-focus-box-shadow !default;
+$input-focus-bg: $input-bg !default;
+$input-focus-border-color: lighten($component-active-bg, 25%) !default;
+$input-focus-color: $input-color !default;
+$input-focus-width: $input-btn-focus-width !default;
+$input-focus-box-shadow: $input-btn-focus-box-shadow !default;
-$input-placeholder-color: $gray-600 !default;
+$input-placeholder-color: $gray-600 !default;
-$input-height-border: $input-border-width * 2 !default;
+$input-height-border: $input-border-width * 2 !default;
-$input-height-inner: ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default;
-$input-height: calc(#{$input-height-inner} + #{$input-height-border}) !default;
+$input-height-inner: ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default;
+$input-height: calc(#{$input-height-inner} + #{$input-height-border}) !default;
-$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default;
-$input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}) !default;
+$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default;
+$input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}) !default;
-$input-height-inner-lg: ($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default;
-$input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}) !default;
+$input-height-inner-lg: ($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default;
+$input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}) !default;
-$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
+$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
-$form-text-margin-top: .25rem !default;
+$form-text-margin-top: .25rem !default;
-$form-check-input-gutter: 1.25rem !default;
-$form-check-input-margin-y: .3rem !default;
-$form-check-input-margin-x: .25rem !default;
+$form-check-input-gutter: 1.25rem !default;
+$form-check-input-margin-y: .3rem !default;
+$form-check-input-margin-x: .25rem !default;
-$form-check-inline-margin-x: .75rem !default;
-$form-check-inline-input-margin-x: .3125rem !default;
+$form-check-inline-margin-x: .75rem !default;
+$form-check-inline-input-margin-x: .3125rem !default;
-$form-group-margin-bottom: 1rem !default;
+$form-group-margin-bottom: 1rem !default;
-$input-group-addon-color: $input-color !default;
-$input-group-addon-bg: $gray-200 !default;
-$input-group-addon-border-color: $input-border-color !default;
+$input-group-addon-color: $input-color !default;
+$input-group-addon-bg: $gray-200 !default;
+$input-group-addon-border-color: $input-border-color !default;
-$custom-control-gutter: 1.5rem !default;
-$custom-control-spacer-x: 1rem !default;
+$custom-control-gutter: 1.5rem !default;
+$custom-control-spacer-x: 1rem !default;
-$custom-control-indicator-size: 1rem !default;
-$custom-control-indicator-bg: $gray-300 !default;
-$custom-control-indicator-bg-size: 50% 50% !default;
-$custom-control-indicator-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;
+$custom-control-indicator-size: 1rem !default;
+$custom-control-indicator-bg: $gray-300 !default;
+$custom-control-indicator-bg-size: 50% 50% !default;
+$custom-control-indicator-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;
-$custom-control-indicator-disabled-bg: $gray-200 !default;
-$custom-control-label-disabled-color: $gray-600 !default;
+$custom-control-indicator-disabled-bg: $gray-200 !default;
+$custom-control-label-disabled-color: $gray-600 !default;
-$custom-control-indicator-checked-color: $component-active-color !default;
-$custom-control-indicator-checked-bg: $component-active-bg !default;
-$custom-control-indicator-checked-disabled-bg: rgba(theme-color("primary"), .5) !default;
-$custom-control-indicator-checked-box-shadow: none !default;
+$custom-control-indicator-checked-color: $component-active-color !default;
+$custom-control-indicator-checked-bg: $component-active-bg !default;
+$custom-control-indicator-checked-disabled-bg: rgba(theme-color("primary"), .5) !default;
+$custom-control-indicator-checked-box-shadow: none !default;
-$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;
+$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;
-$custom-control-indicator-active-color: $component-active-color !default;
-$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;
-$custom-control-indicator-active-box-shadow: none !default;
+$custom-control-indicator-active-color: $component-active-color !default;
+$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;
+$custom-control-indicator-active-box-shadow: none !default;
-$custom-checkbox-indicator-border-radius: $border-radius !default;
-$custom-checkbox-indicator-icon-checked: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"), "#", "%23") !default;
+$custom-checkbox-indicator-border-radius: $border-radius !default;
+$custom-checkbox-indicator-icon-checked: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"), "#", "%23") !default;
-$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;
+$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;
$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;
-$custom-checkbox-indicator-icon-indeterminate: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3E%3C/svg%3E"), "#", "%23") !default;
+$custom-checkbox-indicator-icon-indeterminate: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3E%3C/svg%3E"), "#", "%23") !default;
$custom-checkbox-indicator-indeterminate-box-shadow: none !default;
-$custom-radio-indicator-border-radius: 50% !default;
-$custom-radio-indicator-icon-checked: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3E%3C/svg%3E"), "#", "%23") !default;
+$custom-radio-indicator-border-radius: 50% !default;
+$custom-radio-indicator-icon-checked: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3E%3C/svg%3E"), "#", "%23") !default;
-$custom-select-padding-y: .375rem !default;
-$custom-select-padding-x: .75rem !default;
-$custom-select-height: $input-height !default;
-$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator
-$custom-select-line-height: $input-btn-line-height !default;
-$custom-select-color: $input-color !default;
-$custom-select-disabled-color: $gray-600 !default;
-$custom-select-bg: $white !default;
-$custom-select-disabled-bg: $gray-200 !default;
-$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions
-$custom-select-indicator-color: $gray-800 !default;
-$custom-select-indicator: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E"), "#", "%23") !default;
-$custom-select-border-width: $input-btn-border-width !default;
-$custom-select-border-color: $input-border-color !default;
-$custom-select-border-radius: $border-radius !default;
+$custom-select-padding-y: .375rem !default;
+$custom-select-padding-x: .75rem !default;
+$custom-select-height: $input-height !default;
+$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator
+$custom-select-line-height: $input-btn-line-height !default;
+$custom-select-color: $input-color !default;
+$custom-select-disabled-color: $gray-600 !default;
+$custom-select-bg: $white !default;
+$custom-select-disabled-bg: $gray-200 !default;
+$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions
+$custom-select-indicator-color: $gray-800 !default;
+$custom-select-indicator: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E"), "#", "%23") !default;
+$custom-select-border-width: $input-btn-border-width !default;
+$custom-select-border-color: $input-border-color !default;
+$custom-select-border-radius: $border-radius !default;
-$custom-select-focus-border-color: $input-focus-border-color !default;
-$custom-select-focus-box-shadow: inset 0 1px 2px rgba($black, .075), 0 0 5px rgba($custom-select-focus-border-color, .5) !default;
+$custom-select-focus-border-color: $input-focus-border-color !default;
+$custom-select-focus-box-shadow: inset 0 1px 2px rgba($black, .075), 0 0 5px rgba($custom-select-focus-border-color, .5) !default;
-$custom-select-font-size-sm: 75% !default;
-$custom-select-height-sm: $input-height-sm !default;
+$custom-select-font-size-sm: 75% !default;
+$custom-select-height-sm: $input-height-sm !default;
-$custom-select-font-size-lg: 125% !default;
-$custom-select-height-lg: $input-height-lg !default;
+$custom-select-font-size-lg: 125% !default;
+$custom-select-height-lg: $input-height-lg !default;
-$custom-file-height: $input-height !default;
-$custom-file-focus-border-color: $input-focus-border-color !default;
-$custom-file-focus-box-shadow: $input-btn-focus-box-shadow !default;
+$custom-file-height: $input-height !default;
+$custom-file-focus-border-color: $input-focus-border-color !default;
+$custom-file-focus-box-shadow: $input-btn-focus-box-shadow !default;
-$custom-file-padding-y: $input-btn-padding-y !default;
-$custom-file-padding-x: $input-btn-padding-x !default;
-$custom-file-line-height: $input-btn-line-height !default;
-$custom-file-color: $input-color !default;
-$custom-file-bg: $input-bg !default;
-$custom-file-border-width: $input-btn-border-width !default;
-$custom-file-border-color: $input-border-color !default;
-$custom-file-border-radius: $input-border-radius !default;
-$custom-file-box-shadow: $input-box-shadow !default;
-$custom-file-button-color: $custom-file-color !default;
-$custom-file-button-bg: $input-group-addon-bg !default;
-$custom-file-text: (
- en: "Browse"
-) !default;
+$custom-file-padding-y: $input-btn-padding-y !default;
+$custom-file-padding-x: $input-btn-padding-x !default;
+$custom-file-line-height: $input-btn-line-height !default;
+$custom-file-color: $input-color !default;
+$custom-file-bg: $input-bg !default;
+$custom-file-border-width: $input-btn-border-width !default;
+$custom-file-border-color: $input-border-color !default;
+$custom-file-border-radius: $input-border-radius !default;
+$custom-file-box-shadow: $input-box-shadow !default;
+$custom-file-button-color: $custom-file-color !default;
+$custom-file-button-bg: $input-group-addon-bg !default;
+$custom-file-text: ( en: "Browse" ) !default;
// Form validation
-$form-feedback-margin-top: $form-text-margin-top !default;
-$form-feedback-font-size: $small-font-size !default;
-$form-feedback-valid-color: theme-color("success") !default;
-$form-feedback-invalid-color: theme-color("danger") !default;
+$form-feedback-margin-top: $form-text-margin-top !default;
+$form-feedback-font-size: $small-font-size !default;
+$form-feedback-valid-color: theme-color("success") !default;
+$form-feedback-invalid-color: theme-color("danger") !default;
// Dropdowns
//
// Dropdown menu container and contents.
-$dropdown-min-width: 10rem !default;
-$dropdown-padding-y: .5rem !default;
-$dropdown-spacer: .125rem !default;
-$dropdown-bg: $white !default;
-$dropdown-border-color: rgba($black, .15) !default;
-$dropdown-border-radius: $border-radius !default;
-$dropdown-border-width: $border-width !default;
-$dropdown-divider-bg: $gray-200 !default;
-$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;
+$dropdown-min-width: 10rem !default;
+$dropdown-padding-y: .5rem !default;
+$dropdown-spacer: .125rem !default;
+$dropdown-bg: $white !default;
+$dropdown-border-color: rgba($black, .15) !default;
+$dropdown-border-radius: $border-radius !default;
+$dropdown-border-width: $border-width !default;
+$dropdown-divider-bg: $gray-200 !default;
+$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;
-$dropdown-link-color: $gray-900 !default;
-$dropdown-link-hover-color: darken($gray-900, 5%) !default;
-$dropdown-link-hover-bg: $gray-100 !default;
+$dropdown-link-color: $gray-900 !default;
+$dropdown-link-hover-color: darken($gray-900, 5%) !default;
+$dropdown-link-hover-bg: $gray-100 !default;
-$dropdown-link-active-color: $component-active-color !default;
-$dropdown-link-active-bg: $component-active-bg !default;
+$dropdown-link-active-color: $component-active-color !default;
+$dropdown-link-active-bg: $component-active-bg !default;
-$dropdown-link-disabled-color: $gray-600 !default;
+$dropdown-link-disabled-color: $gray-600 !default;
-$dropdown-item-padding-y: .25rem !default;
-$dropdown-item-padding-x: 1.5rem !default;
+$dropdown-item-padding-y: .25rem !default;
+$dropdown-item-padding-x: 1.5rem !default;
-$dropdown-header-color: $gray-600 !default;
+$dropdown-header-color: $gray-600 !default;
// Z-index master list
@@ -559,336 +501,336 @@ $dropdown-header-color: $gray-600 !default;
// Warning: Avoid customizing these values. They're used for a bird's eye view
// of components dependent on the z-axis and are designed to all work together.
-$zindex-dropdown: 1000 !default;
-$zindex-sticky: 1020 !default;
-$zindex-fixed: 1030 !default;
-$zindex-modal-backdrop: 1040 !default;
-$zindex-modal: 1050 !default;
-$zindex-popover: 1060 !default;
-$zindex-tooltip: 1070 !default;
+$zindex-dropdown: 1000 !default;
+$zindex-sticky: 1020 !default;
+$zindex-fixed: 1030 !default;
+$zindex-modal-backdrop: 1040 !default;
+$zindex-modal: 1050 !default;
+$zindex-popover: 1060 !default;
+$zindex-tooltip: 1070 !default;
// Navs
-$nav-link-padding-y: .5rem !default;
-$nav-link-padding-x: 1rem !default;
-$nav-link-disabled-color: $gray-600 !default;
+$nav-link-padding-y: .5rem !default;
+$nav-link-padding-x: 1rem !default;
+$nav-link-disabled-color: $gray-600 !default;
-$nav-tabs-border-color: $gray-300 !default;
-$nav-tabs-border-width: $border-width !default;
-$nav-tabs-border-radius: $border-radius !default;
-$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;
-$nav-tabs-link-active-color: $gray-700 !default;
-$nav-tabs-link-active-bg: $body-bg !default;
+$nav-tabs-border-color: $gray-300 !default;
+$nav-tabs-border-width: $border-width !default;
+$nav-tabs-border-radius: $border-radius !default;
+$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;
+$nav-tabs-link-active-color: $gray-700 !default;
+$nav-tabs-link-active-bg: $body-bg !default;
$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;
-$nav-pills-border-radius: $border-radius !default;
-$nav-pills-link-active-color: $component-active-color !default;
-$nav-pills-link-active-bg: $component-active-bg !default;
+$nav-pills-border-radius: $border-radius !default;
+$nav-pills-link-active-color: $component-active-color !default;
+$nav-pills-link-active-bg: $component-active-bg !default;
// Navbar
-$navbar-padding-y: 0 !default;
-$navbar-padding-x: $spacer !default;
+$navbar-padding-y: 0 !default;
+$navbar-padding-x: $spacer !default;
-$navbar-nav-link-padding-x: 2rem !default;
+$navbar-nav-link-padding-x: 2rem !default;
$navbar-brand-font-size: $h1-font-size !default;
// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link
-$nav-link-height: ($font-size-base * $line-height-base + $nav-link-padding-y * 2) !default;
-$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;
-$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;
+$nav-link-height: ($font-size-base * $line-height-base + $nav-link-padding-y * 2) !default;
+$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;
+$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;
-$navbar-toggler-padding-y: .25rem !default;
-$navbar-toggler-padding-x: .75rem !default;
-$navbar-toggler-font-size: $h5-font-size !default;
-$navbar-toggler-border-radius: $btn-border-radius !default;
+$navbar-toggler-padding-y: .25rem !default;
+$navbar-toggler-padding-x: .75rem !default;
+$navbar-toggler-font-size: $h5-font-size !default;
+$navbar-toggler-border-radius: $btn-border-radius !default;
-$navbar-dark-color: rgba($white, .5) !default;
-$navbar-dark-hover-color: $primary !default;
-$navbar-dark-active-color: $white !default;
-$navbar-dark-disabled-color: rgba($white, .25) !default;
-$navbar-dark-toggler-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"), "#", "%23") !default;
-$navbar-dark-toggler-border-color: rgba($white, .1) !default;
+$navbar-dark-color: rgba($white, .5) !default;
+$navbar-dark-hover-color: $primary !default;
+$navbar-dark-active-color: $white !default;
+$navbar-dark-disabled-color: rgba($white, .25) !default;
+$navbar-dark-toggler-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"), "#", "%23") !default;
+$navbar-dark-toggler-border-color: rgba($white, .1) !default;
-$navbar-light-color: rgba($black, .5) !default;
-$navbar-light-hover-color: rgba($black, .7) !default;
-$navbar-light-active-color: rgba($black, .9) !default;
-$navbar-light-disabled-color: rgba($black, .3) !default;
-$navbar-light-toggler-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"), "#", "%23") !default;
+$navbar-light-color: rgba($black, .5) !default;
+$navbar-light-hover-color: rgba($black, .7) !default;
+$navbar-light-active-color: rgba($black, .9) !default;
+$navbar-light-disabled-color: rgba($black, .3) !default;
+$navbar-light-toggler-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"), "#", "%23") !default;
$navbar-light-toggler-border-color: rgba($black, .1) !default;
// Pagination
-$pagination-padding-y: .5rem !default;
-$pagination-padding-x: .75rem !default;
-$pagination-padding-y-sm: .25rem !default;
-$pagination-padding-x-sm: .5rem !default;
-$pagination-padding-y-lg: .75rem !default;
-$pagination-padding-x-lg: 1.5rem !default;
-$pagination-line-height: 1.25 !default;
+$pagination-padding-y: .5rem !default;
+$pagination-padding-x: .75rem !default;
+$pagination-padding-y-sm: .25rem !default;
+$pagination-padding-x-sm: .5rem !default;
+$pagination-padding-y-lg: .75rem !default;
+$pagination-padding-x-lg: 1.5rem !default;
+$pagination-line-height: 1.25 !default;
-$pagination-color: $link-color !default;
-$pagination-bg: $white !default;
-$pagination-border-width: $border-width !default;
-$pagination-border-color: $gray-300 !default;
+$pagination-color: $link-color !default;
+$pagination-bg: $white !default;
+$pagination-border-width: $border-width !default;
+$pagination-border-color: $gray-300 !default;
-$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;
+$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;
-$pagination-hover-color: $link-hover-color !default;
-$pagination-hover-bg: $gray-200 !default;
-$pagination-hover-border-color: $gray-300 !default;
+$pagination-hover-color: $link-hover-color !default;
+$pagination-hover-bg: $gray-200 !default;
+$pagination-hover-border-color: $gray-300 !default;
-$pagination-active-color: $component-active-color !default;
-$pagination-active-bg: $component-active-bg !default;
-$pagination-active-border-color: $pagination-active-bg !default;
+$pagination-active-color: $component-active-color !default;
+$pagination-active-bg: $component-active-bg !default;
+$pagination-active-border-color: $pagination-active-bg !default;
-$pagination-disabled-color: $gray-600 !default;
-$pagination-disabled-bg: $white !default;
-$pagination-disabled-border-color: $gray-300 !default;
+$pagination-disabled-color: $gray-600 !default;
+$pagination-disabled-bg: $white !default;
+$pagination-disabled-border-color: $gray-300 !default;
// Jumbotron
-$jumbotron-padding: 2rem !default;
-$jumbotron-bg: $gray-200 !default;
+$jumbotron-padding: 2rem !default;
+$jumbotron-bg: $gray-200 !default;
// Cards
-$card-spacer-y: .75rem !default;
-$card-spacer-x: 1.25rem !default;
-$card-border-width: $border-width !default;
-$card-border-radius: $border-radius !default;
-$card-border-color: rgba($black, .125) !default;
-$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;
-$card-cap-bg: rgba($black, .03) !default;
-$card-bg: $white !default;
+$card-spacer-y: .75rem !default;
+$card-spacer-x: 1.25rem !default;
+$card-border-width: $border-width !default;
+$card-border-radius: $border-radius !default;
+$card-border-color: rgba($black, .125) !default;
+$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;
+$card-cap-bg: rgba($black, .03) !default;
+$card-bg: $white !default;
-$card-img-overlay-padding: 1.25rem !default;
+$card-img-overlay-padding: 1.25rem !default;
-$card-group-margin: ($grid-gutter-width / 2) !default;
-$card-deck-margin: $card-group-margin !default;
+$card-group-margin: ($grid-gutter-width / 2) !default;
+$card-deck-margin: $card-group-margin !default;
-$card-columns-count: 3 !default;
-$card-columns-gap: 1.25rem !default;
-$card-columns-margin: $card-spacer-y !default;
+$card-columns-count: 3 !default;
+$card-columns-gap: 1.25rem !default;
+$card-columns-margin: $card-spacer-y !default;
// Tooltips
-$tooltip-font-size: $font-size-sm !default;
-$tooltip-max-width: 200px !default;
-$tooltip-color: $white !default;
-$tooltip-bg: $black !default;
-$tooltip-border-radius: $border-radius !default;
-$tooltip-opacity: .9 !default;
-$tooltip-padding-y: .25rem !default;
-$tooltip-padding-x: .5rem !default;
-$tooltip-margin: 0 !default;
+$tooltip-font-size: $font-size-sm !default;
+$tooltip-max-width: 200px !default;
+$tooltip-color: $white !default;
+$tooltip-bg: $black !default;
+$tooltip-border-radius: $border-radius !default;
+$tooltip-opacity: .9 !default;
+$tooltip-padding-y: .25rem !default;
+$tooltip-padding-x: .5rem !default;
+$tooltip-margin: 0 !default;
-$tooltip-arrow-width: .8rem !default;
-$tooltip-arrow-height: .4rem !default;
-$tooltip-arrow-color: $tooltip-bg !default;
+$tooltip-arrow-width: .8rem !default;
+$tooltip-arrow-height: .4rem !default;
+$tooltip-arrow-color: $tooltip-bg !default;
// Popovers
-$popover-font-size: $font-size-sm !default;
-$popover-bg: $white !default;
-$popover-max-width: 276px !default;
-$popover-border-width: $border-width !default;
-$popover-border-color: rgba($black, .2) !default;
-$popover-border-radius: $border-radius-lg !default;
-$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;
+$popover-font-size: $font-size-sm !default;
+$popover-bg: $white !default;
+$popover-max-width: 276px !default;
+$popover-border-width: $border-width !default;
+$popover-border-color: rgba($black, .2) !default;
+$popover-border-radius: $border-radius-lg !default;
+$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;
-$popover-header-bg: darken($popover-bg, 3%) !default;
-$popover-header-color: $headings-color !default;
-$popover-header-padding-y: .5rem !default;
-$popover-header-padding-x: .75rem !default;
+$popover-header-bg: darken($popover-bg, 3%) !default;
+$popover-header-color: $headings-color !default;
+$popover-header-padding-y: .5rem !default;
+$popover-header-padding-x: .75rem !default;
-$popover-body-color: $body-color !default;
-$popover-body-padding-y: $popover-header-padding-y !default;
-$popover-body-padding-x: $popover-header-padding-x !default;
+$popover-body-color: $body-color !default;
+$popover-body-padding-y: $popover-header-padding-y !default;
+$popover-body-padding-x: $popover-header-padding-x !default;
-$popover-arrow-width: 1rem !default;
-$popover-arrow-height: .5rem !default;
-$popover-arrow-color: $popover-bg !default;
+$popover-arrow-width: 1rem !default;
+$popover-arrow-height: .5rem !default;
+$popover-arrow-color: $popover-bg !default;
-$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;
+$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;
// Badges
-$badge-font-size: 75% !default;
-$badge-font-weight: $font-weight-bold !default;
-$badge-padding-y: .25em !default;
-$badge-padding-x: .4em !default;
-$badge-border-radius: $border-radius !default;
+$badge-font-size: 75% !default;
+$badge-font-weight: $font-weight-bold !default;
+$badge-padding-y: .25em !default;
+$badge-padding-x: .4em !default;
+$badge-border-radius: $border-radius !default;
-$badge-pill-padding-x: .6em !default;
+$badge-pill-padding-x: .6em !default;
// Use a higher than normal value to ensure completely rounded edges when
// customizing padding or font-size on labels.
-$badge-pill-border-radius: 10rem !default;
+$badge-pill-border-radius: 10rem !default;
// Modals
// Padding applied to the modal body
-$modal-inner-padding: 1rem !default;
+$modal-inner-padding: 1rem !default;
-$modal-dialog-margin: .5rem !default;
+$modal-dialog-margin: .5rem !default;
$modal-dialog-margin-y-sm-up: 1.75rem !default;
-$modal-title-line-height: $line-height-base !default;
+$modal-title-line-height: $line-height-base !default;
-$modal-content-bg: $white !default;
-$modal-content-border-color: rgba($black, .2) !default;
-$modal-content-border-width: $border-width !default;
-$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;
+$modal-content-bg: $white !default;
+$modal-content-border-color: rgba($black, .2) !default;
+$modal-content-border-width: $border-width !default;
+$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;
$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;
-$modal-backdrop-bg: $black !default;
-$modal-backdrop-opacity: .5 !default;
-$modal-header-border-color: $gray-200 !default;
-$modal-footer-border-color: $modal-header-border-color !default;
-$modal-header-border-width: $modal-content-border-width !default;
-$modal-footer-border-width: $modal-header-border-width !default;
-$modal-header-padding: 1rem !default;
+$modal-backdrop-bg: $black !default;
+$modal-backdrop-opacity: .5 !default;
+$modal-header-border-color: $gray-200 !default;
+$modal-footer-border-color: $modal-header-border-color !default;
+$modal-header-border-width: $modal-content-border-width !default;
+$modal-footer-border-width: $modal-header-border-width !default;
+$modal-header-padding: 1rem !default;
-$modal-lg: 800px !default;
-$modal-md: 500px !default;
-$modal-sm: 300px !default;
+$modal-lg: 800px !default;
+$modal-md: 500px !default;
+$modal-sm: 300px !default;
-$modal-transition: transform .3s ease-out !default;
+$modal-transition: transform .3s ease-out !default;
// Alerts
//
// Define alert colors, border radius, and padding.
-$alert-padding-y: .75rem !default;
-$alert-padding-x: 1.25rem !default;
-$alert-margin-bottom: 1rem !default;
-$alert-border-radius: $border-radius !default;
-$alert-link-font-weight: $font-weight-bold !default;
-$alert-border-width: $border-width !default;
+$alert-padding-y: .75rem !default;
+$alert-padding-x: 1.25rem !default;
+$alert-margin-bottom: 1rem !default;
+$alert-border-radius: $border-radius !default;
+$alert-link-font-weight: $font-weight-bold !default;
+$alert-border-width: $border-width !default;
-$alert-bg-level: -10 !default;
-$alert-border-level: -9 !default;
-$alert-color-level: 6 !default;
+$alert-bg-level: -10 !default;
+$alert-border-level: -9 !default;
+$alert-color-level: 6 !default;
// Progress bars
-$progress-height: 1rem !default;
-$progress-font-size: ($font-size-base * .75) !default;
-$progress-bg: $gray-200 !default;
-$progress-border-radius: $border-radius !default;
-$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;
-$progress-bar-color: $white !default;
-$progress-bar-bg: theme-color("primary") !default;
-$progress-bar-animation-timing: 1s linear infinite !default;
-$progress-bar-transition: width .6s ease !default;
+$progress-height: 1rem !default;
+$progress-font-size: ($font-size-base * .75) !default;
+$progress-bg: $gray-200 !default;
+$progress-border-radius: $border-radius !default;
+$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;
+$progress-bar-color: $white !default;
+$progress-bar-bg: theme-color("primary") !default;
+$progress-bar-animation-timing: 1s linear infinite !default;
+$progress-bar-transition: width .6s ease !default;
// List group
-$list-group-bg: $white !default;
-$list-group-border-color: rgba($black, .125) !default;
-$list-group-border-width: $border-width !default;
-$list-group-border-radius: $border-radius !default;
+$list-group-bg: $white !default;
+$list-group-border-color: rgba($black, .125) !default;
+$list-group-border-width: $border-width !default;
+$list-group-border-radius: $border-radius !default;
-$list-group-item-padding-y: .75rem !default;
-$list-group-item-padding-x: 1.25rem !default;
+$list-group-item-padding-y: .75rem !default;
+$list-group-item-padding-x: 1.25rem !default;
-$list-group-hover-bg: $gray-100 !default;
-$list-group-active-color: $component-active-color !default;
-$list-group-active-bg: $component-active-bg !default;
-$list-group-active-border-color: $list-group-active-bg !default;
+$list-group-hover-bg: $gray-100 !default;
+$list-group-active-color: $component-active-color !default;
+$list-group-active-bg: $component-active-bg !default;
+$list-group-active-border-color: $list-group-active-bg !default;
-$list-group-disabled-color: $gray-600 !default;
-$list-group-disabled-bg: $list-group-bg !default;
+$list-group-disabled-color: $gray-600 !default;
+$list-group-disabled-bg: $list-group-bg !default;
-$list-group-action-color: $gray-700 !default;
-$list-group-action-hover-color: $list-group-action-color !default;
+$list-group-action-color: $gray-700 !default;
+$list-group-action-hover-color: $list-group-action-color !default;
-$list-group-action-active-color: $body-color !default;
-$list-group-action-active-bg: $gray-200 !default;
+$list-group-action-active-color: $body-color !default;
+$list-group-action-active-bg: $gray-200 !default;
// Image thumbnails
-$thumbnail-padding: .25rem !default;
-$thumbnail-bg: $body-bg !default;
-$thumbnail-border-width: $border-width !default;
-$thumbnail-border-color: $gray-300 !default;
-$thumbnail-border-radius: $border-radius !default;
-$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;
+$thumbnail-padding: .25rem !default;
+$thumbnail-bg: $body-bg !default;
+$thumbnail-border-width: $border-width !default;
+$thumbnail-border-color: $gray-300 !default;
+$thumbnail-border-radius: $border-radius !default;
+$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;
// Figures
-$figure-caption-font-size: 90% !default;
-$figure-caption-color: $gray-600 !default;
+$figure-caption-font-size: 90% !default;
+$figure-caption-color: $gray-600 !default;
// Breadcrumbs
-$breadcrumb-padding-y: .75rem !default;
-$breadcrumb-padding-x: 1rem !default;
-$breadcrumb-item-padding: .5rem !default;
+$breadcrumb-padding-y: .75rem !default;
+$breadcrumb-padding-x: 1rem !default;
+$breadcrumb-item-padding: .5rem !default;
-$breadcrumb-margin-bottom: 1rem !default;
+$breadcrumb-margin-bottom: 1rem !default;
-$breadcrumb-bg: $gray-200 !default;
-$breadcrumb-divider-color: $gray-600 !default;
-$breadcrumb-active-color: $gray-600 !default;
-$breadcrumb-divider: "/" !default;
+$breadcrumb-bg: $gray-200 !default;
+$breadcrumb-divider-color: $gray-600 !default;
+$breadcrumb-active-color: $gray-600 !default;
+$breadcrumb-divider: "/" !default;
// Carousel
-$carousel-control-color: $white !default;
-$carousel-control-width: 15% !default;
-$carousel-control-opacity: .5 !default;
+$carousel-control-color: $white !default;
+$carousel-control-width: 15% !default;
+$carousel-control-opacity: .5 !default;
-$carousel-indicator-width: 30px !default;
-$carousel-indicator-height: 3px !default;
-$carousel-indicator-spacer: 3px !default;
-$carousel-indicator-active-bg: $white !default;
+$carousel-indicator-width: 30px !default;
+$carousel-indicator-height: 3px !default;
+$carousel-indicator-spacer: 3px !default;
+$carousel-indicator-active-bg: $white !default;
-$carousel-caption-width: 70% !default;
-$carousel-caption-color: $white !default;
+$carousel-caption-width: 70% !default;
+$carousel-caption-color: $white !default;
-$carousel-control-icon-width: 20px !default;
+$carousel-control-icon-width: 20px !default;
-$carousel-control-prev-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"), "#", "%23") !default;
-$carousel-control-next-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"), "#", "%23") !default;
+$carousel-control-prev-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"), "#", "%23") !default;
+$carousel-control-next-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"), "#", "%23") !default;
-$carousel-transition: transform .6s ease !default;
+$carousel-transition: transform .6s ease !default;
// Close
-$close-font-size: $font-size-base * 1.5 !default;
-$close-font-weight: $font-weight-bold !default;
-$close-color: $black !default;
-$close-text-shadow: 0 1px 0 $white !default;
+$close-font-size: $font-size-base * 1.5 !default;
+$close-font-weight: $font-weight-bold !default;
+$close-color: $black !default;
+$close-text-shadow: 0 1px 0 $white !default;
// Code
-$code-font-size: 87.5% !default;
-$code-color: $pink !default;
+$code-font-size: 87.5% !default;
+$code-color: $pink !default;
-$kbd-padding-y: .2rem !default;
-$kbd-padding-x: .4rem !default;
-$kbd-font-size: $code-font-size !default;
-$kbd-color: $white !default;
-$kbd-bg: $gray-900 !default;
+$kbd-padding-y: .2rem !default;
+$kbd-padding-x: .4rem !default;
+$kbd-font-size: $code-font-size !default;
+$kbd-color: $white !default;
+$kbd-bg: $gray-900 !default;
-$pre-color: $gray-900 !default;
-$pre-scrollable-max-height: 340px !default;
+$pre-color: $gray-900 !default;
+$pre-scrollable-max-height: 340px !default;
// Printing
-$print-page-size: a3 !default;
-$print-body-min-width: map-get($grid-breakpoints, "lg") !default;
+$print-page-size: a3 !default;
+$print-body-min-width: map-get($grid-breakpoints, "lg") !default;