Beispiel #1
0
        // Initializes the headers from string that is in msgid "" format (i.e. list of key:value\n entries).
        public void ParseHeaderString(string headers)
        {
            string hdr = StringEscaping.FromGettextFormat(headers);

            string[] tokens = hdr.Split('\n');
            headerEntries.Clear();

            foreach (string token in tokens)
            {
                if (token != String.Empty)
                {
                    int pos = token.IndexOf(':');
                    if (pos == -1)
                    {
                        throw new Exception(String.Format("Malformed header: '{0}'", token));
                    }
                    else
                    {
                        string key   = token.Substring(0, pos).Trim();
                        string value = token.Substring(pos + 1).Trim();
                        headerEntries[key] = value;
                    }
                }
            }
            ParseHeaderDict();
        }
		public void AddIncludeRegex (string regex, int valueGroupIndex, int pluralGroupIndex, string regexOptions, StringEscaping.EscapeMode escapeMode)
		{
			Regex rx = new Regex (regex, ParseOptions (regexOptions));
			RegexInfo ri = new RegexInfo ();
			ri.Regex = rx;
			ri.ValueGroupIndex = valueGroupIndex;
			ri.PluralGroupIndex = pluralGroupIndex;
			ri.EscapeMode = escapeMode;
			regexes.Add (ri);
		}
Beispiel #3
0
        // Converts the header into string representation that can be directly written to .po file as msgid ""
        public string GetHeaderString(string lineDelimeter)
        {
            UpdateHeaderDict();
            StringBuilder sb = new StringBuilder();

            foreach (string key in headerEntries.Keys)
            {
                string value = String.Empty;
                if (headerEntries[key] != null)
                {
                    value = StringEscaping.ToGettextFormat(headerEntries[key]);
                }
                sb.AppendFormat("\"{0}: {1}\\n\"{2}", key, value, lineDelimeter);
            }
            return(sb.ToString());
        }
Beispiel #4
0
        // If input begins with pattern, fill output with end of input (without
        // pattern; strips trailing spaces) and return true.  Return false otherwise
        // and don't touch output
        static bool ReadParam(string input, string pattern, out string output)
        {
            output = String.Empty;
            input  = input.TrimStart(' ', '\t');
            if (input.Length < pattern.Length)
            {
                return(false);
            }

            if (!input.StartsWith(pattern))
            {
                return(false);
            }

            output = StringEscaping.FromGettextFormat(input.Substring(pattern.Length).TrimEnd(' ', '\t'));
            return(true);
        }
Beispiel #5
0
        // returns value in dummy plus any trailing lines in sr enclosed in quotes
        // next line is ready for parsing by function end
        string ParseMessage(ref string line, ref string dummy, StreamReader sr)
        {
            StringBuilder result = new StringBuilder(dummy.Substring(0, dummy.Length - 1));

            while (!String.IsNullOrEmpty(line = sr.ReadLine()))
            {
                if (line[0] == '\t')
                {
                    line = line.Substring(1);
                }

                if (line[0] == '"' && line[line.Length - 1] == '"')
                {
                    result.Append(StringEscaping.FromGettextFormat(line.Substring(1, line.Length - 2)));
                }
                else
                {
                    break;
                }
            }
            return(result.ToString());
        }
Beispiel #6
0
        string ParseMessage(ref string line, ref string dummy, ref int lineNumber)
        {
            StringBuilder result = new StringBuilder(dummy.Substring(0, dummy.Length - 1));

            while ((line = fileLines[lineNumber++]) != String.Empty)
            {
                if (line[0] == '\t')
                {
                    line = line.Substring(1);
                }

                if (line[0] == '"' && line[line.Length - 1] == '"')
                {
                    result.Append(StringEscaping.FromGettextFormat(line.Substring(1, line.Length - 2)));
                }
                else
                {
                    break;
                }
            }
            return(result.ToString());
        }
