diff --git a/SciPost_v1/settings.py b/SciPost_v1/settings.py
index 831913e4b0035d43dc8eb46bd94cd18057460187..4e6a5fc96a19b7b16c793cfa9f3ea3948db188d6 100644
--- a/SciPost_v1/settings.py
+++ b/SciPost_v1/settings.py
@@ -12,12 +12,14 @@ https://docs.djangoproject.com/en/1.8/ref/settings/
 
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 import os
-
 import json
 
+from django.utils.translation import ugettext_lazy as _
+
+
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
-host_settings_path = os.path.join(os.path.dirname(BASE_DIR),"scipost-host-settings.json")
+host_settings_path = os.path.join(os.path.dirname(BASE_DIR), "scipost-host-settings.json")
 host_settings = json.load(open(host_settings_path))
 
 # Quick-start development settings - unsuitable for production
@@ -109,6 +111,7 @@ MATHJAX_CONFIG_DATA = {
 
 MIDDLEWARE_CLASSES = (
     'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.locale.LocaleMiddleware',
     'django.middleware.common.CommonMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
@@ -129,6 +132,7 @@ TEMPLATES = [
             'context_processors': [
                 'django.template.context_processors.debug',
                 'django.template.context_processors.request',
+                'django.template.context_processors.i18n',
                 'django.contrib.auth.context_processors.auth',
                 'django.contrib.messages.context_processors.messages',
                 'scipost.context_processors.searchform',
@@ -159,7 +163,12 @@ DATABASES = {
 # https://docs.djangoproject.com/en/1.8/topics/i18n/
 
 LANGUAGE_CODE = 'en-us'
-
+LANGUAGES = (
+    ('en', _('English')),
+)
+LOCALE_PATHS = (
+    os.path.join(BASE_DIR, 'locale'),
+)
 TIME_ZONE = 'CET'
 
 USE_I18N = True
diff --git a/comments/migrations/0005_merge_20161219_2126.py b/comments/migrations/0005_merge_20161219_2126.py
new file mode 100644
index 0000000000000000000000000000000000000000..f604a8605fd90bc48a48ababc797a758ed29c2a3
--- /dev/null
+++ b/comments/migrations/0005_merge_20161219_2126.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.3 on 2016-12-19 20:26
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('comments', '0004_auto_20161212_1931'),
+        ('comments', '0004_auto_20161213_1208'),
+    ]
+
+    operations = [
+    ]
diff --git a/common/helpers/factories.py b/common/helpers/factories.py
new file mode 100644
index 0000000000000000000000000000000000000000..b033a898be81b691d884566550a661480c663611
--- /dev/null
+++ b/common/helpers/factories.py
@@ -0,0 +1,10 @@
+import factory
+
+
+class FormFactory(factory.Factory):
+    class Meta:
+        strategy = factory.BUILD_STRATEGY
+
+    @classmethod
+    def _build(cls, model_class, *args, **kwargs):
+        return model_class(kwargs)
diff --git a/scipost/templates/scipost/base.html b/scipost/templates/scipost/base.html
index f69fa7db79b8b713e79d763ca35302a632eb0cad..2bedef9de0857fbfb823f74ed24c21783a37cd06 100644
--- a/scipost/templates/scipost/base.html
+++ b/scipost/templates/scipost/base.html
@@ -26,6 +26,7 @@
   <body>
     {% include 'scipost/header.html' %}
     {% include 'scipost/navbar.html' %}
+    {% include 'scipost/messages.html' %}
 
     {% block bodysup %}
     {% endblock bodysup %}
diff --git a/scipost/templates/scipost/messages.html b/scipost/templates/scipost/messages.html
new file mode 100644
index 0000000000000000000000000000000000000000..ac8c6dff8c12a6bea16bcdaca31738d52cd55336
--- /dev/null
+++ b/scipost/templates/scipost/messages.html
@@ -0,0 +1,8 @@
+{% for message in messages %}
+  <div class="alert {{ message.tags }} alert-dismissible" role="alert">
+    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
+      <span aria-hidden="true">&times;</span>
+    </button>
+    {{ message }}
+  </div>
+{% endfor %}
diff --git a/strings/__init__.py b/strings/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..82d957c9dde2ab9c1606aa3568f778e408e13a84
--- /dev/null
+++ b/strings/__init__.py
@@ -0,0 +1 @@
+acknowledge_request_thesis_link = "Thank you for your request for a Thesis Link. Your request will soon be handled by an editor"
diff --git a/theses/factories.py b/theses/factories.py
index 1a12cd026941ad06ef7e4ad82c798b6947813a93..bc57863b350e82579b8725bd27884bdeb1382c24 100644
--- a/theses/factories.py
+++ b/theses/factories.py
@@ -1,7 +1,11 @@
 import factory
-from .models import ThesisLink
+
+from common.helpers.factories import FormFactory
 from scipost.factories import ContributorFactory
 
+from .models import ThesisLink
+from .forms import VetThesisLinkForm
+
 
 class ThesisLinkFactory(factory.django.DjangoModelFactory):
     class Meta:
@@ -9,7 +13,7 @@ class ThesisLinkFactory(factory.django.DjangoModelFactory):
 
     requested_by = factory.SubFactory(ContributorFactory)
     type = ThesisLink.MASTER_THESIS
-    title = factory.Sequence(lambda n: "thesis {0}".format(n))
+    title = factory.Faker('bs')
     pub_link = factory.Faker('uri')
     author = factory.Faker('name')
     supervisor = factory.Faker('name')
@@ -17,3 +21,11 @@ class ThesisLinkFactory(factory.django.DjangoModelFactory):
     defense_date = factory.Faker('date_time_this_century')
     abstract = factory.Faker('text')
     domain = 'ET'
+
+
+class VetThesisLinkFormFactory(FormFactory):
+    class Meta:
+        model = VetThesisLinkForm
+
+    action_option = VetThesisLinkForm.ACCEPT
+    # justification = factory.Faker('lorem')
diff --git a/theses/forms.py b/theses/forms.py
index 13b4a1793a47b46f2e9c993e8c55c2d86ebf0834..05963cb3221ca5cadcc553f653090d316395470b 100644
--- a/theses/forms.py
+++ b/theses/forms.py
@@ -3,18 +3,6 @@ from django import forms
 from .models import *
 from .helpers import past_years
 
-THESIS_ACTION_CHOICES = (
-    (0, 'modify'),
-    (1, 'accept'),
-    (2, 'refuse (give reason below)'),
-    )
-
-THESIS_REFUSAL_CHOICES = (
-    (0, '-'),
-    (-1, 'a link to this thesis already exists'),
-    (-2, 'the external link to this thesis does not work'),
-    )
-
 
 class RequestThesisLinkForm(forms.ModelForm):
     class Meta:
@@ -29,13 +17,35 @@ class RequestThesisLinkForm(forms.ModelForm):
 
 
 class VetThesisLinkForm(forms.Form):
-    action_option = forms.ChoiceField(widget=forms.RadioSelect,
-                                      choices=THESIS_ACTION_CHOICES,
-                                      required=True, label='Action')
+    MODIFY = 0
+    ACCEPT = 1
+    REFUSE = 2
+    THESIS_ACTION_CHOICES = (
+        (MODIFY, 'modify'),
+        (ACCEPT, 'accept'),
+        (REFUSE, 'refuse (give reason below)'),
+    )
+
+    EMPTY_CHOICE = 0
+    ALREADY_EXISTS = 1
+    LINK_DOES_NOT_WORK = 2
+    THESIS_REFUSAL_CHOICES = (
+        (EMPTY_CHOICE, '---'),
+        (ALREADY_EXISTS, 'a link to this thesis already exists'),
+        (LINK_DOES_NOT_WORK, 'the external link to this thesis does not work'),
+    )
+
+    action_option = forms.ChoiceField(
+        widget=forms.RadioSelect, choices=THESIS_ACTION_CHOICES, required=True, label='Action')
     refusal_reason = forms.ChoiceField(choices=THESIS_REFUSAL_CHOICES, required=False)
-    email_response_field = forms.CharField(widget=forms.Textarea(
+    justification = forms.CharField(widget=forms.Textarea(
         attrs={'rows': 5, 'cols': 40}), label='Justification (optional)', required=False)
 
+    def vet_request(self, thesis_link):
+        print(self.cleaned_data)
+        if self.cleaned_data['action_option'] == VetThesisLinkForm.ACCEPT:
+            print('hoi')
+
 
 class ThesisLinkSearchForm(forms.Form):
     author = forms.CharField(max_length=100, required=False, label="Author")
diff --git a/theses/templates/theses/vet_thesislink_requests.html b/theses/templates/theses/vet_thesislink_requests.html
index 4fd2a7d9abc646c28443f658ae4cc156e24e6cb1..c49008776f23329e746b62c1e0d84c9da1f3a178 100644
--- a/theses/templates/theses/vet_thesislink_requests.html
+++ b/theses/templates/theses/vet_thesislink_requests.html
@@ -22,7 +22,7 @@
       <p>{{ thesislink_to_vet.abstract }}</p>
     </div>
     <div class="col-4">
-      <form action="{% url 'theses:vet_thesislink_request_ack' thesislink_id=thesislink_to_vet.id %}" method="post">
+      <form method="post">
         {% csrf_token %}
         {{ form.as_ul }}
         <input type="submit" value="Submit" />
diff --git a/theses/test_forms.py b/theses/test_forms.py
index ce07aa6214b9811d4b0ca54e09c7b5b304b93901..1456184593dd64e0f63f12574fb5c59b87576e6a 100644
--- a/theses/test_forms.py
+++ b/theses/test_forms.py
@@ -2,8 +2,8 @@ import factory
 
 from django.test import TestCase
 
-from .factories import ThesisLinkFactory
-from .forms import RequestThesisLinkForm
+from .factories import ThesisLinkFactory, VetThesisLinkFormFactory
+from .forms import RequestThesisLinkForm, VetThesisLinkForm
 from common.helpers import model_form_data
 
 
@@ -24,3 +24,21 @@ class TestRequestThesisLink(TestCase):
         form = RequestThesisLinkForm(form_data)
         form.is_valid()
         self.assertEqual(form.errors['domain'], ['This field is required.'])
+
+
+class TestVetThesisLinkRequests(TestCase):
+    fixtures = ['permissions', 'groups']
+
+    def test_thesislink_gets_vetted_when_accepted(self):
+        thesis_link = ThesisLinkFactory()
+        form = VetThesisLinkFormFactory()
+        form.is_valid()
+        form.vet_request(thesis_link)
+        self.assertTrue(thesis_link.vetted)
+
+    def test_thesislink_is_not_vetted_when_refused(self):
+        thesis_link = ThesisLinkFactory()
+        form = VetThesisLinkFormFactory(action_option=VetThesisLinkForm.REFUSE)
+        form.is_valid()
+        form.vet_request(thesis_link)
+        self.assertFalse(thesis_link.vetted)
diff --git a/theses/test_views.py b/theses/test_views.py
index 7e70a6dd41170d221dfd8a4d586a4a8b0ff0c38c..faa7f14d5d621096441faa542af7984e8e629573 100644
--- a/theses/test_views.py
+++ b/theses/test_views.py
@@ -1,11 +1,14 @@
+import re
+
+from django.core.exceptions import PermissionDenied
 from django.test import TestCase, RequestFactory
 from django.test.client import Client
-from django.contrib.auth.models import AnonymousUser
+from django.contrib.auth.models import Group
 from django.urls import reverse
 
-from .views import RequestThesisLink
-from scipost.factories import UserFactory
-from .factories import ThesisLinkFactory
+from .views import RequestThesisLink, VetThesisLinkRequests
+from scipost.factories import UserFactory, ContributorFactory
+from .factories import ThesisLinkFactory, VetThesisLinkFormFactory
 from .models import ThesisLink
 
 
@@ -25,18 +28,63 @@ class TestRequestThesisLink(TestCase):
 
     def setUp(self):
         self.client = Client()
+        self.target = reverse('theses:request_thesislink')
 
     def test_response_when_not_logged_in(self):
         '''A visitor that is not logged in cannot view this page.'''
-        response = self.client.get(reverse('theses:request_thesislink'))
+        response = self.client.get(self.target)
         self.assertEqual(response.status_code, 403)
 
     def test_response_when_logged_in(self):
-        request = RequestFactory().get(reverse('theses:request_thesislink'))
+        request = RequestFactory().get(self.target)
         request.user = UserFactory()
         response = RequestThesisLink.as_view()(request)
         self.assertEqual(response.status_code, 200)
 
-    def test_redirects_to_acknowledgement_page(self):
-        response = self.client.post(reverse('theses:request_thesislink'), {}, follow=True)
-        self.assertRedirects(response, reverse('scipost:acknowledgement'))
+
+class TestVetThesisLinkRequests(TestCase):
+    fixtures = ['groups', 'permissions']
+
+    def setUp(self):
+        self.client = Client()
+        self.target = reverse('theses:vet_thesislink_requests')
+
+    def test_response_when_not_logged_in(self):
+        response = self.client.get(self.target)
+        self.assertEqual(response.status_code, 403)
+
+    def test_response_regular_contributor(self):
+        '''
+        A Contributor needs to be in the Vetting Editors group to be able to
+        vet submitted thesis links.
+        '''
+        # Create ThesisLink to vet.
+        ThesisLinkFactory()
+        request = RequestFactory().get(self.target)
+        user = UserFactory()
+        request.user = user
+        self.assertRaises(
+            PermissionDenied, VetThesisLinkRequests.as_view(), request)
+
+    def test_response_vetting_editor(self):
+        # Create ThesisLink to vet.
+        ThesisLinkFactory()
+        request = RequestFactory().get(self.target)
+        user = UserFactory()
+        user.groups.add(Group.objects.get(name="Vetting Editors"))
+        request.user = user
+        response = VetThesisLinkRequests.as_view()(request)
+        self.assertEqual(response.status_code, 200)
+
+    def test_thesislink_is_vetted_by_correct_contributor(self):
+        # TODO: how to make sure we are vetting the right thesis link?
+        contributor = ContributorFactory()
+        contributor.user.groups.add(Group.objects.get(name="Vetting Editors"))
+        post_data = VetThesisLinkFormFactory().data
+
+        request = RequestFactory().post(self.target, post_data)
+        request.user = contributor.user
+
+        response = VetThesisLinkRequests.as_view()(request)
+
+        self.assertTrue(False)
diff --git a/theses/urls.py b/theses/urls.py
index 05839aa7550bedf319b58d82bb3e7aa59703cacf..3d3c530e497a0ca6794259b9626530d6a8e8fbc9 100644
--- a/theses/urls.py
+++ b/theses/urls.py
@@ -9,7 +9,7 @@ urlpatterns = [
     url(r'^browse/(?P<discipline>[a-z]+)/(?P<nrweeksback>[0-9]+)/$', views.browse, name='browse'),
     url(r'^(?P<thesislink_id>[0-9]+)/$', views.thesis_detail, name='thesis'),
     url(r'^request_thesislink$', views.RequestThesisLink.as_view(), name='request_thesislink'),
-    url(r'^vet_thesislink_requests$', views.vet_thesislink_requests,
+    url(r'^vet_thesislink_requests$', views.VetThesisLinkRequests.as_view(),
         name='vet_thesislink_requests'),
     url(r'^vet_thesislink_request_ack/(?P<thesislink_id>[0-9]+)$',
         views.vet_thesislink_request_ack, name='vet_thesislink_request_ack'),
diff --git a/theses/views.py b/theses/views.py
index 00ede98acfc6398837ed08ef52493f877341aa73..7e782a4b88b20052e4c52217c4544106c246ced6 100644
--- a/theses/views.py
+++ b/theses/views.py
@@ -5,12 +5,13 @@ from django.shortcuts import get_object_or_404, render
 from django.contrib.auth import authenticate, login, logout
 from django.contrib.auth.decorators import login_required, permission_required
 from django.contrib.auth.models import User
+from django.contrib import messages
 from django.core.mail import EmailMessage
-from django.core.urlresolvers import reverse
+from django.core.urlresolvers import reverse, reverse_lazy
 from django.http import HttpResponse, HttpResponseRedirect
 from django.views.decorators.csrf import csrf_protect
 from django.db.models import Avg
-from django.views.generic.edit import CreateView
+from django.views.generic.edit import CreateView, FormView
 from django.utils.decorators import method_decorator
 
 from .models import *
@@ -33,25 +34,43 @@ title_dict = dict(TITLE_CHOICES)  # Convert titles for use in emails
 class RequestThesisLink(CreateView):
     form_class = RequestThesisLinkForm
     template_name = 'theses/request_thesislink.html'
-    success_url = ''
+    success_url = reverse_lazy('scipost:personal_page')
 
     def form_valid(self, form):
-        context = {'ack_header': 'Thank you for your request for a Thesis Link',
-                   'ack_message': 'Your request will soon be handled by an Editor. ',
-                   'followup_message': 'Return to your ',
-                   'followup_link': reverse('scipost:personal_page'),
-                   'followup_link_label': 'personal page'}
-        return render(self.request, 'scipost/acknowledgement.html', context)
+        messages.add_message(self.request, messages.SUCCESS,
+                             strings.acknowledge_request_thesis_link)
+        return super(RequestThesisLink, self).form_valid(form)
 
 
-@permission_required('scipost.can_vet_thesislink_requests', raise_exception=True)
-def vet_thesislink_requests(request):
-    contributor = Contributor.objects.get(user=request.user)
-    thesislink_to_vet = ThesisLink.objects.filter(
-        vetted=False).first()  # only handle one at a time
-    form = VetThesisLinkForm()
-    context = {'contributor': contributor, 'thesislink_to_vet': thesislink_to_vet, 'form': form}
-    return render(request, 'theses/vet_thesislink_requests.html', context)
+@method_decorator(permission_required(
+    'scipost.can_vet_thesislink_requests', raise_exception=True), name='dispatch')
+class VetThesisLinkRequests(FormView):
+    form_class = VetThesisLinkForm
+    template_name = 'theses/vet_thesislink_requests.html'
+    # TODO: not right yet
+    success_url = reverse_lazy('theses:vet_thesislink_requests')
+
+    def get_context_data(self, **kwargs):
+        context = super(VetThesisLinkRequests, self).get_context_data(**kwargs)
+        context['thesislink_to_vet'] = self.thesislink_to_vet()
+        return context
+
+    def thesislink_to_vet(self):
+        return ThesisLink.objects.filter(vetted=False).first()
+
+    def form_valid(self, form):
+        form.vet_request(self.thesislink_to_vet())
+        return super(VetThesisLinkRequests, self).form_valid(form)
+
+
+# @permission_required('scipost.can_vet_thesislink_requests', raise_exception=True)
+# def vet_thesislink_requests(request):
+#     contributor = Contributor.objects.get(user=request.user)
+#     thesislink_to_vet = ThesisLink.objects.filter(
+#         vetted=False).first()  # only handle one at a time
+#     form = VetThesisLinkForm()
+#     context = {'contributor': contributor, 'thesislink_to_vet': thesislink_to_vet, 'form': form}
+#     return render(request, 'theses/vet_thesislink_requests.html', context)
 
 
 @permission_required('scipost.can_vet_thesislink_requests', raise_exception=True)
@@ -111,9 +130,9 @@ def vet_thesislink_request_ack(request, thesislink_id):
                               + ', has not been activated for the following reason: '
                               + form.cleaned_data['refusal_reason']
                               + '.\n\nThank you for your interest, \nThe SciPost Team.')
-                if form.cleaned_data['email_response_field']:
+                if form.cleaned_data['justification']:
                     email_text += '\n\nFurther explanations: ' + \
-                        form.cleaned_data['email_response_field']
+                        form.cleaned_data['justification']
                 emailmessage = EmailMessage('SciPost Thesis Link', email_text,
                                             'SciPost Theses <theses@scipost.org>',
                                             [thesislink.requested_by.user.email],
@@ -208,17 +227,16 @@ def thesis_detail(request, thesislink_id):
             new_comment.save()
             author.nr_comments = Comment.objects.filter(author=author).count()
             author.save()
-            #request.session['thesislink_id'] = thesislink_id
-            #return HttpResponseRedirect(reverse('comments:comment_submission_ack'))
-            context = {'ack_header': 'Thank you for contributing a Comment.',
-                       'ack_message': 'It will soon be vetted by an Editor.',
-                       'followup_message': 'Back to the ',
-                       'followup_link': reverse(
-                           'theses:thesis',
-                           kwargs={'thesislink_id': newcomment.thesislink.id}
-                       ),
-                       'followup_link_label': ' Thesis Link page you came from'
-                   }
+            context = {
+                'ack_header': 'Thank you for contributing a Comment.',
+                'ack_message': 'It will soon be vetted by an Editor.',
+                'followup_message': 'Back to the ',
+                'followup_link': reverse(
+                    'theses:thesis',
+                    kwargs={'thesislink_id': new_comment.thesislink.id}
+                ),
+                'followup_link_label': ' Thesis Link page you came from'
+            }
             return render(request, 'scipost/acknowledgement.html', context)
     else:
         form = CommentForm()