]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Support for C# in msgunfmt.
authorBruno Haible <bruno@clisp.org>
Thu, 8 Jan 2004 11:48:40 +0000 (11:48 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:11:35 +0000 (12:11 +0200)
gettext-tools/src/msgunfmt.cs [new file with mode: 0644]

diff --git a/gettext-tools/src/msgunfmt.cs b/gettext-tools/src/msgunfmt.cs
new file mode 100644 (file)
index 0000000..348ce22
--- /dev/null
@@ -0,0 +1,191 @@
+/* GNU gettext for C#
+ * Copyright (C) 2003-2004 Free Software Foundation, Inc.
+ * Written by Bruno Haible <bruno@clisp.org>, 2003.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This program dumps a GettextResourceSet subclass (in a satellite assembly)
+ * as a PO file.
+ */
+
+using System; /* Object, String, Type, Console, Exception */
+using System.Reflection; /* Assembly, MethodInfo, ConstructorInfo */
+using System.Collections; /* Hashtable */
+using System.IO; /* BufferedStream, StreamWriter, TextWriter, FileNotFoundException, Path */
+using System.Text; /* StringBuilder, UTF8Encoding */
+using GNU.Gettext; /* GettextResourceSet */
+
+namespace GNU.Gettext {
+  public class DumpResource {
+    private TextWriter Out;
+    private void DumpString (String str) {
+      int n = str.Length;
+      Out.Write('"');
+      for (int i = 0; i < n; i++) {
+        char c = str[i];
+        if (c == 0x0008) {
+          Out.Write('\\'); Out.Write('b');
+        } else if (c == 0x000c) {
+          Out.Write('\\'); Out.Write('f');
+        } else if (c == 0x000a) {
+          Out.Write('\\'); Out.Write('n');
+        } else if (c == 0x000d) {
+          Out.Write('\\'); Out.Write('r');
+        } else if (c == 0x0009) {
+          Out.Write('\\'); Out.Write('t');
+        } else if (c == '\\' || c == '"') {
+          Out.Write('\\'); Out.Write(c);
+        } else
+          Out.Write(c);
+      }
+      Out.Write('"');
+    }
+    private void DumpMessage (String msgid, String msgid_plural, Object msgstr) {
+      Out.Write("msgid "); DumpString(msgid); Out.Write('\n');
+      if (msgid_plural != null) {
+        Out.Write("msgid_plural "); DumpString(msgid_plural); Out.Write('\n');
+        for (int i = 0; i < (msgstr as String[]).Length; i++) {
+          Out.Write("msgstr[" + i + "] ");
+          DumpString((msgstr as String[])[i]);
+          Out.Write('\n');
+        }
+      } else {
+        Out.Write("msgstr "); DumpString(msgstr as String); Out.Write('\n');
+      }
+      Out.Write('\n');
+    }
+    private void Dump (GettextResourceSet catalog) {
+      MethodInfo pluralMethod =
+        catalog.GetType().GetMethod("GetMsgidPluralTable", Type.EmptyTypes);
+      // Search for the header entry.
+      {
+        Object header_entry = catalog.GetObject("");
+        // If there is no header entry, fake one.
+        // FIXME: This is not needed; right after po_lex_charset_init set
+        // the PO charset to UTF-8.
+        if (header_entry == null)
+          header_entry = "Content-Type: text/plain; charset=UTF-8\n";
+        DumpMessage("", null, header_entry);
+      }
+      // Now the other messages.
+      {
+        Hashtable plural = null;
+        if (pluralMethod != null)
+          plural = pluralMethod.Invoke(catalog, new Object[0]) as Hashtable;
+        foreach (String key in catalog.Keys)
+          if (!"".Equals(key)) {
+            Object value = catalog.GetObject(key);
+            String key_plural =
+              (plural != null && value is String[] ? plural[key] as String : null);
+            DumpMessage(key, key_plural, value);
+          }
+      }
+    }
+    // Essentially taken from class GettextResourceManager.
+    private static Assembly GetSatelliteAssembly (String baseDirectory, String resourceName, String cultureName) {
+      String satelliteExpectedLocation =
+        baseDirectory
+        + Path.DirectorySeparatorChar + cultureName
+        + Path.DirectorySeparatorChar + resourceName + ".resources.dll";
+      return Assembly.LoadFrom(satelliteExpectedLocation);
+    }
+    // Taken from class GettextResourceManager.
+    private static String ConstructClassName (String resourceName) {
+      // We could just return an arbitrary fixed class name, like "Messages",
+      // assuming that every assembly will only ever contain one
+      // GettextResourceSet subclass, but this assumption would break the day
+      // we want to support multi-domain PO files in the same format...
+      bool valid = (resourceName.Length > 0);
+      for (int i = 0; valid && i < resourceName.Length; i++) {
+        char c = resourceName[i];
+        if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_')
+              || (i > 0 && c >= '0' && c <= '9')))
+          valid = false;
+      }
+      if (valid)
+        return resourceName;
+      else {
+        // Use hexadecimal escapes, using the underscore as escape character.
+        String hexdigit = "0123456789abcdef";
+        StringBuilder b = new StringBuilder();
+        b.Append("__UESCAPED__");
+        for (int i = 0; i < resourceName.Length; i++) {
+          char c = resourceName[i];
+          if (c >= 0xd800 && c < 0xdc00
+              && i+1 < resourceName.Length
+              && resourceName[i+1] >= 0xdc00 && resourceName[i+1] < 0xe000) {
+            // Combine two UTF-16 words to a character.
+            char c2 = resourceName[i+1];
+            int uc = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
+            b.Append('_');
+            b.Append('U');
+            b.Append(hexdigit[(uc >> 28) & 0x0f]);
+            b.Append(hexdigit[(uc >> 24) & 0x0f]);
+            b.Append(hexdigit[(uc >> 20) & 0x0f]);
+            b.Append(hexdigit[(uc >> 16) & 0x0f]);
+            b.Append(hexdigit[(uc >> 12) & 0x0f]);
+            b.Append(hexdigit[(uc >> 8) & 0x0f]);
+            b.Append(hexdigit[(uc >> 4) & 0x0f]);
+            b.Append(hexdigit[uc & 0x0f]);
+            i++;
+          } else if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
+                       || (c >= '0' && c <= '9'))) {
+            int uc = c;
+            b.Append('_');
+            b.Append('u');
+            b.Append(hexdigit[(uc >> 12) & 0x0f]);
+            b.Append(hexdigit[(uc >> 8) & 0x0f]);
+            b.Append(hexdigit[(uc >> 4) & 0x0f]);
+            b.Append(hexdigit[uc & 0x0f]);
+          } else
+            b.Append(c);
+        }
+        return b.ToString();
+      }
+    }
+    // Essentially taken from class GettextResourceManager.
+    private static GettextResourceSet InstantiateResourceSet (Assembly satelliteAssembly, String resourceName, String cultureName) {
+      Type clazz = satelliteAssembly.GetType(ConstructClassName(resourceName)+"_"+cultureName.Replace('-','_'));
+      ConstructorInfo constructor = clazz.GetConstructor(Type.EmptyTypes);
+      return constructor.Invoke(null) as GettextResourceSet;
+    }
+    public DumpResource (String baseDirectory, String resourceName, String cultureName) {
+      // We are only interested in the messages belonging to the locale
+      // itself, not in the inherited messages. Therefore we instantiate just
+      // the GettextResourceSet, not a GettextResourceManager.
+      Assembly satelliteAssembly =
+        GetSatelliteAssembly(baseDirectory, resourceName, cultureName);
+      GettextResourceSet catalog =
+        InstantiateResourceSet(satelliteAssembly, resourceName, cultureName);
+      BufferedStream stream = new BufferedStream(Console.OpenStandardOutput());
+      Out = new StreamWriter(stream, new UTF8Encoding());
+      Dump(catalog);
+      Out.Close();
+      stream.Close();
+    }
+    public static int Main (String[] args) {
+      try {
+        new DumpResource(args[0], args[1], args[2]);
+      } catch (Exception e) {
+        Console.Error.WriteLine(e);
+        Console.Error.WriteLine(e.StackTrace);
+        return 1;
+      }
+      return 0;
+    }
+  }
+}