using System.Text.RegularExpressions;
using XFEEDToolBox.Core.Engineering;
using XFEEDToolBox.Core.Outfitting;
namespace XFEEDToolBox.Core.Localization;
/// <summary>Presentation only. Frontier identifiers, recipes and user supplied names retain their original values.</summary>
public static class ChineseNames
{
private static readonly Dictionary<string,string> Names = new(StringComparer.OrdinalIgnoreCase);
private static readonly Dictionary<string,string> Titles = new(StringComparer.OrdinalIgnoreCase);
private static readonly Lazy<Dictionary<string,string>> Aliases=new(()=>
{
var result=new Dictionary<string,string>(StringComparer.OrdinalIgnoreCase);
foreach(var r in EngineeringCatalog.Default.Recipes)if(r.JournalName.Length>0)result.TryAdd(EngineeringCatalog.Key(r.JournalName),r.Name);
using var stream=typeof(ChineseNames).Assembly.GetManifestResourceStream("XFEEDToolBox.Core.Localization.aliases.tsv")!;using var reader=new StreamReader(stream);
while(reader.ReadLine() is {} line){var p=line.Split('\t');if(p.Length==2)result[EngineeringCatalog.Key(p[0])]=p[1];}return result;
});
static ChineseNames()
{
using var stream=typeof(ChineseNames).Assembly.GetManifestResourceStream("XFEEDToolBox.Core.Localization.names.tsv")!;
using var reader=new StreamReader(stream);
while(reader.ReadLine() is {} line)
{
var parts=line.Split('\t');
if(parts.Length==2){var key=EngineeringCatalog.Key(parts[0]);Names[key]=parts[1];Titles.TryAdd(key,parts[0]);}
}
}
public static bool IsChinese(string value)=>value.Any(c=>c is >= '\u3400' and <= '\u9fff');
public static string English(string value)
{
if(string.IsNullOrWhiteSpace(value)||IsChinese(value))return value;
var key=EngineeringCatalog.Key(value.Trim('$',';'));
if(Aliases.Value.TryGetValue(key,out var recipe))return recipe;
if(Titles.TryGetValue(key,out var title))return title;
if(key.StartsWith("special"))key=key[7..];
if(Titles.TryGetValue(key,out title))return title;
return Regex.Replace(value.Replace('_',' '),"(?<=[a-z])(?=[A-Z])"," ").Trim();
}
public static string Translate(string value)
{
if(string.IsNullOrWhiteSpace(value)||IsChinese(value))return value;
var key=EngineeringCatalog.Key(value);
if(Names.TryGetValue(key,out var name))return name;
var english=English(value);key=EngineeringCatalog.Key(english);
if(Names.TryGetValue(key,out name))return name;
if(key.StartsWith("special")&&Names.TryGetValue(key[7..],out name))return name;
return "未收录名称";
}
public static string ShipEnglish(string type)=>OutfittingCatalog.Default.ShipNames.GetValueOrDefault(type.ToLowerInvariant(),English(type));
public static string Ship(string type)=>Translate(ShipEnglish(type));
public static string SlotEnglish(string slot)=>Regex.Replace(slot.Replace('_',' '),"(?<=[a-z])(?=[A-Z0-9])"," ");
public static string Slot(string slot)
{
if(slot=="FrameShiftDrive")return "跃迁引擎槽位";
var military=Regex.Match(slot,@"^Military(\d+)$",RegexOptions.IgnoreCase);if(military.Success)return "军用内部槽位 "+military.Groups[1].Value;
var match=Regex.Match(slot,@"^(Huge|Large|Medium|Small|Tiny)Hardpoint(\d+)$",RegexOptions.IgnoreCase);
if(match.Success)return Translate(match.Groups[1].Value+" Hardpoint")+" "+match.Groups[2].Value;
match=Regex.Match(slot,@"^(Slot|Military)(\d+)_Size(\d+)$",RegexOptions.IgnoreCase);
if(match.Success)return (match.Groups[1].Value.Equals("Military",StringComparison.OrdinalIgnoreCase)?"军用内部槽位 ":"可选内部槽位 ")+match.Groups[2].Value+" · "+match.Groups[3].Value+"级";
return Translate(slot);
}
public static string ModuleEnglish(string item,string fallback="")
{
if(item.Equals("modularcargobaydoor",StringComparison.OrdinalIgnoreCase))return "Cargo Hatch";
if(item.EndsWith("_cockpit",StringComparison.OrdinalIgnoreCase))return ShipEnglish(item[..^8])+" Cockpit";
if(item.StartsWith("voicepack_",StringComparison.OrdinalIgnoreCase))return "COVAS · "+English(item[10..]);
var m=OutfittingCatalog.Default.Find(item);
return m is null?(IsChinese(fallback)||fallback.Length==0?English(item):fallback):$"{m.Size}{m.Rating} {m.Name}"+(m.Mount.Length>0?" · "+m.Mount:"");
}
public static string Module(string item,string fallback="")
{
if(item.Equals("modularcargobaydoor",StringComparison.OrdinalIgnoreCase))return "货舱舱门";
if(item.EndsWith("_cockpit",StringComparison.OrdinalIgnoreCase))return Ship(item[..^8])+"座舱";
if(item.StartsWith("voicepack_",StringComparison.OrdinalIgnoreCase))return "座舱语音 · "+(Translate(item[10..]) is var voice&&voice!="未收录名称"?voice:"自定义声线");
var m=OutfittingCatalog.Default.Find(item);
return m is null?(IsChinese(fallback)?fallback:"未收录模块"):$"{m.Size}{m.Rating} {Translate(m.Name)}"+(m.Mount.Length>0?" · "+Translate(m.Mount):"");
}
public static string Category(string value)=>value switch{"Raw"=>"原始材料","Manufactured"=>"制造材料","Encoded"=>"编码数据","standard"=>"核心内部模块","internal"=>"可选内部模块","hardpoint"=>"武器挂点","utility"=>"通用挂点",_=>Translate(value)};
public static string Value(string text)=>Regex.IsMatch(text,@"^[$A-Za-z_][A-Za-z_$; ]*$")?Translate(text):text;
public static string Effect(string text)
{
var match=Regex.Match(text,@"^(.*?)(\s*[+−-]?\d.*)$");
return match.Success?Translate(match.Groups[1].Value.Trim(' ',':'))+match.Groups[2].Value:Translate(text);
}
}
using System.Text.RegularExpressions;
using XFEEDToolBox.Core.Engineering;
using XFEEDToolBox.Core.Outfitting;
namespace XFEEDToolBox.Core.Localization;
/// <summary>Presentation only. Frontier identifiers, recipes and user supplied names retain their original values.</summary>
public static class ChineseNames
{
private static readonly Dictionary<string,string> Names = new(StringComparer.OrdinalIgnoreCase);
private static readonly Dictionary<string,string> Titles = new(StringComparer.OrdinalIgnoreCase);
private static readonly Lazy<Dictionary<string,string>> Aliases=new(()=>
{
var result=new Dictionary<string,string>(StringComparer.OrdinalIgnoreCase);
foreach(var r in EngineeringCatalog.Default.Recipes)if(r.JournalName.Length>0)result.TryAdd(EngineeringCatalog.Key(r.JournalName),r.Name);
using var stream=typeof(ChineseNames).Assembly.GetManifestResourceStream("XFEEDToolBox.Core.Localization.aliases.tsv")!;using var reader=new StreamReader(stream);
while(reader.ReadLine() is {} line){var p=line.Split('\t');if(p.Length==2)result[EngineeringCatalog.Key(p[0])]=p[1];}return result;
});
static ChineseNames()
{
using var stream=typeof(ChineseNames).Assembly.GetManifestResourceStream("XFEEDToolBox.Core.Localization.names.tsv")!;
using var reader=new StreamReader(stream);
while(reader.ReadLine() is {} line)
{
var parts=line.Split('\t');
if(parts.Length==2){var key=EngineeringCatalog.Key(parts[0]);Names[key]=parts[1];Titles.TryAdd(key,parts[0]);}
}
}
public static bool IsChinese(string value)=>value.Any(c=>c is >= '\u3400' and <= '\u9fff');
public static string English(string value)
{
if(string.IsNullOrWhiteSpace(value)||IsChinese(value))return value;
var key=EngineeringCatalog.Key(value.Trim('$',';'));
if(Aliases.Value.TryGetValue(key,out var recipe))return recipe;
if(Titles.TryGetValue(key,out var title))return title;
if(key.StartsWith("special"))key=key[7..];
if(Titles.TryGetValue(key,out title))return title;
return Regex.Replace(value.Replace('_',' '),"(?<=[a-z])(?=[A-Z])"," ").Trim();
}
public static string Translate(string value)
{
if(string.IsNullOrWhiteSpace(value)||IsChinese(value))return value;
var key=EngineeringCatalog.Key(value);
if(Names.TryGetValue(key,out var name))return name;
var english=English(value);key=EngineeringCatalog.Key(english);
if(Names.TryGetValue(key,out name))return name;
if(key.StartsWith("special")&&Names.TryGetValue(key[7..],out name))return name;
return "未收录名称";
}
public static string ShipEnglish(string type)=>OutfittingCatalog.Default.ShipNames.GetValueOrDefault(type.ToLowerInvariant(),English(type));
public static string Ship(string type)=>Translate(ShipEnglish(type));
public static string SlotEnglish(string slot)=>Regex.Replace(slot.Replace('_',' '),"(?<=[a-z])(?=[A-Z0-9])"," ");
public static string Slot(string slot)
{
if(slot=="FrameShiftDrive")return "跃迁引擎槽位";
var military=Regex.Match(slot,@"^Military(\d+)$",RegexOptions.IgnoreCase);if(military.Success)return "军用内部槽位 "+military.Groups[1].Value;
var match=Regex.Match(slot,@"^(Huge|Large|Medium|Small|Tiny)Hardpoint(\d+)$",RegexOptions.IgnoreCase);
if(match.Success)return Translate(match.Groups[1].Value+" Hardpoint")+" "+match.Groups[2].Value;
match=Regex.Match(slot,@"^(Slot|Military)(\d+)_Size(\d+)$",RegexOptions.IgnoreCase);
if(match.Success)return (match.Groups[1].Value.Equals("Military",StringComparison.OrdinalIgnoreCase)?"军用内部槽位 ":"可选内部槽位 ")+match.Groups[2].Value+" · "+match.Groups[3].Value+"级";
return Translate(slot);
}
public static string ModuleEnglish(string item,string fallback="")
{
if(item.Equals("modularcargobaydoor",StringComparison.OrdinalIgnoreCase))return "Cargo Hatch";
if(item.EndsWith("_cockpit",StringComparison.OrdinalIgnoreCase))return ShipEnglish(item[..^8])+" Cockpit";
if(item.StartsWith("voicepack_",StringComparison.OrdinalIgnoreCase))return "COVAS · "+English(item[10..]);
var m=OutfittingCatalog.Default.Find(item);
return m is null?(IsChinese(fallback)||fallback.Length==0?English(item):fallback):$"{m.Size}{m.Rating} {m.Name}"+(m.Mount.Length>0?" · "+m.Mount:"");
}
public static string Module(string item,string fallback="")
{
if(item.Equals("modularcargobaydoor",StringComparison.OrdinalIgnoreCase))return "货舱舱门";
if(item.EndsWith("_cockpit",StringComparison.OrdinalIgnoreCase))return Ship(item[..^8])+"座舱";
if(item.StartsWith("voicepack_",StringComparison.OrdinalIgnoreCase))return "座舱语音 · "+(Translate(item[10..]) is var voice&&voice!="未收录名称"?voice:"自定义声线");
var m=OutfittingCatalog.Default.Find(item);
return m is null?(IsChinese(fallback)?fallback:"未收录模块"):$"{m.Size}{m.Rating} {Translate(m.Name)}"+(m.Mount.Length>0?" · "+Translate(m.Mount):"");
}
public static string Category(string value)=>value switch{"Raw"=>"原始材料","Manufactured"=>"制造材料","Encoded"=>"编码数据","standard"=>"核心内部模块","internal"=>"可选内部模块","hardpoint"=>"武器挂点","utility"=>"通用挂点",_=>Translate(value)};
public static string Value(string text)=>Regex.IsMatch(text,@"^[$A-Za-z_][A-Za-z_$; ]*$")?Translate(text):text;
public static string Effect(string text)
{
var match=Regex.Match(text,@"^(.*?)(\s*[+−-]?\d.*)$");
return match.Success?Translate(match.Groups[1].Value.Trim(' ',':'))+match.Groups[2].Value:Translate(text);
}
}