Index: main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py	(revision 7714)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py	(revision 7723)
@@ -24,4 +24,5 @@
 from datetime import datetime
 from zope.event import notify
+from zope.i18n import translate
 from zope.catalog.interfaces import ICatalog
 from zope.component import queryUtility, getUtility, createObject
@@ -77,5 +78,5 @@
         notify(grok.ObjectModifiedEvent(view.context.getStudent()))
     fields_string = ' + '.join(changed_fields)
-    view.flash('Form has been saved.')
+    view.flash(_('Form has been saved.'))
     if fields_string:
         write_log_message(view, 'saved: %s' % fields_string)
@@ -85,5 +86,5 @@
     """Flash a lock message.
     """
-    view.flash('The requested form is locked (read-only).')
+    view.flash(_('The requested form is locked (read-only).'))
     view.redirect(view.url(view.context))
     return
@@ -93,5 +94,5 @@
     """
     grok.context(IStudentsContainer)
-    title = 'Students'
+    title = _('Students')
 
     @property
@@ -114,5 +115,5 @@
     """
     grok.context(IStudentStudyCourse)
-    title = 'Study Course'
+    title = _('Study Course')
 
 class PaymentsBreadcrumb(Breadcrumb):
@@ -120,5 +121,5 @@
     """
     grok.context(IStudentPaymentsContainer)
-    title = 'Payments'
+    title = _('Payments')
 
 class OnlinePaymentBreadcrumb(Breadcrumb):
@@ -135,5 +136,5 @@
     """
     grok.context(IStudentAccommodation)
-    title = 'Accommodation'
+    title = _('Accommodation')
 
 class BedTicketBreadcrumb(Breadcrumb):
@@ -144,5 +145,6 @@
     @property
     def title(self):
-        return 'Bed Ticket %s' % self.context.getSessionString()
+        return _('Bed Ticket ${a}',
+            mapping = {'a':self.context.getSessionString()})
 
 class StudyLevelBreadcrumb(Breadcrumb):
@@ -153,5 +155,9 @@
     @property
     def title(self):
-        return self.context.level_title
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        # There is no request attribute, thus we can only translate
+        # to the default (portal) language
+        return translate(self.context.level_title, 'waeup.sirp',
+            target_language=portal_language)
 
 class StudentsContainerPage(SIRPPage):
@@ -162,5 +168,5 @@
     grok.require('waeup.viewStudentsContainer')
     grok.template('containerpage')
-    label = 'Student Section'
+    label = _('Student Section')
     pnav = 4
 
@@ -177,5 +183,5 @@
         else:
             if 'search' in form:
-                self.flash('Empty search string.')
+                self.flash(_('Empty search string.'))
             return
         if self.searchtype == 'current_session':
@@ -195,5 +201,5 @@
     grok.template('containermanagepage')
     pnav = 4
-    label = 'Manage student section'
+    label = _('Manage student section')
 
     def update(self, *args, **kw):
@@ -211,5 +217,5 @@
         else:
             if 'search' in form:
-                self.flash('Empty search string.')
+                self.flash(_('Empty search string.'))
             return
         if not 'entries' in form:
@@ -217,7 +223,7 @@
                 searchtype=self.searchtype, view=self)
             if not self.hitlist:
-                self.flash('No student found.')
+                self.flash(_('No student found.'))
             if 'remove' in form:
-                self.flash('No item selected.')
+                self.flash(_('No item selected.'))
             return
         entries = form['entries']
@@ -232,5 +238,6 @@
             searchtype=self.searchtype, view=self)
         if len(deleted):
-            self.flash('Successfully removed: %s' % ', '.join(deleted))
+            self.flash(_('Successfully removed: ${a}',
+                mapping = {'a':', '.join(deleted)}))
         return
 
@@ -243,13 +250,13 @@
     form_fields = grok.AutoFields(IStudent).select(
         'firstname', 'middlename', 'lastname', 'reg_number')
-    label = 'Add student'
-    pnav = 4
-
-    @action('Create student record', style='primary')
+    label = _('Add student')
+    pnav = 4
+
+    @action(_('Create student record'), style='primary')
     def addStudent(self, **data):
         student = createObject(u'waeup.Student')
         self.applyData(student, **data)
         self.context.addStudent(student)
-        self.flash('Student record created.')
+        self.flash(_('Student record created.'))
         self.redirect(self.url(self.context[student.student_id], 'index'))
         return
@@ -267,11 +274,12 @@
     @property
     def label(self):
-        return '%s: Base Data' % self.context.display_fullname
+        return _('${a}: Base Data',
+            mapping = {'a':self.context.display_fullname})
 
     @property
     def hasPassword(self):
         if self.context.password:
-            return 'set'
-        return 'unset'
+            return _('set')
+        return _('unset')
 
 class ContactStudentForm(ContactAdminForm):
@@ -288,5 +296,6 @@
 
     def label(self):
-        return u'Send message to %s' % self.context.display_fullname
+        return _(u'Send message to ${a}',
+            mapping = {'a':self.context.display_fullname})
 
     @action('Send message now', style='primary')
@@ -306,7 +315,7 @@
                 data['body'],data['subject'])
         if success:
-            self.flash('Your message has been sent.')
+            self.flash(_('Your message has been sent.'))
         else:
-            self.flash('An smtp server error occurred.')
+            self.flash(_('An smtp server error occurred.'))
         return
 
@@ -319,5 +328,5 @@
     form_fields = grok.AutoFields(IStudentBase).omit('student_id')
     grok.template('basemanagepage')
-    label = 'Manage base data'
+    label = _('Manage base data')
     pnav = 4
 
@@ -345,5 +354,5 @@
             dict(name=x, title=y) for x, y in allowed_transitions]
 
-    @action('Save', style='primary')
+    @action(_('Save'), style='primary')
     def save(self, **data):
         form = self.request.form
@@ -371,5 +380,5 @@
             self.wf_info.fireTransition(transition_id)
         fields_string = ' + '.join(changed_fields)
-        self.flash('Form has been saved.')
+        self.flash(_('Form has been saved.'))
         if fields_string:
             write_log_message(self, 'saved: % s' % fields_string)
@@ -388,5 +397,6 @@
     @property
     def label(self):
-        return '%s: Clearance Data' % self.context.display_fullname
+        return _('${a}: Clearance Data',
+            mapping = {'a':self.context.display_fullname})
 
 class ExportPDFClearanceSlipPage(grok.View):
@@ -399,9 +409,17 @@
     form_fields['date_of_birth'].custom_widget = FriendlyDateDisplayWidget('le')
     prefix = 'form'
-    title = 'Clearance Data'
+
+    @property
+    def title(self):
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        return translate(_('Clearance Data'), 'waeup.sirp',
+            target_language=portal_language)
 
     @property
     def label(self):
-        return 'Clearance Slip of %s' % self.context.display_fullname
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        return translate(_('Clearance Slip of '),
+            'waeup.sirp', target_language=portal_language) \
+            + ' %s' % self.context.display_fullname
 
     def render(self):
