using System; using System.Collections.Generic; using System.Linq; using System.Xml; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace Billing.Languages { internal class Resource { public static string Ok => Text(nameof(Ok)); public static string Cancel => Text(nameof(Cancel)); public static string Yes => Text(nameof(Yes)); public static string No => Text(nameof(No)); public static string ConfirmDeleteAccount => Text(nameof(ConfirmDeleteAccount)); public static string ConfirmDeleteBill => Text(nameof(ConfirmDeleteBill)); public static string TitleDateFormat => Text(nameof(TitleDateFormat)); public static string TitleShortDateFormat => Text(nameof(TitleShortDateFormat)); public static string DateRangeFormat => Text(nameof(DateRangeFormat)); public static string Custom => Text(nameof(Custom)); public static string Monthly => Text(nameof(Monthly)); public static string Today => Text(nameof(Today)); public static string PastMonth => Text(nameof(PastMonth)); public static string PastQuarter => Text(nameof(PastQuarter)); public static string PastSixMonths => Text(nameof(PastSixMonths)); public static string PastYear => Text(nameof(PastYear)); public static string Total => Text(nameof(Total)); public static string Cash => Text(nameof(Cash)); public static string CreditCard => Text(nameof(CreditCard)); public static string DebitCard => Text(nameof(DebitCard)); public static string ElecAccount => Text(nameof(ElecAccount)); public static string AddBill => Text(nameof(AddBill)); public static string EditBill => Text(nameof(EditBill)); public static string AddAccount => Text(nameof(AddAccount)); public static string EditAccount => Text(nameof(EditAccount)); public static string AccountRequired => Text(nameof(AccountRequired)); public static string NeedAccount => Text(nameof(NeedAccount)); public static string AmountRequired => Text(nameof(AmountRequired)); public static string Income => Text(nameof(Income)); public static string Spending => Text(nameof(Spending)); public static string LastSelected => Text(nameof(LastSelected)); public static string Recent => Text(nameof(Recent)); public static string CategoryManage => Text(nameof(CategoryManage)); public static string AddCategory => Text(nameof(AddCategory)); public static string ConfirmDeleteCategory => Text(nameof(ConfirmDeleteCategory)); public static string ShareLogs => Text(nameof(ShareLogs)); public static string ManyRecords => Text(nameof(ManyRecords)); public static string SendEmail => Text(nameof(SendEmail)); public static string HowToShareDiagnostic => Text(nameof(HowToShareDiagnostic)); #region Categories public static string Clothing => Text(nameof(Clothing)); public static string Food => Text(nameof(Food)); public static string Drinks => Text(nameof(Drinks)); public static string Daily => Text(nameof(Daily)); public static string Trans => Text(nameof(Trans)); public static string Entertainment => Text(nameof(Entertainment)); public static string Learn => Text(nameof(Learn)); public static string Medical => Text(nameof(Medical)); public static string OtherSpending => Text(nameof(OtherSpending)); public static string Salary => Text(nameof(Salary)); public static string Earnings => Text(nameof(Earnings)); public static string Bonus => Text(nameof(Bonus)); public static string OtherIncome => Text(nameof(OtherIncome)); public static string Jewellery => Text(nameof(Jewellery)); public static string Cosmetics => Text(nameof(Cosmetics)); public static string Brunch => Text(nameof(Brunch)); public static string Dinner => Text(nameof(Dinner)); public static string Fruit => Text(nameof(Fruit)); public static string UtilityBill => Text(nameof(UtilityBill)); public static string PropertyFee => Text(nameof(PropertyFee)); public static string Rent => Text(nameof(Rent)); public static string Maintenance => Text(nameof(Maintenance)); public static string Bus => Text(nameof(Bus)); public static string LightRail => Text(nameof(LightRail)); public static string Taxi => Text(nameof(Taxi)); public static string Fitness => Text(nameof(Fitness)); public static string Party => Text(nameof(Party)); #endregion static readonly Dictionary dict = new(); public static string Text(string name, params object[] args) { string current = App.CurrentCulture.PlatformString; if (!dict.TryGetValue(current, out LanguageResource lang)) { lang = new LanguageResource(App.CurrentCulture); dict.Add(current, lang); } if (args == null || args.Length == 0) { return lang[name]; } return string.Format(lang[name], args); } private class LanguageResource { private readonly Dictionary strings; public string this[string key] { get { if (strings != null && strings.TryGetValue(key, out string val)) { return val; } return key; } } public LanguageResource(PlatformCulture lang) { try { var ns = lang.GetNamespace(); var langId = $"{ns}.Languages.{lang.Language}.xml"; var langCodeId = $"{ns}.Languages.{lang.LanguageCode}.xml"; var assembly = typeof(LanguageResource).Assembly; var name = assembly.GetManifestResourceNames().FirstOrDefault(n => string.Equals(n, langId, StringComparison.OrdinalIgnoreCase) || string.Equals(n, langCodeId, StringComparison.OrdinalIgnoreCase)); if (name == null) { name = $"{ns}.Languages.zh-CN.xml"; } var xml = new XmlDocument(); using (var stream = assembly.GetManifestResourceStream(name)) { xml.Load(stream); } strings = new Dictionary(); foreach (XmlElement ele in xml.DocumentElement) { strings[ele.Name] = ele.InnerText; } } catch (Exception ex) { Helper.Error("language.ctor", $"failed to load json resource: {lang}, {ex.Message}"); } } } } [ContentProperty(nameof(Text))] public class TextExtension : IMarkupExtension { public string Text { get; set; } public object ProvideValue(IServiceProvider serviceProvider) { if (Text == null) { return string.Empty; } return Resource.Text(Text); } } }