public static void RenderItem(StringBuilder sb, string currTrg, EntryStatus currStatus, ChangeItem change, string lang) { CedictParser parser = new CedictParser(); histRenderChange(sb, change, false, lang, parser, "reloaded"); }
public async Task ReadAsync_ShouldSkipComments() { string s = "# This is a comment\n" + "再見 再见 [zai4 jian4] /goodbye/see you again later/"; byte[] b = Encoding.UTF8.GetBytes(s); var stream = new MemoryStream(b); using (var reader = new StreamReader(stream)) { var parser = new CedictParser(reader); CedictEntry entry = await parser.ReadAsync(); Assert.IsNotNull(entry); Assert.AreEqual("再見", entry.Traditional); Assert.AreEqual("再见", entry.Simplified); Assert.AreEqual("zai4 jian4", entry.Pinyin); Assert.IsNotNull(entry.Definitions); Assert.AreEqual(2, entry.Definitions.Length); Assert.AreEqual("goodbye", entry.Definitions[0]); Assert.AreEqual("see you again later", entry.Definitions[1]); } }
public IActionResult SaveFullEntry([FromForm] string entryId, [FromForm] string hw, [FromForm] string trg, [FromForm] string note, [FromForm] string lang) { if (entryId == null || hw == null || trg == null || note == null || lang == null) { return(StatusCode(400, "Missing parameter(s).")); } // Must be authenticated user int userId; string userName; auth.CheckSession(HttpContext.Request.Headers, out userId, out userName); if (userId < 0) { return(StatusCode(401, "Request must contain authentication token.")); } EditEntryResult res = new EditEntryResult(); int idVal = EntryId.StringToId(entryId); trg = trg.Replace("\r\n", "\n"); trg = trg.Replace('/', '\\'); trg = trg.Replace('\n', '/'); trg = "/" + trg + "/"; CedictParser parser = new CedictParser(); CedictEntry entry = null; try { entry = parser.ParseEntry(hw + " " + trg, 0, null); } catch { } if (entry == null) { res.Error = TextProvider.Instance.GetString(lang, "editEntry.badDataOnSave"); return(new ObjectResult(res)); } bool persisted; using (SqlDict.SimpleBuilder builder = dict.GetSimpleBuilder(userId)) { persisted = builder.ChangeHeadAndTarget(userId, idVal, hw, trg, note); } // Not persisted: violates uniqueness constraint if (!persisted) { res.Error = TextProvider.Instance.GetString(lang, "editEntry.duplicateOnSave"); return(new ObjectResult(res)); } // Refresh cached contrib score auth.RefreshUserInfo(userId); // Tell our caller we dun it res.Success = true; return(new ObjectResult(res)); }
/// <summary> /// Import new entries from file as a single bulk change. /// </summary> public void BulkAdd(string dictPath, string workingFolder) { CedictParser parser = new CedictParser(); Startup.InitDB(config, null, false); SqlDict dict = new SqlDict(null, mut); int lineNum = 0; DateTime dt = DateTime.Now; string fnLog = "importlog-" + dt.Year + "-" + dt.Month.ToString("00") + "-" + dt.Day.ToString("00") + "!" + dt.Hour.ToString("00") + "-" + dt.Minute.ToString("00") + "-" + dt.Second.ToString("00") + ".txt"; fnLog = Path.Combine(workingFolder, fnLog); using (FileStream fs = new FileStream(dictPath, FileMode.Open, FileAccess.Read)) using (StreamReader sr = new StreamReader(fs)) using (FileStream fsLog = new FileStream(fnLog, FileMode.Create, FileAccess.ReadWrite)) using (StreamWriter swLog = new StreamWriter(fsLog)) { // First two lines are commented and have metainfo // First line: user name // Second line: bulk change's comment string user = sr.ReadLine().Substring(1).Trim(); string note = sr.ReadLine().Substring(1).Trim(); lineNum = 2; using (SqlDict.ImportBuilder builder = dict.GetBulkBuilder(user, note)) { string line; while ((line = sr.ReadLine()) != null) { ++lineNum; if (line == "" || line.StartsWith("#")) { continue; } CedictEntry entry = parser.ParseEntry(line, lineNum, swLog); if (entry == null) { swLog.WriteLine(line); continue; } entry.Status = EntryStatus.Approved; bool ok = builder.AddNewEntry(entry); if (!ok) { swLog.WriteLine("Line " + lineNum + ": Entry rejected by importer."); swLog.WriteLine(line); continue; } } builder.CommitRest(); } } }
public void Work() { Random rnd = new Random(0); CedictParser parser = new CedictParser(); HashSet <int> idSet = new HashSet <int>(); StringBuilder sb = new StringBuilder(); using (FileStream fsIn = new FileStream("handedict.u8", FileMode.Open, FileAccess.Read)) using (StreamReader sr = new StreamReader(fsIn)) { string line; while ((line = sr.ReadLine()) != null) { if (line.StartsWith("#")) { continue; } CedictEntry entry = parser.ParseEntry(line, 0, null); if (entry == null) { continue; } if (entry.ChSimpl.Length > 16) { continue; } int id = rnd.Next(); while (idSet.Contains(id)) { id = rnd.Next(); } idSet.Add(id); string strId = EntryId.IdToString(id); bool isVerif = isVerified(entry); sb.Clear(); // Line with ID sb.AppendLine("# ID-" + strId); // First version metainfo string statStr = isVerif ? "Stat-Verif" : "Stat-New"; sb.AppendLine("# Ver 2011-05-28T01:27:49Z HanDeDict " + statStr + " 001>Originalversion HanDeDict-Datei"); // The entry itself sb.AppendLine(CedictWriter.Write(entry)); items.Add(new ResItem { ID = id, Lines = sb.ToString() }); } } }
public static void RenderEntryChanges(StringBuilder sb, string currHead, string currTrg, EntryStatus currStatus, List <ChangeItem> changes, string lang) { sb.AppendLine("<div class='pastChanges'><div class='pastInner'>"); CedictParser parser = new CedictParser(); string headNow = currHead; string trgNow = currTrg; EntryStatus statusNow = currStatus; foreach (var ci in changes) { renderPastChange(sb, parser, ref headNow, ref trgNow, ref statusNow, ci, lang); } sb.AppendLine("</div></div>"); // <div class='pastChanges'><div class='pastInner'> }
public void Read_ShouldReturnNull_WhenNothingToRead() { string s = ""; byte[] b = Encoding.UTF8.GetBytes(s); var stream = new MemoryStream(b); using (var reader = new StreamReader(stream)) { var parser = new CedictParser(reader); CedictEntry entry = parser.Read(); Assert.IsNull(entry); } }
public async Task ReadToEndAsync_ShouldReturnEmpty_WhenNothingToRead() { string s = ""; byte[] b = Encoding.UTF8.GetBytes(s); var stream = new MemoryStream(b); using (var reader = new StreamReader(stream)) { var parser = new CedictParser(reader); IList <CedictEntry> entries = await parser.ReadToEndAsync(); Assert.IsNotNull(entries); Assert.AreEqual(0, entries.Count); } }
public async Task ReadToEndAsync_ShouldReturnAllEntries() { string s = "你好 你好 [ni3 hao3] /hello/hi/\n" + "再見 再见 [zai4 jian4] /goodbye/see you again later/"; byte[] b = Encoding.UTF8.GetBytes(s); var stream = new MemoryStream(b); using (var reader = new StreamReader(stream)) { var parser = new CedictParser(reader); IList <CedictEntry> entries = await parser.ReadToEndAsync(); Assert.IsNotNull(entries); Assert.AreEqual(2, entries.Count); CedictEntry entry = entries[0]; Assert.IsNotNull(entry); Assert.AreEqual("你好", entry.Traditional); Assert.AreEqual("你好", entry.Simplified); Assert.AreEqual("ni3 hao3", entry.Pinyin); Assert.IsNotNull(entry.Definitions); Assert.AreEqual(2, entry.Definitions.Length); Assert.AreEqual("hello", entry.Definitions[0]); Assert.AreEqual("hi", entry.Definitions[1]); entry = entries[1]; Assert.IsNotNull(entry); Assert.AreEqual("再見", entry.Traditional); Assert.AreEqual("再见", entry.Simplified); Assert.AreEqual("zai4 jian4", entry.Pinyin); Assert.IsNotNull(entry.Definitions); Assert.AreEqual(2, entry.Definitions.Length); Assert.AreEqual("goodbye", entry.Definitions[0]); Assert.AreEqual("see you again later", entry.Definitions[1]); } }
public void Read_ShouldReturnEntryWithDefaultPropertyValues_WhenEntryIsMalformed() { string s = "你好你好 [ni3 hao3] /hello/hi/"; byte[] b = Encoding.UTF8.GetBytes(s); var stream = new MemoryStream(b); using (var reader = new StreamReader(stream)) { var parser = new CedictParser(reader); CedictEntry entry = parser.Read(); Assert.IsNotNull(entry); Assert.IsNull(entry.Traditional); Assert.IsNull(entry.Simplified); Assert.IsNull(entry.Pinyin); Assert.IsNull(entry.Definitions); } }
public async Task ReadAsync_ShouldReturnNull_WhenNothingLeftToRead() { string s = "你好 你好 [ni3 hao3] /hello/hi/"; byte[] b = Encoding.UTF8.GetBytes(s); var stream = new MemoryStream(b); using (var reader = new StreamReader(stream)) { var parser = new CedictParser(reader); CedictEntry entry = await parser.ReadAsync(); Assert.IsNotNull(entry); entry = parser.Read(); Assert.IsNull(entry); } }
public static CedictEntry BuildEntry(string simp, string trad, string pinyin, string trg) { // Prepare pinyin as list of proper syllables List <PinyinSyllable> pyList = new List <PinyinSyllable>(); string[] pyRawArr = pinyin.Split(' '); foreach (string pyRaw in pyRawArr) { PinyinSyllable ps = PinyinSyllable.FromDisplayString(pyRaw); if (ps == null) { ps = new PinyinSyllable(pyRaw, -1); } pyList.Add(ps); } // Build TRG entry in "canonical" form; parse; render trg = trg.Replace("\r\n", "\n"); string[] senses = trg.Split('\n'); string can = trad + " " + simp + " ["; for (int i = 0; i != pyList.Count; ++i) { if (i != 0) { can += " "; } can += pyList[i].GetDisplayString(false); } can += "] /"; foreach (string str in senses) { can += str.Replace('/', '\\') + "/"; } CedictParser parser = new CedictParser(); return(parser.ParseEntry(can, 0, null)); }
public IActionResult GetEntryPreview([FromQuery] string origHw, [FromQuery] string trad, [FromQuery] string simp, [FromQuery] string pinyin, [FromQuery] string trgTxt, [FromQuery] string lang) { if (origHw == null || trgTxt == null || lang == null) { return(StatusCode(400, "Missing parameter(s).")); } if (trad == null) { trad = ""; } if (simp == null) { simp = ""; } if (pinyin == null) { pinyin = ""; } EditEntryPreviewResult res = new EditEntryPreviewResult(); // Ugly try-catch, but some incorrect input just generates an exception. // We still want to return a meaningful "no preview" response. try { // DBG if (trgTxt.Contains("micu-barf")) { throw new Exception("barf"); } // Validate current headword bool hwParses = validateHeadword(lang, simp, trad, pinyin, res.ErrorsSimp, res.ErrorsTrad, res.ErrorsPinyin); trgTxt = trgTxt.Replace("\r\n", "\n"); trgTxt = trgTxt.Replace('/', '\\'); trgTxt = trgTxt.Replace('\n', '/'); trgTxt = "/" + trgTxt + "/"; // Headword: use original if current headword has errors string hw = trad + " " + simp + " [" + pinyin + "]"; if (!hwParses) { hw = origHw; } CedictParser parser = new CedictParser(); CedictEntry entry = parser.ParseEntry(hw + " " + trgTxt, 0, null); if (entry != null) { EntryRenderer er = new EntryRenderer(lang, entry, true, "mainEntry"); er.OneLineHanziLimit = 12; StringBuilder sb = new StringBuilder(); er.Render(sb, null); res.PreviewHtml = sb.ToString(); } } catch { } return(new ObjectResult(res)); }
public IActionResult GetEditEntryData([FromQuery] string entryId, [FromQuery] string lang) { if (entryId == null || lang == null) { return(StatusCode(400, "Missing parameter(s).")); } // The data we'll return. EditEntryData res = new EditEntryData(); // Is this an authenticated user? int userId; string userName; auth.CheckSession(HttpContext.Request.Headers, out userId, out userName); // Can she approve entries? if (userId != -1) { res.CanApprove = auth.CanApprove(userId); } // Retrieve entry int idVal = EntryId.StringToId(entryId); string hw, trg; EntryStatus status; SqlDict.GetEntryById(idVal, out hw, out trg, out status); CedictParser parser = new CedictParser(); CedictEntry entry = parser.ParseEntry(hw + " " + trg, 0, null); res.Status = status.ToString().ToLowerInvariant(); res.HeadSimp = entry.ChSimpl; res.HeadTrad = entry.ChTrad; res.HeadPinyin = ""; for (int i = 0; i != entry.PinyinCount; ++i) { if (res.HeadPinyin.Length > 0) { res.HeadPinyin += " "; } var pys = entry.GetPinyinAt(i); res.HeadPinyin += pys.GetDisplayString(false); } res.TrgTxt = trg.Trim('/').Replace('/', '\n').Replace('\\', '/'); // Entry HTML entry.Status = status; EntryRenderer er = new EntryRenderer(lang, entry, true, "mainEntry"); er.OneLineHanziLimit = 12; StringBuilder sb = new StringBuilder(); er.Render(sb, null); res.EntryHtml = sb.ToString(); // Entry history List <ChangeItem> changes = SqlDict.GetEntryChanges(idVal); sb.Clear(); HistoryRenderer.RenderEntryChanges(sb, hw, trg, status, changes, lang); res.HistoryHtml = sb.ToString(); return(new ObjectResult(res)); }
public void Work() { Random rnd = new Random(0); CedictParser parser = new CedictParser(); HashSet <int> idSet = new HashSet <int>(); StringBuilder sb = new StringBuilder(); HashSet <char> simpChars = new HashSet <char>(); using (FileStream fsIn = new FileStream("chdict.u8", FileMode.Open, FileAccess.Read)) using (StreamReader sr = new StreamReader(fsIn)) { string line; while ((line = sr.ReadLine()) != null) { if (line.StartsWith("#")) { continue; } int ix1 = line.IndexOf(" ["); int ix2 = line.IndexOf("] /"); line = line.Substring(0, ix1) + " [" + line.Substring(ix1 + 2, ix2 - ix1).ToLower() + line.Substring(ix2 + 2); CedictEntry entry = parser.ParseEntry(line, 0, null); if (entry == null) { continue; } if (entry.ChSimpl.Length > 16) { continue; } int id = rnd.Next(); while (idSet.Contains(id)) { id = rnd.Next(); } idSet.Add(id); string strId = EntryId.IdToString(id); sb.Clear(); // Line with ID sb.AppendLine("# ID-" + strId); // First version metainfo string statStr = "Stat-Verif"; sb.AppendLine("# Ver 2017-05-02T22:41:05Z gabor " + statStr + " 001>CHDICT törzsanyag"); // The entry itself sb.AppendLine(CedictWriter.Write(entry)); foreach (char c in entry.ChSimpl) { simpChars.Add(c); } items.Add(new ResItem { ID = id, Lines = sb.ToString() }); } } }
private static void renderPastChange(StringBuilder sb, CedictParser parser, ref string headNow, ref string trgNow, ref EntryStatus statusNow, ChangeItem ci, string lang) { sb.AppendLine("<div class='pastItem'>"); sb.Append("<div class='changeSummary'>"); sb.Append("<span class='changeType'>"); sb.Append(HtmlEncoder.Default.Encode(getChangeTypeStr(ci.ChangeType, ci.CountB, statusNow, lang))); sb.Append(" • </span>"); sb.Append("<span class='changeUser'>"); sb.Append(HtmlEncoder.Default.Encode(ci.User)); sb.Append("</span>"); sb.Append("<span class='changeTime'>"); sb.Append(HtmlEncoder.Default.Encode(getTimeStr(ci.When, lang))); sb.Append("</span>"); sb.AppendLine("</div>"); // <div class='changeSummary'> sb.AppendLine("<div class='changeNote'>"); sb.Append("<span class='changeNoteText'>"); if (ci.BulkRef != -1) { sb.Append("<span class='bulkLink'>["); sb.Append("<a href='/" + lang + "/read/details/change-" + ci.BulkRef.ToString("000") + "' target='_blank'>"); sb.Append(TextProvider.Instance.GetString(lang, "history.bulkLink") + "</a>"); sb.Append("]</span> "); } string note = HtmlEncoder.Default.Encode(ci.Note); note = note.Replace("
", "<br/>"); sb.Append(note); sb.Append("</span>"); sb.AppendLine("</div>"); // <div class='changeNote'> if (ci.HeadBefore != null) { CedictEntry eCurr = parser.ParseEntry(headNow + " /x/", -1, null); CedictEntry eOld = parser.ParseEntry(ci.HeadBefore + " /x/", -1, null); bool simpChanged = eCurr.ChSimpl != eOld.ChSimpl; bool tradChanged = eCurr.ChTrad != eOld.ChTrad; bool pinyinChanged = CedictWriter.WritePinyin(eCurr) != CedictWriter.WritePinyin(eOld); // Render in parts sb.AppendLine("<div class='entry'>"); // Let's not dim identical chars if anything changed in HW EntryRenderer rCurr = new EntryRenderer(lang, eCurr, !simpChanged && !tradChanged); EntryRenderer rOld = new EntryRenderer(lang, eOld, !simpChanged && !tradChanged); rCurr.OneLineHanziLimit = rOld.OneLineHanziLimit = 12; if (simpChanged || tradChanged) { rCurr.XRenderHanzi(sb, simpChanged ? "new" : "", tradChanged ? "new" : ""); rOld.XRenderHanzi(sb, simpChanged ? "old" : "", tradChanged ? "old" : ""); } if (pinyinChanged) { rCurr.XRenderPinyin(sb, pinyinChanged ? "new" : ""); rOld.XRenderPinyin(sb, "old"); } sb.AppendLine("</div>"); // <div class='entry'> // Propagate change headNow = ci.HeadBefore; } if (ci.BodyBefore != null) { CedictEntry entryNew = parser.ParseEntry("的 的 [de5] " + trgNow, -1, null); EntryRenderer er = new EntryRenderer(lang, entryNew, true); er.XRenderSenses(sb, "new"); CedictEntry entryOld = parser.ParseEntry("的 的 [de5] " + ci.BodyBefore, -1, null); er = new EntryRenderer(lang, entryOld, true); er.XRenderSenses(sb, "old"); // Propagate change trgNow = ci.BodyBefore; } if (ci.StatusBefore != 99) { statusNow = (EntryStatus)ci.StatusBefore; } sb.AppendLine("</div>"); // <div class='pastItem'> }
private static void histRenderChange(StringBuilder sb, ChangeItem ci, bool trailingSeparator, string lang, CedictParser parser, string extraItemClass = "") { var tprov = TextProvider.Instance; sb.AppendLine(); string itemClass = "historyItem"; if (!string.IsNullOrEmpty(extraItemClass)) { itemClass += " " + extraItemClass; } if (ci.EntryId >= 0) { sb.AppendLine("<div class='" + itemClass + "' data-entry-id='" + EntryId.IdToString(ci.EntryId) + "'>"); } else { sb.AppendLine("<div class='" + itemClass + "'>"); } sb.AppendLine("<div class='changeHead'>"); string iconClass = ""; if (ci.ChangeType == ChangeType.New) { iconClass = "fa fa-lightbulb-o ctNew"; } else if (ci.ChangeType == ChangeType.Edit) { iconClass = "fa fa-pencil-square-o ctEdit"; } else if (ci.ChangeType == ChangeType.Note) { iconClass = "fa fa-commenting-o ctNote"; } else if (ci.ChangeType == ChangeType.BulkImport) { iconClass = "fa fa-newspaper-o ctBulk"; } else if (ci.ChangeType == ChangeType.StatusChange) { if (ci.EntryStatus == EntryStatus.Approved) { iconClass = "fa fa-check-square-o ctApprove"; } else if (ci.EntryStatus == EntryStatus.Flagged) { iconClass = "fa fa-flag-o ctFlag"; } else { iconClass = "fa fa-flag-o ctUnflag"; } } sb.Append("<i class='" + iconClass + "' />"); sb.Append("<div class='changeSummary'>"); string changeMsg = getChangeTypeStr(ci.ChangeType, ci.CountB, ci.EntryStatus, lang); string changeCls = "changeType"; sb.Append("<span class='" + changeCls + "'>"); sb.Append(HtmlEncoder.Default.Encode(changeMsg)); sb.Append(" • </span>"); sb.Append("<span class='changeUser'>"); sb.Append(HtmlEncoder.Default.Encode(ci.User)); sb.Append("</span>"); sb.Append("<span class='changeTime'>"); sb.Append(HtmlEncoder.Default.Encode(getTimeStr(ci.When, lang))); sb.Append("</span>"); if (ci.ChangeType != ChangeType.BulkImport && ci.CountA > 0) { sb.Append("<span class='revealPast'>+" + ci.CountA.ToString() + "</span>"); } sb.Append("</div>"); // <div class='changeSummary'> sb.AppendLine("<div class='changeNote'>"); if (ci.ChangeType == ChangeType.BulkImport) { string newCount = null; string chgCount = null; if (ci.CountA > 0) { newCount = tprov.GetString(lang, "history.bulkNewWords"); newCount = string.Format(newCount, ci.CountA); } if (ci.CountB > 0) { chgCount = tprov.GetString(lang, "history.bulkChangedWords"); chgCount = string.Format(chgCount, ci.CountB); } if (chgCount != null || newCount != null) { sb.Append("<p>"); if (newCount != null) { sb.Append(HtmlEncoder.Default.Encode(newCount)); } if (newCount != null && chgCount != null) { sb.Append(" • "); } if (chgCount != null) { sb.Append(HtmlEncoder.Default.Encode(chgCount)); } sb.Append("</p>"); } sb.Append("<span class='bulkLink'>["); sb.Append("<a href='/" + lang + "/read/details/change-" + ci.BulkRef.ToString("000") + "' target='_blank'>"); sb.Append(tprov.GetString(lang, "history.bulkLink") + "</a>"); sb.Append("]</span> "); } sb.Append("<span class='changeNoteText'>"); string note = HtmlEncoder.Default.Encode(ci.Note); note = note.Replace("
", "<br/>"); sb.Append(note); sb.Append("</span>"); sb.Append("</div>"); sb.Append("</div>"); // <div class='changeHead'> sb.AppendLine("<div class='changeEntry'>"); if (ci.ChangeType != ChangeType.BulkImport) { sb.AppendLine("<div class='histEntryOps'>"); sb.Append("<a class='ajax' href='/" + lang + "/edit/existing/" + EntryId.IdToString(ci.EntryId) + "'>"); sb.Append("<i class='opHistEdit fa fa-pencil'></i></a>"); //sb.Append("<i class='opHistEdit fa fa-pencil' />"); sb.Append("<i class='opHistComment fa fa-commenting-o' />"); sb.Append("<i class='opHistFlag fa fa-flag-o' />"); sb.Append("</div>"); // <div class='histEntryOps'> } if (ci.ChangeType != ChangeType.BulkImport) { // NOT edited if (ci.BodyBefore == null && ci.HeadBefore == null) { CedictEntry entry = parser.ParseEntry(ci.EntryHead + " " + ci.EntryBody, 0, null); entry.Status = ci.EntryStatus; EntryRenderer er = new EntryRenderer(lang, entry, true); er.OneLineHanziLimit = 12; er.Render(sb, null); } // Entry edited: show "diff" in head and/or body else { // Current, and comparison base CedictEntry eCurr = parser.ParseEntry(ci.EntryHead + " " + ci.EntryBody, 0, null); eCurr.Status = ci.EntryStatus; string headOld = ci.HeadBefore == null ? ci.EntryHead : ci.HeadBefore; string bodyOld = ci.BodyBefore == null ? ci.EntryBody : ci.BodyBefore; CedictEntry eOld = parser.ParseEntry(headOld + " " + bodyOld, 0, null); bool simpChanged = eCurr.ChSimpl != eOld.ChSimpl; bool tradChanged = eCurr.ChTrad != eOld.ChTrad; bool pinyinChanged = CedictWriter.WritePinyin(eCurr) != CedictWriter.WritePinyin(eOld); bool bodyChanged = ci.BodyBefore != null; // Render in parts sb.AppendLine("<div class='entry'>"); // Let's not dim identical chars if anything changed in HW EntryRenderer rCurr = new EntryRenderer(lang, eCurr, !simpChanged && !tradChanged); EntryRenderer rOld = new EntryRenderer(lang, eOld, !simpChanged && !tradChanged); rCurr.OneLineHanziLimit = rOld.OneLineHanziLimit = 12; rCurr.XRenderStatus(sb); rCurr.XRenderHanzi(sb, simpChanged ? "new" : "", tradChanged ? "new" : ""); if (simpChanged || tradChanged) { rOld.XRenderHanzi(sb, simpChanged ? "old" : "", tradChanged ? "old" : ""); } rCurr.XRenderPinyin(sb, pinyinChanged ? "new" : ""); if (pinyinChanged) { rOld.XRenderPinyin(sb, "old"); } rCurr.XRenderSenses(sb, bodyChanged ? "new" : ""); if (bodyChanged) { rOld.XRenderSenses(sb, "old"); } sb.AppendLine("</div>"); // <div class='entry'> } } sb.Append("</div>"); // <div class='changeEntry'> sb.Append("</div>"); // <div class='changeHead'> sb.Append("</div>"); // <div class='historyItem'> sb.AppendLine(); if (trailingSeparator) { sb.AppendLine("<div class='historySep'></div>"); } }
private bool validateHeadword(string lang, string simp, string trad, string pinyin, List <HeadwordProblem> errorsSimp, List <HeadwordProblem> errorsTrad, List <HeadwordProblem> errorsPinyin) { var tprov = TextProvider.Instance; string msg; // Check each simplified: is it really simplified? UniHanziInfo[] uhiSimp = langRepo.GetUnihanInfo(simp); for (int i = 0; i != uhiSimp.Length; ++i) { var uhi = uhiSimp[i]; if (!uhi.CanBeSimp) { msg = tprov.GetString(lang, "editEntry.hwProblemNotSimplified"); msg = string.Format(msg, simp[i]); errorsSimp.Add(new HeadwordProblem(false, msg)); } } // Check each traditional: is it really traditional? UniHanziInfo[] uhiTrad = langRepo.GetUnihanInfo(trad); for (int i = 0; i != uhiTrad.Length; ++i) { var uhi = uhiTrad[i]; // Traditional chars are listed as their own traditional variant if (Array.IndexOf(uhi.TradVariants, trad[i]) < 0) { msg = tprov.GetString(lang, "editEntry.hwProblemNotTraditional"); msg = string.Format(msg, trad[i]); errorsTrad.Add(new HeadwordProblem(false, msg)); } } // Check each traditional against its simplified friend if (trad.Length != simp.Length) { errorsTrad.Add(new HeadwordProblem(true, tprov.GetString(lang, "editEntry.hwProblemSimpTradCounts"))); } else { for (int i = 0; i != uhiSimp.Length; ++i) { var uhi = uhiSimp[i]; if (Array.IndexOf(uhi.TradVariants, trad[i]) < 0) { msg = tprov.GetString(lang, "editEntry.hwProblemNotTradForSimp"); msg = string.Format(msg, simp[i], trad[i]); errorsTrad.Add(new HeadwordProblem(false, msg)); } } } // Normalize pinyin (multiple spaces, leading/trailing spaces) string pyNorm = pinyin; while (true) { string x = pyNorm.Replace(" ", " "); if (x == pyNorm) { break; } pyNorm = x; } pyNorm = pyNorm.Trim(); if (pyNorm != pinyin) { errorsPinyin.Add(new HeadwordProblem(true, tprov.GetString(lang, "editEntry.hwProblemExtraSpacesPinyin"))); } // Try to match up normalized pinyin with simplified Hanzi CedictParser parser = new CedictParser(); CedictEntry ee = null; try { ee = parser.ParseEntry(trad + " " + simp + " [" + pyNorm + "] /x/", 0, null); } catch { } if (ee == null) { errorsPinyin.Add(new HeadwordProblem(true, tprov.GetString(lang, "editEntry.hwProblemInvalidPinyin"))); } else { if (simp.Length == ee.ChSimpl.Length) { for (int i = 0; i != uhiSimp.Length; ++i) { var uhi = uhiSimp[i]; var py = ee.GetPinyinAt(i); var cnt = uhi.Pinyin.Count(x => x.GetDisplayString(false) == py.GetDisplayString(false)); if (cnt == 0) { msg = tprov.GetString(lang, "editEntry.hwProblemWrongPinyin"); msg = string.Format(msg, py.GetDisplayString(false), simp[i]); errorsPinyin.Add(new HeadwordProblem(false, msg)); } } } } return(ee != null); }