@@ -421,5 +439,5 @@
     grok.template('clearanceeditpage')
     form_fields = grok.AutoFields(IStudentClearance)
-    label = 'Manage clearance data'
+    label = _('Manage clearance data')
     pnav = 4
     form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
@@ -435,5 +453,5 @@
         return super(StudentClearanceManageFormPage, self).update()
 
-    @action('Save', style='primary')
+    @action(_('Save'), style='primary')
     def save(self, **data):
         msave(self, **data)
@@ -450,7 +468,7 @@
         if self.context.state == REQUESTED:
             IWorkflowInfo(self.context).fireTransition('clear')
-            self.flash('Student has been cleared.')
+            self.flash(_('Student has been cleared.'))
         else:
-            self.flash('Student is in the wrong state.')
+            self.flash(_('Student is in wrong state.'))
         self.redirect(self.url(self.context,'view_clearance'))
         return
@@ -469,12 +487,12 @@
         if self.context.state == CLEARED:
             IWorkflowInfo(self.context).fireTransition('reset4')
-            message = 'Clearance has been annulled'
+            message = _('Clearance has been annulled.')
             self.flash(message)
         elif self.context.state == REQUESTED:
             IWorkflowInfo(self.context).fireTransition('reset3')
-            message = 'Clearance request has been rejected'
+            message = _('Clearance request has been rejected.')
             self.flash(message)
         else:
-            self.flash('Student is in the wrong state.')
+            self.flash(_('Student is in wrong state.'))
             self.redirect(self.url(self.context,'view_clearance'))
             return
@@ -499,5 +517,6 @@
     @property
     def label(self):
-        return '%s: Personal Data' % self.context.display_fullname
+        return _('${a}: Personal Data',
+            mapping = {'a':self.context.display_fullname})
 
 class StudentPersonalManageFormPage(SIRPEditFormPage):
@@ -508,8 +527,8 @@
     grok.require('waeup.viewStudent')
     form_fields = grok.AutoFields(IStudentPersonal)
-    label = 'Manage personal data'
-    pnav = 4
-
-    @action('Save', style='primary')
+    label = _('Manage personal data')
+    pnav = 4
+
+    @action(_('Save'), style='primary')
     def save(self, **data):
         msave(self, **data)
@@ -528,5 +547,6 @@
     @property
     def label(self):
-        return '%s: Study Course' % self.context.__parent__.display_fullname
+        return _('${a}: Study Course',
+            mapping = {'a':self.context.__parent__.display_fullname})
 
     @property
@@ -557,9 +577,9 @@
     grok.template('studycoursemanagepage')
     form_fields = grok.AutoFields(IStudentStudyCourse)
-    label = 'Manage study course'
-    pnav = 4
-    taboneactions = ['Save','Cancel']
-    tabtwoactions = ['Remove selected levels','Cancel']
-    tabthreeactions = ['Add study level']
+    label = _('Manage study course')
+    pnav = 4
+    taboneactions = [_('Save'),_('Cancel')]
+    tabtwoactions = [_('Remove selected levels'),_('Cancel')]
+    tabthreeactions = [_('Add study level')]
 
     def update(self):
@@ -575,5 +595,5 @@
         return
 
-    @action('Save', style='primary')
+    @action(_('Save'), style='primary')
     def save(self, **data):
         msave(self, **data)
@@ -587,5 +607,5 @@
             yield(dict(code=code, title=title))
 
-    @action('Add study level')
+    @action(_('Add study level'))
     def addStudyLevel(self, **data):
         level_code = self.request.form.get('addlevel', None)
@@ -595,11 +615,11 @@
             self.context.addStudentStudyLevel(
                 self.context.certificate,studylevel)
-            self.flash('Study level has been added.')
+            self.flash(_('Study level has been added.'))
         except KeyError:
-            self.flash('This level exists.')
+            self.flash(_('This level exists.'))
         self.redirect(self.url(self.context, u'@@manage')+'?tab2')
         return
 
-    @jsaction('Remove selected levels')
+    @jsaction(_('Remove selected levels'))
     def delStudyLevels(self, **data):
         form = self.request.form
@@ -607,5 +627,5 @@
             child_id = form['val_id']
         else:
-            self.flash('No study level selected.')
+            self.flash(_('No study level selected.'))
             self.redirect(self.url(self.context, '@@manage')+'?tab2')
             return
@@ -614,12 +634,9 @@
         deleted = []
         for id in child_id:
-            try:
-                del self.context[id]
-                deleted.append(id)
-            except:
-                self.flash('Could not delete %s: %s: %s' % (
-                        id, sys.exc_info()[0], sys.exc_info()[1]))
+            del self.context[id]
+            deleted.append(id)
         if len(deleted):
-            self.flash('Successfully removed: %s' % ', '.join(deleted))
+            self.flash(_('Successfully removed: ${a}',
+                mapping = {'a':', '.join(deleted)}))
         self.redirect(self.url(self.context, u'@@manage')+'?tab2')
         return
@@ -642,6 +659,11 @@
     @property
     def label(self):
-        return '%s: Study Level %s' % (
-            self.context.getStudent().display_fullname,self.context.level_title)
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        lang = self.request.cookies.get('sirp.language', portal_language)
+        level_title = translate(self.context.level_title, 'waeup.sirp',
+            target_language=lang)
+        return _('${a}: Study Level ${b}', mapping = {
+            'a':self.context.getStudent().display_fullname,
+            'b':level_title})
 
     @property
@@ -660,12 +682,37 @@
     form_fields = grok.AutoFields(IStudentStudyLevel)
     prefix = 'form'
-    title = 'Level Data'
-    content_title = 'Course List'
+
+    @property
+    def title(self):
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        return translate(_('Level Data'), 'waeup.sirp',
+            target_language=portal_language)
+
+    @property
+    def content_title(self):
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        return translate(_('Course List'), 'waeup.sirp',
+            target_language=portal_language)
 
     @property
     def label(self):
-        return 'Course Registration Slip %s' % self.context.level_title
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        lang = self.request.cookies.get('sirp.language', portal_language)
+        level_title = translate(self.context.level_title, 'waeup.sirp',
+            target_language=lang)
+        return translate(_('Course Registration Slip  '),
+            'waeup.sirp', target_language=portal_language) \
+            + ' %s' % level_title
 
     def render(self):
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        Sem = translate(_('Sem.'), 'waeup.sirp', target_language=portal_language)
+        Code = translate(_('Code'), 'waeup.sirp', target_language=portal_language)
+        Title = translate(_('Title'), 'waeup.sirp', target_language=portal_language)
+        Dept = translate(_('Dept.'), 'waeup.sirp', target_language=portal_language)
+        Faculty = translate(_('Faculty'), 'waeup.sirp', target_language=portal_language)
+        Cred = translate(_('Cred.'), 'waeup.sirp', target_language=portal_language)
+        Mand = translate(_('Mand.'), 'waeup.sirp', target_language=portal_language)
+        Score = translate(_('Score'), 'waeup.sirp', target_language=portal_language)
         studentview = StudentBaseDisplayFormPage(self.context.getStudent(),
             self.request)
