/// <summary> /// Check the following lines in the PO file header for compatibility: /// MIME-Version: /// Content-Type: /// Content-Transfer-Encoding: /// X-Poedit-Language: /// X-Poedit-Country: /// </summary> /// <param name="posMainHeader"></param> /// <param name="posNewHeader"></param> private static void CheckCompatiblePOFiles(POString posMainHeader, POString posNewHeader) { CheckCompatiblePOHeader(posMainHeader, posNewHeader, "MIME Version", IsMIMEVersion); CheckCompatiblePOHeader(posMainHeader, posNewHeader, "Content Type", IsContentType); CheckCompatiblePOHeader(posMainHeader, posNewHeader, "Encoding", IsContentTransferEncoding); CheckCompatiblePOHeader(posMainHeader, posNewHeader, "Language", IsXPoeditLanguage); CheckCompatiblePOHeader(posMainHeader, posNewHeader, "Country", IsXPoeditCountry); }
private static void CheckCompatiblePOHeader(POString posMainHeader, POString posNewHeader, string sHeader, Predicate<string> matchFn) { string sPo1 = posMainHeader.MsgStr.Find(matchFn); string sPo2 = posNewHeader.MsgStr.Find(matchFn); if (sPo1 == null || sPo2 == null || sPo1.ToLower() == sPo2.ToLower()) return; int idx = sPo1.IndexOf(":"); string s1 = sPo1.Substring(idx + 1).Trim(); string s2 = sPo2.Substring(idx + 1).Trim(); if (String.IsNullOrEmpty(s1) || String.IsNullOrEmpty(s2)) return; if (s1.ToLower() == s2.ToLower()) return; Console.WriteLine("WARNING: first file's {0} = \"{1}\", but second file's {0} = \"{2}\"", sHeader, s1, s2); }
public bool HasSameMsgId(POString that) { if (this.m_rgsMsgId == null && that.m_rgsMsgId == null) { return(true); } else if (this.m_rgsMsgId == null || that.m_rgsMsgId == null) { return(false); } for (int i = 0; i < this.m_rgsMsgId.Count && i < that.m_rgsMsgId.Count; ++i) { string s1 = this.m_rgsMsgId[i]; string s2 = that.m_rgsMsgId[i]; if (s1 != s2) { return(false); } } return(this.m_rgsMsgId.Count == that.m_rgsMsgId.Count); }
/// <summary> /// CompareMsgIds two POString objects with the purpose of sorting the PO file by msgid. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public static int CompareMsgIds(POString x, POString y) { if (x.m_rgsMsgId == null && y.m_rgsMsgId == null) { return(0); } else if (x.m_rgsMsgId == null) { return(-1); } else if (y.m_rgsMsgId == null) { return(1); } for (int i = 0; i < x.m_rgsMsgId.Count && i < y.m_rgsMsgId.Count; ++i) { string s1 = RemoveLeadingCruft(x.m_rgsMsgId[i].Replace("&", "").Trim()); string s2 = RemoveLeadingCruft(y.m_rgsMsgId[i].Replace("&", "").Trim()); int n = s1.CompareTo(s2); if (n != 0) { return(n); } } if (x.m_rgsMsgId.Count < y.m_rgsMsgId.Count) { return(-1); } else if (x.m_rgsMsgId.Count > y.m_rgsMsgId.Count) { return(1); } else { return(x.m_rgsMsgId[0].CompareTo(y.m_rgsMsgId[0])); } }
private static Dictionary<string, POString> LoadPOFile(string sMsgFile, out POString posHeader) { using (StreamReader srIn = new StreamReader(sMsgFile, Encoding.UTF8)) { Dictionary<string, POString> dictTrans = new Dictionary<string, POString>(); posHeader = POString.ReadFromFile(srIn); POString pos = POString.ReadFromFile(srIn); while (pos != null) { if (!pos.HasEmptyMsgStr) dictTrans.Add(pos.MsgIdAsString(), pos); pos = POString.ReadFromFile(srIn); } srIn.Close(); return dictTrans; } }
private static void MergePOHeaderLines(POString posMainHeader, POString posNewHeader, string sHeaderTag, Predicate<string> matchFn) { string sPo2 = posNewHeader.MsgStr.Find(matchFn); if (sPo2 == null) return; // no information in new file string s2 = sPo2.Substring(sHeaderTag.Length).Trim(); if (String.IsNullOrEmpty(s2)) return; // no information in new file int idx = posMainHeader.MsgStr.FindIndex(matchFn); if (idx < 0) { posMainHeader.MsgStr.Add(sPo2); // no information in old file: add new info at end. return; } string s1 = posMainHeader.MsgStr[idx].Substring(sHeaderTag.Length).Trim(); if (s1.ToLower() == s2.ToLower()) return; // same information as before if (String.IsNullOrEmpty(s1)) { // empty information in the old file: store information from new file posMainHeader.MsgStr[idx] = String.Format("{0} {1}\n", sHeaderTag, s2); return; } int ich = s1.ToLower().IndexOf(s2.ToLower()); if (ich < 0) { // add the new info to the end of the old info posMainHeader.MsgStr[idx] = String.Format("{0} {1}; {2}\n", sHeaderTag, s1, s2); } }
/// <summary> /// Merge information in the following header lines: /// Project-Id-Version: /// POT-Creation-Date: /// PO-Revision-Date: /// Last-Translator: /// Language-Team: /// </summary> /// <param name="posMainHeader"></param> /// <param name="posNewHeader"></param> private static void MergePOHeaders(POString posMainHeader, POString posNewHeader) { MergePOHeaderLines(posMainHeader, posNewHeader, "Project-Id-Version:", IsProjectIdVersion); MergePOHeaderLines(posMainHeader, posNewHeader, "POT-Creation-Date:", IsPOTCreationDate); MergePOHeaderLines(posMainHeader, posNewHeader, "PO-Revision-Date:", IsPORevisionDate); MergePOHeaderLines(posMainHeader, posNewHeader, "Last-Translator:", IsLastTranslator); MergePOHeaderLines(posMainHeader, posNewHeader, "Language-Team:", IsLanguageTeam); }
/// <summary> /// Load a single resource (.resx) file, possibly merging in string values from a /// localized version of the same, and write the strings found therein to the output /// (.po) file. /// </summary> /// <param name="sResxFile">full pathname of the resource file</param> /// <param name="sRoot"></param> /// <param name="rgsPOStrings"></param> private static void ProcessResxFile(string sResxFile, string sRoot, List<POString> rgsPOStrings) { //int cPOStrings = rgsPOStrings.Count; XmlDocument xdoc = new XmlDocument(); xdoc.Load(sResxFile); string sIgnore = sRoot.Replace('\\', '/'); if (sIgnore.EndsWith("/")) sIgnore = sIgnore.Substring(0, sIgnore.Length - 1); foreach (XmlNode x in xdoc.DocumentElement.ChildNodes) { XmlElement xel = x as XmlElement; if (xel != null && xel.Name == "data") { string sName = xel.GetAttribute("name"); string sType = xel.GetAttribute("type"); string sMimeType = xel.GetAttribute("mimetype"); string sValue = null; string sComment = null; if (!String.IsNullOrEmpty(sName) && String.IsNullOrEmpty(sType) && String.IsNullOrEmpty(sMimeType)) { if (!sName.StartsWith(">>") && IsTextName(sName)) { for (int i = 0; i < xel.ChildNodes.Count; ++i) { if (xel.ChildNodes[i].Name == "value") sValue = xel.ChildNodes[i].InnerText; if (xel.ChildNodes[i].Name == "comment") sComment = xel.ChildNodes[i].InnerText; } } } if (!String.IsNullOrEmpty(sValue)) { if (sValue.IndexOfAny("/\\".ToCharArray()) >= 0 && sValue.Trim().EndsWith(".htm")) continue; if (sComment != null && sComment.Trim().ToLower() == "do not translate") continue; if (String.IsNullOrEmpty(sValue.Trim())) continue; if (sValue.IndexOf("\\n") >= 0 || sValue.IndexOf("\\r") >= 0 || sValue.IndexOf("\\t") >= 0 || sValue.IndexOf("\\\\") >= 0 || sValue.IndexOf("\\\"") >= 0) { s_fBadStringValue = true; Console.WriteLine( string.Format("Backslash quoted character found for {0} in {1}", sName, sResxFile)); } string[] rgsComment = null; if (!String.IsNullOrEmpty(sComment)) rgsComment = sComment.Split(s_rgsNewline, StringSplitOptions.None); sValue = FixStringForEmbeddedQuotes(sValue); string[] rgsId = sValue.Split(s_rgsNewline, StringSplitOptions.None); string[] rgsStr = new string[1] { "" }; POString pos = new POString(rgsComment, rgsId, rgsStr); string sPath = String.Format("{0}::{1}", sResxFile.Replace('\\', '/'), sName); if (sPath.StartsWith(sIgnore)) sPath = sPath.Substring(sIgnore.Length); pos.AddAutoComment(sPath); rgsPOStrings.Add(pos); } } } //cPOStrings = rgsPOStrings.Count - cPOStrings; //Console.WriteLine( // String.Format("{0} added {1} strings (possibly duplicates) to the POT file.", // sResxFile, cPOStrings)); }
/// <summary> /// Process one element from the strings-en.xml file. /// </summary> /// <param name="xmlElement"></param> /// <param name="rgsPOStrings"></param> private static void ProcessStringsElement(XmlElement xel, List<POString> rgsPOStrings) { if (xel.Name == "string") { string sTxt = FixStringForEmbeddedQuotes(xel.GetAttribute("txt")); if (!String.IsNullOrEmpty(sTxt.Trim())) { string sComment = xel.GetAttribute("translate"); if (sComment.Trim().ToLower() != "do not translate") { string sPath = ComputeStringPathComment(xel); string[] rgsComments = null; if (!String.IsNullOrEmpty(sComment.Trim())) rgsComments = new string[2] { sComment, sPath }; else rgsComments = new string[1] { sPath }; POString pos = new POString(rgsComments, new string[1] { sTxt }, new string[1] { "" }); rgsPOStrings.Add(pos); } } } foreach (XmlNode xn in xel.ChildNodes) { if (xn is XmlElement) ProcessStringsElement(xn as XmlElement, rgsPOStrings); } }
/// <summary> /// Store the string for a <lit> element. /// </summary> /// <param name="xel"></param> /// <param name="rgsPOStrings"></param> private static void StoreLiteralString(XmlElement xel, List<POString> rgsPOStrings) { string sTranslate = xel.GetAttribute("translate"); if (sTranslate.Trim().ToLower() == "do not translate") return; string sPath = ComputePathComment(xel, null); string[] rgsComment = null; if (String.IsNullOrEmpty(sTranslate)) rgsComment = new string[1] { sPath }; else rgsComment = new string[2] { sPath, FixStringForEmbeddedQuotes(sTranslate) }; string sVal = FixStringForEmbeddedQuotes(xel.InnerText); string[] rgsValue = sVal.Split(s_rgsNewline, StringSplitOptions.None); POString pos = new POString(rgsComment, rgsValue, new string[1] { "" }); rgsPOStrings.Add(pos); }
/// <summary> /// Store an attribute value with a comment giving its xpath location. /// </summary> /// <param name="xel"></param> /// <param name="sName"></param> /// <param name="sValue"></param> /// <param name="rgsPOStrings"></param> private static void StoreAttributeString(XmlElement xel, string sName, string sValue, List<POString> rgsPOStrings) { string sTranslate = xel.GetAttribute("translate"); if (sTranslate.Trim().ToLower() == "do not translate") return; string sPath = ComputePathComment(xel, sName); string[] rgsComment = null; if (String.IsNullOrEmpty(sTranslate)) rgsComment = new string[1] { sPath }; else rgsComment = new string[2] { sPath, FixStringForEmbeddedQuotes(sTranslate) }; POString pos = new POString(rgsComment, new string[1] { FixStringForEmbeddedQuotes(sValue) }, new string[1] { "" }); rgsPOStrings.Add(pos); }
public bool HasSameMsgId(POString that) { if (this.m_rgsMsgId == null && that.m_rgsMsgId == null) return true; else if (this.m_rgsMsgId == null || that.m_rgsMsgId == null) return false; for (int i = 0; i < this.m_rgsMsgId.Count && i < that.m_rgsMsgId.Count; ++i) { string s1 = this.m_rgsMsgId[i]; string s2 = that.m_rgsMsgId[i]; if (s1 != s2) return false; } return this.m_rgsMsgId.Count == that.m_rgsMsgId.Count; }
public static POString ReadFromFile(StreamReader srIn) { // Move past any blank lines, checking for the end of file. if (srIn.EndOfStream) return null; string s = srIn.ReadLine(); ++s_cLines; if (s != null) s = s.Trim(); while (String.IsNullOrEmpty(s)) { if (srIn.EndOfStream) return null; s = srIn.ReadLine(); ++s_cLines; if (s != null) s = s.Trim(); } POString pos = new POString(); bool fMsgId = false; bool fMsgStr = false; bool fError = false; do { if (s == "#") { pos.AddUserComment(""); } else if (s.StartsWith("# ")) { pos.AddUserComment(s.Substring(2).TrimStart()); } else if (s.StartsWith("#.")) { pos.AddAutoComment(s.Substring(2).TrimStart()); } else if (s.StartsWith("#:")) { pos.AddReference(s.Substring(2).TrimStart()); } else if (s.StartsWith("#,")) { pos.AddFlags(s.Substring(2).TrimStart()); } else if (s.ToLower().StartsWith("msgid")) { fMsgId = true; if (fMsgStr) fError = true; pos.AddMsgIdLine(s); } else if (s.ToLower().StartsWith("msgstr")) { if (!fMsgId) fError = true; fMsgId = false; fMsgStr = true; pos.AddMsgStrLine(s); } else if (s.StartsWith("\"")) { if (fMsgId) pos.AddMsgIdLine(s); else if (fMsgStr) pos.AddMsgStrLine(s); else fError = true; } else if (s.StartsWith("#~")) { pos.IsObsolete = true; if (pos.UserComments != null) pos.UserComments.Clear(); if (pos.AutoComments != null) pos.AutoComments.Clear(); if (pos.Reference != null) pos.Reference.Clear(); if (pos.Flags != null) pos.Flags.Clear(); if (pos.MsgId != null) pos.MsgId.Clear(); if (pos.MsgStr != null) pos.MsgStr.Clear(); } else { fError = true; } if (fError) { Console.WriteLine("INVALID PO FILE: ERROR ON LINE " + s_cLines); throw new Exception("BAD PO FILE"); } if (srIn.EndOfStream) break; s = srIn.ReadLine(); ++s_cLines; if (s != null) s = s.Trim(); } while (!String.IsNullOrEmpty(s)); return pos; }
/// <summary> /// CompareMsgIds two POString objects with the purpose of sorting the PO file by msgid. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public static int CompareMsgIds(POString x, POString y) { if (x.m_rgsMsgId == null && y.m_rgsMsgId == null) return 0; else if (x.m_rgsMsgId == null) return -1; else if (y.m_rgsMsgId == null) return 1; for (int i = 0; i < x.m_rgsMsgId.Count && i < y.m_rgsMsgId.Count; ++i) { string s1 = RemoveLeadingCruft(x.m_rgsMsgId[i].Replace("&", "").Trim()); string s2 = RemoveLeadingCruft(y.m_rgsMsgId[i].Replace("&", "").Trim()); int n = s1.CompareTo(s2); if (n != 0) return n; } if (x.m_rgsMsgId.Count < y.m_rgsMsgId.Count) return -1; else if (x.m_rgsMsgId.Count > y.m_rgsMsgId.Count) return 1; else return x.m_rgsMsgId[0].CompareTo(y.m_rgsMsgId[0]); }
static public POString ReadFromFile(StreamReader srIn) { // Move past any blank lines, checking for the end of file. if (srIn.EndOfStream) { return(null); } string s = srIn.ReadLine(); ++s_cLines; if (s != null) { s = s.Trim(); } while (String.IsNullOrEmpty(s)) { if (srIn.EndOfStream) { return(null); } s = srIn.ReadLine(); ++s_cLines; if (s != null) { s = s.Trim(); } } POString pos = new POString(); bool fMsgId = false; bool fMsgStr = false; bool fError = false; do { if (s == "#") { pos.AddUserComment(""); } else if (s.StartsWith("# ")) { pos.AddUserComment(s.Substring(2).TrimStart()); } else if (s.StartsWith("#.")) { pos.AddAutoComment(s.Substring(2).TrimStart()); } else if (s.StartsWith("#:")) { pos.AddReference(s.Substring(2).TrimStart()); } else if (s.StartsWith("#,")) { pos.AddFlags(s.Substring(2).TrimStart()); } else if (s.ToLower().StartsWith("msgid")) { fMsgId = true; if (fMsgStr) { fError = true; } pos.AddMsgIdLine(s); } else if (s.ToLower().StartsWith("msgstr")) { if (!fMsgId) { fError = true; } fMsgId = false; fMsgStr = true; pos.AddMsgStrLine(s); } else if (s.StartsWith("\"")) { if (fMsgId) { pos.AddMsgIdLine(s); } else if (fMsgStr) { pos.AddMsgStrLine(s); } else { fError = true; } } else if (s.StartsWith("#~")) { pos.IsObsolete = true; if (pos.UserComments != null) { pos.UserComments.Clear(); } if (pos.AutoComments != null) { pos.AutoComments.Clear(); } if (pos.Reference != null) { pos.Reference.Clear(); } if (pos.Flags != null) { pos.Flags.Clear(); } if (pos.MsgId != null) { pos.MsgId.Clear(); } if (pos.MsgStr != null) { pos.MsgStr.Clear(); } } else { fError = true; } if (fError) { Console.WriteLine("INVALID PO FILE: ERROR ON LINE " + s_cLines); throw new Exception("BAD PO FILE"); } if (srIn.EndOfStream) { break; } s = srIn.ReadLine(); ++s_cLines; if (s != null) { s = s.Trim(); } } while (!String.IsNullOrEmpty(s)); return(pos); }