| /* |
| * Copyright 2008 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.i18n.rebind.format; |
| |
| import com.google.gwt.core.ext.TreeLogger; |
| import com.google.gwt.core.ext.typeinfo.JClassType; |
| import com.google.gwt.i18n.client.PluralRule.PluralForm; |
| import com.google.gwt.i18n.rebind.AbstractResource.ResourceList; |
| import com.google.gwt.i18n.rebind.AnnotationsResource; |
| import com.google.gwt.i18n.rebind.AnnotationsResource.ArgumentInfo; |
| |
| import java.io.PrintWriter; |
| import java.util.Arrays; |
| import java.util.Set; |
| |
| /** |
| * Writes GWT-style Java properties files for translation. This catalog |
| * format does not support aggregation of messages from multiple interfaces |
| * since there is no way to distinguish messages from another interface from |
| * those that were from this interface but no longer used. The output file |
| * is assumed to be in UTF-8 encoding rather than using the {@code \\uXXXX} |
| * escapes. |
| */ |
| public class PropertiesFormat implements MessageCatalogFormat { |
| |
| public String getExtension() { |
| return ".properties"; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.google.gwt.i18n.rebind.format.MessageCatalogFormat#write(com.google.gwt.i18n.rebind.util.AbstractResource, |
| * java.io.File, com.google.gwt.core.ext.typeinfo.JClassType) |
| */ |
| public void write(TreeLogger logger, String locale, |
| ResourceList resourceList, PrintWriter out, JClassType messageInterface) { |
| writeComment(out, "Generated from " |
| + messageInterface.getQualifiedSourceName()); |
| if (locale != null) { |
| writeComment(out, "for locale " + locale); |
| } |
| // Sort keys for deterministic output. |
| Set<String> keySet = resourceList.keySet(); |
| String[] sortedKeys = keySet.toArray(new String[keySet.size()]); |
| Arrays.sort(sortedKeys); |
| for (String key : sortedKeys) { |
| out.println(); |
| AnnotationsResource annotResource = resourceList.getAnnotationsResource( |
| logger, key); |
| if (annotResource != null) { |
| // Write comments from the annotations. |
| writeAnnotComments(out, annotResource, key); |
| } |
| |
| // Collect plural forms for this locale. |
| PluralForm[] pluralForms = resourceList.getPluralForms(key); |
| if (pluralForms != null) { |
| for (PluralForm form : pluralForms) { |
| String name = form.getName(); |
| if ("other".equals(name)) { |
| // write the "other" description here, and the default message |
| writeComment(out, "- " + form.getDescription()); |
| write(out, key, resourceList.getString(key)); |
| } else { |
| String comment = "- plural form '" + form.getName() + "': " |
| + form.getDescription(); |
| if (!form.getWarnIfMissing()) { |
| comment += " (optional)"; |
| } |
| writeComment(out, comment); |
| String translated = resourceList.getStringExt(key, |
| form.getName()); |
| if (translated == null) { |
| translated = ""; |
| } |
| write(out, key + "[" + form.getName() + "]", translated); |
| } |
| } |
| } else { |
| write(out, key, resourceList.getString(key)); |
| } |
| } |
| } |
| |
| /** |
| * Quote keys for use in a properties file. |
| * |
| * In addition to the usual quoting, all spaces are backslash-quoted. |
| * |
| * @param str key to quote |
| * @return quoted key |
| */ |
| private String quoteKey(String str) { |
| str = str.replace("\\", "\\\\"); |
| str = str.replace(" ", "\\ "); |
| return quoteSpecial(str); |
| } |
| |
| /** |
| * Quote strings for use in a properties file. |
| * |
| * @param str string to quote |
| * @return quoted string |
| */ |
| private String quoteSpecial(String str) { |
| return str.replaceAll("([\f\t\n\r$!=:#])", "\\\\$1"); |
| } |
| |
| /** |
| * Quote values for use in a properties file. |
| * |
| * In addition to the usual quoting, leading spaces are backslash-quoted. |
| * |
| * @param str value to quote |
| * @return quoted value |
| */ |
| private String quoteValue(String str) { |
| str = str.replace("\\", "\\\\"); |
| if (str.startsWith(" ")) { |
| int n = 0; |
| while (n < str.length() && str.charAt(n) == ' ') { |
| n++; |
| } |
| str = str.substring(n); |
| while (n-- > 0) { |
| str = "\\ " + str; |
| } |
| } |
| return quoteSpecial(str); |
| } |
| |
| /** |
| * Write a key-value pair to a properties file with proper quoting. |
| * |
| * @param out PrintWriter to output to |
| * @param key property key |
| * @param value property value |
| */ |
| private void write(PrintWriter out, String key, String value) { |
| out.print(quoteKey(key)); |
| out.print('='); |
| out.println(quoteValue(value)); |
| } |
| |
| /** |
| * Write comments before a line, pulled from the annotations on a |
| * given method. |
| * |
| * @param out PrintWriter stream to write to |
| * @param annotResource AnnotationsResource to get annotation data from |
| * @param key key of method for lookup in annotResource |
| */ |
| private void writeAnnotComments(PrintWriter out, AnnotationsResource annotResource, String key) { |
| String desc = annotResource.getDescription(key); |
| if (desc != null) { |
| writeComment(out, "Description: " + desc); |
| } |
| String meaning = annotResource.getMeaning(key); |
| if (meaning != null) { |
| writeComment(out, "Meaning: " + meaning); |
| } |
| Iterable<ArgumentInfo> arguments = annotResource.argumentsIterator(key); |
| StringBuffer buf = new StringBuffer(); |
| if (arguments != null) { |
| int i = 0; |
| for (ArgumentInfo argInfo : arguments) { |
| if (i > 0) { |
| buf.append(", "); |
| } |
| buf.append(i++ + "="); |
| buf.append(argInfo.name); |
| boolean inParen = false; |
| if (argInfo.optional) { |
| buf.append(" (Optional"); |
| inParen = true; |
| } |
| if (argInfo.isSelect) { |
| if (inParen) { |
| buf.append("; "); |
| } else { |
| buf.append(" ("); |
| inParen = true; |
| } |
| buf.append("Selector"); |
| } |
| if (argInfo.isPluralCount) { |
| if (inParen) { |
| buf.append("; "); |
| } else { |
| buf.append(" ("); |
| inParen = true; |
| } |
| buf.append("Plural Count"); |
| } |
| if (argInfo.example != null) { |
| if (inParen) { |
| buf.append("; "); |
| } else { |
| buf.append(" ("); |
| inParen = true; |
| } |
| buf.append("Example: " + argInfo.example); |
| } |
| if (inParen) { |
| buf.append(')'); |
| } |
| } |
| if (i > 0) { |
| writeComment(out, buf.toString()); |
| } |
| } |
| } |
| |
| /** |
| * Write a comment to a properties file. |
| * |
| * @param out PrintWriter to output to |
| * @param comment comment to write |
| */ |
| private void writeComment(PrintWriter out, String comment) { |
| out.println("# " + comment); |
| } |
| } |