@@ -676,10 +723,10 @@
             self, 'course_registration.pdf',
             self.context.getStudent(), studentview,
-            tableheader=[('Sem.','semester', 1.5),('Code','code', 2.5),
-                         ('Title','title', 5),
-                         ('Dept.','dcode', 1.5), ('Faculty','fcode', 1.5),
-                         ('Cred.', 'credits', 1.5),
-                         ('Mand.', 'mandatory', 1.5),
-                         ('Score', 'score', 1.5),('Auto', 'automatic', 1.5)
+            tableheader=[(Sem,'semester', 1.5),(Code,'code', 2.5),
+                         (Title,'title', 5),
+                         (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
+                         (Cred, 'credits', 1.5),
+                         (Mand, 'mandatory', 1.5),
+                         (Score, 'score', 1.5),('Auto', 'automatic', 1.5)
                          ],
             tabledata=tabledata)
@@ -694,6 +741,7 @@
     form_fields = grok.AutoFields(IStudentStudyLevel)
     pnav = 4
-    taboneactions = ['Save','Cancel']
-    tabtwoactions = ['Add course ticket','Remove selected tickets','Cancel']
+    taboneactions = [_('Save'),_('Cancel')]
+    tabtwoactions = [_('Add course ticket'),
+        _('Remove selected tickets'),_('Cancel')]
 
     def update(self):
@@ -711,16 +759,21 @@
     @property
     def label(self):
-        return 'Manage study level %s' % self.context.level_title
-
-    @action('Save', style='primary')
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        lang = self.request.cookies.get('sirp.language', portal_language)
+        level_title = translate(self.context.level_title, 'waeup.sirp',
+            target_language=lang)
+        return _('Manage study level ${a}',
+            mapping = {'a':level_title})
+
+    @action(_('Save'), style='primary')
     def save(self, **data):
         msave(self, **data)
         return
 
-    @action('Add course ticket')
+    @action(_('Add course ticket'))
     def addCourseTicket(self, **data):
         self.redirect(self.url(self.context, '@@add'))
 
-    @jsaction('Remove selected tickets')
+    @jsaction(_('Remove selected tickets'))
     def delCourseTicket(self, **data):
         form = self.request.form
@@ -728,5 +781,5 @@
             child_id = form['val_id']
         else:
-            self.flash('No ticket selected.')
+            self.flash(_('No ticket selected.'))
             self.redirect(self.url(self.context, '@@manage')+'?tab2')
             return
@@ -735,12 +788,9 @@
         deleted = []
         for id in child_id:
-            try:
-                del self.context[id]
-                deleted.append(id)
-            except:
-                self.flash('Could not delete %s: %s: %s' % (
-                        id, sys.exc_info()[0], sys.exc_info()[1]))
+            del self.context[id]
+            deleted.append(id)
         if len(deleted):
-            self.flash('Successfully removed: %s' % ', '.join(deleted))
+            self.flash(_('Successfully removed: ${a}',
+                mapping = {'a':', '.join(deleted)}))
         self.redirect(self.url(self.context, u'@@manage')+'?tab2')
         return
@@ -755,11 +805,11 @@
     def update(self):
         if str(self.context.__parent__.current_level) != self.context.__name__:
-            self.flash('This level does not correspond current level.')
+            self.flash(_('This level does not correspond current level.'))
         elif self.context.getStudent().state == REGISTERED:
             IWorkflowInfo(self.context.getStudent()).fireTransition(
                 'validate_courses')
-            self.flash('Course list has been validated.')
+            self.flash(_('Course list has been validated.'))
         else:
-            self.flash('Student is in the wrong state.')
+            self.flash(_('Student is in the wrong state.'))
         self.redirect(self.url(self.context))
         return
@@ -777,17 +827,17 @@
     def update(self):
         if str(self.context.__parent__.current_level) != self.context.__name__:
-            self.flash('This level does not correspond current level.')
+            self.flash(_('This level does not correspond current level.'))
             self.redirect(self.url(self.context))
             return
         elif self.context.getStudent().state == VALIDATED:
             IWorkflowInfo(self.context.getStudent()).fireTransition('reset8')
-            message = 'Course list request has been annulled'
+            message = _('Course list request has been annulled.')
             self.flash(message)
         elif self.context.getStudent().state == REGISTERED:
             IWorkflowInfo(self.context.getStudent()).fireTransition('reset7')
-            message = 'Course list request has been rejected'
+            message = _('Course list request has been rejected:')
             self.flash(message)
         else:
-            self.flash('Student is in the wrong state.')
+            self.flash(_('Student is in the wrong state.'))
             self.redirect(self.url(self.context))
             return
@@ -806,10 +856,10 @@
     grok.name('add')
     grok.require('waeup.manageStudent')
-    label = 'Add course ticket'
+    label = _('Add course ticket')
     form_fields = grok.AutoFields(ICourseTicketAdd).omit(
         'grade', 'score', 'automatic', 'carry_over')
     pnav = 4
 
-    @action('Add course ticket')
+    @action(_('Add course ticket'))
     def addCourseTicket(self, **data):
         ticket = CourseTicket()
@@ -826,11 +876,12 @@
             self.context.addCourseTicket(ticket)
         except KeyError:
-            self.flash('The ticket exists.')
-            return
-        self.flash('Successfully added %s.' % ticket.code)
+            self.flash(_('The ticket exists.'))
+            return
+        self.flash(_('Successfully added ${a}.',
+            mapping = {'a':ticket.code}))
         self.redirect(self.url(self.context, u'@@manage')+'?tab2')
         return
 
-    @action('Cancel')
+    @action(_('Cancel'))
     def cancel(self, **data):
         self.redirect(self.url(self.context))
@@ -848,6 +899,7 @@
     @property
     def label(self):
-        return '%s: Course Ticket %s' % (
-            self.context.getStudent().display_fullname,self.context.code)
+        return _('${a}: Course Ticket ${b}', mapping = {
+            'a':self.context.getStudent().display_fullname,
+            'b':self.context.code})
 
 class CourseTicketManageFormPage(SIRPEditFormPage):
@@ -863,5 +915,5 @@
     @property
     def label(self):
-        return 'Manage course ticket %s' % self.context.code
+        return _('Manage course ticket ${a}', mapping = {'a':self.context.code})
 
     @action('Save', style='primary')
@@ -890,5 +942,6 @@
     @property
     def label(self):
-        return '%s: Payments' % self.context.__parent__.display_fullname
+        return _('${a}: Payments',
+            mapping = {'a':self.context.__parent__.display_fullname})
 
     def update(self):
@@ -898,5 +951,5 @@
         return
 
-    @jsaction('Remove selected tickets')
+    @jsaction(_('Remove selected tickets'))
     def delPaymentTicket(self, **data):
         form = self.request.form
@@ -904,5 +957,5 @@
             child_id = form['val_id']
         else:
-            self.flash('No payment selected.')
+            self.flash(_('No payment selected.'))
             self.redirect(self.url(self.context))
             return
@@ -913,17 +966,14 @@
             # Students are not allowed to remove used payment tickets
             if not self.unremovable(self.context[id]):
-                try:
-                    del self.context[id]
-                    deleted.append(id)
-                except:
-                    self.flash('Could not delete %s: %s: %s' % (
-                            id, sys.exc_info()[0], sys.exc_info()[1]))
+                del self.context[id]
+                deleted.append(id)
         if len(deleted):
-            self.flash('Successfully removed: %s' % ', '.join(deleted))
+            self.flash(_('Successfully removed: ${a}',
+                mapping = {'a': ', '.join(deleted)}))
             write_log_message(self,'removed: % s' % ', '.join(deleted))
         self.redirect(self.url(self.context))
         return
 
-    @action('Add online payment ticket')
+    @action(_('Add online payment ticket'))
     def addPaymentTicket(self, **data):
         self.redirect(self.url(self.context, '@@addop'))
@@ -937,8 +987,8 @@
     form_fields = grok.AutoFields(IStudentOnlinePayment).select(
         'p_category')
-    label = 'Add online payment'
-    pnav = 4
-
-    @action('Create ticket', style='primary')
+    label = _('Add online payment')
+    pnav = 4
+
+    @action(_('Create ticket'), style='primary')
     def createTicket(self, **data):
         p_category = data['p_category']
@@ -948,6 +998,6 @@
             'configuration'].accommodation_session:
                 self.flash(
-                    'Your current session does not match '
-                    'accommodation session.')
+                    _('Your current session does not match ' + \
+                    'accommodation session.'))
                 self.redirect(self.url(self.context))
                 return
