diff --git a/src/main/java/org/olat/ims/qti/qpool/ItemFileResourceValidator.java b/src/main/java/org/olat/ims/qti/qpool/ItemFileResourceValidator.java
index 1d9fab8bb8a9935e560d128f0b5e19c38ba93780..62f1f8d2a4c8b1184923b958304ce284bff438e7 100644
--- a/src/main/java/org/olat/ims/qti/qpool/ItemFileResourceValidator.java
+++ b/src/main/java/org/olat/ims/qti/qpool/ItemFileResourceValidator.java
@@ -182,7 +182,6 @@ public class ItemFileResourceValidator {
 
 		@Override
 		public void error(SAXParseException exception) throws SAXException {
-			log.warn("Parsing error importing question item in pool: ", exception);
 			error++;
 		}
 
diff --git a/src/main/java/org/olat/ims/qti/qpool/QTIExportTestResource.java b/src/main/java/org/olat/ims/qti/qpool/QTIExportTestResource.java
index 08db68e3fde210cf8d8c92b371572a1b465b4bf0..899dc720a954c8cc44b9ff706fd559c8c07217cf 100644
--- a/src/main/java/org/olat/ims/qti/qpool/QTIExportTestResource.java
+++ b/src/main/java/org/olat/ims/qti/qpool/QTIExportTestResource.java
@@ -20,6 +20,7 @@
 package org.olat.ims.qti.qpool;
 
 import java.util.List;
+import java.util.Locale;
 import java.util.zip.ZipOutputStream;
 
 import org.olat.modules.qpool.QuestionItemShort;
@@ -35,8 +36,8 @@ public class QTIExportTestResource extends AbstractExportTestResource {
 	
 	private final QTIQPoolServiceProvider provider;
 
-	public QTIExportTestResource(String encoding, List<QuestionItemShort> items, QTIQPoolServiceProvider provider) {
-		super(encoding, items);
+	public QTIExportTestResource(String encoding, Locale locale, List<QuestionItemShort> items, QTIQPoolServiceProvider provider) {
+		super(encoding, locale, items);
 		this.provider = provider;
 	}
 
diff --git a/src/main/java/org/olat/ims/qti/qpool/QTIQPoolServiceProvider.java b/src/main/java/org/olat/ims/qti/qpool/QTIQPoolServiceProvider.java
index 123996bc1ef681f548ef987506fa3bba5c38ae2e..7fbe02902f547d1af2dbf7795ccd9e2f3a851f33 100644
--- a/src/main/java/org/olat/ims/qti/qpool/QTIQPoolServiceProvider.java
+++ b/src/main/java/org/olat/ims/qti/qpool/QTIQPoolServiceProvider.java
@@ -313,9 +313,9 @@ public class QTIQPoolServiceProvider implements QPoolSPI {
 	}
 
 	@Override
-	public MediaResource exportTest(List<QuestionItemShort> items, ExportFormatOptions format) {
+	public MediaResource exportTest(List<QuestionItemShort> items, ExportFormatOptions format, Locale locale) {
 		if(QTIConstants.QTI_12_FORMAT.equals(format.getFormat())) {
-			return new QTIExportTestResource("UTF-8", items, this);
+			return new QTIExportTestResource("UTF-8", locale, items, this);
 		}else if(DefaultExportFormat.DOCX_EXPORT_FORMAT.getFormat().equals(format.getFormat())) {
 			return new QTIPoolWordExport(items, I18nModule.getDefaultLocale(), "UTF-8", questionItemDao, qpoolFileStorage);
 		}
@@ -324,7 +324,7 @@ public class QTIQPoolServiceProvider implements QPoolSPI {
 	}
 
 	@Override
-	public void exportItem(QuestionItemFull item, ZipOutputStream zout, Set<String> names) {
+	public void exportItem(QuestionItemFull item, ZipOutputStream zout, Locale locale, Set<String> names) {
 		QTIExportProcessor processor = new QTIExportProcessor(qpoolFileStorage);
 		processor.process(item, zout, names);
 	}
diff --git a/src/main/java/org/olat/ims/qti21/manager/AssessmentTestSessionDAO.java b/src/main/java/org/olat/ims/qti21/manager/AssessmentTestSessionDAO.java
index 9803a9bcd5ef07a386b98bf4041d90f68b17b15d..0c9f6d6d3da96ff2c94d1b6320fae2d917dc298d 100644
--- a/src/main/java/org/olat/ims/qti21/manager/AssessmentTestSessionDAO.java
+++ b/src/main/java/org/olat/ims/qti21/manager/AssessmentTestSessionDAO.java
@@ -120,5 +120,15 @@ public class AssessmentTestSessionDAO {
 	}
 	
 	
-
+	public void deleteUserTestSessions(RepositoryEntryRef testEntry) {
+		String q = "select session from qtiassessmenttestsession session where session.testEntry.key=:testEntryKey";
+		List<AssessmentTestSession> sessions = dbInstance.getCurrentEntityManager()
+				.createQuery(q, AssessmentTestSession.class)
+				.setParameter("testEntryKey", testEntry.getKey())
+				.getResultList();
+		for(AssessmentTestSession session:sessions) {
+			dbInstance.getCurrentEntityManager().remove(session);
+		}
+		
+	}
 }
diff --git a/src/main/java/org/olat/ims/qti21/model/xml/AssessmentItemBuilder.java b/src/main/java/org/olat/ims/qti21/model/xml/AssessmentItemBuilder.java
index 04c928dd20c0f4bc5c52c80f3146bf8900e550da..8b84c8c693471c0a7c864902d2d941eebfb0f1c1 100644
--- a/src/main/java/org/olat/ims/qti21/model/xml/AssessmentItemBuilder.java
+++ b/src/main/java/org/olat/ims/qti21/model/xml/AssessmentItemBuilder.java
@@ -30,6 +30,7 @@ import org.olat.ims.qti21.model.QTI21QuestionType;
 
 import uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem;
 import uk.ac.ed.ph.jqtiplus.node.item.ModalFeedback;
+import uk.ac.ed.ph.jqtiplus.node.item.interaction.Interaction;
 import uk.ac.ed.ph.jqtiplus.node.item.response.declaration.ResponseDeclaration;
 import uk.ac.ed.ph.jqtiplus.node.item.response.processing.ResponseCondition;
 import uk.ac.ed.ph.jqtiplus.node.item.response.processing.ResponseProcessing;
@@ -207,6 +208,17 @@ public abstract class AssessmentItemBuilder {
 	public AssessmentHtmlBuilder getHtmlHelper() {
 		return htmlHelper;
 	}
+	
+	public List<String> getInteractionNames() {
+		List<Interaction> interactions = assessmentItem.getItemBody().findInteractions();
+		List<String> interactionNames = new ArrayList<>(interactions.size());
+		for(Interaction interaction:interactions) {
+			String interactionName = interaction.getQtiClassName();
+			interactionNames.add(interactionName);
+		}
+		
+		return interactionNames;
+	}
 
 	public final void build() {
 		List<OutcomeDeclaration> outcomeDeclarations = assessmentItem.getOutcomeDeclarations();
diff --git a/src/main/java/org/olat/ims/qti21/model/xml/ManifestBuilder.java b/src/main/java/org/olat/ims/qti21/model/xml/ManifestBuilder.java
index 5b4d604d0c65e7de15e684a3d6524bc4af215f28..cd0d34f9a81069b85e70bee1e636793ad571bab8 100644
--- a/src/main/java/org/olat/ims/qti21/model/xml/ManifestBuilder.java
+++ b/src/main/java/org/olat/ims/qti21/model/xml/ManifestBuilder.java
@@ -44,8 +44,6 @@ import org.olat.imscp.xml.manifest.ResourceType;
 import org.olat.imscp.xml.manifest.ResourcesType;
 import org.olat.imsmd.xml.manifest.LomType;
 import org.olat.imsmd.xml.manifest.TechnicalType;
-import org.olat.imsqti.xml.manifest.QTIMetadataType;
-import org.olat.oo.xml.manifest.OpenOLATMetadataType;
 
 /**
  * manifest
@@ -64,16 +62,16 @@ public class ManifestBuilder {
 	
 	private static final OLog log = Tracing.createLoggerFor(ManifestBuilder.class);
 	
-	public static final String SCHEMA_LOCATIONS = "http://www.imsglobal.org/xsd/imscp_v1p1 http://www.imsglobal.org/xsd/imscp_v1p2.xsd http://www.imsglobal.org/xsd/imsmd_v1p2 http://www.imsglobal.org/xsd/imsmd_v1p2p4.xsd http://www.imsglobal.org/xsd/imsqti_metadata_v2p1 http://www.imsglobal.org/xsd/qti/qtiv2p1/imsqti_metadata_v2p1.xsd";
-
+	protected static final org.olat.oo.xml.manifest.ObjectFactory ooObjectFactory = new org.olat.oo.xml.manifest.ObjectFactory();
+	protected static final org.olat.imscp.xml.manifest.ObjectFactory cpObjectFactory = new org.olat.imscp.xml.manifest.ObjectFactory();
+	protected static final org.olat.imsmd.xml.manifest.ObjectFactory mdObjectFactory = new org.olat.imsmd.xml.manifest.ObjectFactory();
+	protected static final org.olat.imsqti.xml.manifest.ObjectFactory qtiObjectFactory = new org.olat.imsqti.xml.manifest.ObjectFactory();
+	
 	public static final String ASSESSMENTTEST_MIMETYPE = "text/x-imsqti-test-xml";
 	public static final String ASSESSMENTITEM_MIMETYPE = "text/x-imsqti-item-xml";
 	
-	private static final org.olat.oo.xml.manifest.ObjectFactory ooObjectFactory = new org.olat.oo.xml.manifest.ObjectFactory();
-	private static final org.olat.imscp.xml.manifest.ObjectFactory cpObjectFactory = new org.olat.imscp.xml.manifest.ObjectFactory();
-	private static final org.olat.imsmd.xml.manifest.ObjectFactory mdObjectFactory = new org.olat.imsmd.xml.manifest.ObjectFactory();
-	private static final org.olat.imsqti.xml.manifest.ObjectFactory qtiObjectFactory = new org.olat.imsqti.xml.manifest.ObjectFactory();
-	
+	public static final String SCHEMA_LOCATIONS = "http://www.imsglobal.org/xsd/imscp_v1p1 http://www.imsglobal.org/xsd/imscp_v1p2.xsd http://www.imsglobal.org/xsd/imsmd_v1p2 http://www.imsglobal.org/xsd/imsmd_v1p2p4.xsd http://www.imsglobal.org/xsd/imsqti_metadata_v2p1 http://www.imsglobal.org/xsd/qti/qtiv2p1/imsqti_metadata_v2p1.xsd";
+
 	private static JAXBContext context;
 	static {
 		try {
@@ -177,108 +175,48 @@ public class ManifestBuilder {
 	public String appendAssessmentItem() {
 		String itemId = "id" + UUID.randomUUID().toString();
         String itemFileName = itemId + ".xml";
-		ResourceType itemResourceType = appendAssessmentItem(itemId, itemFileName);
-        appendFile(itemResourceType, itemFileName);
+		appendAssessmentItem(itemId, itemFileName);
 		return itemFileName;
 	}
 	
 	public String appendAssessmentItem(String itemFileName) {
 		String itemId = IdentifierGenerator.newAsString("item");
-		ResourceType itemResourceType = appendAssessmentItem(itemId, itemFileName);
-        appendFile(itemResourceType, itemFileName);
+		appendAssessmentItem(itemId, itemFileName);
         return itemFileName;
 	}
 	
-	
-	public void setOpenOLATMetadata(ResourceType resource, String questionType) {
-		OpenOLATMetadataType qtiMetadata = getOpenOLATMetadata(resource, true);
-		qtiMetadata.setQuestionType(questionType);
+	public ManifestMetadataBuilder getResourceBuilderByIdentifier(String resourceId) {
+		ResourceType resourceType = getResourceTypeByIdentifier(resourceId);
+		MetadataType metadata = getMetadata(resourceType);
+		return metadata == null ? null : new ManifestMetadataBuilder(metadata);
 	}
 	
-	/**
-	 * Return the openolat metadata if it exists or, if specified, create
-	 * one and append it to the metadata of the resource.
-	 * 
-	 * @param resource The resource with the metadata
-	 * @param create True create the qtiMetadata
-	 * @return
-	 */
-	public OpenOLATMetadataType getOpenOLATMetadata(ResourceType resource, boolean create) {
-		MetadataType metadata = getMetadataTypeByResource(resource, create);
-		if(metadata == null) return null;
-
-		List<Object> anyMetadataList = metadata.getAny();
-		OpenOLATMetadataType ooMetadata = null;
-		for(Object anyMetadata:anyMetadataList) {
-			if(anyMetadata instanceof JAXBElement<?>
-				&& ((JAXBElement<?>)anyMetadata).getValue() instanceof OpenOLATMetadataType) {
-				ooMetadata = (OpenOLATMetadataType)((JAXBElement<?>)anyMetadata).getValue();
+	public ResourceType getResourceTypeByIdentifier(String resourceId) {
+		List<ResourceType> resources = getResourceList();
+		for(ResourceType resource:resources) {
+			if(resourceId.equals(resource.getIdentifier())) {
+				return resource;
 			}
 		}
-		
-		if(ooMetadata == null && create) {
-			ooMetadata = ooObjectFactory.createOpenOLATMetadataType();
-			metadata.getAny().add(ooObjectFactory.createOoMetadata(ooMetadata));
-		}
-		return ooMetadata;
+		return null;
 	}
 	
-	public void setQtiMetadata(ResourceType resource, List<String> interactions) {
-		QTIMetadataType qtiMetadata = getQtiMetadata(resource, true);
-		
-		qtiMetadata.getInteractionType().clear();
-		for(String interaction:interactions) {
-			qtiMetadata.getInteractionType().add(interaction);
-		}
+	public ManifestMetadataBuilder getResourceBuilderByHref(String href) {
+		ResourceType resourceType = getResourceTypeByHref(href);
+		MetadataType metadata = getMetadata(resourceType);
+		return metadata == null ? null : new ManifestMetadataBuilder(metadata);
 	}
 	
-	/**
-	 * Return the qti metadata if it exists or if specified, create
-	 * one and append it to the metadata of the resource.
-	 * 
-	 * @param resource The resource with the metadata
-	 * @param create True create the qtiMetadata
-	 * @return
-	 */
-	public QTIMetadataType getQtiMetadata(ResourceType resource, boolean create) {
-		MetadataType metadata = getMetadataTypeByResource(resource, create);
-		if(metadata == null) return null;
-
-		List<Object> anyMetadataList = metadata.getAny();
-		QTIMetadataType qtiMetadata = null;
-		for(Object anyMetadata:anyMetadataList) {
-			if(anyMetadata instanceof JAXBElement<?>
-				&& ((JAXBElement<?>)anyMetadata).getValue() instanceof QTIMetadataType) {
-				qtiMetadata = (QTIMetadataType)((JAXBElement<?>)anyMetadata).getValue();
-			}
-		}
-		
-		if(qtiMetadata == null && create) {
-			qtiMetadata = qtiObjectFactory.createQTIMetadataType();
-			metadata.getAny().add(qtiObjectFactory.createQtiMetadata(qtiMetadata));
-		}
-		return qtiMetadata;
-	}
-	
-	private MetadataType getMetadataTypeByResource(ResourceType resource, boolean create) {
-		MetadataType metadata = resource.getMetadata();
-		if(metadata == null && create) {
+	public MetadataType getMetadata(ResourceType resourceType) {
+		if(resourceType == null) return null;
+		MetadataType metadata = resourceType.getMetadata();
+		if(metadata == null) {
 			metadata = cpObjectFactory.createMetadataType();
-			resource.setMetadata(metadata);
+			resourceType.setMetadata(metadata);
 		}
 		return metadata;
 	}
 	
-	public ResourceType getResourceTypeByIdentifier(String resourceId) {
-		List<ResourceType> resources = getResourceList();
-		for(ResourceType resource:resources) {
-			if(resourceId.equals(resource.getIdentifier())) {
-				return resource;
-			}
-		}
-		return null;
-	}
-	
 	public ResourceType getResourceTypeByHref(String href) {
 		List<ResourceType> resources = getResourceList();
 		for(ResourceType resource:resources) {
@@ -314,6 +252,21 @@ public class ManifestBuilder {
         resource.getFile().add(itemFileType);
 	}
 	
+	public ManifestMetadataBuilder getMetadataBuilder(ResourceType resource, boolean create) {
+		MetadataType metadata = getMetadataType(resource, create);
+		return metadata == null ? null : new ManifestMetadataBuilder(metadata);
+		
+	}
+	
+	public MetadataType getMetadataType(ResourceType resource, boolean create) {
+		MetadataType metadata = resource.getMetadata();
+		if(metadata == null && create) {
+			metadata = cpObjectFactory.createMetadataType();
+			resource.setMetadata(metadata);
+		}
+		return metadata;
+	}
+	
 	public void build() {
 		//
 	}
diff --git a/src/main/java/org/olat/ims/qti21/model/xml/ManifestFactory.java b/src/main/java/org/olat/ims/qti21/model/xml/ManifestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..c05874f841cf4d64c7c6517653a2455bd159e192
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/model/xml/ManifestFactory.java
@@ -0,0 +1,34 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.ims.qti21.model.xml;
+
+/**
+ * 
+ * Initial date: 23.02.2016<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class ManifestFactory {
+	
+	
+	
+	
+
+}
diff --git a/src/main/java/org/olat/ims/qti21/model/xml/ManifestMetadataBuilder.java b/src/main/java/org/olat/ims/qti21/model/xml/ManifestMetadataBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..011b8ca4cbb117a5a6add275b2bfcfb38dbcec3d
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/model/xml/ManifestMetadataBuilder.java
@@ -0,0 +1,270 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.ims.qti21.model.xml;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.bind.JAXBElement;
+
+import org.olat.imscp.xml.manifest.ManifestMetadataType;
+import org.olat.imscp.xml.manifest.MetadataType;
+import org.olat.imsmd.xml.manifest.DescriptionType;
+import org.olat.imsmd.xml.manifest.GeneralType;
+import org.olat.imsmd.xml.manifest.LangstringType;
+import org.olat.imsmd.xml.manifest.LomType;
+import org.olat.imsmd.xml.manifest.TechnicalType;
+import org.olat.imsmd.xml.manifest.TitleType;
+import org.olat.imsqti.xml.manifest.QTIMetadataType;
+import org.olat.oo.xml.manifest.OpenOLATMetadataType;
+
+/**
+ * 
+ * Initial date: 23.02.2016<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class ManifestMetadataBuilder {
+	
+	protected static final org.olat.oo.xml.manifest.ObjectFactory ooObjectFactory = new org.olat.oo.xml.manifest.ObjectFactory();
+	protected static final org.olat.imscp.xml.manifest.ObjectFactory cpObjectFactory = new org.olat.imscp.xml.manifest.ObjectFactory();
+	protected static final org.olat.imsmd.xml.manifest.ObjectFactory mdObjectFactory = new org.olat.imsmd.xml.manifest.ObjectFactory();
+	protected static final org.olat.imsqti.xml.manifest.ObjectFactory qtiObjectFactory = new org.olat.imsqti.xml.manifest.ObjectFactory();
+	
+	public static final String ASSESSMENTTEST_MIMETYPE = "text/x-imsqti-test-xml";
+	public static final String ASSESSMENTITEM_MIMETYPE = "text/x-imsqti-item-xml";
+	
+	private MetadataType metadata;
+	private ManifestMetadataType manifestMetadata;
+	
+	
+	
+	public ManifestMetadataBuilder() {
+		metadata = cpObjectFactory.createMetadataType();
+	}
+	
+	public ManifestMetadataBuilder(MetadataType metadata) {
+		this.metadata = metadata;
+	}
+	
+	public MetadataType getMetadata() {
+		return metadata;
+	}
+	
+	public String getTitle() {
+		GeneralType general = getGeneral(false);
+		if(general != null) {
+			TitleType type = getFromAny(TitleType.class, general.getContent());
+			return type == null ? null : getFirstString(type.getLangstring());
+		}
+		return null;
+	}
+	
+	public void setTitle(String title, String lang) {
+		GeneralType general = getGeneral(true);
+		if(general != null) {
+			TitleType type = getFromAny(TitleType.class, general.getContent());
+			if(type == null) {
+				type = mdObjectFactory.createTitleType();
+				general.getContent().add(mdObjectFactory.createTitle(type));
+			}
+			createOrUpdateFirstLangstring(type.getLangstring(), title, lang);
+		}
+	}
+	
+	public String getDescription() {
+		GeneralType general = getGeneral(false);
+		if(general != null) {
+			DescriptionType type = getFromAny(DescriptionType.class, general.getContent());
+			return type == null ? null : getFirstString(type.getLangstring());
+		}
+		return null;
+	}
+	
+	public void setDescription(String description, String lang) {
+		GeneralType general = getGeneral(true);
+		if(general != null) {
+			DescriptionType type = getFromAny(DescriptionType.class, general.getContent());
+			if(type == null) {
+				type = mdObjectFactory.createDescriptionType();
+				general.getContent().add(mdObjectFactory.createDescription(type));
+			}
+			createOrUpdateFirstLangstring(type.getLangstring(), description, lang);
+		}
+	}
+	
+	public void setTechnicalFormat(String... formats) {
+		if(formats != null && formats.length > 0 && formats[0] != null) {
+			TechnicalType technical = getTechnical(true);
+			clearFromAny("format", technical.getContent());
+			for(int i=0; i<formats.length; i++) {
+				technical.getContent().add(mdObjectFactory.createFormat(formats[i]));
+			}
+		}
+	}
+	
+	public void createOrUpdateFirstLangstring(List<LangstringType> langStrings, String value, String lang) {
+		if(langStrings.isEmpty()) {
+			langStrings.add(createString(value, lang));
+		} else {
+			langStrings.get(0).setValue(value);
+			langStrings.get(0).setLang(lang);
+		}
+	}
+	
+	public LangstringType createString(String value, String lang) {
+		LangstringType string = mdObjectFactory.createLangstringType();
+		string.setLang(lang);
+		string.setValue(value);
+		return string;
+	}
+	
+	public String getFirstString(List<LangstringType> langStrings) {
+		String firstString = null;
+		if(langStrings != null && langStrings.size() > 0) {
+			firstString = langStrings.get(0).getValue();
+		}
+		return firstString;
+	}
+	
+	public TechnicalType getTechnical(boolean create) {
+		LomType lom = getLom(create);
+		if(lom == null) return null;
+		
+		TechnicalType technical = lom.getTechnical();
+		if(technical == null && create) {
+			technical = mdObjectFactory.createTechnicalType();
+			lom.setTechnical(technical);
+		}
+		return technical;
+	}
+
+	public GeneralType getGeneral(boolean create) {
+		LomType lom = getLom(create);
+		if(lom == null) return null;
+		
+		GeneralType general = lom.getGeneral();
+		if(general == null && create) {
+			general = mdObjectFactory.createGeneralType();
+			lom.setGeneral(general);
+		}
+		return general;
+	}
+	
+	public LomType getLom(boolean create) {
+		LomType lom = getFromAny(LomType.class, getMetadataList());
+		if(lom == null && create) {
+			lom = mdObjectFactory.createLomType();
+			getMetadataList().add(mdObjectFactory.createLom(lom));
+		}
+        return lom;
+	}
+	
+	/**
+	 * Return the openolat metadata if it exists or, if specified, create
+	 * one and append it to the metadata of the resource.
+	 * 
+	 * @param resource The resource with the metadata
+	 * @param create True create the qtiMetadata
+	 * @return
+	 */
+	public OpenOLATMetadataType getOpenOLATMetadata(boolean create) {
+		List<Object> anyMetadataList = getMetadataList();
+		OpenOLATMetadataType ooMetadata = null;
+		for(Object anyMetadata:anyMetadataList) {
+			if(anyMetadata instanceof JAXBElement<?>
+				&& ((JAXBElement<?>)anyMetadata).getValue() instanceof OpenOLATMetadataType) {
+				ooMetadata = (OpenOLATMetadataType)((JAXBElement<?>)anyMetadata).getValue();
+			}
+		}
+		
+		if(ooMetadata == null && create) {
+			ooMetadata = ooObjectFactory.createOpenOLATMetadataType();
+			getMetadataList().add(ooObjectFactory.createOoMetadata(ooMetadata));
+		}
+		return ooMetadata;
+	}
+	
+	public void setOpenOLATMetadata(String questionType) {
+		OpenOLATMetadataType qtiMetadata = getOpenOLATMetadata(true);
+		qtiMetadata.setQuestionType(questionType);
+	}
+	
+	/**
+	 * Return the qti metadata if it exists or if specified, create
+	 * one and append it to the metadata of the resource.
+	 * 
+	 * @param resource The resource with the metadata
+	 * @param create True create the qtiMetadata
+	 * @return
+	 */
+	public QTIMetadataType getQtiMetadata(boolean create) {
+		List<Object> anyMetadataList = getMetadataList();
+		QTIMetadataType qtiMetadata = null;
+		for(Object anyMetadata:anyMetadataList) {
+			if(anyMetadata instanceof JAXBElement<?>
+				&& ((JAXBElement<?>)anyMetadata).getValue() instanceof QTIMetadataType) {
+				qtiMetadata = (QTIMetadataType)((JAXBElement<?>)anyMetadata).getValue();
+			}
+		}
+		
+		if(qtiMetadata == null && create) {
+			qtiMetadata = qtiObjectFactory.createQTIMetadataType();
+			getMetadataList().add(qtiObjectFactory.createQtiMetadata(qtiMetadata));
+		}
+		return qtiMetadata;
+	}
+	
+	public void setQtiMetadata(List<String> interactions) {
+		QTIMetadataType qtiMetadata = getQtiMetadata(true);
+		
+		qtiMetadata.getInteractionType().clear();
+		for(String interaction:interactions) {
+			qtiMetadata.getInteractionType().add(interaction);
+		}
+	}
+	
+	@SuppressWarnings("unchecked")
+	private <U> U getFromAny(Class<U> type, List<Object> anyList) {
+		U object = null;
+		for(Object any:anyList) {
+			if(any instanceof JAXBElement<?>
+				&& ((JAXBElement<?>)any).getValue().getClass().equals(type)) {
+				object = (U)((JAXBElement<?>)any).getValue();
+			}
+		}
+		return object;
+	}
+
+	private void clearFromAny(String type, List<Object> anyList) {
+		for(Iterator<Object> anyIterator=anyList.iterator(); anyIterator.hasNext(); ) {
+			Object any = anyIterator.next();
+			if(any instanceof JAXBElement<?>
+				&& ((JAXBElement<?>)any).getName().getLocalPart().equals(type)) {
+				anyIterator.remove();
+			}
+		}
+	}
+	
+	public List<Object> getMetadataList() {
+		return metadata == null ? manifestMetadata.getAny() : metadata.getAny();
+	}
+
+}
diff --git a/src/main/java/org/olat/ims/qti21/pool/AssessmentItemFileResourceValidator.java b/src/main/java/org/olat/ims/qti21/pool/AssessmentItemFileResourceValidator.java
index d7066c3bb0652d9b0602002dd36c0b6fa8cfba2e..4f24d9d4353558187c48db38275ae9e46331a765 100644
--- a/src/main/java/org/olat/ims/qti21/pool/AssessmentItemFileResourceValidator.java
+++ b/src/main/java/org/olat/ims/qti21/pool/AssessmentItemFileResourceValidator.java
@@ -27,26 +27,22 @@ import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
 import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
 
 import org.apache.commons.io.IOUtils;
-import org.dom4j.Document;
-import org.dom4j.DocumentType;
-import org.dom4j.io.SAXReader;
-import org.dom4j.io.SAXValidator;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.io.ShieldInputStream;
 import org.olat.core.util.vfs.VFSLeaf;
-import org.olat.ims.resources.IMSEntityResolver;
 import org.xml.sax.Attributes;
 import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
 import org.xml.sax.XMLReader;
 import org.xml.sax.helpers.DefaultHandler;
 
+import uk.ac.ed.ph.jqtiplus.xmlutils.XmlFactories;
+
 /**
  * 
  * Validate an file
@@ -90,7 +86,7 @@ public class AssessmentItemFileResourceValidator {
 			try {
 				ZipEntry oEntr = oZip.getNextEntry();
 				while (oEntr != null) {
-					if (!oEntr.isDirectory()) {
+					if (!oEntr.isDirectory() && !"imsmanifest.xml".equals(oEntr.getName())) {
 						if(validateXml(new ShieldInputStream(oZip))) {
 							valid = true;
 						}
@@ -109,53 +105,19 @@ public class AssessmentItemFileResourceValidator {
 		
 		return valid;
 	}
-	
+
 	private boolean validateXml(InputStream in) {
-		boolean valid = false;
-		Document doc = readDocument(in);
-		if(doc != null) {
-			DocumentType docType = doc.getDocType();
-			if(docType == null) {
-				doc.addDocType("questestinterop", null, "ims_qtiasiv1p2p1.dtd");
-			}
-			valid = validateDocument(doc);
-		}
-		return valid;
-	}
-	
-	private Document readDocument(InputStream in) {
 		try {
-			SAXReader reader = new SAXReader();
-			reader.setEntityResolver(new IMSEntityResolver());
-			reader.setValidation(false);
-			return reader.read(in, "");
-		} catch (Exception e) {
-			return null;
-		}
-	}
-	
-	private boolean validateDocument(Document in) {
-		try {
-			SAXParserFactory factory = SAXParserFactory.newInstance();
-			factory.setValidating(true);
-			factory.setNamespaceAware(true);
-			
+			XMLReader reader = XmlFactories.newSAXParser().getXMLReader();
+
 			SimpleErrorHandler errorHandler = new SimpleErrorHandler();
-			ItemContentHandler contentHandler = new ItemContentHandler();
-			
-			SAXParser parser = factory.newSAXParser();
-			XMLReader reader = parser.getXMLReader();
-			reader.setEntityResolver(new IMSEntityResolver());
 			reader.setErrorHandler(errorHandler);
+			AssessmentItemContentHandler contentHandler = new AssessmentItemContentHandler();
 			reader.setContentHandler(contentHandler);
+			reader.parse(new InputSource(in));
 
-			SAXValidator validator = new SAXValidator(reader);
-			validator.validate(in);
-			
-			return errorHandler.isValid() && contentHandler.isItem();
-		} catch (ParserConfigurationException e) {
-			return false;
-		} catch (SAXException e) {
+			return errorHandler.isValid() && contentHandler.isAssessmentItem();
+		} catch (ParserConfigurationException | SAXException e) {
 			return false;
 		} catch (Exception e) {
 			return false;
@@ -176,7 +138,6 @@ public class AssessmentItemFileResourceValidator {
 
 		@Override
 		public void error(SAXParseException exception) throws SAXException {
-			log.warn("Parsing error importing question item in pool: ", exception);
 			error++;
 		}
 
@@ -186,32 +147,18 @@ public class AssessmentItemFileResourceValidator {
 		}
 	}
 	
-	private static class ItemContentHandler extends DefaultHandler {
-		private boolean interop;
-		private boolean item;
+	private static class AssessmentItemContentHandler extends DefaultHandler {
+		private boolean assessmentItem;
 		
-		public boolean isItem() {
-			return item;
+		public boolean isAssessmentItem() {
+			return assessmentItem;
 		}
 
 		@Override
 		public void startElement(String uri, String localName, String qName, Attributes attributes)
 		throws SAXException {	
-			
-			if("questestinterop".equals(qName)) {
-				interop = true;
-			} else if("item".equals(localName) || "item".equals(qName)) {
-				if(interop) {
-					item = true;
-				}
-			}
-		}
-
-		@Override
-		public void endElement(String uri, String localName, String qName)
-		throws SAXException {
-			if("questestinterop".equals(qName)) {
-				interop = false;
+			if("assessmentItem".equals(qName)) {
+				assessmentItem = true;
 			}
 		}
 	}
diff --git a/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java b/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java
index ba7cb764237c7d1702017ddc83508b636bf81eed..ec3c323042d7c4247520336db1bae4311adf5b2d 100644
--- a/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java
+++ b/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java
@@ -24,6 +24,7 @@ import java.io.FileOutputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.List;
+import java.util.Locale;
 
 import org.olat.core.helpers.Settings;
 import org.olat.core.logging.OLog;
@@ -51,6 +52,7 @@ import org.olat.ims.qti21.model.xml.AssessmentItemFactory;
 import org.olat.ims.qti21.model.xml.AssessmentTestBuilder;
 import org.olat.ims.qti21.model.xml.AssessmentTestFactory;
 import org.olat.ims.qti21.model.xml.ManifestBuilder;
+import org.olat.ims.qti21.model.xml.ManifestMetadataBuilder;
 import org.olat.ims.qti21.model.xml.ModalFeedbackBuilder;
 import org.olat.ims.qti21.model.xml.interactions.ChoiceAssessmentItemBuilder.ScoreEvaluation;
 import org.olat.ims.qti21.model.xml.interactions.EssayAssessmentItemBuilder;
@@ -87,13 +89,15 @@ public class QTI12To21Converter {
 	
 	private static final OLog log = Tracing.createLoggerFor(QTI12To21Converter.class);
 	
+	private final Locale locale;
 	private final File unzippedDirRoot;
 	private final QtiSerializer qtiSerializer = new QtiSerializer(null);
 	private final AssessmentHtmlBuilder htmlBuilder = new AssessmentHtmlBuilder(qtiSerializer);
 	
 	private final ManifestBuilder manifest;
 	
-	public QTI12To21Converter(File unzippedDirRoot) {
+	public QTI12To21Converter(File unzippedDirRoot, Locale locale) {
+		this.locale = locale;
 		this.unzippedDirRoot = unzippedDirRoot;
 		manifest = ManifestBuilder.createAssessmentTestBuilder();
 	}
@@ -210,11 +214,21 @@ public class QTI12To21Converter {
 				itemRef.setHref(new URI(itemFile.getName()));
 				assessmentSection.getSectionParts().add(itemRef);
 				persistAssessmentObject(itemFile, assessmentItem);
-				manifest.appendAssessmentItem(itemFile.getName());
+				appendResourceAndMetadata(item, itemBuilder, itemFile);
 			}
 		}
 	}
 	
+	private void appendResourceAndMetadata(Item item, AssessmentItemBuilder itemBuilder, File itemFile) {
+		manifest.appendAssessmentItem(itemFile.getName());
+		ManifestMetadataBuilder metadata = manifest.getResourceBuilderByHref(itemFile.getName());
+		metadata.setTechnicalFormat(ManifestBuilder.ASSESSMENTITEM_MIMETYPE);
+		metadata.setQtiMetadata(itemBuilder.getInteractionNames());
+		metadata.setOpenOLATMetadata(itemBuilder.getQuestionType().getPrefix());
+		metadata.setTitle(item.getTitle(), locale.getLanguage());
+		metadata.setDescription(item.getObjectives(), locale.getLanguage());
+	}
+	
 	public boolean persistAssessmentObject(File resourceFile, AssessmentObject assessmentObject) {
 		try(FileOutputStream out = new FileOutputStream(resourceFile)) {
 			qtiSerializer.serializeJqtiObject(assessmentObject, out);
diff --git a/src/main/java/org/olat/ims/qti21/pool/QTI21ExportProcessor.java b/src/main/java/org/olat/ims/qti21/pool/QTI21ExportProcessor.java
index 045a90bc45f44a640e17929a8724c20cb285da84..7dc70f8a4c1efab4906748ddcdfd086cfa075ce6 100644
--- a/src/main/java/org/olat/ims/qti21/pool/QTI21ExportProcessor.java
+++ b/src/main/java/org/olat/ims/qti21/pool/QTI21ExportProcessor.java
@@ -26,6 +26,7 @@ import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Set;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
@@ -33,12 +34,14 @@ import java.util.zip.ZipOutputStream;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.FileUtils;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.ZipUtil;
 import org.olat.core.util.io.ShieldOutputStream;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.ims.qti21.QTI21Service;
 import org.olat.ims.qti21.model.xml.AssessmentTestFactory;
 import org.olat.ims.qti21.model.xml.ManifestBuilder;
+import org.olat.ims.qti21.model.xml.ManifestMetadataBuilder;
 import org.olat.modules.qpool.QuestionItemFull;
 import org.olat.modules.qpool.manager.QPoolFileStorage;
 
@@ -57,10 +60,12 @@ public class QTI21ExportProcessor {
 	
 	private static final OLog log = Tracing.createLoggerFor(QTI21ExportProcessor.class);
 	
+	private final Locale locale;
 	private final QTI21Service qtiService;
 	private final QPoolFileStorage qpoolFileStorage;
 
-	public QTI21ExportProcessor(QTI21Service qtiService, QPoolFileStorage qpoolFileStorage) {
+	public QTI21ExportProcessor(QTI21Service qtiService, QPoolFileStorage qpoolFileStorage, Locale locale) {
+		this.locale = locale;
 		this.qtiService = qtiService;
 		this.qpoolFileStorage = qpoolFileStorage;
 	}
@@ -136,11 +141,12 @@ public class QTI21ExportProcessor {
 				String itemFilename = itemFile.getName();
 				
 				//enrichScore(itemEl);
-				//enrichWithMetadata(fullItem, itemEl);
 				//collectResources(itemEl, container, materials);
 				FileUtils.bcopy(itemFile, new File(directory, rootFilename), "");
 				AssessmentTestFactory.appendAssessmentItem(section, itemFilename);
 				manifest.appendAssessmentItem(itemFilename);
+				ManifestMetadataBuilder metadata = manifest.getResourceBuilderByHref(itemFilename);
+				enrichWithMetadata(qitem, metadata);
 			}
 
 			try(FileOutputStream out = new FileOutputStream(new File(directory, assessmentTestFilename))) {
@@ -177,12 +183,13 @@ public class QTI21ExportProcessor {
 				String itemFilename = itemFile.getName();
 				
 				//enrichScore(itemEl);
-				//enrichWithMetadata(fullItem, itemEl);
 				//collectResources(itemEl, container, materials);
 
 				ZipUtil.addFileToZip(itemFilename, itemFile, zout);
 				AssessmentTestFactory.appendAssessmentItem(section, itemFilename);
 				manifest.appendAssessmentItem(itemFilename);
+				ManifestMetadataBuilder metadata = manifest.getResourceBuilderByHref(itemFilename);
+				enrichWithMetadata(qitem, metadata);
 			}
 
 			zout.putNextEntry(new ZipEntry(assessmentTestFilename));
@@ -197,6 +204,21 @@ public class QTI21ExportProcessor {
 		}
 	}
 
+	private void enrichWithMetadata(QuestionItemFull qitem, ManifestMetadataBuilder metadata) {
+		String lang = qitem.getLanguage();
+		if(!StringHelper.containsNonWhitespace(lang)) {
+			lang = locale.getLanguage();
+		}
+		if(StringHelper.containsNonWhitespace(qitem.getTitle())) {
+			metadata.setTitle(qitem.getTitle(), lang);
+		}
+		if(StringHelper.containsNonWhitespace(qitem.getDescription())) {
+			metadata.setDescription(qitem.getDescription(), lang);
+		}
+		
+		
+	}
+
 	private static final class AssessmentItemsAndResources {
 		private final Set<String> paths = new HashSet<String>();
 		private final List<ResolvedAssessmentItem> itemEls = new ArrayList<ResolvedAssessmentItem>();
diff --git a/src/main/java/org/olat/ims/qti21/pool/QTI21ExportTestResource.java b/src/main/java/org/olat/ims/qti21/pool/QTI21ExportTestResource.java
index 3bf2b888c0b4d58bb54a84b3871f1ec749c44f27..ccaeccd1ba483b6e2adf8b438af44104b7b62cac 100644
--- a/src/main/java/org/olat/ims/qti21/pool/QTI21ExportTestResource.java
+++ b/src/main/java/org/olat/ims/qti21/pool/QTI21ExportTestResource.java
@@ -20,6 +20,7 @@
 package org.olat.ims.qti21.pool;
 
 import java.util.List;
+import java.util.Locale;
 import java.util.zip.ZipOutputStream;
 
 import org.olat.modules.qpool.QuestionItemShort;
@@ -35,14 +36,14 @@ public class QTI21ExportTestResource extends AbstractExportTestResource {
 	
 	private final QTI21QPoolServiceProvider qtiPoolServiceProvider;
 
-	public QTI21ExportTestResource(String encoding, List<QuestionItemShort> items,
+	public QTI21ExportTestResource(String encoding, Locale locale, List<QuestionItemShort> items,
 			QTI21QPoolServiceProvider qti21qPoolServiceProvider) {
-		super(encoding, items);
+		super(encoding, locale, items);
 		this.qtiPoolServiceProvider = qti21qPoolServiceProvider;
 	}
 
 	@Override
 	protected void exportTest(List<QuestionItemShort> items, ZipOutputStream zout) {
-		qtiPoolServiceProvider.assembleTest(items, zout);
+		qtiPoolServiceProvider.assembleTest(items, getLocale(), zout);
 	}
 }
diff --git a/src/main/java/org/olat/ims/qti21/pool/QTI21ImportProcessor.java b/src/main/java/org/olat/ims/qti21/pool/QTI21ImportProcessor.java
index 3266b5ca2d7893a1b7a532fb49c5007d39c1cbf2..3c817b83d4bb87cd76aa591f6089664fb9402123 100644
--- a/src/main/java/org/olat/ims/qti21/pool/QTI21ImportProcessor.java
+++ b/src/main/java/org/olat/ims/qti21/pool/QTI21ImportProcessor.java
@@ -23,7 +23,6 @@ import java.io.File;
 import java.util.List;
 import java.util.Locale;
 
-import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.core.util.StringHelper;
 import org.olat.ims.qti.qpool.QTIMetadataConverter;
@@ -64,10 +63,9 @@ public class QTI21ImportProcessor {
 	private final TaxonomyLevelDAO taxonomyLevelDao;
 	private final QEducationalContextDAO qEduContextDao;
 	
-	public QTI21ImportProcessor(Identity owner, Locale defaultLocale, String filename, File file,
+	public QTI21ImportProcessor(Identity owner, Locale defaultLocale,
 			QuestionItemDAO questionItemDao, QItemTypeDAO qItemTypeDao, QEducationalContextDAO qEduContextDao,
-			TaxonomyLevelDAO taxonomyLevelDao, QLicenseDAO qLicenseDao, QPoolFileStorage qpoolFileStorage,
-			DB dbInstance) {
+			TaxonomyLevelDAO taxonomyLevelDao, QLicenseDAO qLicenseDao, QPoolFileStorage qpoolFileStorage) {
 		this.owner = owner;
 		this.defaultLocale = defaultLocale;
 		this.qLicenseDao = qLicenseDao;
@@ -78,7 +76,14 @@ public class QTI21ImportProcessor {
 		this.taxonomyLevelDao = taxonomyLevelDao;
 	}
 
-	public List<QuestionItem> process() {
+	public List<QuestionItem> process(File file) {
+		
+		//export zip file
+		
+		//metadata copy in question
+		
+		
+		
 		return null;
 	}
 	
diff --git a/src/main/java/org/olat/ims/qti21/pool/QTI21QPoolServiceProvider.java b/src/main/java/org/olat/ims/qti21/pool/QTI21QPoolServiceProvider.java
index f177c4cf5d12b4ac33514a82bcc611d14d464245..3b2536bde028f2ed6580596d80e705b9136d19c1 100644
--- a/src/main/java/org/olat/ims/qti21/pool/QTI21QPoolServiceProvider.java
+++ b/src/main/java/org/olat/ims/qti21/pool/QTI21QPoolServiceProvider.java
@@ -189,25 +189,25 @@ public class QTI21QPoolServiceProvider implements QPoolSPI {
 
 	@Override
 	public List<QuestionItem> importItems(Identity owner, Locale defaultLocale, String filename, File file) {
-		QTI21ImportProcessor processor = new QTI21ImportProcessor(owner, defaultLocale, filename, file,
-				questionItemDao, qItemTypeDao, qEduContextDao, taxonomyLevelDao, qLicenseDao, qpoolFileStorage, dbInstance);
-		return processor.process();
+		QTI21ImportProcessor processor = new QTI21ImportProcessor(owner, defaultLocale,
+				questionItemDao, qItemTypeDao, qEduContextDao, taxonomyLevelDao, qLicenseDao, qpoolFileStorage);
+		return processor.process(file);
 	}
 	
 
 
 	@Override
-	public MediaResource exportTest(List<QuestionItemShort> items, ExportFormatOptions format) {
+	public MediaResource exportTest(List<QuestionItemShort> items, ExportFormatOptions format, Locale locale) {
 		if(QTI21Constants.QTI_21_FORMAT.equals(format.getFormat())) {
-			return new QTI21ExportTestResource("UTF-8", items, this);
+			return new QTI21ExportTestResource("UTF-8", locale, items, this);
 		}
 		
 		return null;
 	}
 
 	@Override
-	public void exportItem(QuestionItemFull item, ZipOutputStream zout, Set<String> names) {
-		QTI21ExportProcessor processor = new QTI21ExportProcessor(qtiService, qpoolFileStorage);
+	public void exportItem(QuestionItemFull item, ZipOutputStream zout, Locale locale, Set<String> names) {
+		QTI21ExportProcessor processor = new QTI21ExportProcessor(qtiService, qpoolFileStorage, locale);
 		processor.process(item, zout, names);
 	}
 
@@ -252,8 +252,8 @@ public class QTI21QPoolServiceProvider implements QPoolSPI {
 		AssessmentItemMetadata itemMetadata = new AssessmentItemMetadata();
 		itemMetadata.setQuestionType(type);
 		
-		QTI21ImportProcessor processor = new QTI21ImportProcessor(identity, locale, null, null,
-				questionItemDao, qItemTypeDao, qEduContextDao, taxonomyLevelDao, qLicenseDao, qpoolFileStorage, dbInstance);
+		QTI21ImportProcessor processor = new QTI21ImportProcessor(identity, locale, 
+				questionItemDao, qItemTypeDao, qEduContextDao, taxonomyLevelDao, qLicenseDao, qpoolFileStorage);
 		QuestionItemImpl qitem = processor.processItem(assessmentItem, "", null, "OpenOLAT", Settings.getVersion(), itemMetadata);
 
 		VFSContainer baseDir = qpoolFileStorage.getContainer(qitem.getDirectory());
@@ -275,8 +275,8 @@ public class QTI21QPoolServiceProvider implements QPoolSPI {
 	 * @param editorContainer
 	 * @return
 	 */
-	public AssessmentItem exportToQTIEditor(QuestionItemShort qitem, File editorContainer) throws IOException {
-		QTI21ExportProcessor processor = new QTI21ExportProcessor(qtiService, qpoolFileStorage);
+	public AssessmentItem exportToQTIEditor(QuestionItemShort qitem, Locale locale, File editorContainer) throws IOException {
+		QTI21ExportProcessor processor = new QTI21ExportProcessor(qtiService, qpoolFileStorage, locale);
 		QuestionItemFull fullItem = questionItemDao.loadById(qitem.getKey());
 		ResolvedAssessmentItem resolvedAssessmentItem = processor.exportToQTIEditor(fullItem, editorContainer);
 		AssessmentItem assessmentItem = resolvedAssessmentItem.getItemLookup().extractAssumingSuccessful();
@@ -284,22 +284,22 @@ public class QTI21QPoolServiceProvider implements QPoolSPI {
 		return assessmentItem;
 	}
 	
-	public void assembleTest(List<QuestionItemShort> items, ZipOutputStream zout) {
+	public void assembleTest(List<QuestionItemShort> items, Locale locale, ZipOutputStream zout) {
 		List<Long> itemKeys = new ArrayList<Long>();
 		for(QuestionItemShort item:items) {
 			itemKeys.add(item.getKey());
 		}
 
 		List<QuestionItemFull> fullItems = questionItemDao.loadByIds(itemKeys);
-		QTI21ExportProcessor processor = new QTI21ExportProcessor(qtiService, qpoolFileStorage);
+		QTI21ExportProcessor processor = new QTI21ExportProcessor(qtiService, qpoolFileStorage, locale);
 		processor.assembleTest(fullItems, zout);	
 	}
 	
-	public void exportToEditorPackage(File exportDir, List<QuestionItemShort> items) {
+	public void exportToEditorPackage(File exportDir, List<QuestionItemShort> items, Locale locale) {
 		List<Long> itemKeys = toKeys(items);
 		List<QuestionItemFull> fullItems = questionItemDao.loadByIds(itemKeys);
 
-		QTI21ExportProcessor processor = new QTI21ExportProcessor(qtiService, qpoolFileStorage);
+		QTI21ExportProcessor processor = new QTI21ExportProcessor(qtiService, qpoolFileStorage, locale);
 		processor.assembleTest(fullItems, exportDir);
 	}
 	
@@ -308,9 +308,9 @@ public class QTI21QPoolServiceProvider implements QPoolSPI {
 	 * 
 	 * @param qtiEditorPackage
 	 */
-	public boolean convertFromEditorPackage(QTIEditorPackage qtiEditorPackage, File unzippedDirRoot) {
+	public boolean convertFromEditorPackage(QTIEditorPackage qtiEditorPackage, File unzippedDirRoot, Locale locale) {
 		try {
-			QTI12To21Converter converter = new QTI12To21Converter(unzippedDirRoot);
+			QTI12To21Converter converter = new QTI12To21Converter(unzippedDirRoot, locale);
 			converter.convert(qtiEditorPackage);
 			return true;
 		} catch (URISyntaxException e) {
diff --git a/src/main/java/org/olat/ims/qti21/questionimport/AssessmentItemAndMetadata.java b/src/main/java/org/olat/ims/qti21/questionimport/AssessmentItemAndMetadata.java
index 98b53ddf53de926f028076b1d4ec5695a92494a1..7aab83a796b4f22a1071b0b248f5ee0e82f74211 100644
--- a/src/main/java/org/olat/ims/qti21/questionimport/AssessmentItemAndMetadata.java
+++ b/src/main/java/org/olat/ims/qti21/questionimport/AssessmentItemAndMetadata.java
@@ -20,9 +20,14 @@
 package org.olat.ims.qti21.questionimport;
 
 import java.math.BigDecimal;
+import java.util.Locale;
 
+import org.olat.core.util.StringHelper;
+import org.olat.core.util.filter.FilterFactory;
 import org.olat.ims.qti21.model.QTI21QuestionType;
 import org.olat.ims.qti21.model.xml.AssessmentItemBuilder;
+import org.olat.ims.qti21.model.xml.ManifestBuilder;
+import org.olat.ims.qti21.model.xml.ManifestMetadataBuilder;
 
 /**
  * 
@@ -33,8 +38,9 @@ import org.olat.ims.qti21.model.xml.AssessmentItemBuilder;
 public class AssessmentItemAndMetadata {
 	
 	private final AssessmentItemBuilder item;
+	private final QTI21QuestionType questionType;
 	
-	private QTI21QuestionType questionType;
+	private String description;
 	private String language;
 	private String taxonomyPath;
 	private String keywords;
@@ -53,12 +59,21 @@ public class AssessmentItemAndMetadata {
 	
 	public AssessmentItemAndMetadata(AssessmentItemBuilder item) {
 		this.item = item;
+		questionType = item.getQuestionType();
 	}
 
 	public AssessmentItemBuilder getItemBuilder() {
 		return item;
 	}
 	
+	public String getDescription() {
+		return description;
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
 	public BigDecimal getDifficulty() {
 		return difficulty;
 	}
@@ -182,4 +197,18 @@ public class AssessmentItemAndMetadata {
 	public void setHasError(boolean hasError) {
 		this.hasError = hasError;
 	}
+	
+	public void transfer(ManifestMetadataBuilder metadata, Locale locale) {
+		if(questionType != null) {
+			metadata.setOpenOLATMetadata(questionType.getPrefix());
+		}
+		metadata.setTechnicalFormat(ManifestBuilder.ASSESSMENTITEM_MIMETYPE);
+		if(StringHelper.containsNonWhitespace(item.getTitle())) {
+			metadata.setTitle(item.getTitle(), locale.getLanguage());
+		}
+		if(StringHelper.containsNonWhitespace(description)) {
+			String cleanedDescription = FilterFactory.getHtmlTagsFilter().filter(description);
+			metadata.setDescription(cleanedDescription, locale.getLanguage());
+		}
+	}
 }
diff --git a/src/main/java/org/olat/ims/qti21/questionimport/CSVToAssessmentItemConverter.java b/src/main/java/org/olat/ims/qti21/questionimport/CSVToAssessmentItemConverter.java
index 9b4de39de04e8c5a763b19082b459b8b3dca8832..05f8b6d8b96ee435d8363e7f2647c334c11ec03c 100644
--- a/src/main/java/org/olat/ims/qti21/questionimport/CSVToAssessmentItemConverter.java
+++ b/src/main/java/org/olat/ims/qti21/questionimport/CSVToAssessmentItemConverter.java
@@ -97,7 +97,7 @@ public class CSVToAssessmentItemConverter {
 			case "titel":
 			case "title": processTitle(parts); break;
 			case "beschreibung":
-			case "description": break;
+			case "description": processDescription(parts); break;
 			case "frage":
 			case "question": processQuestion(parts); break;
 			case "punkte":
@@ -130,6 +130,15 @@ public class CSVToAssessmentItemConverter {
 			default: processChoice(parts);
 		}
 	}
+	
+	private void processDescription(String[] parts) {
+		if(currentItem == null || parts.length < 2) return;
+		
+		String description = parts[1];
+		if(StringHelper.containsNonWhitespace(description)) {
+			currentItem.setDescription(description);
+		}
+	}
 
 	private void processLevel(String[] parts) {
 		if(currentItem == null || parts.length < 2) return;
diff --git a/src/main/java/org/olat/ims/qti21/repository/handlers/QTI21AssessmentTestHandler.java b/src/main/java/org/olat/ims/qti21/repository/handlers/QTI21AssessmentTestHandler.java
index 49756bf0ebb1b740eec77b0357a44105ce5c3216..e031010d124fb7ce11b86f5f29ff2028d8d317ae 100644
--- a/src/main/java/org/olat/ims/qti21/repository/handlers/QTI21AssessmentTestHandler.java
+++ b/src/main/java/org/olat/ims/qti21/repository/handlers/QTI21AssessmentTestHandler.java
@@ -66,6 +66,7 @@ import org.olat.fileresource.types.ImsQTI21Resource;
 import org.olat.fileresource.types.ResourceEvaluation;
 import org.olat.ims.qti.editor.QTIEditorPackage;
 import org.olat.ims.qti21.QTI21Service;
+import org.olat.ims.qti21.manager.AssessmentTestSessionDAO;
 import org.olat.ims.qti21.model.IdentifierGenerator;
 import org.olat.ims.qti21.model.QTI21QuestionType;
 import org.olat.ims.qti21.model.xml.AssessmentItemFactory;
@@ -115,6 +116,8 @@ public class QTI21AssessmentTestHandler extends FileHandler {
 	private RepositoryService repositoryService;
 	@Autowired
 	private QTI21QPoolServiceProvider qpoolServiceProvider;
+	@Autowired
+	private AssessmentTestSessionDAO assessmentTestSessionDao;
 
 	@Override
 	public String getSupportedType() {
@@ -145,10 +148,10 @@ public class QTI21AssessmentTestHandler extends FileHandler {
 		}
 		if(createObject instanceof QItemList) {
 			QItemList itemToImport = (QItemList)createObject;
-			qpoolServiceProvider.exportToEditorPackage(repositoryDir, itemToImport.getItems());
+			qpoolServiceProvider.exportToEditorPackage(repositoryDir, itemToImport.getItems(), locale);
 		} else if(createObject instanceof QTIEditorPackage) {
 			QTIEditorPackage testToConvert = (QTIEditorPackage)createObject;
-			qpoolServiceProvider.convertFromEditorPackage(testToConvert, repositoryDir);
+			qpoolServiceProvider.convertFromEditorPackage(testToConvert, repositoryDir, locale);
 		} else {
 			createMinimalAssessmentTest(displayname, repositoryDir);
 		}
@@ -358,11 +361,14 @@ public class QTI21AssessmentTestHandler extends FileHandler {
 
 	@Override
 	public boolean readyToDelete(RepositoryEntry entry, Identity identity, Roles roles, Locale locale, ErrorList errors) {
-		boolean ready = super.readyToDelete(entry, identity, roles, locale, errors);
-		if(ready) {
-			//update / remove assessment test sessions
-		}
-		return ready;
+		return super.readyToDelete(entry, identity, roles, locale, errors);
+	}
+
+	@Override
+	public boolean cleanupOnDelete(RepositoryEntry entry, OLATResourceable res) {
+		boolean clean = super.cleanupOnDelete(entry, res);
+		assessmentTestSessionDao.deleteUserTestSessions(entry);
+		return clean;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java
index c57a9ed077be94622a2d3042c2c79731bb5b4243..d2401717f7341809330a0169ee60067f5789b7cd 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java
@@ -34,6 +34,8 @@ import org.olat.ims.qti21.QTI21Service;
 import org.olat.ims.qti21.model.QTI21QuestionType;
 import org.olat.ims.qti21.model.QTI21QuestionTypeDetector;
 import org.olat.ims.qti21.model.xml.AssessmentItemBuilder;
+import org.olat.ims.qti21.model.xml.ManifestBuilder;
+import org.olat.ims.qti21.model.xml.ManifestMetadataBuilder;
 import org.olat.ims.qti21.model.xml.interactions.EssayAssessmentItemBuilder;
 import org.olat.ims.qti21.model.xml.interactions.KPrimAssessmentItemBuilder;
 import org.olat.ims.qti21.model.xml.interactions.MultipleChoiceAssessmentItemBuilder;
@@ -67,10 +69,12 @@ public class AssessmentItemEditorController extends BasicController {
 	private final TabbedPane tabbedPane;
 	private final VelocityContainer mainVC;
 	
-	private Controller itemEditor, scoreEditor, feedbackEditor;
+	private MetadataEditorController metadataEditor;
 	private AssessmentItemDisplayController displayCtrl;
+	private Controller itemEditor, scoreEditor, feedbackEditor;
 	
 	private AssessmentItemBuilder itemBuilder;
+	private ManifestMetadataBuilder metadataBuilder;
 	
 	@Autowired
 	private QTI21Service qtiService;
@@ -99,9 +103,11 @@ public class AssessmentItemEditorController extends BasicController {
 	}
 	
 	public AssessmentItemEditorController(UserRequest ureq, WindowControl wControl, RepositoryEntry testEntry,
-			ResolvedAssessmentItem resolvedAssessmentItem, AssessmentItemRef itemRef, File unzippedDirectory) {
+			ResolvedAssessmentItem resolvedAssessmentItem, AssessmentItemRef itemRef, ManifestMetadataBuilder metadataBuilder,
+			File unzippedDirectory) {
 		super(ureq, wControl);
 		this.itemRef = itemRef;
+		this.metadataBuilder = metadataBuilder;
 		this.resolvedAssessmentItem = resolvedAssessmentItem;
 		
 		mainVC = createVelocityContainer("assessment_item_editor");
@@ -130,10 +136,8 @@ public class AssessmentItemEditorController extends BasicController {
 	}
 	
 	private void initItemEditor(UserRequest ureq) {
-		
-		
-		
 		AssessmentItem item = resolvedAssessmentItem.getItemLookup().getRootNodeHolder().getRootNode();
+		
 		QTI21QuestionType type = QTI21QuestionTypeDetector.getType(item);
 		switch(type) {
 			case sc: itemBuilder = initSingleChoiceEditors(ureq, item); break;
@@ -142,7 +146,12 @@ public class AssessmentItemEditorController extends BasicController {
 			case essay: itemBuilder = initEssayEditors(ureq, item); break;
 			default: initItemCreatedByUnkownEditor(ureq); break;
 		}
-
+		
+		if(metadataBuilder != null) {
+			metadataEditor = new MetadataEditorController(ureq, getWindowControl(), metadataBuilder);
+			listenTo(metadataEditor);
+			tabbedPane.addTab(translate("form.metadata"), metadataEditor.getInitialComponent());
+		}
 	}
 	
 	private void initItemCreatedByUnkownEditor(UserRequest ureq) {
@@ -223,14 +232,22 @@ public class AssessmentItemEditorController extends BasicController {
 				AssessmentItemEvent aie = (AssessmentItemEvent)event;
 				if(AssessmentItemEvent.ASSESSMENT_ITEM_CHANGED.equals(aie.getCommand())) {
 					doBuildAndSaveAssessmentItem();
+					doBuildAndCommitMetadata();
 					fireEvent(ureq, new AssessmentItemEvent(aie.getCommand(), aie.getAssessmentItem(), itemRef, aie.getQuestionType()));
 				}
 			}
+		} else if(metadataEditor == source) {
+			if(event == Event.CHANGED_EVENT) {
+				doBuildAndCommitMetadata();
+				AssessmentItem item = resolvedAssessmentItem.getItemLookup().getRootNodeHolder().getRootNode();
+				fireEvent(ureq, new AssessmentItemEvent(AssessmentItemEvent.ASSESSMENT_ITEM_METADATA_CHANGED, item, itemRef, null));
+			}
 		}
 		super.event(ureq, source, event);
 	}
 
 	private void doBuildAndSaveAssessmentItem() {
+		//update assessment item file
 		if(itemBuilder != null) {
 			itemBuilder.build();
 		}
@@ -238,4 +255,17 @@ public class AssessmentItemEditorController extends BasicController {
 		File itemFile = new File(itemUri);
 		qtiService.updateAssesmentObject(itemFile, resolvedAssessmentItem);
 	}
+
+	private void doBuildAndCommitMetadata() {
+		if(metadataBuilder == null) return;
+		
+		//update manifest
+		metadataBuilder.setTechnicalFormat(ManifestBuilder.ASSESSMENTITEM_MIMETYPE);		
+		metadataBuilder.setQtiMetadata(itemBuilder.getInteractionNames());
+		if(itemBuilder != null) {
+			metadataBuilder.setOpenOLATMetadata(itemBuilder.getQuestionType().getPrefix());
+		} else {
+			metadataBuilder.setOpenOLATMetadata(QTI21QuestionType.unkown.getPrefix());
+		}
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java
index 93539f6bda459a676630aa7fe3d4c1aec3ec3ba3..b49323a2f4ce12454b32db8bbaa08f58feee11de 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java
@@ -23,7 +23,6 @@ import java.io.File;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.util.ArrayList;
 import java.util.List;
 
 import org.olat.core.commons.fullWebApp.LayoutMain3ColsController;
@@ -55,10 +54,10 @@ import org.olat.fileresource.FileResourceManager;
 import org.olat.ims.qti21.QTI21Constants;
 import org.olat.ims.qti21.QTI21Service;
 import org.olat.ims.qti21.model.IdentifierGenerator;
-import org.olat.ims.qti21.model.QTI21QuestionType;
 import org.olat.ims.qti21.model.xml.AssessmentItemBuilder;
 import org.olat.ims.qti21.model.xml.AssessmentTestFactory;
 import org.olat.ims.qti21.model.xml.ManifestBuilder;
+import org.olat.ims.qti21.model.xml.ManifestMetadataBuilder;
 import org.olat.ims.qti21.model.xml.interactions.EssayAssessmentItemBuilder;
 import org.olat.ims.qti21.model.xml.interactions.KPrimAssessmentItemBuilder;
 import org.olat.ims.qti21.model.xml.interactions.MultipleChoiceAssessmentItemBuilder;
@@ -82,7 +81,6 @@ import org.olat.repository.ui.RepositoryEntryRuntimeController.ToolbarAware;
 import org.springframework.beans.factory.annotation.Autowired;
 
 import uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem;
-import uk.ac.ed.ph.jqtiplus.node.item.interaction.Interaction;
 import uk.ac.ed.ph.jqtiplus.node.test.AbstractPart;
 import uk.ac.ed.ph.jqtiplus.node.test.AssessmentItemRef;
 import uk.ac.ed.ph.jqtiplus.node.test.AssessmentSection;
@@ -244,12 +242,15 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 			if(AssessmentSectionEvent.ASSESSMENT_SECTION_CHANGED.equals(ase.getCommand())) {
 				doSaveAssessmentTest();
 				doUpdate(ase.getSection().getIdentifier(), ase.getSection().getTitle());
+				doSaveManifest();
 			}
 		} else if(event instanceof AssessmentItemEvent) {
 			AssessmentItemEvent aie = (AssessmentItemEvent)event;
 			if(AssessmentItemEvent.ASSESSMENT_ITEM_CHANGED.equals(aie.getCommand())) {
-				doUpdateManifest(aie.getAssessmentItemRef(), aie.getAssessmentItem(), aie.getQuestionType());
 				doUpdate(aie.getAssessmentItemRef().getIdentifier(), aie.getAssessmentItem().getTitle());
+				doSaveManifest();
+			} else if(AssessmentItemEvent.ASSESSMENT_ITEM_METADATA_CHANGED.equals(aie.getCommand())) {
+				doSaveManifest();
 			}
 		} else if(selectQItemCtrl == source) {
 			cmc.deactivate();
@@ -352,10 +353,10 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 		try {
 			AssessmentSection section = (AssessmentSection)sectionNode.getUserObject();
 			for(QuestionItemView item:items) {
-				AssessmentItem assessmentItem = qti21QPoolServiceProvider.exportToQTIEditor(item, unzippedDirRoot);
-				String itemId = doInsert(section, assessmentItem);
+				AssessmentItem assessmentItem = qti21QPoolServiceProvider.exportToQTIEditor(item, getLocale(), unzippedDirRoot);
+				AssessmentItemRef itemRef = doInsert(section, assessmentItem);
 				if(firstItemId == null) {
-					firstItemId = itemId;
+					firstItemId = itemRef.getIdentifier().toString();
 				}
 			}
 		} catch (IOException | URISyntaxException e) {
@@ -381,10 +382,14 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 			
 			List<AssessmentItemAndMetadata> itemsAndMetadata = importPackage.getItems();
 			for(AssessmentItemAndMetadata itemAndMetadata:itemsAndMetadata) {
-				AssessmentItem assessmentItem = itemAndMetadata.getItemBuilder().getAssessmentItem();
-				String itemId = doInsert(section, assessmentItem);
+				AssessmentItemBuilder itemBuilder = itemAndMetadata.getItemBuilder();
+				AssessmentItem assessmentItem = itemBuilder.getAssessmentItem();
+				AssessmentItemRef itemRef = doInsert(section, assessmentItem);
+				ManifestMetadataBuilder metadata = manifestBuilder.getResourceBuilderByHref(itemRef.getHref().toString());
+				metadata.setQtiMetadata(itemBuilder.getInteractionNames());
+				itemAndMetadata.transfer(metadata, getLocale());
 				if(firstItemId == null) {
-					firstItemId = itemId;
+					firstItemId = itemRef.getIdentifier().toString();
 				}
 			}
 		} catch (URISyntaxException e) {
@@ -392,6 +397,9 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 			logError("", e);
 		}
 		
+		//persist metadata
+		manifestBuilder.write(new File(unzippedDirRoot, "imsmanifest.xml"));
+		
 		updateTreeModel();
 		
 		TreeNode newItemNode = menuTree.getTreeModel().getNodeById(firstItemId);
@@ -400,7 +408,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 		partEditorFactory(ureq, newItemNode);
 	}
 	
-	private String doInsert(AssessmentSection section, AssessmentItem assessmentItem)
+	private AssessmentItemRef doInsert(AssessmentSection section, AssessmentItem assessmentItem)
 	throws URISyntaxException {
 		AssessmentItemRef itemRef = new AssessmentItemRef(section);
 		String itemId = assessmentItem.getIdentifier();
@@ -417,7 +425,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 
 		manifestBuilder.appendAssessmentItem(itemFile.getName());
 		manifestBuilder.write(new File(unzippedDirRoot, "imsmanifest.xml"));
-		return itemId;
+		return itemRef;
 	}
 	
 	private TreeNode doOpenFirstItem() {
@@ -538,25 +546,8 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 		qtiService.updateAssesmentObject(testFile, resolvedAssessmentTest);
 	}
 	
-	private void doUpdateManifest(AssessmentItemRef ref, AssessmentItem item, QTI21QuestionType questionType) {
-		URI itemUri = resolvedAssessmentTest.getResolvedAssessmentItem(ref).getItemLookup().getSystemId();
-		File itemFile = new File(itemUri);
-		String relativePathToManifest = unzippedDirRoot.toPath().relativize(itemFile.toPath()).toString();
-		
-		ResourceType resource = manifestBuilder.getResourceTypeByHref(relativePathToManifest);
-		if(resource != null) {
-			List<Interaction> interactions = item.getItemBody().findInteractions();
-			List<String> interactionNames = new ArrayList<>(interactions.size());
-			for(Interaction interaction:interactions) {
-				String interactionName = interaction.getQtiClassName();
-				interactionNames.add(interactionName);
-			}
-			manifestBuilder.setQtiMetadata(resource, interactionNames);
-			if(questionType != null) {
-				manifestBuilder.setOpenOLATMetadata(resource, questionType.getPrefix());
-			}
-			manifestBuilder.write(new File(unzippedDirRoot, "imsmanifest.xml"));
-		}
+	private void doSaveManifest() {
+		this.manifestBuilder.write(new File(unzippedDirRoot, "imsmanifest.xml"));
 	}
 	
 	private void doUpdate(Identifier identifier, String newTitle) {
@@ -598,8 +589,9 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 				currentEditorCtrl = new BadResourceController(ureq, getWindowControl(),
 						item.getItemLookup().getBadResourceException(), unzippedDirRoot, itemRef.getHref());
 			} else {
+				ManifestMetadataBuilder metadata = getMetadataBuilder(itemRef);
 				currentEditorCtrl = new AssessmentItemEditorController(ureq, getWindowControl(), testEntry,
-						item, itemRef, unzippedDirRoot);
+						item, itemRef, metadata, unzippedDirRoot);
 			}
 		}
 		
@@ -610,4 +602,12 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 			mainVC.put("content", new Panel("empty"));
 		}
 	}
+	
+	private ManifestMetadataBuilder getMetadataBuilder(AssessmentItemRef itemRef) {
+		URI itemUri = resolvedAssessmentTest.getResolvedAssessmentItem(itemRef).getItemLookup().getSystemId();
+		File itemFile = new File(itemUri);
+		String relativePathToManifest = unzippedDirRoot.toPath().relativize(itemFile.toPath()).toString();
+		ResourceType resource = manifestBuilder.getResourceTypeByHref(relativePathToManifest);
+		return manifestBuilder.getMetadataBuilder(resource, true);
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/MetadataEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/MetadataEditorController.java
new file mode 100644
index 0000000000000000000000000000000000000000..46f765e380fc717aef729272a0320ae455a18b6e
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/MetadataEditorController.java
@@ -0,0 +1,77 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.ims.qti21.ui.editor;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.TextElement;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.ims.qti21.model.xml.ManifestMetadataBuilder;
+
+/**
+ * 
+ * Initial date: 23.02.2016<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class MetadataEditorController extends FormBasicController {
+	
+	private TextElement titleEl, descriptionEl;
+	//keywords, language
+	
+	private final ManifestMetadataBuilder metadataBuilder;
+	
+	public MetadataEditorController(UserRequest ureq, WindowControl wControl, ManifestMetadataBuilder metadataBuilder) {
+		super(ureq, wControl);
+		this.metadataBuilder = metadataBuilder;
+		initForm(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		String title = metadataBuilder.getTitle();
+		titleEl = uifactory.addTextElement("title", "form.metadata.title", 256, title, formLayout);
+		
+		String description = metadataBuilder.getDescription();
+		descriptionEl = uifactory.addTextAreaElement("description", "form.metadata.description", 4000, 4, 60, true, description, formLayout);
+		
+		// Submit Button
+		FormLayoutContainer buttonsContainer = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
+		buttonsContainer.setRootForm(mainForm);
+		formLayout.add(buttonsContainer);
+		uifactory.addFormSubmitButton("submit", buttonsContainer);
+	}
+
+	@Override
+	protected void doDispose() {
+		//
+	}
+	
+	@Override
+	protected void formOK(UserRequest ureq) {
+		metadataBuilder.setTitle(titleEl.getValue(), "en");
+		metadataBuilder.setDescription(descriptionEl.getValue(), "en");
+		fireEvent(ureq, Event.CHANGED_EVENT);
+	}
+}
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
index ea8bdde7f273d2cb4f511b7b9540d8a89aac1cda..484b32caac2f6e3da995bc12859fecc03bc650a7 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
@@ -26,6 +26,9 @@ form.imd.incorrect.title=Incorrect title
 form.imd.incorrect.text=Incorrect feedback
 form.imd.rubric=Rubric
 form.imd.shuffle=Shuffle
+form.metadata=Metadata
+form.metadata.title=Title
+form.metadata.description=Description
 form.score=Score
 form.section.shuffle=Random order of questions?
 form.section.selection_pre=Number of questions in this section
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/events/AssessmentItemEvent.java b/src/main/java/org/olat/ims/qti21/ui/editor/events/AssessmentItemEvent.java
index 3999384c8dda2a66cc20ba0f0516510c90db13b5..69d2a16c6a35a3c09e2f3d1923090bb81cfe9343 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/events/AssessmentItemEvent.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/events/AssessmentItemEvent.java
@@ -36,6 +36,7 @@ public class AssessmentItemEvent extends Event {
 	private static final long serialVersionUID = -1768118856227595311L;
 	
 	public static final String ASSESSMENT_ITEM_CHANGED = "assessment-item-changed";
+	public static final String ASSESSMENT_ITEM_METADATA_CHANGED = "assessment-item-metadata-changed";
 	
 	private AssessmentItem item;
 	private AssessmentItemRef itemRef;
diff --git a/src/main/java/org/olat/modules/qpool/QPoolSPI.java b/src/main/java/org/olat/modules/qpool/QPoolSPI.java
index 7352397302c1d791185da8ccf0ea249791a37954..e87e5a72c7c2d5428679172dff4aeaa0e1018650 100644
--- a/src/main/java/org/olat/modules/qpool/QPoolSPI.java
+++ b/src/main/java/org/olat/modules/qpool/QPoolSPI.java
@@ -69,7 +69,7 @@ public interface QPoolSPI {
 	 * Export a test
 	 * @param items
 	 */
-	public MediaResource exportTest(List<QuestionItemShort> items, ExportFormatOptions format);
+	public MediaResource exportTest(List<QuestionItemShort> items, ExportFormatOptions format, Locale locale);
 	
 	/**
 	 * Export the item to the Zip
@@ -77,7 +77,7 @@ public interface QPoolSPI {
 	 * @param zout
 	 * @param names Collection of the file names used in the ZIP
 	 */
-	public void exportItem(QuestionItemFull item, ZipOutputStream zout, Set<String> names);
+	public void exportItem(QuestionItemFull item, ZipOutputStream zout, Locale locale, Set<String> names);
 	
 	/**
 	 * Copy the item attachment...
diff --git a/src/main/java/org/olat/modules/qpool/QPoolService.java b/src/main/java/org/olat/modules/qpool/QPoolService.java
index 9155f49a6329de15559bc16abb75ea019086dcfe..1204ad9f9ad8c7e24183935c5eeede5c42a5fcc3 100644
--- a/src/main/java/org/olat/modules/qpool/QPoolService.java
+++ b/src/main/java/org/olat/modules/qpool/QPoolService.java
@@ -88,7 +88,7 @@ public interface QPoolService {
 	public void removeAuthors(List<Identity> authors, List<QuestionItemShort> items);
 	
 	//import / export
-	public MediaResource export(List<QuestionItemShort> items, ExportFormatOptions format);
+	public MediaResource export(List<QuestionItemShort> items, ExportFormatOptions format, Locale locale);
 	
 	/**
 	 * 
@@ -96,7 +96,7 @@ public interface QPoolService {
 	 * @param zout
 	 * @param names Collection of the names used in the ZIP dd
 	 */
-	public void exportItem(QuestionItemShort item, ZipOutputStream zout, Set<String> names);
+	public void exportItem(QuestionItemShort item, ZipOutputStream zout, Locale locale, Set<String> names);
 	
 	public List<QuestionItem> importItems(Identity owner, Locale defaultLocale, String filename, File file);
 
diff --git a/src/main/java/org/olat/modules/qpool/manager/AbstractExportTestResource.java b/src/main/java/org/olat/modules/qpool/manager/AbstractExportTestResource.java
index f85475edfde70ea8a1f6d2e210f098f03ab6ccf9..0123b493594dc98bd623998eba357f383a83e590 100644
--- a/src/main/java/org/olat/modules/qpool/manager/AbstractExportTestResource.java
+++ b/src/main/java/org/olat/modules/qpool/manager/AbstractExportTestResource.java
@@ -22,6 +22,7 @@ package org.olat.modules.qpool.manager;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
+import java.util.Locale;
 import java.util.zip.ZipOutputStream;
 
 import javax.servlet.http.HttpServletResponse;
@@ -44,13 +45,19 @@ public abstract class AbstractExportTestResource implements MediaResource {
 	private static final OLog log = Tracing.createLoggerFor(AbstractExportTestResource.class);
 	
 	private String encoding;
+	private final Locale locale;
 	private final List<QuestionItemShort> items;
 	
-	public AbstractExportTestResource(String encoding, List<QuestionItemShort> items) {
+	public AbstractExportTestResource(String encoding, Locale locale, List<QuestionItemShort> items) {
 		this.encoding = encoding;
+		this.locale = locale;
 		this.items = items;
 	}
 	
+	public Locale getLocale() {
+		return locale;
+	}
+	
 	@Override
 	public boolean acceptRanges() {
 		return false;
diff --git a/src/main/java/org/olat/modules/qpool/manager/AbstractQPoolServiceProvider.java b/src/main/java/org/olat/modules/qpool/manager/AbstractQPoolServiceProvider.java
index 3f2ad1f257017e87ba0615adec39dc74b92ebbf3..9f19e2f9858a33a59d37e757db4127a7f11795fb 100644
--- a/src/main/java/org/olat/modules/qpool/manager/AbstractQPoolServiceProvider.java
+++ b/src/main/java/org/olat/modules/qpool/manager/AbstractQPoolServiceProvider.java
@@ -143,12 +143,12 @@ public abstract class AbstractQPoolServiceProvider implements QPoolSPI {
 	}
 
 	@Override
-	public MediaResource exportTest(List<QuestionItemShort> items, ExportFormatOptions format) {
+	public MediaResource exportTest(List<QuestionItemShort> items, ExportFormatOptions format, Locale locale) {
 		return null;//Zip are made by qpool service
 	}
 
 	@Override
-	public void exportItem(QuestionItemFull item, ZipOutputStream zout, Set<String> names) {
+	public void exportItem(QuestionItemFull item, ZipOutputStream zout, Locale locale, Set<String> names) {
 		String directory = item.getDirectory();
 		VFSContainer itemDir = getFileStorage().getContainer(directory);
 		VFSItem file = itemDir.resolve(item.getRootFilename());
diff --git a/src/main/java/org/olat/modules/qpool/manager/ExportQItemResource.java b/src/main/java/org/olat/modules/qpool/manager/ExportQItemResource.java
index 6244b09f88db4b53d065433c316dc3e252093b16..ef45d167b85532fb12efa8731977f9ec98577d45 100644
--- a/src/main/java/org/olat/modules/qpool/manager/ExportQItemResource.java
+++ b/src/main/java/org/olat/modules/qpool/manager/ExportQItemResource.java
@@ -22,6 +22,7 @@ package org.olat.modules.qpool.manager;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.HashSet;
+import java.util.Locale;
 import java.util.Set;
 import java.util.zip.ZipOutputStream;
 
@@ -47,10 +48,12 @@ public class ExportQItemResource implements MediaResource {
 	private static final OLog log = Tracing.createLoggerFor(ExportQItemResource.class);
 	
 	private String encoding;
+	private final Locale locale;
 	private final QuestionItemShort item;
 	
-	public ExportQItemResource(String encoding, QuestionItemShort item) {
+	public ExportQItemResource(String encoding, Locale locale, QuestionItemShort item) {
 		this.encoding = encoding;
+		this.locale = locale;
 		this.item = item;
 	}
 	
@@ -99,7 +102,7 @@ public class ExportQItemResource implements MediaResource {
 			zout.setLevel(9);
 			Set<String> names = new HashSet<String>();
 			QPoolService qpoolService = CoreSpringFactory.getImpl(QPoolService.class);
-			qpoolService.exportItem(item, zout, names);
+			qpoolService.exportItem(item, zout, locale, names);
 		} catch (IOException e) {
 			log.error("", e);
 		} finally {
diff --git a/src/main/java/org/olat/modules/qpool/manager/ExportQItemsZipResource.java b/src/main/java/org/olat/modules/qpool/manager/ExportQItemsZipResource.java
index 6edd61b94e3f5473451ce829d2bb7f24f129fcd8..c0e802a53f7940fd351c549a5e1c70aa6e474b91 100644
--- a/src/main/java/org/olat/modules/qpool/manager/ExportQItemsZipResource.java
+++ b/src/main/java/org/olat/modules/qpool/manager/ExportQItemsZipResource.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Set;
 import java.util.zip.ZipOutputStream;
 
@@ -48,10 +49,12 @@ public class ExportQItemsZipResource implements MediaResource {
 	private static final OLog log = Tracing.createLoggerFor(ExportQItemsZipResource.class);
 	
 	private String encoding;
+	private final Locale locale;
 	private final List<QuestionItemFull> items;
 	
-	public ExportQItemsZipResource(String encoding, List<QuestionItemFull> items) {
+	public ExportQItemsZipResource(String encoding, Locale locale, List<QuestionItemFull> items) {
 		this.encoding = encoding;
+		this.locale = locale;
 		this.items = items;
 	}
 	
@@ -101,7 +104,7 @@ public class ExportQItemsZipResource implements MediaResource {
 			Set<String> names = new HashSet<String>();
 			QPoolService qpoolService = CoreSpringFactory.getImpl(QPoolService.class);
 			for(QuestionItemFull item:items) {
-				qpoolService.exportItem(item, zout, names);
+				qpoolService.exportItem(item, zout, locale, names);
 			}
 		} catch (IOException e) {
 			log.error("", e);
diff --git a/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java b/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java
index c7b7e89b084e117ae48c3432e72234af1ab73b52..14f21a8fc3a791fc5ee6acd9ad9afa5e9a370b5f 100644
--- a/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java
+++ b/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java
@@ -223,12 +223,12 @@ public class QuestionPoolServiceImpl implements QPoolService {
 	}
 	
 	@Override
-	public MediaResource export(List<QuestionItemShort> items, ExportFormatOptions format) {
+	public MediaResource export(List<QuestionItemShort> items, ExportFormatOptions format, Locale locale) {
 		MediaResource mr = null;
 		if(DefaultExportFormat.ZIP_EXPORT_FORMAT.equals(format)) {
 			List<Long> keys = toKeys(items);
 			List<QuestionItemFull> fullItems = questionItemDao.loadByIds(keys);
-			mr = new ExportQItemsZipResource("UTF-8", fullItems);
+			mr = new ExportQItemsZipResource("UTF-8", locale, fullItems);
 			//make a zip with all items
 		} else {
 			QPoolSPI selectedSp = null;
@@ -241,7 +241,7 @@ public class QuestionPoolServiceImpl implements QPoolService {
 			}
 			
 			if(selectedSp != null) {
-				mr = selectedSp.exportTest(items, format);
+				mr = selectedSp.exportTest(items, format, locale);
 			}
 		}
 		return mr;
@@ -257,7 +257,7 @@ public class QuestionPoolServiceImpl implements QPoolService {
 	}
 
 	@Override
-	public void exportItem(QuestionItemShort item, ZipOutputStream zout, Set<String> names) {
+	public void exportItem(QuestionItemShort item, ZipOutputStream zout, Locale locale, Set<String> names) {
 		QPoolSPI provider = qpoolModule.getQuestionPoolProvider(item.getFormat());
 		if(provider == null) {
 			log.error("Not found provider for this format: " + item.getFormat());
@@ -268,7 +268,7 @@ public class QuestionPoolServiceImpl implements QPoolService {
 			} else {
 				fullItem = questionItemDao.loadById(item.getKey());
 			}
-			provider.exportItem(fullItem, zout, names);
+			provider.exportItem(fullItem, zout, locale, names);
 		}
 	}
 
diff --git a/src/main/java/org/olat/modules/qpool/ui/QuestionItemDetailsController.java b/src/main/java/org/olat/modules/qpool/ui/QuestionItemDetailsController.java
index fb0e3ba3f86c0e05ce4c11c53b91cd6757fdd982..db211d312dbc3db33ddfa9f77e3ac805c0bc61bc 100644
--- a/src/main/java/org/olat/modules/qpool/ui/QuestionItemDetailsController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/QuestionItemDetailsController.java
@@ -280,7 +280,7 @@ public class QuestionItemDetailsController extends BasicController implements Br
 	}
 	
 	private void doExport(UserRequest ureq, QuestionItemShort item) {
-		ExportQItemResource mr = new ExportQItemResource("UTF-8", item);
+		ExportQItemResource mr = new ExportQItemResource("UTF-8", getLocale(), item);
 		ureq.getDispatchResult().setResultingMediaResource(mr);
 	}
 }
diff --git a/src/main/java/org/olat/modules/qpool/ui/QuestionListController.java b/src/main/java/org/olat/modules/qpool/ui/QuestionListController.java
index 6f784913e34d0943b09d84a4f689aeb332a09c9e..63724a4e44c87c660229f462315a278dcddee953 100644
--- a/src/main/java/org/olat/modules/qpool/ui/QuestionListController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/QuestionListController.java
@@ -741,7 +741,7 @@ public class QuestionListController extends AbstractItemListController implement
 		List<QuestionItemShort> items = (List<QuestionItemShort>)runContext.get("itemsToExport");
 		switch(format.getOutcome()) {
 			case download: {
-				MediaResource mr = qpoolService.export(items, format);
+				MediaResource mr = qpoolService.export(items, format, getLocale());
 				if(mr != null) {
 					ureq.getDispatchResult().setResultingMediaResource(mr);
 				}
diff --git a/src/test/java/org/olat/ims/qti21/pool/QTI12To21ConverterTest.java b/src/test/java/org/olat/ims/qti21/pool/QTI12To21ConverterTest.java
index bc7a84788060d3e5fafe7c384a9df9d470e26f1c..f8887b9968f73d12e4f23f16b1134a3569e31c6d 100644
--- a/src/test/java/org/olat/ims/qti21/pool/QTI12To21ConverterTest.java
+++ b/src/test/java/org/olat/ims/qti21/pool/QTI12To21ConverterTest.java
@@ -22,6 +22,7 @@ package org.olat.ims.qti21.pool;
 import java.io.File;
 import java.io.InputStream;
 import java.net.URISyntaxException;
+import java.util.Locale;
 
 import org.dom4j.Document;
 import org.junit.Test;
@@ -47,7 +48,7 @@ public class QTI12To21ConverterTest {
 		QTIDocument doc = loadDocument("qti12_4questiontypes.xml");
 		File exportDir = new File("/HotCoffee/QTI/today/");
 		exportDir.mkdirs();
-		QTI12To21Converter converter = new QTI12To21Converter(exportDir);
+		QTI12To21Converter converter = new QTI12To21Converter(exportDir, Locale.ENGLISH);
 		
 		converter.convert(doc);