Ejemplo n.º 1
0
        /// <summary>
        /// Extract all the localizable strings from the XML configuration files in the FieldWorks distribution tree.
        /// </summary>
        /// <returns>Sorted and merged list of localizable strings</returns>
        private static List <POString> ExtractLocalizableStrings(string distFilesDir)
        {
            var poStrings = new List <POString>(1000);

            ExtractFromXmlConfigFiles(distFilesDir, poStrings);

            poStrings.Sort(POString.CompareMsgIds);
            POString.MergeDuplicateStrings(poStrings);
            return(poStrings);
        }
Ejemplo n.º 2
0
        internal static Dictionary <string, POString> ReadPoFile(TextReader srIn, TaskLoggingHelper log)
        {
            POString.ResetInputLineNumber();
            var dictTrans = new Dictionary <string, POString>();

            POString.ReadFromFile(srIn);             // read header
            var poStr = POString.ReadFromFile(srIn);

            while (poStr != null)
            {
                StoreString(dictTrans, poStr, log);
                poStr = POString.ReadFromFile(srIn);
            }
            return(dictTrans);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Store an attribute value with a comment giving its xpath location.
        /// </summary>
        private static void StoreAttributeString(XElement xel, string name, string value,
                                                 List <POString> poStrings, string autoCommentFilePath)
        {
            var sTranslate = xel.Attribute("translate")?.Value;

            if (sTranslate?.Trim().ToLower() == "do not translate")
            {
                return;
            }
            var sPath    = ComputePathComment(xel, name, autoCommentFilePath);
            var comments = string.IsNullOrEmpty(sTranslate)
                                ? new[] { sPath }
                                : new[] { sPath, EscapeStringForPo(sTranslate) };
            var pos = new POString(comments, new[] { EscapeStringForPo(value) });

            poStrings.Add(pos);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Store a POString in the dictionary, unless another string with the same msgid already exists.
        /// </summary>
        public static void StoreString(Dictionary <string, POString> dictTrans, POString poStr, TaskLoggingHelper log)
        {
            if (poStr.IsObsolete)
            {
                return;
            }
            var msgid = poStr.MsgIdAsString();

            if (dictTrans.ContainsKey(msgid))
            {
                log?.LogMessage("The message id '{0}' already exists.  Ignoring this occurrence around line {1}.", msgid, POString.InputLineNumber);
            }
            else
            {
                dictTrans.Add(msgid, poStr);
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Store the string for a &lt;lit&gt; element.
        /// </summary>
        private static void StoreLiteralString(XElement xel, List <POString> poStrings, string autoCommentFilePath)
        {
            var sTranslate = xel.Attribute("translate")?.Value;

            if (sTranslate?.Trim().ToLower() == "do not translate")
            {
                return;
            }
            var sPath    = ComputePathComment(xel, null, autoCommentFilePath);
            var comments = string.IsNullOrEmpty(sTranslate)
                                ? new[] { sPath }
                                : new[] { sPath, EscapeStringForPo(sTranslate) };
            var value      = EscapeStringForPo(xel.Value);
            var valueLines = value.Split(NewlineChars, StringSplitOptions.None);
            var pos        = new POString(comments, valueLines);

            poStrings.Add(pos);
        }
Ejemplo n.º 6
0
 public bool HasSameMsgId(POString that)
 {
     if (MsgId == null && that.MsgId == null)
     {
         return(true);
     }
     if (MsgId == null || that.MsgId == null || MsgId.Count != that.MsgId.Count)
     {
         return(false);
     }
     for (var i = 0; i < MsgId.Count; ++i)
     {
         var s1 = MsgId[i];
         var s2 = that.MsgId[i];
         if (s1 != s2)
         {
             return(false);
         }
     }
     return(true);
 }
Ejemplo n.º 7
0
        /// <summary>
        /// CompareMsgIds two POString objects with the purpose of sorting the PO file by msgid.
        /// </summary>
        public static int CompareMsgIds(POString x, POString y)
        {
            if (x.MsgId == null && y.MsgId == null)
            {
                return(0);
            }
            if (x.MsgId == null)
            {
                return(-1);
            }
            if (y.MsgId == null)
            {
                return(1);
            }

            // First, ignore case and cruft so that similar strings are close together
            for (var i = 0; i < x.MsgId.Count && i < y.MsgId.Count; ++i)
            {
                var s1 = RemoveCruft(x.MsgId[i]);
                var s2 = RemoveCruft(y.MsgId[i]);
                var n  = string.Compare(s1, s2, StringComparison.OrdinalIgnoreCase);
                if (n != 0)
                {
                    return(n);
                }
            }
            if (x.MsgId.Count < y.MsgId.Count)
            {
                return(-1);
            }
            if (x.MsgId.Count > y.MsgId.Count)
            {
                return(1);
            }

            // If the strings are otherwise identical, sort including case and cruft so that
            // identical strings can be merged without the interference of not-quite-identical strings
            return(string.Compare(x.MsgId[0], y.MsgId[0], StringComparison.Ordinal));
        }
Ejemplo n.º 8
0
        private static void WritePoHeader(TextWriter writer, string fwRoot, string locale)
        {
            writer.WriteLine("");               // StreamWriter writes a BOM for UTF-8: put it on a line by itself.
            var          sTime         = DateTime.Now.ToLocalTime().ToString("o");
            const string fromFwSources = "Created from FieldWorks sources";

            POString.WriteComment(fromFwSources, ' ', writer);
            var copyrightSIL = $"Copyright (c) {DateTime.Now.Year} SIL International";

            POString.WriteComment(copyrightSIL, ' ', writer);
            POString.WriteComment("This software is licensed under the LGPL, version 2.1 or later",
                                  ' ', writer);
            POString.WriteComment("(http://www.gnu.org/licenses/lgpl-2.1.html)", ' ', writer);
            POString.WriteComment("", ' ', writer);
            //POString.WriteComment("fuzzy", ',', swOut);	the on-line translation site doesn't like this.
            writer.Write("msgid ");
            POString.WriteQuotedLine("", writer);
            writer.Write("msgstr ");
            POString.WriteQuotedLine("", writer);
            var sVersion = GetFieldWorksVersion(fwRoot);

            POString.WriteQuotedLine($@"Project-Id-Version: {sVersion}\n", writer);
            POString.WriteQuotedLine(@"Report-Msgid-Bugs-To: [email protected]\n", writer);
            POString.WriteQuotedLine($@"POT-Creation-Date: {sTime}\n", writer);
            POString.WriteQuotedLine(@"PO-Revision-Date: \n", writer);
            POString.WriteQuotedLine(@"Last-Translator: Full Name <email@address>\n", writer);
            POString.WriteQuotedLine(@"Language-Team: Language <email@address>\n", writer);
            POString.WriteQuotedLine(@"MIME-Version: 1.0\n", writer);
            POString.WriteQuotedLine(@"Content-Type: text/plain; charset=UTF-8\n", writer);
            POString.WriteQuotedLine(@"Content-Transfer-Encoding: 8bit\n", writer);
            if (string.IsNullOrEmpty(locale))
            {
                POString.WriteQuotedLine(@"X-Poedit-Language: \n", writer);
                POString.WriteQuotedLine(@"X-Poedit-Country: \n", writer);
            }
            else
            {
                var localeParts = locale.Split('-', '_');
                var ci          = new CultureInfo(localeParts[0]);
                var englishName = ci.EnglishName;
                var country     = string.Empty;
                var variant     = string.Empty;
                if (localeParts.Length > 1)
                {
                    var ri = new RegionInfo(localeParts[1]);
                    country = ri.EnglishName;
                }
                if (localeParts.Length > 2)
                {
                    ci      = new CultureInfo(locale);
                    variant = ci.EnglishName;
                    var idx = variant.IndexOf(englishName, StringComparison.Ordinal);
                    if (idx >= 0)
                    {
                        variant = variant.Remove(idx, englishName.Length);
                    }
                    idx = variant.IndexOf(country, StringComparison.Ordinal);
                    if (idx >= 0)
                    {
                        variant = variant.Remove(idx, country.Length);
                    }
                    variant = variant.Replace('(', ' ');
                    variant = variant.Replace(')', ' ');
                    variant = variant.Trim(',', ' ', '\t', '\n', '\r');
                }
                POString.WriteQuotedLine($@"X-Poedit-Language: {englishName}\n", writer);
                POString.WriteQuotedLine($@"X-Poedit-Country: {country}\n", writer);
                if (!string.IsNullOrEmpty(variant))
                {
                    POString.WriteQuotedLine($@"X-Poedit-Variant: {variant}\n", writer);
                }
            }
            writer.WriteLine("");
        }
Ejemplo n.º 9
0
        public static POString ReadFromFile(TextReader srIn)
        {
            // Move past any blank lines, checking for the end of file.
            var s = srIn.ReadLine();

            if (s == null)
            {
                return(null);
            }
            ++InputLineNumber;
            s = s.Trim();
            while (string.IsNullOrEmpty(s))
            {
                s = srIn.ReadLine();
                if (s == null)
                {
                    return(null);
                }
                ++InputLineNumber;
                s = s.Trim();
            }
            var pos     = new POString();
            var fMsgId  = false;
            var fMsgStr = false;
            var fError  = false;

            do
            {
                if (s == "#")
                {
                    pos.AddUserComment("");
                }
                else if (s.StartsWith("# "))
                {
                    if (pos.IsObsolete)
                    {
                        pos.UserComments.Add(s.Substring(1));
                    }
                    else
                    {
                        pos.AddUserComment(s.Substring(2));
                    }
                }
                else if (s.StartsWith("#."))
                {
                    if (pos.IsObsolete)
                    {
                        pos.UserComments.Add(s.Substring(1));
                    }
                    else
                    {
                        pos.AddAutoComment(s.Substring(2).TrimStart());
                    }
                }
                else if (s.StartsWith("#:"))
                {
                    if (pos.IsObsolete)
                    {
                        pos.UserComments.Add(s.Substring(1));
                    }
                    else
                    {
                        pos.AddReference(s.Substring(2).TrimStart());
                    }
                }
                else if (s.StartsWith("#,"))
                {
                    if (pos.IsObsolete)
                    {
                        pos.UserComments.Add(s.Substring(1));
                    }
                    else
                    {
                        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("#~"))
                {
                    if (!pos.IsObsolete)
                    {
                        if (pos.UserComments != null)
                        {
                            for (var i = 0; i < pos.UserComments.Count; ++i)
                            {
                                if (pos.UserComments[i] != null)
                                {
                                    pos.UserComments[i] = " " + pos.UserComments[i];
                                }
                            }
                        }

                        pos.AutoComments?.Clear();
                        pos.References?.Clear();
                        pos.Flags?.Clear();
                        pos.MsgId?.Clear();
                        pos.MsgStr?.Clear();
                        pos.IsObsolete = true;
                    }
                    pos.AddUserComment(s.Substring(1));
                }
                else if (string.IsNullOrEmpty(s))
                {
                    Console.WriteLine("Ignoring invalid empty line at line {0}", InputLineNumber);
                }
                else
                {
                    fError = true;
                }
                if (fError)
                {
                    Console.WriteLine("INVALID PO FILE: ERROR ON LINE " + InputLineNumber);
                    throw new Exception("BAD PO FILE");
                }
                s = srIn.ReadLine();
                if (s == null)
                {
                    break;
                }
                ++InputLineNumber;
                s = s.Trim();
            } while (!string.IsNullOrEmpty(s) || pos.MsgId == null || pos.MsgStr == null);
            // Multiline messages start with an empty line in PO files.  Remove it from our data.
            // (Otherwise we add an extra "\n" line on output.)
            if (pos.MsgId != null && pos.MsgId.Count > 1 && string.IsNullOrEmpty(pos.MsgId[0]))
            {
                pos.MsgId.RemoveAt(0);
            }
            if (pos.MsgStr != null && pos.MsgStr.Count > 1 && string.IsNullOrEmpty(pos.MsgStr[0]))
            {
                pos.MsgStr.RemoveAt(0);
            }
            return(pos);
        }