@@ -968,5 +1018,5 @@
                ticket.p_session == p_session:
                   self.flash(
-                      'This type of payment has already been made.')
+                      _('This type of payment has already been made.'))
                   self.redirect(self.url(self.context))
                   return
@@ -982,5 +1032,5 @@
         payment.surcharge_3 = pay_details['surcharge_3']
         self.context[payment.p_id] = payment
-        self.flash('Payment ticket created.')
+        self.flash(_('Payment ticket created.'))
         self.redirect(self.url(self.context))
         return
@@ -1001,6 +1051,7 @@
     @property
     def label(self):
-        return '%s: Online Payment Ticket %s' % (
-            self.context.getStudent().display_fullname,self.context.p_id)
+        return _('${a}: Online Payment Ticket ${b}', mapping = {
+            'a':self.context.getStudent().display_fullname,
+            'b':self.context.p_id})
 
 class OnlinePaymentCallbackPage(UtilityView, grok.View):
@@ -1016,5 +1067,5 @@
     def update(self):
         if self.context.p_state == 'paid':
-            self.flash('This ticket has already been paid.')
+            self.flash(_('This ticket has already been paid.'))
             return
         student = self.context.getStudent()
@@ -1029,5 +1080,6 @@
             pin, error = create_accesscode('CLR',0,student.student_id)
             if error:
-                self.flash('Valid callback received. ' + error)
+                self.flash(_('Valid callback received. ${a}',
+                    mapping = {'a':error}))
                 return
             self.context.ac = pin
@@ -1036,5 +1088,6 @@
             pin, error = create_accesscode('SFE',0,student.student_id)
             if error:
-                self.flash('Valid callback received. ' + error)
+                self.flash(_('Valid callback received. ${a}',
+                    mapping = {'a':error}))
                 return
             self.context.ac = pin
@@ -1043,8 +1096,9 @@
             pin, error = create_accesscode('HOS',0,student.student_id)
             if error:
-                self.flash('Valid callback received. ' + error)
+                self.flash(_('Valid callback received. ${a}',
+                    mapping = {'a':error}))
                 return
             self.context.ac = pin
-        self.flash('Valid callback received.')
+        self.flash(_('Valid callback received.'))
         return
 
@@ -1092,9 +1146,10 @@
     grok.template('accommodationmanagepage')
     pnav = 4
-    officers_only_actions = ['Remove selected']
+    officers_only_actions = [_('Remove selected')]
 
     @property
     def label(self):
-        return '%s: Accommodation' % self.context.__parent__.display_fullname
+        return _('${a}: Accommodation',
+            mapping = {'a':self.context.__parent__.display_fullname})
 
     def update(self):
@@ -1104,8 +1159,8 @@
         return
 
-    @jsaction('Remove selected')
+    @jsaction(_('Remove selected'))
     def delBedTickets(self, **data):
         if getattr(self.request.principal, 'user_type', None) == 'student':
-            self.flash('You are not allowed to remove bed tickets.')
+            self.flash(_('You are not allowed to remove bed tickets.'))
             self.redirect(self.url(self.context))
             return
@@ -1114,5 +1169,5 @@
             child_id = form['val_id']
         else:
-            self.flash('No bed ticket selected.')
+            self.flash(_('No bed ticket selected.'))
             self.redirect(self.url(self.context))
             return
@@ -1124,5 +1179,6 @@
             deleted.append(id)
         if len(deleted):
-            self.flash('Successfully removed: %s' % ', '.join(deleted))
+            self.flash(_('Successfully removed: ${a}',
+                mapping = {'a':', '.join(deleted)}))
             write_log_message(self,'removed: % s' % ', '.join(deleted))
         self.redirect(self.url(self.context))
@@ -1144,7 +1200,7 @@
     grok.template('enterpin')
     ac_prefix = 'HOS'
-    label = 'Add bed ticket'
-    pnav = 4
-    buttonname = 'Create bed ticket'
+    label = _('Add bed ticket')
+    pnav = 4
+    buttonname = _('Create bed ticket')
     notice = ''
 
@@ -1154,9 +1210,9 @@
         acc_details  = students_utils.getAccommodationDetails(student)
         if not acc_details:
-            self.flash("Your data are incomplete.")
+            self.flash(_("Your data are incomplete."))
             self.redirect(self.url(self.context))
             return
         if not student.state in acc_details['allowed_states']:
-            self.flash("You are in the wrong registration state.")
+            self.flash(_("You are in the wrong registration state."))
             self.redirect(self.url(self.context))
             return
@@ -1164,11 +1220,11 @@
             'booking_session']:
             self.flash(
-                'Your current session does not match accommodation session.')
+                _('Your current session does not match accommodation session.'))
             self.redirect(self.url(self.context))
             return
         if str(acc_details['booking_session']) in self.context.keys():
             self.flash(
-                'You already booked a bed space in current '
-                'accommodation session.')
+                _('You already booked a bed space in current ' \
+                    + 'accommodation session.'))
             self.redirect(self.url(self.context))
             return
@@ -1180,5 +1236,5 @@
         code = get_access_code(pin)
         if not code:
-            self.flash('Activation code is invalid.')
+            self.flash(_('Activation code is invalid.'))
             return
         # Search and book bed
@@ -1200,19 +1256,18 @@
                 bed.bookBed(student.student_id)
             else:
