ceecae267f
X-SVN-Rev: 16000
389 lines
16 KiB
Java
389 lines
16 KiB
Java
/*
|
|
*****************************************************************************
|
|
* Copyright (C) 2000-2004, International Business Machines Corporation and *
|
|
* others. All Rights Reserved. *
|
|
*****************************************************************************
|
|
*/
|
|
package com.ibm.rbm;
|
|
|
|
import java.io.*;
|
|
import java.util.*;
|
|
import java.text.*;
|
|
|
|
import javax.swing.*;
|
|
import javax.xml.parsers.*;
|
|
import javax.xml.transform.*;
|
|
import javax.xml.transform.dom.*;
|
|
import javax.xml.transform.stream.*;
|
|
|
|
import org.w3c.dom.*;
|
|
|
|
/**
|
|
* This class is a plug-in to RBManager that allows the user to export Resource Bundles
|
|
* along with some of the meta-data associated by RBManager to the XLIFF specification.
|
|
* For more information on XLIFF visit the web site
|
|
* <a href="http://www.lisa.org/xliff/">http://www.lisa.org/xliff/</a>
|
|
*
|
|
* @author George Rhoten
|
|
* @see com.ibm.rbm.RBManager
|
|
*/
|
|
public class RBxliffExporter extends RBExporter {
|
|
private static final String VERSION = "0.7";
|
|
private static final String XLIFF_DTD = "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd";
|
|
private static final String XLIFF_PUBLIC_NAME = "-//XLIFF//DTD XLIFF//EN";
|
|
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
|
|
|
/**
|
|
* Default constructor for the XLIFF exporter.
|
|
*/
|
|
|
|
public RBxliffExporter() {
|
|
super();
|
|
|
|
// Initialize the file chooser if necessary
|
|
if (chooser == null) {
|
|
chooser = new JFileChooser();
|
|
chooser.setFileFilter(new javax.swing.filechooser.FileFilter(){
|
|
public String getDescription() {
|
|
return "XLIFF Files";
|
|
}
|
|
public boolean accept(File f) {
|
|
return (f.isDirectory() || f.getName().endsWith(".xlf"));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
private String convertToISO(Date d) {
|
|
GregorianCalendar gc = new GregorianCalendar();
|
|
gc.setTime(d);
|
|
return convertToISO(gc);
|
|
}
|
|
|
|
private String convertToISO(GregorianCalendar gc) {
|
|
dateFormat.setCalendar(gc);
|
|
return dateFormat.format(gc.getTime());
|
|
}
|
|
|
|
private String getLocale(Bundle item) {
|
|
String language = item.getLanguageEncoding();
|
|
if (language != null && !language.equals("")) {
|
|
//language = language.toUpperCase();
|
|
String country = item.getCountryEncoding();
|
|
if (country != null && !country.equals("")) {
|
|
//country = country.toUpperCase();
|
|
String variant = item.getVariantEncoding();
|
|
if (variant != null && !variant.equals("")) {
|
|
//variant = variant.toUpperCase();
|
|
return language + "-" + country + "-" + variant;
|
|
}
|
|
return language + "-" + country;
|
|
}
|
|
return language;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
private String getParentLocale(String locale) {
|
|
|
|
int truncIndex = locale.lastIndexOf('-');
|
|
if (truncIndex > 0) {
|
|
locale = locale.substring(0, truncIndex);
|
|
}
|
|
else {
|
|
locale = "";
|
|
}
|
|
return locale;
|
|
}
|
|
|
|
private void addTransUnit(Document xml, Element groupElem, BundleItem item, BundleItem parent_item) {
|
|
Element transUnit = xml.createElement("trans-unit");
|
|
transUnit.setAttribute("date",convertToISO(item.getModifiedDate()));
|
|
transUnit.setAttribute("id",item.getKey());
|
|
|
|
String sourceOrTarget = "target";
|
|
if (parent_item == null) {
|
|
sourceOrTarget = "source";
|
|
}
|
|
else {
|
|
Element source = xml.createElement("source");
|
|
source.setAttribute("xml:space","preserve");
|
|
source.appendChild(xml.createTextNode(parent_item.getTranslation()));
|
|
transUnit.appendChild(source);
|
|
}
|
|
Element target = xml.createElement(sourceOrTarget);
|
|
target.setAttribute("xml:space","preserve");
|
|
// This is different from the translate attribute
|
|
if (item.isTranslated()) {
|
|
// TODO Handle the other states in the future.
|
|
transUnit.setAttribute("state", "translated");
|
|
}
|
|
target.appendChild(xml.createTextNode(item.getTranslation()));
|
|
transUnit.appendChild(target);
|
|
|
|
if (item.getComment() != null && item.getComment().length() > 1) {
|
|
Element comment_prop = xml.createElement("note");
|
|
comment_prop.setAttribute("xml:space","preserve");
|
|
comment_prop.appendChild(xml.createTextNode(item.getComment()));
|
|
transUnit.appendChild(comment_prop);
|
|
}
|
|
|
|
if ((item.getCreator() != null && item.getCreator().length() > 1)
|
|
|| (item.getModifier() != null && item.getModifier().length() > 1))
|
|
{
|
|
Element transUnit_prop_group_elem = xml.createElement("prop-group");
|
|
|
|
if (item.getCreator() != null && item.getCreator().length() > 1) {
|
|
Element creator_prop = xml.createElement("prop");
|
|
creator_prop.setAttribute("prop-type","creator");
|
|
creator_prop.appendChild(xml.createTextNode(item.getCreator()));
|
|
transUnit_prop_group_elem.appendChild(creator_prop);
|
|
}
|
|
|
|
if (item.getCreator() != null && item.getCreator().length() > 1) {
|
|
Element created_prop = xml.createElement("prop");
|
|
created_prop.setAttribute("prop-type","created");
|
|
created_prop.appendChild(xml.createTextNode(convertToISO(item.getCreatedDate())));
|
|
transUnit_prop_group_elem.appendChild(created_prop);
|
|
}
|
|
|
|
if (item.getModifier() != null && item.getModifier().length() > 1) {
|
|
Element modifier_prop = xml.createElement("prop");
|
|
modifier_prop.setAttribute("prop-type","modifier");
|
|
modifier_prop.appendChild(xml.createTextNode(item.getModifier()));
|
|
transUnit_prop_group_elem.appendChild(modifier_prop);
|
|
}
|
|
|
|
transUnit.appendChild(transUnit_prop_group_elem);
|
|
}
|
|
|
|
groupElem.appendChild(transUnit);
|
|
}
|
|
|
|
public void export(RBManager rbm) throws IOException {
|
|
if (rbm == null)
|
|
return;
|
|
// Open the Save Dialog
|
|
int ret_val = chooser.showSaveDialog(null);
|
|
if (ret_val != JFileChooser.APPROVE_OPTION)
|
|
return;
|
|
// Retrieve basic file information
|
|
File file = chooser.getSelectedFile(); // The file(s) we will be working with
|
|
File directory = new File(file.getParent()); // The directory we will be writing to
|
|
String base_name = file.getName(); // The base name of the files we will write
|
|
if (base_name == null || base_name.equals(""))
|
|
base_name = rbm.getBaseClass();
|
|
if (base_name.endsWith(".xlf"))
|
|
base_name = base_name.substring(0,base_name.length()-4);
|
|
|
|
String file_name = base_name + ".xlf";
|
|
|
|
Vector bundle_v = rbm.getBundles();
|
|
Enumeration bundleIter = bundle_v.elements();
|
|
while (bundleIter.hasMoreElements()) {
|
|
exportFile(rbm, directory, base_name, (Bundle)bundleIter.nextElement());
|
|
}
|
|
}
|
|
|
|
private void addHeaderProperties(Document xml, Element header, Bundle main_bundle) {
|
|
if (main_bundle.comment != null && main_bundle.comment.length() > 0) {
|
|
Element note = xml.createElement("note");
|
|
header.appendChild(note);
|
|
note.appendChild(xml.createTextNode(main_bundle.comment));
|
|
note.setAttribute("xml:space","preserve");
|
|
}
|
|
if ((main_bundle.name != null && main_bundle.name.length() > 0)
|
|
|| (main_bundle.manager != null && main_bundle.manager.length() > 0)
|
|
|| (main_bundle.language != null && main_bundle.language.length() > 0)
|
|
|| (main_bundle.country != null && main_bundle.country.length() > 0)
|
|
|| (main_bundle.variant != null && main_bundle.variant.length() > 0))
|
|
{
|
|
Element prop_group = xml.createElement("prop-group");
|
|
header.appendChild(prop_group);
|
|
if (main_bundle.name != null && main_bundle.name.length() > 0) {
|
|
Element prop = xml.createElement("prop");
|
|
header.appendChild(prop);
|
|
prop.setAttribute("xml:space","preserve");
|
|
prop.setAttribute("prop-type","name");
|
|
prop.appendChild(xml.createTextNode(main_bundle.name));
|
|
prop_group.appendChild(prop);
|
|
}
|
|
if (main_bundle.manager != null && main_bundle.manager.length() > 0) {
|
|
Element prop = xml.createElement("prop");
|
|
header.appendChild(prop);
|
|
prop.setAttribute("xml:space","preserve");
|
|
prop.setAttribute("prop-type","manager");
|
|
prop.appendChild(xml.createTextNode(main_bundle.manager));
|
|
prop_group.appendChild(prop);
|
|
}
|
|
if (main_bundle.language != null && main_bundle.language.length() > 0) {
|
|
Element prop = xml.createElement("prop");
|
|
header.appendChild(prop);
|
|
prop.setAttribute("xml:space","preserve");
|
|
prop.setAttribute("prop-type","language");
|
|
prop.appendChild(xml.createTextNode(main_bundle.language));
|
|
prop_group.appendChild(prop);
|
|
}
|
|
if (main_bundle.country != null && main_bundle.country.length() > 0) {
|
|
Element prop = xml.createElement("prop");
|
|
header.appendChild(prop);
|
|
prop.setAttribute("xml:space","preserve");
|
|
prop.setAttribute("prop-type","country");
|
|
prop.appendChild(xml.createTextNode(main_bundle.country));
|
|
prop_group.appendChild(prop);
|
|
}
|
|
if (main_bundle.variant != null && main_bundle.variant.length() > 0) {
|
|
Element prop = xml.createElement("prop");
|
|
header.appendChild(prop);
|
|
prop.setAttribute("xml:space","preserve");
|
|
prop.setAttribute("prop-type","variant");
|
|
prop.appendChild(xml.createTextNode(main_bundle.variant));
|
|
prop_group.appendChild(prop);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void exportFile(RBManager rbm, File directory, String base_name, Bundle main_bundle)
|
|
throws IOException
|
|
{
|
|
Bundle parent_bundle = null;
|
|
String parent_bundle_name = null;
|
|
if (!getLocale(main_bundle).equals("")) {
|
|
// If this isn't the root locale, find the parent
|
|
parent_bundle_name = getParentLocale(getLocale(main_bundle));
|
|
do {
|
|
parent_bundle = rbm.getBundle(parent_bundle_name);
|
|
if (parent_bundle != null) {
|
|
break;
|
|
}
|
|
parent_bundle_name = getParentLocale(parent_bundle_name);
|
|
} while (!parent_bundle_name.equals(""));
|
|
}
|
|
|
|
|
|
// Find the implementation
|
|
DocumentBuilder builder;
|
|
try {
|
|
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
|
}
|
|
catch (ParserConfigurationException pce) {
|
|
throw new IOException(pce.getMessage());
|
|
}
|
|
|
|
// Create the document
|
|
Document xml = builder.getDOMImplementation().createDocument(null, "xliff", null);
|
|
|
|
// Fill the document
|
|
Element root = xml.getDocumentElement();
|
|
root.setAttribute("version", "1.1");
|
|
//root.appendChild(root);
|
|
|
|
Element file_elem = xml.createElement("file");
|
|
String mainLocale = getLocale(main_bundle);
|
|
Bundle parentBundle = null;
|
|
if (mainLocale.equals("")) {
|
|
file_elem.setAttribute("source-language", getLocale(main_bundle));
|
|
}
|
|
else {
|
|
file_elem.setAttribute("source-language", parent_bundle_name);
|
|
file_elem.setAttribute("target-language", getLocale(main_bundle));
|
|
}
|
|
file_elem.setAttribute("datatype", "plaintext");
|
|
file_elem.setAttribute("date", convertToISO(new Date()));
|
|
root.appendChild(file_elem);
|
|
|
|
Element header = xml.createElement("header");
|
|
Element tool = xml.createElement("tool");
|
|
tool.setAttribute("tool-name", "RBManager");
|
|
tool.setAttribute("tool-id", "RBManager");
|
|
tool.setAttribute("tool-version", VERSION);
|
|
// TODO Add file attribute
|
|
//header.setAttribute("file", "");
|
|
header.appendChild(tool);
|
|
addHeaderProperties(xml, header, main_bundle);
|
|
file_elem.appendChild(header);
|
|
|
|
Element body = xml.createElement("body");
|
|
file_elem.appendChild(body);
|
|
|
|
Vector group_v = main_bundle.getGroupsAsVector();
|
|
Vector parent_group_v = null;
|
|
if (parent_bundle != null) {
|
|
parent_group_v = parent_bundle.getGroupsAsVector();
|
|
}
|
|
// Loop through each bundle group in main_bundle
|
|
for (int i=0; i < group_v.size(); i++) {
|
|
BundleGroup curr_group = (BundleGroup)group_v.elementAt(i);
|
|
BundleGroup parent_group = null;
|
|
if (parent_group_v != null) {
|
|
Enumeration parentGroupIter = parent_group_v.elements();
|
|
|
|
while (parentGroupIter.hasMoreElements()) {
|
|
BundleGroup groupToFind = (BundleGroup)parentGroupIter.nextElement();
|
|
if (groupToFind.getName().equals(curr_group.getName())) {
|
|
parent_group = groupToFind;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
Element group_elem = xml.createElement("group");
|
|
group_elem.setAttribute("id", curr_group.getName());
|
|
if (curr_group.getComment() != null && curr_group.getComment().length() > 1) {
|
|
Element comment_prop = xml.createElement("note");
|
|
comment_prop.setAttribute("xml:space","preserve");
|
|
comment_prop.appendChild(xml.createTextNode(curr_group.getComment()));
|
|
group_elem.appendChild(comment_prop);
|
|
}
|
|
|
|
Vector group_items = curr_group.getItemsAsVector();
|
|
for (int j=0; j < group_items.size(); j++) {
|
|
BundleItem main_item = (BundleItem)group_items.get(j);
|
|
BundleItem parent_item = null;
|
|
if (parent_group != null) {
|
|
Enumeration parentIter = parent_group.getItemsAsVector().elements();
|
|
BundleItem itemToFind = null;
|
|
while (parentIter.hasMoreElements()) {
|
|
itemToFind = (BundleItem)parentIter.nextElement();
|
|
if (itemToFind.getKey().equals(main_item.getKey())) {
|
|
parent_item = itemToFind;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
addTransUnit(xml, group_elem, main_item, parent_item);
|
|
//group_elem.appendChild(tu);
|
|
}
|
|
body.appendChild(group_elem);
|
|
} // end for - i
|
|
String suffix = mainLocale;
|
|
if (!suffix.equals("")) {
|
|
suffix = '_' + suffix;
|
|
}
|
|
char array[] = suffix.toCharArray();
|
|
for (int k=0; k < array.length; k++) {
|
|
if (array[k] == '-')
|
|
array[k] = '_';
|
|
}
|
|
suffix = String.valueOf(array);
|
|
|
|
// serialize document
|
|
OutputStreamWriter osw = new OutputStreamWriter(
|
|
new FileOutputStream(new File(directory, base_name + suffix + ".xlf")), "UTF-8");
|
|
try {
|
|
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
|
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
|
|
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
|
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
|
|
transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, XLIFF_DTD);
|
|
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, XLIFF_PUBLIC_NAME);
|
|
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
|
|
transformer.transform(new DOMSource(xml), new StreamResult(osw));
|
|
}
|
|
catch (TransformerException te) {
|
|
throw new IOException(te.getMessage());
|
|
}
|
|
|
|
osw.close();
|
|
}
|
|
}
|