diff --git a/.gitignore b/.gitignore index f5ab8b8..17832f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ target /.project +.metadata/ +.recommenders/ \ No newline at end of file diff --git a/csharp/.classpath b/csharp/.classpath new file mode 100644 index 0000000..7f0537f --- /dev/null +++ b/csharp/.classpath @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/csharp/.gitignore b/csharp/.gitignore new file mode 100644 index 0000000..174222f --- /dev/null +++ b/csharp/.gitignore @@ -0,0 +1,3 @@ +/OSGI-INF +/lib +/.settings diff --git a/csharp/.project b/csharp/.project new file mode 100644 index 0000000..47dea4c --- /dev/null +++ b/csharp/.project @@ -0,0 +1,23 @@ + + + csharp + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/csharp/META-INF/.gitignore b/csharp/META-INF/.gitignore new file mode 100644 index 0000000..4854a41 --- /dev/null +++ b/csharp/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/csharp/pom.xml b/csharp/pom.xml new file mode 100644 index 0000000..9058c98 --- /dev/null +++ b/csharp/pom.xml @@ -0,0 +1,116 @@ + + 4.0.0 + csharp + bundle + + + org.jabylon + 1.3.0 + jabylon-parent + + + 1.3.0-SNAPSHOT + + Adds support for C# strings XML + + + https://github.com/jutzig/jabylon-plugins + scm:git:https://github.com/jutzig/jabylon-plugins.git + scm:git:https://github.com/jutzig/jabylon-plugins.git + HEAD + + + + + jabylon + http://www.jabylon.org/maven + + true + + + false + + + + + + + + src/main/java + + **/*.html + **/*.properties + + + + ./ + + plugin.xml + + + + + + + + ${project.groupId} + properties + ${project.parent.version} + provided + + + ${project.groupId} + common + ${project.parent.version} + provided + + + ${project.groupId} + rest.ui + ${project.parent.version} + provided + + + + org.eclipse.emf + cdo + + + org.apache.wicket + wicket-core + + + org.slf4j + slf4j-api + + + org.eclipse.emf + ecore + + + org.eclipse.emf + common + + + org.eclipse.osgi + services + + + org.eclipse.equinox + common + + + org.eclipse.equinox + preferences + + + org.apache.felix + org.apache.felix.scr.annotations + + + + junit + junit + + + diff --git a/csharp/src/main/java/org/jabylon/csharp/CSharpConverter.java b/csharp/src/main/java/org/jabylon/csharp/CSharpConverter.java new file mode 100644 index 0000000..73089c4 --- /dev/null +++ b/csharp/src/main/java/org/jabylon/csharp/CSharpConverter.java @@ -0,0 +1,398 @@ +package org.jabylon.csharp; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.StringWriter; +import java.io.StringReader; + +import java.util.Map; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.jabylon.properties.PropertiesFactory; +import org.jabylon.properties.PropertiesPackage; +import org.jabylon.properties.Property; +import org.jabylon.properties.PropertyAnnotation; +import org.jabylon.properties.PropertyFile; +import org.jabylon.properties.types.PropertyAnnotations; +import org.jabylon.properties.types.PropertyConverter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.DOMException; +import org.xml.sax.SAXException; +import org.xml.sax.InputSource; + +public class CSharpConverter implements PropertyConverter{ + + private static final String NAME_ATTRIBUTE = "name"; + private static final String XML_SPACE = "xml:space"; + private static final String DATA = "data"; + private static final String COMMENT = "comment"; + private static final String PRESERVE = "preserve"; + private static final String VALUE = "value"; + private static final String TYPE = "type"; + private static final String SYSTEM_STRING = "System.String"; + private static final String INVARIANT = "@Invariant"; // denotes non translatable content + + private static final Logger LOG = LoggerFactory.getLogger(CSharpConverter.class); + + /** + * allows to disable pretty print for unit tests + */ + private boolean prettyPrint = true; + + private String comment; + + public CSharpConverter(URI resourceLocation, boolean prettyPrint) { + this.prettyPrint = prettyPrint; + LOG.debug("C#:CSharpConverter1"); + } + + + @Override + public PropertyFile load(InputStream in, String encoding) throws IOException { + LOG.debug("C#:load0, in: " + in.toString()); + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setIgnoringComments(false); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document result = builder.parse(in); + PropertyFile file = PropertiesFactory.eINSTANCE.createPropertyFile(); + + Node resources = result.getDocumentElement(); + + LOG.debug("C#:load2, resources, TextContent: " + resources.getTextContent()); + + NodeList nodes = resources.getChildNodes(); + + int nodesLength = nodes.getLength(); + LOG.debug("C#:load4, nodesLength: " + nodesLength); + + for (int i = nodesLength-1; i >= 0; i--) { + Node node = nodes.item(i); + LOG.debug("C#:load5, child node_" + i + " Name: " + node.getNodeName() + " Value: " + node.getNodeValue() + " Content:" + node.getTextContent() + " Type: " + node.getNodeType()); + + if (true == loadNode(node,file)) { + // 5/14/2019: Now we try plan B and replace the values in the xml file therefore there is no removal anymore of the Jabylon treated nodes + //resources.removeChild(node); + //LOG.info("C#:load6, child node_" + i + " removed. nodes.getLength afterwards: " + nodes.getLength()); + } + } + + // Build a new Document includes the nodes getting treated by Jabylon + DocumentBuilderFactory docBuilderFact = DocumentBuilderFactory.newInstance(); + docBuilderFact.setNamespaceAware(true); + DocumentBuilder docBuilder = docBuilderFact.newDocumentBuilder(); + Document newDoc = docBuilder.newDocument(); + Node importedNode = newDoc.importNode(resources, true); + newDoc.appendChild(importedNode); + + StringWriter sw = new StringWriter(); + String resFileAsString = ""; + + Node firstNode = newDoc.getChildNodes().item(0); + + try { + Transformer t = TransformerFactory.newInstance().newTransformer(); + t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + t.setOutputProperty(OutputKeys.INDENT, "yes"); + t.transform(new DOMSource(firstNode), new StreamResult(sw)); + resFileAsString = sw.toString(); + LOG.debug("C#:load7, resFileAsString: " + resFileAsString); + } catch (TransformerException te) { + LOG.error("C#:load8, nodeToString Transformer exception: ", te); + } + file.setLicenseHeader(resFileAsString); // we take the license header to store everything from our .resx + + return file; + + } catch (SAXException e) { + throw new IOException(e); + } catch (ParserConfigurationException e) { + throw new IOException(e); + } finally { + in.close(); + } + } + + + /** + * + * @param node + * @param file + * @return true: node is provided for translation + * false: node is not provided for translation + */ + private boolean loadNode(Node node, PropertyFile file) { + String name = node.getNodeName(); + LOG.debug("C#:loadNode1, Name: " + name); + + if(false == name.equals(DATA)){ + LOG.debug("C#:loadNode2, NodeName not appropriate"); + return false; + } + + NamedNodeMap namedNodeMap = node.getAttributes(); + if (null == namedNodeMap) { + LOG.error("C#:loadNode3, namedNodeMap is null"); + return false; + } + + Node namedNode = namedNodeMap.getNamedItem(NAME_ATTRIBUTE); + if (null == namedNode) { + LOG.error("C#:loadNode4, NAME_ATTRIBUTE not found"); + return false; + } + + for (int j=0; j>")) { + LOG.debug("C#:loadNode6, node value not appropriate"); + return false; + } + if (true == attribute.getNodeName().equals(TYPE)) { + if (false == attribute.getNodeValue().equals(SYSTEM_STRING)) { + LOG.debug("C#:loadNode7, type attribute found which is not appropriate"); + return false; + } + } + } + + // search for comment + NodeList childNodes = node.getChildNodes(); + + int childNodesLength = childNodes.getLength(); + LOG.debug("C#:loadNode8, nodesLength: " + childNodesLength); + + for (int k = childNodesLength-1; k >= 0; k--) { + Node childNode = childNodes.item(k); + String nodeName = childNode.getNodeName(); + String nodeContent = childNode.getTextContent(); + LOG.debug("C#:loadNode9, childNode_" + k + " Name: " + nodeName + " Value: " + childNode.getNodeValue() + " Content: " + nodeContent + " Type: " + childNode.getNodeType()); + if (null != nodeName) { + if (nodeName.equals(COMMENT)) { + LOG.debug("C#:loadNode10, comment found"); + if (nodeContent.equals(INVARIANT)) { // identifies an entry that is not provided for translation + LOG.debug("C#:loadNode11, comment indicates that this entry is not provided for translation, nodeContent: " + nodeContent); + return false; + } + else { + comment = nodeContent; + } + } + } + } + + String textContentName = namedNode.getTextContent(); + LOG.debug("C#:loadNode13, textContentName: " + textContentName); + + Property property = PropertiesFactory.eINSTANCE.createProperty(); + String key = namedNode.getNodeValue(); + property.setKey(key); + + LOG.debug("C#:loadNode14, provided for translation "); + + Node valueNode = getValueNode(node); + if (null != valueNode) { + property.setValue(valueNode.getTextContent()); + } + + if (null != comment) { + LOG.debug("C#:loadNode15, comment was set: " + comment); + property.setComment(comment); + } + comment = null; + LOG.debug("C#:loadNode16, property to be added"); + file.getProperties().add(property); + return true; + } + + + private Node getValueNode(Node node) { + LOG.debug("C#:getValueNode1"); + Node childNode = getChildNode(node, VALUE); + return childNode; + } + + + private Node getCommentNode(Node node) { + LOG.debug("C#:getCommentNode1"); + Node childNode = getChildNode(node, COMMENT); + return childNode; + } + + + private Node getChildNode(Node node, String desiredNodeName) { + LOG.debug("C#:getChildNode1, desiredNodeName: " + desiredNodeName); + NodeList childNodes = node.getChildNodes(); + if (null != childNodes) { + int numberOfChildren = childNodes.getLength(); + LOG.debug("C#:getChildNode2, number of child nodes: " + numberOfChildren); + + for (int i=0; i properties = file.getProperties(); + LOG.debug("C#:write9, Count Properties: " + properties.size()); + + for (Property property : properties) { + LOG.debug("C#:write10, property: " + property.toString()); + + try { + XPath xPath = XPathFactory.newInstance().newXPath(); + Node nodeWithValue = GetNodeWithValue(document, property.getKey(), xPath); + + if (null == nodeWithValue) { + LOG.debug("C#:write11, node not found"); + Node rootNode = (Node)xPath.evaluate("/root", document, XPathConstants.NODE); + + Element newElem = document.createElement(DATA); + newElem.setAttribute(NAME_ATTRIBUTE, property.getKey()); + newElem.setAttribute(XML_SPACE, PRESERVE); + rootNode.appendChild(newElem); + nodeWithValue = GetNodeWithValue(document, property.getKey(), xPath); + } + LOG.debug("C#:write12, nodeWithValue: " + nodeWithValue); + + LOG.debug("C#:write13, nodeWithValue.getNodeName: " + nodeWithValue.getNodeName() + " nodeWithValue.getTextContent: " + nodeWithValue.getTextContent() + " nodeWithValue.getNodeValue: " + nodeWithValue.getNodeValue() + " nodeWithValue.getNodeType: " + nodeWithValue.getNodeType()); + + String newVal = property.getValue(); + // remove the carriage return: + newVal = newVal.replaceAll("\\r", ""); + Node valueNode = getValueNode(nodeWithValue); + if (null != valueNode) { + LOG.debug("C#:write14, newVal replaced: " + newVal); + valueNode.setTextContent(newVal); + } + else { + Element newElem = document.createElement(VALUE); + LOG.debug("C#:write15, value node inserted: " + newVal); + newElem.setTextContent(newVal); + } + + String newComment = property.getComment(); + if (null != newComment) { + // remove the carriage return: + newComment = newComment.replaceAll("\\r", ""); + LOG.debug("C#:write16, newComment: " + newComment); + Node commentNode = getCommentNode(nodeWithValue); + if (null != commentNode) { + LOG.debug("C#:write17, comment replaced: " + newComment); + commentNode.setTextContent(newComment); + } + else { + Node newNode = nodeWithValue.appendChild(document.createElement(COMMENT)); + LOG.debug("C#:write18, comment inserted"); + newNode.setTextContent(newComment); + } + } + } catch (Exception e) { + LOG.error("C#:write19 ", e); + } + } + + LOG.debug("C#:write20"); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + if(prettyPrint){ + LOG.debug("C#:write21"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + } + DOMSource source = new DOMSource(document); + StreamResult result = new StreamResult(out); + + LOG.debug("C#:write22"); + transformer.transform(source, result); + LOG.debug("C#:write23"); + return counter; + } catch (ParserConfigurationException e) { + throw new IOException(e); + } catch (TransformerConfigurationException e) { + throw new IOException(e); + } catch (TransformerException e) { + throw new IOException(e); + } finally{ + out.close(); + } + } + + + private Node GetNodeWithValue(Document document, String key, XPath xPath) { + String searchStr = "//data[@name=\"" + key + "\"]"; + LOG.debug("C#:GetNodeWithValue1, searchstr: " + searchStr); + Node nodeWithValue =null; + try { + nodeWithValue = (Node)xPath.evaluate(searchStr, document, XPathConstants.NODE); + } catch (XPathExpressionException e) { + LOG.debug("C#:GetNodeWithValue2 failed with exception: ", e); + } + return nodeWithValue; + } + + + private boolean isFilled(String s){ + LOG.debug("C#:isFilled1, s: " + s); + return s!=null && !s.isEmpty(); + } +} \ No newline at end of file diff --git a/csharp/src/main/java/org/jabylon/csharp/CSharpScanner.java b/csharp/src/main/java/org/jabylon/csharp/CSharpScanner.java new file mode 100644 index 0000000..dafda72 --- /dev/null +++ b/csharp/src/main/java/org/jabylon/csharp/CSharpScanner.java @@ -0,0 +1,279 @@ +/** + * + */ +package org.jabylon.csharp; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.Service; +import org.apache.wicket.util.crypt.StringUtils; +import org.eclipse.emf.common.util.URI; +import org.jabylon.properties.PropertiesFactory; +import org.jabylon.properties.PropertiesPackage; +import org.jabylon.properties.ScanConfiguration; +import org.jabylon.properties.types.PropertyConverter; +import org.jabylon.properties.types.PropertyScanner; +import org.jabylon.properties.types.impl.AbstractPropertyScanner; +//import org.jabylon.security.CommonPermissions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * adds support for the C# xml format. + * + * @author c.gromer@seeburger.de + * + */ +@Component(enabled=true,immediate=true) +@Service +public class CSharpScanner implements PropertyScanner { + + @Property(name=PropertyScanner.TYPE, value="CSHARP") + public static final String TYPE = "CSHARP"; + + private static final String[] DEFAULT_EXCLUDES = {}; + private static final String[] DEFAULT_INCLUDES = {"**/*.resx"}; + + private static final Logger LOG = LoggerFactory.getLogger(CSharpScanner.class); + + public CSharpScanner() { + LOG.debug("C#:CSharpScanner1"); + } + + + @Override + public String[] getDefaultIncludes() { + LOG.debug("C#:getDefaultIncludes1"); + return DEFAULT_INCLUDES; + } + + /* (non-Javadoc) + * @see org.jabylon.properties.types.PropertyScanner#getDefaultExcludes() + */ + @Override + public String[] getDefaultExcludes() { + LOG.debug("C#:getDefaultExcludes1"); + return DEFAULT_EXCLUDES; + } + + + @Override + public boolean isTemplate(File propertyFile, String masterLocale) { + LOG.debug("C#:isTemplate2 propertyFile: " + propertyFile.getName() + " masterLocale: " + masterLocale); + + if(isResourceFile(propertyFile) && countingPeriodsFullfillsTemplateFileCondition(propertyFile)) { + LOG.debug("C#:isTemplate3 propertyFile is a template"); + return true; + } + + LOG.debug("C#:isTemplate4 propertyFile is not a template"); + return false; + } + + + @Override + public boolean isTranslation(File propertyFile, ScanConfiguration config) { + String fileName = propertyFile.getName(); + LOG.debug("C#:isTranslation2 fileName: " + fileName); + + if (isResourceFile(propertyFile) && (countingPeriodsFullfillsTranslationFileCondition(propertyFile))) { + LOG.debug("C#:isTranslation3 property file is a translation file"); + return true; + } + + LOG.debug("C#:isTranslation4 property file is not a translation file"); + return false; + } + + + private boolean countingPeriodsFullfillsTranslationFileCondition(File propertyFile) { + //E.g.: Resources.nl.resx is a translation file, Resources.resx is a template file + LOG.debug("C#:countingPeriodsFullfillsTranslationFileCondition1: propertyFile: " + propertyFile.getName()); + + if (2 == propertyFile.getName().length() - propertyFile.getName().replace(".","").length()) { + LOG.debug("C#:countingPeriodsFullfillsTranslationFileCondition2: translation file" ); + return true; + } + LOG.debug("C#:countingPeriodsFullfillsTranslationFileCondition3: no translation file" ); + return false; + } + + + private boolean countingPeriodsFullfillsTemplateFileCondition(File propertyFile) { + //E.g.: Resources.nl.resx is a translation file, Resources.resx is a template file + boolean bReturn = false; + LOG.debug("C#:countingPeriodsFullfillsTemplateFileCondition1: propertyFile: " + propertyFile.getName()); + + if (1 == propertyFile.getName().length() - propertyFile.getName().replace(".","").length()) { + LOG.debug("C#:countingPeriodsFullfillsTemplateFileCondition2: template" ); + bReturn = true; + } + + LOG.debug("C#:countingPeriodsFullfillsTemplateFileCondition3: bReturn: " + bReturn); + return bReturn; + } + + + private boolean isResourceFile(File propertyFile) { + LOG.debug("C#:isResourceFile2, propertyFile: " + propertyFile.getName()); + boolean isResFile = false; + if(propertyFile.getName().endsWith(".resx")) { + LOG.debug("C#:isResourceFile3: resource file" ); + isResFile = true; + } + LOG.debug("C#:isResourceFile4: isResFile: " + isResFile ); + return isResFile; + } + + + @Override + public File findTemplate(File propertyFile, ScanConfiguration config) { + LOG.info("C#:findTemplate1"); + if (isTranslation(propertyFile, config)) { + String fileName = propertyFile.getName(); + LOG.debug("C#:findTemplate2: fileName: " + fileName ); // e.g.: Resources.nl.resx + String[] strings = fileName.split(".", -1); + if (3 == strings.length) { + String templateFile = strings[0] + "." + strings[2]; // e.g.: Resources.resx + LOG.debug("C#:findTemplate3: templateFile: " + templateFile); + return new File(templateFile); + } + } + LOG.debug("C#:findTemplate4"); + return null; + } + + + @Override + public Map findTranslations(File template, ScanConfiguration config) { + LOG.debug("C#:findTranslations1, template: " + template.getName()); + if (isTemplate(template, "")) { + // instead of using org.apache.commons: + String templateWithoutExtension = getFirstPart(template); + String folder = template.getParent(); + LOG.debug("C#:findTranslations2: folder: " + folder); + File[] files = new File(folder).listFiles(); + Map translations = new HashMap(); + for (File file : files) { + LOG.debug("C#:findTranslations3: file: " + file.getName()); + if (templateWithoutExtension.equals(getFirstPart(file))) { + LOG.debug("C#:findTranslations4: first part matches"); + if (isTranslation(file, config)) { + LOG.debug("C#:findTranslations5: is translation"); + translations.put(getLocale(file), file); + } + } + } + return translations; + } + return null; + } + + + private String getFirstPart(File file) { + String firstPart = ""; + String fileParts[] = file.getName().split("\\."); + + if (0 < fileParts.length) { + firstPart = fileParts[0]; + } + LOG.debug("C#:getFirstPart, return: " + firstPart); + return(firstPart); + } + + + @Override + public File computeTranslationPath(File template, Locale templateLocale, Locale translationLocale) { + LOG.debug("C#:computeTranslationPath1, template:" + template.getName() + " template.getPath: " + template.getPath()); + File folder = template.getParentFile(); // template and translation files reside in the same folder + + if (null != folder) { + LOG.debug("C#:computeTranslationPath2, folder: " + folder.getName()); + LOG.debug("C#:computeTranslationPath2.1, folder.getPath: " + folder.getPath()); + LOG.debug("C#:computeTranslationPath2.2, folder.getParent: " + folder.getParent()); + } + + return folder; + } + + + @Override + public Locale getLocale(File propertyFile) { + LOG.debug("C#:getLocale1, propertyFile: " + propertyFile); + String propFileName = propertyFile.getName(); // e.g.: dialog.resx (template file), dialog.nl.resx (translation file) + LOG.debug("C#:getLocale2, propFileName: " + propFileName); + + String[] splittedPropFileName = propFileName.split("\\."); + + String language = ""; // "en" in "en_US" + String culture = ""; // "US" in "en_US" but there is also "Hans" in "zh-Hans" + boolean isTemplate = false; + + if (1 == splittedPropFileName.length) { + LOG.debug("C#:getLocale3, obviously no property file: " + propFileName); + } + else if (1 < splittedPropFileName.length) { + LOG.debug("C#:getLocale4, splittedPropFileName.length: " + splittedPropFileName.length); + + if (2 == splittedPropFileName.length) { + //e.g.: dialog.resx (template file) + isTemplate = true; + } + else if (3 == splittedPropFileName.length){ + if (2 == splittedPropFileName[splittedPropFileName.length-2].length()) { + LOG.debug("C#:getLocale6, only language "); + language = splittedPropFileName[splittedPropFileName.length-2]; + } + else { + LOG.debug("C#:getLocale7, splittedPropFileName[splittedPropFileName.length-2].substring(2,3): " + splittedPropFileName[splittedPropFileName.length-2].substring(2,3)); + if ("-".equals(splittedPropFileName[splittedPropFileName.length-2].substring(2,3))) { + LOG.debug("C#:getLocale8, language + culture "); + language = splittedPropFileName[splittedPropFileName.length-2].substring(0,2); // two chars + culture = splittedPropFileName[splittedPropFileName.length-2].substring(3); // can be more than two chars + } + } + } + } + Locale loc = null; + + if (false == isTemplate) { + LOG.debug("C#:getLocale11, no Template"); + if (0 < language.length()){ + LOG.debug("C#:getLocale12, isTranslation File, language: " + language + " culture: " + culture); + loc = new Locale(language, culture); + } + } + return loc; + } + + + @Override + public boolean isBilingual() { + LOG.debug("C#:isBilingual1"); + return false; + } + + + @Override + public PropertyConverter createConverter(URI resource) { + LOG.debug("C#:createConverter1, resource: " + resource.path()); + return new CSharpConverter(resource, true); + } + + + @Override + public String getEncoding() { + String encoding = "UTF-8"; + LOG.debug("C#:getEncoding1, encoding: " + encoding); + return encoding; + } +} diff --git a/csharp/src/test/Resources/TestRibbon.de.resx b/csharp/src/test/Resources/TestRibbon.de.resx new file mode 100644 index 0000000..a2e36d3 --- /dev/null +++ b/csharp/src/test/Resources/TestRibbon.de.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + BIS FileExchange SyncManager Status-Übersicht + + + BIS FileExchange Einstellungen... + + + Über BIS FileExchange... + + \ No newline at end of file diff --git a/csharp/src/test/Resources/TestRibbon.nl.resx b/csharp/src/test/Resources/TestRibbon.nl.resx new file mode 100644 index 0000000..5ba5a81 --- /dev/null +++ b/csharp/src/test/Resources/TestRibbon.nl.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + BIS FileExchange SyncManager status overzicht + + + BIS FileExchange voorkeuren … + + + Over BIS FileExchange ... + + + BIS FileExchange bestanden of permissies als bijlage toevoegen + + + Toon permissie instellingen + + + Toon de eigenschappen van de permissies + + + Activering van permissive weergave-instellingen. + + \ No newline at end of file diff --git a/csharp/src/test/Resources/TestRibbon.resx b/csharp/src/test/Resources/TestRibbon.resx new file mode 100644 index 0000000..4618176 --- /dev/null +++ b/csharp/src/test/Resources/TestRibbon.resx @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + BIS FileExchange SyncManager Status Overview + + + SeeFxSyncManagerStateViewButton + + + Microsoft.VisualStudio.Tools.Office.Ribbon.View.ButtonView, Microsoft.VisualStudio.Tools.Office.Designer, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + GroupWindow + + + 0 + + + BIS FileExchange + @Invariant + + + GroupWindow + + + Microsoft.VisualStudio.Tools.Office.Ribbon.View.GroupView, Microsoft.VisualStudio.Tools.Office.Designer, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + tab1 + + + 0 + + + TabView + @Invariant + + + tab1 + + + Microsoft.VisualStudio.Tools.Office.Ribbon.View.TabView, Microsoft.VisualStudio.Tools.Office.Designer, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + BIS FileExchange Prefs... + + + SeeFxPrefsButton + + + Microsoft.VisualStudio.Tools.Office.Ribbon.View.ButtonView, Microsoft.VisualStudio.Tools.Office.Designer, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + SeeFxToolBarButton.Items + + + 0 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAACwwAAAsMAT9AIsgAAAB6SURBVDhPpYwBDoRACAPv/5/mUgqxENCNNpkqLezPzMCm + 7FdgFH6VSxhWYPxMPCu2+uEJIf5NCyfglN6KU3Dq/kHxjLw6se0gprdCSS1deCuSTdKHR5BHfYY0ky68 + hq6e6Sw5fdN0pGCFXkOXZhtYo9ewzHdg1f21zP7N7NRI5EAs1QAAAABJRU5ErkJggg== + + + + About BIS FileExchange... + + + SeeFxAboutButton + + + Microsoft.VisualStudio.Tools.Office.Ribbon.View.ButtonView, Microsoft.VisualStudio.Tools.Office.Designer, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + SeeFxToolBarButton.Items + + + 1 + + + SeeFxToolBarButton + + + Microsoft.VisualStudio.Tools.Office.Ribbon.View.SplitButtonView, Microsoft.VisualStudio.Tools.Office.Designer, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + group1 + + + 0 + + + BIS FileExchange + @Invariant + + + group1 + + + Microsoft.VisualStudio.Tools.Office.Ribbon.View.GroupView, Microsoft.VisualStudio.Tools.Office.Designer, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + tab2 + + + 0 + + + TabMail + @Invariant + + + tab2 + + + Microsoft.VisualStudio.Tools.Office.Ribbon.View.TabView, Microsoft.VisualStudio.Tools.Office.Designer, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + True + + + SeeFxViewRibbon.OfficeMenu + + + Microsoft.VisualStudio.Tools.Office.Ribbon.View.OfficeMenuView, Microsoft.VisualStudio.Tools.Office.Designer, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + $this + + + 0 + + \ No newline at end of file diff --git a/csharp/src/test/java/org/jabylon/csharp/CSharpConverterTest.java b/csharp/src/test/java/org/jabylon/csharp/CSharpConverterTest.java new file mode 100644 index 0000000..bd8f751 --- /dev/null +++ b/csharp/src/test/java/org/jabylon/csharp/CSharpConverterTest.java @@ -0,0 +1,63 @@ +package org.jabylon.csharp; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.jabylon.csharp.CSharpConverter; +import org.jabylon.properties.Property; +import org.jabylon.properties.PropertyFile; +import org.junit.Before; +import org.junit.Test; + + +public class CSharpConverterTest { + + private CSharpConverter fixture; + + private static final String RESX_FILE = "src/test/resources/TestRibbon.resx"; + + @Before + public void setup() { + fixture = new CSharpConverter(URI.createFileURI(RESX_FILE), false); + } + + @Test + public void testLoad() throws IOException { + PropertyFile result = fixture.load(loadXML(new File(RESX_FILE)), "UTF-8"); + EList properties = result.getProperties(); + int sizeOfProperties = properties.size(); + assertEquals(3, sizeOfProperties); + for (int i=0; i translationFiles = fixture.findTranslations(template, null); + assertEquals(2, translationFiles.size()); + + Locale de = new Locale("de"); + if (false == translationFiles.containsKey(de)) + fail("No translation file found that was suitable for German local"); + Locale nl = new Locale("nl"); + if (false == translationFiles.containsKey(nl)) + fail("No translation file found that was suitable for Dutch local"); + + File trans_NL = getFileObject(RESX_FILE_NL); + if (false == translationFiles.containsValue(trans_NL)) + fail(" Dutch translation file not found! "); + + File trans_DE = getFileObject(RESX_FILE_DE); + if (false == translationFiles.containsValue(trans_DE)) + fail(" German translation file not found! "); + } +}