-                self.flash('There is no free bed in your category %s.'
-                            % acc_details['bt'])
+                self.flash(_('There is no free bed in your category ${a}.',
+                    mapping = {'a':acc_details['bt']}))
                 return
         # Mark pin as used (this also fires a pin related transition)
         if code.state == USED:
-            self.flash('Activation code has already been used.')
+            self.flash(_('Activation code has already been used.'))
             return
         else:
-            comment = u"AC invalidated for %s" % (
-                self.context.getStudent().student_id,)
+            comment = _(u'invalidated')
             # Here we know that the ac is in state initialized so we do not
             # expect an exception, but the owner might be different
             if not invalidate_accesscode(
                 pin,comment,self.context.getStudent().student_id):
-                self.flash('You are not the owner of this access code.')
+                self.flash(_('You are not the owner of this access code.'))
                 return
         # Create bed ticket
@@ -1225,10 +1280,15 @@
         coordinates = bed.getBedCoordinates()[1:]
         block, room_nr, bed_nr = coordinates
-        bedticket.bed_coordinates = '%s, Block %s, Room %s, Bed %s (%s)' % (
-            hall_title, block, room_nr, bed_nr, bed.bed_type)
+        bc = _('${a}, Block ${b}, Room ${c}, Bed ${d} (${e})', mapping = {
+            'a':hall_title, 'b':block,
+            'c':room_nr, 'd':bed_nr,
+            'e':bed.bed_type})
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        bedticket.bed_coordinates = translate(
+            bc, 'waeup.sirp',target_language=portal_language)
         key = str(acc_details['booking_session'])
         self.context[key] = bedticket
-        self.flash('Bed ticket created and bed booked: %s'
-            % bedticket.bed_coordinates)
+        self.flash(_('Bed ticket created and bed booked: ${a}',
+            mapping = {'a':bedticket.bed_coordinates}))
         self.redirect(self.url(self.context))
         return
@@ -1247,5 +1307,6 @@
     @property
     def label(self):
-        return 'Bed Ticket for Session %s' % self.context.getSessionString()
+        return _('Bed Ticket for Session ${a}',
+            mapping = {'a':self.context.getSessionString()})
 
 class ExportPDFBedTicketSlipPage(UtilityView, grok.View):
@@ -1258,9 +1319,17 @@
     form_fields['booking_date'].custom_widget = FriendlyDateDisplayWidget('le')
     prefix = 'form'
-    title = 'Bed Allocation Data'
+
+    @property
+    def title(self):
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        return translate(_('Bed Allocation Data'), 'waeup.sirp',
+            target_language=portal_language)
 
     @property
     def label(self):
-        return 'Bed Allocation: %s' % self.context.bed_coordinates
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        return translate(_('Bed Allocation: '),
+            'waeup.sirp', target_language=portal_language) \
+            + ' %s' % self.context.bed_coordinates
 
     def render(self):
@@ -1287,5 +1356,5 @@
         if self.context.bed != None and \
               'reserved' in self.context.bed.bed_type:
-            self.flash("Students in reserved beds can't be relocated.")
+            self.flash(_("Students in reserved beds can't be relocated."))
             self.redirect(self.url(self.context))
             return
@@ -1293,5 +1362,5 @@
                 self.context.bed != None and \
                 self.context.bed.bed_type == self.context.bed_type:
-            self.flash("Student can't be relocated.")
+            self.flash(_("Student can't be relocated."))
             self.redirect(self.url(self.context))
             return
@@ -1315,6 +1384,6 @@
                 new_bed.bookBed(student.student_id)
             else:
-                self.flash('There is no free bed in your category %s.'
-                            % acc_details['bt'])
+                self.flash(_('There is no free bed in your category ${a}.',
+                    mapping = {'a':acc_details['bt']}))
                 self.redirect(self.url(self.context))
                 return
@@ -1329,7 +1398,13 @@
         coordinates = new_bed.getBedCoordinates()[1:]
         block, room_nr, bed_nr = coordinates
-        self.context.bed_coordinates = '%s, Block %s, Room %s, Bed %s (%s)' % (
-            hall_title, block, room_nr, bed_nr, new_bed.bed_type)
-        self.flash('Student relocated: %s' % self.context.bed_coordinates)
+        bc = _('${a}, Block ${b}, Room ${c}, Bed ${d} (${e})', mapping = {
+            'a':hall_title, 'b':block,
+            'c':room_nr, 'd':bed_nr,
+            'e':new_bed.bed_type})
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        self.context.bed_coordinates = translate(
+            bc, 'waeup.sirp',target_language=portal_language)
+        self.flash(_('Student relocated: ${a}',
+            mapping = {'a':self.context.bed_coordinates}))
         self.redirect(self.url(self.context))
         return
@@ -1349,5 +1424,5 @@
     @property
     def label(self):
-        return '%s: History' % self.context.display_fullname
+        return _('${a}: History', mapping = {'a':self.context.display_fullname})
 
 # Pages for students only
@@ -1361,8 +1436,8 @@
     form_fields = grok.AutoFields(IStudentBase).select(
         'email', 'phone')
-    label = 'Edit base data'
-    pnav = 4
-
-    @action('Save', style='primary')
+    label = _('Edit base data')
+    pnav = 4
+
+    @action(_('Save'), style='primary')
     def save(self, **data):
         msave(self, **data)
@@ -1376,8 +1451,8 @@
     grok.require('waeup.handleStudent')
     grok.template('change_password')
-    label = 'Change password'
-    pnav = 4
-
-    @action('Save', style='primary')
+    label = _('Change password')
+    pnav = 4
+
+    @action(_('Save'), style='primary')
     def save(self, **data):
         form = self.request.form
@@ -1390,5 +1465,5 @@
                 IUserAccount(self.context).setPassword(password)
                 write_log_message(self, 'saved: password')
-                self.flash('Password changed.')
+                self.flash(_('Password changed.'))
             else:
                 self.flash( ' '.join(errors))
@@ -1402,5 +1477,5 @@
     grok.require('waeup.uploadStudentFile')
     grok.template('filesuploadpage')
-    label = 'Upload portrait'
+    label = _('Upload portrait')
     pnav = 4
 
@@ -1417,9 +1492,9 @@
     grok.require('waeup.handleStudent')
     grok.template('enterpin')
-    label = 'Start clearance'
+    label = _('Start clearance')
     ac_prefix = 'CLR'
     notice = ''
     pnav = 4
-    buttonname = 'Start clearance now'
+    buttonname = _('Start clearance now')
 
     @property
@@ -1438,13 +1513,13 @@
     def update(self, SUBMIT=None):
         if not self.context.state == ADMITTED:
-            self.flash("Wrong state.")
+            self.flash(_("Wrong state."))
             self.redirect(self.url(self.context))
             return
         if not self.portrait_uploaded:
-            self.flash("No portrait uploaded.")
+            self.flash(_("No portrait uploaded."))
             self.redirect(self.url(self.context, 'change_portrait'))
             return
         if not self.all_required_fields_filled:
