diff --git a/openbis/.settings/.gitignore b/openbis/.settings/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
index a516f3a348df3c6a257dc1ef9523c950be94189a..1e78b91ba288a1de22fd854d4c18053f17c549ba 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
@@ -171,7 +171,8 @@ public interface ICommonClientService extends IClientService
     /**
      * Returns a list of all persons which belong to the current database instance.
      */
-    public TypedTableResultSet<Person> listPersons(ListPersonsCriteria criteria) throws UserFailureException;
+    public TypedTableResultSet<Person> listPersons(ListPersonsCriteria criteria)
+            throws UserFailureException;
 
     /**
      * Returns a list of persons registered in given database instance.
@@ -181,7 +182,8 @@ public interface ICommonClientService extends IClientService
     /**
      * Like {@link #prepareExportSamples(TableExportCriteria)}, but for persons.
      */
-    public String prepareExportPersons(final TableExportCriteria<TableModelRowWithObject<Person>> criteria)
+    public String prepareExportPersons(
+            final TableExportCriteria<TableModelRowWithObject<Person>> criteria)
             throws UserFailureException;
 
     /**
@@ -541,6 +543,13 @@ public interface ICommonClientService extends IClientService
     public void addVocabularyTerms(TechId vocabularyId, List<String> vocabularyTerms,
             Long previousTermOrdinal) throws UserFailureException;
 
+    /**
+     * Adds specified unofficial terms to the specified vocabulary after specified ordinal (first
+     * shift all terms with bigger ordinal).
+     */
+    public void addUnofficialVocabularyTerms(TechId vocabularyId, List<String> vocabularyTerms,
+            Long previousTermOrdinal) throws UserFailureException;
+
     /**
      * Updates vocabulary term.
      */
@@ -553,6 +562,12 @@ public interface ICommonClientService extends IClientService
     public void deleteVocabularyTerms(TechId vocabularyId, List<VocabularyTerm> termsToBeDeleted,
             List<VocabularyTermReplacement> termsToBeReplaced) throws UserFailureException;
 
+    /**
+     * Makes given terms official
+     */
+    public void makeVocabularyTermsOfficial(TechId vocabularyId,
+            List<VocabularyTerm> termsToBeOfficial);
+
     /** Lists terms of a specified vocabulary */
     public List<VocabularyTerm> listVocabularyTerms(Vocabulary vocabulary)
             throws UserFailureException;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
index f5e30cb9037aec60336792465a5e788b085acd81..4e06d804084369327ad10bec89c1de9259ac5cb4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
@@ -324,12 +324,14 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
             AsyncCallback<String> callback);
 
     /** @see ICommonClientService#listSampleTypes(DefaultResultSetConfig) */
