| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- using Newtonsoft.Json.Linq;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Windows.Forms;
- namespace UAS_MES_NEW.PublicMethod
- {
- public class LanguageReload
- {
- private static readonly object _lock = new object();
- private static JObject _root;
- private static string _loadedPath;
- private static string _defaultCulture = "en-US";
- public static void Load(string filePath)
- {
- lock (_lock)
- {
- if (!File.Exists(filePath)) throw new FileNotFoundException("Language file not found", filePath);
- var text = File.ReadAllText(filePath, System.Text.Encoding.UTF8);
- _root = JObject.Parse(text);
- _loadedPath = filePath;
- // try to read a default culture from file if provided
- var metaDefault = _root["meta"]?["defaultCulture"]?.ToString();
- if (!string.IsNullOrWhiteSpace(metaDefault)) _defaultCulture = metaDefault;
- }
- }
- public static string GetString(string key, string culture)
- {
- lock (_lock)
- {
- if (_root == null) return null;
- var node = _root["control"]?[key];
- if (node == null) return null;
- var v = node[culture]?.ToString();
- if (!string.IsNullOrEmpty(v)) return v;
- // fallback to default culture
- v = node[_defaultCulture]?.ToString();
- if (!string.IsNullOrEmpty(v)) return v;
- // fallback to any available value
- var first = node.Children<JProperty>().FirstOrDefault()?.Value?.ToString();
- return first;
- }
- }
- public static void ApplyToControl(Control ctrl, string culture)
- {
- if (ctrl == null) return;
- // For controls that expose Text property
- var value = GetString(ctrl.Name, culture);
- if (!string.IsNullOrEmpty(value))
- {
- ctrl.Text = value;
- }
- // Special handling for ToolStrip / MenuStrip items
- if (ctrl is ToolStrip ts)
- {
- foreach (ToolStripItem item in ts.Items)
- {
- var v = GetString(item.Name, culture);
- if (!string.IsNullOrEmpty(v)) item.Text = v;
- }
- }
- // recursively apply to child controls
- foreach (Control child in ctrl.Controls)
- {
- ApplyToControl(child, culture);
- }
- }
- public static void ApplyToForm(Form form, string culture)
- {
- if (form == null) return;
- // 必须在 InitializeComponent() 之后调用
- ApplyToControl(form, culture);
- }
- public static bool IsLoaded => _root != null;
- public static string LoadedPath => _loadedPath;
- public static string GetMessage(string key)
- {
- try
- {
- var ltObj = BaseUtil.GetCacheData("LanguageType");
- var lt = ltObj == null ? "0" : ltObj.ToString();
- var culture = lt == "1" ? "en-US" : lt == "2" ? "vi-VN" : "zh-CN";
- var s = GetString(key, culture);
- if (!string.IsNullOrEmpty(s)) return s;
- // 回退到默认文化由 LocalizationProvider 处理,仍未找到则返回 key
- return key;
- }
- catch
- {
- return key;
- }
- }
- public static string Format(string key, params object[] args)
- {
- var format = GetMessage(key);
- try
- {
- return string.Format(format, args);
- }
- catch
- {
- return format;
- }
- }
- public static void ApplyLocalization(Form form, string culture, string langFilePath = null)
- {
- if (form == null) return;
- try
- {
- if (!IsLoaded)
- {
- if (string.IsNullOrEmpty(langFilePath))
- throw new InvalidOperationException("语言文件未加载,请传入 langFilePath 或先调用 LocalizationProvider.Load");
- Load(langFilePath);
- }
- // 1. 基本 Text / ToolStrip 项目处理(递归)
- ApplyToForm(form, culture);
- // 2. 处理 Designer 中声明为字段的 ColumnHeader:按字段名(如 columnHeader1)查找并设置 Text
- var formType = form.GetType();
- var headerFields = formType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
- .Where(f => f.FieldType == typeof(ColumnHeader));
- foreach (var f in headerFields)
- {
- try
- {
- var header = f.GetValue(form) as ColumnHeader;
- if (header == null) continue;
- var key = f.Name; // e.g. "columnHeader1"
- var txt = GetString(key, culture);
- if (!string.IsNullOrEmpty(txt))
- {
- header.Text = txt;
- }
- }
- catch
- {
- // 忽略单个列头设置错误
- }
- }
- // 3. 处理控件上的 PlaceHolder / Placeholder 属性(自定义控件)
- ApplyPlaceholdersRecursive(form, culture);
- // 4. 如果需要,可在此加入对其它特殊控件/属性的处理
- }
- catch (Exception ex)
- {
- // 仅做调试输出,生产环境可记录日志
- System.Diagnostics.Debug.WriteLine("ApplyLocalization 错误: " + ex.Message);
- }
- }
- private static void ApplyPlaceholdersRecursive(Control parent, string culture)
- {
- foreach (Control ctrl in parent.Controls)
- {
- try
- {
- // 查找 PlaceHolder / Placeholder 属性(大小写兼容)
- var prop = ctrl.GetType().GetProperty("PlaceHolder", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
- ?? ctrl.GetType().GetProperty("Placeholder", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
- if (prop != null && prop.CanWrite)
- {
- // 先尝试按 "控件名.PlaceHolder" 查找占位符翻译
- var keyWithProp = $"{ctrl.Name}.PlaceHolder";
- var val = GetString(keyWithProp, culture);
- if (string.IsNullOrEmpty(val))
- {
- // 回退到按控件名直接查找
- val = GetString(ctrl.Name, culture);
- }
- if (!string.IsNullOrEmpty(val))
- {
- prop.SetValue(ctrl, val, null);
- }
- }
- }
- catch
- {
- // 忽略单控件占位符设置错误
- }
- // 递归子控件
- if (ctrl.HasChildren)
- {
- ApplyPlaceholdersRecursive(ctrl, culture);
- }
- }
- }
- }
- }
|