Unstable 0.17.0.0
This commit is contained in:
+35
@@ -0,0 +1,35 @@
|
||||
#nullable enable
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class AddedPunctuationLString : LocalizedString
|
||||
{
|
||||
private readonly ImmutableArray<LocalizedString> nestedStrs;
|
||||
private readonly char punctuationSymbol;
|
||||
|
||||
public AddedPunctuationLString(char symbol, params LocalizedString[] nStrs) { nestedStrs = nStrs.ToImmutableArray(); punctuationSymbol = symbol; }
|
||||
|
||||
public override bool Loaded => nestedStrs.All(s => s.Loaded);
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
string separator = "";
|
||||
if (GameSettings.CurrentConfig.Language == "French".ToLanguageIdentifier())
|
||||
{
|
||||
bool addNonBreakingSpace =
|
||||
punctuationSymbol == ':' || punctuationSymbol == ';' ||
|
||||
punctuationSymbol == '!' || punctuationSymbol == '?';
|
||||
separator = addNonBreakingSpace ?
|
||||
new string(new char[] { (char)(0xA0), punctuationSymbol, ' ' }) :
|
||||
new string(new char[] { punctuationSymbol, ' ' });
|
||||
}
|
||||
else
|
||||
{
|
||||
separator = new string(new char[] { punctuationSymbol, ' ' });
|
||||
}
|
||||
cachedValue = string.Join(separator, nestedStrs.Select(str => str.Value));
|
||||
UpdateLanguage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#nullable enable
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class CapitalizeLString : LocalizedString
|
||||
{
|
||||
private readonly LocalizedString nestedStr;
|
||||
|
||||
public CapitalizeLString(LocalizedString nStr) { nestedStr = nStr; }
|
||||
|
||||
public override bool Loaded => nestedStr.Loaded;
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
string str = nestedStr.Value;
|
||||
if (!string.IsNullOrEmpty(str))
|
||||
{
|
||||
cachedValue = char.ToUpper(str[0]) + str[1..];
|
||||
}
|
||||
else
|
||||
{
|
||||
cachedValue = "";
|
||||
}
|
||||
UpdateLanguage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#nullable enable
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class ConcatLString : LocalizedString
|
||||
{
|
||||
private readonly LocalizedString left;
|
||||
private readonly LocalizedString right;
|
||||
|
||||
public ConcatLString(LocalizedString l, LocalizedString r)
|
||||
{
|
||||
left = l; right = r;
|
||||
}
|
||||
|
||||
public override bool Loaded => left.Loaded || right.Loaded;
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
cachedValue = left.Value + right.Value;
|
||||
UpdateLanguage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#nullable enable
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class FallbackLString : LocalizedString
|
||||
{
|
||||
private readonly LocalizedString primary;
|
||||
private readonly LocalizedString fallback;
|
||||
|
||||
private bool primaryIsLoaded = false;
|
||||
|
||||
public FallbackLString(LocalizedString primary, LocalizedString fallback)
|
||||
{
|
||||
if (primary is FallbackLString {primary: { } innerPrimary, fallback: { } innerFallback})
|
||||
{
|
||||
this.primary = innerPrimary;
|
||||
this.fallback = innerFallback.Fallback(fallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.primary = primary;
|
||||
this.fallback = fallback;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool MustRetrieveValue()
|
||||
{
|
||||
return base.MustRetrieveValue()
|
||||
|| MustRetrieveValue(primary)
|
||||
|| MustRetrieveValue(fallback)
|
||||
|| primaryIsLoaded != primary.Loaded;
|
||||
}
|
||||
|
||||
public override bool Loaded => primary.Loaded || fallback.Loaded;
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
cachedValue = primary.Value;
|
||||
primaryIsLoaded = primary.Loaded;
|
||||
if (!primary.Loaded)
|
||||
{
|
||||
cachedValue = fallback.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#nullable enable
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class FormattedLString : LocalizedString
|
||||
{
|
||||
private readonly LocalizedString str;
|
||||
private readonly ImmutableArray<LocalizedString> subStrs;
|
||||
public FormattedLString(LocalizedString str, params LocalizedString[] subStrs)
|
||||
{
|
||||
this.str = str;
|
||||
this.subStrs = subStrs.ToImmutableArray();
|
||||
}
|
||||
|
||||
public override bool Loaded => str.Loaded && subStrs.All(s => s.Loaded);
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
//TODO: possibly broken!
|
||||
cachedValue = string.Format(str.Value, subStrs.Select(s => s.Value as object).ToArray());
|
||||
UpdateLanguage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class InputTypeLString : LocalizedString
|
||||
{
|
||||
private readonly LocalizedString nestedStr;
|
||||
public InputTypeLString(LocalizedString nStr) { nestedStr = nStr; }
|
||||
|
||||
protected override bool MustRetrieveValue()
|
||||
{
|
||||
//TODO: check for config changes!
|
||||
return base.MustRetrieveValue();
|
||||
}
|
||||
|
||||
public override bool Loaded => nestedStr.Loaded;
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
cachedValue = nestedStr.Value;
|
||||
#if CLIENT
|
||||
//TODO: server shouldn't have this type at all
|
||||
foreach (InputType? inputType in Enum.GetValues(typeof(InputType)))
|
||||
{
|
||||
if (!inputType.HasValue) { continue; }
|
||||
cachedValue = cachedValue.Replace($"[{inputType}]", GameSettings.CurrentConfig.KeyMap.KeyBindText(inputType.Value).Value, StringComparison.OrdinalIgnoreCase);
|
||||
cachedValue = cachedValue.Replace($"[InputType.{inputType}]", GameSettings.CurrentConfig.KeyMap.KeyBindText(inputType.Value).Value, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
#endif
|
||||
UpdateLanguage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class JoinLString : LocalizedString
|
||||
{
|
||||
private readonly IEnumerable<LocalizedString> subStrs;
|
||||
private readonly string separator;
|
||||
|
||||
public JoinLString(string separator, IEnumerable<LocalizedString> subStrs)
|
||||
{
|
||||
this.separator = separator; this.subStrs = subStrs;
|
||||
}
|
||||
|
||||
public override bool Loaded => subStrs.All(s => s.Loaded);
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
cachedValue = string.Join(separator, subStrs);
|
||||
UpdateLanguage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public abstract class LocalizedString : IComparable
|
||||
{
|
||||
protected enum LoadedSuccessfully
|
||||
{
|
||||
Unknown,
|
||||
No,
|
||||
Yes
|
||||
}
|
||||
|
||||
protected LanguageIdentifier language { get; private set; } = LanguageIdentifier.None;
|
||||
private int languageVersion = 0;
|
||||
|
||||
protected string cachedValue = "";
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (MustRetrieveValue()) { RetrieveValue(); }
|
||||
return cachedValue;
|
||||
}
|
||||
}
|
||||
|
||||
public int Length => Value.Length;
|
||||
|
||||
public abstract bool Loaded { get; }
|
||||
|
||||
protected void UpdateLanguage()
|
||||
{
|
||||
language = GameSettings.CurrentConfig.Language;
|
||||
languageVersion = TextManager.LanguageVersion;
|
||||
}
|
||||
|
||||
protected virtual bool MustRetrieveValue() //this can't be called on other LocalizedStrings by derived classes
|
||||
{
|
||||
return language != GameSettings.CurrentConfig.Language || languageVersion != TextManager.LanguageVersion;
|
||||
}
|
||||
|
||||
protected static bool MustRetrieveValue(LocalizedString str) //this can be called by derived classes
|
||||
{
|
||||
return str.MustRetrieveValue();
|
||||
}
|
||||
|
||||
public abstract void RetrieveValue();
|
||||
|
||||
public static implicit operator LocalizedString(string value) => new RawLString(value);
|
||||
public static implicit operator LocalizedString(char value) => new RawLString(value.ToString());
|
||||
|
||||
public static LocalizedString operator+(LocalizedString left, LocalizedString right) => new ConcatLString(left, right);
|
||||
public static LocalizedString operator+(LocalizedString left, object right) => left + (right.ToString() ?? "");
|
||||
public static LocalizedString operator+(object left, LocalizedString right) => (left.ToString() ?? "") + right;
|
||||
|
||||
public static bool operator==(LocalizedString? left, LocalizedString? right)
|
||||
{
|
||||
return left?.Value == right?.Value;
|
||||
}
|
||||
|
||||
public static bool operator!=(LocalizedString? left, LocalizedString? right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
public bool Contains(string subStr, StringComparison comparison = StringComparison.Ordinal)
|
||||
{
|
||||
return !Value.IsNullOrEmpty() && Value.Contains(subStr, comparison);
|
||||
}
|
||||
|
||||
public bool Contains(char chr, StringComparison comparison = StringComparison.Ordinal)
|
||||
{
|
||||
return Value.Contains(chr, comparison);
|
||||
}
|
||||
|
||||
public virtual LocalizedString ToUpper()
|
||||
{
|
||||
return new UpperLString(this);
|
||||
}
|
||||
|
||||
public static LocalizedString Join(string separator, params LocalizedString[] subStrs)
|
||||
{
|
||||
return Join(separator, (IEnumerable<LocalizedString>)subStrs);
|
||||
}
|
||||
|
||||
public static LocalizedString Join(string separator, IEnumerable<LocalizedString> subStrs)
|
||||
{
|
||||
return new JoinLString(separator, subStrs);
|
||||
}
|
||||
|
||||
public LocalizedString Fallback(LocalizedString fallback)
|
||||
{
|
||||
return new FallbackLString(this, fallback);
|
||||
}
|
||||
|
||||
public IReadOnlyList<LocalizedString> Split(params char[] separators)
|
||||
{
|
||||
var splitter = new LStringSplitter(this, separators);
|
||||
return splitter.Substrings;
|
||||
}
|
||||
|
||||
public LocalizedString Replace(Identifier find, LocalizedString replace, StringComparison stringComparison = StringComparison.Ordinal)
|
||||
{
|
||||
return new ReplaceLString(this, stringComparison, (find, replace));
|
||||
}
|
||||
|
||||
public LocalizedString Replace(string find, LocalizedString replace, StringComparison stringComparison = StringComparison.Ordinal)
|
||||
{
|
||||
return new ReplaceLString(this, stringComparison, (find.ToIdentifier(), replace));
|
||||
}
|
||||
|
||||
public LocalizedString Replace(LocalizedString find, LocalizedString replace,
|
||||
StringComparison stringComparison = StringComparison.Ordinal)
|
||||
{
|
||||
return new ReplaceLString(this, stringComparison, (find, replace));
|
||||
}
|
||||
|
||||
public LocalizedString TrimStart()
|
||||
{
|
||||
return new TrimLString(this, TrimLString.Mode.Start);
|
||||
}
|
||||
|
||||
public LocalizedString TrimEnd()
|
||||
{
|
||||
return new TrimLString(this, TrimLString.Mode.End);
|
||||
}
|
||||
|
||||
public LocalizedString ToLower()
|
||||
{
|
||||
return new LowerLString(this);
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is LocalizedString lStr) { return Equals(lStr, StringComparison.Ordinal); }
|
||||
if (obj is string str) { return Equals(str, StringComparison.Ordinal); }
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
public bool Equals(LocalizedString other, StringComparison comparison = StringComparison.Ordinal)
|
||||
{
|
||||
return Equals(other.Value, comparison);
|
||||
}
|
||||
|
||||
public bool Equals(string other, StringComparison comparison = StringComparison.Ordinal)
|
||||
{
|
||||
return string.Equals(Value, other, comparison);
|
||||
}
|
||||
|
||||
public bool StartsWith(LocalizedString other, StringComparison comparison = StringComparison.Ordinal)
|
||||
{
|
||||
return StartsWith(other.Value, comparison);
|
||||
}
|
||||
|
||||
public bool StartsWith(string other, StringComparison comparison = StringComparison.Ordinal)
|
||||
{
|
||||
return Value.StartsWith(other, comparison);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Value.GetHashCode();
|
||||
}
|
||||
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
return Value.CompareTo(obj?.ToString() ?? "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#nullable enable
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class LowerLString : LocalizedString
|
||||
{
|
||||
private readonly LocalizedString nestedStr;
|
||||
|
||||
public LowerLString(LocalizedString nestedStr)
|
||||
{
|
||||
this.nestedStr = nestedStr;
|
||||
}
|
||||
|
||||
public override bool Loaded => nestedStr.Loaded;
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
cachedValue = nestedStr.Value.ToLowerInvariant();
|
||||
UpdateLanguage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#nullable enable
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class RawLString : LocalizedString
|
||||
{
|
||||
public RawLString(string value) { cachedValue = value; }
|
||||
|
||||
protected override bool MustRetrieveValue() => false;
|
||||
|
||||
public override bool Loaded => true;
|
||||
public override void RetrieveValue() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class ReplaceLString : LocalizedString
|
||||
{
|
||||
private readonly LocalizedString nestedStr;
|
||||
private readonly ImmutableDictionary<LocalizedString, (LocalizedString Value, FormatCapitals FormatCapitals)> replacements;
|
||||
private readonly StringComparison stringComparison;
|
||||
|
||||
public ReplaceLString(LocalizedString nStr, StringComparison sc, IEnumerable<(LocalizedString Key, LocalizedString Value, FormatCapitals FormatCapitals)> r)
|
||||
{
|
||||
nestedStr = nStr;
|
||||
replacements = r.Select(kvf => (kvf.Key, (kvf.Value, kvf.FormatCapitals))).ToImmutableDictionary();
|
||||
stringComparison = sc;
|
||||
}
|
||||
|
||||
public ReplaceLString(LocalizedString nStr, StringComparison sc, params (LocalizedString Key, LocalizedString Value)[] r)
|
||||
: this(nStr, sc, r.Select(kv => (kv.Key, kv.Value, FormatCapitals.No))) { }
|
||||
|
||||
public ReplaceLString(LocalizedString nStr, StringComparison sc, IEnumerable<(Identifier Key, LocalizedString Value, FormatCapitals FormatCapitals)> r)
|
||||
: this(nStr, sc, r.Select(p => ((LocalizedString)p.Key.Value, p.Value, p.FormatCapitals))) { }
|
||||
|
||||
public ReplaceLString(LocalizedString nStr, StringComparison sc, params (Identifier Key, LocalizedString Value)[] r)
|
||||
: this(nStr, sc, r.Select(kv => ((LocalizedString)kv.Key.Value, kv.Value, FormatCapitals.No))) { }
|
||||
|
||||
private static string HandleVariableCapitalization(string text, string variableTag, string variableValue)
|
||||
{
|
||||
int index = text.IndexOf(variableTag, StringComparison.InvariantCulture) - 1;
|
||||
if (index == -1)
|
||||
{
|
||||
return variableValue;
|
||||
}
|
||||
|
||||
for (int i = index; i >= 0; i--)
|
||||
{
|
||||
if (char.IsWhiteSpace(text[i])) { continue; }
|
||||
|
||||
if (text[i] != '.')
|
||||
{
|
||||
variableValue = variableValue.ToLowerInvariant();
|
||||
}
|
||||
else
|
||||
{
|
||||
variableValue = TextManager.Capitalize(variableValue).Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return variableValue;
|
||||
}
|
||||
|
||||
public override bool Loaded => nestedStr.Loaded;
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
cachedValue = nestedStr.Value;
|
||||
foreach (var varName in replacements.Keys)
|
||||
{
|
||||
string key = varName.Value;
|
||||
string value = replacements[varName].Value.Value;
|
||||
if (replacements[varName].FormatCapitals == FormatCapitals.Yes)
|
||||
{
|
||||
value = HandleVariableCapitalization(cachedValue, key, value);
|
||||
}
|
||||
cachedValue = cachedValue.Replace(key, value, stringComparison);
|
||||
}
|
||||
UpdateLanguage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
#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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
#nullable enable
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class LStringSplitter
|
||||
{
|
||||
public IReadOnlyList<LocalizedString> Substrings => substrings;
|
||||
|
||||
private class SubstringList : IReadOnlyList<LocalizedString>
|
||||
{
|
||||
public SubstringList(LStringSplitter splitter) { this.splitter = splitter; }
|
||||
|
||||
private LStringSplitter splitter;
|
||||
private readonly List<LocalizedString> underlyingList = new List<LocalizedString>();
|
||||
|
||||
public List<LocalizedString> UnderlyingList
|
||||
{
|
||||
get
|
||||
{
|
||||
splitter.UpdateSubstrings();
|
||||
return underlyingList;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<LocalizedString> GetEnumerator() => UnderlyingList.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
public int Count => UnderlyingList.Count;
|
||||
|
||||
public LocalizedString this[int index] => UnderlyingList[index];
|
||||
}
|
||||
|
||||
private readonly SubstringList substrings;
|
||||
private readonly char[] separators;
|
||||
private readonly LocalizedString originalString;
|
||||
private string[] substrValues;
|
||||
|
||||
private string cachedOriginal;
|
||||
|
||||
public bool Loaded => originalString.Loaded;
|
||||
|
||||
public LStringSplitter(LocalizedString input, params char[] separators)
|
||||
{
|
||||
originalString = input;
|
||||
substrings = new SubstringList(this);
|
||||
substrValues = Array.Empty<string>();
|
||||
this.separators = separators;
|
||||
cachedOriginal = "";
|
||||
}
|
||||
|
||||
private void UpdateSubstrings()
|
||||
{
|
||||
if (originalString.Value != cachedOriginal)
|
||||
{
|
||||
cachedOriginal = originalString.Value;
|
||||
substrValues = cachedOriginal.Split(separators);
|
||||
substrings.UnderlyingList.Clear();
|
||||
substrings.UnderlyingList.AddRange(Enumerable.Range(0, substrValues.Length).Select(i => new SplitLString(this, i) as LocalizedString));
|
||||
}
|
||||
}
|
||||
|
||||
public string GetValue(int index)
|
||||
{
|
||||
UpdateSubstrings();
|
||||
return substrValues[index];
|
||||
}
|
||||
}
|
||||
|
||||
public class SplitLString : LocalizedString
|
||||
{
|
||||
private bool loaded = false;
|
||||
private readonly LStringSplitter splitter;
|
||||
private readonly int index;
|
||||
|
||||
public SplitLString(LStringSplitter splitter, int index)
|
||||
{
|
||||
this.splitter = splitter; this.index = index;
|
||||
}
|
||||
|
||||
public override bool Loaded => loaded && splitter.Loaded;
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
loaded = true;
|
||||
cachedValue = splitter.GetValue(index);
|
||||
UpdateLanguage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class TagLString : LocalizedString
|
||||
{
|
||||
private readonly ImmutableArray<Identifier> tags;
|
||||
|
||||
public TagLString(params Identifier[] tags)
|
||||
{
|
||||
this.tags = tags.ToImmutableArray();
|
||||
}
|
||||
|
||||
private LoadedSuccessfully loadedSuccessfully = LoadedSuccessfully.Unknown;
|
||||
|
||||
public override bool Loaded
|
||||
{
|
||||
get
|
||||
{
|
||||
if (loadedSuccessfully == LoadedSuccessfully.Unknown) { RetrieveValue(); }
|
||||
return loadedSuccessfully == LoadedSuccessfully.Yes;
|
||||
}
|
||||
}
|
||||
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
UpdateLanguage();
|
||||
|
||||
(string value, bool loaded) tryLoad(LanguageIdentifier lang)
|
||||
{
|
||||
IReadOnlyList<string> candidates = Array.Empty<string>();
|
||||
int tagIndex = 0;
|
||||
|
||||
if (TextManager.TextPacks.TryGetValue(lang, out var packs))
|
||||
{
|
||||
while (candidates.Count == 0 && tagIndex < tags.Length)
|
||||
{
|
||||
foreach (var pack in packs)
|
||||
{
|
||||
if (pack.Texts.TryGetValue(tags[tagIndex], out var texts))
|
||||
{
|
||||
candidates = candidates.ListConcat(texts);
|
||||
}
|
||||
}
|
||||
tagIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
bool loaded = candidates.Count > 0;
|
||||
return (loaded ? candidates.GetRandomUnsynced() : "", loaded);
|
||||
}
|
||||
|
||||
var (value, loaded) = tryLoad(language);
|
||||
loadedSuccessfully = loaded ? LoadedSuccessfully.Yes : LoadedSuccessfully.No;
|
||||
cachedValue = value;
|
||||
if (!loaded && language != TextManager.DefaultLanguage)
|
||||
{
|
||||
(value, _) = tryLoad(TextManager.DefaultLanguage);
|
||||
cachedValue = value;
|
||||
//Notice how we don't set loadedSuccessfully again here.
|
||||
//This is by design; falling back to English means that
|
||||
//this text did NOT load successfully, so Loaded must
|
||||
//return false.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class TrimLString : LocalizedString
|
||||
{
|
||||
[Flags]
|
||||
public enum Mode { Start = 0x1, End = 0x2, Both=0x3 }
|
||||
private readonly LocalizedString nestedStr;
|
||||
private readonly Mode mode;
|
||||
|
||||
public TrimLString(LocalizedString nestedStr, Mode mode)
|
||||
{
|
||||
this.nestedStr = nestedStr;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public override bool Loaded => nestedStr.Loaded;
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
cachedValue = nestedStr.Value;
|
||||
if (mode.HasFlag(Mode.Start)) { cachedValue = cachedValue.TrimStart(); }
|
||||
if (mode.HasFlag(Mode.End)) { cachedValue = cachedValue.TrimEnd(); }
|
||||
UpdateLanguage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#nullable enable
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class UpperLString : LocalizedString
|
||||
{
|
||||
private readonly LocalizedString nestedStr;
|
||||
|
||||
public UpperLString(LocalizedString nestedStr)
|
||||
{
|
||||
this.nestedStr = nestedStr;
|
||||
}
|
||||
|
||||
public override bool Loaded => nestedStr.Loaded;
|
||||
public override void RetrieveValue()
|
||||
{
|
||||
cachedValue = nestedStr.Value.ToUpper();
|
||||
UpdateLanguage();
|
||||
}
|
||||
|
||||
public override LocalizedString ToUpper()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user