-    public void listSampleTypes(DefaultResultSetConfig<String, TableModelRowWithObject<SampleType>> criteria,
+    public void listSampleTypes(
+            DefaultResultSetConfig<String, TableModelRowWithObject<SampleType>> criteria,
             final AsyncCallback<TypedTableResultSet<SampleType>> asyncCallback)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException;
 
     /** @see ICommonClientService#prepareExportSampleTypes(TableExportCriteria) */
-    public void prepareExportSampleTypes(final TableExportCriteria<TableModelRowWithObject<SampleType>> criteria,
+    public void prepareExportSampleTypes(
+            final TableExportCriteria<TableModelRowWithObject<SampleType>> criteria,
             AsyncCallback<String> callback);
 
     /** @see ICommonClientService#listExperimentTypes(DefaultResultSetConfig) */
@@ -455,6 +457,10 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     public void addVocabularyTerms(TechId vocabularyId, List<String> vocabularyTerms,
             Long previousTermOrdinal, AsyncCallback<Void> callback);
 
+    /** @see ICommonClientService#addUnofficialVocabularyTerms(TechId, List, Long) */
+    public void addUnofficialVocabularyTerms(TechId vocabularyId, List<String> vocabularyTerms,
+            Long previousTermOrdinal, AsyncCallback<Void> callback);
+
     /** @see ICommonClientService#updateVocabularyTerm(IVocabularyTermUpdates) */
     public void updateVocabularyTerm(final IVocabularyTermUpdates updates,
             final AsyncCallback<Void> asyncCallback);
@@ -467,6 +473,10 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     public void deleteVocabularyTerms(TechId vocabularyId, List<VocabularyTerm> termsToBeDeleted,
             List<VocabularyTermReplacement> termsToBeReplaced, AsyncCallback<Void> callback);
 
+    /** @see ICommonClientService#makeVocabularyTermsOfficial(TechId, List) */
+    public void makeVocabularyTermsOfficial(TechId vocabularyId,
+            List<VocabularyTerm> termsToBeOfficial, AsyncCallback<Void> callback);
+
     /** @see ICommonClientService#listVocabularyTerms(Vocabulary) */
     public void listVocabularyTerms(Vocabulary vocabulary,
             AsyncCallback<List<VocabularyTerm>> callback);
@@ -887,5 +897,4 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
      */
     public void evaluate(DynamicPropertyEvaluationInfo dynamicPropertyEvaluationInfo,
             AsyncCallback<String> callback);
-
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
index 9638c2c3b02f64853c1eb30d507c46695778f078..dd85ab630cf55152f6748d69a7ceca2203c3a365 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
@@ -721,6 +721,18 @@ public abstract class Dict
 
     public static final String EDIT_VOCABULARY_TERM_BUTTON = "edit_vocabulary_term_button";
 
+    public static final String MAKE_OFFICIAL_VOCABULARY_TERM_BUTTON =
+            "make_official_vocabulary_term_button";
+
+    public static final String MAKE_OFFICIAL_VOCABULARY_TERMS_CONFIRMATION_TITLE =
+            "make_official_vocabulary_terms_confirmation_title";
+
+    public static final String MAKE_OFFICIAL_VOCABULARY_TERMS_CONFIRMATION_MESSAGE_SINGULAR =
+            "make_official_vocabulary_terms_confirmation_message_singular";
+
+    public static final String MAKE_OFFICIAL_VOCABULARY_TERMS_CONFIRMATION_MESSAGE =
+            "make_official_vocabulary_terms_confirmation_message";
+
     //
     // Group Browser
     //
@@ -1074,6 +1086,12 @@ public abstract class Dict
 
     public static final String MORE_RESULTS_FOUND_TITLE = "more_results_found_title";
 
+    public static final String ADD_UNOFFICIAL_VOCABULARY_TERM_DIALOG_TITLE =
+            "add_unofficial_vocabulary_term_dialog_title";
+
+    public static final String ADD_UNOFFICIAL_VOCABULARY_TERM_DIALOG_MESSAGE =
+            "add_unofficial_vocabulary_term_dialog_message";
+
     // Material Viewer
 
     public static final String MATERIAL_PROPERTIES_HEADING = "material_properties_heading";
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/VocabularyTermModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/VocabularyTermModel.java
index 2515e0b7e52090488d9a66074b2b7fb7d5eda7e2..a43f2d289b6481e0db229469e104f778ef7cd45d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/VocabularyTermModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/VocabularyTermModel.java
@@ -21,6 +21,8 @@ import java.util.Collections;
 import java.util.List;
 
 import com.extjs.gxt.ui.client.data.ModelData;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.renderer.VocabularyPropertyColRenderer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
@@ -35,17 +37,34 @@ public class VocabularyTermModel extends SimplifiedBaseModel implements
 {
     private static final String ORDINAL = "ordinal";
 
+    private static final String IS_OFFICIAL = "is_official";
+
+    public static final String DISPLAY_FIELD = "display_field";
+
     private static final long serialVersionUID = 1L;
 
     public VocabularyTermModel(VocabularyTerm term)
     {
         set(ModelDataPropertyNames.CODE, term.getCode());
         set(ORDINAL, term.getOrdinal());
+        set(IS_OFFICIAL, term.isOfficial());
         set(ModelDataPropertyNames.CODE_WITH_LABEL, term.getCodeOrLabel());
+        set(DISPLAY_FIELD, generateDisplatField(term));
         set(ModelDataPropertyNames.TOOLTIP, VocabularyPropertyColRenderer.renderAsTooltip(term));
         set(ModelDataPropertyNames.OBJECT, term);
     }
 
+    public String generateDisplatField(VocabularyTerm term)
+    {
+        final Element span = DOM.createSpan();
+        if (false == term.isOfficial())
+        {
+            span.setAttribute("style", "color: grey; font-style:italic");
+        }
+        span.setInnerHTML(term.getCodeOrLabel());
+        return DOM.toString(span);
+    }
+
     public static final List<VocabularyTermModel> convert(List<VocabularyTerm> terms)
     {
         final ArrayList<VocabularyTermModel> list = new ArrayList<VocabularyTermModel>();
@@ -65,10 +84,15 @@ public class VocabularyTermModel extends SimplifiedBaseModel implements
     //
     // Comparable
     //
-
     public int compareTo(VocabularyTermModel o)
     {
-        return getValueToCompare().compareTo(o.getValueToCompare());
+        if (isOfficial() == o.isOfficial())
+        {
+            return getValueToCompare().compareTo(o.getValueToCompare());
+        } else
+        {
+            return isOfficial() ? -1 : 1;
+        }
     }
 
     /** @return value that will be used to compare Vocabulary Terms and display them in order */
@@ -77,4 +101,8 @@ public class VocabularyTermModel extends SimplifiedBaseModel implements
         return get(ORDINAL);
     }
 
+    private Boolean isOfficial()
+    {
+        return get(IS_OFFICIAL);
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/VocabularyPropertyColRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/VocabularyPropertyColRenderer.java
index 103f80748f500f5a1f266921d444a9fce24ef9f3..6e298d1315342307e146b90b7aa472892cd78cd4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/VocabularyPropertyColRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/renderer/VocabularyPropertyColRenderer.java
@@ -65,7 +65,16 @@ public class VocabularyPropertyColRenderer<T extends IEntityPropertiesHolder> ex
         {
             result = ExternalHyperlink.createAnchorString(result, url);
         }
-        result = MultilineHTML.wrapUpInDivWithTooltip(result, description);
+
+        if (term.isOfficial() == null || term.isOfficial())
+        {
+            result = MultilineHTML.wrapUpInDivWithTooltip(result, description);
+        } else
+        {
+            result =
+                    MultilineHTML.wrapUpInDivWithTooltip(result, description,
+                            "color: grey; font-style:italic");
+        }
 
         return result;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/VocabularyTermSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/VocabularyTermSelectionWidget.java
index aebcbbf54674296f00ffbf4c496877f33d353554..85d63c1a7316c576fb21f32d089fc373fb11a7e0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/VocabularyTermSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/VocabularyTermSelectionWidget.java
@@ -17,20 +17,36 @@
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import com.extjs.gxt.ui.client.event.BaseEvent;
+import com.extjs.gxt.ui.client.event.Events;
+import com.extjs.gxt.ui.client.event.Listener;
+import com.extjs.gxt.ui.client.widget.Dialog;
+import com.extjs.gxt.ui.client.widget.Label;
+import com.extjs.gxt.ui.client.widget.button.Button;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+import ch.systemsx.cisd.common.shared.basic.utils.StringUtils;
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.VocabularyTermModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.CodeField.CodeFieldKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.AbstractRegistrationDialog;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.DropDownList;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GWTUtils;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * @author Izabela Adamczyk
@@ -39,6 +55,54 @@ public class VocabularyTermSelectionWidget extends
         DropDownList<VocabularyTermModel, VocabularyTerm>
 {
 
+    private class UnofficialTermRegistrationDialog extends AbstractRegistrationDialog
+    {
+        private final IViewContext<ICommonClientServiceAsync> viewContext;
+
+        private final String code;
+
+        private final Vocabulary vocabulary;
+
+        public UnofficialTermRegistrationDialog(
+                IViewContext<ICommonClientServiceAsync> viewContext, String code)
+        {
+            super(viewContext, viewContext
+                    .getMessage(Dict.ADD_UNOFFICIAL_VOCABULARY_TERM_DIALOG_TITLE),
+                    createRefreshAction(code));
+
+            this.viewContext = viewContext;
+            this.code = code;
+            this.vocabulary = vocabularyOrNull;
+
+            addField(new Label(viewContext.getMessage(
+                    Dict.ADD_UNOFFICIAL_VOCABULARY_TERM_DIALOG_MESSAGE, code, vocabulary.getCode())));
+        }
+
+        @Override
+        protected void register(AsyncCallback<Void> registrationCallback)
+        {
+            ICommonClientServiceAsync service = viewContext.getService();
+
+            service.addUnofficialVocabularyTerms(TechId.create(vocabulary), Arrays.asList(code),
+                    getMaxOrdinal(), registrationCallback);
+            hide();
+        }
+
+        private long getMaxOrdinal()
+        {
+            long result = 0l;
+
+            for (VocabularyTermModel term : VocabularyTermSelectionWidget.this.store.getModels())
+            {
+                if (term.getTerm().getOrdinal() > result)
+                {
+                    result = term.getTerm().getOrdinal();
+                }
+            }
+            return result;
+        }
+    }
+
     private static final String CHOOSE_MSG = "Choose...";
 
     private static final String VALUE_NOT_IN_LIST_MSG = "Value not in the list";
@@ -51,6 +115,8 @@ public class VocabularyTermSelectionWidget extends
 
     private String initialTermCodeOrNull;
 
+    private String typedValue = null;
+
     /**
      * Allows to choose one of the specified vocabulary's terms, is able to refresh the available
      * terms by calling the server.
@@ -73,7 +139,7 @@ public class VocabularyTermSelectionWidget extends
     }
 
     protected VocabularyTermSelectionWidget(String idSuffix, String label, boolean mandatory,
-            Vocabulary vocabularyOrNull, IViewContext<?> viewContextOrNull,
+            Vocabulary vocabularyOrNull, final IViewContext<?> viewContextOrNull,
             List<VocabularyTerm> termsOrNull, String initialTermCodeOrNull)
     {
         super(idSuffix, ModelDataPropertyNames.CODE_WITH_LABEL, label, CHOOSE_MSG, EMPTY_MSG,
@@ -87,8 +153,72 @@ public class VocabularyTermSelectionWidget extends
         {
             setTerms(termsOrNull);
         }
-        setTemplate(GWTUtils.getTooltipTemplate(ModelDataPropertyNames.CODE_WITH_LABEL,
+
+        setLazyRender(false);
+        setTemplate(GWTUtils.getTooltipTemplate(VocabularyTermModel.DISPLAY_FIELD,
                 ModelDataPropertyNames.TOOLTIP));
+
+        if (viewContextOrNull != null
+                && viewContextOrNull.getModel().getApplicationInfo().getWebClientConfiguration()
+                        .getAllowAddingUnofficialTerms())
+        {
+            this.addListener(Events.Blur, new Listener<BaseEvent>()
+                {
+                    public void handleEvent(BaseEvent be)
+                    {
+                        if (VocabularyTermSelectionWidget.this.vocabularyOrNull != null
+                                && VocabularyTermSelectionWidget.this.viewContextOrNull
+                                        .getService() instanceof ICommonClientServiceAsync
+                                && getSelection().size() != 1
+                                && (false == StringUtils.isBlank(VocabularyTermSelectionWidget.this
+                                        .getRawValue())))
+                        {
+                            final String code = getRawValue().toUpperCase();
+                            if (!code.matches(CodeFieldKind.CODE_WITH_COLON.getPattern()))
+                            {
+                                Dialog d = new Dialog()
+                                    {
+                                        @Override
+                                        protected void onButtonPressed(Button button)
+                                        {
+                                            super.onButtonPressed(button);
+                                            VocabularyTermSelectionWidget.this.focus();
+                                        }
+                                    };
+                                d.setHeading(viewContextOrNull.getMessage(Dict.MESSAGEBOX_ERROR));
+                                d.addText(viewContextOrNull.getMessage(Dict.INVALID_CODE_MESSAGE,
+                                        CodeFieldKind.CODE_WITH_COLON.getAllowedCharacters()));
+                                d.setSize(400, 200);
+                                d.setHideOnButtonClick(true);
+                                d.setButtons(Dialog.OK);
+                                d.show();
+                            } else
+                            {
+                                @SuppressWarnings("unchecked")
+                                UnofficialTermRegistrationDialog d =
+                                        new UnofficialTermRegistrationDialog(
+                                                (IViewContext<ICommonClientServiceAsync>) viewContextOrNull,
+                                                code);
+                                d.show();
+                            }
+                        }
+                    }
+                });
+        }
+    }
+
+    private IDelegatedAction createRefreshAction(final String _typedValue)
+    {
+        return new IDelegatedAction()
+            {
+                public void execute()
+                {
+                    VocabularyTermSelectionWidget.this.typedValue = _typedValue;
+                    refreshStore();
+                    clearInvalid();
+                    focus();
+                }
+            };
     }
 
     public void setVocabulary(Vocabulary vocabulary)
@@ -130,7 +260,17 @@ public class VocabularyTermSelectionWidget extends
 
     public void selectInitialValue()
     {
-        if (initialTermCodeOrNull != null)
+        if (typedValue != null)
+        {
+            try
+            {
+                trySelectByCode(typedValue);
+                updateOriginalValue();
+            } finally
+            {
+                typedValue = null;
+            }
+        } else if (initialTermCodeOrNull != null)
         {
             trySelectByCode(initialTermCodeOrNull);
             updateOriginalValue();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java
index a24f82ddec373bd1898d70ee56ef8ab8baba6f50..c2c96397c2166915ccce2f2f5c2ac223219fb56b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java
@@ -205,6 +205,21 @@ public class VocabularyTermGrid extends TypedTableGrid<VocabularyTermWithStats>
                             });
         addButton(deleteButton);
 
+        if (getWebClientConfiguration().getAllowAddingUnofficialTerms())
+        {
+            Button makeOfficialButton =
+                    new Button(viewContext.getMessage(Dict.MAKE_OFFICIAL_VOCABULARY_TERM_BUTTON),
+                            new SelectionListener<ButtonEvent>()
+                                {
+                                    @Override
+                                    public void componentSelected(ButtonEvent ce)
+                                    {
+                                        makeOfficial();
+                                    }
+                                });
+            addButton(makeOfficialButton);
+        }
+
         if (vocabulary.isManagedInternally())
         {
             String tooltip = viewContext.getMessage(Dict.TOOLTIP_VOCABULARY_MANAGED_INTERNALLY);
@@ -657,6 +672,54 @@ public class VocabularyTermGrid extends TypedTableGrid<VocabularyTermWithStats>
         }
     }
 
+    private void makeOfficial()
+    {
+        List<BaseEntityModel<TableModelRowWithObject<VocabularyTermWithStats>>> terms =
+                getSelectedItems();
+        if (terms.isEmpty())
+        {
+            return;
+        }
+
+        Set<String> selectedTerms = new HashSet<String>();
+        final List<VocabularyTerm> termsToBeOfficial = new ArrayList<VocabularyTerm>();
+        for (BaseEntityModel<TableModelRowWithObject<VocabularyTermWithStats>> model : terms)
+        {
+            VocabularyTerm term = model.getBaseObject().getObjectOrNull().getTerm();
+            selectedTerms.add(term.getCode());
+            termsToBeOfficial.add(term);
+        }
+
+        String title =
+                viewContext.getMessage(Dict.MAKE_OFFICIAL_VOCABULARY_TERMS_CONFIRMATION_TITLE);
+        int size = termsToBeOfficial.size();
+        String message;
+        if (size == 1)
+        {
+            message =
+                    viewContext
+                            .getMessage(Dict.MAKE_OFFICIAL_VOCABULARY_TERMS_CONFIRMATION_MESSAGE_SINGULAR);
+        } else
+        {
+            message =
+                    viewContext.getMessage(
+                            Dict.MAKE_OFFICIAL_VOCABULARY_TERMS_CONFIRMATION_MESSAGE, size);
+        }
+        ConfirmationDialog confirmationDialog = new ConfirmationDialog(title, message)
+            {
+                @Override
+                protected void onYes()
+                {
+                    RefreshCallback callback = new RefreshCallback(viewContext);
+                    viewContext.getService().makeVocabularyTermsOfficial(TechId.create(vocabulary),
+                            termsToBeOfficial, callback);
+
+                }
+            };
+        confirmationDialog.show();
+
+    }
+
     private List<VocabularyTerm> getTerms()
     {
         List<VocabularyTerm> terms = new ArrayList<VocabularyTerm>();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/DropDownList.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/DropDownList.java
index 6c4d5b0a26e24ac4047c6f7a86047fc163b9f11c..7a8c7c90234f6fbf265185b94d7d5e5b00d27228 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/DropDownList.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/DropDownList.java
@@ -144,7 +144,6 @@ abstract public class DropDownList<M extends ModelData, E> extends ComboBox<M> i
             };
         ListStore<M> newStore = new ListStore<M>()
             {
-
                 @Override
                 public void filter(String property, String beginsWith)
                 {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/MultilineHTML.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/MultilineHTML.java
index 53485ee26eb712dacd9dd38d054176887d0cf254..54eaa759f656ebcffa21b8508624ba25e6cafc9c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/MultilineHTML.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/MultilineHTML.java
@@ -68,11 +68,19 @@ public final class MultilineHTML extends HTML
     }
 
     public static String wrapUpInDivWithTooltip(String text, String tooltip)
+    {
+        return wrapUpInDivWithTooltip(text, tooltip, null);
+    }
+
+    public static String wrapUpInDivWithTooltip(String text, String tooltip, String styleOrNull)
     {
         final Element div = DOM.createDiv();
         div.setInnerHTML(text);
+        if (styleOrNull != null)
+        {
+            div.setAttribute("style", styleOrNull);
+        }
         div.setTitle(StringEscapeUtils.unescapeHtml(tooltip));
         return DOM.toString(div);
     }
-
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
index c14c575b1a0255d76fed8798c64c6ae72d8ddd22..a97e2dcf14b69cbfa57806a60d4d63693c5947ac 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
@@ -770,13 +770,13 @@ public final class CommonClientService extends AbstractClientService implements
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
         return listEntities(new EntityTypeProvider<MaterialType>(commonServer, getSessionToken())
+            {
+                @Override
+                protected List<MaterialType> listTypes()
                 {
-                    @Override
-                    protected List<MaterialType> listTypes()
-                    {
-                        return commonServer.listMaterialTypes(sessionToken);
-                    }
-                }, criteria);
+                    return commonServer.listMaterialTypes(sessionToken);
+                }
+            }, criteria);
     }
 
     public TypedTableResultSet<SampleType> listSampleTypes(
@@ -1277,6 +1277,26 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
+    public void addUnofficialVocabularyTerms(TechId vocabularyId, List<String> vocabularyTerms,
+            Long previousTermOrdinal)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        assert vocabularyId != null : "Unspecified vocabulary id.";
+
+        if (vocabularyTerms != null && vocabularyTerms.isEmpty() == false)
+        {
+            try
+            {
+                final String sessionToken = getSessionToken();
+                commonServer.addUnofficialVocabularyTerms(sessionToken, vocabularyId,
+                        vocabularyTerms, previousTermOrdinal);
+            } catch (final UserFailureException e)
+            {
+                throw UserFailureExceptionTranslator.translate(e);
+            }
+        }
+    }
+
     public void deleteVocabularyTerms(TechId vocabularyId, List<VocabularyTerm> termsToBeDeleted,
             List<VocabularyTermReplacement> termsToBeReplaced)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
@@ -1296,6 +1316,22 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
+    public void makeVocabularyTermsOfficial(TechId vocabularyId,
+            List<VocabularyTerm> termsToBeOfficial)
+    {
+        assert vocabularyId != null : "Unspecified vocabulary id.";
+        assert termsToBeOfficial != null : "Unspecified term to be official.";
+
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.makeVocabularyTermsOfficial(sessionToken, vocabularyId, termsToBeOfficial);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
     public List<VocabularyTerm> listVocabularyTerms(Vocabulary vocabulary)
     {
         try
@@ -2638,5 +2674,4 @@ public final class CommonClientService extends AbstractClientService implements
             throw UserFailureExceptionTranslator.translate(e);
         }
     }
-
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/WebClientConfigurationProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/WebClientConfigurationProvider.java
index de17ea64efa65b33baf97da87e53dc09d3c39457..b9c69af4c09179d2104dbc9a35acbd9e488565d8 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/WebClientConfigurationProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/WebClientConfigurationProvider.java
@@ -56,20 +56,24 @@ public class WebClientConfigurationProvider
     private static final String DEFAULT_VIEW_MODE = "default-view-mode";
 
     private static final ViewMode DEFAULT_VIEW_MODE_VALUE = ViewMode.NORMAL;
-    
+
     private static final String DEFAULT_ANONYMOUS_LOGIN = "default-anonymous-login";
 
     private static final String MAX_VISIBLE_COLUMNS = "max-visible-columns";
-    
+
     private static final int DEFAULT_MAX_VISIBLE_COLUMNS = 50;
 
     private static final String MAX_ENTITY_VISITS = "max-entity-visits";
-    
+
     private static final int DEFAULT_MAX_ENTITY_VISITS = 20;
-    
+
     private static final String DATA_SET_TYPES_WITH_IMAGE_OVERVIEW =
             "data-set-types-with-image-overview";
 
+    private static final String ALLOW_ADDING_UNOFFICIAL_TERMS = "allow-adding-unofficial-terms";
+
+    private static final boolean DEFAULT_ALLOW_ADDING_UNOFFICIAL_TERMS = false;
+
     static final String TECHNOLOGIES = "technologies";
 
     private WebClientConfiguration webClientConfiguration = new WebClientConfiguration();
@@ -96,6 +100,7 @@ public class WebClientConfigurationProvider
         webClientConfiguration.setDefaultViewMode(DEFAULT_VIEW_MODE_VALUE);
         webClientConfiguration.setMaxVisibleColumns(DEFAULT_MAX_VISIBLE_COLUMNS);
         webClientConfiguration.setMaxEntityVisits(DEFAULT_MAX_ENTITY_VISITS);
+        webClientConfiguration.setAllowAddingUnofficielTerms(DEFAULT_ALLOW_ADDING_UNOFFICIAL_TERMS);
     }
 
     private void init(Properties properties)
@@ -103,6 +108,8 @@ public class WebClientConfigurationProvider
         webClientConfiguration.setDefaultViewMode(extractDefaultViewMode(properties));
         webClientConfiguration.setDefaultAnonymousLogin(extractDefaultAnonymousLogin(properties));
         webClientConfiguration.setMaxVisibleColumns(extractMaxVisibleColumns(properties));
+        webClientConfiguration
+                .setAllowAddingUnofficielTerms(extractAllowAddingUnofficialTerms(properties));
         webClientConfiguration.setMaxEntityVisits(PropertyUtils.getInt(properties,
                 MAX_ENTITY_VISITS, DEFAULT_MAX_ENTITY_VISITS));
         webClientConfiguration
@@ -208,6 +215,11 @@ public class WebClientConfigurationProvider
         return PropertyUtils.getInt(properties, MAX_VISIBLE_COLUMNS, DEFAULT_MAX_VISIBLE_COLUMNS);
     }
 
+    private boolean extractAllowAddingUnofficialTerms(Properties properties)
+    {
+        return PropertyUtils.getBoolean(properties, ALLOW_ADDING_UNOFFICIAL_TERMS, false);
+    }
+
     public WebClientConfiguration getWebClientConfiguration()
     {
         return webClientConfiguration;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/VocabularyTermsProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/VocabularyTermsProvider.java
index fac647a6ce7d0ccb0584755ece42f81d423e55c0..a630c6085c4655cad3ac592033b7abdc5368c116 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/VocabularyTermsProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/VocabularyTermsProvider.java
@@ -22,6 +22,7 @@ import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.CommonGridIDs.LA
 import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.CommonGridIDs.ORDINAL;
 import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.CommonGridIDs.REGISTRATION_DATE;
 import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.CommonGridIDs.REGISTRATOR;
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTermGridIDs.IS_OFFICIAL;
 import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTermGridIDs.TERM_FOR_DATA_SET_USAGE;
 import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTermGridIDs.TERM_FOR_EXPERIMENTS_USAGE;
 import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTermGridIDs.TERM_FOR_MATERIALS_USAGE;
@@ -32,6 +33,7 @@ import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTermGr
 import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
+import ch.systemsx.cisd.openbis.generic.shared.basic.SimpleYesNoRenderer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TypedTableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
@@ -40,17 +42,16 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTermWithStats
 import ch.systemsx.cisd.openbis.generic.shared.translator.VocabularyTermTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.util.TypedTableModelBuilder;
 
-
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
-public class VocabularyTermsProvider extends AbstractCommonTableModelProvider<VocabularyTermWithStats>
+public class VocabularyTermsProvider extends
+        AbstractCommonTableModelProvider<VocabularyTermWithStats>
 {
     private final Vocabulary vocabulary;
 
-    public VocabularyTermsProvider(ICommonServer commonServer, String sessionToken, Vocabulary vocabulary)
+    public VocabularyTermsProvider(ICommonServer commonServer, String sessionToken,
+            Vocabulary vocabulary)
     {
         super(commonServer, sessionToken);
         this.vocabulary = vocabulary;
@@ -68,6 +69,7 @@ public class VocabularyTermsProvider extends AbstractCommonTableModelProvider<Vo
         builder.addColumn(DESCRIPTION).withDefaultWidth(300);
         builder.addColumn(ORDINAL).withDefaultWidth(100).hideByDefault();
         builder.addColumn(URL).withDefaultWidth(200);
+        builder.addColumn(IS_OFFICIAL).withDefaultWidth(100).hideByDefault();
         builder.addColumn(REGISTRATOR).withDefaultWidth(200);
         builder.addColumn(REGISTRATION_DATE).withDefaultWidth(300).hideByDefault();
         builder.addColumn(TERM_TOTAL_USAGE).withDefaultWidth(100);
@@ -84,13 +86,21 @@ public class VocabularyTermsProvider extends AbstractCommonTableModelProvider<Vo
             builder.column(DESCRIPTION).addString(term.getDescription());
             builder.column(ORDINAL).addInteger(term.getOrdinal());
             builder.column(URL).addString(term.getUrl());
+            builder.column(IS_OFFICIAL).addString(
+                    term.isOfficial() == null ? null
+                            : SimpleYesNoRenderer.render(term.isOfficial()));
             builder.column(REGISTRATOR).addPerson(term.getRegistrator());
             builder.column(REGISTRATION_DATE).addDate(term.getRegistrationDate());
-            builder.column(TERM_TOTAL_USAGE).addInteger((long) termWithStats.getTotalUsageCounter());
-            builder.column(TERM_FOR_DATA_SET_USAGE).addInteger(termWithStats.getUsageCounter(EntityKind.DATA_SET));
-            builder.column(TERM_FOR_EXPERIMENTS_USAGE).addInteger(termWithStats.getUsageCounter(EntityKind.EXPERIMENT));
-            builder.column(TERM_FOR_MATERIALS_USAGE).addInteger(termWithStats.getUsageCounter(EntityKind.MATERIAL));
-            builder.column(TERM_FOR_SAMPLES_USAGE).addInteger(termWithStats.getUsageCounter(EntityKind.SAMPLE));
+            builder.column(TERM_TOTAL_USAGE)
+                    .addInteger((long) termWithStats.getTotalUsageCounter());
+            builder.column(TERM_FOR_DATA_SET_USAGE).addInteger(
+                    termWithStats.getUsageCounter(EntityKind.DATA_SET));
+            builder.column(TERM_FOR_EXPERIMENTS_USAGE).addInteger(
+                    termWithStats.getUsageCounter(EntityKind.EXPERIMENT));
+            builder.column(TERM_FOR_MATERIALS_USAGE).addInteger(
+                    termWithStats.getUsageCounter(EntityKind.MATERIAL));
+            builder.column(TERM_FOR_SAMPLES_USAGE).addInteger(
+                    termWithStats.getUsageCounter(EntityKind.SAMPLE));
         }
         return builder.getModel();
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index c963e39606c8f5701fc28ff03e2507e484bd42b6..8f546a765165722eb0e2e7bb58d1896f08f37691 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
@@ -800,6 +800,20 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         vocabularyBO.save();
     }
 
+    public void addUnofficialVocabularyTerms(String sessionToken, TechId vocabularyId,
+            List<String> vocabularyTerms, Long previousTermOrdinal)
+    {
+        assert sessionToken != null : "Unspecified session token";
+        assert vocabularyId != null : "Unspecified vocabulary id";
+        assert previousTermOrdinal != null : "Unspecified previous term ordinal";
+
+        final Session session = getSession(sessionToken);
+        final IVocabularyBO vocabularyBO = businessObjectFactory.createVocabularyBO(session);
+        vocabularyBO.loadDataByTechId(vocabularyId);
+        vocabularyBO.addNewUnofficialTerms(vocabularyTerms, previousTermOrdinal);
+        vocabularyBO.save();
+    }
+
     public final void updateVocabularyTerm(final String sessionToken,
             final IVocabularyTermUpdates updates)
     {
@@ -825,6 +839,18 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         vocabularyBO.save();
     }
 
+    public void makeVocabularyTermsOfficial(String sessionToken, TechId vocabularyId,
+            List<VocabularyTerm> termsToBeOfficial)
+    {
+        assert sessionToken != null : "Unspecified session token";
+        assert vocabularyId != null : "Unspecified vocabulary id";
+
+        final Session session = getSession(sessionToken);
+        final IVocabularyTermBO vocabularyTermBO =
+                businessObjectFactory.createVocabularyTermBO(session);
+        vocabularyTermBO.makeOfficial(termsToBeOfficial);
+    }
+
     public void registerProject(String sessionToken, ProjectIdentifier projectIdentifier,
             String description, String leaderId, Collection<NewAttachment> attachments)
     {
@@ -2417,4 +2443,5 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         }
         return dataStores.get(0).getDownloadUrl();
     }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
index a9d7c499cf0255e4d1ff3f64c546c2bb9372b101..59177115274a0b92b8cd59234237f19753654ea7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
@@ -420,6 +420,14 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
                 vocabularyId, abbreviate(vocabularyTerms), Long.toString(previousTermOrdinal));
     }
 
+    public void addUnofficialVocabularyTerms(String sessionToken, TechId vocabularyId,
+            List<String> vocabularyTerms, Long previousTermOrdinal)
+    {
+        logTracking(sessionToken, "add_unofficial_vocabulary_terms",
+                "ID(%s) TERMS(%s) PREVIOUS_ORDINAL(%s)", vocabularyId, abbreviate(vocabularyTerms),
+                Long.toString(previousTermOrdinal));
+    }
+
     public void updateVocabularyTerm(String sessionToken, IVocabularyTermUpdates updates)
     {
         logTracking(sessionToken, "update_vocabulary_term", "VOCABULARY_TERM(%s)", updates);
@@ -433,6 +441,13 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
                 abbreviate(termsToBeDeleted), abbreviate(termsToBeReplaced));
     }
 
+    public void makeVocabularyTermsOfficial(String sessionToken, TechId vocabularyId,
+            List<VocabularyTerm> termsToBeOfficial)
+    {
+        logTracking(sessionToken, "make_vocabulary_terms_official",
+                "VOCABULARY_ID(%s) OFFICIAL(%s)", vocabularyId, abbreviate(termsToBeOfficial));
+    }
+
     public void registerProject(String sessionToken, ProjectIdentifier projectIdentifier,
             String description, String leaderId, Collection<NewAttachment> attachments)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IVocabularyBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IVocabularyBO.java
index e2f82120ef33ac29715b61dac674e76e0b996332..d17fd79d28344cff0405d96d05b30b16076aabf7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IVocabularyBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IVocabularyBO.java
@@ -75,6 +75,13 @@ public interface IVocabularyBO extends IEntityBusinessObject
      */
     void addNewTerms(List<String> newTerms, Long previousTermOrdinal);
 
+    /**
+     * Add unofficial terms with specified codes to a loaded vocabulary.
+     * 
+     * @param previousTermOrdinal ordinal of term after which new terms should be added
+     */
+    void addNewUnofficialTerms(List<String> newTerms, Long previousTermOrdinal);
+
     /**
      * Deletes the specified terms from a loaded vocabulary and replaces terms which are used.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IVocabularyTermBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IVocabularyTermBO.java
index 2b376878eb29ae2ed957c8e7ba4a2d3122dc0bcd..842e746755b88e1e2d812c8daebe5bb6ac32e598 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IVocabularyTermBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IVocabularyTermBO.java
@@ -16,7 +16,10 @@
 
 package ch.systemsx.cisd.openbis.generic.server.business.bo;
 
+import java.util.List;
+
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermPE;
 
 /**
@@ -36,4 +39,8 @@ public interface IVocabularyTermBO
      */
     public void update(IVocabularyTermUpdates updates);
 
+    /**
+     * Makes vocabulary terms official
+     */
+    public void makeOfficial(List<VocabularyTerm> termsToBeOfficial);
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/VocabularyBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/VocabularyBO.java
index 9cd2dcc36cbdedf515b39684cc025c604e431254..63305ae3546787571ffbb502917894efdb1ea82c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/VocabularyBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/VocabularyBO.java
@@ -109,7 +109,7 @@ public class VocabularyBO extends AbstractBusinessObject implements IVocabularyB
         }
     }
 
-    public void addNewTerms(List<String> newTermCodes, Long previousTermOrdinal)
+    private void addNewTerms(List<String> newTermCodes, Long previousTermOrdinal, boolean isOfficial)
     {
         assert vocabularyPE != null : UNSPECIFIED_VOCABULARY;
         assert previousTermOrdinal != null : "Unspecified previous term ordinal";
@@ -124,10 +124,20 @@ public class VocabularyBO extends AbstractBusinessObject implements IVocabularyB
         Long currentTermOrdinal = previousTermOrdinal + 1;
         for (String code : newTermCodes)
         {
-            addTerm(code, currentTermOrdinal++, true);
+            addTerm(code, currentTermOrdinal++, isOfficial);
         }
     }
 
+    public void addNewTerms(List<String> newTermCodes, Long previousTermOrdinal)
+    {
+        addNewTerms(newTermCodes, previousTermOrdinal, true);
+    }
+
+    public void addNewUnofficialTerms(List<String> newTermCodes, Long previousTermOrdinal)
+    {
+        addNewTerms(newTermCodes, previousTermOrdinal, false);
+    }
+
     /** shift terms in vocabulary by specified increment starting from term with specified ordinal */
     private void increaseVocabularyTermOrdinals(Long startOrdinal, int increment)
     {
@@ -463,5 +473,4 @@ public class VocabularyBO extends AbstractBusinessObject implements IVocabularyB
         }
         return list;
     }
-
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/VocabularyTermBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/VocabularyTermBO.java
index 3fbef1cb2fcaf8b2e70fc73ca293f1b68f6e584e..67f7f2f25202e70d29f671fcb0cd4c6d2e79b896 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/VocabularyTermBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/VocabularyTermBO.java
@@ -16,12 +16,15 @@
 
 package ch.systemsx.cisd.openbis.generic.server.business.bo;
 
+import java.util.List;
+
 import org.springframework.dao.DataRetrievalFailureException;
 
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermPE;
 
@@ -85,4 +88,21 @@ public final class VocabularyTermBO extends AbstractBusinessObject implements IV
             throw new UserFailureException(exception.getMessage());
         }
     }
