• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/gettext-0.17/gettext-tools/src/
1/* GNU gettext for C#
2 * Copyright (C) 2003-2004, 2007 Free Software Foundation, Inc.
3 * Written by Bruno Haible <bruno@clisp.org>, 2003.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/*
20 * This program dumps a GettextResourceSet subclass (in a satellite assembly)
21 * or a .resources file as a PO file.
22 */
23
24using System; /* Object, String, Type, Console, Exception */
25using System.Reflection; /* Assembly, MethodInfo, ConstructorInfo */
26using System.Collections; /* Hashtable, DictionaryEntry */
27using System.IO; /* BufferedStream, StreamWriter, TextWriter, FileNotFoundException, Path */
28using System.Text; /* StringBuilder, UTF8Encoding */
29using System.Resources; /* ResourceReader */
30using GNU.Gettext; /* GettextResourceSet */
31
32namespace GNU.Gettext {
33  public class DumpResource {
34    private TextWriter Out;
35    private void DumpString (String str) {
36      int n = str.Length;
37      Out.Write('"');
38      for (int i = 0; i < n; i++) {
39        char c = str[i];
40        if (c == 0x0008) {
41          Out.Write('\\'); Out.Write('b');
42        } else if (c == 0x000c) {
43          Out.Write('\\'); Out.Write('f');
44        } else if (c == 0x000a) {
45          Out.Write('\\'); Out.Write('n');
46        } else if (c == 0x000d) {
47          Out.Write('\\'); Out.Write('r');
48        } else if (c == 0x0009) {
49          Out.Write('\\'); Out.Write('t');
50        } else if (c == '\\' || c == '"') {
51          Out.Write('\\'); Out.Write(c);
52        } else
53          Out.Write(c);
54      }
55      Out.Write('"');
56    }
57    private void DumpMessage (String msgid, String msgid_plural, Object msgstr) {
58      int separatorPos = msgid.IndexOf('\u0004');
59      if (separatorPos >= 0) {
60        String msgctxt = msgid.Substring(0,separatorPos);
61        msgid = msgid.Substring(separatorPos+1);
62        Out.Write("msgctxt "); DumpString(msgctxt);
63      }
64      Out.Write("msgid "); DumpString(msgid); Out.Write('\n');
65      if (msgid_plural != null) {
66        Out.Write("msgid_plural "); DumpString(msgid_plural); Out.Write('\n');
67        for (int i = 0; i < (msgstr as String[]).Length; i++) {
68          Out.Write("msgstr[" + i + "] ");
69          DumpString((msgstr as String[])[i]);
70          Out.Write('\n');
71        }
72      } else {
73        Out.Write("msgstr "); DumpString(msgstr as String); Out.Write('\n');
74      }
75      Out.Write('\n');
76    }
77
78    // ---------------- Dumping a GettextResourceSet ----------------
79
80    private void Dump (GettextResourceSet catalog) {
81      MethodInfo pluralMethod =
82        catalog.GetType().GetMethod("GetMsgidPluralTable", Type.EmptyTypes);
83      // Search for the header entry.
84      {
85        Object header_entry = catalog.GetObject("");
86        // If there is no header entry, fake one.
87        // FIXME: This is not needed; right after po_lex_charset_init set
88        // the PO charset to UTF-8.
89        if (header_entry == null)
90          header_entry = "Content-Type: text/plain; charset=UTF-8\n";
91        DumpMessage("", null, header_entry);
92      }
93      // Now the other messages.
94      {
95        Hashtable plural = null;
96        if (pluralMethod != null)
97          plural = pluralMethod.Invoke(catalog, new Object[0]) as Hashtable;
98        foreach (String key in catalog.Keys)
99          if (!"".Equals(key)) {
100            Object value = catalog.GetObject(key);
101            String key_plural =
102              (plural != null && value is String[] ? plural[key] as String : null);
103            DumpMessage(key, key_plural, value);
104          }
105      }
106    }
107    // Essentially taken from class GettextResourceManager.
108    private static Assembly GetSatelliteAssembly (String baseDirectory, String resourceName, String cultureName) {
109      String satelliteExpectedLocation =
110        baseDirectory
111        + Path.DirectorySeparatorChar + cultureName
112        + Path.DirectorySeparatorChar + resourceName + ".resources.dll";
113      return Assembly.LoadFrom(satelliteExpectedLocation);
114    }
115    // Taken from class GettextResourceManager.
116    private static String ConstructClassName (String resourceName) {
117      // We could just return an arbitrary fixed class name, like "Messages",
118      // assuming that every assembly will only ever contain one
119      // GettextResourceSet subclass, but this assumption would break the day
120      // we want to support multi-domain PO files in the same format...
121      bool valid = (resourceName.Length > 0);
122      for (int i = 0; valid && i < resourceName.Length; i++) {
123        char c = resourceName[i];
124        if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_')
125              || (i > 0 && c >= '0' && c <= '9')))
126          valid = false;
127      }
128      if (valid)
129        return resourceName;
130      else {
131        // Use hexadecimal escapes, using the underscore as escape character.
132        String hexdigit = "0123456789abcdef";
133        StringBuilder b = new StringBuilder();
134        b.Append("__UESCAPED__");
135        for (int i = 0; i < resourceName.Length; i++) {
136          char c = resourceName[i];
137          if (c >= 0xd800 && c < 0xdc00
138              && i+1 < resourceName.Length
139              && resourceName[i+1] >= 0xdc00 && resourceName[i+1] < 0xe000) {
140            // Combine two UTF-16 words to a character.
141            char c2 = resourceName[i+1];
142            int uc = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
143            b.Append('_');
144            b.Append('U');
145            b.Append(hexdigit[(uc >> 28) & 0x0f]);
146            b.Append(hexdigit[(uc >> 24) & 0x0f]);
147            b.Append(hexdigit[(uc >> 20) & 0x0f]);
148            b.Append(hexdigit[(uc >> 16) & 0x0f]);
149            b.Append(hexdigit[(uc >> 12) & 0x0f]);
150            b.Append(hexdigit[(uc >> 8) & 0x0f]);
151            b.Append(hexdigit[(uc >> 4) & 0x0f]);
152            b.Append(hexdigit[uc & 0x0f]);
153            i++;
154          } else if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
155                       || (c >= '0' && c <= '9'))) {
156            int uc = c;
157            b.Append('_');
158            b.Append('u');
159            b.Append(hexdigit[(uc >> 12) & 0x0f]);
160            b.Append(hexdigit[(uc >> 8) & 0x0f]);
161            b.Append(hexdigit[(uc >> 4) & 0x0f]);
162            b.Append(hexdigit[uc & 0x0f]);
163          } else
164            b.Append(c);
165        }
166        return b.ToString();
167      }
168    }
169    // Essentially taken from class GettextResourceManager.
170    private static GettextResourceSet InstantiateResourceSet (Assembly satelliteAssembly, String resourceName, String cultureName) {
171      Type clazz = satelliteAssembly.GetType(ConstructClassName(resourceName)+"_"+cultureName.Replace('-','_'));
172      ConstructorInfo constructor = clazz.GetConstructor(Type.EmptyTypes);
173      return constructor.Invoke(null) as GettextResourceSet;
174    }
175    public DumpResource (String baseDirectory, String resourceName, String cultureName) {
176      // We are only interested in the messages belonging to the locale
177      // itself, not in the inherited messages. Therefore we instantiate just
178      // the GettextResourceSet, not a GettextResourceManager.
179      Assembly satelliteAssembly =
180        GetSatelliteAssembly(baseDirectory, resourceName, cultureName);
181      GettextResourceSet catalog =
182        InstantiateResourceSet(satelliteAssembly, resourceName, cultureName);
183      BufferedStream stream = new BufferedStream(Console.OpenStandardOutput());
184      Out = new StreamWriter(stream, new UTF8Encoding());
185      Dump(catalog);
186      Out.Close();
187      stream.Close();
188    }
189
190    // ----------------- Dumping a .resources file ------------------
191
192    public DumpResource (String filename) {
193      BufferedStream stream = new BufferedStream(Console.OpenStandardOutput());
194      Out = new StreamWriter(stream, new UTF8Encoding());
195      ResourceReader rr;
196      if (filename.Equals("-")) {
197        BufferedStream input = new BufferedStream(Console.OpenStandardInput());
198        // A temporary output stream is needed because ResourceReader expects
199        // to be able to seek in the Stream.
200        byte[] contents;
201        {
202          MemoryStream tmpstream = new MemoryStream();
203          byte[] buf = new byte[1024];
204          for (;;) {
205            int n = input.Read(buf, 0, 1024);
206            if (n == 0)
207              break;
208            tmpstream.Write(buf, 0, n);
209          }
210          contents = tmpstream.ToArray();
211          tmpstream.Close();
212        }
213        MemoryStream tmpinput = new MemoryStream(contents);
214        rr = new ResourceReader(tmpinput);
215      } else {
216        rr = new ResourceReader(filename);
217      }
218      foreach (DictionaryEntry entry in rr) // uses rr.GetEnumerator()
219        DumpMessage(entry.Key as String, null, entry.Value as String);
220      rr.Close();
221      Out.Close();
222      stream.Close();
223    }
224
225    // --------------------------------------------------------------
226
227    public static int Main (String[] args) {
228      try {
229        if (args.Length > 1)
230          new DumpResource(args[0], args[1], args[2]);
231        else
232          new DumpResource(args[0]);
233      } catch (Exception e) {
234        Console.Error.WriteLine(e);
235        Console.Error.WriteLine(e.StackTrace);
236        return 1;
237      }
238      return 0;
239    }
240  }
241}
242