blob: 1fb4e64916c93216dbdf7faddec74d2e4038d6ac [file] [log] [blame]
/*
* 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);
}
}