+
+    public void makeOfficial(List<VocabularyTerm> termsToBeOfficial)
+    {
+        for (VocabularyTerm term : termsToBeOfficial)
+        {
+            makeOfficial(term);
+        }
+    }
+
+    private void makeOfficial(VocabularyTerm term)
+    {
+        loadDataByTechId(TechId.create(term));
+
+        vocabularyTermPE.setOfficial(true);
+
+        validateAndSave();
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
index 2baa060ab8e98d60c39d272ca23892f1bcb02a3d..b941e1d66b95b103dbfefa8bb39cb746b604c51e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
@@ -528,6 +528,15 @@ public interface ICommonServer extends IServer
     public void addVocabularyTerms(String sessionToken, TechId vocabularyId,
             List<String> vocabularyTerms, Long previousTermOrdinal);
 
+    /**
+     * Adds new unofficial terms to a vocabulary starting from specified ordinal + 1.
+     */
+    @Transactional
+    @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.VOCABULARY_TERM)
+    public void addUnofficialVocabularyTerms(String sessionToken, TechId vocabularyId,
+            List<String> vocabularyTerms, Long previousTermOrdinal);
+
     /**
      * Updates a vocabulary term.
      */
@@ -545,6 +554,15 @@ public interface ICommonServer extends IServer
     public void deleteVocabularyTerms(String sessionToken, TechId vocabularyId,
             List<VocabularyTerm> termsToBeDeleted, List<VocabularyTermReplacement> termsToBeReplaced);
 
