| /* GNU gettext for Java |
| * Copyright (C) 2001-2003, 2007 Free Software Foundation, Inc. |
| * |
| * 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 3 of the License, 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, see <https://www.gnu.org/licenses/>. |
| */ |
| |
| package gnu.gettext; |
| |
| import java.lang.reflect.*; |
| import java.util.*; |
| import java.io.*; |
| |
| /** |
| * This programs dumps a resource as a PO file. The resource must be |
| * accessible through the CLASSPATH. |
| * |
| * @author Bruno Haible |
| */ |
| public class DumpResource { |
| private Writer out; |
| private void dumpString (String str) throws IOException { |
| int n = str.length(); |
| out.write('"'); |
| for (int i = 0; i < n; i++) { |
| char c = str.charAt(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) throws IOException { |
| int separatorPos = msgid.indexOf('\u0004'); |
| if (separatorPos >= 0) { |
| String msgctxt = msgid.substring(0,separatorPos); |
| msgid = msgid.substring(separatorPos+1); |
| out.write("msgctxt "); dumpString(msgctxt); |
| } |
| 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 < ((String[])msgstr).length; i++) { |
| out.write("msgstr[" + i + "] "); |
| dumpString(((String[])msgstr)[i]); |
| out.write('\n'); |
| } |
| } else { |
| out.write("msgstr "); dumpString((String)msgstr); out.write('\n'); |
| } |
| out.write('\n'); |
| } |
| private ResourceBundle catalog; |
| private Method lookupMethod; |
| // Lookup the value corresponding to a key found in catalog.getKeys(). |
| // Here we assume that the catalog returns a non-inherited value for |
| // these keys. FIXME: Not true. Better see whether handleGetObject is |
| // public - it is in ListResourceBundle and PropertyResourceBundle. |
| private Object lookup (String key) { |
| Object value = null; |
| if (lookupMethod != null) { |
| try { |
| value = lookupMethod.invoke(catalog, new Object[] { key }); |
| } catch (IllegalAccessException e) { |
| e.printStackTrace(); |
| } catch (InvocationTargetException e) { |
| e.getTargetException().printStackTrace(); |
| } |
| } else { |
| try { |
| value = catalog.getObject(key); |
| } catch (MissingResourceException e) { |
| } |
| } |
| return value; |
| } |
| private void dump () throws IOException { |
| lookupMethod = null; |
| try { |
| lookupMethod = catalog.getClass().getMethod("lookup", new Class[] { java.lang.String.class }); |
| } catch (NoSuchMethodException e) { |
| } catch (SecurityException e) { |
| } |
| Method pluralMethod = null; |
| try { |
| pluralMethod = catalog.getClass().getMethod("get_msgid_plural_table", new Class[0]); |
| } catch (NoSuchMethodException e) { |
| } catch (SecurityException e) { |
| } |
| Field pluralField = null; |
| try { |
| pluralField = catalog.getClass().getField("plural"); |
| } catch (NoSuchFieldException e) { |
| } catch (SecurityException e) { |
| } |
| // Search for the header entry. |
| { |
| Object header_entry = null; |
| Enumeration keys = catalog.getKeys(); |
| while (keys.hasMoreElements()) |
| if ("".equals(keys.nextElement())) { |
| header_entry = lookup(""); |
| break; |
| } |
| // 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. |
| { |
| Enumeration keys = catalog.getKeys(); |
| Object plural = null; |
| if (pluralMethod != null) { |
| // msgfmt versions > 0.13.1 create a static get_msgid_plural_table() |
| // method. |
| try { |
| plural = pluralMethod.invoke(catalog, new Object[0]); |
| } catch (IllegalAccessException e) { |
| e.printStackTrace(); |
| } catch (InvocationTargetException e) { |
| e.getTargetException().printStackTrace(); |
| } |
| } else if (pluralField != null) { |
| // msgfmt versions <= 0.13.1 create a static plural field. |
| try { |
| plural = pluralField.get(catalog); |
| } catch (IllegalAccessException e) { |
| e.printStackTrace(); |
| } |
| } |
| if (plural instanceof String[]) { |
| // A GNU gettext created class with plural handling, Java2 format. |
| int i = 0; |
| while (keys.hasMoreElements()) { |
| String key = (String)keys.nextElement(); |
| Object value = lookup(key); |
| String key_plural = (value instanceof String[] ? ((String[])plural)[i++] : null); |
| if (!"".equals(key)) |
| dumpMessage(key,key_plural,value); |
| } |
| if (i != ((String[])plural).length) |
| throw new RuntimeException("wrong plural field length"); |
| } else if (plural instanceof Hashtable) { |
| // A GNU gettext created class with plural handling, Java format. |
| while (keys.hasMoreElements()) { |
| String key = (String)keys.nextElement(); |
| if (!"".equals(key)) { |
| Object value = lookup(key); |
| String key_plural = (value instanceof String[] ? (String)((Hashtable)plural).get(key) : null); |
| dumpMessage(key,key_plural,value); |
| } |
| } |
| } else if (plural == null) { |
| // No plural handling. |
| while (keys.hasMoreElements()) { |
| String key = (String)keys.nextElement(); |
| if (!"".equals(key)) |
| dumpMessage(key,null,lookup(key)); |
| } |
| } else |
| throw new RuntimeException("wrong plural field value"); |
| } |
| } |
| |
| public DumpResource (String resource_name, String locale_name) { |
| // Split locale_name into language_country_variant. |
| String language; |
| String country; |
| String variant; |
| language = locale_name; |
| { |
| int i = language.indexOf('_'); |
| if (i >= 0) { |
| country = language.substring(i+1); |
| language = language.substring(0,i); |
| } else |
| country = ""; |
| } |
| { |
| int j = country.indexOf('_'); |
| if (j >= 0) { |
| variant = country.substring(j+1); |
| country = country.substring(0,j); |
| } else |
| variant = ""; |
| } |
| Locale locale = new Locale(language,country,variant); |
| // Get the resource. |
| ResourceBundle catalog = ResourceBundle.getBundle(resource_name,locale); |
| // We are only interested in the messsages belonging to the locale |
| // itself, not in the inherited messages. But catalog.getLocale() exists |
| // only in Java2 and sometimes differs from the given locale. |
| try { |
| Writer w1 = new OutputStreamWriter(System.out,"UTF8"); |
| Writer w2 = new BufferedWriter(w1); |
| this.out = w2; |
| this.catalog = catalog; |
| dump(); |
| w2.close(); |
| w1.close(); |
| System.out.flush(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| System.exit(1); |
| } |
| } |
| |
| public static void main (String[] args) { |
| new DumpResource(args[0], args.length > 1 ? args[1] : ""); |
| System.exit(0); |
| } |
| } |