using System.Text.RegularExpressions; using GFramework.Core.Abstractions.Localization; namespace GFramework.Core.Localization; /// /// 本地化字符串实现 /// public class LocalizationString : ILocalizationString { /// /// 匹配 {variableName} 或 {variableName:formatter:args} 的正则表达式模式 /// private const string FormatVariablePattern = @"\{([a-zA-Z_][a-zA-Z0-9_]*)(?::([a-zA-Z_][a-zA-Z0-9_]*)(?::([^}]+))?)?\}"; /// /// 预编译的静态正则表达式,用于格式化字符串中的变量替换 /// private static readonly Regex FormatVariableRegex = new(FormatVariablePattern, RegexOptions.Compiled | RegexOptions.CultureInvariant); private readonly ILocalizationManager _manager; private readonly Dictionary _variables; /// /// 初始化本地化字符串 /// /// 本地化管理器实例 /// 本地化表名,用于定位本地化资源表 /// 本地化键名,用于在表中定位具体的本地化文本 /// 当 manager、table 或 key 为 null 时抛出 public LocalizationString(ILocalizationManager manager, string table, string key) { _manager = manager ?? throw new ArgumentNullException(nameof(manager)); Table = table ?? throw new ArgumentNullException(nameof(table)); Key = key ?? throw new ArgumentNullException(nameof(key)); _variables = new Dictionary(); } /// public string Table { get; } /// public string Key { get; } /// /// 添加单个变量到本地化字符串中 /// /// 变量名称,用于在模板中匹配对应的占位符 /// 变量值,将被转换为字符串并替换到对应位置 /// 返回当前的 LocalizationString 实例,支持链式调用 /// 当 name 为 null 时抛出 public ILocalizationString WithVariable(string name, object value) { if (name == null) { throw new ArgumentNullException(nameof(name)); } _variables[name] = value; return this; } /// /// 批量添加多个变量到本地化字符串中 /// /// 变量元组数组,每个元组包含变量名称和对应的值 /// 返回当前的 LocalizationString 实例,支持链式调用 /// 当 variables 为 null 时抛出 public ILocalizationString WithVariables(params (string name, object value)[] variables) { if (variables == null) { throw new ArgumentNullException(nameof(variables)); } foreach (var (name, value) in variables) { WithVariable(name, value); } return this; } /// /// 格式化本地化字符串,将模板中的变量占位符替换为实际值 /// /// 格式化后的完整字符串。如果本地化文本不存在,则返回 "[Table.Key]" 格式的占位符 /// /// 支持两种格式: /// 1. {variableName} - 简单变量替换 /// 2. {variableName:formatter:args} - 使用格式化器进行格式化 /// public string Format() { var rawText = GetRaw(); return FormatString(rawText, _variables, _manager); } /// /// 获取原始的本地化文本,不进行任何变量替换 /// /// 本地化文本。如果在本地化管理器中未找到对应的文本,则返回 "[Table.Key]" 格式的占位符 public string GetRaw() { if (!_manager.TryGetText(Table, Key, out var text)) { return $"[{Table}.{Key}]"; } return text; } /// /// 检查当前本地化键是否存在于本地化管理器中 /// /// 如果存在返回 true;否则返回 false public bool Exists() { return _manager.TryGetText(Table, Key, out _); } /// /// 格式化字符串(支持变量替换和格式化器) /// /// 包含占位符的模板字符串 /// 包含变量名称和值的字典 /// 本地化管理器实例,用于获取格式化器 /// 格式化后的字符串。如果模板为空或 null,则直接返回原模板 private static string FormatString( string template, Dictionary variables, ILocalizationManager manager) { if (string.IsNullOrEmpty(template)) { return template; } // 使用预编译的静态正则表达式匹配 {variableName} 或 {variableName:formatter:args} return FormatVariableRegex.Replace(template, match => FormatMatch(match, variables, manager)); } /// /// 处理单个正则表达式匹配项,根据是否有格式化器决定如何处理变量值 /// /// 正则表达式匹配结果 /// 变量字典 /// 本地化管理器实例 /// 替换后的字符串。如果变量不存在则返回原始匹配值;如果有格式化器则尝试格式化,失败则使用默认格式化 private static string FormatMatch( Match match, Dictionary variables, ILocalizationManager manager) { var variableName = match.Groups[1].Value; if (!variables.TryGetValue(variableName, out var value)) { return match.Value; } var formatterName = GetOptionalGroupValue(match, 2); if (string.IsNullOrEmpty(formatterName)) { return FormatValue(value, manager); } return TryFormatValue(match, value, formatterName, manager, out var result) ? result : FormatValue(value, manager); } /// /// 尝试使用指定的格式化器格式化变量值 /// /// 正则表达式匹配结果,用于获取格式化参数 /// 要格式化的变量值 /// 格式化器名称 /// 本地化管理器实例 /// 格式化后的结果字符串 /// 如果格式化成功返回 true;否则返回 false,此时 result 为空字符串 private static bool TryFormatValue( Match match, object value, string formatterName, ILocalizationManager manager, out string result) { var formatterArgs = GetOptionalGroupValue(match, 3) ?? string.Empty; if (GetFormatter(manager, formatterName) is { } formatter && formatter.TryFormat(formatterArgs, value, manager.CurrentCulture, out result)) { return true; } result = string.Empty; return false; } /// /// 对变量值进行默认格式化,不使用自定义格式化器 /// /// 要格式化的值 /// 本地化管理器实例,提供当前文化信息 /// 格式化后的字符串。如果值实现 IFormattable 接口则使用其 ToString 方法,否则调用默认的 ToString 方法 private static string FormatValue(object value, ILocalizationManager manager) { return value switch { IFormattable formattable => formattable.ToString(null, manager.CurrentCulture), _ => value.ToString() ?? string.Empty }; } /// /// 获取正则表达式匹配组中的可选值 /// /// 正则表达式匹配结果 /// 要获取的组索引 /// 如果该组匹配成功则返回其值;否则返回 null private static string? GetOptionalGroupValue(Match match, int groupIndex) { return match.Groups[groupIndex].Success ? match.Groups[groupIndex].Value : null; } /// /// 从本地化管理器获取指定名称的格式化器 /// /// 本地化管理器实例 /// 格式化器名称 /// 如果找到对应的格式化器则返回;否则返回 null private static ILocalizationFormatter? GetFormatter(ILocalizationManager manager, string name) { return manager.GetFormatter(name); } }