+    /**
+     * Makes given vocabulary terms official.
+     */
+    @Transactional
+    @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.VOCABULARY_TERM)
+    public void makeVocabularyTermsOfficial(String sessionToken, TechId vocabularyId,
+            List<VocabularyTerm> termsToBeOfficial);
+
     /**
      * Registers new project.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/WebClientConfiguration.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/WebClientConfiguration.java
index 94064cbf1f0fb4e5f108e20d00bb0ea5b8ee1a34..05ede33e0d3da055570a11d470dc9d37d7df5863 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/WebClientConfiguration.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/WebClientConfiguration.java
@@ -46,13 +46,15 @@ public class WebClientConfiguration implements ISerializable
     private Set<String> dataSetTypePatternsWithImageOverview = new HashSet<String>();
 
     private ViewMode defaultViewMode;
-    
+
     private boolean defaultAnonymousLogin;
 
     private int maxVisibleColumns;
-    
+
     private int maxEntityVisits;
 
+    private boolean allowAddingUnofficielTerms;
+
     public String getPropertyOrNull(String technology, String key)
     {
         Map<String, String> properties = technologyProperties.get(technology);
@@ -124,8 +126,17 @@ public class WebClientConfiguration implements ISerializable
         this.maxEntityVisits = maxEntityVisits;
     }
 
-    public WebClientConfiguration()
+    public void setAllowAddingUnofficielTerms(boolean allowAddingUnofficialTerms)
+    {
+        this.allowAddingUnofficielTerms = allowAddingUnofficialTerms;
+    }
+
+    public boolean getAllowAddingUnofficialTerms()
     {
+        return allowAddingUnofficielTerms;
     }
 
+    public WebClientConfiguration()
+    {
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/VocabularyTermTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/VocabularyTermTranslator.java
index 967a00365bfd9c0d8e9f366f1fdb1b5a5f2d355b..230785ef629e00babf91c0d36c7ef1215f7d7b4a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/VocabularyTermTranslator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/VocabularyTermTranslator.java
@@ -47,6 +47,7 @@ public class VocabularyTermTranslator
         result.setDescription(vt.getDescription());
         result.setOrdinal(vt.getOrdinal());
         result.setUrl(vt.getUrl());
+        result.setOfficial(vt.isOfficial());
         result.setRegistrationDate(vt.getRegistrationDate());
         result.setRegistrator(PersonTranslator.translate(vt.getRegistrator()));
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
index 8d1c8a0674f9f5b7dc2e8da638daeeb237f3f67a..d73711ccaba50dd3c6547ff4024b0dc584cb5312 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
@@ -52,9 +52,11 @@ var common = {
   main_data_set_pattern: "Main Data Set Pattern",
   main_data_set_pattern_tooltip: "If there is just one data set with path matching chosen 'main data set' pattern, it will be automatically displayed.\nA Regular Expression is expected. Example: '.*\.jpg'",
   main_data_set_pattern_example: "for example: .*\.jpg",
-	auto_resolve_label: "Smart View",
-	data_report_label: "Report:",
-	explore_label: "Explore:",
+  auto_resolve_label: "Smart View",
+  data_report_label: "Report:",
+  explore_label: "Explore:",
+  add_unofficial_vocabulary_term_dialog_title: "Add unofficial term",
+  add_unofficial_vocabulary_term_dialog_message: "Do you want to add new unofficial term '{0}' to dictionary '{1}'?",
 	  
   //
   // Field
@@ -169,7 +171,7 @@ var common = {
   more_results_found_message: "More search results were found, but are not shown. Consider making the search more specific.",
   more_results_found_title: "More results found",
   search_criteria_dialog_title: "{0} Search Criteria",
-  
+
   //
   // Sample Browser
   //
@@ -558,7 +560,10 @@ var common = {
  delete_vocabulary_terms_confirmation_message_for_replacements: "{0} terms will be deleted.\n\nThe terms below are used. They have to be replaced by one of the remaining terms.",
  edit_vocabulary_term_button: "Edit Term",
  make_official_vocabulary_term_button: "Make Official",
- 
+ make_official_vocabulary_terms_confirmation_title: "Making Vocabulary Terms Official",
+ make_official_vocabulary_terms_confirmation_message_singular: "Do you want to make the selected term official?",
+ make_official_vocabulary_terms_confirmation_message: "Do you want to make the {0} selected terms official?",
+
  //
  // Person Browser
  //