Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'main/po/StripMnemonics/POProcessor.cs')
-rw-r--r--main/po/StripMnemonics/POProcessor.cs266
1 files changed, 266 insertions, 0 deletions
diff --git a/main/po/StripMnemonics/POProcessor.cs b/main/po/StripMnemonics/POProcessor.cs
new file mode 100644
index 0000000000..172b2f41f2
--- /dev/null
+++ b/main/po/StripMnemonics/POProcessor.cs
@@ -0,0 +1,266 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace StripMnemonics
+{
+ public static class POProcessor
+ {
+ public static POFile Read (string poFile)
+ {
+ var po = new POFile {
+ FileName = poFile
+ };
+
+ using (var stream = File.OpenRead (poFile))
+ using (var reader = new StreamReader (stream)) {
+ string line = reader.ReadLine ();
+
+ // Read PO Copyright header.
+ while (line.StartsWith ("# ", StringComparison.Ordinal)) {
+ po.CopyrightHeader.Add (line);
+ line = reader.ReadLine ();
+ }
+
+ po.Header = ReadBlock (ref line, reader, po);
+ if (!po.NPluralsSet)
+ {
+ po.NPluralsSet = true;
+ po.NPlurals = 2;
+ }
+
+ while (!reader.EndOfStream) {
+ var block = ReadBlock (ref line, reader, po);
+ if (block != null)
+ po.Messages.Add (block);
+ }
+ }
+ return po;
+ }
+
+ static POBlock ReadBlock (ref string line, StreamReader reader, POFile po)
+ {
+ var map = new HashSet<string> {
+ { "# " },
+ { "#. " },
+ { "#: " },
+ { "#, " },
+ { "#| msgid " },
+ };
+
+ var block = new POBlock ();
+ bool init = false;
+
+ do {
+ foreach (var mapping in map) {
+ if (line.StartsWith (mapping, StringComparison.Ordinal)) {
+ block.Metadata.Add(line);
+ goto read_next;
+ }
+ }
+
+ string actual;
+ bool readNext;
+ if ((actual = ReadString(ref line, reader, "msgid ", out readNext, po)) != null)
+ {
+ block.Id = actual;
+ init = true;
+ if (!readNext)
+ continue;
+ }
+
+ if ((actual = ReadString(ref line, reader, "msgid_plural ", out readNext, po)) != null)
+ {
+ block.IdPlural = actual;
+ if (!readNext)
+ continue;
+ }
+
+ if ((actual = ReadString(ref line, reader, "msgstr ", out readNext, po)) != null)
+ {
+ block.TranslatedString = actual;
+ if (!readNext)
+ continue;
+ }
+
+ if ((actual = ReadString(ref line, reader, "msgstr[0] ", out readNext, po)) != null)
+ {
+ block.SetTranslatedPlural(0, actual);
+ if (!readNext)
+ continue;
+ }
+
+ if ((actual = ReadString(ref line, reader, "msgstr[1] ", out readNext, po)) != null)
+ {
+ block.SetTranslatedPlural(1, actual);
+ if (!readNext)
+ continue;
+ }
+
+ if ((actual = ReadString(ref line, reader, "msgstr[2] ", out readNext, po)) != null)
+ {
+ block.SetTranslatedPlural(2, actual);
+ if (!readNext)
+ continue;
+ }
+
+ read_next:
+ line = reader.ReadLine ();
+ } while (!string.IsNullOrEmpty (line));
+
+ if (init)
+ return block;
+ return null;
+ }
+
+ static string ReadString(ref string line, StreamReader reader, string header, out bool readNext, POFile po)
+ {
+ if (!line.StartsWith(header, StringComparison.Ordinal))
+ {
+ readNext = false;
+ return null;
+ }
+
+ var actual = line.Substring(header.Length);
+ actual = actual.Substring(Math.Min (1, actual.Length), Math.Max (actual.Length - 2, 0));
+ bool isMultiline = string.IsNullOrEmpty(actual);
+ if (!isMultiline)
+ {
+ readNext = true;
+ return actual;
+ }
+
+ var multiLineString = new List<string>();
+
+ line = reader.ReadLine();
+ while (!string.IsNullOrEmpty(line) && line.StartsWith("\"", StringComparison.Ordinal))
+ {
+ var leadingStripped = line.Remove(0, 1);
+ var stripped = leadingStripped.Remove(leadingStripped.Length - 1, 1);
+ multiLineString.Add(stripped);
+
+ // Parse number of plural forms to write for each string.
+ if (line.StartsWith("\"Plural-Forms:", StringComparison.Ordinal))
+ {
+ var rest = line.Substring("\"Plural-Forms: ".Length).TrimEnd('\"').Split (';');
+ int plurals;
+ if (int.TryParse(rest[0].Trim().Substring("nplurals=".Length), out plurals))
+ po.NPlurals = plurals;
+ po.NPluralsSet = true;
+ }
+ line = reader.ReadLine();
+ }
+ readNext = false;
+ return string.Concat (multiLineString);
+ }
+
+
+ public static void Write(POFile po, string outPath)
+ {
+ using (var stream = File.Open(outPath, FileMode.Create))
+ using (var writer = new StreamWriter(stream))
+ {
+ foreach (var line in po.CopyrightHeader)
+ writer.WriteLine(line);
+
+ writer.WriteLine("msgid \"\"");
+ writer.WriteLine("msgstr \"\"");
+ foreach (var line in po.Header.TranslatedString.Split(new string[] { "\\n" }, StringSplitOptions.RemoveEmptyEntries))
+ writer.WriteLine($"\"{line}\\n\"");
+
+ writer.WriteLine();
+ bool isMessages = po.FileName.EndsWith("messages.po", StringComparison.OrdinalIgnoreCase);
+ foreach (var block in po.Messages)
+ {
+ WriteBlock(block, writer, po, isMessages);
+ writer.WriteLine();
+ }
+ }
+ }
+
+ static IEnumerable<string> LineWrap(string text, string kind)
+ {
+ // Gettext wraps at 80 chars, including quotes.
+ // Also breaks on \n.
+
+ // Take into account kind, quotes and space.
+ if (text.Length + kind.Length + 3 > 80 || text.Contains("\\n"))
+ yield return kind + " \"\"";
+ else
+ {
+ yield return kind + $" \"{text}\"";
+ yield break;
+ }
+
+ var words = text.Split(new char[] { ' ' });
+ var sb = new StringBuilder();
+
+ for (int i = 0; i < words.Length; ++i)
+ {
+ // Add the space into account.
+ if (sb.Length + words[i].Length + 3 > 79)
+ {
+ yield return $"\"{sb.ToString()}\"";
+ sb.Clear();
+ }
+
+ if (words[i].Contains("\\n"))
+ {
+ var split = words[i].Split(new string[] { "\\n" }, StringSplitOptions.None);
+ for (int splitIndex = 0; splitIndex < split.Length - 1; ++splitIndex)
+ {
+ sb.Append(split[splitIndex]);
+ sb.Append("\\n");
+ yield return $"\"{sb.ToString()}\"";
+ sb.Clear();
+ }
+ sb.Append(split[split.Length - 1]);
+ }
+ else
+ {
+ sb.Append(words[i]);
+ }
+
+ if (i != words.Length - 1)
+ sb.Append(' ');
+ }
+ if (sb.Length > 0)
+ yield return $"\"{sb.ToString()}\"";
+ yield break;
+ }
+
+ static void WriteBlock(POBlock block, StreamWriter writer, POFile po, bool isMessages)
+ {
+ foreach (var item in block.Metadata)
+ writer.WriteLine(item);
+
+ foreach (var line in LineWrap(block.Id.Replace("\r\n", "\n"), "msgid"))
+ writer.WriteLine(line);
+
+ if (block.IdPlural != null)
+ {
+ foreach (var line in LineWrap(block.IdPlural.Replace("\r\n", "\n"), "msgid_plural"))
+ writer.WriteLine(line);
+
+ for (int i = 0; i < po.NPlurals; ++i)
+ {
+ var translatedPlural = block.GetTranslatedPlural(i);
+ if (translatedPlural == null)
+ continue;
+
+ string value = isMessages ? "" : translatedPlural.Replace("\r\n", "\n");
+ foreach (var line in LineWrap(value, $"msgstr[{i}]"))
+ writer.WriteLine(line);
+ }
+ }
+ else
+ {
+ string value = isMessages ? "" : block.TranslatedString.Replace("\r\n", "\n");
+ foreach (var line in LineWrap(value, "msgstr"))
+ writer.WriteLine(line);
+ }
+ }
+ }
+}
+