using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Wox.Plugin.Caculator { /// /// Tries to convert all numbers in a text from one culture format to another. /// public class NumberTranslator { private readonly CultureInfo sourceCulture; private readonly CultureInfo targetCulture; private readonly Regex splitRegexForSource; private readonly Regex splitRegexForTarget; private NumberTranslator(CultureInfo sourceCulture, CultureInfo targetCulture) { this.sourceCulture = sourceCulture; this.targetCulture = targetCulture; this.splitRegexForSource = GetSplitRegex(this.sourceCulture); this.splitRegexForTarget = GetSplitRegex(this.targetCulture); } /// /// Create a new - returns null if no number conversion /// is required between the cultures. /// /// source culture /// target culture /// public static NumberTranslator Create(CultureInfo sourceCulture, CultureInfo targetCulture) { bool conversionRequired = sourceCulture.NumberFormat.NumberDecimalSeparator != targetCulture.NumberFormat.NumberDecimalSeparator || sourceCulture.NumberFormat.PercentGroupSeparator != targetCulture.NumberFormat.PercentGroupSeparator || sourceCulture.NumberFormat.NumberGroupSizes != targetCulture.NumberFormat.NumberGroupSizes; return conversionRequired ? new NumberTranslator(sourceCulture, targetCulture) : null; } /// /// Translate from source to target culture. /// /// /// public string Translate(string input) { return this.Translate(input, this.sourceCulture, this.targetCulture, this.splitRegexForSource); } /// /// Translate from target to source culture. /// /// /// public string TranslateBack(string input) { return this.Translate(input, this.targetCulture, this.sourceCulture, this.splitRegexForTarget); } private string Translate(string input, CultureInfo cultureFrom, CultureInfo cultureTo, Regex splitRegex) { var outputBuilder = new StringBuilder(); string[] tokens = splitRegex.Split(input); foreach (string token in tokens) { decimal number; outputBuilder.Append( decimal.TryParse(token, NumberStyles.Number, cultureFrom, out number) ? number.ToString(cultureTo) : token); } return outputBuilder.ToString(); } private Regex GetSplitRegex(CultureInfo culture) { var splitPattern = $"((?:\\d|{Regex.Escape(culture.NumberFormat.NumberDecimalSeparator)}"; if (!string.IsNullOrEmpty(culture.NumberFormat.NumberGroupSeparator)) { splitPattern += $"|{Regex.Escape(culture.NumberFormat.NumberGroupSeparator)}"; } splitPattern += ")+)"; return new Regex(splitPattern); } } }