-            self.flash("Not all required fields filled.")
+            self.flash(_("Not all required fields filled."))
             self.redirect(self.url(self.context, 'edit_base'))
             return
@@ -1457,21 +1532,21 @@
         code = get_access_code(pin)
         if not code:
-            self.flash('Activation code is invalid.')
+            self.flash(_('Activation code is invalid.'))
             return
         # Mark pin as used (this also fires a pin related transition)
         # and fire transition start_clearance
         if code.state == USED:
-            self.flash('Activation code has already been used.')
+            self.flash(_('Activation code has already been used.'))
             return
         else:
-            comment = u"AC invalidated for %s" % self.context.student_id
+            comment = _(u"invalidated")
             # Here we know that the ac is in state initialized so we do not
             # expect an exception, but the owner might be different
             if not invalidate_accesscode(pin,comment,self.context.student_id):
-                self.flash('You are not the owner of this access code.')
+                self.flash(_('You are not the owner of this access code.'))
                 return
             self.context.clr_code = pin
         IWorkflowInfo(self.context).fireTransition('start_clearance')
-        self.flash('Clearance process has been started.')
+        self.flash(_('Clearance process has been started.'))
         self.redirect(self.url(self.context,'cedit'))
         return
@@ -1485,5 +1560,5 @@
     form_fields = grok.AutoFields(
         IStudentClearance).omit('clearance_locked')
-    label = 'Edit clearance data'
+    label = _('Edit clearance data')
     form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
 
@@ -1494,8 +1569,8 @@
         return super(StudentClearanceEditFormPage, self).update()
 
-    @action('Save', style='primary')
+    @action(_('Save'), style='primary')
     def save(self, **data):
         self.applyData(self.context, **data)
-        self.flash('Clearance form has been saved.')
+        self.flash(_('Clearance form has been saved.'))
         return
 
@@ -1505,5 +1580,5 @@
         return False
 
-    @action('Save and request clearance', style='primary')
+    @action(_('Save and request clearance'), style='primary')
     def requestClearance(self, **data):
         self.applyData(self.context, **data)
@@ -1511,5 +1586,5 @@
             self.flash(self.dataNotComplete())
             return
-        self.flash('Clearance form has been saved.')
+        self.flash(_('Clearance form has been saved.'))
         self.redirect(self.url(self.context,'request_clearance'))
         return
@@ -1520,9 +1595,9 @@
     grok.require('waeup.handleStudent')
     grok.template('enterpin')
-    label = 'Request clearance'
-    notice = 'Enter the CLR access code used for starting clearance.'
+    label = _('Request clearance')
+    notice = _('Enter the CLR access code used for starting clearance.')
     ac_prefix = 'CLR'
     pnav = 4
-    buttonname = 'Request clearance now'
+    buttonname = _('Request clearance now')
 
     def update(self, SUBMIT=None):
@@ -1533,5 +1608,5 @@
         pin = '%s-%s-%s' % (self.ac_prefix, self.ac_series, self.ac_number)
         if self.context.clr_code != pin:
-            self.flash("This isn't your CLR access code.")
+            self.flash(_("This isn't your CLR access code."))
             return
         state = IWorkflowState(self.context).getState()
@@ -1539,8 +1614,8 @@
         # might have forgotten to lock the form after changing the state
         if state != CLEARANCE:
-            self.flash('This form cannot be submitted. Wrong state!')
+            self.flash(_('This form cannot be submitted. Wrong state!'))
             return
         IWorkflowInfo(self.context).fireTransition('request_clearance')
-        self.flash('Clearance has been requested.')
+        self.flash(_('Clearance has been requested.'))
         self.redirect(self.url(self.context))
         return
@@ -1551,13 +1626,13 @@
     grok.require('waeup.handleStudent')
     grok.template('enterpin')
-    label = 'Start course registration'
+    label = _('Start course registration')
     ac_prefix = 'SFE'
     notice = ''
     pnav = 4
-    buttonname = 'Start course registration now'
+    buttonname = _('Start course registration now')
 
     def update(self, SUBMIT=None):
         if not self.context.getStudent().state in (CLEARED,RETURNING):
-            self.flash("Wrong state.")
+            self.flash(_("Wrong state."))
             self.redirect(self.url(self.context))
             return
@@ -1570,19 +1645,18 @@
         code = get_access_code(pin)
         if not code:
-            self.flash('Activation code is invalid.')
+            self.flash(_('Activation code is invalid.'))
             return
         # Mark pin as used (this also fires a pin related transition)
         # and fire transition start_clearance
         if code.state == USED:
-            self.flash('Activation code has already been used.')
+            self.flash(_('Activation code has already been used.'))
             return
         else:
-            comment = u"AC invalidated for %s" % (
-                self.context.getStudent().student_id,)
+            comment = _(u"invalidated")
             # Here we know that the ac is in state initialized so we do not
             # expect an exception, but the owner might be different
             if not invalidate_accesscode(
                 pin,comment,self.context.getStudent().student_id):
-                self.flash('You are not the owner of this access code.')
+                self.flash(_('You are not the owner of this access code.'))
                 return
         if self.context.getStudent().state == CLEARED:
@@ -1592,5 +1666,5 @@
             IWorkflowInfo(self.context.getStudent()).fireTransition(
                 'pay_school_fee')
-        self.flash('Course registration has been started.')
+        self.flash(_('Course registration has been started.'))
         self.redirect(self.url(self.context))
         return
@@ -1611,5 +1685,5 @@
         code = self.context.current_level
         title = studylevelsource.getTitle(self.context, code)
-        return 'Add current level %s' % title
+        return _('Add current level ${a}', mapping = {'a':title})
 
     def update(self):
@@ -1620,5 +1694,5 @@
         return
 
-    @action('Create course list now', style='primary')
+    @action(_('Create course list now'), style='primary')
     def addStudyLevel(self, **data):
         studylevel = StudentStudyLevel()
@@ -1629,5 +1703,5 @@
                 self.context.certificate,studylevel)
         except KeyError:
-            self.flash('This level exists.')
+            self.flash(_('This level exists.'))
         self.redirect(self.url(self.context))
         return
@@ -1655,6 +1729,10 @@
     @property
     def label(self):
-        return 'Add and remove course tickets of study level %s' % (
-            self.context.level_title,)
+        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
+        lang = self.request.cookies.get('sirp.language', portal_language)
+        level_title = translate(self.context.level_title, 'waeup.sirp',
+            target_language=lang)
+        return _('Add and remove course tickets of study level ${a}',
+            mapping = {'a':level_title})
 
     @property
@@ -1665,9 +1743,9 @@
         return total_credits
 
-    @action('Add course ticket')
+    @action(_('Add course ticket'))
     def addCourseTicket(self, **data):
         self.redirect(self.url(self.context, 'ctadd'))
 
-    @jsaction('Remove selected tickets')
+    @jsaction(_('Remove selected tickets'))
     def delCourseTicket(self, **data):
         form = self.request.form