Beispiel #7
0
        public virtual void UpdateCatalog(TranslationProject project, Catalog catalog, ProgressMonitor monitor, string fileName)
        {
            string text             = File.ReadAllText(fileName);
            string relativeFileName = MonoDevelop.Core.FileService.AbsoluteToRelativePath(project.BaseDirectory, fileName);
            string fileNamePrefix   = relativeFileName + ":";

            if (String.IsNullOrEmpty(text))
            {
                return;
            }

            // Get a list of all excluded regions
            List <Match> excludeMatches = new List <Match> ();

            foreach (Regex regex in excluded)
            {
                foreach (Match m in regex.Matches(text))
                {
                    excludeMatches.Add(m);
                }
            }

            // Sort the list by match index
            excludeMatches.Sort(delegate(Match a, Match b) {
                return(a.Index.CompareTo(b.Index));
            });

            // Remove from the list all regions which start in an excluded region
            int pos = 0;

            for (int n = 0; n < excludeMatches.Count; n++)
            {
                Match m = excludeMatches [n];
                if (m.Index < pos)
                {
                    excludeMatches.RemoveAt(n);
                    n--;
                }
                else
                {
                    pos = m.Index + m.Length;
                }
            }

            foreach (RegexInfo ri in regexes)
            {
                int lineNumber = 0;
                int oldIndex   = 0;
                foreach (Match match in ri.Regex.Matches(text))
                {
                    // Ignore matches inside excluded regions
                    bool ignore = false;
                    foreach (Match em in excludeMatches)
                    {
                        if (match.Index >= em.Index && match.Index < em.Index + em.Length)
                        {
                            ignore = true;
                            LoggingService.LogDebug("Excluded Gettext string '{0}' in file '{1}'", match.Groups[ri.ValueGroupIndex].Value, fileName);
                            break;
                        }
                    }
                    if (ignore)
                    {
                        continue;
                    }

                    string mt = match.Groups[ri.ValueGroupIndex].Value;
                    if (mt.Length == 0)
                    {
                        continue;
                    }

                    foreach (TransformInfo ti in transforms)
                    {
                        mt = ti.Regex.Replace(mt, ti.ReplaceText);
                    }

                    try {
                        mt = StringEscaping.UnEscape(ri.EscapeMode, mt);
                    } catch (FormatException fex) {
                        monitor.ReportWarning("Error unescaping string '" + mt + "': " + fex.Message);
                        continue;
                    }

                    if (mt.Trim().Length == 0)
                    {
                        continue;
                    }

                    //get the plural string if it's a plural form and apply transforms
                    string pt = ri.PluralGroupIndex != -1 ? match.Groups[ri.PluralGroupIndex].Value : null;
                    if (pt != null)
                    {
                        foreach (TransformInfo ti in transforms)
                        {
                            pt = ti.Regex.Replace(pt, ti.ReplaceText);
                        }
                    }

                    //add to the catalog
                    CatalogEntry entry = catalog.AddItem(mt, pt);
                    lineNumber += GetLineCount(text, oldIndex, match.Index);
                    oldIndex    = match.Index;
                    entry.AddReference(fileNamePrefix + lineNumber);
                }
            }
        }
		public void AddIncludeRegex (string regex, int valueGroupIndex, string regexOptions, StringEscaping.EscapeMode escapeMode)
		{
			AddIncludeRegex (regex, valueGroupIndex, -1, regexOptions, escapeMode);
		}
Beispiel #9
0
        //escapes string and lays it out to 80 cols
        static void FormatMessageForFile(StringBuilder sb, string prefix, string message, string newlineChar)
        {
            string escaped = StringEscaping.ToGettextFormat(message);

            //format to 80 cols
            //first the simple case: does it fit one one line, with the prefix, and contain no newlines?
            if (prefix.Length + escaped.Length < 77 && !escaped.Contains("\\n"))
            {
                sb.Append(prefix);
                sb.Append(" \"");
                sb.Append(escaped);
                sb.Append("\"");
                sb.Append(newlineChar);
                return;
            }

            //not the simple case.

            // first line is typically: prefix ""
            sb.Append(prefix);
            sb.Append(" \"\"");
            sb.Append(newlineChar);

            //followed by 80-col width break on spaces
            int  possibleBreak = -1;
            int  currLineLen   = 0;
            int  lastBreakAt   = 0;
            bool forceBreak    = false;

            int pos = 0;

            while (pos < escaped.Length)
            {
                char c = escaped[pos];

                //handle escapes
                if (c == '\\' && pos + 1 < escaped.Length)
                {
                    pos++;
                    currLineLen++;

                    char c2 = escaped[pos];
                    if (c2 == 'n')
                    {
                        possibleBreak = pos + 1;
                        forceBreak    = true;
                    }
                    else if (c2 == 't')
                    {
                        possibleBreak = pos + 1;
                    }
                }

                if (c == ' ')
                {
                    possibleBreak = pos + 1;
                }

                if (forceBreak || (currLineLen >= 77 && possibleBreak != -1))
                {
                    sb.Append("\"");
                    sb.Append(escaped.Substring(lastBreakAt, possibleBreak - lastBreakAt));
                    sb.Append("\"");
                    sb.Append(newlineChar);

                    //reset state for new line
                    currLineLen   = 0;
                    lastBreakAt   = possibleBreak;
                    possibleBreak = -1;
                    forceBreak    = false;
                }
                pos++;
                currLineLen++;
            }
            string remainder = escaped.Substring(lastBreakAt);

            if (remainder.Length > 0)
            {
                sb.Append("\"");
                sb.Append(remainder);
                sb.Append("\"");
                sb.Append(newlineChar);
            }
            return;
        }
