You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

389 lines
18 KiB

2 years ago
  1. using EasyBL.WebApi.Message;
  2. using Entity.Sugar;
  3. using HtmlAgilityPack;
  4. using Newtonsoft.Json;
  5. using SqlSugar.Base;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.IO;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Text.RegularExpressions;
  12. namespace EasyBL
  13. {
  14. public class LanguageService : ServiceBase
  15. {
  16. #region 獲取資料產生語系檔Json文件
  17. //產生語系檔
  18. public ResponseMessage CreateLangJson(RequestMessage i_crm)
  19. {
  20. ResponseMessage crm = null;
  21. string sMsg = null;
  22. var db = SugarBase.GetIntance();
  23. var DicLangData = new Dictionary<string, Dictionary<string, string>>();
  24. try
  25. {
  26. do
  27. {
  28. var saLanguage = db.Queryable<OTB_SYS_Language>().Where(x => x.OrgID == i_crm.ORIGID).ToList();
  29. // 分語言 oLanguageSource
  30. foreach (OTB_SYS_Language oLanguageSource in saLanguage)
  31. {
  32. if (!DicLangData.ContainsKey(oLanguageSource.Country))
  33. {
  34. DicLangData.Add(oLanguageSource.Country, new Dictionary<string, string>());
  35. }
  36. if (!DicLangData[oLanguageSource.Country].ContainsKey(oLanguageSource.Type + "." + oLanguageSource.LangId))
  37. {
  38. DicLangData[oLanguageSource.Country].Add(oLanguageSource.Type + "." + oLanguageSource.LangId, oLanguageSource.LangName);
  39. }
  40. }
  41. var dicLangResult = new Dictionary<string, string>();
  42. foreach (string sLang in DicLangData.Keys)
  43. {
  44. // Make Json
  45. var sOut = MakeJson(DicLangData[sLang], out sMsg);
  46. if (sMsg != null)
  47. {
  48. break;
  49. }
  50. if (!dicLangResult.ContainsKey(sLang))
  51. {
  52. dicLangResult.Add(sLang, sOut);
  53. }
  54. }
  55. if (sMsg != null)
  56. {
  57. break;
  58. }
  59. foreach (string sLang in dicLangResult.Keys)
  60. {
  61. var sFoder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Scripts", "lang", i_crm.ORIGID);
  62. Common.FnCreateDir(sFoder);
  63. var sLangPath = Path.Combine(sFoder, $"{sLang}.json");
  64. File.WriteAllText(sLangPath, dicLangResult[sLang], Encoding.UTF8);
  65. }
  66. crm = new SuccessResponseMessage(null, i_crm);
  67. }
  68. while (false);
  69. }
  70. catch (Exception ex)
  71. {
  72. sMsg = Util.GetLastExceptionMsg(ex);
  73. LogAndSendEmail(sMsg + "Param:" + JsonToString(i_crm), ex, i_crm.ORIGID, i_crm.USERID, "EasyBL.LanguageService", "", "CreateLangJson(獲取資料產生語系檔Json文件)", "", "", "");
  74. }
  75. if (null != sMsg)
  76. {
  77. crm = new ErrorResponseMessage(sMsg, i_crm);
  78. }
  79. return crm;
  80. }
  81. #endregion 獲取資料產生語系檔Json文件
  82. #region 多語系初始化(依據文件)
  83. //多語系初始化(依據文件)
  84. public ResponseMessage InitializeLanguage(RequestMessage i_crm)
  85. {
  86. ResponseMessage rm = null;
  87. string sMsg = null;
  88. try
  89. {
  90. do
  91. {
  92. rm = SugarBase.ExecTran(db =>
  93. {
  94. do
  95. {
  96. var dicI18ns = new Dictionary<string, string>();
  97. var saFilesPath = new List<string>();
  98. var sInitLngHTMLPath = Common.ConfigGetValue("", "InitLngHTMLPath");
  99. var sInitLngJSPath = Common.ConfigGetValue("", "InitLngJSPath");
  100. // 將虛擬路徑轉為實體路徑
  101. sInitLngHTMLPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, sInitLngHTMLPath);
  102. sInitLngJSPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, sInitLngJSPath);
  103. foreach (var fi in Directory.GetFiles(sInitLngHTMLPath, "*.html", SearchOption.AllDirectories))
  104. {
  105. saFilesPath.Add(fi);
  106. }
  107. foreach (var fi in Directory.GetFiles(sInitLngJSPath, "*.js", SearchOption.AllDirectories))
  108. {
  109. saFilesPath.Add(fi);
  110. }
  111. foreach (string path in saFilesPath)
  112. {
  113. if (path.ToLower().EndsWith(".html"))
  114. {
  115. var doc = new HtmlDocument();
  116. doc.Load(path, Encoding.UTF8);
  117. var allHn = GetI18nNode(doc);
  118. var templHn = doc.DocumentNode.Descendants().Where(x => x.Name == "script" && x.Attributes.Any(p => p.Value == "text/x-jsrender"));
  119. GetI18nKeyValue(allHn, dicI18ns);
  120. foreach (var nd in templHn)//處理html模版中的多語系
  121. {
  122. var docTempl = new HtmlDocument();
  123. docTempl.LoadHtml(nd.InnerHtml);
  124. var allTemplHn = GetI18nNode(docTempl);
  125. GetI18nKeyValue(allTemplHn, dicI18ns);
  126. }
  127. }
  128. else
  129. {
  130. var sJSText = File.ReadAllText(path, Encoding.UTF8);
  131. var r = new Regex("╠"); // 定义一个Regex对象实例
  132. var mc = r.Matches(sJSText); // 在字符串中匹配
  133. foreach (Match m in mc)
  134. {
  135. var iIndex = m.Index;
  136. var sCur = sJSText.Substring(iIndex, sJSText.Length - iIndex);
  137. var _r = new Regex("╣");
  138. var _m = _r.Match(sCur); // 在字符串中第一個匹配項
  139. var sI18nArray = sCur.Substring(1, _m.Index - 1);
  140. if (sI18nArray.IndexOf("⇒") > -1)//如果不含⇒的就不添加
  141. {
  142. var saI18nText = sI18nArray.Split('⇒');
  143. if (saI18nText.Count() > 1 && !dicI18ns.Keys.Contains(saI18nText[0].ToString()))
  144. {
  145. dicI18ns.Add(saI18nText[0].ToString(), saI18nText[1].ToString());
  146. }
  147. }
  148. }
  149. }
  150. }
  151. if (dicI18ns.Keys.Count > 0)
  152. {
  153. //List<OTB_SYS_Language> saLng_Del = new List<OTB_SYS_Language>();
  154. var saLng_Add = new List<OTB_SYS_Language>();
  155. var saLanguage = db.Queryable<OTB_SYS_Language>().Where(x => x.OrgID == i_crm.ORIGID).ToList();
  156. var saModuleList = db.Queryable<OTB_SYS_ModuleList>().Where(x => x.OrgID == i_crm.ORIGID).ToList();
  157. var saPrgList = db.Queryable<OTB_SYS_ProgramList>().Where(x => x.OrgID == i_crm.ORIGID).ToList();
  158. foreach (var i18nkey in dicI18ns)
  159. {
  160. if (!saLanguage.Any(x => i18nkey.Key == x.Type + "." + x.LangId))
  161. {
  162. var saLang = i18nkey.Key.Split('.');
  163. if (saLang.Count() > 1)
  164. {
  165. var oLng = new OTB_SYS_Language
  166. {
  167. OrgID = i_crm.ORIGID,
  168. Type = saLang[0].ToString(),
  169. LangId = saLang[1].ToString(),
  170. Country = "zh-TW",
  171. LangName = i18nkey.Value,
  172. Memo = i18nkey.Value,
  173. CreateUser = i_crm.USERID,
  174. CreateDate = DateTime.Now,
  175. ModifyUser = i_crm.USERID,
  176. ModifyDate = DateTime.Now
  177. };
  178. if (!saLng_Add.Any(x => x.OrgID == oLng.OrgID && x.Type == oLng.Type && x.Country == oLng.Country && x.LangId.ToLower() == oLng.LangId.ToLower()))
  179. {
  180. saLng_Add.Add(oLng);
  181. }
  182. }
  183. }
  184. }
  185. //系統程式多語系
  186. foreach (var prg in saPrgList)
  187. {
  188. var oLng = new OTB_SYS_Language
  189. {
  190. OrgID = i_crm.ORIGID,
  191. Type = "common",
  192. LangId = prg.ProgramID,
  193. Country = "zh-TW",
  194. LangName = prg.ProgramName,
  195. Memo = prg.ProgramName,
  196. CreateUser = i_crm.USERID,
  197. CreateDate = DateTime.Now,
  198. ModifyUser = i_crm.USERID,
  199. ModifyDate = DateTime.Now
  200. };
  201. if (!saLng_Add.Any(x => x.OrgID == oLng.OrgID && x.Type == oLng.Type && x.Country == oLng.Country && x.LangId.ToLower() == oLng.LangId.ToLower()) && !saLanguage.Any(x => x.OrgID == oLng.OrgID && x.Type == oLng.Type && x.Country == oLng.Country && x.LangId.ToLower() == oLng.LangId.ToLower()))
  202. {
  203. saLng_Add.Add(oLng);
  204. }
  205. }
  206. //系統模組多語系
  207. foreach (var mod in saModuleList)
  208. {
  209. var oLng = new OTB_SYS_Language
  210. {
  211. OrgID = i_crm.ORIGID,
  212. Type = "common",
  213. LangId = mod.ModuleID,
  214. Country = "zh-TW",
  215. LangName = mod.ModuleName,
  216. Memo = mod.ModuleName,
  217. CreateUser = i_crm.USERID,
  218. CreateDate = DateTime.Now,
  219. ModifyUser = i_crm.USERID,
  220. ModifyDate = DateTime.Now
  221. };
  222. if (!saLng_Add.Any(x => x.OrgID == oLng.OrgID && x.Type == oLng.Type && x.Country == oLng.Country && x.LangId.ToLower() == oLng.LangId.ToLower()) && !saLanguage.Any(x => x.OrgID == oLng.OrgID && x.Type == oLng.Type && x.Country == oLng.Country && x.LangId.ToLower() == oLng.LangId.ToLower()))
  223. {
  224. saLng_Add.Add(oLng);
  225. }
  226. }
  227. //if (saLng_Del.Count > 0)
  228. //{
  229. // db.Deleteable(saLng_Del).ExecuteCommand();
  230. //}
  231. if (saLng_Add.Count > 0)
  232. {
  233. db.Insertable(saLng_Add).ExecuteCommand();
  234. }
  235. rm = new SuccessResponseMessage(null, i_crm);
  236. rm.DATA.Add(BLWording.REL, true);
  237. }
  238. } while (false);
  239. return rm;
  240. });
  241. }
  242. while (false);
  243. }
  244. catch (Exception ex)
  245. {
  246. sMsg = Util.GetLastExceptionMsg(ex);
  247. LogAndSendEmail(sMsg + "Param:" + JsonToString(i_crm), ex, i_crm.ORIGID, i_crm.USERID, "EasyBL.LanguageService", "", "InitializeLanguage(多語系初始化(依據文件))", "", "", "");
  248. }
  249. if (null != sMsg)
  250. {
  251. rm = new ErrorResponseMessage(sMsg, i_crm);
  252. }
  253. return rm;
  254. }
  255. /// <summary>
  256. /// 篩選i18n標籤
  257. /// </summary>
  258. /// <param name="hd"></param>
  259. /// <returns></returns>
  260. private static IEnumerable<HtmlNode> GetI18nNode(HtmlDocument hd)
  261. {
  262. var saI18nNode = hd.DocumentNode.Descendants()
  263. .Where(x => x.Attributes.Contains("data-i18n")
  264. || x.Attributes.Contains("placeholderid")
  265. || x.Attributes.Any(p => p.Name.StartsWith("data-msg")));
  266. return saI18nNode;
  267. }
  268. /// <summary>
  269. /// 獲取i18n鍵值對
  270. /// </summary>
  271. /// <param name="i18nNode">todo: describe i18nNode parameter on GetI18nKeyValue</param>
  272. /// <param name="dicI18">todo: describe dicI18 parameter on GetI18nKeyValue</param>
  273. /// <returns></returns>
  274. private static void GetI18nKeyValue(IEnumerable<HtmlNode> i18nNode, Dictionary<string, string> dicI18)
  275. {
  276. foreach (HtmlNode hn in i18nNode)//回圈所有節點尋找
  277. {
  278. var allAttr = hn.Attributes;
  279. foreach (var attr in allAttr)
  280. {
  281. var sText = "*";
  282. if (attr.Name == "data-i18n")
  283. {
  284. sText = hn.InnerText;
  285. if (sText == "" && allAttr["type"] != null && allAttr["type"].Value == "button")
  286. {
  287. sText = allAttr["value"] == null ? "" : allAttr["value"].Value;
  288. }
  289. }
  290. else if (attr.Name == "placeholderid")
  291. {
  292. var text = hn.Attributes["placeholder"];
  293. sText = text == null ? "" : text.Value;
  294. }
  295. else if (attr.Name.StartsWith("data-msg"))
  296. {
  297. var text = hn.Attributes[attr.Name.Replace("-", "")];
  298. sText = text == null ? "" : text.Value;
  299. }
  300. if (sText != "*" && !dicI18.Keys.Contains(attr.Value) && attr.Value.IndexOf("{{:") == -1)
  301. {
  302. dicI18.Add(attr.Value, sText);
  303. }
  304. }
  305. }
  306. }
  307. #endregion 多語系初始化(依據文件)
  308. #region 產生Json格式
  309. //產生語系檔Json格式
  310. protected static string MakeJson(Dictionary<string, string> i_dicMap, out string o_sError)
  311. {
  312. string sErrorMsg = null;
  313. string sRes = null;
  314. do
  315. {
  316. var dicJSMap = new Dictionary<string, Dictionary<string, string>>();
  317. foreach (string sKey in i_dicMap.Keys)
  318. {
  319. //oComparison
  320. var oComparison = sKey.Split(".".ToCharArray());
  321. if (oComparison.Length != 2)
  322. {
  323. sErrorMsg = "多語系配置格式有無!!";
  324. break;
  325. }
  326. if (!dicJSMap.ContainsKey(oComparison[0]))
  327. {
  328. dicJSMap.Add(oComparison[0], new Dictionary<string, string>());
  329. }
  330. if (dicJSMap[oComparison[0]].ContainsKey(oComparison[1]))
  331. {
  332. sErrorMsg = "多語系ID重複!!";
  333. break;
  334. }
  335. if (!dicJSMap[oComparison[0]].ContainsKey(oComparison[1]))
  336. {
  337. dicJSMap[oComparison[0]].Add(oComparison[1], i_dicMap[sKey]);
  338. }
  339. }
  340. if (sErrorMsg != null)
  341. {
  342. break;
  343. }
  344. sRes = JsonConvert.SerializeObject(dicJSMap);
  345. }
  346. while (false);
  347. o_sError = sErrorMsg;
  348. return sRes;
  349. }
  350. #endregion 產生Json格式
  351. }
  352. }