@@ -1675,5 +1753,5 @@
             child_id = form['val_id']
         else:
-            self.flash('No ticket selected.')
+            self.flash(_('No ticket selected.'))
             self.redirect(self.url(self.context, '@@edit'))
             return
@@ -1684,20 +1762,17 @@
             # Students are not allowed to remove core tickets
             if not self.context[id].mandatory:
-                try:
-                    del self.context[id]
-                    deleted.append(id)
-                except:
-                    self.flash('Could not delete %s: %s: %s' % (
-                            id, sys.exc_info()[0], sys.exc_info()[1]))
+                del self.context[id]
+                deleted.append(id)
         if len(deleted):
-            self.flash('Successfully removed: %s' % ', '.join(deleted))
+            self.flash(_('Successfully removed: ${a}',
+                mapping = {'a':', '.join(deleted)}))
         self.redirect(self.url(self.context, u'@@edit'))
         return
 
-    @action('Register course list', style='primary')
+    @action(_('Register course list'), style='primary')
     def RegisterCourses(self, **data):
         IWorkflowInfo(self.context.getStudent()).fireTransition(
             'register_courses')
-        self.flash('Course list has been registered.')
+        self.flash(_('Course list has been registered.'))
         self.redirect(self.url(self.context))
         return
@@ -1718,5 +1793,5 @@
         return
 
-    @action('Add course ticket')
+    @action(_('Add course ticket'))
     def addCourseTicket(self, **data):
         # Safety belt
@@ -1731,7 +1806,8 @@
             self.context.addCourseTicket(ticket)
         except KeyError:
-            self.flash('The ticket exists.')
-            return
-        self.flash('Successfully added %s.' % ticket.code)
+            self.flash(_('The ticket exists.'))
+            return
+        self.flash(_('Successfully added ${a}.',
+            mapping = {'a':ticket.code}))
         self.redirect(self.url(self.context, u'@@edit'))
         return
@@ -1744,5 +1820,5 @@
     grok.require('waeup.Anonymous')
     grok.template('changepw')
-    label = 'Change my password'
+    label = _('Change my password')
     form_fields = grok.AutoFields(IStudentChangePassword)
 
@@ -1754,5 +1830,5 @@
         return
 
-    @action('Get new login credentials', style='primary')
+    @action(_('Get new login credentials'), style='primary')
     def request(self, **data):
         if not self.captcha_result.is_valid:
@@ -1768,5 +1844,5 @@
             email=(email,email))
         if len(results) == 0:
-            self.flash('No student record found.')
+            self.flash(_('No student record found.'))
             return
         student = list(results)[0]
@@ -1781,8 +1857,8 @@
             IUserAccount(student),pwd,login_url,msg)
         if success:
-            self.flash('An email with your user name and password ' +
-                'has been sent to %s.' % email)
+            self.flash(_('An email with your user name and password ' +
+                'has been sent to ${a}.', mapping = {'a':email}))
         else:
-            self.flash('An smtp server error occurred.')
+            self.flash(_('An smtp server error occurred.'))
         return
 
@@ -1792,5 +1868,5 @@
     grok.require('waeup.Anonymous')
     grok.template('setpassword')
-    label = 'Set password for first-time login'
+    label = _('Set password for first-time login')
     ac_prefix = 'PWD'
     pnav = 0
@@ -1806,8 +1882,8 @@
             searchtype='reg_number', view=self)
         if not hitlist:
-            self.flash('No student found.')
+            self.flash(_('No student found.'))
             return
         if len(hitlist) != 1:   # Cannot happen but anyway
-            self.flash('More than one student found.')
+            self.flash(_('More than one student found.'))
             return
         student = hitlist[0].context
@@ -1817,22 +1893,23 @@
         code = get_access_code(pin)
         if not code:
-            self.flash('Access code is invalid.')
+            self.flash(_('Access code is invalid.'))
             return
         if student_pw and pin == student.adm_code:
-            self.flash('Password has already been set. Your Student Id is %s'
-                % self.student_id)
+            self.flash(_(
+                'Password has already been set. Your Student Id is ${a}',
+                mapping = {'a':self.student_id}))
             return
         elif student_pw:
             self.flash(
-                'Password has already been set. You are using the '
-                'wrong Access Code.')
+                _('Password has already been set. You are using the ' +
+                'wrong Access Code.'))
             return
         # Mark pin as used (this also fires a pin related transition)
         # and set student password
         if code.state == USED:
-            self.flash('Access code has already been used.')
+            self.flash(_('Access code has already been used.'))
             return
         else:
-            comment = u"AC invalidated for %s" % self.student_id
+            comment = _(u"invalidated")
             # Here we know that the ac is in state initialized so we do not
             # expect an exception
@@ -1840,5 +1917,5 @@
             IUserAccount(student).setPassword(self.ac_number)
             student.adm_code = pin
-        self.flash('Password has been set. Your Student Id is %s'
-            % self.student_id)
-        return
+        self.flash(_('Password has been set. Your Student Id is ${a}',
+            mapping = {'a':self.student_id}))
+        return
Index: main/waeup.sirp/trunk/src/waeup/sirp/students/interfaces.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/interfaces.py	(revision 7714)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/interfaces.py	(revision 7723)
@@ -23,4 +23,5 @@
 from waeup.sirp.interfaces import (
     ISIRPObject, academic_sessions_vocab, validate_email, ISIRPUtils)
+from waeup.sirp.interfaces import MessageFactory as _
 from waeup.sirp.schema import TextLineChoice
 from waeup.sirp.university.vocabularies import CourseSource, StudyModeSource
