1 /* GNU gettext for Java 2 * Copyright (C) 2001-2003 Free Software Foundation, Inc. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2, or (at your option) 7 * any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19 package gnu.gettext; 20 21 import java.lang.reflect.*; 22 import java.util.*; 23 import java.io.*; 24 25 /** 26 * This programs dumps a resource as a PO file. The resource must be 27 * accessible through the CLASSPATH. 28 * 29 * @author Bruno Haible 30 */ 31 public class DumpResource { 32 private Writer out; dumpString(String str)33 private void dumpString (String str) throws IOException { 34 int n = str.length(); 35 out.write('"'); 36 for (int i = 0; i < n; i++) { 37 char c = str.charAt(i); 38 if (c == 0x0008) { 39 out.write('\\'); out.write('b'); 40 } else if (c == 0x000c) { 41 out.write('\\'); out.write('f'); 42 } else if (c == 0x000a) { 43 out.write('\\'); out.write('n'); 44 } else if (c == 0x000d) { 45 out.write('\\'); out.write('r'); 46 } else if (c == 0x0009) { 47 out.write('\\'); out.write('t'); 48 } else if (c == '\\' || c == '"') { 49 out.write('\\'); out.write(c); 50 } else 51 out.write(c); 52 } 53 out.write('"'); 54 } dumpMessage(String msgid, String msgid_plural, Object msgstr)55 private void dumpMessage (String msgid, String msgid_plural, Object msgstr) throws IOException { 56 out.write("msgid "); dumpString(msgid); out.write('\n'); 57 if (msgid_plural != null) { 58 out.write("msgid_plural "); dumpString(msgid_plural); out.write('\n'); 59 for (int i = 0; i < ((String[])msgstr).length; i++) { 60 out.write("msgstr[" + i + "] "); 61 dumpString(((String[])msgstr)[i]); 62 out.write('\n'); 63 } 64 } else { 65 out.write("msgstr "); dumpString((String)msgstr); out.write('\n'); 66 } 67 out.write('\n'); 68 } 69 private ResourceBundle catalog; 70 private Method lookupMethod; 71 // Lookup the value corresponding to a key found in catalog.getKeys(). 72 // Here we assume that the catalog returns a non-inherited value for 73 // these keys. FIXME: Not true. Better see whether handleGetObject is 74 // public - it is in ListResourceBundle and PropertyResourceBundle. lookup(String key)75 private Object lookup (String key) { 76 Object value = null; 77 if (lookupMethod != null) { 78 try { 79 value = lookupMethod.invoke(catalog, new Object[] { key }); 80 } catch (IllegalAccessException e) { 81 e.printStackTrace(); 82 } catch (InvocationTargetException e) { 83 e.getTargetException().printStackTrace(); 84 } 85 } else { 86 try { 87 value = catalog.getObject(key); 88 } catch (MissingResourceException e) { 89 } 90 } 91 return value; 92 } dump()93 private void dump () throws IOException { 94 lookupMethod = null; 95 try { 96 lookupMethod = catalog.getClass().getMethod("lookup", new Class[] { java.lang.String.class }); 97 } catch (NoSuchMethodException e) { 98 } catch (SecurityException e) { 99 } 100 Method pluralMethod = null; 101 try { 102 pluralMethod = catalog.getClass().getMethod("get_msgid_plural_table", new Class[0]); 103 } catch (NoSuchMethodException e) { 104 } catch (SecurityException e) { 105 } 106 Field pluralField = null; 107 try { 108 pluralField = catalog.getClass().getField("plural"); 109 } catch (NoSuchFieldException e) { 110 } catch (SecurityException e) { 111 } 112 // Search for the header entry. 113 { 114 Object header_entry = null; 115 Enumeration keys = catalog.getKeys(); 116 while (keys.hasMoreElements()) 117 if ("".equals(keys.nextElement())) { 118 header_entry = lookup(""); 119 break; 120 } 121 // If there is no header entry, fake one. 122 // FIXME: This is not needed; right after po_lex_charset_init set 123 // the PO charset to UTF-8. 124 if (header_entry == null) 125 header_entry = "Content-Type: text/plain; charset=UTF-8\n"; 126 dumpMessage("",null,header_entry); 127 } 128 // Now the other messages. 129 { 130 Enumeration keys = catalog.getKeys(); 131 Object plural = null; 132 if (pluralMethod != null) { 133 // msgfmt versions > 0.13.1 create a static get_msgid_plural_table() 134 // method. 135 try { 136 plural = pluralMethod.invoke(catalog, new Object[0]); 137 } catch (IllegalAccessException e) { 138 e.printStackTrace(); 139 } catch (InvocationTargetException e) { 140 e.getTargetException().printStackTrace(); 141 } 142 } else if (pluralField != null) { 143 // msgfmt versions <= 0.13.1 create a static plural field. 144 try { 145 plural = pluralField.get(catalog); 146 } catch (IllegalAccessException e) { 147 e.printStackTrace(); 148 } 149 } 150 if (plural instanceof String[]) { 151 // A GNU gettext created class with plural handling, Java2 format. 152 int i = 0; 153 while (keys.hasMoreElements()) { 154 String key = (String)keys.nextElement(); 155 Object value = lookup(key); 156 String key_plural = (value instanceof String[] ? ((String[])plural)[i++] : null); 157 if (!"".equals(key)) 158 dumpMessage(key,key_plural,value); 159 } 160 if (i != ((String[])plural).length) 161 throw new RuntimeException("wrong plural field length"); 162 } else if (plural instanceof Hashtable) { 163 // A GNU gettext created class with plural handling, Java format. 164 while (keys.hasMoreElements()) { 165 String key = (String)keys.nextElement(); 166 if (!"".equals(key)) { 167 Object value = lookup(key); 168 String key_plural = (value instanceof String[] ? (String)((Hashtable)plural).get(key) : null); 169 dumpMessage(key,key_plural,value); 170 } 171 } 172 } else if (plural == null) { 173 // No plural handling. 174 while (keys.hasMoreElements()) { 175 String key = (String)keys.nextElement(); 176 if (!"".equals(key)) 177 dumpMessage(key,null,lookup(key)); 178 } 179 } else 180 throw new RuntimeException("wrong plural field value"); 181 } 182 } 183 DumpResource(String resource_name, String locale_name)184 public DumpResource (String resource_name, String locale_name) { 185 // Split locale_name into language_country_variant. 186 String language; 187 String country; 188 String variant; 189 language = locale_name; 190 { 191 int i = language.indexOf('_'); 192 if (i >= 0) { 193 country = language.substring(i+1); 194 language = language.substring(0,i); 195 } else 196 country = ""; 197 } 198 { 199 int j = country.indexOf('_'); 200 if (j >= 0) { 201 variant = country.substring(j+1); 202 country = country.substring(0,j); 203 } else 204 variant = ""; 205 } 206 Locale locale = new Locale(language,country,variant); 207 // Get the resource. 208 ResourceBundle catalog = ResourceBundle.getBundle(resource_name,locale); 209 // We are only interested in the messsages belonging to the locale 210 // itself, not in the inherited messages. But catalog.getLocale() exists 211 // only in Java2 and sometimes differs from the given locale. 212 try { 213 Writer w1 = new OutputStreamWriter(System.out,"UTF8"); 214 Writer w2 = new BufferedWriter(w1); 215 this.out = w2; 216 this.catalog = catalog; 217 dump(); 218 w2.close(); 219 w1.close(); 220 System.out.flush(); 221 } catch (IOException e) { 222 e.printStackTrace(); 223 System.exit(1); 224 } 225 } 226 main(String[] args)227 public static void main (String[] args) { 228 new DumpResource(args[0], args.length > 1 ? args[1] : ""); 229 System.exit(0); 230 } 231 } 232