1 /* GNU gettext for Java
2 * Copyright (C) 2001-2003, 2007, 2015 Free Software Foundation, Inc.
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 3 of the License, or
7 * (at your option) any later version.
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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 import java.lang.reflect.*;
25 * This programs dumps a resource as a PO file. The resource must be
26 * accessible through the CLASSPATH.
28 * @author Bruno Haible
30 public class DumpResource {
32 private void dumpString (String str) throws IOException {
35 for (int i = 0; i < n; i++) {
36 char c = str.charAt(i);
38 out.write('\\'); out.write('b');
39 } else if (c == 0x000c) {
40 out.write('\\'); out.write('f');
41 } else if (c == 0x000a) {
42 out.write('\\'); out.write('n');
43 } else if (c == 0x000d) {
44 out.write('\\'); out.write('r');
45 } else if (c == 0x0009) {
46 out.write('\\'); out.write('t');
47 } else if (c == '\\' || c == '"') {
48 out.write('\\'); out.write(c);
54 private void dumpMessage (String msgid, String msgid_plural, Object msgstr) throws IOException {
55 int separatorPos = msgid.indexOf('\u0004');
56 if (separatorPos >= 0) {
57 String msgctxt = msgid.substring(0,separatorPos);
58 msgid = msgid.substring(separatorPos+1);
59 out.write("msgctxt "); dumpString(msgctxt);
61 out.write("msgid "); dumpString(msgid); out.write('\n');
62 if (msgid_plural != null) {
63 out.write("msgid_plural "); dumpString(msgid_plural); out.write('\n');
64 for (int i = 0; i < ((String[])msgstr).length; i++) {
65 out.write("msgstr[" + i + "] ");
66 dumpString(((String[])msgstr)[i]);
70 out.write("msgstr "); dumpString((String)msgstr); out.write('\n');
74 private ResourceBundle catalog;
75 private Method lookupMethod;
76 // Lookup the value corresponding to a key found in catalog.getKeys().
77 // Here we assume that the catalog returns a non-inherited value for
78 // these keys. FIXME: Not true. Better see whether handleGetObject is
79 // public - it is in ListResourceBundle and PropertyResourceBundle.
80 private Object lookup (String key) {
82 if (lookupMethod != null) {
84 value = lookupMethod.invoke(catalog, new Object[] { key });
85 } catch (IllegalAccessException e) {
87 } catch (InvocationTargetException e) {
88 e.getTargetException().printStackTrace();
92 value = catalog.getObject(key);
93 } catch (MissingResourceException e) {
98 private void dump () throws IOException {
101 lookupMethod = catalog.getClass().getMethod("lookup", new Class[] { java.lang.String.class });
102 } catch (NoSuchMethodException e) {
103 } catch (SecurityException e) {
105 Method pluralMethod = null;
107 pluralMethod = catalog.getClass().getMethod("get_msgid_plural_table", new Class[0]);
108 } catch (NoSuchMethodException e) {
109 } catch (SecurityException e) {
111 Field pluralField = null;
113 pluralField = catalog.getClass().getField("plural");
114 } catch (NoSuchFieldException e) {
115 } catch (SecurityException e) {
117 // Search for the header entry.
119 Object header_entry = null;
120 Enumeration keys = catalog.getKeys();
121 while (keys.hasMoreElements())
122 if ("".equals(keys.nextElement())) {
123 header_entry = lookup("");
126 // If there is no header entry, fake one.
127 // FIXME: This is not needed; right after po_lex_charset_init set
128 // the PO charset to UTF-8.
129 if (header_entry == null)
130 header_entry = "Content-Type: text/plain; charset=UTF-8\n";
131 dumpMessage("",null,header_entry);
133 // Now the other messages.
135 Enumeration keys = catalog.getKeys();
136 Object plural = null;
137 if (pluralMethod != null) {
138 // msgfmt versions > 0.13.1 create a static get_msgid_plural_table()
141 plural = pluralMethod.invoke(catalog, new Object[0]);
142 } catch (IllegalAccessException e) {
144 } catch (InvocationTargetException e) {
145 e.getTargetException().printStackTrace();
147 } else if (pluralField != null) {
148 // msgfmt versions <= 0.13.1 create a static plural field.
150 plural = pluralField.get(catalog);
151 } catch (IllegalAccessException e) {
155 if (plural instanceof String[]) {
156 // A GNU gettext created class with plural handling, Java2 format.
158 while (keys.hasMoreElements()) {
159 String key = (String)keys.nextElement();
160 Object value = lookup(key);
161 String key_plural = (value instanceof String[] ? ((String[])plural)[i++] : null);
163 dumpMessage(key,key_plural,value);
165 if (i != ((String[])plural).length)
166 throw new RuntimeException("wrong plural field length");
167 } else if (plural instanceof Hashtable) {
168 // A GNU gettext created class with plural handling, Java format.
169 while (keys.hasMoreElements()) {
170 String key = (String)keys.nextElement();
171 if (!"".equals(key)) {
172 Object value = lookup(key);
173 String key_plural = (value instanceof String[] ? (String)((Hashtable)plural).get(key) : null);
174 dumpMessage(key,key_plural,value);
177 } else if (plural == null) {
178 // No plural handling.
179 while (keys.hasMoreElements()) {
180 String key = (String)keys.nextElement();
182 dumpMessage(key,null,lookup(key));
185 throw new RuntimeException("wrong plural field value");
189 public DumpResource (String resource_name, String locale_name) {
190 // Split locale_name into language_country_variant.
194 language = locale_name;
196 int i = language.indexOf('_');
198 country = language.substring(i+1);
199 language = language.substring(0,i);
204 int j = country.indexOf('_');
206 variant = country.substring(j+1);
207 country = country.substring(0,j);
211 Locale locale = new Locale(language,country,variant);
213 ResourceBundle catalog = ResourceBundle.getBundle(resource_name,locale);
214 // We are only interested in the messsages belonging to the locale
215 // itself, not in the inherited messages. But catalog.getLocale() exists
216 // only in Java2 and sometimes differs from the given locale.
218 Writer w1 = new OutputStreamWriter(System.out,"UTF8");
219 Writer w2 = new BufferedWriter(w1);
221 this.catalog = catalog;
226 } catch (IOException e) {
232 public static void main (String[] args) {
233 new DumpResource(args[0], args.length > 1 ? args[1] : "");