Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaShared/SharedSource/Text/LocalizedString/ServerMsgLString.cs
2022-02-26 02:43:01 +09:00

185 lines
7.3 KiB
C#

#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text.RegularExpressions;
namespace Barotrauma
{
public class ServerMsgLString : LocalizedString
{
private static readonly Regex reFormattedMessage =
new Regex(@"^(?<variable>[\[\].a-z0-9_]+?)=(?<formatter>[a-z0-9_]+?)\((?<value>.+?)\)",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex reReplacedMessage = new Regex(@"^(?<variable>[\[\].a-z0-9_]+?)=(?<message>.*)$",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly ImmutableDictionary<Identifier, Func<string, string?>> messageFormatters =
new Dictionary<Identifier, Func<string, string?>>
{
{
"duration".ToIdentifier(),
secondsValue => double.TryParse(secondsValue, out var seconds)
? $"{TimeSpan.FromSeconds(seconds):g}"
: null
}
}.ToImmutableDictionary();
private static readonly ImmutableHashSet<char> serverMessageCharacters =
new [] {'~', '[', ']', '='}.ToImmutableHashSet();
private readonly string serverMessage;
private readonly ImmutableArray<string> messageSplit;
public ServerMsgLString(string serverMsg)
{
serverMessage = serverMsg;
messageSplit = serverMessage.Split("/").ToImmutableArray();
}
private static bool IsServerMessageWithVariables(string message) =>
serverMessageCharacters.All(message.Contains);
private LoadedSuccessfully loadedSuccessfully = LoadedSuccessfully.Unknown;
public override bool Loaded
{
get
{
if (loadedSuccessfully == LoadedSuccessfully.Unknown) { RetrieveValue(); }
return loadedSuccessfully == LoadedSuccessfully.Yes;
}
}
public override void RetrieveValue()
{
Dictionary<string, string> replacedMessages = new Dictionary<string, string>();
bool translationsFound = false;
string? TranslateMessage(string input)
{
string? message = input;
if (message.EndsWith("~", StringComparison.Ordinal))
{
message = message.Substring(0, message.Length - 1);
}
if (!IsServerMessageWithVariables(message) && !message.Contains('=')) // No variables, try to translate
{
foreach (var replacedMessage in replacedMessages)
{
message = message.Replace(replacedMessage.Key, replacedMessage.Value);
}
if (message.Contains(" "))
{
return message;
} // Spaces found, do not translate
var msg = TextManager.Get(message);
if (msg.Loaded) // If a translation was found, otherwise use the original
{
message = msg.Value;
translationsFound = true;
}
}
else
{
string? messageVariable = null;
var matchFormatted = reFormattedMessage.Match(message);
if (matchFormatted.Success)
{
var formatter = matchFormatted.Groups["formatter"].ToString().ToIdentifier();
if (messageFormatters.TryGetValue(formatter, out var formatterFn))
{
var formattedValue = formatterFn(matchFormatted.Groups["value"].ToString());
if (formattedValue != null)
{
messageVariable = matchFormatted.Groups["variable"].ToString();
message = formattedValue;
}
}
}
if (messageVariable == null)
{
var matchReplaced = reReplacedMessage.Match(message);
if (matchReplaced.Success)
{
messageVariable = matchReplaced.Groups["variable"].ToString();
message = matchReplaced.Groups["message"].ToString();
}
}
foreach (var replacedMessage in replacedMessages)
{
message = message.Replace(replacedMessage.Key, replacedMessage.Value);
}
string[] messageWithVariables = message.Split('~');
var msg = TextManager.Get(messageWithVariables[0]);
if (msg.Loaded) // If a translation was found, otherwise use the original
{
message = msg.Value;
translationsFound = true;
}
else if (messageVariable == null)
{
return message; // No translation found, probably caused by player input -> skip variable handling
}
// First index is always the message identifier -> start at 1
for (int j = 1; j < messageWithVariables.Length; j++)
{
string[] variableAndValue = messageWithVariables[j].Split('=');
message = message.Replace(variableAndValue[0],
variableAndValue[1].Length > 1 && variableAndValue[1][0] == '§'
? TextManager.Get(variableAndValue[1].Substring(1)).Value
: variableAndValue[1]);
}
if (messageVariable != null)
{
replacedMessages[messageVariable] = message;
message = null;
}
}
return message;
}
try
{
string translatedServerMessage = "";
for (int i = 0; i < messageSplit.Length; i++)
{
string? message = TranslateMessage(messageSplit[i]);
if (message != null)
{
translatedServerMessage += message;
}
}
cachedValue = translationsFound ? translatedServerMessage : serverMessage;
loadedSuccessfully = LoadedSuccessfully.Yes;
}
catch (IndexOutOfRangeException exception)
{
string errorMsg = $"Failed to translate server message \"{serverMessage}\".";
#if DEBUG
DebugConsole.ThrowError(errorMsg, exception);
#endif
GameAnalyticsManager.AddErrorEventOnce($"TextManager.GetServerMessage:{serverMessage}",
GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
cachedValue = errorMsg;
loadedSuccessfully = LoadedSuccessfully.No;
}
UpdateLanguage();
}
}
}