Beispiel #10
0
        // Parses the entire file, calls OnEntry each time msgid/msgstr pair is found.
        // return false if parsing failed, true otherwise
        public bool Parse()
        {
            string        line, dummy;
            string        mflags        = String.Empty;
            string        mstr          = String.Empty;
            string        msgidPlural   = String.Empty;
            string        mcomment      = String.Empty;
            List <string> mrefs         = new List <string> ();
            List <string> mautocomments = new List <string> ();
            List <string> mtranslations = new List <string> ();
            bool          hasPlural     = false;

            using (StreamReader sr = new StreamReader(fileName, encoding))
            {
                line = sr.ReadLine();

                while (line == "")
                {
                    line = sr.ReadLine();
                }

                if (line == null)
                {
                    return(false);
                }

                while (line != null)
                {
                    // ignore empty special tags (except for automatic comments which we
                    // DO want to preserve):
                    while (line == "#," || line == "#:")
                    {
                        line = sr.ReadLine();
                    }

                    // flags:
                    // Can't we have more than one flag, now only the last is kept ...
                    if (CatalogParser.ReadParam(line, "#, ", out dummy))
                    {
                        mflags = dummy;                         //"#, " +
                        line   = sr.ReadLine();
                    }

                    // auto comments:
                    if (CatalogParser.ReadParam(line, "#. ", out dummy) || CatalogParser.ReadParam(line, "#.", out dummy))                       // second one to account for empty auto comments
                    {
                        mautocomments.Add(dummy);
                        line = sr.ReadLine();
                    }

                    // references:
                    else if (CatalogParser.ReadParam(line, "#: ", out dummy))
                    {
                        // A line may contain several references, separated by white-space.
                        // Each reference is in the form "path_name:line_number"
                        // (path_name may contain spaces)
                        dummy = dummy.Trim();
                        while (dummy != String.Empty)
                        {
                            int i = 0;
                            while (i < dummy.Length && dummy[i] != ':')
                            {
                                i++;
                            }
                            while (i < dummy.Length && !Char.IsWhiteSpace(dummy[i]))
                            {
                                i++;
                            }

                            //store paths as Unix-type paths, but internally use native style
                            string refpath = dummy.Substring(0, i);
                            if (MonoDevelop.Core.Platform.IsWindows)
                            {
                                refpath = refpath.Replace('/', '\\');
                            }

                            mrefs.Add(refpath);
                            dummy = dummy.Substring(i).Trim();
                        }

                        line = sr.ReadLine();
                    }

                    // msgid:
                    else if (CatalogParser.ReadParam(line, "msgid \"", out dummy) ||
                             CatalogParser.ReadParam(line, "msgid\t\"", out dummy))
                    {
                        mstr = ParseMessage(ref line, ref dummy, sr);
                    }

                    // msgid_plural:
                    else if (CatalogParser.ReadParam(line, "msgid_plural \"", out dummy) ||
                             CatalogParser.ReadParam(line, "msgid_plural\t\"", out dummy))
                    {
                        msgidPlural = ParseMessage(ref line, ref dummy, sr);
                        hasPlural   = true;
                    }

                    // msgstr:
                    else if (CatalogParser.ReadParam(line, "msgstr \"", out dummy) ||
                             CatalogParser.ReadParam(line, "msgstr\t\"", out dummy))
                    {
                        if (hasPlural)
                        {
                            // TODO: use logging
                            Console.WriteLine("Broken catalog file: singular form msgstr used together with msgid_plural");
                            return(false);
                        }

                        string str = ParseMessage(ref line, ref dummy, sr);
                        mtranslations.Add(str);

                        if (!OnEntry(mstr, String.Empty, false, mtranslations.ToArray(),
                                     mflags, mrefs.ToArray(), mcomment,
                                     mautocomments.ToArray()))
                        {
                            return(false);
                        }

                        mcomment  = mstr = msgidPlural = mflags = String.Empty;
                        hasPlural = false;
                        mrefs.Clear();
                        mautocomments.Clear();
                        mtranslations.Clear();
                    }
                    else if (CatalogParser.ReadParam(line, "msgstr[", out dummy))
                    {
                        // msgstr[i]:
                        if (!hasPlural)
                        {
                            // TODO: use logging
                            Console.WriteLine("Broken catalog file: plural form msgstr used without msgid_plural");
                            return(false);
                        }

                        int    pos   = dummy.IndexOf(']');
                        string idx   = dummy.Substring(pos - 1, 1);
                        string label = "msgstr[" + idx + "]";

                        while (CatalogParser.ReadParam(line, label + " \"", out dummy) || CatalogParser.ReadParam(line, label + "\t\"", out dummy))
                        {
                            StringBuilder str = new StringBuilder(dummy.Substring(0, dummy.Length - 1));

                            while (!String.IsNullOrEmpty(line = sr.ReadLine()))
                            {
                                if (line[0] == '\t')
                                {
                                    line = line.Substring(1);
                                }
                                if (line[0] == '"' && line[line.Length - 1] == '"')
                                {
                                    str.Append(line, 1, line.Length - 2);
                                }
                                else
                                {
                                    if (ReadParam(line, "msgstr[", out dummy))
                                    {
                                        pos   = dummy.IndexOf(']');
                                        idx   = dummy.Substring(pos - 1, 1);
                                        label = "msgstr[" + idx + "]";
                                    }
                                    break;
                                }
                            }
                            mtranslations.Add(StringEscaping.FromGettextFormat(str.ToString()));
                        }

                        if (!OnEntry(mstr, msgidPlural, true, mtranslations.ToArray(),
                                     mflags, mrefs.ToArray(), mcomment,
                                     mautocomments.ToArray()))
                        {
                            return(false);
                        }

                        mcomment  = mstr = msgidPlural = mflags = String.Empty;
                        hasPlural = false;
                        mrefs.Clear();
                        mautocomments.Clear();
                        mtranslations.Clear();
                    }
                    else if (CatalogParser.ReadParam(line, "#~ ", out dummy))
                    {
                        // deleted lines:

                        List <string> deletedLines = new List <string> ();
                        deletedLines.Add(line);
                        while (!String.IsNullOrEmpty(line = sr.ReadLine()))
                        {
                            // if line does not start with "#~ " anymore, stop reading
                            if (!ReadParam(line, "#~ ", out dummy))
                            {
                                break;
                            }

                            deletedLines.Add(line);
                        }
                        if (!OnDeletedEntry(deletedLines.ToArray(), mflags, null, mcomment, mautocomments.ToArray()))
                        {
                            return(false);
                        }

                        mcomment  = mstr = msgidPlural = mflags = String.Empty;
                        hasPlural = false;
                        mrefs.Clear();
                        mautocomments.Clear();
                        mtranslations.Clear();
                    }
                    else if (line != null && line[0] == '#')
                    {
                        // comment:

                        //  added line[1] != '~' check as deleted lines where being wrongly detected as comments
                        while (!String.IsNullOrEmpty(line) &&
                               ((line[0] == '#' && line.Length < 2) ||
                                (line[0] == '#' && line[1] != ',' && line[1] != ':' && line[1] != '.' && line[1] != '~')))
                        {
                            mcomment += mcomment.Length > 0 ? '\n' + line : line;
                            line      = sr.ReadLine();
                        }
                    }
                    else
                    {
                        line = sr.ReadLine();
                    }

                    while (line == String.Empty)
                    {
                        line = sr.ReadLine();
                    }
                }
            }
            return(true);
        }