@@ -146,25 +147,25 @@
 
     student_id = schema.TextLine(
-        title = u'Student Id',
+        title = _(u'Student Id'),
         required = False,
         )
 
     firstname = schema.TextLine(
-        title = u'First Name',
+        title = _(u'First Name'),
         required = True,
         )
 
     middlename = schema.TextLine(
-        title = u'Middle Name',
+        title = _(u'Middle Name'),
         required = False,
         )
 
     lastname = schema.TextLine(
-        title = u'Last Name (Surname)',
+        title = _(u'Last Name (Surname)'),
         required = True,
         )
 
     sex = schema.Choice(
-        title = u'Sex',
+        title = _(u'Sex'),
         source = GenderSource(),
         default = u'm',
@@ -173,5 +174,5 @@
 
     reg_number = TextLineChoice(
-        title = u'Registration Number',
+        title = _(u'Registration Number'),
         required = True,
         readonly = False,
@@ -180,5 +181,5 @@
 
     matric_number = TextLineChoice(
-        title = u'Matriculation Number',
+        title = _(u'Matriculation Number'),
         #default = u'',
         required = False,
@@ -188,5 +189,5 @@
 
     adm_code = schema.TextLine(
-        title = u'PWD Activation Code',
+        title = _(u'PWD Activation Code'),
         default = u'',
         required = False,
@@ -195,10 +196,10 @@
 
     email = schema.ASCIILine(
-        title = u'Email',
+        title = _(u'Email'),
         required = False,
         constraint=validate_email,
         )
     phone = schema.TextLine(
-        title = u'Phone',
+        title = _(u'Phone'),
         description = u'',
         required = False,
@@ -210,15 +211,15 @@
     """
     date_of_birth = schema.Date(
-        title = u'Date of Birth',
+        title = _(u'Date of Birth'),
         required = True,
         )
 
     clearance_locked = schema.Bool(
-        title = u'Clearance form locked',
+        title = _(u'Clearance form locked'),
         default = False,
         )
 
     clr_code = schema.TextLine(
-        title = u'CLR Activation Code',
+        title = _(u'CLR Activation Code'),
         default = u'',
         required = False,
@@ -228,5 +229,5 @@
     nationality = schema.Choice(
         source = nats_vocab,
-        title = u'Nationality',
+        title = _(u'Nationality'),
         default = 'nigeria',
         required = True,
@@ -238,5 +239,5 @@
     """
     perm_address = schema.Text(
-        title = u'Permanent Address',
+        title = _(u'Permanent Address'),
         required = False,
         )
@@ -252,5 +253,5 @@
     """
     reg_number = schema.TextLine(
-        title = u'Registration Number',
+        title = _(u'Registration Number'),
         default = None,
         required = False,
@@ -262,5 +263,5 @@
     """
     matric_number = schema.TextLine(
-        title = u'Matriculation Number',
+        title = _(u'Matriculation Number'),
         default = None,
         required = False,
@@ -272,5 +273,5 @@
     """
     certificate = schema.Choice(
-        title = u'Certificate',
+        title = _(u'Certificate'),
         source = CertificateSource(),
         default = None,
@@ -279,5 +280,5 @@
 
     entry_mode = schema.Choice(
-        title = u'Entry Mode',
+        title = _(u'Entry Mode'),
         source = StudyModeSource(),
         default = u'ug_ft',
@@ -287,5 +288,5 @@
 
     entry_session = schema.Choice(
-        title = u'Entry Session',
+        title = _(u'Entry Session'),
         source = academic_sessions_vocab,
         #default = datetime.now().year,
@@ -296,5 +297,5 @@
 
     current_session = schema.Choice(
-        title = u'Current Session',
+        title = _(u'Current Session'),
         source = academic_sessions_vocab,
         default = None,
@@ -304,5 +305,5 @@
 
     current_level = schema.Choice(
-        title = u'Current Level',
+        title = _(u'Current Level'),
         source = StudyLevelSource(),
         default = None,
@@ -312,5 +313,5 @@
 
     current_verdict = schema.Choice(
-        title = u'Current Verdict',
+        title = _(u'Current Verdict'),
         source = VerdictSource(),
         default = '0',
@@ -319,5 +320,5 @@
 
     previous_verdict = schema.Choice(
-        title = u'Previous Verdict',
+        title = _(u'Previous Verdict'),
         source = VerdictSource(),
         default = '0',
@@ -334,5 +335,5 @@
 
     level_session = schema.Choice(
-        title = u'Session',
+        title = _(u'Session'),
         source = academic_sessions_vocab,
         default = None,
@@ -341,5 +342,5 @@
 
     level_verdict = schema.Choice(
-        title = u'Verdict',
+        title = _(u'Verdict'),
         source = VerdictSource(),
         default = '0',
@@ -360,5 +361,5 @@
 
     mandatory = schema.Bool(
-        title = u'Mandatory',
+        title = _(u'Mandatory'),
         default = False,
         required = False,
@@ -367,5 +368,5 @@
 
     score = schema.Int(
-        title = u'Score',
+        title = _(u'Score'),
         default = 0,
         required = False,
@@ -374,5 +375,5 @@
 
     automatic = schema.Bool(
-        title = u'Automatical Creation',
+        title = _(u'Automatical Creation'),
         default = False,
         required = False,
@@ -381,5 +382,5 @@
 
     carry_over = schema.Bool(
-        title = u'Carry-over Course',
+        title = _(u'Carry-over Course'),
         default = False,
         required = False,
@@ -400,5 +401,5 @@
     """
     course = schema.Choice(
-        title = u'Course',
+        title = _(u'Course'),
         source = CourseSource(),
         readonly = False,
@@ -417,5 +418,5 @@
 
     bed_coordinates = schema.TextLine(
-        title = u'Bed Coordinates',
+        title = _(u'Bed Coordinates'),
         default = None,
         required = False,
@@ -424,5 +425,5 @@
 
     bed_type = schema.TextLine(
-        title = u'Bed Type',
+        title = _(u'Bed Type'),
         default = None,
         required = False,
@@ -431,5 +432,5 @@
 
     booking_session = schema.Choice(
-        title = u'Session',
+        title = _(u'Session'),
         source = academic_sessions_vocab,
         default = None,
@@ -439,5 +440,5 @@
 
     booking_date = schema.Datetime(
-        title = u'Booking Date',
+        title = _(u'Booking Date'),
         required = False,
         readonly = True,
@@ -445,5 +446,5 @@
 
     booking_code = schema.TextLine(
-        title = u'Booking Activation Code',
+        title = _(u'Booking Activation Code'),
         default = u'',
         required = False,
@@ -466,5 +467,5 @@
     """
     p_session = schema.Choice(
-        title = u'Payment Session',
+        title = _(u'Payment Session'),
         source = academic_sessions_vocab,
         required = False,
@@ -480,5 +481,5 @@
 
     reg_number = schema.TextLine(
-        title = u'Registration Number',
+        title = _(u'Registration Number'),
         default = None,
         required = True,
@@ -487,5 +488,5 @@
 
     email = schema.ASCIILine(
-        title = u'Email Address',
+        title = _(u'Email Address'),
         required = True,
         constraint=validate_email,
Index: main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py	(revision 7714)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py	(revision 7723)
@@ -865,5 +865,5 @@
         self.browser.getLink("Reject clearance").click()
         self.assertTrue('Clearance has been annulled' in self.browser.contents)
-        urlmessage = 'Clearance+has+been+annulled'
+        urlmessage = 'Clearance+has+been+annulled.'
         # CO does now see the contact form
         self.assertEqual(self.browser.url, self.student_path +
@@ -884,5 +884,5 @@
         # clearance requested
         self.browser.open(self.student_path + '/clear')
-        self.assertTrue('Student is in the wrong state'
+        self.assertTrue('Student is in wrong state'
             in self.browser.contents)
         # The CO can go to his department throug the my_roles page
@@ -968,7 +968,7 @@
         self.assertTrue('courses validated' in self.browser.contents)
         self.browser.getLink("Reject courses").click()
-        self.assertTrue('Course list request has been annulled'
+        self.assertTrue('Course list request has been annulled.'
             in self.browser.contents)
-        urlmessage = 'Course+list+request+has+been+annulled'
+        urlmessage = 'Course+list+request+has+been+annulled.'
         self.assertEqual(self.browser.url, self.student_path +
             '/contactstudent?subject=%s' % urlmessage)
