From c6655c82ebcfd517da23e7803236a93968895d42 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Thu, 3 Aug 2017 13:09:49 +0200
Subject: [PATCH] OO-2941: upgrade quartz and spring framework, refactor
 I18nModule to prevent dependency cycle

---
 pom.xml                                       |   4 +-
 .../bps/course/nodes/vc/_spring/vcContext.xml |   4 +-
 .../links/LinksPortletRunController.java      |  11 +-
 .../bps/onyx/plugin/_spring/onyxContext.xml   |   6 +-
 .../NotificationsEmailAdminController.java    |  37 +-
 .../SystemRegistrationManager.java            |  31 +-
 .../statistics/StatisticsAdminController.java |  71 +--
 .../olat/admin/user/SendTokenToUserForm.java  |  10 +-
 .../org/olat/admin/user/imp/ImportStep00.java |  11 +-
 .../org/olat/basesecurity/AuthHelper.java     |   8 +-
 .../_spring/baseSecurityContext.xml           |   5 +-
 .../calendar/_spring/calendarContext.xml      |   4 +-
 .../org/olat/core/_spring/mainCorecontext.xml |   7 +-
 .../impressum/ImpressumAdminController.java   |   6 +-
 .../fullWebApp/BaseFullWebappController.java  |  15 +-
 .../_spring/notificationsContext.xml          |   6 +-
 .../scheduler/_spring/schedulerContext.xml    |  16 +-
 .../_spring/taskExecutorCorecontext.xml       |   4 +-
 .../manager/TaskExecutorManagerImpl.java      |   5 +-
 .../configuration/AbstractOLATModule.java     | 347 ------------
 .../velocity/VelocityRenderDecorator.java     |   8 +-
 .../gui/translator/PackageTranslator.java     |  17 +-
 .../logging/LogRealTimeViewerController.java  | 118 +++--
 .../olat/core/servlets/OpenOLATServlet.java   |   3 -
 .../core/util/_spring/utilCorecontext.xml     |   2 +-
 .../util/i18n/I18nDirectoriesVisitor.java     |   7 +-
 .../org/olat/core/util/i18n/I18nManager.java  | 397 ++++----------
 .../org/olat/core/util/i18n/I18nModule.java   | 496 ++++++++++++------
 .../util/i18n/_spring/i18nCorecontext.xml     | 117 -----
 .../devtools/TranslationDevController.java    |  10 +-
 .../TranslationDevMainController.java         |  20 +-
 .../i18n/devtools/TranslationDevManager.java  | 121 ++---
 .../devtools/_spring/devtoolsCorecontext.xml  |   3 -
 .../util/i18n/ui/I18nConfigController.java    |  27 +-
 .../ui/I18nConfigSubDeleteLangController.java |  18 +-
 .../I18nConfigSubDeletePackageController.java |   6 +-
 .../ui/I18nConfigSubExportLangController.java |  11 +-
 .../ui/I18nConfigSubImportLangController.java |  18 +-
 .../ui/I18nConfigSubNewLangController.java    |   6 +-
 ...TranslationInterceptHandlerController.java |  23 +-
 .../ui/SingleKeyTranslatorController.java     |  11 +-
 ...lationToolI18nItemEditCrumbController.java |  23 +-
 .../ui/TranslationToolLauncherController.java |  15 +-
 .../TranslationToolStartCrumbController.java  | 108 ++--
 .../assessment/_spring/assessmentContext.xml  |   4 +-
 .../manager/CertificatesManagerImpl.java      |   2 +-
 .../site/ui/CourseSiteAdminController.java    |   6 +-
 .../statistic/MySQLTempStatTableCreator.java  |   5 +-
 .../_spring/statisticsJobContext.xml          |   6 +-
 .../org/olat/dispatcher/LocaleNegotiator.java |   6 +-
 .../qti/render/LocalizedXSLTransformer.java   |   8 +-
 .../java/org/olat/ldap/LDAPLoginModule.java   |  24 +-
 .../login/LoginAuthprovidersController.java   |   6 +-
 .../lecture/_spring/lectureContext.xml        |  12 +-
 .../ui/_i18n/LocalStrings_en.properties       |   8 +-
 .../olat/modules/reminder/ReminderModule.java |  19 +-
 .../reminder/_spring/reminderContext.xml      |   4 +-
 .../modules/video/_spring/videoContext.xml    |   4 +-
 .../video/manager/VideoManagerImpl.java       |   7 +-
 .../video/manager/VideoTranscodingJob.java    |   3 +-
 .../org/olat/modules/vitero/ViteroModule.java |  32 +-
 .../portfolio/_spring/portfolioContext.xml    |  12 +-
 .../LanguageChooserController.java            |  10 +-
 .../olat/registration/PwChangeController.java |  13 +-
 .../registration/RegistrationController.java  |  18 +-
 .../olat/registration/RegistrationForm2.java  |   4 +-
 .../restapi/RegistrationWebService.java       |   4 +-
 .../repository/_spring/repositoryContext.xml  |   4 +-
 .../accesscontrol/_spring/acContext.xml       |   4 +-
 .../olat/restapi/_spring/restApiContext.xml   |  14 +-
 .../org/olat/restapi/i18n/I18nWebService.java |   8 +-
 .../system/NotificationsAdminWebService.java  |  11 +-
 .../search/service/SearchServiceImpl.java     |  14 +-
 .../org/olat/user/ChangePrefsController.java  |  10 +-
 .../olat/user/PreferencesFormController.java  |   6 +-
 .../user/_i18n/LocalStrings_en.properties     |   4 +-
 .../services/scheduler/SchedulerTest.java     |  25 +-
 .../org/olat/core/util/i18n/I18nTest.java     | 103 ++--
 .../accesscontrol/ACReservationDAOTest.java   |   3 +-
 79 files changed, 1108 insertions(+), 1508 deletions(-)
 delete mode 100644 src/main/java/org/olat/core/configuration/AbstractOLATModule.java
 delete mode 100644 src/main/java/org/olat/core/util/i18n/_spring/i18nCorecontext.xml

diff --git a/pom.xml b/pom.xml
index 8089884104f..9efdf9727a7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<targetJdk>1.8</targetJdk>
-		<org.springframework.version>3.2.18.RELEASE</org.springframework.version>
+		<org.springframework.version>4.3.10.RELEASE</org.springframework.version>
 		<org.hibernate.version>5.2.10.Final</org.hibernate.version>
 		<com.sun.jersey.version>1.19.4</com.sun.jersey.version>
 		<jackson.version>1.9.2</jackson.version>
@@ -2296,7 +2296,7 @@
 		<dependency>
 			<groupId>org.quartz-scheduler</groupId>
 			<artifactId>quartz</artifactId>
-			<version>1.8.6</version>
+			<version>2.2.3</version>
 		</dependency>
 		<dependency>
 			<groupId>com.thoughtworks.xstream</groupId>
diff --git a/src/main/java/de/bps/course/nodes/vc/_spring/vcContext.xml b/src/main/java/de/bps/course/nodes/vc/_spring/vcContext.xml
index 548ddfc686c..35e4bd045d5 100644
--- a/src/main/java/de/bps/course/nodes/vc/_spring/vcContext.xml
+++ b/src/main/java/de/bps/course/nodes/vc/_spring/vcContext.xml
@@ -64,9 +64,9 @@
 <!-- ################################## -->
 <!-- # VIRTUAL CLASSROOM SERVICE JOBS # -->
 <!-- ################################## -->
-	<bean id="adobeCleanupJob" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="adobeCleanupJob" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
     	<property name="jobDetail">
-    		<bean class="org.springframework.scheduling.quartz.JobDetailBean">
+    		<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
 				<property name="jobClass" value="de.bps.course.nodes.vc.provider.adobe.AdobeConnectCleanupJob" />
 				<property name="jobDataAsMap">
 				    <map>
diff --git a/src/main/java/de/bps/olat/portal/links/LinksPortletRunController.java b/src/main/java/de/bps/olat/portal/links/LinksPortletRunController.java
index eb8e42aecf4..209120917e9 100644
--- a/src/main/java/de/bps/olat/portal/links/LinksPortletRunController.java
+++ b/src/main/java/de/bps/olat/portal/links/LinksPortletRunController.java
@@ -38,8 +38,8 @@ import org.olat.core.gui.control.generic.closablewrapper.CloseableModalControlle
 import org.olat.core.gui.control.generic.modal.DialogBoxController;
 import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
 import org.olat.core.id.UserConstants;
-import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  *
@@ -58,6 +58,9 @@ public class LinksPortletRunController extends BasicController {
 	private Link backLink;
 	private DialogBoxController delLinkCtrl;
 	
+	@Autowired
+	private I18nModule i18nModule;
+	
 	protected LinksPortletRunController(UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl);
 		
@@ -76,9 +79,9 @@ public class LinksPortletRunController extends BasicController {
 	}
 	
 	private void initOrUpdatePortletView(UserRequest ureq){
-		String lang = I18nManager.getInstance().getLocaleKey(ureq.getLocale());
+		String lang = i18nModule.getLocaleKey(ureq.getLocale());
 		if (lang == null) {
-			lang = I18nManager.getInstance().getLocaleKey(I18nModule.getDefaultLocale());
+			lang = i18nModule.getLocaleKey(I18nModule.getDefaultLocale());
 		}
 		// fxdiff: compare with language-base not with variant...
 		int underlinePos = lang.indexOf("_");
@@ -199,7 +202,7 @@ public class LinksPortletRunController extends BasicController {
 				}
 			} else if (linkName.contains(LINKADD)){
 				// add a link to institution:
-				PortletLink newLink = new PortletLink("", "", "", I18nManager.getInstance().getLocaleKey(ureq.getLocale()), "", null);
+				PortletLink newLink = new PortletLink("", "", "", i18nModule.getLocaleKey(ureq.getLocale()), "", null);
 				// find institution and port in link!
 				String institution = link.getCommand().substring(LINKADD.length());
 				PortletInstitution inst = LinksPortlet.getContent().get(institution);
diff --git a/src/main/java/de/bps/onyx/plugin/_spring/onyxContext.xml b/src/main/java/de/bps/onyx/plugin/_spring/onyxContext.xml
index a2d626a2e08..8f8f2d6ba80 100644
--- a/src/main/java/de/bps/onyx/plugin/_spring/onyxContext.xml
+++ b/src/main/java/de/bps/onyx/plugin/_spring/onyxContext.xml
@@ -6,13 +6,13 @@
   http://www.springframework.org/schema/beans/spring-beans.xsd">
 
 <!-- update job for onyx results -->
-<bean id="updateQtiResultsTriggerOnyx" class="org.springframework.scheduling.quartz.CronTriggerBean">
+<bean id="updateQtiResultsTriggerOnyx" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
     <property name="jobDetail" ref="updateOnyxResults.${onyx.update.results.job}" />
     <property name="cronExpression" value="0 0 2 * * ?"/><!-- 2am, daily -->
     <property name="startDelay" value="90000" />
 </bean>
 
-<bean id="updateOnyxResults.enabled" class="org.springframework.scheduling.quartz.JobDetailBean">
+<bean id="updateOnyxResults.enabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
 	  <property name="jobClass" value="de.bps.jobs.UpdateOnyxResults" />
 	    <property name="jobDataAsMap">
 	    <map>
@@ -21,7 +21,7 @@
 	  </property>
 	</bean>	
 	
-<bean id="updateOnyxResults.disabled" class="org.springframework.scheduling.quartz.JobDetailBean">
+<bean id="updateOnyxResults.disabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
 	<!-- NOTE: reusing the notifications.DummyJob here -->
 	<property name="jobClass" value="org.olat.core.commons.services.scheduler.DummyJob" />
 </bean>
diff --git a/src/main/java/org/olat/admin/notifications/NotificationsEmailAdminController.java b/src/main/java/org/olat/admin/notifications/NotificationsEmailAdminController.java
index 2e33fbdee0d..958f10a11d4 100644
--- a/src/main/java/org/olat/admin/notifications/NotificationsEmailAdminController.java
+++ b/src/main/java/org/olat/admin/notifications/NotificationsEmailAdminController.java
@@ -24,6 +24,8 @@
 */
 package org.olat.admin.notifications;
 
+import java.util.List;
+
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
@@ -33,10 +35,12 @@ import org.olat.core.gui.components.velocity.VelocityContainer;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
-import org.quartz.JobDetail;
+import org.quartz.CronTrigger;
+import org.quartz.JobKey;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
-import org.springframework.scheduling.quartz.CronTriggerBean;
+import org.quartz.Trigger;
+import org.springframework.beans.factory.annotation.Autowired;
 
 
 /**
@@ -49,20 +53,26 @@ import org.springframework.scheduling.quartz.CronTriggerBean;
  */
 public class NotificationsEmailAdminController extends BasicController {
 	private static final String TRIGGER_NOTIFY = "notification.start.button";
+	
+	private final JobKey notificationsJobKey = new JobKey("org.olat.notifications.job.enabled", Scheduler.DEFAULT_GROUP);
 
-	private VelocityContainer content;
 	private Link startNotifyButton;
+	
+	@Autowired
+	private Scheduler scheduler;
 
 	public NotificationsEmailAdminController(UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl);
-		content = createVelocityContainer("index");
+		VelocityContainer content = createVelocityContainer("index");
 		boolean enabled;
 		String cronExpression = "";
 		try {
 			CoreSpringFactory.getBean("org.olat.notifications.job.enabled");
 			enabled = true;
-			CronTriggerBean bean = (CronTriggerBean)CoreSpringFactory.getBean("sendNotificationsEmailTrigger");
-			cronExpression = bean.getCronExpression();
+			List<? extends Trigger> triggers = scheduler.getTriggersOfJob(notificationsJobKey);
+			if(triggers.size() == 1 && triggers.get(0) instanceof CronTrigger) {
+				cronExpression = ((CronTrigger)triggers.get(0)).getCronExpression();
+			}
 		} catch (Exception e) {
 			enabled = false;
 		}
@@ -71,31 +81,20 @@ public class NotificationsEmailAdminController extends BasicController {
 		putInitialPanel(content);
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.components.Component,
-	 *      org.olat.core.gui.control.Event)
-	 */
 	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
 		if (source == startNotifyButton) {
 			//trigger the cron job
 			try {
-				Scheduler scheduler = CoreSpringFactory.getImpl(Scheduler.class);
-				JobDetail detail = scheduler.getJobDetail("org.olat.notifications.job.enabled", Scheduler.DEFAULT_GROUP);
-				scheduler.triggerJob(detail.getName(), detail.getGroup());
+				CoreSpringFactory.getImpl(Scheduler.class).triggerJob(notificationsJobKey);
 			} catch (SchedulerException e) {
 				logError("", e);
 			}
 		}
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
-	 */
 	@Override
 	protected void doDispose() {
 		//nothing to do
 	}
-
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/admin/registration/SystemRegistrationManager.java b/src/main/java/org/olat/admin/registration/SystemRegistrationManager.java
index 6c9f9583256..93c9c4606e1 100644
--- a/src/main/java/org/olat/admin/registration/SystemRegistrationManager.java
+++ b/src/main/java/org/olat/admin/registration/SystemRegistrationManager.java
@@ -24,7 +24,10 @@
 */
 package org.olat.admin.registration;
 
-import java.text.ParseException;
+import static org.quartz.CronScheduleBuilder.cronSchedule;
+import static org.quartz.JobBuilder.newJob;
+import static org.quartz.TriggerBuilder.newTrigger;
+
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.HashMap;
@@ -63,10 +66,11 @@ import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.instantMessaging.InstantMessagingModule;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryManager;
-import org.quartz.CronTrigger;
 import org.quartz.JobDetail;
+import org.quartz.JobKey;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
+import org.quartz.Trigger;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -171,7 +175,7 @@ public class SystemRegistrationManager implements InitializingBean {
 	
 	public void send() {
 		try {
-			scheduler.triggerJob(SCHEDULER_NAME, Scheduler.DEFAULT_GROUP);
+			scheduler.triggerJob(new JobKey(SCHEDULER_NAME, Scheduler.DEFAULT_GROUP));
 		} catch (SchedulerException e) {
 			log.error("", e);
 		}
@@ -250,7 +254,7 @@ public class SystemRegistrationManager implements InitializingBean {
 		
 		// System config
 		msgProperties.put("instantMessagingEnabled", String.valueOf(CoreSpringFactory.getImpl(InstantMessagingModule.class).isEnabled()));
-		msgProperties.put("enabledLanguages", I18nModule.getEnabledLanguageKeys().toString());
+		msgProperties.put("enabledLanguages", CoreSpringFactory.getImpl(I18nModule.class).getEnabledLanguageKeys().toString());
 		msgProperties.put("clusterEnabled", clusterMode);
 		msgProperties.put("debuggingEnabled", String.valueOf(Settings.isDebuging()));
 		
@@ -318,19 +322,16 @@ public class SystemRegistrationManager implements InitializingBean {
 
 		String cronExpression = createCronTriggerExpression();
 		try {
-			// Create job with cron trigger configuration
-			JobDetail jobDetail = new JobDetail(SCHEDULER_NAME, Scheduler.DEFAULT_GROUP, SystemRegistrationJob.class);
-			CronTrigger trigger = new CronTrigger();
-			trigger.setName(TRIGGER);
-			// Use this cron expression for debugging, tries to send data every minute
-			//trigger.setCronExpression("0 * * * * ?");
-			trigger.setCronExpression(cronExpression);
-			// Schedule job now
+			JobDetail jobDetail = newJob(SystemRegistrationJob.class)
+					.withIdentity(SCHEDULER_NAME, Scheduler.DEFAULT_GROUP)
+					.build();
+			Trigger trigger = newTrigger()
+				    .withIdentity(TRIGGER)
+				    .withSchedule(cronSchedule(cronExpression))
+				    .build();
 			scheduler.scheduleJob(jobDetail, trigger);
-		} catch (ParseException e) {
+		} catch (Exception e) {
 			log.error("Illegal cron expression for system registration", e);
-		} catch (SchedulerException e) {
-			log.error("Can not start system registration scheduler", e);
 		}
 		log.info("Registration background job successfully started: "+cronExpression, null);
 	}
diff --git a/src/main/java/org/olat/admin/statistics/StatisticsAdminController.java b/src/main/java/org/olat/admin/statistics/StatisticsAdminController.java
index f6635f31062..6bdd1266246 100644
--- a/src/main/java/org/olat/admin/statistics/StatisticsAdminController.java
+++ b/src/main/java/org/olat/admin/statistics/StatisticsAdminController.java
@@ -41,11 +41,12 @@ import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.course.statistic.StatisticUpdateManager;
-import org.quartz.JobDetail;
+import org.quartz.CronTrigger;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
 import org.quartz.Trigger;
-import org.springframework.scheduling.quartz.CronTriggerBean;
+import org.quartz.TriggerKey;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * Admin Controller for statistics - similar to the notifications controller.
@@ -70,6 +71,9 @@ public class StatisticsAdminController extends BasicController {
 
 	private DialogBoxController dialogCtr_;
 	
+	@Autowired
+	private Scheduler scheduler;
+	
 	public StatisticsAdminController(UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl);
 		content = createVelocityContainer("index");
@@ -82,38 +86,42 @@ public class StatisticsAdminController extends BasicController {
 	}
 
 	private void refreshUIState() {
+
+		log_.info("refreshUIState: schedulerFactoryBean found");
+
 		boolean enabled = false;
 		String cronExpression = "";
-		if (CoreSpringFactory.containsBean("schedulerFactoryBean")) {
-			log_.info("refreshUIState: schedulerFactoryBean found");
-			Object schedulerFactoryBean = CoreSpringFactory.getBean("schedulerFactoryBean");
-			if (schedulerFactoryBean!=null && schedulerFactoryBean instanceof Scheduler) {
-				Scheduler schedulerBean = (Scheduler) schedulerFactoryBean;
-				int triggerState;
-				try {
-					triggerState = schedulerBean.getTriggerState("updateStatisticsTrigger", null/*trigger group*/);
-					enabled = (triggerState!=Trigger.STATE_NONE) && (triggerState!=Trigger.STATE_ERROR);
-					log_.info("refreshUIState: updateStatisticsTrigger state was "+triggerState+", enabled now: "+enabled);
-				} catch (SchedulerException e) {
-					log_.warn("refreshUIState: Got a SchedulerException while asking for the updateStatisticsTrigger's state", e);
-				}
-			}
-			CronTriggerBean triggerBean = (CronTriggerBean) CoreSpringFactory.getBean("updateStatisticsTrigger");
-			JobDetail jobDetail = triggerBean.getJobDetail();
-			enabled &= jobDetail.getName().equals("org.olat.statistics.job.enabled");
-			log_.info("refreshUIState: org.olat.statistics.job.enabled check, enabled now: "+enabled);
-			cronExpression = triggerBean.getCronExpression();
-			StatisticUpdateManager statisticUpdateManager = getStatisticUpdateManager();
-			if (statisticUpdateManager==null) {
-				log_.info("refreshUIState: statisticUpdateManager not configured");
-				enabled = false;
+		Trigger.TriggerState triggerState;
+		try {
+			TriggerKey triggerKey = new TriggerKey("updateStatisticsTrigger", null/*trigger group*/);
+			triggerState = scheduler.getTriggerState(triggerKey);
+			enabled = triggerState != Trigger.TriggerState.NONE && triggerState!=Trigger.TriggerState.ERROR;
+			
+			Trigger trigger = scheduler.getTrigger(triggerKey);
+			if(trigger == null) {
+				enabled &= false;
 			} else {
-				enabled &= statisticUpdateManager.isEnabled();
-				log_.info("refreshUIState: statisticUpdateManager configured, enabled now: "+enabled);
+				enabled &= trigger.getJobKey().getName().equals("org.olat.statistics.job.enabled");
+				if(trigger instanceof CronTrigger) {
+					log_.info("refreshUIState: org.olat.statistics.job.enabled check, enabled now: "+enabled);
+					cronExpression = ((CronTrigger)trigger).getCronExpression();
+				}
 			}
+			
+			log_.info("refreshUIState: updateStatisticsTrigger state was "+triggerState+", enabled now: "+enabled);
+		} catch (SchedulerException e) {
+			log_.warn("refreshUIState: Got a SchedulerException while asking for the updateStatisticsTrigger's state", e);
+		}
+		
+		StatisticUpdateManager statisticUpdateManager = getStatisticUpdateManager();
+		if (statisticUpdateManager==null) {
+			log_.info("refreshUIState: statisticUpdateManager not configured");
+			enabled = false;
 		} else {
-			log_.info("refreshUIState: schedulerFactoryBean not found");
+			enabled &= statisticUpdateManager.isEnabled();
+			log_.info("refreshUIState: statisticUpdateManager configured, enabled now: "+enabled);
 		}
+
 		if (enabled) {
 			content.contextPut("status", getTranslator().translate("statistics.status.enabled", new String[]{ cronExpression }));
 		} else {
@@ -150,6 +158,7 @@ public class StatisticsAdminController extends BasicController {
 		}
 	}
 
+	@Override
 	public void event(UserRequest ureq, Controller source, Event event) {
 		if (source == dialogCtr_) {
 			if (DialogBoxUIFactory.isYesEvent(event)) {				
@@ -165,12 +174,6 @@ public class StatisticsAdminController extends BasicController {
 		}
 	}
 
-	
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.components.Component,
-	 *      org.olat.core.gui.control.Event)
-	 */
 	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
 		if (STATISTICS_FULL_RECALCULATION_TRIGGER_BUTTON.equals(event.getCommand())) {
diff --git a/src/main/java/org/olat/admin/user/SendTokenToUserForm.java b/src/main/java/org/olat/admin/user/SendTokenToUserForm.java
index 89081c6588e..3510ddf2708 100644
--- a/src/main/java/org/olat/admin/user/SendTokenToUserForm.java
+++ b/src/main/java/org/olat/admin/user/SendTokenToUserForm.java
@@ -42,6 +42,7 @@ import org.olat.core.id.UserConstants;
 import org.olat.core.util.Encoder;
 import org.olat.core.util.Util;
 import org.olat.core.util.i18n.I18nManager;
+import org.olat.core.util.i18n.I18nModule;
 import org.olat.core.util.mail.MailBundle;
 import org.olat.core.util.mail.MailManager;
 import org.olat.core.util.mail.MailerResult;
@@ -64,6 +65,11 @@ public class SendTokenToUserForm extends FormBasicController {
 	private TextElement mailText;
 	
 	private String dummyKey;
+	
+	@Autowired
+	private I18nModule i18nModule;
+	@Autowired
+	private I18nManager i18nManager;
 	@Autowired
 	private MailManager mailManager;
 	@Autowired
@@ -122,7 +128,7 @@ public class SendTokenToUserForm extends FormBasicController {
 			Translator userTrans = Util.createPackageTranslator(RegistrationManager.class, locale) ;
 			String body = userTrans.translate("pwchange.intro", new String[] { user.getName() })
 					+ userTrans.translate("pwchange.body", new String[] {
-							serverpath, dummyKey, I18nManager.getInstance().getLocaleKey(locale)
+							serverpath, dummyKey, i18nModule.getLocaleKey(locale)
 					});
 			return body;
 		}
@@ -147,7 +153,7 @@ public class SendTokenToUserForm extends FormBasicController {
 		}
 		
 		Preferences prefs = user.getUser().getPreferences();
-		Locale locale = I18nManager.getInstance().getLocaleOrDefault(prefs.getLanguage());
+		Locale locale = i18nManager.getLocaleOrDefault(prefs.getLanguage());
 		String emailAdress = user.getUser().getProperty(UserConstants.EMAIL, locale);
 
 		TemporaryKey tk = registrationManager.loadTemporaryKeyByEmail(emailAdress);
diff --git a/src/main/java/org/olat/admin/user/imp/ImportStep00.java b/src/main/java/org/olat/admin/user/imp/ImportStep00.java
index 0005b9bf3ff..2a46213ab29 100644
--- a/src/main/java/org/olat/admin/user/imp/ImportStep00.java
+++ b/src/main/java/org/olat/admin/user/imp/ImportStep00.java
@@ -60,7 +60,6 @@ import org.olat.core.gui.media.MediaResource;
 import org.olat.core.id.Identity;
 import org.olat.core.id.UserConstants;
 import org.olat.core.util.StringHelper;
-import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
 import org.olat.registration.RegistrationManager;
 import org.olat.registration.TemporaryKey;
@@ -124,6 +123,8 @@ class ImportStep00 extends BasicStep {
 		@Autowired
 		private UserManager um;
 		@Autowired
+		private I18nModule i18nModule;
+		@Autowired
 		private BaseSecurity securityManager;
 		@Autowired
 		private ShibbolethModule shibbolethModule;
@@ -165,7 +166,7 @@ class ImportStep00 extends BasicStep {
 				return true;
 			}
 
-			String defaultlang = I18nModule.getDefaultLocale().toString();
+			String defaultlang = i18nModule.getDefaultLocale().toString();
 			List<String> importedEmails = new ArrayList<String>();
 
 			boolean importDataError = false;
@@ -184,7 +185,7 @@ class ImportStep00 extends BasicStep {
 			// org.olat.admin.user.imp.UserImportController
 			// are required and have to be submitted in the right order
 			// - pwd can be enabled / disabled by configuration
-			Collection<String> languages = I18nModule.getEnabledLanguageKeys();
+			Collection<String> languages = i18nModule.getEnabledLanguageKeys();
 			String[] lines = inp.split("\r?\n");
 			for (int i = 0; i < lines.length; i++) {
 				if(i % 25 == 0) {
@@ -449,7 +450,7 @@ class ImportStep00 extends BasicStep {
 		private Mapper createMapper(UserRequest ureq) {
 			final String charset = UserManager.getInstance().getUserCharset(ureq.getIdentity());
 			Mapper m = new Mapper() {
-				@SuppressWarnings({"synthetic-access" })
+				@Override
 				public MediaResource handle(String relPath, HttpServletRequest request) {
 					setTranslator(UserManager.getInstance().getPropertyHandlerTranslator(getTranslator()));
 					String headerLine = translate("table.user.login") + " *";
@@ -459,7 +460,7 @@ class ImportStep00 extends BasicStep {
 						dataLine += "\t" + "olat4you";
 					}
 					headerLine += "\t" + translate("table.user.lang");
-					dataLine += "\t" + I18nManager.getInstance().getLocaleKey(getLocale());
+					dataLine += "\t" + i18nModule.getLocaleKey(getLocale());
 					UserPropertyHandler userPropertyHandler;
 					for (int i = 0; i < userPropertyHandlers.size(); i++) {
 						userPropertyHandler = userPropertyHandlers.get(i);
diff --git a/src/main/java/org/olat/basesecurity/AuthHelper.java b/src/main/java/org/olat/basesecurity/AuthHelper.java
index f6708fee6aa..fab7172cc5b 100644
--- a/src/main/java/org/olat/basesecurity/AuthHelper.java
+++ b/src/main/java/org/olat/basesecurity/AuthHelper.java
@@ -219,7 +219,7 @@ public class AuthHelper {
 	 * @return true if login was successful, false otherwise
 	 */
 	public static int doAnonymousLogin(UserRequest ureq, Locale locale) {
-		Collection<String> supportedLanguages = I18nModule.getEnabledLanguageKeys();
+		Collection<String> supportedLanguages = CoreSpringFactory.getImpl(I18nModule.class).getEnabledLanguageKeys();
 		if ( locale == null || ! supportedLanguages.contains(locale.toString()) ) {
 			locale = I18nModule.getDefaultLocale();
 		} 
@@ -266,7 +266,7 @@ public class AuthHelper {
 			}
 		}
 		
-		Collection<String> supportedLanguages = I18nModule.getEnabledLanguageKeys();
+		Collection<String> supportedLanguages = CoreSpringFactory.getImpl(I18nModule.class).getEnabledLanguageKeys();
 		if ( locale == null || ! supportedLanguages.contains(locale.toString()) ) {
 			locale = I18nModule.getDefaultLocale();
 		} 
@@ -358,10 +358,10 @@ public class AuthHelper {
 		boolean wasGuest = false;
 		UserSession usess = ureq.getUserSession();
 		if(usess != null && usess.getRoles() != null) {
-			wasGuest = ureq.getUserSession().getRoles().isGuestOnly();
+			wasGuest = usess.getRoles().isGuestOnly();
 		}
 		
-		String lang = I18nManager.getInstance().getLocaleKey(ureq.getLocale());
+		String lang = CoreSpringFactory.getImpl(I18nModule.class).getLocaleKey(ureq.getLocale());
 		HttpSession session = ureq.getHttpReq().getSession(false);
 		// next line fires a valueunbound event to UserSession, which does some
 		// stuff on logout
diff --git a/src/main/java/org/olat/basesecurity/_spring/baseSecurityContext.xml b/src/main/java/org/olat/basesecurity/_spring/baseSecurityContext.xml
index f2a10a370bb..88ed650d5ba 100644
--- a/src/main/java/org/olat/basesecurity/_spring/baseSecurityContext.xml
+++ b/src/main/java/org/olat/basesecurity/_spring/baseSecurityContext.xml
@@ -10,14 +10,11 @@
 
 	<context:component-scan base-package="org.olat.basesecurity" />
 
-	<!-- manager -->
-	<bean id="baseSecurityManager" class="org.olat.basesecurity.BaseSecurityManager" init-method="init" 
-		depends-on="database, i18nModule, triggerI18nModuleInit">
+	<bean id="baseSecurityManager" class="org.olat.basesecurity.BaseSecurityManager" init-method="init" depends-on="database">
 		<property name="resourceManager" ref="resourceManager"/>
 		<property name="loginModule" ref="loginModule"/>
 		<property name="dbInstance" ref="database"/>
 		<property name="invitationDao" ref="invitationDao" />
 		<property name="dbVendor" value="${db.vendor}" />
 	</bean>
-
 </beans>
\ No newline at end of file
diff --git a/src/main/java/org/olat/commons/calendar/_spring/calendarContext.xml b/src/main/java/org/olat/commons/calendar/_spring/calendarContext.xml
index 5a5369adfe5..750df1f6e94 100644
--- a/src/main/java/org/olat/commons/calendar/_spring/calendarContext.xml
+++ b/src/main/java/org/olat/commons/calendar/_spring/calendarContext.xml
@@ -10,7 +10,7 @@
   
 	<context:component-scan base-package="org.olat.commons.calendar" />
   
-	<bean id="calendarImportTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="calendarImportTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 	    <property name="jobDetail" ref="calendarImportJob" />
 	    <!-- adjust cron style syntax for your needs 
 	    A "Cron-Expression" is a string comprised of 6 or 7 fields separated by white space. The 6 mandatory and 1 optional fields are as follows:
@@ -30,7 +30,7 @@
 	    <property name="startDelay" value="40000" />
 	</bean>
 	
-	<bean id="calendarImportJob" class="org.springframework.scheduling.quartz.JobDetailBean">
+	<bean id="calendarImportJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
 	  <property name="jobClass" value="org.olat.commons.calendar.ImportCalendarJob" />
 	</bean>
 	
diff --git a/src/main/java/org/olat/core/_spring/mainCorecontext.xml b/src/main/java/org/olat/core/_spring/mainCorecontext.xml
index 3ab96ee70d0..69bc796fff3 100644
--- a/src/main/java/org/olat/core/_spring/mainCorecontext.xml
+++ b/src/main/java/org/olat/core/_spring/mainCorecontext.xml
@@ -8,12 +8,11 @@
   http://www.springframework.org/schema/context 
   http://www.springframework.org/schema/context/spring-context.xsd">
   
-	<context:component-scan base-package="org.olat.core.dispatcher.mapper,org.olat.core.id.context,org.olat.core.commons.controllers.impressum,org.olat.core.gui.render.velocity" />
+	<context:component-scan base-package="org.olat.core.dispatcher.mapper,org.olat.core.id.context,org.olat.core.commons.controllers.impressum,org.olat.core.helpers,org.olat.core.gui.render.velocity" />
 
 	<bean id="coreSpringFactory" class="org.olat.core.CoreSpringFactory" />
 	
 	<import resource="classpath:/org/olat/core/util/vfs/version/_spring/versioningCorecontext.xml"/>
-	<import resource="classpath:/org/olat/core/util/i18n/_spring/i18nCorecontext.xml"/>
 	<import resource="classpath:/org/olat/core/util/_spring/utilCorecontext.xml"/>
 	<import resource="classpath:/org/olat/core/util/i18n/devtools/_spring/devtoolsCorecontext.xml"/>
 	<import resource="classpath:/org/olat/core/util/event/_spring/frameworkStartedEventCorecontext.xml"/>
@@ -41,13 +40,13 @@
 	    <property name="parserPoolSize" value="${velocity.parser.pool.size}" />	
 	</bean>
 
-	<bean id="mapperSlayerTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="mapperSlayerTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 	    <property name="jobDetail" ref="mapperSlayerJob" />
 	    <property name="cronExpression" value="0 5 0/1 * * ?" />
 		<property name="startDelay" value="200000" />
 	</bean>
 	
-	<bean id="mapperSlayerJob" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="mapperSlayerJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 	  <property name="jobClass" value="org.olat.core.dispatcher.mapper.manager.MapperZombieSlayerJob" />
 	</bean>
 
diff --git a/src/main/java/org/olat/core/commons/controllers/impressum/ImpressumAdminController.java b/src/main/java/org/olat/core/commons/controllers/impressum/ImpressumAdminController.java
index ee7371c11b5..08c97ecef81 100644
--- a/src/main/java/org/olat/core/commons/controllers/impressum/ImpressumAdminController.java
+++ b/src/main/java/org/olat/core/commons/controllers/impressum/ImpressumAdminController.java
@@ -73,6 +73,8 @@ public class ImpressumAdminController extends FormBasicController {
 	private final VFSContainer impressumDir;
 	private final VFSContainer termsOfUseDir;
 	
+	@Autowired
+	private I18nModule i18nModule;
 	@Autowired
 	private I18nManager i18nManager;
 	@Autowired
@@ -116,7 +118,7 @@ public class ImpressumAdminController extends FormBasicController {
 		List<ButtonGroup> impressumButtons = new ArrayList<>();
 		impressumCont.contextPut("buttons", impressumButtons);
 		
-		for(String lang:I18nModule.getEnabledLanguageKeys()) {
+		for(String lang:i18nModule.getEnabledLanguageKeys()) {
 			FormLink editLink = uifactory
 					.addFormLink("impressum." + lang, "impressum", getTranslated(lang), "impressum.file", impressumCont, Link.BUTTON | Link.NONTRANSLATED);
 			editLink.setLabel(null, null);
@@ -146,7 +148,7 @@ public class ImpressumAdminController extends FormBasicController {
 		List<ButtonGroup> termsOfUseButtons = new ArrayList<>();
 		termsCont.contextPut("buttons", termsOfUseButtons);
 		
-		for(String lang:I18nModule.getEnabledLanguageKeys()) {
+		for(String lang:i18nModule.getEnabledLanguageKeys()) {
 			FormLink editLink = uifactory.addFormLink("termofuser." + lang, "termsofuse", getTranslated(lang), "termofuse.file", termsCont, Link.BUTTON | Link.NONTRANSLATED);
 			editLink.setLabel(null, null);
 			String filePath = "index_" + lang + ".html";
diff --git a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java
index a9f4cd1f294..8b2f579b360 100644
--- a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java
+++ b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java
@@ -114,6 +114,7 @@ import org.olat.course.assessment.ui.mode.AssessmentModeGuardController;
 import org.olat.course.assessment.ui.mode.ChooseAssessmentModeEvent;
 import org.olat.gui.control.UserToolsMenuController;
 import org.olat.home.HomeSite;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * Description:<br>
@@ -185,6 +186,11 @@ public class BaseFullWebappController extends BasicController implements DTabs,
 	private final boolean isAdmin;
 	private final int maxTabs = 20;
 	
+	@Autowired
+	private I18nModule i18nModule;
+	@Autowired
+	private I18nManager i18nManager;
+	
 	public BaseFullWebappController(UserRequest ureq, BaseFullWebappControllerParts baseFullWebappControllerParts) {
 		// only-use-in-super-call, since we define our own
 		super(ureq, null);
@@ -350,14 +356,15 @@ public class BaseFullWebappController extends BasicController implements DTabs,
 		// will start the translation tool in translation mode, if the overlay
 		// feature is enabled it will start in customizing mode
 		// fxdiff: allow user-managers to use the inline translation also.
-		if (ureq.getUserSession().isAuthenticated()
-				&& (ureq.getUserSession().getRoles().isOLATAdmin() || ureq.getUserSession().getRoles().isUserManager())
-				&& (I18nModule.isTransToolEnabled() || I18nModule.isOverlayEnabled())) {
+		UserSession usess = ureq.getUserSession();
+		if (usess.isAuthenticated()
+				&& (usess.getRoles().isOLATAdmin() || usess.getRoles().isUserManager())
+				&& (i18nModule.isTransToolEnabled() || i18nModule.isOverlayEnabled())) {
 			inlineTranslationC = wbo.createInlineTranslationDispatcherController(ureq, getWindowControl());
 			Preferences guiPrefs = ureq.getUserSession().getGuiPreferences();
 			Boolean isInlineTranslationEnabled = (Boolean) guiPrefs.get(I18nModule.class, I18nModule.GUI_PREFS_INLINE_TRANSLATION_ENABLED,
 					Boolean.FALSE);
-			I18nManager.getInstance().setMarkLocalizedStringsEnabled(ureq.getUserSession(), isInlineTranslationEnabled);
+			i18nManager.setMarkLocalizedStringsEnabled(ureq.getUserSession(), isInlineTranslationEnabled);
 			mainVc.put("inlineTranslation", inlineTranslationC.getInitialComponent());
 		}
 
diff --git a/src/main/java/org/olat/core/commons/services/notifications/_spring/notificationsContext.xml b/src/main/java/org/olat/core/commons/services/notifications/_spring/notificationsContext.xml
index 4d026f0150b..932c363c47e 100644
--- a/src/main/java/org/olat/core/commons/services/notifications/_spring/notificationsContext.xml
+++ b/src/main/java/org/olat/core/commons/services/notifications/_spring/notificationsContext.xml
@@ -63,7 +63,7 @@
 		is 10min after midnight.
 	 -->
 
-	<bean id="sendNotificationsEmailTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="sendNotificationsEmailTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 	    <property name="jobDetail" ref="org.olat.notifications.job.${cluster.singleton.services}" />
 	    <!-- adjust cron style syntax for your notification needs 
 	    	"0 10 0 * *"  e.g. 10 minutes after midnight
@@ -87,12 +87,12 @@
 	    <property name="startDelay" value="300000" />
 	</bean>
 	
-	<bean id="org.olat.notifications.job.enabled" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="org.olat.notifications.job.enabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 	  <property name="jobClass" value="org.olat.core.commons.services.notifications.manager.EmailNotificationJob" />
 	</bean>
 	
 	<!-- dummy bean -->
-	<bean id="org.olat.notifications.job.disabled" class="org.springframework.scheduling.quartz.JobDetailBean"  lazy-init="true">
+	<bean id="org.olat.notifications.job.disabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"  lazy-init="true">
 		<property name="jobClass" value="org.olat.core.commons.services.scheduler.DummyJob" />
 	</bean>
 
diff --git a/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml b/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml
index d570acedcfb..19d35e7235a 100644
--- a/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml
+++ b/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml
@@ -16,8 +16,8 @@ to the MBeanExporter Bean at the end.
 How to add a new job:
 1. Create you class which extends from QuartzJobBean see ChangePresenceJob as example
 2. Create a file called "olatextconfig.xml" with your own beans and place it in the same directory as this file. It will be loaded automatically.
-3. Add a bean definition where your job is created like ="<bean id="changePresenceJob" class="org.springframework.scheduling.quartz.JobDetailBean">"
-4. Create a scheduler for your definded bean: Either an SimpleTriggerBean or an CronTriggerBean
+3. Add a bean definition where your job is created like ="<bean id="changePresenceJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">"
+4. Create a scheduler for your definded bean: Either an SimpleTriggerFactoryBean or an CronTriggerFactoryBean
 5. Add your trigger bean to the SchedulerFactoryBean list.
 -->
 
@@ -61,7 +61,7 @@ How to add a new job:
 <!-- add referenced schedulers here -->
 
 <!-- Only needed in cluster mode, dumps jmx info to disc --> 
-<bean id="dumpJMXJobTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
+<bean id="dumpJMXJobTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
     <property name="jobDetail" ref="dumpJMXJob" />
     <!-- 5 minute -->
     <property name="startDelay" value="300000" />
@@ -72,7 +72,7 @@ How to add a new job:
 <!-- Example bean for cron style scheduling--> 
 <!-- OLAT-5093 start delay ensures there's no conflict with server startup and db not being ready yet -->
 <!--
-<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
     <property name="jobDetail" ref="exampleJob" />
     <property name="cronExpression" value="0 0 6 * * ?" />
     <property name="startDelay" value="300000" />
@@ -81,7 +81,7 @@ How to add a new job:
 
 
 <!--  job definition  -->
-<bean id="dumpJMXJob" class="org.springframework.scheduling.quartz.JobDetailBean">
+<bean id="dumpJMXJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
 	<property name="jobClass" value="org.olat.admin.jmx.DumpJMXJob"/>
 	<property name="jobDataAsMap">
     <map>
@@ -103,7 +103,7 @@ How to add a new job:
 
 	<!-- SEARCH INDEXING CONFIGURATION -->
 
-	<bean id="searchIndexingTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="searchIndexingTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 	    <property name="jobDetail" ref="org.olat.search.job.${search.indexing.cronjob}" />
 	    <property name="cronExpression" ref="searchIndexCronGenerator" />
 		<!-- OLAT-5093 start delay ensures there's no conflict with server startup and db not being ready yet -->
@@ -116,12 +116,12 @@ How to add a new job:
 		<property name="cronExpression" value="${search.indexing.cronjob.expression}" />
 	</bean>
 	
-	<bean id="org.olat.search.job.enabled" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="org.olat.search.job.enabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 	  <property name="jobClass" value="org.olat.search.service.indexer.SearchIndexingJob"/>
 	</bean>
 	
 	<!-- dummy bean -->
-	<bean id="org.olat.search.job.disabled" class="org.springframework.scheduling.quartz.JobDetailBean"  lazy-init="true">
+	<bean id="org.olat.search.job.disabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"  lazy-init="true">
 		<!-- NOTE: reusing the notifications.DummyJob here -->
 		<property name="jobClass" value="org.olat.core.commons.services.scheduler.DummyJob" />
 	</bean>
diff --git a/src/main/java/org/olat/core/commons/services/taskexecutor/_spring/taskExecutorCorecontext.xml b/src/main/java/org/olat/core/commons/services/taskexecutor/_spring/taskExecutorCorecontext.xml
index 3dfedfa0560..564f9696967 100644
--- a/src/main/java/org/olat/core/commons/services/taskexecutor/_spring/taskExecutorCorecontext.xml
+++ b/src/main/java/org/olat/core/commons/services/taskexecutor/_spring/taskExecutorCorecontext.xml
@@ -34,13 +34,13 @@
 	</bean>
 	
 	<!-- Persistent task executor job -->
-	<bean id="taskExecutorTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="taskExecutorTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 		<property name="jobDetail" ref="taskExecutorJob" />
   		<!--  every day at 1:21 -->
 		<property name="cronExpression" value="10 */5 * * * ?" />
 		<property name="startDelay" value="60000" />
 	</bean>
-	<bean id="taskExecutorJob" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="taskExecutorJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 		<property name="jobClass" value="org.olat.core.commons.services.taskexecutor.manager.ExecutorJob" />
 	</bean>
 
diff --git a/src/main/java/org/olat/core/commons/services/taskexecutor/manager/TaskExecutorManagerImpl.java b/src/main/java/org/olat/core/commons/services/taskexecutor/manager/TaskExecutorManagerImpl.java
index 777d9f829bb..b014f529c67 100644
--- a/src/main/java/org/olat/core/commons/services/taskexecutor/manager/TaskExecutorManagerImpl.java
+++ b/src/main/java/org/olat/core/commons/services/taskexecutor/manager/TaskExecutorManagerImpl.java
@@ -46,7 +46,7 @@ import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.manager.BasicManager;
 import org.olat.resource.OLATResource;
-import org.quartz.JobDetail;
+import org.quartz.JobKey;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
 
@@ -150,8 +150,7 @@ public class TaskExecutorManagerImpl extends BasicManager implements TaskExecuto
 	@Override
 	public void executeTaskToDo() {
 		try {
-			JobDetail detail = scheduler.getJobDetail("taskExecutorJob", Scheduler.DEFAULT_GROUP);
-			scheduler.triggerJob(detail.getName(), detail.getGroup());
+			scheduler.triggerJob(new JobKey("taskExecutorJob", Scheduler.DEFAULT_GROUP));
 		} catch (SchedulerException e) {
 			log.error("", e);
 		}
diff --git a/src/main/java/org/olat/core/configuration/AbstractOLATModule.java b/src/main/java/org/olat/core/configuration/AbstractOLATModule.java
deleted file mode 100644
index 9d6042498f4..00000000000
--- a/src/main/java/org/olat/core/configuration/AbstractOLATModule.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.  
-* <p>
-*/
-package org.olat.core.configuration;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.olat.core.gui.control.Event;
-import org.olat.core.logging.LogDelegator;
-import org.olat.core.logging.OLog;
-import org.olat.core.logging.StartupException;
-import org.olat.core.logging.Tracing;
-import org.olat.core.util.StringHelper;
-import org.olat.core.util.event.GenericEventListener;
-
-/**
- * Description:<br>
- * Default/abstract class with helper methods. <br>
- * The abstract olat module features reading and writing of configuration
- * properties to config and properties files. The idea is that the system can be
- * configured with default values either in the config xml file or by providing
- * reasonable default values directly in the module code.
- * <p>
- * The developer should provide a GUI for each value that can be configured at
- * runtime without the need of rebooting the entire system. But this is up to
- * the programmer who implements the setter methods for the config values.
- * <p>
- * The getter methods will load the configuration in the following order:
- * <ol>
- * <li>
- * <code>olatdata/system/configuration/fully.qualified.ClassName.properties</code>
- * </li>
- * <li>falling back to<code>olat.local.properties</code></li>
- * <li>falling back to<code>olat.properties</code></li>
- * <li>falling back to default value defined in method call</li>
- * </ol>
- * The class does also provide save methods. Setting a config parameter will
- * store it always in the user space config file
- * <code>olatdata/system/configuration/fully.qualified.ClassName.properties</code>
- * and not in the olat.properties, those are only the default values in case no
- * other configuration.
- * <p>
- * To work properly in a cluster environment, the module will fire a
- * ModuleConfigurationChangedEvent at the end of each save cycle. This event is
- * catched automatically and the abstract method initFromChangedProperties() is
- * called.
- * <p>
- * For more information on how the storing mechanism of the configuration works
- * please have a look at the PersistedProperties class.
- * <p>
- * If you want to use the properties mechanism in a spring loaded class, use the
- * PersistedProperties class directly to read/write your application
- * configuration.
- * <p>
- * Initial Date: 01.10.2007 <br>
- * 
- * @author Felix Jost, http://www.goodsolutions.ch
- * @author Florian Gnägi, http://www.frentix.com
- */
-public abstract class AbstractOLATModule extends LogDelegator implements GenericEventListener {
-	protected PersistedProperties moduleConfigProperties;
-	private Properties moduleDefaultConfig;
-	
-	public static final Map<Class<?>,AtomicInteger> starts = new HashMap<Class<?>,AtomicInteger>();
-	
-	public AbstractOLATModule() {
-		if(!starts.containsKey(this.getClass())) {
-			starts.put(this.getClass(), new AtomicInteger(1));
-		} else {
-			starts.get(this.getClass()).incrementAndGet();
-		}
-	}
-	
-	public static void printStats() {
-		OLog logger = Tracing.createLoggerFor(AbstractOLATModule.class);
-		for(Map.Entry<Class<?>, AtomicInteger> entry:starts.entrySet()) {
-			if(entry.getValue().get() > 1) {
-				logger.info(entry.getValue().get() + " :: " + entry.getKey());
-			}
-		}
-	}
-
-	/**
-	 * Initialize the module. Called by the spring framework at startup time
-	 */
-	public final void init(Properties moduleConfig) {
-		// Default module configuration from xml file
-		this.moduleDefaultConfig = moduleConfig;
-		// Let the module set the default properties
-		if (moduleConfigProperties == null) throw new StartupException("PersistedProperties is null. You have to set Persisted properties in spring config when you use abstractOlatModule!");
-		initDefaultProperties();
-		init();
-	}
-	
-	public abstract void init();
-	
-	
-	public abstract void setPersistedProperties(PersistedProperties persistedProperties);
-
-	/**
-	 * Called during module initialization to read the default values from the
-	 * configuration and set them as config properties default.
-	 */
-	protected abstract void initDefaultProperties();
-
-	/**
-	 * Called whenever the properties configuraton changed (e.g. on this or on another
-	 * cluster node). The properties have been reloaded prior to when this method is executed.
-	 */
-	protected abstract void initFromChangedProperties();
-	
-	
-	/**
-	 * Return an int value for certain config-parameter. If the parameter does
-	 * not exist, return the defaultValue.
-	 * 
-	 * @param parameterName
-	 * @param defaultValue
-	 * @param
-	 * @return The int value.
-	 */
-	protected int getIntConfigParameter(String parameterName, int defaultValue) {
-		String stringValue = moduleDefaultConfig.getProperty(parameterName);
-		if (StringHelper.containsNonWhitespace(stringValue)) {
-			try {
-				return Integer.parseInt(stringValue.trim());
-			} catch (Exception ex) {
-				logWarn("Cannot parse to integer conf-parameter '" + parameterName + "', value=" + stringValue, null);
-			}
-		}
-		logInfo("Take default value for integer conf-parameter '" + parameterName + "', value=" + defaultValue, null);
-		return defaultValue;
-	}
-
-	/**
-	 * Return a string value for certain config-parameter. If the parameter does
-	 * not exist, return the defaultValue.
-	 * 
-	 * @param parameterName
-	 * @param defaultValue
-	 * @param
-	 * @return The string value. Can be empty, but never null
-	 */
-	protected String getStringConfigParameter(String parameterName, String defaultValue, boolean allowEmptyString) {
-		String stringValue = moduleDefaultConfig.getProperty(parameterName);
-		if (stringValue != null) {
-			if (allowEmptyString || StringHelper.containsNonWhitespace(stringValue)) {
-				return stringValue.trim();				
-			}
-		}
-		logInfo("Take default value for String conf-parameter '" + parameterName + "', value=" + defaultValue, null);
-		return defaultValue;
-	}
-
-	/**
-	 * Return a boolean value for certain config-parameter. If the paramter does
-	 * not exist, return the defaultValue. 'true' and 'enabled' return <code>true</code>, 'false' and 'disabled' return <code>false</code>. 
-	 * 
-	 * @param parameterName
-	 * @param defaultValue
-	 * @return
-	 */
-	protected boolean getBooleanConfigParameter(String parameterName, boolean defaultValue) {
-		String stringValue = moduleDefaultConfig.getProperty(parameterName);			
-		if ((stringValue != null) && (stringValue.trim().equalsIgnoreCase("TRUE") || stringValue.trim().equalsIgnoreCase("ENABLED"))) {
-			return true;
-		}
-		if ((stringValue != null) && (stringValue.trim().equalsIgnoreCase("FALSE") || stringValue.trim().equalsIgnoreCase("DISABLED"))) {
-			return false;
-		}
-		logInfo("Take default Boolean conf-parameter '" + parameterName + "', value=" + stringValue
-				+ ", only true/false supported => take default value.", null);
-		return defaultValue;
-	}
-	
-	//
-	// Delegate methods used to get and set the values and default in the user
-	// configuration using the persisted properties.
-	//
-
-	/**
-	 * Return a string value for certain propertyName-parameter.
-	 * 
-	 * @param propertyName
-	 * @param allowEmptyString
-	 *            true: empty strings are valid values; false: emtpy strings are
-	 *            discarded
-	 * @return the value from the configuration or the default value or ""/NULL
-	 *         (depending on allowEmptyString flag)
-	 */
-	protected String getStringPropertyValue(String propertyName, boolean allowEmptyString) {
-		// delegate to new property based config style
-		return moduleConfigProperties.getStringPropertyValue(propertyName, allowEmptyString);
-	}
-	/**
-	 * Set a string property
-	 * 
-	 * @param propertyName
-	 *            The key
-	 * @param value
-	 *            The Value
-	 * @param saveConfiguration
-	 *            true: will save property and fire event; false: will not save,
-	 *            but set a dirty flag
-	 */
-	protected void setStringProperty(String propertyName, String value, boolean saveConfiguration) {
-		// delegate to new property based config style
-		moduleConfigProperties.setStringProperty(propertyName, value, saveConfiguration);
-		logAudit("change system property: " + propertyName, value);
-	}
-	/**
-	 * Retrun an int value for a certain propertyName
-	 * 
-	 * @param propertyName
-	 * @return the value from the configuration or the default value or 0
-	 */
-	protected int getIntPropertyValue(String propertyName) {
-		// delegate to new property based config style
-		return moduleConfigProperties.getIntPropertyValue(propertyName);
-	}
-	/**
-	 * Set an int property
-	 * 
-	 * @param propertyName
-	 *            The key
-	 * @param value
-	 *            The Value
-	 * @param saveConfiguration
-	 *            true: will save property and fire event; false: will not save,
-	 *            but set a dirty flag
-	 */
-	protected void setIntProperty(String propertyName, int value, boolean saveConfiguration) {
-		// delegate to new property based config style
-		moduleConfigProperties.setIntProperty(propertyName, value, saveConfiguration);
-		logAudit("change system property: " + propertyName, Integer.toString(value));
-	}
-	/**
-	 * Return a boolean value for certain propertyName
-	 * 
-	 * @param propertyName
-	 * @return the value from the configuration or the default value or false
-	 */
-	protected boolean getBooleanPropertyValue(String propertyName) {
-		// delegate to new property based config style
-		return moduleConfigProperties.getBooleanPropertyValue(propertyName);
-	}
-	/**
-	 * Set a boolean property
-	 * 
-	 * @param propertyName
-	 *            The key
-	 * @param value
-	 *            The Value
-	 * @param saveConfiguration
-	 *            true: will save property and fire event; false: will not save,
-	 *            but set a dirty flag
-	 */
-	protected void setBooleanProperty(String propertyName, boolean value, boolean saveConfiguration) {
-		// delegate to new property based config style
-		moduleConfigProperties.setBooleanProperty(propertyName, value, saveConfiguration);
-		logAudit("change system property: " + propertyName,  Boolean.toString(value));
-	}
-	/**
-	 * Save the properties configuration to disk and notify other nodes about
-	 * change. This is only done when there are dirty changes, otherwhile the
-	 * method call does nothing.
-	 */
-	protected void savePropertiesAndFireChangedEvent() {
-		// delegate to new property based config style
-		moduleConfigProperties.savePropertiesAndFireChangedEvent();
-	}
-	/**
-	 * Clear the properties and save the empty properties to the file system.
-	 */
-	protected void clearAndSaveProperties() {
-		// delegate to new property based config style
-		moduleConfigProperties.clearAndSaveProperties();
-	}
-	/**
-	 * Set a default value for a string property
-	 * @param propertyName
-	 * @param value
-	 */
-	protected void setStringPropertyDefault(String key, String value){
-		// delegate to new property based config style
-		moduleConfigProperties.setStringPropertyDefault(key, value);		
-	}
-	/**
-	 * Set a default value for a boolean property
-	 * @param propertyName
-	 * @param value
-	 */
-	protected void setBooleanPropertyDefault(String key, boolean value){
-		// delegate to new property based config style
-		moduleConfigProperties.setBooleanPropertyDefault(key, value);		
-	}
-	/**
-	 * Set a default value for an integer property
-	 * @param propertyName
-	 * @param value
-	 */
-	protected void setIntPropertyDefault(String key, int value){
-		// delegate to new property based config style
-		moduleConfigProperties.setIntPropertyDefault(key, value);		
-	}
-	
-	/**
-	 * @see org.olat.core.util.event.GenericEventListener#event(org.olat.core.gui.control.Event)
-	 */
-	public void event(Event event) {
-		if (event instanceof PersistedPropertiesChangedEvent) {
-			PersistedPropertiesChangedEvent persistedPropertiesEvent = (PersistedPropertiesChangedEvent) event;
-			if (!persistedPropertiesEvent.isEventOnThisNode()) {
-				// Reload the module configuration from disk, only when event not fired by this node
-				moduleConfigProperties.loadPropertiesFromFile();
-			}
-			// Call abstract method to initialize after the property changed, even when changes
-			// were triggered by this node. 
-			initFromChangedProperties();				
-		}		
-	}
-}
diff --git a/src/main/java/org/olat/core/gui/render/velocity/VelocityRenderDecorator.java b/src/main/java/org/olat/core/gui/render/velocity/VelocityRenderDecorator.java
index 269a4cee654..f7f61642d63 100644
--- a/src/main/java/org/olat/core/gui/render/velocity/VelocityRenderDecorator.java
+++ b/src/main/java/org/olat/core/gui/render/velocity/VelocityRenderDecorator.java
@@ -982,15 +982,17 @@ public class VelocityRenderDecorator implements Closeable {
 	}
 	
 	public Languages getLanguages() {
-		I18nManager i18nMgr = I18nManager.getInstance();
-		Collection<String> enabledKeysSet = I18nModule.getEnabledLanguageKeys();
+		I18nManager i18nMgr = CoreSpringFactory.getImpl(I18nManager.class);
+		I18nModule i18nModule = CoreSpringFactory.getImpl(I18nModule.class);
+		
+		Collection<String> enabledKeysSet = i18nModule.getEnabledLanguageKeys();
 		Map<String, String> langNames = new HashMap<String, String>();
 		Map<String, String> langTranslators = new HashMap<String, String>();
 		String[] enabledKeys = ArrayHelper.toArray(enabledKeysSet);
 		String[] names = new String[enabledKeys.length];
 		for (int i = 0; i < enabledKeys.length; i++) {
 			String key = enabledKeys[i];
-			String langName = i18nMgr.getLanguageInEnglish(key, I18nModule.isOverlayEnabled());
+			String langName = i18nMgr.getLanguageInEnglish(key, i18nModule.isOverlayEnabled());
 			langNames.put(key, langName);
 			names[i] = langName;
 			String author = i18nMgr.getLanguageAuthor(key);
diff --git a/src/main/java/org/olat/core/gui/translator/PackageTranslator.java b/src/main/java/org/olat/core/gui/translator/PackageTranslator.java
index 2558f5c6fd5..e0c7cb79537 100644
--- a/src/main/java/org/olat/core/gui/translator/PackageTranslator.java
+++ b/src/main/java/org/olat/core/gui/translator/PackageTranslator.java
@@ -32,6 +32,7 @@ import java.io.Writer;
 import java.util.Locale;
 
 import org.apache.log4j.Level;
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.helpers.Settings;
 import org.olat.core.logging.OLATRuntimeException;
 import org.olat.core.logging.OLog;
@@ -51,12 +52,19 @@ public class PackageTranslator implements Translator {
 	private final String packageName;
 	private Locale locale;
 	private int fallBackLevel = 0;
+	
+	private final I18nModule i18nModule;
+	private final I18nManager i18nManager;
+	
+	
 
 	private PackageTranslator(String packageName, Locale locale, boolean fallBack, Translator fallBackTranslator) {
 		this.locale = locale;
 		this.packageName = packageName;
 		this.fallBackTranslator = fallBackTranslator;
 		this.fallBack = fallBack;
+		i18nManager = CoreSpringFactory.getImpl(I18nManager.class);
+		i18nModule = CoreSpringFactory.getImpl(I18nModule.class);
 	}
 	
 	public void setFallBack(PackageTranslator fallback){
@@ -198,9 +206,8 @@ public class PackageTranslator implements Translator {
    */
 	@Override
 	public String translate(String key, String[] args, boolean fallBackToDefaultLocale) {
-		I18nManager i18n = I18nManager.getInstance();
-		boolean overlayEnabled = I18nModule.isOverlayEnabled();
-		String val = i18n.getLocalizedString(packageName, key, args, locale, overlayEnabled, fallBackToDefaultLocale);
+		boolean overlayEnabled = i18nModule.isOverlayEnabled();
+		String val = i18nManager.getLocalizedString(packageName, key, args, locale, overlayEnabled, fallBackToDefaultLocale);
 		if (val == null) {
 			// if not found, try the fallBackTranslator
 			if (fallBackTranslator != null && fallBackLevel < 10) {
@@ -209,10 +216,10 @@ public class PackageTranslator implements Translator {
 			} else if (fallBack) { // both fallback and fallbacktranslator does not
 				// make sense; latest translator in chain should
 				// fallback to application fallback.
-				val = i18n.getLocalizedString(I18nModule.getApplicationFallbackBundle(), key, args, locale, overlayEnabled, fallBackToDefaultLocale);
+				val = i18nManager.getLocalizedString(i18nModule.getApplicationFallbackBundle(), key, args, locale, overlayEnabled, fallBackToDefaultLocale);
 				if (val == null) {
 					// lastly fall back to brasato framework fallback
-					val = i18n.getLocalizedString(I18nModule.getCoreFallbackBundle(), key, args, locale, overlayEnabled, fallBackToDefaultLocale);
+					val = i18nManager.getLocalizedString(i18nModule.getCoreFallbackBundle(), key, args, locale, overlayEnabled, fallBackToDefaultLocale);
 				}
 			}
 		} 
diff --git a/src/main/java/org/olat/core/logging/LogRealTimeViewerController.java b/src/main/java/org/olat/core/logging/LogRealTimeViewerController.java
index 86e13430246..75f3c56297b 100644
--- a/src/main/java/org/olat/core/logging/LogRealTimeViewerController.java
+++ b/src/main/java/org/olat/core/logging/LogRealTimeViewerController.java
@@ -19,9 +19,13 @@
  */
 package org.olat.core.logging;
 
+import static org.quartz.CronScheduleBuilder.cronSchedule;
+import static org.quartz.JobBuilder.newJob;
+import static org.quartz.TriggerBuilder.newTrigger;
+import static org.quartz.impl.matchers.KeyMatcher.keyEquals;
+
 import java.io.IOException;
 import java.io.StringWriter;
-import java.text.ParseException;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -31,6 +35,7 @@ import org.apache.log4j.Logger;
 import org.apache.log4j.PatternLayout;
 import org.apache.log4j.WriterAppender;
 import org.olat.core.CoreSpringFactory;
+import org.olat.core.commons.services.scheduler.DummyJob;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.htmlheader.jscss.JSAndCSSComponent;
@@ -41,14 +46,16 @@ import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
 import org.olat.core.util.Formatter;
-import org.quartz.CronTrigger;
 import org.quartz.JobDetail;
 import org.quartz.JobExecutionContext;
 import org.quartz.JobExecutionException;
+import org.quartz.JobKey;
 import org.quartz.JobListener;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
-import org.quartz.jobs.NoOpJob;
+import org.quartz.Trigger;
+import org.quartz.TriggerKey;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * Description:<br>
@@ -68,10 +75,13 @@ public class LogRealTimeViewerController extends BasicController implements JobL
 	private Logger log4JLogger;
 	private WriterAppender writerAppender;
 	private StringWriter writer;
-	private JobDetail jobDetail;
-	private String jobName;
+	private JobKey jobKey;
+	private TriggerKey triggerKey;
 	private Link updateLink, startLink, stopLink;
 	private boolean removeLogNoise;
+	
+	@Autowired
+	private Scheduler scheduler;
 
 	/**
 	 * Constructor for creating a real time log viewer controller
@@ -106,21 +116,23 @@ public class LogRealTimeViewerController extends BasicController implements JobL
 		updateLogViewFromWriter();
 		// Add job to read from the string writer every second
 		try {
-			jobName = "Log_Displayer_Job_" + this.hashCode();
-			jobDetail = new JobDetail(jobName, LOG_DISPLAYER_GROUP, NoOpJob.class);
-			jobDetail.addJobListener(jobName);
-			CronTrigger trigger = new CronTrigger();
-			trigger.setName(jobName);
-			trigger.setGroup(LOG_DISPLAYER_GROUP);
-			trigger.setCronExpression("* * * * * ?");
+			jobKey = new JobKey("Log_Displayer_Job_" + this.hashCode(), LOG_DISPLAYER_GROUP);
+			triggerKey = new TriggerKey("Log_Displayer_Trigger_" + this.hashCode(), LOG_DISPLAYER_GROUP);
+			
+			JobDetail jobDetail = newJob(DummyJob.class)
+					.withIdentity(jobKey)
+					.build();
+			
+			Trigger trigger = newTrigger()
+				    .withIdentity(triggerKey)
+				    .withSchedule(cronSchedule("* * * * * ?"))
+				    .build();
+			
 			// Schedule job now
-			Scheduler scheduler = (Scheduler) CoreSpringFactory.getBean("schedulerFactoryBean");
-			scheduler.addJobListener(this);
+			scheduler.getListenerManager().addJobListener(this, keyEquals(jobKey));
 			scheduler.scheduleJob(jobDetail, trigger);
-		} catch (ParseException e) {
+		} catch (Exception e) {
 			logError("Can not parse log viewer cron expression", e);
-		} catch (SchedulerException e) {
-			logError("Problem when creating log viewer scheduler", e);
 		}
 		// Add one second interval to update the log view every second
 		JSAndCSSComponent jsc = new JSAndCSSComponent("intervall", this.getClass(), 3000);
@@ -138,13 +150,12 @@ public class LogRealTimeViewerController extends BasicController implements JobL
 	 */
 	@Override
 	protected void doDispose() {
-		
 		if (logViewerVC != null) { // don't clean up twice
 			Scheduler scheduler = (Scheduler) CoreSpringFactory.getBean("schedulerFactoryBean");
 			// remove scheduler job first
 			try {
-				scheduler.deleteJob(jobName, LOG_DISPLAYER_GROUP);
-				scheduler.removeJobListener(jobName);
+				scheduler.deleteJob(jobKey);
+				scheduler.getListenerManager().removeJobListener(jobKey.getName());
 			} catch (SchedulerException e) {
 				logError("Can not delete log viewer job", e);
 			}
@@ -193,44 +204,51 @@ public class LogRealTimeViewerController extends BasicController implements JobL
 	protected void event(UserRequest ureq, Component source, Event event) {
 		if (source == updateLink) {
 			updateLogViewFromWriter();
+		} else if (source == stopLink) {
+			doStop();
+		} else if (source == startLink) {
+			doStart();
+		}		
+	}
+	
+	private void doStart() {
+		// update viewable links
+		logViewerVC.remove(startLink);
+		updateLink = LinkFactory.createButtonSmall("logviewer.link.update", logViewerVC, this);
+		stopLink = LinkFactory.createButtonSmall("logviewer.link.stop", logViewerVC, this);
+		// re-add appender to logger
+		log4JLogger.addAppender(writerAppender);
+		// resume trigger job
+		try {
+			Scheduler scheduler = (Scheduler) CoreSpringFactory.getBean("schedulerFactoryBean");
+			scheduler.resumeJob(jobKey);
+		} catch (SchedulerException e) {
+			logError("Can not resume log viewer job", e);
 		}
-		if (source == stopLink) {
-			// update viewable links
-			logViewerVC.remove(stopLink);
-			logViewerVC.remove(updateLink);
-			startLink = LinkFactory.createButtonSmall("logviewer.link.start", logViewerVC, this);
-			// remove logger appender
-			log4JLogger.removeAppender(writerAppender);
-			// pause log update trigger job
-			try {
-				Scheduler scheduler = (Scheduler) CoreSpringFactory.getBean("schedulerFactoryBean");
-				scheduler.pauseJob(jobName, LOG_DISPLAYER_GROUP);
-			} catch (SchedulerException e) {
-				logError("Can not pause log viewer job", e);
-			}
+	}
+	
+	private void doStop() {
+		// update viewable links
+		logViewerVC.remove(stopLink);
+		logViewerVC.remove(updateLink);
+		startLink = LinkFactory.createButtonSmall("logviewer.link.start", logViewerVC, this);
+		// remove logger appender
+		log4JLogger.removeAppender(writerAppender);
+		// pause log update trigger job
+		try {
+			Scheduler scheduler = (Scheduler) CoreSpringFactory.getBean("schedulerFactoryBean");
+			scheduler.pauseJob(jobKey);
+		} catch (SchedulerException e) {
+			logError("Can not pause log viewer job", e);
 		}
-		if (source == startLink) {
-			// update viewable links
-			logViewerVC.remove(startLink);
-			updateLink = LinkFactory.createButtonSmall("logviewer.link.update", logViewerVC, this);
-			stopLink = LinkFactory.createButtonSmall("logviewer.link.stop", logViewerVC, this);
-			// re-add appender to logger
-			log4JLogger.addAppender(writerAppender);
-			// resume trigger job
-			try {
-				Scheduler scheduler = (Scheduler) CoreSpringFactory.getBean("schedulerFactoryBean");
-				scheduler.resumeJob(jobName, LOG_DISPLAYER_GROUP);
-			} catch (SchedulerException e) {
-				logError("Can not resume log viewer job", e);
-			}
-		}		
 	}
 
 	/**
 	 * @see org.quartz.JobListener#getName()
 	 */
+	@Override
 	public String getName() {
-		return jobName;
+		return jobKey.getName();
 	}
 
 	/**
diff --git a/src/main/java/org/olat/core/servlets/OpenOLATServlet.java b/src/main/java/org/olat/core/servlets/OpenOLATServlet.java
index 5ead513dede..b78d55c54b0 100644
--- a/src/main/java/org/olat/core/servlets/OpenOLATServlet.java
+++ b/src/main/java/org/olat/core/servlets/OpenOLATServlet.java
@@ -36,7 +36,6 @@ import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.persistence.DBFactory;
 import org.olat.core.commons.services.taskexecutor.TaskExecutorManager;
 import org.olat.core.commons.services.webdav.WebDAVDispatcher;
-import org.olat.core.configuration.AbstractOLATModule;
 import org.olat.core.configuration.AbstractSpringModule;
 import org.olat.core.configuration.PreWarm;
 import org.olat.core.dispatcher.Dispatcher;
@@ -127,8 +126,6 @@ public class OpenOLATServlet extends HttpServlet {
 		
 		//preload extensions
 		ExtManager.getInstance().getExtensions();
-		
-		AbstractOLATModule.printStats();
 		AbstractSpringModule.printStats();
 		preWarm();
 	}
diff --git a/src/main/java/org/olat/core/util/_spring/utilCorecontext.xml b/src/main/java/org/olat/core/util/_spring/utilCorecontext.xml
index e48bab49995..9dfa12cb166 100644
--- a/src/main/java/org/olat/core/util/_spring/utilCorecontext.xml
+++ b/src/main/java/org/olat/core/util/_spring/utilCorecontext.xml
@@ -8,7 +8,7 @@
   http://www.springframework.org/schema/context 
   http://www.springframework.org/schema/context/spring-context.xsd">
   
-	<context:component-scan base-package="org.olat.core.util.session,org.olat.core.util.vfs.version,org.olat.core.helpers" />
+	<context:component-scan base-package="org.olat.core.util.session,org.olat.core.util.vfs.version,org.olat.core.util.i18n" />
 
 	<bean id="codeHelper" class="org.olat.core.util.CodeHelper" >
 		<constructor-arg value="${node.id}" />
diff --git a/src/main/java/org/olat/core/util/i18n/I18nDirectoriesVisitor.java b/src/main/java/org/olat/core/util/i18n/I18nDirectoriesVisitor.java
index bf1233447f3..54bea141813 100644
--- a/src/main/java/org/olat/core/util/i18n/I18nDirectoriesVisitor.java
+++ b/src/main/java/org/olat/core/util/i18n/I18nDirectoriesVisitor.java
@@ -36,9 +36,10 @@ import org.olat.core.util.FileVisitor;
  * @author gnaegi
  */
 class I18nDirectoriesVisitor implements FileVisitor {
-	private OLog log = Tracing.createLoggerFor(I18nDirectoriesVisitor.class);
+	private static final OLog log = Tracing.createLoggerFor(I18nDirectoriesVisitor.class);
 	private String basePath;
 	private List<String> bundles = new LinkedList<String>();
+	private final List<String> referenceLangKeys;
 
 	/**
 	 * Packag scope constructor
@@ -46,8 +47,9 @@ class I18nDirectoriesVisitor implements FileVisitor {
 	 * @param basePathConfig The base path to be subtracted from the file name to
 	 *          get the classname
 	 */
-	I18nDirectoriesVisitor(String basePathConfig) {
+	I18nDirectoriesVisitor(String basePathConfig, List<String> referenceLangKeys) {
 		basePath = basePathConfig;
+		this.referenceLangKeys = referenceLangKeys;
 	}
 
 	/**
@@ -58,7 +60,6 @@ class I18nDirectoriesVisitor implements FileVisitor {
 		if (file.isFile()) { // regular file
 			String toBeChechedkFilName = file.getName();
 			// match?
-			List<String> referenceLangKeys = I18nModule.getTransToolReferenceLanguages();
 			for (String langKey : referenceLangKeys) {
 				String computedFileName = I18nModule.LOCAL_STRINGS_FILE_PREFIX + langKey + I18nModule.LOCAL_STRINGS_FILE_POSTFIX;
 				if (toBeChechedkFilName.equals(computedFileName)) {
diff --git a/src/main/java/org/olat/core/util/i18n/I18nManager.java b/src/main/java/org/olat/core/util/i18n/I18nManager.java
index 1d96939ef14..2af4f1d209b 100644
--- a/src/main/java/org/olat/core/util/i18n/I18nManager.java
+++ b/src/main/java/org/olat/core/util/i18n/I18nManager.java
@@ -30,7 +30,6 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
-import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -71,9 +70,7 @@ import org.olat.core.helpers.Settings;
 import org.olat.core.logging.AssertException;
 import org.olat.core.logging.OLATRuntimeException;
 import org.olat.core.logging.OLog;
-import org.olat.core.logging.StartupException;
 import org.olat.core.logging.Tracing;
-import org.olat.core.manager.BasicManager;
 import org.olat.core.util.AlwaysEmptyMap;
 import org.olat.core.util.CodeHelper;
 import org.olat.core.util.FileUtils;
@@ -83,8 +80,8 @@ import org.olat.core.util.StringHelper;
 import org.olat.core.util.UserSession;
 import org.olat.core.util.WebappHelper;
 import org.olat.core.util.session.UserSessionManager;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
 
 
 /**
@@ -96,12 +93,14 @@ import org.springframework.core.io.Resource;
  * 
  * @author Felix Jost
  */
+@Service("I18nManager")
+public class I18nManager {
 
-public class I18nManager extends BasicManager {
+	private static final OLog log = Tracing.createLoggerFor(I18nManager.class);
+	
 	private static final String BUNDLE_INLINE_TRANSLATION_INTERCEPTOR = "org.olat.core.util.i18n.ui";
 	private static final String BUNDLE_EXCEPTION = "org.olat.core.gui.exception";
 	private static I18nManager INSTANCE;
-	private static final OLog log = Tracing.createLoggerFor(I18nManager.class);
 	public static final String FILE_NOT_FOUND_ERROR_PREFIX = ":::file not found";
 	public static final String USESS_KEY_I18N_MARK_LOCALIZED_STRINGS = "I18N_MARK_LOCALIZED_STRINGS";
 
@@ -139,17 +138,16 @@ public class I18nManager extends BasicManager {
 	private ConcurrentMap<String, Properties> cachedBundles = new ConcurrentHashMap<String, Properties>();
 	private ConcurrentMap<String, String> cachedJSTranslatorData = new ConcurrentHashMap<String, String>();
 	private ConcurrentMap<String, Deque<String>> referencingBundlesIndex = new ConcurrentHashMap<String, Deque<String>>();
-	private static final ConcurrentMap<Locale,String> localeToLocaleKey = new ConcurrentHashMap<>();
 	private boolean cachingEnabled = true;
+	
+	private final I18nModule i18nModule;
 
-	private static FilenameFilter i18nFileFilter = new FilenameFilter() {
-		public boolean accept(File dir, String name) {
-			// don't add overlayLocales as selectable availableLanguages
-			// (LocaleStrings_de__VENDOR.properties)
-			if (name.startsWith(I18nModule.LOCAL_STRINGS_FILE_PREFIX) && name.indexOf("_") != 0 && name.endsWith(I18nModule.LOCAL_STRINGS_FILE_POSTFIX)) { return true; }
-			return false;
-		}
-	};
+	@Autowired
+	public I18nManager(I18nModule i18nModule) {
+		this.i18nModule = i18nModule;
+		setCachingEnabled(i18nModule.isCachingEnabled());
+		INSTANCE = this;
+	}
 
 	/**
 	 * @return the manager
@@ -217,7 +215,7 @@ public class I18nManager extends BasicManager {
 		// file
 		if (overlayEnabled) {
 
-			Locale overlayLocale = I18nModule.getOverlayLocales().get(locale);
+			Locale overlayLocale = i18nModule.getOverlayLocales().get(locale);
 			if (overlayLocale != null) {
 				properties = getProperties(overlayLocale, bundleName, resolveRecursively, recursionLevel);
 				if (properties != null) {
@@ -257,7 +255,7 @@ public class I18nManager extends BasicManager {
 			// 1. Check on variant
 			String variant = locale.getVariant();
 			if (!variant.equals("")) {
-				Locale newLoc = I18nModule.getAllLocales().get(locale.getLanguage() + "_" + locale.getCountry());
+				Locale newLoc = i18nModule.getAllLocales().get(locale.getLanguage() + "_" + locale.getCountry());
 				if (newLoc != null) msg = getLocalizedString(bundleName, key, args, newLoc, overlayEnabled, false, fallBackToFallbackLocale, resolveRecursively,
 						recursionLevel);
 			}
@@ -265,7 +263,7 @@ public class I18nManager extends BasicManager {
 				// 2. Check on country
 				String country = locale.getCountry();
 				if (!country.equals("")) {
-					Locale newLoc = I18nModule.getAllLocales().get(locale.getLanguage());
+					Locale newLoc = i18nModule.getAllLocales().get(locale.getLanguage());
 					if (newLoc != null) msg = getLocalizedString(bundleName, key, args, newLoc, overlayEnabled, false, fallBackToFallbackLocale, resolveRecursively,
 							recursionLevel);
 				}
@@ -280,16 +278,16 @@ public class I18nManager extends BasicManager {
 			// no: return null to indicate nothing was found so that callers may
 			// use fallbacks
 			if (fallBackToDefaultLocale) {
-				return getLocalizedString(bundleName, key, args, I18nModule.getDefaultLocale(), overlayEnabled, false, fallBackToFallbackLocale,
+				return getLocalizedString(bundleName, key, args, i18nModule.getDefaultLocale(), overlayEnabled, false, fallBackToFallbackLocale,
 						resolveRecursively, recursionLevel);
 			} else {
 				if (fallBackToFallbackLocale) {
 					// fallback to fallback locale
-					Locale fallbackLocale = I18nModule.getFallbackLocale();
+					Locale fallbackLocale = i18nModule.getFallbackLocale();
 					if (fallbackLocale.equals(locale)) {
 						// finish when when already in fallback locale
-						if (isLogDebugEnabled()) {
-							logWarn("Could not find translation for bundle::" + bundleName + " and key::" + key
+						if (log.isDebug()) {
+							log.warn("Could not find translation for bundle::" + bundleName + " and key::" + key
 									+ " ; not even in default or fallback packages", null);
 						}
 						return null;
@@ -374,7 +372,7 @@ public class I18nManager extends BasicManager {
 	 * @return List of i18n items
 	 */
 	public List<I18nItem> findExistingI18nItems(Locale targetLocale, String limitToBundleName, boolean includeBundlesChildren) {
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		List<I18nItem> foundTranslationItems = new LinkedList<I18nItem>();
 		for (String bundleName : allBundles) {
 			if (limitToBundleName == null || limitToBundleName.equals(bundleName)
@@ -411,7 +409,7 @@ public class I18nManager extends BasicManager {
 	 */
 	public List<I18nItem> findMissingI18nItems(Locale referenceLocale, Locale targetLocale, String limitToBundleName,
 			boolean includeBundlesChildren) {
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		List<I18nItem> foundTranslationItems = new LinkedList<I18nItem>();
 		for (String bundleName : allBundles) {
 			if (limitToBundleName == null || limitToBundleName.equals(bundleName)
@@ -450,7 +448,7 @@ public class I18nManager extends BasicManager {
 	 */
 	public List<I18nItem> findExistingAndMissingI18nItems(Locale referenceLocale, Locale targetLocale, String limitToBundleName,
 			boolean includeBundlesChildren) {
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		List<I18nItem> foundTranslationItems = new LinkedList<I18nItem>();
 		for (String bundleName : allBundles) {
 			if (limitToBundleName == null || limitToBundleName.equals(bundleName)
@@ -504,7 +502,7 @@ public class I18nManager extends BasicManager {
 	 */
 	public List<I18nItem> findI18nItemsByValueSearch(String searchString, Locale searchLocale, Locale targetLocale, String limitToBundleName,
 			boolean includeBundlesChildren) {
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		List<I18nItem> foundTranslationItems = new LinkedList<I18nItem>();
 		searchString = searchString.toLowerCase();
 		String[] parts = searchString.split("\\*");
@@ -553,7 +551,7 @@ public class I18nManager extends BasicManager {
 	 */
 	public List<I18nItem> findI18nItemsByKeySearch(String searchString, Locale searchLocale, Locale targetLocale, String limitToBundleName,
 			boolean includeBundlesChildren) {
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		List<I18nItem> foundTranslationItems = new LinkedList<I18nItem>();
 		searchString = searchString.toLowerCase();
 		for (String bundleName : allBundles) {
@@ -674,17 +672,17 @@ public class I18nManager extends BasicManager {
 	public void saveOrUpdateI18nItem(I18nItem i18nItem, String value) {
 		Properties properties = getPropertiesWithoutResolvingRecursively(i18nItem.getLocale(), i18nItem.getBundleName());
 		// Add logging block to find bogus save issues
-		if (isLogDebugEnabled()) {
+		if (log.isDebug()) {
 			String itemIdent = i18nItem.getLocale() + ":" + buildI18nItemIdentifyer(i18nItem.getBundleName(), i18nItem.getKey());
 			if (properties.containsKey(i18nItem.getKey())) {
 				if (StringHelper.containsNonWhitespace(value)) {
-					logDebug("Updating i18n item::" + itemIdent + " with new value::" + value, null);					
+					log.debug("Updating i18n item::" + itemIdent + " with new value::" + value, null);					
 				} else {
-					logDebug("Deleting i18n item::" + itemIdent + " because new value is emty", null);
+					log.debug("Deleting i18n item::" + itemIdent + " because new value is emty", null);
 				}
 			} else {
 				if (StringHelper.containsNonWhitespace(value)) {
-					logDebug("Creating i18n item::" + itemIdent + " with new value::" + value, null);		
+					log.debug("Creating i18n item::" + itemIdent + " with new value::" + value, null);		
 				}				
 			}
 		}
@@ -731,7 +729,7 @@ public class I18nManager extends BasicManager {
 	 * @return
 	 */
 	public int countI18nItems(Locale locale, String limitToBundleName, boolean includeBundlesChildren) {
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		int counter = 0;
 		for (String bundleName : allBundles) {
 			if (limitToBundleName == null || limitToBundleName.equals(bundleName)
@@ -755,7 +753,7 @@ public class I18nManager extends BasicManager {
 	 * @return
 	 */
 	public int countBundles(String limitToBundleName, boolean includeBundlesChildren) {
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		if (limitToBundleName == null) {
 			return allBundles.size();
 		} else if (!includeBundlesChildren) { return (allBundles.contains(limitToBundleName) ? 1 : 0); }
@@ -799,7 +797,7 @@ public class I18nManager extends BasicManager {
 			// Try to resolve all keys within this properties and add to
 			// cache
 			if (resolveRecursively) {
-				resolvePropertiesInternalKeys(locale, bundleName, props, I18nModule.isOverlayEnabled(), recursionLevel);
+				resolvePropertiesInternalKeys(locale, bundleName, props, i18nModule.isOverlayEnabled(), recursionLevel);
 				cachedBundles.put(key, props);
 			}
 			if (locale == null) {
@@ -819,14 +817,14 @@ public class I18nManager extends BasicManager {
 			//
 			// 1) Try to load the bundle from a configured source path
 			// This is also used to load the overlay properties
-			File baseDir = I18nModule.getPropertyFilesBaseDir(locale, bundleName);
+			File baseDir = i18nModule.getPropertyFilesBaseDir(locale, bundleName);
 			if (baseDir != null) {
 				File f = getPropertiesFile(locale, bundleName, baseDir);
 				// if file exists load properties from file, otherwise
 				// proceed with 2)
 				if (f.exists()) {
 					is = new FileInputStream(f);
-					if (logDebug) logDebug("loading LocalStrings from file::" + f.getAbsolutePath(), null);
+					if (logDebug) log.debug("loading LocalStrings from file::" + f.getAbsolutePath(), null);
 				}
 			}
 			//
@@ -838,7 +836,7 @@ public class I18nManager extends BasicManager {
 				String relPath = bundleName.replace('.', '/') + "/" + I18N_DIRNAME + "/" + fileName;
 				ClassLoader classLoader = this.getClass().getClassLoader();
 				is = classLoader.getResourceAsStream(relPath);
-				if (logDebug && is != null) logDebug("loading LocalStrings from classpath relpath::" + relPath, null);
+				if (logDebug && is != null) log.debug("loading LocalStrings from classpath relpath::" + relPath, null);
 			}
 			// Now load the properties from resource (file, classpath or
 			// langpacks)
@@ -974,10 +972,10 @@ public class I18nManager extends BasicManager {
 	 */
 	public void saveOrUpdateProperties(Properties properties, Locale locale, String bundleName) {
 		String key = calcPropertiesFileKey(locale, bundleName);
-		if (isLogDebugEnabled()) logDebug("saveOrUpdateProperties for key::" + key, null);
+		if (log.isDebug()) log.debug("saveOrUpdateProperties for key::" + key, null);
 
 		// 1) Save file to disk
-		File baseDir = I18nModule.getPropertyFilesBaseDir(locale, bundleName);
+		File baseDir = i18nModule.getPropertyFilesBaseDir(locale, bundleName);
 		if (baseDir == null) { throw new AssertException("Can not save or update properties file for bundle::" + bundleName
 				+ " and language::" + locale.toString() + " - no base directory found, probably loaded from jar!"); }
 		File propertiesFile = getPropertiesFile(locale, bundleName, baseDir);
@@ -999,11 +997,11 @@ public class I18nManager extends BasicManager {
 			try {
 				if (fileStream != null) fileStream.close();
 			} catch (IOException e) {
-				logError("Could not close stream after save or update to file::" + propertiesFile.getAbsolutePath(), e);
+				log.error("Could not close stream after save or update to file::" + propertiesFile.getAbsolutePath(), e);
 			}
 		}
 		// 2) Check if bundle was already in list of known bundles, add it
-		List<String> knownBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> knownBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		if (!knownBundles.contains(bundleName)) {
 			knownBundles.add(bundleName);
 			Collections.sort(knownBundles);
@@ -1038,7 +1036,7 @@ public class I18nManager extends BasicManager {
 	 */
 	public void deleteProperties(Locale locale, String bundleName) {
 		String key = calcPropertiesFileKey(locale, bundleName);
-		if (isLogDebugEnabled()) logDebug("deleteProperties for key::" + key, null);
+		if (log.isDebug()) log.debug("deleteProperties for key::" + key, null);
 
 		if (locale != null) { // metadata files are not in cache
 			// 1) Remove from cache first
@@ -1050,7 +1048,7 @@ public class I18nManager extends BasicManager {
 			}
 		}
 		// 2) Remove from filesystem
-		File baseDir = I18nModule.getPropertyFilesBaseDir(locale, bundleName);
+		File baseDir = i18nModule.getPropertyFilesBaseDir(locale, bundleName);
 		if (baseDir == null) {
 			if (baseDir == null) { throw new AssertException("Can not delete properties file for bundle::" + bundleName + " and language::"
 					+ locale.toString() + " - no base directory found, probably loaded from jar!"); }
@@ -1060,8 +1058,8 @@ public class I18nManager extends BasicManager {
 		// 3) Check if for this bundle any other language file exists, if
 		// not remove
 		// the bundle from the list of translatable bundles
-		List<String> knownBundles = I18nModule.getBundleNamesContainingI18nFiles();
-		Set<String> knownLangs = I18nModule.getAvailableLanguageKeys();
+		List<String> knownBundles = i18nModule.getBundleNamesContainingI18nFiles();
+		Set<String> knownLangs = i18nModule.getAvailableLanguageKeys();
 		boolean foundOther = false;
 		for (String lang : knownLangs) {
 			f = getPropertiesFile(getLocaleOrDefault(lang), bundleName, baseDir);
@@ -1102,13 +1100,13 @@ public class I18nManager extends BasicManager {
 			StringBuilder data = new StringBuilder();
 			// we build an js object with key-value pairs
 			data.append("var transData = {");
-			Locale referenceLocale = I18nModule.getFallbackLocale();
+			Locale referenceLocale = i18nModule.getFallbackLocale();
 			Properties properties = getPropertiesWithoutResolvingRecursively(referenceLocale, bundleName);
 			Set<Object> keys = properties.keySet();
 			boolean addComma = false;
 			for (Object keyObject : keys) {
 				String key = (String) keyObject;
-				String value = getLocalizedString(bundleName, key, null, locale, I18nModule.isOverlayEnabled(), true);
+				String value = getLocalizedString(bundleName, key, null, locale, i18nModule.isOverlayEnabled(), true);
 				if (value == null) {
 					// use bundlename:key as value in case the key can't be
 					// translated
@@ -1133,12 +1131,12 @@ public class I18nManager extends BasicManager {
 	
 	public JSONObject getJSONTranslatorData(Locale locale, String bundleName) {
 		JSONObject array = new JSONObject();
-		Locale referenceLocale = I18nModule.getFallbackLocale();
+		Locale referenceLocale = i18nModule.getFallbackLocale();
 		Properties properties = getPropertiesWithoutResolvingRecursively(referenceLocale, bundleName);
 		Set<Object> keys = properties.keySet();
 		for (Object keyObject : keys) {
 			String key = (String) keyObject;
-			String value = getLocalizedString(bundleName, key, null, locale, I18nModule.isOverlayEnabled(), true);
+			String value = getLocalizedString(bundleName, key, null, locale, i18nModule.isOverlayEnabled(), true);
 			if (value == null) {
 				// use bundlename:key as value in case the key can't be
 				// translated
@@ -1151,7 +1149,7 @@ public class I18nManager extends BasicManager {
 			try {
 				array.put(key, value);
 			} catch (JSONException e) {
-				logError("", e);
+				log.error("", e);
 			}
 		}
 		return array;
@@ -1165,7 +1163,7 @@ public class I18nManager extends BasicManager {
 	 * @return
 	 */
 	public Long getLastModifiedDate(Locale locale, String bundleName) {
-		File baseDir = I18nModule.getPropertyFilesBaseDir(locale, bundleName);
+		File baseDir = i18nModule.getPropertyFilesBaseDir(locale, bundleName);
 		if (baseDir != null) {
 			File propertyFile = getPropertiesFile(locale, bundleName, baseDir);
 			return (propertyFile.lastModified());
@@ -1188,9 +1186,11 @@ public class I18nManager extends BasicManager {
 	 *         method, or the default locale if the language was not found
 	 */
 	public Locale getLocaleOrDefault(String localeKey) {
-		if (localeKey == null || !I18nModule.getAvailableLanguageKeys().contains(localeKey)) { return I18nModule.getDefaultLocale(); }
-		Locale loc = I18nModule.getAllLocales().get(localeKey);
-		if (loc == null) loc = I18nModule.getDefaultLocale();
+		if (localeKey == null || !i18nModule.getAvailableLanguageKeys().contains(localeKey)) {
+			return i18nModule.getDefaultLocale();
+		}
+		Locale loc = i18nModule.getAllLocales().get(localeKey);
+		if (loc == null) loc = i18nModule.getDefaultLocale();
 		return loc;
 	}
 
@@ -1206,8 +1206,10 @@ public class I18nManager extends BasicManager {
 	 *         method, or if no language was found
 	 */
 	public Locale getLocaleOrNull(String localeKey) {
-		if (localeKey == null || (!I18nModule.getAvailableLanguageKeys().contains(localeKey) && !I18nModule.getOverlayLanguageKeys().contains(localeKey))) { return null; }
-		Locale loc = I18nModule.getAllLocales().get(localeKey);
+		if (localeKey == null || (!i18nModule.getAvailableLanguageKeys().contains(localeKey) && !i18nModule.getOverlayLanguageKeys().contains(localeKey))) {
+			return null;
+		}
+		Locale loc = i18nModule.getAllLocales().get(localeKey);
 		return loc;
 	}
 
@@ -1223,9 +1225,9 @@ public class I18nManager extends BasicManager {
 	public String getLanguageTranslated(String languageKey, boolean overlayEnabled) {
 		// Load it from package without fallback
 		String translated = null;
-		Locale locale = I18nModule.getAllLocales().get(languageKey);
+		Locale locale = i18nModule.getAllLocales().get(languageKey);
 		if(locale != null) {
-			translated = getLocalizedString(I18nModule.getCoreFallbackBundle(), "this.language.translated", null, locale, overlayEnabled, false, false, false, 0);
+			translated = getLocalizedString(i18nModule.getCoreFallbackBundle(), "this.language.translated", null, locale, overlayEnabled, false, false, false, 0);
 		}
 		if (translated == null) {
 			// Use the english version as callback
@@ -1242,12 +1244,12 @@ public class I18nManager extends BasicManager {
 	 * @return
 	 */
 	public Map<String, String> getEnabledLanguagesTranslated() {
-		Collection<String> enabledLangs = I18nModule.getEnabledLanguageKeys();
+		Collection<String> enabledLangs = i18nModule.getEnabledLanguageKeys();
 		Map<String, String> translatedLangs = new HashMap<String, String>(11);
 		for (String langKey : enabledLangs) {
 			String translated = cachedLangTranslated.get(langKey);
 			if(translated == null) {
-				String newTranslated = getLanguageTranslated(langKey, I18nModule.isOverlayEnabled());
+				String newTranslated = getLanguageTranslated(langKey, i18nModule.isOverlayEnabled());
 				translated = cachedLangTranslated.putIfAbsent(langKey, newTranslated);
 				if(translated == null) {
 					translated = newTranslated;
@@ -1268,7 +1270,7 @@ public class I18nManager extends BasicManager {
 	 */
 	public String getLanguageInEnglish(String languageKey, boolean overlayEnabled) {
 		// Load it from package without fallback
-		String inEnglish = getLocalizedString(I18nModule.getCoreFallbackBundle(), "this.language.in.english", null, I18nModule
+		String inEnglish = getLocalizedString(i18nModule.getCoreFallbackBundle(), "this.language.in.english", null, i18nModule
 				.getAllLocales().get(languageKey), overlayEnabled, false, false, false, 0);
 		if (inEnglish == null) {
 			// use key as fallback
@@ -1287,7 +1289,7 @@ public class I18nManager extends BasicManager {
 	 */
 	public String getLanguageAuthor(String languageKey) {
 		// Load it from package without fallback
-		String authors = getLocalizedString(I18nModule.getCoreFallbackBundle(), "this.language.translator.names", null, I18nModule
+		String authors = getLocalizedString(i18nModule.getCoreFallbackBundle(), "this.language.translator.names", null, i18nModule
 				.getAllLocales().get(languageKey), false, false, false, false, 0);
 		if (authors == null) { return "-"; }
 		return authors;
@@ -1322,21 +1324,18 @@ public class I18nManager extends BasicManager {
 	public static void attachI18nInfoToThread(HttpServletRequest hreq) {
 		UserSession usess = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(hreq);
 		if (threadLocalLocale == null) {
-			I18nManager.getInstance().logError("can't attach i18n info to thread: threadLocalLocale is null", null);
+			log.error("can't attach i18n info to thread: threadLocalLocale is null", null);
 		} else {
 			if (threadLocalLocale.getThreadLocale() != null) {
-				I18nManager.getInstance().logWarn(
-						"try to attach i18n info to thread, but threadLocalLocale is not null - a thread forgot to remove it!", new Exception("attachI18nInfoToThread"));
+				log.warn("try to attach i18n info to thread, but threadLocalLocale is not null - a thread forgot to remove it!", new Exception("attachI18nInfoToThread"));
 			}
 			threadLocalLocale.setThredLocale(usess.getLocale());
 		}
 		if (threadLocalIsMarkLocalizedStringsEnabled == null) {
-			I18nManager.getInstance().logError("can't attach i18n info to thread: threadLocalIsMarkLocalizedStringsEnabled is null", null);
+			log.error("can't attach i18n info to thread: threadLocalIsMarkLocalizedStringsEnabled is null", null);
 		} else {
 			if (threadLocalIsMarkLocalizedStringsEnabled.isMarkLocalizedStringsEnabled() != null) {
-				I18nManager.getInstance().logWarn(
-						"try to attach i18n info to thread, but threadLocalIsMarkLocalizedStringsEnabled is not null - a thread forgot to remove it!",
-						null);
+				log.warn("try to attach i18n info to thread, but threadLocalIsMarkLocalizedStringsEnabled is not null - a thread forgot to remove it!", null);
 			}
 			Boolean isMarkLocalizedStringsEnabled = (Boolean) usess.getEntry(USESS_KEY_I18N_MARK_LOCALIZED_STRINGS);
 			if (isMarkLocalizedStringsEnabled != null) {
@@ -1347,7 +1346,7 @@ public class I18nManager extends BasicManager {
 	
 	public static void updateLocaleInfoToThread(UserSession usess) {
 		if (threadLocalLocale == null) {
-			I18nManager.getInstance().logError("can't attach i18n info to thread: threadLocalLocale is null", null);
+			log.error("can't attach i18n info to thread: threadLocalLocale is null", null);
 		} else {
 			threadLocalLocale.setThredLocale(usess.getLocale());
 		}
@@ -1377,7 +1376,7 @@ public class I18nManager extends BasicManager {
 			Locale locale = threadLocalLocale.getThreadLocale();
 			if (locale != null) return threadLocalLocale.getThreadLocale();
 		}
-		return I18nModule.getDefaultLocale();
+		return i18nModule.getDefaultLocale();
 	}
 
 	/**
@@ -1431,7 +1430,7 @@ public class I18nManager extends BasicManager {
 			try {
 				return (Integer.parseInt(bundlePrioValue.trim()));
 			} catch (NumberFormatException e) {
-				logWarn("Can not parse metadata priority for bundle::" + bundleName, e);
+				log.warn("Can not parse metadata priority for bundle::" + bundleName, e);
 			}
 		}
 		// 2) Not found, try with parent bundle
@@ -1459,7 +1458,7 @@ public class I18nManager extends BasicManager {
 			try {
 				keyPriority = Integer.parseInt(keyPriorityValue.trim());
 			} catch (NumberFormatException e) {
-				logWarn("Can not parse metadata priority for key::" + bundleName + ":" + key, e);
+				log.warn("Can not parse metadata priority for key::" + bundleName + ":" + key, e);
 			}
 		}
 		return keyPriority;
@@ -1596,7 +1595,7 @@ public class I18nManager extends BasicManager {
 			cachedJSTranslatorData = new AlwaysEmptyMap<String, String>();
 			referencingBundlesIndex = new AlwaysEmptyMap<String, Deque<String>>();
 		}
-		this.cachingEnabled = useCache;
+		cachingEnabled = useCache;
 	}
 
 	/**
@@ -1604,74 +1603,7 @@ public class I18nManager extends BasicManager {
 	 *         filesystem
 	 */
 	public boolean isCachingEnabled() {
-		return this.cachingEnabled;
-	}
-
-	/**
-	 * Helper method to create a locale from a given locale key ('de', 'de_CH',
-	 * 'de_CH_ZH')
-	 * 
-	 * @param localeKey
-	 * @return the locale or NULL if no locale could be generated from this string
-	 */
-	Locale createLocale(String localeKey) {
-		Locale aloc = null;
-		// de
-		// de_CH
-		// de_CH_zueri
-		String[] parts = localeKey.split("_");
-		switch (parts.length) {
-			case 1:
-				aloc = new Locale(parts[0]);
-				break;
-			case 2:
-				aloc = new Locale(parts[0], parts[1]);
-				break;
-			case 3:
-				String lastPart = parts[2];
-				// Add all remaining parts to variant, variant can contain
-				// underscores according to Locale spec
-				for (int i = 3; i < parts.length; i++) {
-					String part = parts[i];
-					lastPart = lastPart + "_" + part;
-				}
-				aloc = new Locale(parts[0], parts[1], lastPart);
-				break;
-			default:
-				return null;
-		}
-		// Test if the locale has been constructed correctly. E.g. when the
-		// language part is not existing in the ISO chart, the locale can
-		// convert to something else.
-		// E.g. he_HE_HE will convert automatically to iw_HE_HE
-		if (aloc.toString().equals(localeKey)) {
-			return aloc;
-		} else {
-			return null;
-		}
-	}
-
-	/**
-	 * Create a local that represents the overlay locale for the given locale
-	 * 
-	 * @param locale The original locale
-	 * @return The overlay locale
-	 */
-	Locale createOverlay(Locale locale) {
-		String lang = locale.getLanguage();
-		String country = (locale.getCountry() == null ? "" : locale.getCountry());
-		String variant = createOverlayKeyForLanguage(locale.getVariant() == null ? "" : locale.getVariant());
-		Locale overlay = new Locale(lang, country, variant);
-		return overlay;
-	}
-
-	/**
-	 * Add the overlay postfix to the given language key
-	 * @param langKey
-	 * @return
-	 */
-	String createOverlayKeyForLanguage(String langKey) {
-		return langKey + "__" + I18nModule.getOverlayName();
+		return cachingEnabled;
 	}
 		
 	/**
@@ -1686,49 +1618,10 @@ public class I18nManager extends BasicManager {
 	 * @return
 	 */
 	public String buildI18nFilename(Locale locale) {
-		String langKey = getLocaleKey(locale);
+		String langKey = i18nModule.getLocaleKey(locale);
 		return I18nModule.LOCAL_STRINGS_FILE_PREFIX + langKey + I18nModule.LOCAL_STRINGS_FILE_POSTFIX;
 	}
 
-	/**
-	 * Calculate the locale key that identifies the given locale. Adds support for
-	 * the overlay mechanism.
-	 * 
-	 * @param locale
-	 * @return
-	 */
-	public String getLocaleKey(Locale locale) {
-		String key = localeToLocaleKey.get(locale);
-		if(key == null) {
-			String langKey = locale.getLanguage();
-			String country = locale.getCountry();
-			// Only add country when available - in case of an overlay country is
-			// set to
-			// an empty value
-			if (StringHelper.containsNonWhitespace(country)) {
-				langKey = langKey + "_" + country;
-			}
-			String variant = locale.getVariant();
-			// Only add the _ separator if the variant contains something in
-			// addition to
-			// the overlay, otherways use the __ only
-			if (StringHelper.containsNonWhitespace(variant)) {
-				if (variant.startsWith("__" + I18nModule.getOverlayName())) {
-					langKey += variant;
-				} else {
-					langKey = langKey + "_" + variant;
-				}
-			}
-			
-			key = localeToLocaleKey.putIfAbsent(locale, langKey);
-			if(key == null) {
-				key = langKey;
-			}
-			
-		}
-		return key;
-	}
-
 	/**
 	 * Calculate the language key from the given overlay locale without the locale
 	 * (the original language before adding the overlay postfix)
@@ -1737,11 +1630,11 @@ public class I18nManager extends BasicManager {
 	 * @return The original language key or NULL if not found
 	 */
 	public String createOrigianlLocaleKeyForOverlay(Locale overlay) {
-		Map<Locale,Locale> overlaysLooup = I18nModule.getOverlayLocales();
+		Map<Locale,Locale> overlaysLooup = i18nModule.getOverlayLocales();
 		Set<Map.Entry<Locale, Locale>> entries = overlaysLooup.entrySet();
 		for (Map.Entry<Locale, Locale> entry : entries) {
-			if (getLocaleKey(entry.getValue()).equals(getLocaleKey(overlay))) {
-				return getLocaleKey(entry.getKey());
+			if (i18nModule.getLocaleKey(entry.getValue()).equals(i18nModule.getLocaleKey(overlay))) {
+				return i18nModule.getLocaleKey(entry.getKey());
 			}
 		}
 		return null;
@@ -1758,79 +1651,6 @@ public class I18nManager extends BasicManager {
 		return bundleName + ":" + key;
 	}
 
-	/**
-	 * Search in all packages on the source patch for packages that contain an
-	 * _i18n directory that can be used to store olatcore localization files
-	 * 
-	 * @return set of bundles that contain olatcore i18n compatible localization
-	 *         files
-	 */
-	List<String> searchForBundleNamesContainingI18nFiles() {
-		List<String> foundBundles;
-		// 1) First search on normal source path of application
-		String srcPath = null; 
-		File applicationDir = I18nModule.getTransToolApplicationLanguagesSrcDir();
-		if (applicationDir != null) {
-			srcPath = applicationDir.getAbsolutePath();
-		} else {
-			// Fall back to compiled classes
-			srcPath = WebappHelper.getBuildOutputFolderRoot();
-		}
-		if(StringHelper.containsNonWhitespace(srcPath)) {
-			I18nDirectoriesVisitor srcVisitor = new I18nDirectoriesVisitor(srcPath);
-			FileUtils.visitRecursively(new File(srcPath), srcVisitor);
-			foundBundles = srcVisitor.getBundlesContainingI18nFiles();
-			// 3) For jUnit tests, add also the I18n test dir
-			if (Settings.isJUnitTest()) {
-				Resource testres = new ClassPathResource("olat.local.properties");
-				String jUnitSrcPath = null;
-				try {
-					jUnitSrcPath = testres.getFile().getAbsolutePath();
-				} catch (IOException e) {
-					throw new StartupException("Could not find classpath resource for: test-classes/olat.local.property ", e);
-	  			}
-	
-	
-				I18nDirectoriesVisitor juniSrcVisitor = new I18nDirectoriesVisitor(jUnitSrcPath);
-				FileUtils.visitRecursively(new File(jUnitSrcPath), juniSrcVisitor);
-				foundBundles.addAll(juniSrcVisitor.getBundlesContainingI18nFiles());
-			}
-			// Sort alphabetically
-			Collections.sort(foundBundles);
-		} else {
-			foundBundles = new ArrayList<String>();
-		}
-		return foundBundles;
-	}
-
-	/**
-	 * Search for available languages in the given directory. The translation
-	 * files must start with 'LocalStrings_' and end with '.properties'.
-	 * Everything in between is considered a language key.
-	 * <p>
-	 * If the directory contains jar files, those files are opened and searched
-	 * for languages files as well. In this case, the algorythm only looks for
-	 * translation files that are in the org/olat/core/_i18n package
-	 * 
-	 * @param i18nDir
-	 * @return set of language keys the system will find translations for
-	 */
-	Set<String> searchForAvailableLanguages(File i18nDir) {
-		Set<String> foundLanguages = new TreeSet<String>();
-		i18nDir = new File(i18nDir.getAbsolutePath()+"/org/olat/_i18n");
-		if (i18nDir.exists()) {
-			// First check for locale files
-			String[] langFiles = i18nDir.list(i18nFileFilter);
-			for (String langFileName : langFiles) {
-				String lang = langFileName.substring(I18nModule.LOCAL_STRINGS_FILE_PREFIX.length(), langFileName.lastIndexOf("."));
-				foundLanguages.add(lang);
-				if (isLogDebugEnabled()) logDebug("Adding lang::" + lang + " from filename::" + langFileName + " from dir::"
-						+ i18nDir.getAbsolutePath(), null);
-			}
-		}
-		return foundLanguages;
-	}
-
 	/**
 	 * Searches within a jar file for available languages.
 	 * 
@@ -1852,15 +1672,14 @@ public class I18nManager extends BasicManager {
 				// check for executables
 				if (checkForExecutables && (jarEntryName.endsWith("java") || jarEntryName.endsWith("class"))) { return new TreeSet<String>(); }
 				// search for core util in jar
-				if (jarEntryName.indexOf(I18nModule.getCoreFallbackBundle().replace(".", "/") + "/" + I18N_DIRNAME) != -1) {
+				if (jarEntryName.indexOf(i18nModule.getCoreFallbackBundle().replace(".", "/") + "/" + I18N_DIRNAME) != -1) {
 					// don't add overlayLocales as selectable
 					// availableLanguages
 					if (jarEntryName.indexOf("__") == -1 && jarEntryName.indexOf(I18nModule.LOCAL_STRINGS_FILE_PREFIX) != -1) {
 						String lang = jarEntryName.substring(jarEntryName.indexOf(I18nModule.LOCAL_STRINGS_FILE_PREFIX)
 								+ I18nModule.LOCAL_STRINGS_FILE_PREFIX.length(), jarEntryName.lastIndexOf("."));
 						foundLanguages.add(lang);
-						if (isLogDebugEnabled()) logDebug("Adding lang::" + lang + " from filename::" + jarEntryName + " in jar::" + jar.getName(),
-								null);
+						if (log.isDebug()) log.debug("Adding lang::" + lang + " from filename::" + jarEntryName + " in jar::" + jar.getName(), null);
 					}
 				}
 			}
@@ -1881,7 +1700,7 @@ public class I18nManager extends BasicManager {
 	 * @param toCopyI18nKeys
 	 */
 	public void copyLanguagesFromJar(File jarFile, Collection<String> toCopyI18nKeys) {
-		if (!I18nModule.isTransToolEnabled()) {
+		if (!i18nModule.isTransToolEnabled()) {
 			throw new AssertException("Programming error - can only copy i18n files from a language pack to the source when in translation mode");
 		}
 		JarFile jar = null;
@@ -1896,9 +1715,9 @@ public class I18nManager extends BasicManager {
 					if (jarEntryName.endsWith(I18N_DIRNAME + "/" + I18nModule.LOCAL_STRINGS_FILE_PREFIX + i18nKey + I18nModule.LOCAL_STRINGS_FILE_POSTFIX)) {
 						File targetBaseDir;
 						if (i18nKey.equals("de") || i18nKey.equals("en")) {
-							targetBaseDir = I18nModule.getTransToolApplicationLanguagesSrcDir();
+							targetBaseDir = i18nModule.getTransToolApplicationLanguagesSrcDir();
 						} else {
-							targetBaseDir = I18nModule.getTransToolApplicationOptLanguagesSrcDir();
+							targetBaseDir = i18nModule.getTransToolApplicationOptLanguagesSrcDir();
 						}
 						// Copy file
 						File targetFile = new File(targetBaseDir, jarEntryName);
@@ -1948,18 +1767,18 @@ public class I18nManager extends BasicManager {
 		String relPath = "/" + bundleName + "/" + I18N_DIRNAME + "/" + fileName;
 		// Load file from path
 		File f = new File(sourceDir, relPath);
-		if (f.exists() || I18nModule.isTransToolEnabled()) { return f; }
+		if (f.exists() || i18nModule.isTransToolEnabled()) { return f; }
 		return f;
 	}
 
 	public boolean createNewLanguage(String localeKey, String languageInEnglish, String languageTranslated, String authors) {
-		if (!I18nModule.isTransToolEnabled()) { throw new AssertException(
+		if (!i18nModule.isTransToolEnabled()) { throw new AssertException(
 				"Can not create a new language when the translation tool is not enabled and the transtool source pathes are not configured! Check your olat.properties files"); }
-		if (I18nModule.getAvailableLanguageKeys().contains(localeKey)) { return false; }
+		if (i18nModule.getAvailableLanguageKeys().contains(localeKey)) { return false; }
 		// Create new property file in the brasato bundle and re-initialize
 		// everything
-		String coreFallbackBundle = I18nModule.getApplicationFallbackBundle();
-		File transToolCoreLanguagesDir = I18nModule.getTransToolApplicationOptLanguagesSrcDir();
+		String coreFallbackBundle = i18nModule.getApplicationFallbackBundle();
+		File transToolCoreLanguagesDir = i18nModule.getTransToolApplicationOptLanguagesSrcDir();
 		String i18nDirRelPath = "/" + coreFallbackBundle.replace(".", "/") + "/" + I18nManager.I18N_DIRNAME;
 		File transToolCoreLanguagesDir_I18n = new File(transToolCoreLanguagesDir, i18nDirRelPath);
 		File newPropertiesFile = new File(transToolCoreLanguagesDir_I18n, I18nModule.LOCAL_STRINGS_FILE_PREFIX + localeKey
@@ -1987,12 +1806,12 @@ public class I18nManager extends BasicManager {
 			newProperties.store(fileStream, null);
 			fileStream.flush();
 			// Now set new language as enabled to allow user to translate the language. 
-			Collection<String> enabledLangKeys = I18nModule.getEnabledLanguageKeys();
+			Collection<String> enabledLangKeys = i18nModule.getEnabledLanguageKeys();
 			enabledLangKeys.add(localeKey);
 			// Reinitialize languages with new language
-			I18nModule.reInitializeAndFlushCache();
+			i18nModule.reInitializeAndFlushCache();
 			// Now add new language as new language (will re-initialize everything a second time)
-			I18nModule.setEnabledLanguageKeys(enabledLangKeys);
+			i18nModule.setEnabledLanguageKeys(enabledLangKeys);
 			return true;
 			
 		} catch (FileNotFoundException e) {
@@ -2004,7 +1823,7 @@ public class I18nManager extends BasicManager {
 			try {
 				if (fileStream != null) fileStream.close();
 			} catch (IOException e) {
-				logError("Could not close stream after creating new language file::" + newPropertiesFile.getAbsolutePath(), e);
+				log.error("Could not close stream after creating new language file::" + newPropertiesFile.getAbsolutePath(), e);
 			}
 		}
 	}
@@ -2017,22 +1836,22 @@ public class I18nManager extends BasicManager {
 	 *        logging
 	 */
 	public void deleteLanguage(String deleteLangKey, boolean reallyDeleteIt) {
-		Locale deleteLoclae = I18nModule.getAllLocales().get(deleteLangKey);
+		Locale deleteLoclae = i18nModule.getAllLocales().get(deleteLangKey);
 		// copy bundles list to prevent concurrent modification exception
 		List<String> bundlesCopy = new ArrayList<String>();
-		bundlesCopy.addAll(I18nModule.getBundleNamesContainingI18nFiles());
+		bundlesCopy.addAll(i18nModule.getBundleNamesContainingI18nFiles());
 		for (String bundleName : bundlesCopy) {
 			if (reallyDeleteIt) {
 				deleteProperties(deleteLoclae, bundleName);
-				logDebug("Deleted bundle::" + bundleName + " and lang::" + deleteLangKey, null);
+				log.debug("Deleted bundle::" + bundleName + " and lang::" + deleteLangKey, null);
 			} else {
 				// just log
-				logInfo("Dry-run-delete of bundle::" + bundleName + " and lang::" + deleteLangKey, null);
+				log.info("Dry-run-delete of bundle::" + bundleName + " and lang::" + deleteLangKey, null);
 			}
 		}
 		// Now reinitialize everything
 		if (reallyDeleteIt) {
-			I18nModule.reInitializeAndFlushCache();
+			i18nModule.reInitializeAndFlushCache();
 		}
 	}
 
@@ -2065,7 +1884,7 @@ public class I18nManager extends BasicManager {
 			for (String langKey : languageKeys) {
 				Locale locale = getLocaleOrNull(langKey);
 				// Add all bundles in the current language
-				for (String bundleName : I18nModule.getBundleNamesContainingI18nFiles()) {
+				for (String bundleName : i18nModule.getBundleNamesContainingI18nFiles()) {
 					Properties propertyFile = getPropertiesWithoutResolvingRecursively(locale, bundleName);
 					String entryFileName = bundleName.replace(".", "/") + "/" + I18N_DIRNAME + "/" + buildI18nFilename(locale);
 					// Create jar entry for this path, name and last modified
@@ -2074,21 +1893,21 @@ public class I18nManager extends BasicManager {
 					// Write properties to jar file
 					out.putNextEntry(jarEntry);
 					propertyFile.store(out, null);
-					if (isLogDebugEnabled()) {
-						logDebug("Adding file::" + entryFileName + " + to jar", null);
+					if (log.isDebug()) {
+						log.debug("Adding file::" + entryFileName + " + to jar", null);
 					}
 				}
 			}
-			logDebug("Finished writing jar file::" + file.getAbsolutePath(), null);
+			log.debug("Finished writing jar file::" + file.getAbsolutePath(), null);
 		} catch (Exception e) {
-			logError("Could not write jar file", e);
+			log.error("Could not write jar file", e);
 			return null;
 		} finally {
 			try {
 				out.close();
 				stream.close();
 			} catch (IOException e) {
-				logError("Could not close stream of jar file", e);
+				log.error("Could not close stream of jar file", e);
 				return null;
 			}
 		}
@@ -2099,12 +1918,6 @@ public class I18nManager extends BasicManager {
 	 * Private helper methods
 	 *************************/
 
-	/**
-	 * [used by spring]
-	 */
-	private I18nManager() {
-		INSTANCE = this;
-	}
 
 	/**
 	 * Helper method to create a key that uniquely identifies a property file
@@ -2119,7 +1932,7 @@ public class I18nManager extends BasicManager {
 		if (locale == null) {
 			return bundleName + ":" + METADATA_KEY;
 		} else {
-			return bundleName + ":" + getLocaleKey(locale);
+			return bundleName + ":" + i18nModule.getLocaleKey(locale);
 		}
 	}
 
diff --git a/src/main/java/org/olat/core/util/i18n/I18nModule.java b/src/main/java/org/olat/core/util/i18n/I18nModule.java
index e893d052069..3957c24f119 100644
--- a/src/main/java/org/olat/core/util/i18n/I18nModule.java
+++ b/src/main/java/org/olat/core/util/i18n/I18nModule.java
@@ -21,29 +21,40 @@
 package org.olat.core.util.i18n;
 
 import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
-import org.olat.core.configuration.AbstractOLATModule;
-import org.olat.core.configuration.Destroyable;
-import org.olat.core.configuration.PersistedProperties;
+import org.olat.core.configuration.AbstractSpringModule;
 import org.olat.core.gui.control.Event;
 import org.olat.core.helpers.Settings;
 import org.olat.core.id.OLATResourceable;
 import org.olat.core.logging.OLATRuntimeException;
 import org.olat.core.logging.OLog;
+import org.olat.core.logging.StartupException;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.ArrayHelper;
+import org.olat.core.util.FileUtils;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.WebappHelper;
 import org.olat.core.util.coordinate.CoordinatorManager;
 import org.olat.core.util.resource.OresHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.stereotype.Service;
 
 /**
  * <h3>Description:</h3> The I18nModule initializes the localization
@@ -54,8 +65,8 @@ import org.olat.core.util.resource.OresHelper;
  * 
  * @author Florian Gnaegi, frentix GmbH, http://www.frentix.com
  */
-
-public class I18nModule extends AbstractOLATModule implements Destroyable {
+@Service("i18nModule")
+public class I18nModule extends AbstractSpringModule {
 	
 	private static final OLog log = Tracing.createLoggerFor(I18nModule.class);
 	
@@ -81,71 +92,75 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	private static final String CONFIG_LANGUAGES_ENABLED = "enabledLanguages";
 	private static final String CONFIG_LANGUAGES_ENABLED_ALL = "all";
 	private static final String CONFIG_DEFAULT_LANG = "defaultLanguage";
-	private static final String CONFIG_FALLBACK_LANG = "fallbackLanguage";
-	private static final String CONFIG_LANGUAGES_REFERENCES = "transToolReferenceLanguages";
-	private static final String CONFIG_OVERLAY = "overlayName";
-	private static final String CONFIG_OVERLAY_ENABLED = "overlayEnabled";
-	private static final String CONFIG_CACHING_ENABLED = "cachingEnabled";
-	private static final String CONFIG_LANGUAGE_LIST_ENABLED = "dropDownListEnabled";
-	private static final String CONFIG_APPLICATION_FALLBACK_BUNDLE = "applicationFallbackBundle";
-	private static final String CONFIG_CORE_FALLBACK_BUNDLE = "coreFallbackBundle";
-	private static final String CONFIG_TRANS_TOOL_ENABLED = "transToolEnabled";
-	private static final String CONFIG_TRANS_TOOL_APPLICATION_SRC_PATH = "transToolApplicationSrcPath";
-	private static final String CONFIG_TRANS_TOOL_APPLICATION_OPT_SRC_PATH = "transToolApplicationOptSrcPath";
+	
+	@Value("${enabledLanguages}")
+	private String enabledLanguages;
+	@Value("${defaultlang:en}")
+	private String defaultLanguage;
+	@Value("${fallbacklang:en}")
+	private String fallbackLanguage;
 
 	// General configuration
-	private static String overlayName;
-	private static boolean overlayEnabled;
-	private static boolean cachingEnabled;
-	private static boolean languageDropDownListEnabled;
+	private final String overlayName = "customizing";
+	private final boolean overlayEnabled = true;
+
+	@Value("${localization.cache:true}")
+	private boolean cachingEnabled;
+	private boolean languageDropDownListEnabled = true;
 	// Lists of the available and enabled languages and locales
-	private static final Set<String> availableLanguages = new HashSet<String>();
-	private static final Set<String> translatableLanguages = new HashSet<String>();
-	private static final Map<String, File> translatableLangAppBaseDirLookup = new HashMap<String, File>();
+	private final Set<String> availableLanguages = new HashSet<>();
+	private final Set<String> translatableLanguages = new HashSet<>();
+	private final Map<String, File> translatableLangAppBaseDirLookup = new HashMap<>();
 	// keys: lang string, values: locale
-	private static final Map<String, Locale> allLocales = new HashMap<String, Locale>();
+	private static final Map<String, Locale> allLocales = new HashMap<>();
 	// keys: orig Locale, values: overlay Locale
-	private static final Map<Locale, Locale> overlayLocales = new HashMap<Locale, Locale>();
-	private static final Set<String> overlayLanguagesKeys = new HashSet<String>();
-	private static final Set<String> enabledLanguagesKeys = new HashSet<String>();
+	private final Map<Locale, Locale> overlayLocales = new HashMap<>();
+	private final Set<String> overlayLanguagesKeys = new HashSet<>();
+	private final Set<String> enabledLanguagesKeys = new HashSet<>();
 	// The default locale (used on loginscreen and as first fallback) and the
 	// fallback (used as second fallback)
 	private static Locale defaultLocale;
-	private static Locale fallbackLocale;
+	private Locale fallbackLocale;
 	// The available bundles
-	private static List<String> bundleNames = null; // sorted alphabetically
-	private static String coreFallbackBundle = null;
-	private static String applicationFallbackBundle = null;
+	private List<String> bundleNames; // sorted alphabetically
+	
+	private final String coreFallbackBundle = "org.olat.core";
+	private final String applicationFallbackBundle = "org.olat";
+
 	// Translation tool related configuration
-	private static final List<String> transToolReferenceLanguages = new ArrayList<String>();
-	private static File transToolApplicationLanguagesDir = null;
-	private static File transToolApplicationOptLanguagesSrcDir = null;
-	private static boolean transToolEnabled = false;
+	private final List<String> transToolReferenceLanguages = new ArrayList<>();
+	
+    @Value("${i18n.application.src.dir}")
+	private String transToolApplicationSrcPath;
+	private File transToolApplicationLanguagesDir;
+	@Value("${i18n.application.opt.src.dir}")
+	private String transToolApplicationOptSrcPath;
+	private File transToolApplicationOptLanguagesSrcDir;
+	@Value("${is.translation.server:disabled}")
+	private String transToolEnabled;
+	private final String referenceLanguages = "en,de";
+
+	private final ConcurrentMap<Locale,String> localeToLocaleKey = new ConcurrentHashMap<>();
+	
 	// When running on a cluster, we need an event when flushing the i18n cache to do this on all machines
 	private static OLATResourceable I18N_CACHE_FLUSHED_EVENT_CHANNEL;
 
 	// Reference to instance for static methods
-	private static I18nModule INSTANCE;
-	private CoordinatorManager coordinatorManager;
+	private final CoordinatorManager coordinatorManager;
 
-	/**
-	 * [spring]
-	 */
-	private I18nModule(CoordinatorManager coordinatorManager) {
-		super();
+	@Autowired
+	public I18nModule(CoordinatorManager coordinatorManager, WebappHelper webappHelper) {
+		super(coordinatorManager);
+		assert webappHelper != null;
 		this.coordinatorManager = coordinatorManager;
-		//if (INSTANCE != null && !Settings.isJUnitTest()) { throw new OLATRuntimeException("Tried to construct I18nModule, but module was already loaded!", null); }
-		INSTANCE = this;
 	}
 
 	@Override
 	protected void initDefaultProperties() {
 		// First read default configuration from the module config and then set
 		// is as default in the properties
-		String defaultLanguageKey = getStringConfigParameter(CONFIG_DEFAULT_LANG, "en", false);
-		setStringPropertyDefault(CONFIG_DEFAULT_LANG, defaultLanguageKey);
-		String enabledLanguagesConfig = getStringConfigParameter(CONFIG_LANGUAGES_ENABLED, CONFIG_LANGUAGES_ENABLED_ALL, false);
-		setStringPropertyDefault(CONFIG_LANGUAGES_ENABLED, enabledLanguagesConfig);
+		setStringPropertyDefault(CONFIG_DEFAULT_LANG, defaultLanguage);
+		setStringPropertyDefault(CONFIG_LANGUAGES_ENABLED, enabledLanguages);
 	}
 
 	@Override
@@ -185,8 +200,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 		// can't be changed at runtime and are project specific
 
 		// Set configured reference languages
-		String referenceLanguagesConfig = getStringConfigParameter(CONFIG_LANGUAGES_REFERENCES, "en", false);
-		String[] referenceAndFallbackKeys = referenceLanguagesConfig.split(",");
+		String[] referenceAndFallbackKeys = referenceLanguages.split(",");
 		// remove whitespace and check for douplicates
 		for (int i = 0; i < referenceAndFallbackKeys.length; i++) {
 			String langKey = referenceAndFallbackKeys[i];
@@ -194,61 +208,39 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 			transToolReferenceLanguages.add(langKey);
 		}
 
-		// Language overlay: used to override a language with some custom wording
-		overlayName = getStringConfigParameter(CONFIG_OVERLAY, "customizing", false);
-		overlayEnabled = getBooleanConfigParameter(CONFIG_OVERLAY_ENABLED, true);
-
 		// Set caching configuration of local strings
-		cachingEnabled = getBooleanConfigParameter(CONFIG_CACHING_ENABLED, true);
-		logInfo("Localization caching set to: " + cachingEnabled, null);
+		log.info("Localization caching set to: " + cachingEnabled, null);
 
 		// Set how the list of available availableLanguages will be shown
 		// (drop-down[true] or in one line[false])
-		languageDropDownListEnabled = getBooleanConfigParameter(CONFIG_LANGUAGE_LIST_ENABLED, true);
-		logInfo("Configuring 'dropDownListEnabled = " + languageDropDownListEnabled + "'", null);
+		log.info("Configuring 'dropDownListEnabled = " + languageDropDownListEnabled + "'", null);
 
 		// Set additional source path to load languages from and to store
 		// languages when using the translation tool. Init the values even when transtool is not configured for development mode		
-		String appSrc = getStringConfigParameter(CONFIG_TRANS_TOOL_APPLICATION_SRC_PATH, "", false);
-		if (StringHelper.containsNonWhitespace(appSrc)) {
-			appSrc = appSrc.trim();
-			transToolApplicationLanguagesDir = new File(appSrc);
+		if (StringHelper.containsNonWhitespace(transToolApplicationSrcPath)) {
+			transToolApplicationSrcPath = transToolApplicationSrcPath.trim();
+			transToolApplicationLanguagesDir = new File(transToolApplicationSrcPath);
 		}
-		String optAppSrc = getStringConfigParameter(CONFIG_TRANS_TOOL_APPLICATION_OPT_SRC_PATH, "", false);
-		if (StringHelper.containsNonWhitespace(optAppSrc)) {
-			optAppSrc = optAppSrc.trim();
-			transToolApplicationOptLanguagesSrcDir = new File(optAppSrc);
+		if (StringHelper.containsNonWhitespace(transToolApplicationOptSrcPath)) {
+			transToolApplicationOptSrcPath = transToolApplicationOptSrcPath.trim();
+			transToolApplicationOptLanguagesSrcDir = new File(transToolApplicationOptSrcPath);
 		}
 		
 		// Enable or disable translation tool and i18n source directories
-		transToolEnabled = getBooleanConfigParameter(CONFIG_TRANS_TOOL_ENABLED, false);
-		if (transToolEnabled) {
-			//
+		boolean translationToolEnabled = "enabled".equals(transToolEnabled);
+		if (translationToolEnabled) {
 			if (transToolApplicationLanguagesDir != null && transToolApplicationOptLanguagesSrcDir != null) {
 				// Check if configuration is valid, otherwise disable translation server mode
 			} else {
 				// disable, pathes not configured properly
-				transToolEnabled = false;
-			}
-			// error handling, notify on console about disabled translation tool
-			if (!transToolEnabled) {
-				logWarn(
-						"Translation configuration enabled but invalid translation tool source path defined. Disabling translation tool. Fix your configuration in spring config of i18Module",
-						null);
-				logWarn(" transToolApplicationSrcPath::" + appSrc + " transToolApplicationI18nSrcPath::" + optAppSrc, null);
+				translationToolEnabled = false;
+				log.warn("Translation configuration enabled but invalid translation tool source path defined. Disabling translation tool. Fix your configuration in spring config of i18Module", null);
+				log.warn(" transToolApplicationSrcPath::" + transToolApplicationSrcPath + " transToolApplicationI18nSrcPath::" + transToolApplicationOptSrcPath, null);
 			}
 		}
 
-		I18nManager i18nMgr = I18nManager.getInstance();
-		i18nMgr.setCachingEnabled(cachingEnabled);
-
 		// Get all bundles that contain i18n files
 		initBundleNames();
-		// Set the base bundles for olatcore and the application. When a key is
-		// not found, the manager looks it up in the application base and the in
-		// the core base bundle before it gives up
-		applicationFallbackBundle = getStringConfigParameter(CONFIG_APPLICATION_FALLBACK_BUNDLE, "org.olat", false);
-		coreFallbackBundle = getStringConfigParameter(CONFIG_CORE_FALLBACK_BUNDLE, "org.olat.core", false);
 
 		// Search for all available languages on the build path and initialize them
 		doInitAvailableLanguages();
@@ -257,15 +249,13 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 		// the persisted system configuration
 		doInitLanguageConfiguration();
 
-		logInfo("Configured i18nModule with default language::" + getDefaultLocale().toString() + " and the reference languages '"
-				+ referenceLanguagesConfig + "' and the following enabled languages: " + enabledLanguagesKeys.toString(), null);
+		log.info("Configured i18nModule with default language::" + getDefaultLocale().toString() + " and the reference languages '"
+				+ referenceLanguages + "' and the following enabled languages: " + enabledLanguagesKeys.toString(), null);
 	}
 
-	/**
-	 * 
-	 * @see org.olat.core.configuration.Destroyable#destroy()
-	 */
+	@Override
 	public void destroy() {
+		super.destroy();
 		// remove from event channel
 		if (I18N_CACHE_FLUSHED_EVENT_CHANNEL != null) {
 			coordinatorManager.getCoordinator().getEventBus().deregisterFor(this, I18N_CACHE_FLUSHED_EVENT_CHANNEL);
@@ -277,21 +267,20 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * Initialize the available languages and load all locales
 	 */
 	private void doInitAvailableLanguages() {
-		I18nManager i18nMgr = I18nManager.getInstance();
 		// Search all availableLanguages files that exist 
 
 		String i18nDirRelPath = File.separator + applicationFallbackBundle.replace(".", File.separator) + File.separator + I18nManager.I18N_DIRNAME;
 		if (transToolApplicationLanguagesDir != null) {
 			File coreSrcI18nDir = new File(transToolApplicationLanguagesDir, i18nDirRelPath);
 			if (coreSrcI18nDir.exists()) {
-				for (String languageCode : i18nMgr.searchForAvailableLanguages(transToolApplicationLanguagesDir)) {
+				for (String languageCode : searchForAvailableLanguages(transToolApplicationLanguagesDir)) {
 					if (availableLanguages.contains(languageCode)) {
 						String path = "";
 						if (transToolApplicationOptLanguagesSrcDir != null) path = transToolApplicationOptLanguagesSrcDir.getAbsolutePath();
-						logDebug("Skipping duplicate or previously loaded language::" + languageCode + " found in " +path , null);
+						log.debug("Skipping duplicate or previously loaded language::" + languageCode + " found in " +path , null);
 						continue;
 					}
-					logDebug("Detected translatable language " + languageCode + " in " + transToolApplicationLanguagesDir.getAbsolutePath(), null);
+					log.debug("Detected translatable language " + languageCode + " in " + transToolApplicationLanguagesDir.getAbsolutePath(), null);
 					availableLanguages.add(languageCode);
 					translatableLanguages.add(languageCode);
 					translatableLangAppBaseDirLookup.put(languageCode, transToolApplicationLanguagesDir);
@@ -300,12 +289,12 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 		}
 		// 2) Add languages from the translation tool source path
 		if (isTransToolEnabled()) {
-			for (String languageCode : i18nMgr.searchForAvailableLanguages(transToolApplicationOptLanguagesSrcDir)) {
+			for (String languageCode : searchForAvailableLanguages(transToolApplicationOptLanguagesSrcDir)) {
 				if (availableLanguages.contains(languageCode)) {
-					logDebug("Skipping duplicate or previously loaded language::" + languageCode + " found in " + transToolApplicationOptLanguagesSrcDir.getAbsolutePath(), null);
+					log.debug("Skipping duplicate or previously loaded language::" + languageCode + " found in " + transToolApplicationOptLanguagesSrcDir.getAbsolutePath(), null);
 					continue;
 				}
-				logDebug("Detected translatable language " + languageCode + " in " + transToolApplicationOptLanguagesSrcDir.getAbsolutePath(), null);
+				log.debug("Detected translatable language " + languageCode + " in " + transToolApplicationOptLanguagesSrcDir.getAbsolutePath(), null);
 				availableLanguages.add(languageCode);
 				translatableLanguages.add(languageCode);
 				translatableLangAppBaseDirLookup.put(languageCode, transToolApplicationOptLanguagesSrcDir);
@@ -316,12 +305,12 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 		if(StringHelper.containsNonWhitespace(folderRoot)) {
 			//started from WEB-INF/classes
 			File libDir = new File(WebappHelper.getBuildOutputFolderRoot());
-			for (String languageCode : i18nMgr.searchForAvailableLanguages(libDir)) {
+			for (String languageCode : searchForAvailableLanguages(libDir)) {
 				if (availableLanguages.contains(languageCode)) {
-					logDebug("Skipping duplicate or previously loaded  language::" + languageCode + " found in " + libDir.getAbsolutePath(), null);
+					log.debug("Skipping duplicate or previously loaded  language::" + languageCode + " found in " + libDir.getAbsolutePath(), null);
 					continue;
 				}
-				logDebug("Detected non-translatable language " + languageCode + " in " + libDir.getAbsolutePath(), null);
+				log.debug("Detected non-translatable language " + languageCode + " in " + libDir.getAbsolutePath(), null);
 				availableLanguages.add(languageCode);
 				// don't add to translatable languages nor to source lookup maps - those
 				// langs are read only
@@ -332,23 +321,23 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 			String[] enabledLanguages = enabledLanguagesConfig.split(",");
 			for (String languageCode : enabledLanguages) {
 				if (availableLanguages.contains(languageCode)) {
-					logWarn("Skipping duplicate or previously loaded  language::" + languageCode + " found in "
+					log.warn("Skipping duplicate or previously loaded  language::" + languageCode + " found in "
 							+ LANG_PACKS_DIRECTORY.getAbsolutePath(), null);
 					continue;
 				}
-				logDebug("Force non-translatable language " + languageCode + " defined from enabledLanguages.", null);
+				log.debug("Force non-translatable language " + languageCode + " defined from enabledLanguages.", null);
 				availableLanguages.add(languageCode);
 			}
 		}
 		
 		// 4) Add languages from the customizing lang packs
-		for (String languageCode : i18nMgr.searchForAvailableLanguages(LANG_PACKS_DIRECTORY)) {
+		for (String languageCode : searchForAvailableLanguages(LANG_PACKS_DIRECTORY)) {
 			if (availableLanguages.contains(languageCode)) {
-				logWarn("Skipping duplicate or previously loaded  language::" + languageCode + " found in "
+				log.warn("Skipping duplicate or previously loaded  language::" + languageCode + " found in "
 						+ LANG_PACKS_DIRECTORY.getAbsolutePath(), null);
 				continue;
 			}
-			logDebug("Detected non-translatable language " + languageCode + " in " + LANG_PACKS_DIRECTORY.getAbsolutePath(), null);
+			log.debug("Detected non-translatable language " + languageCode + " in " + LANG_PACKS_DIRECTORY.getAbsolutePath(), null);
 			availableLanguages.add(languageCode);
 			// don't add to translatable languages nor to source lookup maps - those
 			// langs are read only
@@ -363,9 +352,9 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 		//
 		// Build list of all locales and the overlay locales if available
 		for (String langKey : availableLanguages) {
-			Locale locale = i18nMgr.createLocale(langKey);
+			Locale locale = createLocale(langKey);
 			if (locale == null) {
-				logError("Could not create locale for lang::" + langKey + ", skipping language and remove it from list of available languages",
+				log.error("Could not create locale for lang::" + langKey + ", skipping language and remove it from list of available languages",
 						null);
 				toRemoveLangs.add(langKey);
 				continue;
@@ -377,12 +366,12 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 			//
 			// Add overlay
 			if (isOverlayEnabled()) {
-				Locale overlayLocale = i18nMgr.createOverlay(locale);
+				Locale overlayLocale = createOverlay(locale);
 				// Calculate the overlay key as used as reference. Note, this is not the
 				// same as overlayLocale.toString(), this would add '_' for each element
-				String overlayKey = i18nMgr.getLocaleKey(overlayLocale);
+				String overlayKey = getLocaleKey(overlayLocale);
 				if (overlayLocale == null) {
-					logError("Could not create overlay locale for lang::" + langKey + " (" + overlayKey + "), skipping language", null);
+					log.error("Could not create overlay locale for lang::" + langKey + " (" + overlayKey + "), skipping language", null);
 					continue;
 				}
 				// Don't add same overlay twice
@@ -402,38 +391,180 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 			translatableLangAppBaseDirLookup.remove(langKey);
 		}
 		// Set fallback locale from configuration
-		String fallbackLangKey = getStringConfigParameter(CONFIG_FALLBACK_LANG, Locale.ENGLISH.toString(), false);
 		// fallbackLangKey can't be null because EN is guaranteed to be available,
 		// see above
-		fallbackLocale = allLocales.get(fallbackLangKey);
+		fallbackLocale = allLocales.get(fallbackLanguage);
 
 		// Check if translation tool reference languages are available
 		if (isTransToolEnabled() && transToolReferenceLanguages.size() == 0) {
-			logError("Did not find the fallback language configuration in the configuration, using language::en instead", null);
+			log.error("Did not find the fallback language configuration in the configuration, using language::en instead", null);
 		} else {
 			for (String langKey : transToolReferenceLanguages) {
 				if (!allLocales.containsKey(langKey)) {
-					logError("The configured fallback language::" + langKey + " does not exist. Using language::en instead", null);
+					log.error("The configured fallback language::" + langKey + " does not exist. Using language::en instead", null);
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Search for available languages in the given directory. The translation
+	 * files must start with 'LocalStrings_' and end with '.properties'.
+	 * Everything in between is considered a language key.
+	 * <p>
+	 * If the directory contains jar files, those files are opened and searched
+	 * for languages files as well. In this case, the algorythm only looks for
+	 * translation files that are in the org/olat/core/_i18n package
+	 * 
+	 * @param i18nDir
+	 * @return set of language keys the system will find translations for
+	 */
+	Set<String> searchForAvailableLanguages(File i18nDir) {
+		Set<String> foundLanguages = new TreeSet<String>();
+		i18nDir = new File(i18nDir.getAbsolutePath()+"/org/olat/_i18n");
+		if (i18nDir.exists()) {
+			// First check for locale files
+			String[] langFiles = i18nDir.list(i18nFileFilter);
+			for (String langFileName : langFiles) {
+				String lang = langFileName.substring(I18nModule.LOCAL_STRINGS_FILE_PREFIX.length(), langFileName.lastIndexOf("."));
+				foundLanguages.add(lang);
+				log.debug("Adding lang::" + lang + " from filename::" + langFileName + " from dir::" + i18nDir.getAbsolutePath(), null);
+			}
+		}
+		return foundLanguages;
+	}
+	
+	/**
+	 * Create a local that represents the overlay locale for the given locale
+	 * 
+	 * @param locale The original locale
+	 * @return The overlay locale
+	 */
+	Locale createOverlay(Locale locale) {
+		String lang = locale.getLanguage();
+		String country = (locale.getCountry() == null ? "" : locale.getCountry());
+		String variant = createOverlayKeyForLanguage(locale.getVariant() == null ? "" : locale.getVariant());
+		Locale overlay = new Locale(lang, country, variant);
+		return overlay;
+	}
+	
+	/**
+	 * Add the overlay postfix to the given language key
+	 * @param langKey
+	 * @return
+	 */
+	String createOverlayKeyForLanguage(String langKey) {
+		return langKey + "__" + getOverlayName();
+	}
+	
+	/**
+	 * Helper method to create a locale from a given locale key ('de', 'de_CH',
+	 * 'de_CH_ZH')
+	 * 
+	 * @param localeKey
+	 * @return the locale or NULL if no locale could be generated from this string
+	 */
+	Locale createLocale(String localeKey) {
+		Locale aloc = null;
+		// de
+		// de_CH
+		// de_CH_zueri
+		String[] parts = localeKey.split("_");
+		switch (parts.length) {
+			case 1:
+				aloc = new Locale(parts[0]);
+				break;
+			case 2:
+				aloc = new Locale(parts[0], parts[1]);
+				break;
+			case 3:
+				String lastPart = parts[2];
+				// Add all remaining parts to variant, variant can contain
+				// underscores according to Locale spec
+				for (int i = 3; i < parts.length; i++) {
+					String part = parts[i];
+					lastPart = lastPart + "_" + part;
+				}
+				aloc = new Locale(parts[0], parts[1], lastPart);
+				break;
+			default:
+				return null;
+		}
+		// Test if the locale has been constructed correctly. E.g. when the
+		// language part is not existing in the ISO chart, the locale can
+		// convert to something else.
+		// E.g. he_HE_HE will convert automatically to iw_HE_HE
+		if (aloc.toString().equals(localeKey)) {
+			return aloc;
+		} else {
+			return null;
+		}
+	}
+	
+	/**
+	 * Calculate the locale key that identifies the given locale. Adds support for
+	 * the overlay mechanism.
+	 * 
+	 * @param locale
+	 * @return
+	 */
+	public String getLocaleKey(Locale locale) {
+		String key = localeToLocaleKey.get(locale);
+		if(key == null) {
+			String langKey = locale.getLanguage();
+			String country = locale.getCountry();
+			// Only add country when available - in case of an overlay country is
+			// set to
+			// an empty value
+			if (StringHelper.containsNonWhitespace(country)) {
+				langKey = langKey + "_" + country;
+			}
+			String variant = locale.getVariant();
+			// Only add the _ separator if the variant contains something in
+			// addition to
+			// the overlay, otherways use the __ only
+			if (StringHelper.containsNonWhitespace(variant)) {
+				if (variant.startsWith("__" + getOverlayName())) {
+					langKey += variant;
+				} else {
+					langKey = langKey + "_" + variant;
 				}
 			}
+			
+			key = localeToLocaleKey.putIfAbsent(locale, langKey);
+			if(key == null) {
+				key = langKey;
+			}
+			
 		}
+		return key;
 	}
+	
+	private static FilenameFilter i18nFileFilter = new FilenameFilter() {
+		@Override
+		public boolean accept(File dir, String name) {
+			// don't add overlayLocales as selectable availableLanguages
+			// (LocaleStrings_de__VENDOR.properties)
+			if (name.startsWith(I18nModule.LOCAL_STRINGS_FILE_PREFIX) && name.indexOf("_") != 0 && name.endsWith(I18nModule.LOCAL_STRINGS_FILE_POSTFIX)) { return true; }
+			return false;
+		}
+	};
 
 	private void doInitLanguageConfiguration() {
 		// Set the default language
 		String defaultLanguageKey = getStringPropertyValue(CONFIG_DEFAULT_LANG, false);
 		Locale newDefaultLocale = allLocales.get(defaultLanguageKey);
 		if (newDefaultLocale == null) {
-			logError("Could not set default locale to value::" + defaultLanguageKey + " - no such language found. Using fallback locale instead",
+			log.error("Could not set default locale to value::" + defaultLanguageKey + " - no such language found. Using fallback locale instead",
 					null);
 			newDefaultLocale = allLocales.get(transToolReferenceLanguages.get(0));
 		} else if (!availableLanguages.contains(newDefaultLocale.toString())) {
-			logError("Did not find the default language::" + newDefaultLocale.toString()
+			log.error("Did not find the default language::" + newDefaultLocale.toString()
 					+ " in the available availableLanguages files! Using fallback locale instead", null);
 			newDefaultLocale = allLocales.get(transToolReferenceLanguages.get(0));
 		}
 		defaultLocale = newDefaultLocale;
-		logInfo("Setting default locale::" + newDefaultLocale.toString(), null);
+		log.info("Setting default locale::" + newDefaultLocale.toString(), null);
 
 		// Enabling configured languages (a subset of the available languages)
 		String[] enabledLanguages;
@@ -450,12 +581,12 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 				enabledLanguagesKeys.add(langKey);
 			} // else skip this entry
 		}
-		logInfo("Enabling languages::" + enabledLanguagesConfig, null);
+		log.info("Enabling languages::" + enabledLanguagesConfig, null);
 		// Make sure that the configured default language is enabled
 		if (!enabledLanguagesKeys.contains(getDefaultLocale().toString())) {
 			String defLang = getDefaultLocale().toString();
 			enabledLanguagesKeys.add(defLang);
-			logWarn("The configured default language::" + defLang + " is not in the list of enabled languages. Enabling language::" + defLang,
+			log.warn("The configured default language::" + defLang + " is not in the list of enabled languages. Enabling language::" + defLang,
 					null);
 		}
 	}
@@ -476,11 +607,11 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * 
 	 * @param newDefaultLocale
 	 */
-	public static void setDefaultLocale(Locale newDefaultLocale) {
+	public void setDefaultLocale(Locale newDefaultLocale) {
 		if (defaultLocale == null || !defaultLocale.toString().equals(newDefaultLocale.toString())) {
 			// Just set the string property here. This will fire an event and
 			// call the method initFromChangedProperties()
-			INSTANCE.setStringProperty(CONFIG_DEFAULT_LANG, newDefaultLocale.toString(), true);
+			setStringProperty(CONFIG_DEFAULT_LANG, newDefaultLocale.toString(), true);
 		}
 	}
 
@@ -488,7 +619,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * @return The locale that is used when a string is not found in any other
 	 *         locale
 	 */
-	public static Locale getFallbackLocale() {
+	public Locale getFallbackLocale() {
 		return fallbackLocale;
 	}
 
@@ -499,7 +630,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	/**
 	 * @return true: caching is enabled; false: caching is disabled
 	 */
-	static boolean isCachingEnabled() {
+	public boolean isCachingEnabled() {
 		return cachingEnabled;
 	}
 
@@ -509,7 +640,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 *         the enabled languages to get the list of languages that are enabled
 	 *         to be used
 	 */
-	public static Set<String> getAvailableLanguageKeys() {
+	public Set<String> getAvailableLanguageKeys() {
 		return availableLanguages;
 	}
 
@@ -518,7 +649,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 *         tool. Theses are the languages that are available in the source
 	 *         form. Languages embedded in jars can't be edited.
 	 */
-	public static Set<String> getTranslatableLanguageKeys() {
+	public Set<String> getTranslatableLanguageKeys() {
 		return translatableLanguages;
 	}
 
@@ -526,7 +657,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * @return the map (with dummy value) of all languages including
 	 *         overlayLocales (as a String)
 	 */
-	public static Map<String, Locale> getAllLocales() {
+	public Map<String, Locale> getAllLocales() {
 		return allLocales;
 	}
 
@@ -534,7 +665,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * @return The lookup map of the overlay locales. Key: the locale; value: the
 	 *         corresponding overlay
 	 */
-	public static Map<Locale, Locale> getOverlayLocales() {
+	public Map<Locale, Locale> getOverlayLocales() {
 		return overlayLocales;
 	}
 
@@ -543,7 +674,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 *         de_CH, en, ...). those are the languages which can be chosen by the
 	 *         user
 	 */
-	public static Collection<String> getEnabledLanguageKeys() {
+	public Collection<String> getEnabledLanguageKeys() {
 		synchronized (enabledLanguagesKeys) {
 			return new HashSet<String>(enabledLanguagesKeys);
 		}
@@ -552,8 +683,8 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	/**
 	 * @return as keys: a List of Strings with the supported languages overlay keys
 	 */
-	public static Set<String> getOverlayLanguageKeys() {
-			return overlayLanguagesKeys;
+	public Set<String> getOverlayLanguageKeys() {
+		return overlayLanguagesKeys;
 	}
 
 	
@@ -563,7 +694,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * 
 	 * @param newEnabledLangKeys
 	 */
-	public static void setEnabledLanguageKeys(Collection<String> newEnabledLangKeys) {
+	public void setEnabledLanguageKeys(Collection<String> newEnabledLangKeys) {
 		if (!newEnabledLangKeys.equals(enabledLanguagesKeys)) {
 			String newEnabledConfig = "";
 			for (String enabledKey : newEnabledLangKeys) {
@@ -576,7 +707,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 
 			// Just set the string property here. This will fire an event and
 			// call the method initFromChangedProperties()
-			INSTANCE.setStringProperty(CONFIG_LANGUAGES_ENABLED, newEnabledConfig.toString(), true);
+			setStringProperty(CONFIG_LANGUAGES_ENABLED, newEnabledConfig.toString(), true);
 			// No need to reinitialize i18n Module, setting the new property will already do this
 		}
 	}
@@ -584,14 +715,14 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	/**
 	 * @return A list of language keys that are reference and fallback languages
 	 */
-	public static List<String> getTransToolReferenceLanguages() {
+	public List<String> getTransToolReferenceLanguages() {
 		return transToolReferenceLanguages;
 	}
 
 	/**
 	 * @return All bundles that contain a _i18n directory with translation files
 	 */
-	public static List<String> getBundleNamesContainingI18nFiles() {
+	public List<String> getBundleNamesContainingI18nFiles() {
 		return bundleNames;
 	}
 
@@ -599,7 +730,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * @return The bundle name that contains the commonly used translations from
 	 *         the olatcore framework
 	 */
-	public static String getCoreFallbackBundle() {
+	public String getCoreFallbackBundle() {
 		return coreFallbackBundle;
 	}
 
@@ -607,7 +738,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * @return The bundle name that contains the commonly used translations from
 	 *         the application
 	 */
-	public static String getApplicationFallbackBundle() {
+	public String getApplicationFallbackBundle() {
 		return applicationFallbackBundle;
 	}
 
@@ -617,7 +748,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * 
 	 * @return true: enabled; false: disabled
 	 */
-	public static boolean isOverlayEnabled() {
+	public boolean isOverlayEnabled() {
 		return (overlayEnabled && StringHelper.containsNonWhitespace(overlayName));
 	}
 
@@ -627,7 +758,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * 
 	 * @return name of the overlay
 	 */
-	public static String getOverlayName() {
+	public String getOverlayName() {
 		if (isOverlayEnabled()) return overlayName;
 		else return null;
 	}
@@ -636,17 +767,61 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * @return true: enable the translation tool; false: disable the translation
 	 *         tool
 	 */
-	public static boolean isTransToolEnabled() {
-		return transToolEnabled;
+	public boolean isTransToolEnabled() {
+		return "enabled".equals(transToolEnabled);
 	}
 
 	/**
 	 * search for bundles that contain i18n files. Searches in the org.olat.core
 	 * package
 	 */
-	static void initBundleNames() {
-		I18nManager i18nMgr = I18nManager.getInstance();
-		bundleNames = i18nMgr.searchForBundleNamesContainingI18nFiles();
+	void initBundleNames() {
+		bundleNames = searchForBundleNamesContainingI18nFiles();
+	}
+	
+	/**
+	 * Search in all packages on the source patch for packages that contain an
+	 * _i18n directory that can be used to store olatcore localization files
+	 * 
+	 * @return set of bundles that contain olatcore i18n compatible localization
+	 *         files
+	 */
+	List<String> searchForBundleNamesContainingI18nFiles() {
+		List<String> foundBundles;
+		// 1) First search on normal source path of application
+		String srcPath = null; 
+		File applicationDir = getTransToolApplicationLanguagesSrcDir();
+		if (applicationDir != null) {
+			srcPath = applicationDir.getAbsolutePath();
+		} else {
+			// Fall back to compiled classes
+			srcPath = WebappHelper.getBuildOutputFolderRoot();
+		}
+		if(StringHelper.containsNonWhitespace(srcPath)) {
+			I18nDirectoriesVisitor srcVisitor = new I18nDirectoriesVisitor(srcPath, getTransToolReferenceLanguages());
+			FileUtils.visitRecursively(new File(srcPath), srcVisitor);
+			foundBundles = srcVisitor.getBundlesContainingI18nFiles();
+			// 3) For jUnit tests, add also the I18n test dir
+			if (Settings.isJUnitTest()) {
+				Resource testres = new ClassPathResource("olat.local.properties");
+				String jUnitSrcPath = null;
+				try {
+					jUnitSrcPath = testres.getFile().getAbsolutePath();
+				} catch (IOException e) {
+					throw new StartupException("Could not find classpath resource for: test-classes/olat.local.property ", e);
+	  			}
+	
+	
+				I18nDirectoriesVisitor juniSrcVisitor = new I18nDirectoriesVisitor(jUnitSrcPath, getTransToolReferenceLanguages());
+				FileUtils.visitRecursively(new File(jUnitSrcPath), juniSrcVisitor);
+				foundBundles.addAll(juniSrcVisitor.getBundlesContainingI18nFiles());
+			}
+			// Sort alphabetically
+			Collections.sort(foundBundles);
+		} else {
+			foundBundles = new ArrayList<String>();
+		}
+		return foundBundles;
 	}
 
 	/**
@@ -657,7 +832,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * @param bundleName
 	 * @return The file or null if the language is not read-write configured
 	 */
-	public static File getPropertyFilesBaseDir(Locale locale, String bundleName) {
+	public File getPropertyFilesBaseDir(Locale locale, String bundleName) {
 		// 1) Special case, junit test files are not in olat source path
 		// We don't want translator to translate those files!
 		if (Settings.isJUnitTest() && bundleName.startsWith("org.olat.core.util.i18n.junittestdata") ) {
@@ -670,21 +845,19 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 			return transToolApplicationLanguagesDir;
 		}
 		// 3) Locale files from core or application
-		String localeKey = I18nManager.getInstance().getLocaleKey(locale);
+		String localeKey = getLocaleKey(locale);
 		return translatableLangAppBaseDirLookup.get(localeKey);
 	}
 
 	/**
 	 * Reinitialize the entire i18n system
 	 */
-	public static void reInitializeAndFlushCache() {
-		synchronized (enabledLanguagesKeys) {
-			// Re-initialize all local caches
-			doReInitialize();
-			// Notify other nodes to reInitialize the caches as well
-			I18nReInitializeCachesEvent changedConfigEvent = new I18nReInitializeCachesEvent();
-			CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(changedConfigEvent, I18N_CACHE_FLUSHED_EVENT_CHANNEL);				
-		}
+	public void reInitializeAndFlushCache() {
+		// Re-initialize all local caches
+		doReInitialize();
+		// Notify other nodes to reInitialize the caches as well
+		I18nReInitializeCachesEvent changedConfigEvent = new I18nReInitializeCachesEvent();
+		CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(changedConfigEvent, I18N_CACHE_FLUSHED_EVENT_CHANNEL);				
 	}
 
 	/**
@@ -692,7 +865,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * is decoupled from the reInitialize() to prevent endless firing of events
 	 * in the cluster.
 	 */
-	private static void doReInitialize() {		
+	private void doReInitialize() {		
 		synchronized (enabledLanguagesKeys) {
 			// Clear everything
 			availableLanguages.clear();
@@ -705,13 +878,14 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 			transToolReferenceLanguages.clear();
 			I18nManager.getInstance().clearCaches();
 			// Now rebuild everything from scratch
-			INSTANCE.doInit();
+			doInit();
 		}
 	}
 
 	/**
 	 * @see org.olat.core.configuration.AbstractOLATModule#event(org.olat.core.gui.control.Event)
 	 */
+	@Override
 	public void event(Event event) {
 		// First delegate to AbstractOLATModule
 		super.event(event);
@@ -731,7 +905,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * 
 	 * @return
 	 */
-	public static File getTransToolApplicationLanguagesSrcDir() {
+	public File getTransToolApplicationLanguagesSrcDir() {
 		return transToolApplicationLanguagesDir;
 	}
 
@@ -741,13 +915,7 @@ public class I18nModule extends AbstractOLATModule implements Destroyable {
 	 * 
 	 * @return
 	 */
-	public static File getTransToolApplicationOptLanguagesSrcDir() {
+	public File getTransToolApplicationOptLanguagesSrcDir() {
 		return transToolApplicationOptLanguagesSrcDir;
 	}
-
-	@Override
-	public void setPersistedProperties(PersistedProperties persistedProperties) {
-		this.moduleConfigProperties = persistedProperties;
-	}
-
 }
diff --git a/src/main/java/org/olat/core/util/i18n/_spring/i18nCorecontext.xml b/src/main/java/org/olat/core/util/i18n/_spring/i18nCorecontext.xml
deleted file mode 100644
index 0083981366b..00000000000
--- a/src/main/java/org/olat/core/util/i18n/_spring/i18nCorecontext.xml
+++ /dev/null
@@ -1,117 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xmlns:context="http://www.springframework.org/schema/context" 
-	xsi:schemaLocation="
-  http://www.springframework.org/schema/beans 
-  http://www.springframework.org/schema/beans/spring-beans.xsd">
-
-<bean id="I18nManager" class="org.olat.core.util.i18n.I18nManager" />
-
-<bean id="i18nModule" class="org.olat.core.util.i18n.I18nModule" destroy-method="destroy" depends-on="I18nManager, org.olat.core.util.WebappHelper">
-	<constructor-arg ref="coordinatorManager" />
-      <property name="persistedProperties">
-		  <bean class="org.olat.core.configuration.PersistedProperties" scope="prototype" init-method="init" destroy-method="destroy">
-		    <constructor-arg index="0" ref="coordinatorManager"/>
-		    <constructor-arg index="1" ref="i18nModule" />
-		  </bean>
-	  </property>
-      
-</bean>
-                
-       <bean id="triggerI18nModuleInit" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
-        <property name="targetObject" ref="i18nModule" />
-        <property name="targetMethod" value="init" />
-        <property name="arguments">
-                    <value>
-	                      <!-- 
-			Default setting for enabled languages: comma separated list of lang keys. Set to 'all' to 
-			enable all languages that can be found in the source code 
-			Example:
-			<enabledLanguages>en,de,fr,it,es,da,cs,el,ru,pl,zh_CN,zh_TW,lt,fa,pt_PT,pt_BR,tr,hu,sq,in,ar,rm,af,iw,vi,mn</enabledLanguages>
-			or
-			<enabledLanguages>all</enabledLanguages>
-			NOTE: this default setting will be overridden by the values configured in 
-			olatdata/system/configuration/org.olat.core.util.i18n.I18nModule.properties
-		-->
-                         enabledLanguages=${enabledLanguages}
-                         <!-- 
-			Default setting for the system default locale to use: language of login page 
-			NOTE: this default setting will be overridden by the values configured in 
-			olatdata/system/configuration/org.olat.core.util.i18n.I18nModule.properties
-		-->
-                         defaultLanguage=${defaultlang}
-                         <!--
-			The language that is used as a fallback in case the system does not find a key in the 
-			users language nor in the default language. Note that in this language
-			all keys must exist! Since developers only add the 'de' and 'en' keys it is strongly recommended 
-			that you don't set it to any other value that this. If unsure, use the default 'de'.
-		-->	
-                         fallbackLanguage=${fallbacklang}
-                         <!-- 
-			The application fallback bundle contains the common words used everywhere in your web application. 
-			During translation, when a translation is not found, the system checks if the fallback bundle contains
-			the translation. Here you find things you often use in your application. 
-			If unsure, leave default value. 
-		-->
-                         applicationFallbackBundle=org.olat
-                         <!-- 
-			The olatcore fallback bundle contains the common words used everywhere in the core framework. 
-			During translation, when a translation is not found, the system checks if the fallback bundle contains
-			the translation. Here you find things like 'yes', 'no' etc. Normally you don't change this.			
-			In the fallback chain the system first checks for the application fallback and as last option it then 
-			checks for the olatcore fallback
-			If unsure, leave default value. 
-		-->
-                         coreFallbackBundle=org.olat.core
-                         <!-- 
-			Name of the overlay that should be used to customize the language. E.g. if your overlay 
-			files are labelled "de__customizing" you must set "customizing" here. The overlay properties files are
-			stored in olatdata/customizing/lang/overlay/*
-			If unsure, leave default value. 
-		--> 
-                         overlayName=customizing
-                         <!-- 
-			Enable or disable the customizing overlay feature. If set to true it is not possible to customize
-			the interface text elements. If unsure, set to true.
-		-->
-                         overlayEnabled=true
-                         <!-- 
-			Whether to cache i18n properties files (recommended in production). 
-			If unsure, set to true. 	
-		-->
-                         cachingEnabled=${localization.cache}
-                         <!-- 
-			Define language selection list style on login page. true=drop-box, false=in one line. 
-			If unsure, leave default value. 
-		-->
-                         dropDownListEnabled=true
-                         <!-- 
-			Enable the translation tool. This is only enabled on the official OLAT translation server
-			at translation.olat.org. If you want to setup your own translation server you must specify
-			the following path in order to work properly:
-			i18n.application.src.dir		: path to the source of your application code, typically olat3/webapp/WEB-INF/src
-			i18n.application.opt.src.dir	: path to the source of your application i18n files, typically olat3_i18n/src/main/java
-			i18n.core.src.dir				: path to the source of the framework core code, typically olatcore/src/main/java
-			i18n.core.opt.src.dir			: path to the source of the framework i18n files, typically olatcore_i18n/src/main/java
-			In most cases you can set this value to disabled and ignore the application and core src path. 
-			You can still use the translation tool to customize the languages using the overlay feature
-			If unsure, set to disabled in the olat.local.properties.
-			
-			Values are disabled / enabled, this is also used to enable the translation status job.
-			see your olat.properties or olat.local.properties for the value set.
-		-->
-                         transToolEnabled=${is.translation.server}
-                         transToolApplicationSrcPath=${i18n.application.src.dir}
-                         transToolApplicationOptSrcPath=${i18n.application.opt.src.dir}
-                         <!-- 
-			The languages that serve as a base in the translation tool. Note that in those languages 
-			all keys must exist! Since developers only add the 'de' and 'en' keys it is strongly recommended 
-			that you don't set it to any other value that this. If unsure, use the default 'en,de'.
-		-->
-                         transToolReferenceLanguages=de,en
-	                </value>
-                </property>
-</bean>
-
-</beans>
diff --git a/src/main/java/org/olat/core/util/i18n/devtools/TranslationDevController.java b/src/main/java/org/olat/core/util/i18n/devtools/TranslationDevController.java
index 80564f48230..311f951ec15 100644
--- a/src/main/java/org/olat/core/util/i18n/devtools/TranslationDevController.java
+++ b/src/main/java/org/olat/core/util/i18n/devtools/TranslationDevController.java
@@ -37,9 +37,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 
 public class TranslationDevController extends FormBasicController {
 
-	@Autowired
-	private TranslationDevManager translationDevManager;
-
 	private String[] values = { "" };
 	private String[] keys = { "on" };
 
@@ -93,6 +90,11 @@ public class TranslationDevController extends FormBasicController {
     private TextElement addKeyValue;
 	private TextElement addKeyKey;
 	private FormLink submitAdd;
+	
+	@Autowired
+	private I18nModule i18nModule;
+	@Autowired
+	private TranslationDevManager translationDevManager;
 
 	public TranslationDevController(UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl);
@@ -103,7 +105,7 @@ public class TranslationDevController extends FormBasicController {
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 
-		if(!I18nModule.isTransToolEnabled()){
+		if(!i18nModule.isTransToolEnabled()){
 			setFormWarning("devtools.warning");
 		}
 
diff --git a/src/main/java/org/olat/core/util/i18n/devtools/TranslationDevMainController.java b/src/main/java/org/olat/core/util/i18n/devtools/TranslationDevMainController.java
index b40197ca083..a97a91e1491 100644
--- a/src/main/java/org/olat/core/util/i18n/devtools/TranslationDevMainController.java
+++ b/src/main/java/org/olat/core/util/i18n/devtools/TranslationDevMainController.java
@@ -26,17 +26,17 @@ import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.MainLayoutBasicController;
 import org.olat.core.util.i18n.I18nModule;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
- * Description:<br>
- * TODO: rhaag Class Description for TranslationDevMainController
- * 
  * <P>
  * Initial Date:  23.09.2008 <br>
  * @author Roman Haag, frentix GmbH, roman.haag@frentix.com
  */
 public class TranslationDevMainController extends MainLayoutBasicController {
-	private final VelocityContainer vc;
+	
+	@Autowired
+	private I18nModule i18nModule;
 	
 	/**
 	 * @param ureq
@@ -44,18 +44,12 @@ public class TranslationDevMainController extends MainLayoutBasicController {
 	 */
 	public TranslationDevMainController(UserRequest ureq, WindowControl control) {
 		super(ureq, control);
-		vc = createVelocityContainer("translationdev");
-		String srcPath = I18nModule.getTransToolApplicationLanguagesSrcDir().getAbsolutePath();
+		VelocityContainer vc = createVelocityContainer("translationdev");
+		String srcPath = i18nModule.getTransToolApplicationLanguagesSrcDir().getAbsolutePath();
 		vc.contextPut("srcPath", srcPath);
-		//TODO RH: check for enabled debug-mode in order to prevent caching! 
-//		vc.contextPut("cachingDisabled", I18nModule.isCachingEnabled());
-		
-//		formFactory.addTextElement(name, maxLen, initialValue, i18nLabel, formItemContainer)
 		putInitialPanel(vc);
 	}
 
-	
-	
 	/**
 	 * @see org.olat.core.gui.control.DefaultController#doDispose()
 	 */
@@ -71,4 +65,4 @@ public class TranslationDevMainController extends MainLayoutBasicController {
 	protected void event(UserRequest ureq, Component source, Event event) {
 		//
 	}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/util/i18n/devtools/TranslationDevManager.java b/src/main/java/org/olat/core/util/i18n/devtools/TranslationDevManager.java
index 3776ef6f83e..14deaff880f 100644
--- a/src/main/java/org/olat/core/util/i18n/devtools/TranslationDevManager.java
+++ b/src/main/java/org/olat/core/util/i18n/devtools/TranslationDevManager.java
@@ -33,9 +33,9 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.Set;
-import java.util.Map.Entry;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -48,6 +48,8 @@ import org.olat.core.util.StringHelper;
 import org.olat.core.util.i18n.I18nItem;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
 
 
 /**
@@ -59,27 +61,20 @@ import org.olat.core.util.i18n.I18nModule;
  * 
  * @author Roman Haag, frentix GmbH, roman.haag@frentix.com
  */
+@Service("translationDevManager")
 public class TranslationDevManager extends BasicManager {
-
-	private static TranslationDevManager INSTANCE;
 	private static final OLog log = Tracing.createLoggerFor(TranslationDevManager.class);
-	I18nManager i18nMgr;
-	private StringBuffer logText = new StringBuffer();
-
-	/**
-	 * [spring]
-	 */
-	private TranslationDevManager(I18nManager i18nManager) {
-		this.i18nMgr = i18nManager;
-		INSTANCE = this;
-	}
 
-	public static TranslationDevManager getInstance() {
-		return INSTANCE;
-	}
+	private StringBuffer logText = new StringBuffer();
+	
+	@Autowired
+	private 	I18nManager i18nMgr;
+	@Autowired
+	private I18nModule i18nModule;
+	
 
 	protected Set<String> getAllLanguages() {
-		return I18nModule.getAvailableLanguageKeys();
+		return i18nModule.getAvailableLanguageKeys();
 	}
 
 	protected void renameKeyTask(String bundleName, String origKey, String targetKey) {
@@ -124,7 +119,7 @@ public class TranslationDevManager extends BasicManager {
 		int counter = 0;
 		Pattern resolvingKeyPattern = Pattern.compile("\\$\\{?("+originBundleName+")+:([\\w\\.\\-]*[\\w\\-])\\}?");
 		
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		Set<String> allLangs = getAllLanguages();
 		for (String langKey : allLangs) {
 	    Locale locale = i18nMgr.getLocaleOrNull(langKey);
@@ -163,7 +158,7 @@ public class TranslationDevManager extends BasicManager {
 							lastPos = matcher.end();
 							newValue.append(value.substring(lastPos));
 							log.info("Key:: " + key + " should get changed to value:: " + newValue.toString());
-							logText.append(i18nMgr.getPropertiesFile(locale, bundleName, I18nModule.getPropertyFilesBaseDir(locale, bundleName)) + 
+							logText.append(i18nMgr.getPropertiesFile(locale, bundleName, i18nModule.getPropertyFilesBaseDir(locale, bundleName)) + 
 									" update reference in lang::" + locale.getLanguage() + " bundle::" + bundleName + " key::" + key + " value::" + value + " \n\t to new value:: " + newValue.toString() + "\n");	
 							counter ++;
 //					changeValueForSingleKey(locale, bundleName, key, newValue.toString());	
@@ -194,7 +189,6 @@ public class TranslationDevManager extends BasicManager {
 		i18nMgr.saveOrUpdateProperties(tempProp, locale, bundleName);
 		
 		checkForEmptyPropertyAndDelete(locale, bundleName);
-		checkForEmptyBundleAndDelete(bundleName);
 	}
 
 	protected void addKey(Locale locale, String bundleName, String key, String value) {
@@ -210,12 +204,6 @@ public class TranslationDevManager extends BasicManager {
 		}
 	}
 
-	private void checkForEmptyBundleAndDelete(String bundleName) {
-	// if _i18n is empty:
-	// TODO: RH: remove dir, remove .cvs
-	// deletePackage(bundleName);
-	}
-
 	public void movePackageTask(String originBundleName, String targetBundleName) {
 		//remove package priority from metadata first
 		deleteKey(null, originBundleName, I18nManager.METADATA_BUNDLE_PRIORITY_KEY);
@@ -232,7 +220,7 @@ public class TranslationDevManager extends BasicManager {
 	}
 	
 	public void movePackageByMovingSingleKeysTask(String originBundleName, String targetBundleName) {
-		Properties properties = i18nMgr.getPropertiesWithoutResolvingRecursively(I18nModule.getFallbackLocale(), originBundleName);
+		Properties properties = i18nMgr.getPropertiesWithoutResolvingRecursively(i18nModule.getFallbackLocale(), originBundleName);
 		Set<Object> keys = properties.keySet();		
 		for (Object keyObj : keys) {
 			String key = (String) keyObj;
@@ -272,7 +260,7 @@ public class TranslationDevManager extends BasicManager {
 	public void renameLanguageTask(Locale sourceLocale, Locale targetLocale){
 	
 		//check if targetLocale exists already
-		Set<String> allLangKeys = I18nModule.getAvailableLanguageKeys();
+		Set<String> allLangKeys = i18nModule.getAvailableLanguageKeys();
 		if (allLangKeys.contains(targetLocale.getLanguage())){
 			log.error("Target Language " + targetLocale.getLanguage() + " already exists! ");
 		}
@@ -301,7 +289,7 @@ public class TranslationDevManager extends BasicManager {
 	 * @param reallyRemoveIt true: really remove it; false: dry run, only produce logging
 	 */
 	public void removeXKeysTask(boolean reallyRemoveIt){
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		Set<String> allLangs = getAllLanguages();
 		int counter = 0;
 		for (String langKey : allLangs) {
@@ -320,7 +308,7 @@ public class TranslationDevManager extends BasicManager {
 							}
 						}
 						log.info("XKEY detected in lang::" + locale.getLanguage() + " bundle::" + bundleName + " key::" + key);
-						File propertyFileDir = I18nModule.getPropertyFilesBaseDir(locale, bundleName);
+						File propertyFileDir = i18nModule.getPropertyFilesBaseDir(locale, bundleName);
 						if(propertyFileDir != null) {
 							File propertyFile = i18nMgr.getPropertiesFile(locale, bundleName, propertyFileDir);
 							logText.append(propertyFile + " XKEY detected in lang::" + locale.getLanguage() + " bundle::" + bundleName + " key::" + key + " value::" + value + "\n");		
@@ -339,7 +327,7 @@ public class TranslationDevManager extends BasicManager {
 	}
 
 	public void sortKeysTask(boolean reallySortIt){
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		Set<String> allLangs = getAllLanguages();
 		int counter = 0;
 		for (String langKey : allLangs) {
@@ -366,7 +354,7 @@ public class TranslationDevManager extends BasicManager {
 	 * @param reallyRemoveIt true: really remove it; false: dry run, only produce logging
 	 */
 	public void removeTodoKeysTask(boolean reallyRemoveIt) {
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		Set<String> allLangs = getAllLanguages();
 		int counter = 0;
 		String[] comparisonStrings = {"TODO"};
@@ -385,7 +373,7 @@ public class TranslationDevManager extends BasicManager {
 							if (value.length() > comparisonStrings[i].length()+1) {
 								log.warn("this is a TODO-Key WITH TEXT::" + value.substring(comparisonStrings[i].length()) + "::");
 							} else {
-								logText.append(i18nMgr.getPropertiesFile(locale, bundleName, I18nModule.getPropertyFilesBaseDir(locale, bundleName)) + 
+								logText.append(i18nMgr.getPropertiesFile(locale, bundleName, i18nModule.getPropertyFilesBaseDir(locale, bundleName)) + 
 										" TODO-Key detected in lang::" + locale.getLanguage() + " bundle::" + bundleName + " key::" + key + " value::" + value + "\n");
 								if (reallyRemoveIt) {
 									deleteKey(locale, bundleName, key);
@@ -405,7 +393,7 @@ public class TranslationDevManager extends BasicManager {
 	 * @param reallyRemoveIt true: really remove it; false: dry run, only produce logging
 	 */
 	public void removeEmptyKeysTask(boolean reallyRemoveIt) {
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		int counter = 0;
 		Set<String> allLangs = getAllLanguages();
 		for (String langKey : allLangs) {
@@ -418,7 +406,7 @@ public class TranslationDevManager extends BasicManager {
 					String value = properties.getProperty(key);
 					if (!StringHelper.containsNonWhitespace(value) ) {
 						log.info("empty Key detected in lang::" + locale.getLanguage() + " bundle::" + bundleName + " key::" + key + " value::" + value);
-						File propertyFileDir = I18nModule.getPropertyFilesBaseDir(locale, bundleName);
+						File propertyFileDir = i18nModule.getPropertyFilesBaseDir(locale, bundleName);
 						if(propertyFileDir != null) {
 							File propertyFile = i18nMgr.getPropertiesFile(locale, bundleName, propertyFileDir);
 							logText.append(propertyFile + " empty Key detected in lang" + locale.getLanguage() + " bundle::" + bundleName + " key::" + key + " value::" + value + "\n");						
@@ -447,7 +435,7 @@ public class TranslationDevManager extends BasicManager {
 		// first get all available keys from de and en language
 		Set<String> validCombinedKeys = new HashSet<String>();
 		//copy list to prevent concurrent modification exception
-		List<String> allBundles = new ArrayList<String>(I18nModule.getBundleNamesContainingI18nFiles());
+		List<String> allBundles = new ArrayList<String>(i18nModule.getBundleNamesContainingI18nFiles());
 		for (String bundleName : allBundles) {
 			for (String refLangKey : referenceLanguages) {
 				Properties properties = i18nMgr.getPropertiesWithoutResolvingRecursively(i18nMgr.getLocaleOrNull(refLangKey), bundleName);
@@ -520,7 +508,7 @@ public class TranslationDevManager extends BasicManager {
 	 * reallyCopy: set to true to create Props/keys in Head, false: only log them
 	 */
 	public void getLostTranslationsFromBranch(boolean reallyCopy, String[] referenceLanguages, String pathToOlatBranch, String pathToCoreBranch){
-		List<String> allBundles = new ArrayList<String>(I18nModule.getBundleNamesContainingI18nFiles());
+		List<String> allBundles = new ArrayList<String>(i18nModule.getBundleNamesContainingI18nFiles());
 		
 		Set<String> allLangs = getAllLanguages();
 		//loop over all langs
@@ -626,12 +614,12 @@ public class TranslationDevManager extends BasicManager {
 	 * false: dry run, only produce logging
 	 */
 	public void removeReferenceLanguageCopiesTask(boolean reallyRemoveIt){
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		// don't remove EN and DE here, this is a shared Map!!		
 		int counter = 0;
 		int aliasCounter = 0;
 		//prepare exclusion list
-		String exKeys = FileUtils.load(new File(I18nModule.getTransToolApplicationLanguagesSrcDir() + "/org/olat/core/util/i18n/devtools/exclusionKeys.txt"), "UTF-8");
+		String exKeys = FileUtils.load(new File(i18nModule.getTransToolApplicationLanguagesSrcDir() + "/org/olat/core/util/i18n/devtools/exclusionKeys.txt"), "UTF-8");
 		String[] exArray = exKeys.split("\n");
 		List<String> exList = new ArrayList<String>(Arrays.asList(exArray));
 
@@ -675,7 +663,7 @@ public class TranslationDevManager extends BasicManager {
 						}
 						if (readyToDelete) {
 							counter++;
-							logText.append(i18nMgr.getPropertiesFile(locale, bundleName, I18nModule.getPropertyFilesBaseDir(locale, bundleName)) + 
+							logText.append(i18nMgr.getPropertiesFile(locale, bundleName, i18nModule.getPropertyFilesBaseDir(locale, bundleName)) + 
 									" value of key found in reference -> remove lang::" + locale.getLanguage() + " bundle::" + bundleName + " key::" + key + " value::" + value + "\n");			
 						}
 					}
@@ -689,9 +677,9 @@ public class TranslationDevManager extends BasicManager {
 	
 	// do this only for reference language!
 	public List<I18nItem> getDouplicateKeys(){
-		Locale refLocale = I18nModule.getDefaultLocale();
+		Locale refLocale = i18nModule.getDefaultLocale();
 		List<I18nItem> doupList = new ArrayList<I18nItem>();
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		Map<String, String> tempKeyMap = new HashMap<String, String>();
 		
 		for (String bundleName : allBundles) {
@@ -716,9 +704,9 @@ public class TranslationDevManager extends BasicManager {
 	
 	//do this only for reference language!
 	public List<I18nItem> getDouplicateValues(){
-		Locale refLocale = I18nModule.getDefaultLocale();
+		Locale refLocale = i18nModule.getDefaultLocale();
 		List<I18nItem> doupList = new ArrayList<I18nItem>();
-		List<String> allBundles = I18nModule.getBundleNamesContainingI18nFiles();
+		List<String> allBundles = i18nModule.getBundleNamesContainingI18nFiles();
 		Map<String, String> tempKeyMap = new HashMap<String, String>();
 		
 		for (String bundleName : allBundles) {
@@ -755,10 +743,10 @@ public class TranslationDevManager extends BasicManager {
 	}
 
 	private File getBundlePath(String bundleName){
-		Locale locale = I18nModule.getAllLocales().get("de");
-		File baseDir = I18nModule.getPropertyFilesBaseDir(locale, bundleName);
+		Locale locale = i18nModule.getAllLocales().get("de");
+		File baseDir = i18nModule.getPropertyFilesBaseDir(locale, bundleName);
 		if (baseDir != null) {
-			File deFile = I18nManager.getInstance().getPropertiesFile(locale, bundleName, baseDir);
+			File deFile = i18nMgr.getPropertiesFile(locale, bundleName, baseDir);
 			return deFile.getParentFile();
 		}
 		return null;
@@ -800,43 +788,4 @@ public class TranslationDevManager extends BasicManager {
 			out.close();
 		}
 	}
-	
-	public void logToFile(String fname){
-//		FileUtils.save(new File("/Users/rhaag/Desktop/devtoolsoutput/"+fname+".txt"), logText.toString(), "UTF-8");
-//		logText = new StringBuffer();
-	}
-	
-	
-//		String srcPath;
-//		if (bundleName.startsWith("org.olat.core")) {
-//			srcPath = I18nModule.getTransToolCoreLanguagesSrcDir().getAbsolutPath();
-//			if (srcPath == null) {
-//				log.error("Can not add bundle priority to core while olatcore source path is not configured! Check olatcore.src in olat.properties");
-//				return;
-//			}			
-//		} else {
-//			srcPath = I18nModule.getTransToolApplicationLanguagesSrcDir().getAbsolutPath();
-//		}
-//		File baseDir = new File(srcPath + bundleName.replace(".", "/"));
-//		if (baseDir.exists()) {
-//			addMissingBundlePriority(baseDir, priority);			
-//		} else {
-//			log.error("Can not add priority to bundle::" + bundleName + " - invalid source path::" + baseDir.getAbsolutePath());
-//		}
-//	}
-//	
-//	private void addMissingBundlePriority(File dir, int priority) {
-//		File[] files = dir.listFiles(DirectoryFilter.DIRECTORY_FILTER);
-//		for (File childDir : files) {
-//			if (childDir.getName().equals(I18nManager.I18N_DIRNAME )) {
-//				// add priority to file
-//				int bundle1Prio = getBundlePriority(metadata1, bundle1);
-//				
-//			} else {
-//				// do it recursively
-//				addMissingBundlePriority(childDir, priority);
-//			}
-//		}
-//	}
-
 }
diff --git a/src/main/java/org/olat/core/util/i18n/devtools/_spring/devtoolsCorecontext.xml b/src/main/java/org/olat/core/util/i18n/devtools/_spring/devtoolsCorecontext.xml
index e4c33b1f1b5..ff6bcb4ce67 100644
--- a/src/main/java/org/olat/core/util/i18n/devtools/_spring/devtoolsCorecontext.xml
+++ b/src/main/java/org/olat/core/util/i18n/devtools/_spring/devtoolsCorecontext.xml
@@ -5,9 +5,6 @@
   http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
-<bean id="translationDevManager" class="org.olat.core.util.i18n.devtools.TranslationDevManager">
-	<constructor-arg ref="I18nManager" />
-</bean>
 	<!-- Devel / snoop user session -->
 	<bean class="org.olat.core.extensions.action.GenericActionExtension"  init-method="initExtensionPoints">
 			<property name="order" value="15120" />
diff --git a/src/main/java/org/olat/core/util/i18n/ui/I18nConfigController.java b/src/main/java/org/olat/core/util/i18n/ui/I18nConfigController.java
index a49cb3bd422..0485dcf8481 100644
--- a/src/main/java/org/olat/core/util/i18n/ui/I18nConfigController.java
+++ b/src/main/java/org/olat/core/util/i18n/ui/I18nConfigController.java
@@ -40,6 +40,7 @@ import org.olat.core.gui.control.generic.closablewrapper.CloseableModalControlle
 import org.olat.core.util.ArrayHelper;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * <h3>Description:</h3> This controller offers a workflow to configure the
@@ -68,6 +69,11 @@ class I18nConfigController extends FormBasicController {
 	private FormLink createLanguageLink, deleteLanguageLink, importPackageLink, exportPackageLink, deletePackageLink;
 	private CloseableModalController cmc;
 	private Controller subCtr;
+	
+	@Autowired
+	private I18nManager i18nMgr;
+	@Autowired
+	private I18nModule i18nModule;
 
 	/**
 	 * Constructor for the language configuration workflow
@@ -86,15 +92,14 @@ class I18nConfigController extends FormBasicController {
 	 */
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
-		I18nManager i18nMgr = I18nManager.getInstance();
 		//
 		// Add default languages pulldown
-		Set<String> availableKeys = I18nModule.getAvailableLanguageKeys();
+		Set<String> availableKeys = i18nModule.getAvailableLanguageKeys();
 		String[] defaultlangKeys = ArrayHelper.toArray(availableKeys);
 		String[] defaultLangValues = new String[defaultlangKeys.length];
 		for (int i = 0; i < defaultlangKeys.length; i++) {
 			String key = defaultlangKeys[i];
-			String explLang = i18nMgr.getLanguageInEnglish(key, I18nModule.isOverlayEnabled());
+			String explLang = i18nMgr.getLanguageInEnglish(key, i18nModule.isOverlayEnabled());
 			String all = explLang;
 			if (explLang != null && !explLang.equals(key)) all += " (" + key + ")";
 			defaultLangValues[i] = all;
@@ -111,10 +116,10 @@ class I18nConfigController extends FormBasicController {
 		// Add enabled languages checkboxes
 		String[] availablelangKeys = ArrayHelper.toArray(availableKeys);
 		String[] availableValues = new String[availablelangKeys.length];
-		int referenceKeyCount = i18nMgr.countI18nItems(I18nModule.getFallbackLocale(), null, true);
+		int referenceKeyCount = i18nMgr.countI18nItems(i18nModule.getFallbackLocale(), null, true);
 		for (int i = 0; i < availablelangKeys.length; i++) {
 			String key = availablelangKeys[i];
-			String explLang = i18nMgr.getLanguageInEnglish(key, I18nModule.isOverlayEnabled());
+			String explLang = i18nMgr.getLanguageInEnglish(key, i18nModule.isOverlayEnabled());
 			String all = explLang;
 			if (explLang != null && !explLang.equals(key)) all += " (" + key + ")";
 			// count translation status
@@ -133,12 +138,12 @@ class I18nConfigController extends FormBasicController {
 		enabledLangSelection.setEscapeHtml(false);
 		enabledLangSelection.addActionListener(FormEvent.ONCLICK); // Radios/Checkboxes need onclick because of IE bug OLAT-5753
 		// Enable current enabled languages
-		for (String langKey : I18nModule.getEnabledLanguageKeys()) {
+		for (String langKey : i18nModule.getEnabledLanguageKeys()) {
 			enabledLangSelection.select(langKey, true);
 		}
 		//
 		// Add create / delete links, but only when translation tool is configured
-		if (I18nModule.isTransToolEnabled()) {
+		if (i18nModule.isTransToolEnabled()) {
 			createLanguageLink = uifactory.addFormLink("configuration.management.create", formLayout, Link.BUTTON);
 			deleteLanguageLink = uifactory.addFormLink("configuration.management.delete", formLayout, Link.BUTTON);
 		}
@@ -166,12 +171,12 @@ class I18nConfigController extends FormBasicController {
 		if (source == defaultLangSelection) {
 			// Get new default language and update I18nModule accordingly
 			String langKey = defaultLangSelection.getSelectedKey();
-			Locale defaultLocale = I18nManager.getInstance().getLocaleOrNull(langKey);
+			Locale defaultLocale = i18nMgr.getLocaleOrNull(langKey);
 			this.flc.contextPut("defaultLangKey", defaultLocale.toString());
-			I18nModule.setDefaultLocale(defaultLocale);
+			i18nModule.setDefaultLocale(defaultLocale);
 			// Make sure this language is in the list of enabled languages
 			enabledLangSelection.select(langKey, true);
-			I18nModule.getEnabledLanguageKeys().add(langKey);
+			i18nModule.getEnabledLanguageKeys().add(langKey);
 
 		} else if (source == enabledLangSelection) {
 			// Get enabled values, make sure the default language is enabled and
@@ -195,7 +200,7 @@ class I18nConfigController extends FormBasicController {
 //				showWarning("configuration.fallback.lang.must.be.enabed", fallbackLangKey);
 //			}
 
-			I18nModule.setEnabledLanguageKeys(enabledLangKeys);
+			i18nModule.setEnabledLanguageKeys(enabledLangKeys);
 
 		} else if (source == createLanguageLink) {
 			// Show new language sub form in an overlay window
diff --git a/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubDeleteLangController.java b/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubDeleteLangController.java
index 4346c295905..541d10682b6 100644
--- a/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubDeleteLangController.java
+++ b/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubDeleteLangController.java
@@ -46,6 +46,7 @@ import org.olat.core.logging.AssertException;
 import org.olat.core.util.ArrayHelper;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * Description:<br>
@@ -68,6 +69,11 @@ class I18nConfigSubDeleteLangController extends FormBasicController {
 	private DialogBoxController dialogCtr;
 	private FormLink cancelButton;
 	private FormSubmit submitButton;
+	
+	@Autowired
+	private I18nManager i18nMgr;
+	@Autowired
+	private I18nModule i18nModule;
 
 	/**
 	 * Constructor for the delete-language workflow
@@ -77,7 +83,7 @@ class I18nConfigSubDeleteLangController extends FormBasicController {
 	 */
 	public I18nConfigSubDeleteLangController(UserRequest ureq, WindowControl control) {
 		super(ureq, control, LAYOUT_VERTICAL);
-		if (!I18nModule.isTransToolEnabled()) { throw new AssertException(
+		if (!i18nModule.isTransToolEnabled()) { throw new AssertException(
 				"Languages can only be deleted when the translation tool is enabled and the translation tool source pathes are configured in the olat.properties"); }
 		initForm(ureq);
 	}
@@ -88,13 +94,12 @@ class I18nConfigSubDeleteLangController extends FormBasicController {
 	 */
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener,UserRequest ureq) {
-		I18nManager i18nMgr = I18nManager.getInstance();
 		// A title, displayed in fieldset
 		setFormTitle("configuration.management.delete.title");
 		setFormDescription("configuration.management.delete.description");
 		//
 		// Add languages checkboxes
-		Set<String> deletableKeysUnsorted = I18nModule.getTranslatableLanguageKeys();
+		Set<String> deletableKeysUnsorted = i18nModule.getTranslatableLanguageKeys();
 		String[] deletableKeys = ArrayHelper.toArray(deletableKeysUnsorted);
 		String[] availableValues = new String[deletableKeys.length];
 		for (int i = 0; i < deletableKeys.length; i++) {
@@ -132,10 +137,10 @@ class I18nConfigSubDeleteLangController extends FormBasicController {
 			showError("configuration.management.delete.error", defaultKey);
 			return;
 		}
-		String fallbackKey = I18nModule.getFallbackLocale().toString();
+		String fallbackKey = i18nModule.getFallbackLocale().toString();
 		if (toDelete.contains(fallbackKey)) {
 			deleteLangSelection.select(fallbackKey, false);
-			showError("configuration.management.delete.error", I18nModule.getFallbackLocale().toString());
+			showError("configuration.management.delete.error", i18nModule.getFallbackLocale().toString());
 			return;
 		}
 		dialogCtr = activateYesNoDialog(ureq, translate("configuration.management.delete.confirm.title"), translate(
@@ -146,12 +151,13 @@ class I18nConfigSubDeleteLangController extends FormBasicController {
 	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
 	 *      org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
 	 */
+	@Override
 	public void event(UserRequest ureq, Controller source, Event event) {
 		if (source == dialogCtr) {
 			if (DialogBoxUIFactory.isYesEvent(event)) {
 				// Yes case, delete now
 				for (String deleteLang : deleteLangSelection.getSelectedKeys()) {
-					I18nManager.getInstance().deleteLanguage(deleteLang, true);
+					i18nMgr.deleteLanguage(deleteLang, true);
 					logAudit("Deleted language::" + deleteLang, null);
 				}
 				// wow, everything worked fine
diff --git a/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubDeletePackageController.java b/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubDeletePackageController.java
index e1c28ae035d..949464188b9 100644
--- a/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubDeletePackageController.java
+++ b/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubDeletePackageController.java
@@ -43,6 +43,7 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.modal.DialogBoxController;
 import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
 import org.olat.core.util.i18n.I18nModule;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * Description:<br>
@@ -64,6 +65,9 @@ class I18nConfigSubDeletePackageController extends FormBasicController {
 	private DialogBoxController dialogCtr;
 	private FormLink cancelButton;
 	private FormSubmit submitButton;
+	
+	@Autowired
+	private I18nModule i18nModule;
 
 	/**
 	 * Constructor for the delete-language pack workflow
@@ -121,7 +125,7 @@ class I18nConfigSubDeletePackageController extends FormBasicController {
 					logAudit("Deleted language pack::" + deleteLangPack, null);
 				}
 				// Reset i18n system
-				I18nModule.reInitializeAndFlushCache();
+				i18nModule.reInitializeAndFlushCache();
 				// wow, everything worked fine
 				showInfo("configuration.management.package.delete.success", deleteLangPackSelection.getSelectedKeys().toString());
 				fireEvent(ureq, Event.DONE_EVENT);
diff --git a/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubExportLangController.java b/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubExportLangController.java
index 719f9a824e4..91d0b7a8072 100644
--- a/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubExportLangController.java
+++ b/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubExportLangController.java
@@ -47,6 +47,7 @@ import org.olat.core.util.ArrayHelper;
 import org.olat.core.util.CodeHelper;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * Description:<br>
@@ -67,6 +68,11 @@ class I18nConfigSubExportLangController extends FormBasicController {
 	private MultipleSelectionElement exportLangSelection;
 	private FormLink cancelButton;
 	private FormSubmit submitButton;
+	
+	@Autowired
+	private I18nModule i18nModule;
+	@Autowired
+	private I18nManager i18nMgr;
 
 	/**
 	 * Constructor for the export-language workflow
@@ -85,13 +91,12 @@ class I18nConfigSubExportLangController extends FormBasicController {
 	 */
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
-		I18nManager i18nMgr = I18nManager.getInstance();
 		// A title, displayed in fieldset
 		setFormTitle("configuration.management.package.export.title");
 		setFormDescription("configuration.management.package.export.description");
 		//
 		// Add languages checkboxes
-		Set<String> availableKeysUnsorted = I18nModule.getAvailableLanguageKeys();
+		Set<String> availableKeysUnsorted = i18nModule.getAvailableLanguageKeys();
 		String[] availableKeys = ArrayHelper.toArray(availableKeysUnsorted);
 		String[] availableValues = new String[availableKeys.length];
 		for (int i = 0; i < availableKeys.length; i++) {
@@ -127,7 +132,7 @@ class I18nConfigSubExportLangController extends FormBasicController {
 		}
 		String tmpFileName = CodeHelper.getGlobalForeverUniqueID();
 		// crate new temp file
-		File exportFile = I18nManager.getInstance().createLanguageJarFile(toExport, tmpFileName);
+		File exportFile = i18nMgr.createLanguageJarFile(toExport, tmpFileName);
 		if (exportFile != null) {
 			String fileName = "language_export_" + Settings.getApplicationName() + "_" + Settings.getVersion() + ".jar";
 			// Create a temporary media resource that gets deleted from the
diff --git a/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubImportLangController.java b/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubImportLangController.java
index e5429c050e1..23ee6e96110 100644
--- a/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubImportLangController.java
+++ b/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubImportLangController.java
@@ -41,6 +41,7 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.util.ArrayHelper;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * <h3>Description:</h3> This form allows the user to import languages from a
@@ -61,6 +62,11 @@ class I18nConfigSubImportLangController extends FormBasicController {
 	private FileElement importFile;
 	private FormLink cancelButton;
 	private MultipleSelectionElement importKeys;
+	
+	@Autowired
+	private I18nModule i18nModule;
+	@Autowired
+	private I18nManager i18nManager;
 
 	public I18nConfigSubImportLangController(UserRequest ureq, WindowControl control) {
 		super(ureq, control, LAYOUT_VERTICAL);
@@ -71,7 +77,7 @@ class I18nConfigSubImportLangController extends FormBasicController {
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		// A title, displayed in fieldset
 		setFormTitle("configuration.management.package.import.title");
-		if (I18nModule.isTransToolEnabled()) {
+		if (i18nModule.isTransToolEnabled()) {
 			setFormDescription("configuration.management.package.import.description.transserver");			
 		} else {
 			setFormDescription("configuration.management.package.import.description");						
@@ -108,15 +114,15 @@ class I18nConfigSubImportLangController extends FormBasicController {
 			Collection<String> importLangKeys = importKeys.getSelectedKeys();			
 			Set<String> alreadyInstalledLangs = new HashSet<String>();
 			for (String langKey : importLangKeys) {
-				if (I18nModule.getAvailableLanguageKeys().contains(langKey)) {
+				if (i18nModule.getAvailableLanguageKeys().contains(langKey)) {
 					alreadyInstalledLangs.add(langKey);
 				}
 			}
-			if (I18nModule.isTransToolEnabled()) {
+			if (i18nModule.isTransToolEnabled()) {
 				// In translation mode importing will copy the language package
 				// over an existing language or create a new language
 				File tmpJar = importFile.getUploadFile();
-				I18nManager.getInstance().copyLanguagesFromJar(tmpJar, importLangKeys);
+				i18nManager.copyLanguagesFromJar(tmpJar, importLangKeys);
 				logAudit("Uploaded languages from jar::" + importFile.getUploadFileName(), null);
 				showInfo("configuration.management.package.import.success", importLangKeys.toString());
 				
@@ -139,7 +145,7 @@ class I18nConfigSubImportLangController extends FormBasicController {
 				}
 			}
 			// Reset i18n system
-			I18nModule.reInitializeAndFlushCache();
+			i18nModule.reInitializeAndFlushCache();
 			fireEvent(ureq, Event.DONE_EVENT);
 		}
 	}
@@ -153,7 +159,7 @@ class I18nConfigSubImportLangController extends FormBasicController {
 		} else if (source == importFile) {
 			if (importFile.isUploadSuccess()) {
 				File tmpJar = importFile.getUploadFile();
-				Set<String> importLangKeys = I18nManager.getInstance().sarchForAvailableLanguagesInJarFile(tmpJar, true);
+				Set<String> importLangKeys = i18nManager.sarchForAvailableLanguagesInJarFile(tmpJar, true);
 				if (importLangKeys.size() == 0) {
 					showError("configuration.management.package.import.failure.empty");
 					return;
diff --git a/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubNewLangController.java b/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubNewLangController.java
index 397c6ba305e..ccd78fd9d2c 100644
--- a/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubNewLangController.java
+++ b/src/main/java/org/olat/core/util/i18n/ui/I18nConfigSubNewLangController.java
@@ -51,6 +51,7 @@ import org.olat.core.util.Util;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
 import org.olat.user.UserManager;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * Description:<br>
@@ -72,6 +73,9 @@ import org.olat.user.UserManager;
 class I18nConfigSubNewLangController extends FormBasicController {
 	private TextElement newLanguage, newCountry, newVariant, newTranslatedInEnglish, newTranslatedInLanguage, newTranslator;
 	private FormLink cancelButton;
+	
+	@Autowired
+	private I18nModule i18nModule;
 
 	/**
 	 * Constructor for the new-language workflow
@@ -81,7 +85,7 @@ class I18nConfigSubNewLangController extends FormBasicController {
 	 */
 	protected I18nConfigSubNewLangController(UserRequest ureq, WindowControl control) {
 		super(ureq, control, LAYOUT_DEFAULT);
-		if (!I18nModule.isTransToolEnabled()) { throw new AssertException(
+		if (!i18nModule.isTransToolEnabled()) { throw new AssertException(
 				"New languages can only be created when the translation tool is enabled and the translation tool source pathes are configured in the olat.properties"); }
 		initForm(ureq);
 	}
diff --git a/src/main/java/org/olat/core/util/i18n/ui/InlineTranslationInterceptHandlerController.java b/src/main/java/org/olat/core/util/i18n/ui/InlineTranslationInterceptHandlerController.java
index 790cf85b08a..c65e010f507 100644
--- a/src/main/java/org/olat/core/util/i18n/ui/InlineTranslationInterceptHandlerController.java
+++ b/src/main/java/org/olat/core/util/i18n/ui/InlineTranslationInterceptHandlerController.java
@@ -25,6 +25,7 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.commons.lang.StringEscapeUtils;
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.ComponentRenderer;
@@ -48,6 +49,7 @@ import org.olat.core.util.i18n.I18nItem;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
 import org.olat.core.util.prefs.Preferences;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * Description:<br>
@@ -86,6 +88,11 @@ public class InlineTranslationInterceptHandlerController extends BasicController
 	private static final Pattern patternInput = Pattern.compile("<input[^>]*?" + decoratedTranslatedPattern + ".*?>");
 	private static final Pattern patAttribute = Pattern.compile("<[^>]*?" + decoratedTranslatedPattern + "[^>]*?>");
 
+	@Autowired
+	private I18nManager i18nMgr;
+	@Autowired
+	private I18nModule i18nModule;
+	
 	/**
 	 * Constructor
 	 * 
@@ -200,16 +207,14 @@ public class InlineTranslationInterceptHandlerController extends BasicController
 			if (StringHelper.containsNonWhitespace(bundle) && StringHelper.containsNonWhitespace(key)) {
 				// Get userconfigured reference locale
 				Preferences guiPrefs = ureq.getUserSession().getGuiPreferences();
-				List<String> referenceLangs = I18nModule.getTransToolReferenceLanguages();
-				String referencePrefs = (String) guiPrefs.get(I18nModule.class, I18nModule.GUI_PREFS_PREFERRED_REFERENCE_LANG, referenceLangs
-						.get(0));
-				I18nManager i18nMgr = I18nManager.getInstance();
+				List<String> referenceLangs = i18nModule.getTransToolReferenceLanguages();
+				String referencePrefs = (String) guiPrefs.get(I18nModule.class, I18nModule.GUI_PREFS_PREFERRED_REFERENCE_LANG, referenceLangs.get(0));
 				Locale referenceLocale = i18nMgr.getLocaleOrNull(referencePrefs);
 				// Set target local to current user language
 				Locale targetLocale = i18nMgr.getLocaleOrNull(ureq.getLocale().toString());
-				if (I18nModule.isOverlayEnabled() && !I18nModule.isTransToolEnabled()) {
+				if (i18nModule.isOverlayEnabled() && !i18nModule.isTransToolEnabled()) {
 					// use overlay locale when in customizing mode
-					targetLocale = I18nModule.getOverlayLocales().get(targetLocale);	
+					targetLocale = i18nModule.getOverlayLocales().get(targetLocale);	
 				}
 				List<I18nItem> i18nItems = i18nMgr.findExistingAndMissingI18nItems(referenceLocale, targetLocale, bundle, false);
 				if(i18nItems.isEmpty()) {
@@ -222,7 +227,7 @@ public class InlineTranslationInterceptHandlerController extends BasicController
 					// running -
 					// must be done before instantiating the translation controller
 					i18nMgr.setMarkLocalizedStringsEnabled(ureq.getUserSession(), false);
-					i18nItemEditCtr = new TranslationToolI18nItemEditCrumbController(ureq, getWindowControl(), i18nItems, referenceLocale, !I18nModule.isTransToolEnabled());
+					i18nItemEditCtr = new TranslationToolI18nItemEditCrumbController(ureq, getWindowControl(), i18nItems, referenceLocale, !i18nModule.isTransToolEnabled());
 					listenTo(i18nItemEditCtr);
 					// set current key from the package as current translation item
 					for (I18nItem item : i18nItems) {
@@ -251,7 +256,7 @@ public class InlineTranslationInterceptHandlerController extends BasicController
 	protected void event(UserRequest ureq, Controller source, Event event) {
 		if (source == cmc) {
 			// user closed dialog, go back to inline translation mode
-			I18nManager.getInstance().setMarkLocalizedStringsEnabled(ureq.getUserSession(), true);
+			i18nMgr.setMarkLocalizedStringsEnabled(ureq.getUserSession(), true);
 		}
 	}
 
@@ -459,7 +464,7 @@ public class InlineTranslationInterceptHandlerController extends BasicController
 			inlineTranslationURLBuilder.buildURI(link, new String[] { ARG_BUNDLE, ARG_KEY, ARG_IDENT }, arguments);
 			link.append("\" title=\"");
 			String combinedKey = arguments[0] + ":" + arguments[1];
-			if (I18nModule.isTransToolEnabled()) {
+			if (CoreSpringFactory.getImpl(I18nModule.class).isTransToolEnabled()) {
 				link.append(StringEscapeUtils.escapeHtml(inlineTrans.translate("inline.translate", new String[] { combinedKey })));
 			} else {
 				link.append(StringEscapeUtils.escapeHtml(inlineTrans.translate("inline.customize.translate", new String[] { combinedKey })));			
diff --git a/src/main/java/org/olat/core/util/i18n/ui/SingleKeyTranslatorController.java b/src/main/java/org/olat/core/util/i18n/ui/SingleKeyTranslatorController.java
index cb94ae14990..82235c18f85 100644
--- a/src/main/java/org/olat/core/util/i18n/ui/SingleKeyTranslatorController.java
+++ b/src/main/java/org/olat/core/util/i18n/ui/SingleKeyTranslatorController.java
@@ -40,6 +40,7 @@ import org.olat.core.util.Util;
 import org.olat.core.util.i18n.I18nItem;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -61,7 +62,10 @@ public class SingleKeyTranslatorController extends FormBasicController {
 	private static final String LBL_NAME_PREFIX = "lbl.";
 	private Map<String, TextElement> textElements;
 
+	@Autowired
 	private I18nManager i18nMng;
+	@Autowired
+	private I18nModule i18nModule;
 
 	public SingleKeyTranslatorController(UserRequest ureq, WindowControl wControl, String keyToTranslate, Class<?> translatorBaseClass) {
 		this(ureq,wControl,new String[]{keyToTranslate},translatorBaseClass);
@@ -94,12 +98,9 @@ public class SingleKeyTranslatorController extends FormBasicController {
 
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
-		// load 18n-stuff
-		i18nMng = I18nManager.getInstance();
+		Map<Locale, Locale> allOverlays = i18nModule.getOverlayLocales();
 
-		Map<Locale, Locale> allOverlays = I18nModule.getOverlayLocales();
-
-		Collection<String> enabledKeys = I18nModule.getEnabledLanguageKeys();
+		Collection<String> enabledKeys = i18nModule.getEnabledLanguageKeys();
 		bundles = new ArrayList<I18nRowBundle>();
 		for (String key : enabledKeys) {
 			Locale loc = i18nMng.getLocaleOrNull(key);
diff --git a/src/main/java/org/olat/core/util/i18n/ui/TranslationToolI18nItemEditCrumbController.java b/src/main/java/org/olat/core/util/i18n/ui/TranslationToolI18nItemEditCrumbController.java
index d378cb02ea0..fa41cbea99c 100644
--- a/src/main/java/org/olat/core/util/i18n/ui/TranslationToolI18nItemEditCrumbController.java
+++ b/src/main/java/org/olat/core/util/i18n/ui/TranslationToolI18nItemEditCrumbController.java
@@ -46,6 +46,7 @@ import org.olat.core.util.i18n.I18nItem;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
 import org.olat.core.util.prefs.Preferences;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * <h3>Description:</h3> This controller can be used to edit one or more
@@ -83,7 +84,10 @@ public class TranslationToolI18nItemEditCrumbController extends CrumbFormBasicCo
 	// true when the overlay files are edited and not the language files itself
 	private boolean customizingMode = false;
 	
-	private final I18nManager i18nMgr;
+	@Autowired
+	private I18nManager i18nMgr;
+	@Autowired
+	private I18nModule i18nModule;
 
 	/**
 	 * Constructor for the item edit controller. Use the
@@ -101,12 +105,11 @@ public class TranslationToolI18nItemEditCrumbController extends CrumbFormBasicCo
 	public TranslationToolI18nItemEditCrumbController(UserRequest ureq, WindowControl control, List<I18nItem> i18nItems,
 			Locale referenceLocale, boolean customizingMode) {
 		super(ureq, control, "translationToolI18nItemEdit");
-		i18nMgr = I18nManager.getInstance();
 		this.customizingMode = customizingMode;
 		this.i18nItems = i18nItems;
 		if(referenceLocale == null) {
 			Preferences guiPrefs = ureq.getUserSession().getGuiPreferences();
-			List<String> referenceLangs = I18nModule.getTransToolReferenceLanguages();
+			List<String> referenceLangs = i18nModule.getTransToolReferenceLanguages();
 			String referencePrefs = (String)guiPrefs.get(I18nModule.class, I18nModule.GUI_PREFS_PREFERRED_REFERENCE_LANG, referenceLangs.get(0));
 			this.referenceLocale = i18nMgr.getLocaleOrNull(referencePrefs);
 			if(this.referenceLocale == null) {
@@ -200,7 +203,7 @@ public class TranslationToolI18nItemEditCrumbController extends CrumbFormBasicCo
 		flc.contextPut("compareSwitchEnabled", compareEnabledPrefs);
 		
 		// Add compare language selection
-		Set<String> availableLangKeys = I18nModule.getAvailableLanguageKeys();
+		Set<String> availableLangKeys = i18nModule.getAvailableLanguageKeys();
 		String[] comparelangKeys = ArrayHelper.toArray(availableLangKeys);
 		String[] compareLangValues = new String[comparelangKeys.length];
 		for (int i = 0; i < comparelangKeys.length; i++) {
@@ -218,14 +221,14 @@ public class TranslationToolI18nItemEditCrumbController extends CrumbFormBasicCo
 		if (compareLocale == null) compareLocale = I18nModule.getDefaultLocale();
 		compareLangSelection = uifactory.addDropdownSingleselect("compareLangSelection", flc, comparelangKeys, compareLangValues, null);
 		compareLangSelection.setDomReplacementWrapperRequired(false);
-		compareLangSelection.select(i18nMgr.getLocaleKey(compareLocale), true);
-		flc.contextPut("compareLanguageKey", i18nMgr.getLocaleKey(compareLocale));
+		compareLangSelection.select(i18nModule.getLocaleKey(compareLocale), true);
+		flc.contextPut("compareLanguageKey", i18nModule.getLocaleKey(compareLocale));
 		compareLangSelection.addActionListener(FormEvent.ONCHANGE);
 		compareLangSelection.setEnabled(compareEnabledPrefs.booleanValue());
 		
 		// Add target box
-		flc.contextPut("targetLanguageKey", i18nMgr.getLocaleKey(currentItem.getLocale()));
-		flc.contextPut("targetLanguage", i18nMgr.getLanguageTranslated(i18nMgr.getLocaleKey(currentItem.getLocale()), false));			
+		flc.contextPut("targetLanguageKey", i18nModule.getLocaleKey(currentItem.getLocale()));
+		flc.contextPut("targetLanguage", i18nMgr.getLanguageTranslated(i18nModule.getLocaleKey(currentItem.getLocale()), false));			
 		targetArea = uifactory.addTextAreaElement("targetArea", "edit.targetArea", -1, 5, -1, true, null, flc);
 		// Add annotation box
 		annotationArea = uifactory.addTextAreaElement("annotationArea", "edit.annotationArea", -1, 1, -1, true, null, flc);
@@ -254,11 +257,11 @@ public class TranslationToolI18nItemEditCrumbController extends CrumbFormBasicCo
 			// don't edit annotations in customizing mode
 			annotationArea.setEnabled(false);
 			// target lang flags and lang name		
-			Locale origLocale = I18nModule.getAllLocales().get(i18nMgr.createOrigianlLocaleKeyForOverlay(currentItem.getLocale()));
+			Locale origLocale = i18nModule.getAllLocales().get(i18nMgr.createOrigianlLocaleKeyForOverlay(currentItem.getLocale()));
 			if(origLocale == null) {
 				origLocale = currentItem.getLocale();
 			}
-			String localeKey = i18nMgr.getLocaleKey(origLocale);
+			String localeKey = i18nModule.getLocaleKey(origLocale);
 			flc.contextPut("targetLanguageKey", localeKey);			
 			flc.contextPut("targetLanguage", i18nMgr.getLanguageTranslated(localeKey, true));		
 		}
diff --git a/src/main/java/org/olat/core/util/i18n/ui/TranslationToolLauncherController.java b/src/main/java/org/olat/core/util/i18n/ui/TranslationToolLauncherController.java
index ea3789dfcad..8d9bc978de8 100644
--- a/src/main/java/org/olat/core/util/i18n/ui/TranslationToolLauncherController.java
+++ b/src/main/java/org/olat/core/util/i18n/ui/TranslationToolLauncherController.java
@@ -35,6 +35,7 @@ import org.olat.core.gui.control.generic.popup.PopupBrowserWindow;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
 import org.olat.core.util.prefs.Preferences;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * <h3>Description:</h3> This controller offers a panel for translators. On the
@@ -52,6 +53,9 @@ import org.olat.core.util.prefs.Preferences;
 public class TranslationToolLauncherController extends BasicController {
 	private VelocityContainer translationToolLauncherVC;
 	private Link startTranslationToolLink, enableInlineTranslationLink, disableInlineTranslationLink, cacheFlushLink;
+	
+	@Autowired
+	private I18nModule i18nModule;
 
 	/**
 	 * Constructor for the translation tool start panel controller
@@ -66,7 +70,7 @@ public class TranslationToolLauncherController extends BasicController {
 		startTranslationToolLink = LinkFactory.createButton("start", translationToolLauncherVC, this);
 		startTranslationToolLink.setTarget("_transtool");
 		// Add link to flush the cache
-		if (I18nManager.getInstance().isCachingEnabled()) {
+		if (i18nModule.isCachingEnabled()) {
 			cacheFlushLink = LinkFactory.createButton("cache.flush", translationToolLauncherVC, this);
 		}
 		// Add inline translation status and link
@@ -74,11 +78,11 @@ public class TranslationToolLauncherController extends BasicController {
 		updateInlineTranslationStatusAndLink(guiPrefs);
 		putInitialPanel(translationToolLauncherVC);
 		// Enable or disable entire translation tool
-		boolean isTranslationToolEnabled = I18nModule.isTransToolEnabled();
+		boolean isTranslationToolEnabled = i18nModule.isTransToolEnabled();
 		translationToolLauncherVC.contextPut("transToolEnabled", Boolean.valueOf(isTranslationToolEnabled));
 		// Enable or disable customizing tool. The customzing tool is only enabled
 		// when not configured as translation tool server
-		translationToolLauncherVC.contextPut("customizingToolEnabled", Boolean.valueOf(!isTranslationToolEnabled && I18nModule.isOverlayEnabled()));
+		translationToolLauncherVC.contextPut("customizingToolEnabled", Boolean.valueOf(!isTranslationToolEnabled && i18nModule.isOverlayEnabled()));
 	}
 
 	/*
@@ -93,8 +97,9 @@ public class TranslationToolLauncherController extends BasicController {
 		if (source == startTranslationToolLink) {
 			// wrap the content controller into a full header layout
 			ControllerCreator controllerCreator = new ControllerCreator() {
+				@Override
 				public Controller createController(UserRequest uureq, WindowControl wControl) {
-					return new TranslationToolMainController(uureq, wControl, !I18nModule.isTransToolEnabled());
+					return new TranslationToolMainController(uureq, wControl, !i18nModule.isTransToolEnabled());
 				}
 			};
 			// no need for later disposal, opens in popup window and will be disposed
@@ -112,7 +117,7 @@ public class TranslationToolLauncherController extends BasicController {
 
 		} else if (source == cacheFlushLink) {
 			// clear i18n cache
-			I18nModule.reInitializeAndFlushCache();
+			i18nModule.reInitializeAndFlushCache();
 			showInfo("cache.flush.ok");
 		}
 	}
diff --git a/src/main/java/org/olat/core/util/i18n/ui/TranslationToolStartCrumbController.java b/src/main/java/org/olat/core/util/i18n/ui/TranslationToolStartCrumbController.java
index bd63a8b2538..15af7b4c197 100644
--- a/src/main/java/org/olat/core/util/i18n/ui/TranslationToolStartCrumbController.java
+++ b/src/main/java/org/olat/core/util/i18n/ui/TranslationToolStartCrumbController.java
@@ -50,6 +50,7 @@ import org.olat.core.util.i18n.I18nItem;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
 import org.olat.core.util.prefs.Preferences;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * <h3>Description:</h3> This is the start controller for the translation tool
@@ -112,6 +113,12 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 	private Locale targetLocale;
 	// true when the overlay files are edited and not the language files itself
 	private boolean customizingMode = false;
+	
+	@Autowired
+	private I18nModule i18nModule;
+	@Autowired
+	private I18nManager i18nManager;
+	
 	/**
 	 * Constructor for the start crumb controller
 	 * 
@@ -135,12 +142,12 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		FormUIFactory formFactory = FormUIFactory.getInstance();
-		I18nManager i18nMgr = I18nManager.getInstance();
-		List<String> bundleNames = I18nModule.getBundleNamesContainingI18nFiles();
+
+		List<String> bundleNames = i18nModule.getBundleNamesContainingI18nFiles();
 		String[] bundlesKeys = buildBundleArrayKeys(bundleNames, true);
 		String[] bundlesValues = buildBundleArrayValues(bundleNames, true);
 		// call init methods for each form part
-		initLanguageSelectorElements(ureq.getUserSession(), formFactory, i18nMgr, formLayout);
+		initLanguageSelectorElements(ureq.getUserSession(), formFactory, formLayout);
 		initMissingItemsElements(formFactory, formLayout, bundlesKeys, bundlesValues);
 		initExistingItemsElements(formFactory, formLayout, bundlesKeys, bundlesValues);
 		initAllItemsElements(formFactory, formLayout, bundlesKeys, bundlesValues);
@@ -155,22 +162,22 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 		this.flc.contextPut("customizingPrefix", (customizingMode ? "customize." : ""));
 	}
 
-	private void initLanguageSelectorElements(UserSession usess, FormUIFactory formFactory, I18nManager i18nMgr,
+	private void initLanguageSelectorElements(UserSession usess, FormUIFactory formFactory,
 			FormItemContainer formLayout) {
 		// Add language selection as a subform
 		List<String> referenceLangs;
 		if (customizingMode) {
 			// Add all enabled languages that can be customized
-			referenceLangs = new ArrayList<String>(I18nModule.getEnabledLanguageKeys());
+			referenceLangs = new ArrayList<>(i18nModule.getEnabledLanguageKeys());
 		} else {
 			// Add configured reference languages in translation mode
-			referenceLangs = I18nModule.getTransToolReferenceLanguages();
+			referenceLangs = i18nModule.getTransToolReferenceLanguages();
 		}
 		String[] referencelangKeys = ArrayHelper.toArray(referenceLangs);
 		String[] referenceLangValues = new String[referencelangKeys.length];
 		for (int i = 0; i < referencelangKeys.length; i++) {
 			String key = referencelangKeys[i];
-			String explLang = i18nMgr.getLanguageInEnglish(key, false);
+			String explLang = i18nManager.getLanguageInEnglish(key, false);
 			String all = explLang;
 			if (explLang != null && !explLang.equals(key)) all += " (" + key + ")";
 			referenceLangValues[i] = all;
@@ -178,13 +185,13 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 		ArrayHelper.sort(referencelangKeys, referenceLangValues, false, true, false);
 		// Build css classes for reference languages
 		// Use first reference locale as default
-		referenceLocale = i18nMgr.getLocaleOrNull(referenceLangs.get(0));
+		referenceLocale = i18nManager.getLocaleOrNull(referenceLangs.get(0));
 		// Override with user preset
 		Preferences guiPrefs = usess.getGuiPreferences();
 		String referencePrefs = (String) guiPrefs.get(I18nModule.class, I18nModule.GUI_PREFS_PREFERRED_REFERENCE_LANG, referenceLangs.get(0));
 		for (String refLang : referencelangKeys) {
 			if (referencePrefs.equals(refLang)) {
-				referenceLocale = i18nMgr.getLocaleOrNull(referencePrefs);
+				referenceLocale = i18nManager.getLocaleOrNull(referencePrefs);
 				break;
 			}
 		}
@@ -197,10 +204,10 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 		Set<String> translatableKeys;	
 		if (customizingMode) {
 			// Use all enabled languages in customizing mode
-			translatableKeys = I18nModule.getOverlayLanguageKeys();
+			translatableKeys = i18nModule.getOverlayLanguageKeys();
 		} else {
 			// Allow translators to also translate other languages if they really desire. Show all languages.
-			translatableKeys = I18nModule.getTranslatableLanguageKeys();
+			translatableKeys = i18nModule.getTranslatableLanguageKeys();
 		}
 		String[] targetlangKeys = ArrayHelper.toArray(translatableKeys);
 		String[] targetLangValues = new String[targetlangKeys.length];
@@ -211,10 +218,10 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 			// overlay enabled, this would double the customizing extension to the key
 			String explLang;
 			if (customizingMode) {
-				String origKey = i18nMgr.createOrigianlLocaleKeyForOverlay(I18nModule.getAllLocales().get(key));
-				explLang = i18nMgr.getLanguageInEnglish(origKey, true);
+				String origKey = i18nManager.createOrigianlLocaleKeyForOverlay(i18nModule.getAllLocales().get(key));
+				explLang = i18nManager.getLanguageInEnglish(origKey, true);
 			} else {
-				explLang = i18nMgr.getLanguageInEnglish(key, false);
+				explLang = i18nManager.getLanguageInEnglish(key, false);
 			}
 			String all = explLang;
 			if (explLang != null && !explLang.equals(key)) all += "   (" + key + ")";
@@ -226,26 +233,26 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 		// Select current language if in list or the first one in the menu
 		if (customizingMode) {
 			// Use same as reference language in customizing mode
-			targetLocale = I18nModule.getOverlayLocales().get(referenceLocale);	
+			targetLocale = i18nModule.getOverlayLocales().get(referenceLocale);	
 			// Disable target lang selection - user should only choose reference language, target is updated automatically
 			targetLangSelection.setEnabled(false);
 		} else {			
 			// Use users current language in translation mode
 			targetLocale = getTranslator().getLocale();
-			if (!Arrays.asList(targetlangKeys).contains(i18nMgr.getLocaleKey(targetLocale))) {
-				targetLocale = i18nMgr.getLocaleOrNull(targetlangKeys[0]);
+			if (!Arrays.asList(targetlangKeys).contains(i18nModule.getLocaleKey(targetLocale))) {
+				targetLocale = i18nManager.getLocaleOrNull(targetlangKeys[0]);
 			}
 		}
-		targetLangSelection.select(i18nMgr.getLocaleKey(targetLocale), true);
+		targetLangSelection.select(i18nModule.getLocaleKey(targetLocale), true);
 		// Add lang key for image - don't use customizing lang key
 		if (customizingMode) {
-			this.flc.contextPut("targetLangKey", i18nMgr.createOrigianlLocaleKeyForOverlay(targetLocale));
+			this.flc.contextPut("targetLangKey", i18nManager.createOrigianlLocaleKeyForOverlay(targetLocale));
 		} else {
 			this.flc.contextPut("targetLangKey", targetLocale.toString());
 		}
 		targetLangSelection.addActionListener(FormEvent.ONCHANGE);
 		// Add progress bar as normal component (not a form element)
-		int bundlesCount = i18nMgr.countBundles(null, true);
+		int bundlesCount = i18nManager.countBundles(null, true);
 		progressBar = new ProgressBar("progressBar", 300, 0, 0, translate("start.progressBar.unitLabel", bundlesCount + ""));
 		this.flc.put("progressBar", progressBar);
 	}
@@ -389,10 +396,9 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 	 * 
 	 */
 	private void updateStatistics() {
-		I18nManager i18nMgr = I18nManager.getInstance();
 		// update progress bar with all package values
-		int toTranslateCount = i18nMgr.countI18nItems(referenceLocale, null, true);
-		int translatedCount = i18nMgr.countI18nItems(targetLocale, null, true);
+		int toTranslateCount = i18nManager.countI18nItems(referenceLocale, null, true);
+		int translatedCount = i18nManager.countI18nItems(targetLocale, null, true);
 		progressBar.setMax(toTranslateCount);
 		progressBar.setActual(translatedCount);
 		// calculate package dependent values for missing keys display
@@ -400,9 +406,9 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 		if (missingBundle.equals(ALL_BUNDLES_IDENTIFYER)) {
 			this.flc.contextPut("missingCount", (toTranslateCount - translatedCount));
 		} else {
-			int missingToTranslateCount = i18nMgr.countI18nItems(referenceLocale, missingBundle, missingBundlesIncludeBundlesChildrenSwitch
+			int missingToTranslateCount = i18nManager.countI18nItems(referenceLocale, missingBundle, missingBundlesIncludeBundlesChildrenSwitch
 					.isSelected(0));
-			int missingTranslatedCount = i18nMgr.countI18nItems(targetLocale, missingBundle, missingBundlesIncludeBundlesChildrenSwitch
+			int missingTranslatedCount = i18nManager.countI18nItems(targetLocale, missingBundle, missingBundlesIncludeBundlesChildrenSwitch
 					.isSelected(0));
 			this.flc.contextPut("missingCount", (missingToTranslateCount - missingTranslatedCount));
 		}
@@ -410,7 +416,7 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 		if (existingBundle.equals(ALL_BUNDLES_IDENTIFYER)) {
 			this.flc.contextPut("existingCount", translatedCount);
 		} else {
-			int existingTranslateCount = i18nMgr.countI18nItems(referenceLocale, existingBundle, existingBundlesIncludeBundlesChildrenSwitch.isSelected(0));
+			int existingTranslateCount = i18nManager.countI18nItems(referenceLocale, existingBundle, existingBundlesIncludeBundlesChildrenSwitch.isSelected(0));
 			this.flc.contextPut("existingCount", existingTranslateCount);
 		}
 		// calculate package dependent values for all keys display
@@ -418,7 +424,7 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 		if (allBundle.equals(ALL_BUNDLES_IDENTIFYER)) {
 			this.flc.contextPut("allCount", toTranslateCount);
 		} else {
-			int allToTranslateCount = i18nMgr.countI18nItems(referenceLocale, allBundle, allBundlesIncludeBundlesChildrenSwitch.isSelected(0));
+			int allToTranslateCount = i18nManager.countI18nItems(referenceLocale, allBundle, allBundlesIncludeBundlesChildrenSwitch.isSelected(0));
 			this.flc.contextPut("allCount", allToTranslateCount);
 		}
 	}
@@ -428,10 +434,9 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 	 * instead of the translation texts
 	 */
 	private void setCustomizingTextLabels() {
-		I18nManager i18nMgr = I18nManager.getInstance();
 		referenceLangSelection.setLabel("start.customize.referenceLangSelection", null);
 		targetLangSelection.setLabel("start.customize.targetLangSelection", null);		
-		int bundlesCount = i18nMgr.countBundles(null, true);
+		int bundlesCount = i18nManager.countBundles(null, true);
 		progressBar.setUnitLabel(translate("start.customize.progressBar.unitLabel", bundlesCount + ""));
 		missingTranslateButton.setI18nKey("generic.customize.translateButton");
 		allTranslateButton.setI18nKey("generic.customize.translateButton");
@@ -448,13 +453,12 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 	 * org.olat.core.gui.components.form.flexible.impl.FormEvent)
 	 */
 	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
-		I18nManager i18nMgr = I18nManager.getInstance();
 		if (source == targetLangSelection) {
 			String langKey = targetLangSelection.getSelectedKey();
-			targetLocale = i18nMgr.getLocaleOrNull(langKey);
+			targetLocale = i18nManager.getLocaleOrNull(langKey);
 			// Add lang key for image - don't use customizing lang key
 			if (customizingMode) {
-				this.flc.contextPut("targetLangKey", i18nMgr.createOrigianlLocaleKeyForOverlay(targetLocale));
+				this.flc.contextPut("targetLangKey", i18nManager.createOrigianlLocaleKeyForOverlay(targetLocale));
 			} else {
 				this.flc.contextPut("targetLangKey", targetLocale.toString());
 			}
@@ -462,17 +466,17 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 
 		} else if (source == referenceLangSelection) {
 			String langKey = referenceLangSelection.getSelectedKey();
-			referenceLocale = i18nMgr.getLocaleOrNull(langKey);
+			referenceLocale = i18nManager.getLocaleOrNull(langKey);
 			// update in gui prefs
 			Preferences guiPrefs = ureq.getUserSession().getGuiPreferences();
 			guiPrefs.putAndSave(I18nModule.class, I18nModule.GUI_PREFS_PREFERRED_REFERENCE_LANG, referenceLocale.toString());
 			// update GUI
-			this.flc.contextPut("referenceLangKey", i18nMgr.getLocaleKey(referenceLocale));
+			this.flc.contextPut("referenceLangKey", i18nModule.getLocaleKey(referenceLocale));
 			// Set target language to reference language when in customizing mode
 			if (customizingMode) {
-				targetLocale = I18nModule.getOverlayLocales().get(referenceLocale);	
-				targetLangSelection.select(i18nMgr.getLocaleKey(targetLocale), true);
-				this.flc.contextPut("targetLangKey", i18nMgr.getLocaleKey(referenceLocale));
+				targetLocale = i18nModule.getOverlayLocales().get(referenceLocale);	
+				targetLangSelection.select(i18nModule.getLocaleKey(targetLocale), true);
+				this.flc.contextPut("targetLangKey", i18nModule.getLocaleKey(referenceLocale));
 			}
 			updateStatistics();
 
@@ -481,10 +485,10 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 			if (bundle.equals(ALL_BUNDLES_IDENTIFYER)) bundle = null;
 			boolean includeBundlesChildren = missingBundlesIncludeBundlesChildrenSwitch.isSelected(0);
 			// use the fallback locale because it won't find the key if not already translated in the searchLocale
-			List<I18nItem> i18nItems = i18nMgr.findMissingI18nItems(referenceLocale, targetLocale, bundle,
+			List<I18nItem> i18nItems = i18nManager.findMissingI18nItems(referenceLocale, targetLocale, bundle,
 					includeBundlesChildren);
 			boolean prioSortEnabled = missingBundlesPrioritySortSwitch.isSelected(0);
-			i18nMgr.sortI18nItems(i18nItems, prioSortEnabled, prioSortEnabled);
+			i18nManager.sortI18nItems(i18nItems, prioSortEnabled, prioSortEnabled);
 			deactivateAndDisposeChildCrumbController();
 			// first the list controller
 			TranslationToolI18nItemListCrumbController i18nItemlistCrumbCtr = new TranslationToolI18nItemListCrumbController(ureq,
@@ -501,9 +505,9 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 			String bundle = existingBundlesSelection.getSelectedKey();
 			if (bundle.equals(ALL_BUNDLES_IDENTIFYER)) bundle = null;
 			boolean includeBundlesChildren = existingBundlesIncludeBundlesChildrenSwitch.isSelected(0);
-			List<I18nItem> i18nItems = i18nMgr.findExistingI18nItems(targetLocale, bundle, includeBundlesChildren);
+			List<I18nItem> i18nItems = i18nManager.findExistingI18nItems(targetLocale, bundle, includeBundlesChildren);
 			boolean prioSortEnabled = existingBundlesPrioritySortSwitch.isSelected(0);
-			i18nMgr.sortI18nItems(i18nItems, prioSortEnabled, prioSortEnabled);
+			i18nManager.sortI18nItems(i18nItems, prioSortEnabled, prioSortEnabled);
 			deactivateAndDisposeChildCrumbController();
 			// first the list controller
 			TranslationToolI18nItemListCrumbController i18nItemlistCrumbCtr = new TranslationToolI18nItemListCrumbController(ureq,
@@ -520,10 +524,10 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 			String bundle = allBundlesSelection.getSelectedKey();
 			if (bundle.equals(ALL_BUNDLES_IDENTIFYER)) bundle = null;
 			boolean includeBundlesChildren = allBundlesIncludeBundlesChildrenSwitch.isSelected(0);
-			List<I18nItem> i18nItems = i18nMgr.findExistingAndMissingI18nItems(referenceLocale, targetLocale, bundle,
+			List<I18nItem> i18nItems = i18nManager.findExistingAndMissingI18nItems(referenceLocale, targetLocale, bundle,
 					includeBundlesChildren);
 			boolean prioSortEnabled = allBundlesPrioritySortSwitch.isSelected(0);
-			i18nMgr.sortI18nItems(i18nItems, prioSortEnabled, prioSortEnabled);
+			i18nManager.sortI18nItems(i18nItems, prioSortEnabled, prioSortEnabled);
 			deactivateAndDisposeChildCrumbController();
 			// first the list controller
 			TranslationToolI18nItemListCrumbController i18nItemlistCrumbCtr = new TranslationToolI18nItemListCrumbController(ureq,
@@ -545,14 +549,14 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 			Locale searchLocale = (searchReferenceTargetSelection.getSelectedKey().equals(KEYS_REFERENCE) ? referenceLocale : targetLocale);
 			if (searchKeyValueSelection.getSelectedKey().equals(KEYS_KEY)) {
 				// use the fallback locale because it won't find the key if not already translated in the searchLocale
-				i18nItems = i18nMgr.findI18nItemsByKeySearch(searchString, I18nModule.getFallbackLocale(), targetLocale, bundle,
+				i18nItems = i18nManager.findI18nItemsByKeySearch(searchString, i18nModule.getFallbackLocale(), targetLocale, bundle,
 						includeBundlesChildren);
 			} else {
-				i18nItems = i18nMgr.findI18nItemsByValueSearch(searchString, searchLocale, targetLocale, bundle,
+				i18nItems = i18nManager.findI18nItemsByValueSearch(searchString, searchLocale, targetLocale, bundle,
 						includeBundlesChildren);
 			}
 			boolean prioSortEnabled = searchBundlesPrioritySortSwitch.isSelected(0);
-			I18nManager.getInstance().sortI18nItems(i18nItems, prioSortEnabled, prioSortEnabled);
+			i18nManager.sortI18nItems(i18nItems, prioSortEnabled, prioSortEnabled);
 			deactivateAndDisposeChildCrumbController();
 			// first the list controller
 			TranslationToolI18nItemListCrumbController i18nItemlistCrumbCtr = new TranslationToolI18nItemListCrumbController(ureq,
@@ -607,28 +611,28 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 
 		} else if (source == missingBundlesPrioritySortSwitch) {
 			boolean enabled = missingBundlesPrioritySortSwitch.isSelected(0);
-			List<String> bundleNames = I18nModule.getBundleNamesContainingI18nFiles();
+			List<String> bundleNames = i18nModule.getBundleNamesContainingI18nFiles();
 			String[] bundlesKeys = buildBundleArrayKeys(bundleNames, enabled);
 			String[] bundlesValues = buildBundleArrayValues(bundleNames, enabled);
 			missingBundlesSelection.setKeysAndValues(bundlesKeys, bundlesValues, null);
 
 		} else if (source == existingBundlesPrioritySortSwitch) {
 			boolean enabled = existingBundlesPrioritySortSwitch.isSelected(0);
-			List<String> bundleNames = I18nModule.getBundleNamesContainingI18nFiles();
+			List<String> bundleNames = i18nModule.getBundleNamesContainingI18nFiles();
 			String[] bundlesKeys = buildBundleArrayKeys(bundleNames, enabled);
 			String[] bundlesValues = buildBundleArrayValues(bundleNames, enabled);
 			existingBundlesSelection.setKeysAndValues(bundlesKeys, bundlesValues, null);
 
 		} else if (source == allBundlesPrioritySortSwitch) {
 			boolean enabled = allBundlesPrioritySortSwitch.isSelected(0);
-			List<String> bundleNames = I18nModule.getBundleNamesContainingI18nFiles();
+			List<String> bundleNames = i18nModule.getBundleNamesContainingI18nFiles();
 			String[] bundlesKeys = buildBundleArrayKeys(bundleNames, enabled);
 			String[] bundlesValues = buildBundleArrayValues(bundleNames, enabled);
 			allBundlesSelection.setKeysAndValues(bundlesKeys, bundlesValues, null);
 
 		} else if (source == searchBundlesPrioritySortSwitch) {
 			boolean enabled = searchBundlesPrioritySortSwitch.isSelected(0);
-			List<String> bundleNames = I18nModule.getBundleNamesContainingI18nFiles();
+			List<String> bundleNames = i18nModule.getBundleNamesContainingI18nFiles();
 			String[] bundlesKeys = buildBundleArrayKeys(bundleNames, enabled);
 			String[] bundlesValues = buildBundleArrayValues(bundleNames, enabled);
 			searchBundlesSelection.setKeysAndValues(bundlesKeys, bundlesValues, null);
@@ -675,7 +679,7 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 			for (String bundle : bundleNames) {
 				copy.add(bundle);
 			}
-			I18nManager.getInstance().sortBundles(copy, true);
+			i18nManager.sortBundles(copy, true);
 			bundlesListKeys.addAll(copy);
 		} else {
 			bundlesListKeys.addAll(bundleNames);
@@ -700,7 +704,7 @@ class TranslationToolStartCrumbController extends CrumbFormBasicController {
 			for (String bundle : bundleNames) {
 				copy.add(bundle);
 			}
-			I18nManager.getInstance().sortBundles(copy, true);
+			i18nManager.sortBundles(copy, true);
 			bundlesListValues.addAll(copy);
 		} else {
 			bundlesListValues.addAll(bundleNames);
diff --git a/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml b/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml
index 95cedcd772a..91b2d0754a2 100644
--- a/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml
+++ b/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml
@@ -10,13 +10,13 @@
 
 	<context:component-scan base-package="org.olat.course.assessment" />
 	
-	<bean id="assessmentNotificationsTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="assessmentNotificationsTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 	    <property name="jobDetail" ref="assessmentNotificationsJob" />
 	    <property name="cronExpression" value="1 * * * * ?" />
 	    <property name="startDelay" value="55000" />
 	</bean>
 	
-	<bean id="assessmentNotificationsJob" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="assessmentNotificationsJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 		<property name="jobClass" value="org.olat.course.assessment.manager.AssessmentModeNotificationJob" />
 	</bean>
 	
diff --git a/src/main/java/org/olat/course/certificate/manager/CertificatesManagerImpl.java b/src/main/java/org/olat/course/certificate/manager/CertificatesManagerImpl.java
index 44c2f7e8f00..1ae56fc5e9c 100644
--- a/src/main/java/org/olat/course/certificate/manager/CertificatesManagerImpl.java
+++ b/src/main/java/org/olat/course/certificate/manager/CertificatesManagerImpl.java
@@ -874,7 +874,7 @@ public class CertificatesManagerImpl implements CertificatesManager, MessageList
 		
 		Float score = workUnit.getScore();
 		String lang = identity.getUser().getPreferences().getLanguage();
-		Locale locale = I18nManager.getInstance().getLocaleOrDefault(lang);
+		Locale locale = i18nManager.getLocaleOrDefault(lang);
 		Boolean passed = workUnit.getPassed();
 		Date dateCertification = certificate.getCreationDate();
 		Date dateFirstCertification = getDateFirstCertification(identity, resource.getKey());
diff --git a/src/main/java/org/olat/course/site/ui/CourseSiteAdminController.java b/src/main/java/org/olat/course/site/ui/CourseSiteAdminController.java
index 02198886963..66e426c58ad 100644
--- a/src/main/java/org/olat/course/site/ui/CourseSiteAdminController.java
+++ b/src/main/java/org/olat/course/site/ui/CourseSiteAdminController.java
@@ -57,6 +57,7 @@ import org.olat.course.site.model.LanguageConfiguration;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryManager;
 import org.olat.repository.controllers.ReferencableEntriesSearchController;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -80,6 +81,9 @@ public class CourseSiteAdminController extends FormBasicController {
 	private CourseSiteConfiguration siteConfiguration;
 	private final RepositoryManager repositoryManager;
 	
+	@Autowired
+	private I18nModule i18nModule;
+	
 	public CourseSiteAdminController(UserRequest ureq, WindowControl wControl, CourseSiteConfiguration siteConfiguration) {
 		super(ureq, wControl);
 		
@@ -128,7 +132,7 @@ public class CourseSiteAdminController extends FormBasicController {
 			}
 		}
 		
-		for(String langKey:I18nModule.getEnabledLanguageKeys()) {
+		for(String langKey:i18nModule.getEnabledLanguageKeys()) {
 			if(langToConfigMap.containsKey(langKey)) {
 				LanguageConfiguration langConfig = langToConfigMap.get(langKey);
 				RepositoryEntry re = repositoryManager.lookupRepositoryEntryBySoftkey(langConfig.getRepoSoftKey(), false);
diff --git a/src/main/java/org/olat/course/statistic/MySQLTempStatTableCreator.java b/src/main/java/org/olat/course/statistic/MySQLTempStatTableCreator.java
index 28c96b5ebad..c64f4a3c402 100644
--- a/src/main/java/org/olat/course/statistic/MySQLTempStatTableCreator.java
+++ b/src/main/java/org/olat/course/statistic/MySQLTempStatTableCreator.java
@@ -98,7 +98,7 @@ public class MySQLTempStatTableCreator implements IStatisticUpdater {
 			long fromSeconds = from.getTime() / 1000l;
 			long untilSeconds = until.getTime() / 1000l;
 
-			jdbcTemplate_.update(
+			long numLoggingActions = jdbcTemplate_.update(
 					"insert into o_stat_temptable (creationdate,businesspath,userproperty2,userproperty4,userproperty10,userproperty3) " +
 						"select " +
 							"creationdate,businesspath,userproperty2,userproperty4,userproperty10,userproperty3 " +
@@ -107,8 +107,7 @@ public class MySQLTempStatTableCreator implements IStatisticUpdater {
 						" where " +
 							"actionverb='launch' and actionobject='node' and creationdate>from_unixtime('"+ fromSeconds +"') and creationdate<=from_unixtime('"+ untilSeconds +"');");
 			
-			long numLoggingActions = jdbcTemplate_.queryForLong("select count(*) from o_stat_temptable;");
-			log_.info("updateStatistic: insert done. number of logging actions: "+numLoggingActions);
+			log_.info("updateStatistic: insert done. number of logging actions: " + numLoggingActions);
 		} catch(RuntimeException e) {
 			log_.warn("updateStatistic: ran into a RuntimeException: "+e, e);
 		} catch(Error er) {
diff --git a/src/main/java/org/olat/course/statistic/_spring/statisticsJobContext.xml b/src/main/java/org/olat/course/statistic/_spring/statisticsJobContext.xml
index e079b063686..29d74357e51 100644
--- a/src/main/java/org/olat/course/statistic/_spring/statisticsJobContext.xml
+++ b/src/main/java/org/olat/course/statistic/_spring/statisticsJobContext.xml
@@ -6,7 +6,7 @@
 	<!-- 
 	 -->
 
-	<bean id="updateStatisticsTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="updateStatisticsTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 	    <property name="jobDetail" ref="org.olat.statistics.job.${cluster.singleton.services}" />
 	    <!-- adjust cron style syntax for your notification needs 
 	    	"0 10 0 * *"  e.g. 10 minutes after midnight
@@ -27,12 +27,12 @@
 	    <property name="startDelay" value="300000" />
 	</bean>
 	
-	<bean id="org.olat.statistics.job.enabled" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="org.olat.statistics.job.enabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 	  <property name="jobClass" value="org.olat.course.statistic.UpdateStatisticsJob"/>
 	</bean>
 	
 	<!-- dummy bean -->
-	<bean id="org.olat.statistics.job.disabled" class="org.springframework.scheduling.quartz.JobDetailBean"  lazy-init="true">
+	<bean id="org.olat.statistics.job.disabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"  lazy-init="true">
 		<!-- NOTE: reusing the notifications.DummyJob here -->
 		<property name="jobClass" value="org.olat.core.commons.services.scheduler.DummyJob" />
 	</bean>
diff --git a/src/main/java/org/olat/dispatcher/LocaleNegotiator.java b/src/main/java/org/olat/dispatcher/LocaleNegotiator.java
index b3d83dd2f70..b6d7893dfab 100644
--- a/src/main/java/org/olat/dispatcher/LocaleNegotiator.java
+++ b/src/main/java/org/olat/dispatcher/LocaleNegotiator.java
@@ -24,6 +24,7 @@ import java.util.Enumeration;
 import java.util.Locale;
 import java.util.Map;
 
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.util.i18n.I18nModule;
 
@@ -98,8 +99,9 @@ public class LocaleNegotiator {
  * match language and country and the final ty it with language only
  */
 	public static Locale getNegotiatedLocale(Locale loc) {
-		Map<String,Locale> allLocales = I18nModule.getAllLocales();
-		Collection<String> enabledLanguageKeys = I18nModule.getEnabledLanguageKeys();
+		I18nModule i18nModule = CoreSpringFactory.getImpl(I18nModule.class);
+		Map<String,Locale> allLocales = i18nModule.getAllLocales();
+		Collection<String> enabledLanguageKeys = i18nModule.getEnabledLanguageKeys();
 		
 		String lang = loc.getLanguage();
 		//search a direct match first de_CH_bs...
diff --git a/src/main/java/org/olat/ims/qti/render/LocalizedXSLTransformer.java b/src/main/java/org/olat/ims/qti/render/LocalizedXSLTransformer.java
index 2c7dba6f738..47ca6dcb0b7 100644
--- a/src/main/java/org/olat/ims/qti/render/LocalizedXSLTransformer.java
+++ b/src/main/java/org/olat/ims/qti/render/LocalizedXSLTransformer.java
@@ -51,13 +51,14 @@ import org.dom4j.Document;
 import org.dom4j.Element;
 import org.dom4j.dom.DOMDocument;
 import org.dom4j.io.DocumentSource;
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.dispatcher.impl.StaticMediaDispatcher;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.logging.OLATRuntimeException;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.Util;
-import org.olat.core.util.i18n.I18nManager;
+import org.olat.core.util.i18n.I18nModule;
 import org.olat.ims.qti.QTI12ResultDetailsController;
 import org.olat.ims.resources.IMSEntityResolver;
 import org.xml.sax.EntityResolver;
@@ -116,11 +117,12 @@ public class LocalizedXSLTransformer {
 	 */
 	 // cluster_ok only in VM
 	public static LocalizedXSLTransformer getInstance(Locale locale) {
-		LocalizedXSLTransformer instance = instanceHash.get(I18nManager.getInstance().getLocaleKey(locale));
+		I18nModule i18nModule = CoreSpringFactory.getImpl(I18nModule.class);
+		LocalizedXSLTransformer instance = instanceHash.get(i18nModule.getLocaleKey(locale));
 		if (instance == null) {
 			Translator trans = Util.createPackageTranslator(QTI12ResultDetailsController.class, locale);
 			LocalizedXSLTransformer newInstance = new LocalizedXSLTransformer(trans);
-			instance = instanceHash.putIfAbsent(I18nManager.getInstance().getLocaleKey(locale), newInstance); //see javadoc of ConcurrentHashMap
+			instance = instanceHash.putIfAbsent(i18nModule.getLocaleKey(locale), newInstance); //see javadoc of ConcurrentHashMap
 			if(instance == null) { //newInstance was put into the map
 				instance = newInstance;
 			}
diff --git a/src/main/java/org/olat/ldap/LDAPLoginModule.java b/src/main/java/org/olat/ldap/LDAPLoginModule.java
index e3e351c8486..839b802b92f 100644
--- a/src/main/java/org/olat/ldap/LDAPLoginModule.java
+++ b/src/main/java/org/olat/ldap/LDAPLoginModule.java
@@ -20,11 +20,14 @@
 
 package org.olat.ldap;
 
+import static org.quartz.CronScheduleBuilder.cronSchedule;
+import static org.quartz.JobBuilder.newJob;
+import static org.quartz.TriggerBuilder.newTrigger;
+
 import java.io.FileInputStream;
 import java.security.KeyStore;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
-import java.text.ParseException;
 import java.util.Date;
 import java.util.Enumeration;
 
@@ -35,10 +38,9 @@ import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.coordinate.CoordinatorManager;
-import org.quartz.CronTrigger;
 import org.quartz.JobDetail;
 import org.quartz.Scheduler;
-import org.quartz.SchedulerException;
+import org.quartz.Trigger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
@@ -267,21 +269,23 @@ public class LDAPLoginModule extends AbstractSpringModule {
 	private void initCronSyncJob() {
 		try {
 			// Create job with cron trigger configuration
-			JobDetail jobDetail = new JobDetail("LDAP_Cron_Syncer_Job", Scheduler.DEFAULT_GROUP, LDAPUserSynchronizerJob.class);
-			CronTrigger trigger = new CronTrigger();
-			trigger.setName("LDAP_Cron_Syncer_Trigger");
-			trigger.setCronExpression(ldapSyncCronSyncExpression);
+			JobDetail jobDetail = newJob(LDAPUserSynchronizerJob.class)
+					.withIdentity("LDAP_Cron_Syncer_Job", Scheduler.DEFAULT_GROUP)
+					.build();
+			Trigger trigger = newTrigger()
+				    .withIdentity("LDAP_Cron_Syncer_Trigger")
+				    .withSchedule(cronSchedule(ldapSyncCronSyncExpression))
+				    .build();
+
 			// Schedule job now
 			scheduler.scheduleJob(jobDetail, trigger);
 			log.info("LDAP cron syncer is enabled with expression::" + ldapSyncCronSyncExpression);
-		} catch (ParseException e) {
+		} catch (Exception e) {
 			setLdapSyncCronSync(false);
 			log.error("LDAP configuration in attribute 'ldapSyncCronSyncExpression' is not valid ("
 				+ ldapSyncCronSyncExpression
 				+ "). See http://quartz.sourceforge.net/javadoc/org/quartz/CronTrigger.html to learn more about the cron syntax. Disabling LDAP cron syncing",
 				e);
-		} catch (SchedulerException e) {
-			log.error("Error while scheduling LDAP cron sync job. Disabling LDAP cron syncing", e);
 		}
 	}
 
diff --git a/src/main/java/org/olat/login/LoginAuthprovidersController.java b/src/main/java/org/olat/login/LoginAuthprovidersController.java
index 08a57b79b85..83dccae10dd 100644
--- a/src/main/java/org/olat/login/LoginAuthprovidersController.java
+++ b/src/main/java/org/olat/login/LoginAuthprovidersController.java
@@ -84,6 +84,8 @@ public class LoginAuthprovidersController extends MainLayoutBasicController impl
 	private Link anoLink;
 	private StackedPanel dmzPanel;
 	
+	@Autowired
+	private I18nModule i18nModule;
 	@Autowired
 	private LoginModule loginModule;
 	
@@ -283,14 +285,14 @@ public class LoginAuthprovidersController extends MainLayoutBasicController impl
 		aboutVC.contextPut("version", Settings.getFullVersionInfo());
 		// Add translator and languages info
 		I18nManager i18nMgr = I18nManager.getInstance();
-		Collection<String> enabledKeysSet = I18nModule.getEnabledLanguageKeys();
+		Collection<String> enabledKeysSet = i18nModule.getEnabledLanguageKeys();
 		Map<String, String> langNames = new HashMap<String, String>();
 		Map<String, String> langTranslators = new HashMap<String, String>();
 		String[] enabledKeys = ArrayHelper.toArray(enabledKeysSet);
 		String[] names = new String[enabledKeys.length];
 		for (int i = 0; i < enabledKeys.length; i++) {
 			String key = enabledKeys[i];
-			String langName = i18nMgr.getLanguageInEnglish(key, I18nModule.isOverlayEnabled());
+			String langName = i18nMgr.getLanguageInEnglish(key, i18nModule.isOverlayEnabled());
 			langNames.put(key, langName);
 			names[i] = langName;
 			String author = i18nMgr.getLanguageAuthor(key);
diff --git a/src/main/java/org/olat/modules/lecture/_spring/lectureContext.xml b/src/main/java/org/olat/modules/lecture/_spring/lectureContext.xml
index 0bda9385b78..7b76f6e05bc 100644
--- a/src/main/java/org/olat/modules/lecture/_spring/lectureContext.xml
+++ b/src/main/java/org/olat/modules/lecture/_spring/lectureContext.xml
@@ -77,7 +77,7 @@
 	</bean>
 	
 	<!-- Lectures reminder job -->
-	<bean id="reminderLecturesTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="reminderLecturesTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 		<property name="jobDetail" ref="reminderLecturesJob.${cluster.singleton.services}" />
 	  	<!-- adjust cron style syntax for your notification needs 
 	   	"0 10 0 * *"  e.g. 10 minutes after midnight
@@ -99,17 +99,17 @@
 		<property name="startDelay" value="60000" />
 	</bean>
 
-	<bean id="reminderLecturesJob.enabled" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="reminderLecturesJob.enabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 		<property name="jobClass" value="org.olat.modules.lecture.manager.ReminderLecturesJob" />
 	</bean>
 	
 	<!-- dummy bean -->
-	<bean id="reminderLecturesJob.disabled" class="org.springframework.scheduling.quartz.JobDetailBean"  lazy-init="true">
+	<bean id="reminderLecturesJob.disabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"  lazy-init="true">
 		<property name="jobClass" value="org.olat.core.commons.services.scheduler.DummyJob" />
 	</bean>
 	
 	<!-- Lectures auto close job -->
-	<bean id="autoCloseLecturesTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="autoCloseLecturesTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 		<property name="jobDetail" ref="autoCloseLecturesJob.${cluster.singleton.services}" />
 	  	<!-- adjust cron style syntax for your notification needs 
 	   	"0 10 0 * *"  e.g. 10 minutes after midnight
@@ -131,12 +131,12 @@
 		<property name="startDelay" value="60000" />
 	</bean>
 
-	<bean id="autoCloseLecturesJob.enabled" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="autoCloseLecturesJob.enabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 		<property name="jobClass" value="org.olat.modules.lecture.manager.AutoCloseLecturesJob" />
 	</bean>
 	
 	<!-- dummy bean -->
-	<bean id="autoCloseLecturesJob.disabled" class="org.springframework.scheduling.quartz.JobDetailBean"  lazy-init="true">
+	<bean id="autoCloseLecturesJob.disabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"  lazy-init="true">
 		<property name="jobClass" value="org.olat.core.commons.services.scheduler.DummyJob" />
 	</bean>
 	
diff --git a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_en.properties
index 6b88fa06628..f955ec9ad8a 100644
--- a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Mon Jul 17 21:15:51 CEST 2017
+#Thu Aug 03 10:50:01 CEST 2017
 active=Active
 add.lecture=New lecture block
 add.reason=Add reason
@@ -81,7 +81,7 @@ form.managedflags.intro.short=This lecture block has been created by an external
 in.progress=In process
 info.lecture.block.optional=This lecture block is optional.
 info.no.lectures=You don't follow any lectures for the moment.
-infos.participant.attendance.rate=Personal attendance rate: {0}%
+infos.participant.attendance.rate=Personal attendance rate\: {0}%
 interceptor.start=You have now a roll call for the course "{0}" {1} from {4} until {5}.
 lecture.absence.default.authorized=Absence per default authorized
 lecture.admin.course.override.title=Configuration - can be overridden at course level
@@ -223,7 +223,7 @@ table.header.entry=Course
 table.header.export=Export
 table.header.external.ref=Ext. ref.
 table.header.id=ID
-table.header.infos=<i class='o_icon o_icon-lg o_icon_info'>  </i>
+table.header.infos=<i class\='o_icon o_icon-lg o_icon_info'>  </i>
 table.header.lecture.1=1
 table.header.lecture.10=10
 table.header.lecture.11=11
@@ -242,6 +242,8 @@ table.header.lecture.block=Lecture block
 table.header.location=Location
 table.header.log.action=Action
 table.header.log.author=Changed by
+table.header.log.effective.end.date=Effective end date
+table.header.log.effective.lectures=Effective lectures
 table.header.log.planned.lectures=Planned lectures
 table.header.log.user=User
 table.header.planned.lectures=Lectures
diff --git a/src/main/java/org/olat/modules/reminder/ReminderModule.java b/src/main/java/org/olat/modules/reminder/ReminderModule.java
index 41d5017bbf8..7c800102df5 100644
--- a/src/main/java/org/olat/modules/reminder/ReminderModule.java
+++ b/src/main/java/org/olat/modules/reminder/ReminderModule.java
@@ -19,7 +19,8 @@
  */
 package org.olat.modules.reminder;
 
-import java.text.ParseException;
+import static org.quartz.CronScheduleBuilder.cronSchedule;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.TimeZone;
@@ -32,8 +33,8 @@ import org.olat.core.util.coordinate.CoordinatorManager;
 import org.olat.modules.reminder.model.SendTime;
 import org.quartz.CronTrigger;
 import org.quartz.Scheduler;
-import org.quartz.SchedulerException;
 import org.quartz.Trigger;
+import org.quartz.TriggerKey;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
@@ -48,6 +49,8 @@ import org.springframework.stereotype.Service;
 public class ReminderModule extends AbstractSpringModule {
 	
 	private static final OLog log = Tracing.createLoggerFor(ReminderModule.class);
+
+	private final TriggerKey reminderTriggerKey = new TriggerKey("reminderTrigger", Scheduler.DEFAULT_GROUP);
 	
 	private static final String REMINDER_ENABLED = "remiNder.enabled";
 	private static final String SMS_ENABLED = "sms.enabled";
@@ -129,24 +132,28 @@ public class ReminderModule extends AbstractSpringModule {
 		}
 		return selectedSpi;
 	}
+	
 	/**
 	 * Default 0 0 9/1 * * ?
 	 * 
 	 */
 	private void configureQuartzJob() {
 		try {
-			Trigger trigger = scheduler.getTrigger("reminderTrigger", Scheduler.DEFAULT_GROUP);
+			Trigger trigger = scheduler.getTrigger(reminderTriggerKey);
 			if(trigger instanceof CronTrigger) {
 				CronTrigger cronTrigger = (CronTrigger)trigger;
 				String currentCronExpression = cronTrigger.getCronExpression();
 				String cronExpression = getCronExpression();
 				if(!cronExpression.equals(currentCronExpression)) {
 					log.info("Start reminder with this cron expression: " + cronExpression);
-					cronTrigger.setCronExpression(cronExpression);
-					scheduler.rescheduleJob("reminderTrigger", Scheduler.DEFAULT_GROUP, (Trigger)cronTrigger.clone());
+					
+					Trigger newTrigger = cronTrigger.getTriggerBuilder()
+							.withSchedule(cronSchedule(cronExpression))
+						    .build();
+					scheduler.rescheduleJob(reminderTriggerKey, newTrigger);
 				}
 			}
-		} catch (SchedulerException | ParseException e) {
+		} catch (Exception e) {
 			log.error("", e);
 		}
 	}
diff --git a/src/main/java/org/olat/modules/reminder/_spring/reminderContext.xml b/src/main/java/org/olat/modules/reminder/_spring/reminderContext.xml
index 2e6f5480c79..e5e946533e8 100644
--- a/src/main/java/org/olat/modules/reminder/_spring/reminderContext.xml
+++ b/src/main/java/org/olat/modules/reminder/_spring/reminderContext.xml
@@ -25,12 +25,12 @@
 		</property>
 	</bean>
 	
-	<bean id="reminderTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="reminderTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
     	<property name="jobDetail" ref="reminderJobDetail" />
     	<property name="cronExpression" value="0 0 9 * * ?" />
 	</bean>
 	
-	<bean id="reminderJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="reminderJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 		<property name="jobClass" value="org.olat.modules.reminder.manager.ReminderJob"/>
 	</bean>
 	
diff --git a/src/main/java/org/olat/modules/video/_spring/videoContext.xml b/src/main/java/org/olat/modules/video/_spring/videoContext.xml
index 7d962b2e32c..077b68312b4 100644
--- a/src/main/java/org/olat/modules/video/_spring/videoContext.xml
+++ b/src/main/java/org/olat/modules/video/_spring/videoContext.xml
@@ -6,7 +6,7 @@
   http://www.springframework.org/schema/beans/spring-beans.xsd">
   
   
-	<bean id="videoTranscodingTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="videoTranscodingTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 	    <property name="jobDetail" ref="videoTranscodingJobDetail" />
 	    <!-- adjust cron style syntax for your notification needs 
 	    	"0 10 0 * *"  e.g. 10 minutes after midnight
@@ -30,7 +30,7 @@
 	    <property name="startDelay" value="350000" />
 	</bean>
 	
-	<bean id="videoTranscodingJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
+	<bean id="videoTranscodingJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
 	  <property name="jobClass" value="org.olat.modules.video.manager.VideoTranscodingJob" />
 	</bean>
 
diff --git a/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java b/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java
index 28d716d331b..269638ae7d8 100644
--- a/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java
+++ b/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java
@@ -86,7 +86,7 @@ import org.olat.repository.RepositoryEntryImportExport;
 import org.olat.repository.RepositoryEntryImportExport.RepositoryEntryImport;
 import org.olat.repository.RepositoryManager;
 import org.olat.resource.OLATResource;
-import org.quartz.JobDetail;
+import org.quartz.JobKey;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -116,6 +116,8 @@ public class VideoManagerImpl implements VideoManager {
 	
 	private static final SimpleDateFormat displayDateFormat = new SimpleDateFormat("HH:mm:ss");
 	private static final SimpleDateFormat vttDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
+	
+	private final JobKey videoJobKey = new JobKey("videoTranscodingJobDetail", Scheduler.DEFAULT_GROUP);
 
 	@Autowired
 	private MovieService movieService;
@@ -427,8 +429,7 @@ public class VideoManagerImpl implements VideoManager {
 		// 3) Start transcoding immediately, force job execution
 		if (videoModule.isTranscodingLocal()) {
 			try {
-				JobDetail detail = scheduler.getJobDetail("videoTranscodingJobDetail", Scheduler.DEFAULT_GROUP);
-				scheduler.triggerJob(detail.getName(), detail.getGroup());
+				scheduler.triggerJob(videoJobKey);
 			} catch (SchedulerException e) {
 				log.error("Error while starting video transcoding job", e);
 			}			
diff --git a/src/main/java/org/olat/modules/video/manager/VideoTranscodingJob.java b/src/main/java/org/olat/modules/video/manager/VideoTranscodingJob.java
index 8bb6cfd3d27..b6508b5706b 100644
--- a/src/main/java/org/olat/modules/video/manager/VideoTranscodingJob.java
+++ b/src/main/java/org/olat/modules/video/manager/VideoTranscodingJob.java
@@ -41,7 +41,6 @@ import org.olat.modules.video.VideoTranscoding;
 import org.olat.resource.OLATResource;
 import org.quartz.JobExecutionContext;
 import org.quartz.JobExecutionException;
-import org.quartz.StatefulJob;
 
 /**
  * 
@@ -49,7 +48,7 @@ import org.quartz.StatefulJob;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-public class VideoTranscodingJob extends JobWithDB implements StatefulJob {
+public class VideoTranscodingJob extends JobWithDB {
 
 	/**
 	 * 
diff --git a/src/main/java/org/olat/modules/vitero/ViteroModule.java b/src/main/java/org/olat/modules/vitero/ViteroModule.java
index 4b53ac19524..69ae3452f0b 100644
--- a/src/main/java/org/olat/modules/vitero/ViteroModule.java
+++ b/src/main/java/org/olat/modules/vitero/ViteroModule.java
@@ -19,8 +19,11 @@
  */
 package org.olat.modules.vitero;
 
+import static org.quartz.CronScheduleBuilder.cronSchedule;
+import static org.quartz.JobBuilder.newJob;
+import static org.quartz.TriggerBuilder.newTrigger;
+
 import java.net.URI;
-import java.text.ParseException;
 import java.util.Calendar;
 
 import javax.ws.rs.core.UriBuilder;
@@ -32,10 +35,10 @@ import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.coordinate.CoordinatorManager;
 import org.olat.modules.vitero.manager.ViteroZombieSlayerJob;
-import org.quartz.CronTrigger;
 import org.quartz.JobDetail;
 import org.quartz.Scheduler;
-import org.quartz.SchedulerException;
+import org.quartz.Trigger;
+import org.quartz.TriggerKey;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
@@ -146,20 +149,25 @@ public class ViteroModule extends AbstractSpringModule implements ConfigOnOff {
 	
 	private void initCronJob() {
 		try {
-			if(scheduler.getTrigger("Vitero_Cleaner_Cron_Trigger", Scheduler.DEFAULT_GROUP) == null) {
-				JobDetail jobDetail = new JobDetail("Vitero_Cleaner_Cron_Job", Scheduler.DEFAULT_GROUP, ViteroZombieSlayerJob.class);
-				CronTrigger trigger = new CronTrigger();
+			TriggerKey triggerKey = new TriggerKey("Vitero_Cleaner_Cron_Trigger", Scheduler.DEFAULT_GROUP);
+			if(scheduler.getTrigger(triggerKey) == null) {
+				
+				// Create job with cron trigger configuration
+				JobDetail jobDetail = newJob(ViteroZombieSlayerJob.class)
+						.withIdentity("Vitero_Cleaner_Cron_Job", Scheduler.DEFAULT_GROUP)
+						.build();
 				
 				Calendar cal = Calendar.getInstance();
 				cal.add(Calendar.SECOND, 30);
-				trigger.setStartTime(cal.getTime());
-				trigger.setName("Vitero_Cleaner_Cron_Trigger");
-				trigger.setCronExpression(cronExpression);
+				Trigger trigger = newTrigger()
+					    .withIdentity("Vitero_Cleaner_Cron_Trigger")
+					    .withSchedule(cronSchedule(cronExpression))
+					    .startAt(cal.getTime())
+					    .build();
+
 				scheduler.scheduleJob(jobDetail, trigger);
 			}
-		} catch (ParseException e) {
-			log.error("Cannot start the Quartz Job which clean the Vitero rooms", e);
-		} catch (SchedulerException e) {
+		} catch (Exception e) {
 			log.error("Cannot start the Quartz Job which clean the Vitero rooms", e);
 		}
 	}
diff --git a/src/main/java/org/olat/portfolio/_spring/portfolioContext.xml b/src/main/java/org/olat/portfolio/_spring/portfolioContext.xml
index 94c3cbd3be9..5d5f9f883bd 100644
--- a/src/main/java/org/olat/portfolio/_spring/portfolioContext.xml
+++ b/src/main/java/org/olat/portfolio/_spring/portfolioContext.xml
@@ -69,7 +69,7 @@
 	</bean>
 	
 	<!-- Deadline Job -->
-	<bean id="epDeadlineTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="epDeadlineTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 		<property name="jobDetail" ref="epDeadlineJob.${cluster.singleton.services}" />
   	<!-- adjust cron style syntax for your notification needs 
    	"0 10 0 * *"  e.g. 10 minutes after midnight
@@ -88,16 +88,16 @@
 		<property name="startDelay" value="60000" />
 	</bean>
 
-	<bean id="epDeadlineJob.enabled" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="epDeadlineJob.enabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 		<property name="jobClass" value="org.olat.portfolio.manager.EPDeadlineJob" />
 	</bean>
 	
 	<!-- dummy bean -->
-	<bean id="epDeadlineJob.disabled" class="org.springframework.scheduling.quartz.JobDetailBean"  lazy-init="true">
+	<bean id="epDeadlineJob.disabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"  lazy-init="true">
 		<property name="jobClass" value="org.olat.core.commons.services.scheduler.DummyJob" />
 	</bean>
 	
-	<bean id="invitationCleanupTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="invitationCleanupTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 		<property name="jobDetail" ref="invitationCleanupJob.${cluster.singleton.services}" />
 		 <!-- adjust cron style syntax for your notification needs 
 		  	"0 10 0 * *"  e.g. 10 minutes after midnight
@@ -119,11 +119,11 @@
 		<property name="startDelay" value="150000" />
 	</bean>
 
-	<bean id="invitationCleanupJob.enabled" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="invitationCleanupJob.enabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 		<property name="jobClass" value="org.olat.portfolio.manager.InvitationCleanupJob" />
 	</bean>
 	<!-- dummy bean -->
-	<bean id="invitationCleanupJob.disabled" class="org.springframework.scheduling.quartz.JobDetailBean"  lazy-init="true">
+	<bean id="invitationCleanupJob.disabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"  lazy-init="true">
 		<property name="jobClass" value="org.olat.core.commons.services.scheduler.DummyJob" />
 	</bean>
 	
diff --git a/src/main/java/org/olat/registration/LanguageChooserController.java b/src/main/java/org/olat/registration/LanguageChooserController.java
index a321d1cfa26..4c06a4c99f2 100644
--- a/src/main/java/org/olat/registration/LanguageChooserController.java
+++ b/src/main/java/org/olat/registration/LanguageChooserController.java
@@ -41,12 +41,10 @@ import org.olat.core.util.event.MultiUserEvent;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.dispatcher.LocaleNegotiator;
+import org.springframework.beans.factory.annotation.Autowired;
 
 
 /**
- * Description:<br>
- * TODO: srosse Class Description for LanguageChooserController
- * 
  * <P>
  * Initial Date:  17 nov. 2009 <br>
  * @author srosse, stephane.rosse@frentix.com, www.frentix.com
@@ -59,6 +57,8 @@ public class LanguageChooserController extends FormBasicController {
 	
 	private boolean fireStandardEvent = true;
 	
+	@Autowired
+	private I18nManager i18nManager;
 	
 	/**
 	 * @param ureq
@@ -94,7 +94,7 @@ public class LanguageChooserController extends FormBasicController {
 	@Override
 	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
 		if(source == langs) {
-			Locale loc = I18nManager.getInstance().getLocaleOrDefault(getSelectedLanguage());
+			Locale loc = i18nManager.getLocaleOrDefault(getSelectedLanguage());
 			MultiUserEvent mue = new LanguageChangedEvent(loc, ureq);
 			setLocale(loc, true);
 			ureq.getUserSession().setLocale(loc);
@@ -124,7 +124,7 @@ public class LanguageChooserController extends FormBasicController {
 	 */
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, final UserRequest ureq) {
-		Map<String, String> languages = I18nManager.getInstance().getEnabledLanguagesTranslated();
+		Map<String, String> languages = i18nManager.getEnabledLanguagesTranslated();
 		String[] langKeys = StringHelper.getMapKeysAsStringArray(languages);
 		String[] langValues = StringHelper.getMapValuesAsStringArray(languages);
 		ArrayHelper.sort(langKeys, langValues, false, true, false);
diff --git a/src/main/java/org/olat/registration/PwChangeController.java b/src/main/java/org/olat/registration/PwChangeController.java
index 5b10fd76a14..1a4f1e29d81 100644
--- a/src/main/java/org/olat/registration/PwChangeController.java
+++ b/src/main/java/org/olat/registration/PwChangeController.java
@@ -54,6 +54,7 @@ import org.olat.core.id.UserConstants;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
 import org.olat.core.util.i18n.I18nManager;
+import org.olat.core.util.i18n.I18nModule;
 import org.olat.core.util.mail.MailBundle;
 import org.olat.core.util.mail.MailHelper;
 import org.olat.core.util.mail.MailManager;
@@ -70,8 +71,6 @@ import org.springframework.beans.factory.annotation.Autowired;
  */
 public class PwChangeController extends BasicController {
 
-	private static String SEPARATOR = "____________________________________________________________________\n";
-
 	private Panel passwordPanel;
 	private Link pwchangeHomelink;
 	private final VelocityContainer myContent;
@@ -85,6 +84,10 @@ public class PwChangeController extends BasicController {
 	private String pwKey;
 	private TemporaryKey tempKey;
 	
+	@Autowired
+	private I18nModule i18nModule;
+	@Autowired
+	private I18nManager i18nManager;
 	@Autowired
 	private UserModule userModule;
 	@Autowired
@@ -248,7 +251,7 @@ public class PwChangeController extends BasicController {
 			return null;
 		}
 		Preferences prefs = identity.getUser().getPreferences();
-		Locale locale = I18nManager.getInstance().getLocaleOrDefault(prefs.getLanguage());
+		Locale locale = i18nManager.getLocaleOrDefault(prefs.getLanguage());
 		ureq.getUserSession().setLocale(locale);
 		myContent.contextPut("locale", locale);
 		
@@ -274,8 +277,8 @@ public class PwChangeController extends BasicController {
 			.append("<div class='o_body'>")
 			.append(userTrans.translate("pwchange.headline"))
 			.append(userTrans.translate("pwchange.intro", new String[] { identity.getName() }))
-		    .append(userTrans.translate("pwchange.body", new String[] { serverpath, tk.getRegistrationKey(), I18nManager.getInstance().getLocaleKey(ureq.getLocale()) }))
-		    .append(userTrans.translate("pwchange.body.alt", new String[] { serverpath, tk.getRegistrationKey(), I18nManager.getInstance().getLocaleKey(ureq.getLocale()) }))
+		    .append(userTrans.translate("pwchange.body", new String[] { serverpath, tk.getRegistrationKey(), i18nModule.getLocaleKey(ureq.getLocale()) }))
+		    .append(userTrans.translate("pwchange.body.alt", new String[] { serverpath, tk.getRegistrationKey(), i18nModule.getLocaleKey(ureq.getLocale()) }))
 		    .append("</div>")
 		    .append("<div class='o_footer'>")
 		    .append(userTrans.translate("reg.wherefrom", new String[] { serverpath, today, ip }))
diff --git a/src/main/java/org/olat/registration/RegistrationController.java b/src/main/java/org/olat/registration/RegistrationController.java
index b37da45a021..4fde7fa7f95 100644
--- a/src/main/java/org/olat/registration/RegistrationController.java
+++ b/src/main/java/org/olat/registration/RegistrationController.java
@@ -97,6 +97,8 @@ public class RegistrationController extends BasicController implements Activatea
 	private String uniqueRegistrationKey;
 	private TemporaryKey tempKey;
 	
+	@Autowired
+	private I18nModule i18nModule;
 	@Autowired
 	private I18nManager i18nManager;
 	@Autowired
@@ -131,7 +133,7 @@ public class RegistrationController extends BasicController implements Activatea
 			// support for legacy lang parameter
 			lang = ureq.getParameter("lang");
 		}
-		if (lang != null && ! lang.equals(i18nManager.getLocaleKey(getLocale()))) {
+		if (lang != null && ! lang.equals(i18nModule.getLocaleKey(getLocale()))) {
 			Locale loc = i18nManager.getLocaleOrDefault(lang);
 			ureq.getUserSession().setLocale(loc);
 			setLocale(loc, true);
@@ -154,7 +156,7 @@ public class RegistrationController extends BasicController implements Activatea
 			// render in a modal dialog, no need to add the 3cols layout controller
 			// wrapper
 			//fxdiff FXOLAT-113: business path in DMZ
-			if(I18nModule.getEnabledLanguageKeys().size() == 1) {
+			if(i18nModule.getEnabledLanguageKeys().size() == 1) {
 				wizInfoController.setCurStep(2);
 				createEmailForm(ureq);
 			} else {
@@ -169,7 +171,7 @@ public class RegistrationController extends BasicController implements Activatea
 				// error, there should be an entry
 				showError("regkey.missingentry");
 				//fxdiff FXOLAT-113: business path in DMZ
-				if(I18nModule.getEnabledLanguageKeys().size() == 1) {
+				if(i18nModule.getEnabledLanguageKeys().size() == 1) {
 					wizInfoController.setCurStep(2);
 					createEmailForm(ureq);
 				} else {
@@ -232,7 +234,7 @@ public class RegistrationController extends BasicController implements Activatea
 	}
 	
 	private void createRegForm2(UserRequest ureq, String proposedUsername, boolean userInUse, boolean usernameReadonly) {
-		registrationForm = new RegistrationForm2(ureq, getWindowControl(), I18nManager.getInstance().getLocaleKey(getLocale()), proposedUsername, userInUse, usernameReadonly);
+		registrationForm = new RegistrationForm2(ureq, getWindowControl(), i18nModule.getLocaleKey(getLocale()), proposedUsername, userInUse, usernameReadonly);
 		listenTo(registrationForm);
 		regarea.setContent(registrationForm.getInitialComponent());
 	}
@@ -303,11 +305,11 @@ public class RegistrationController extends BasicController implements Activatea
 					if (tk == null) tk = registrationManager.createTemporaryKeyByEmail(email, ip, RegistrationManager.REGISTRATION);
 					myContent.contextPut("regKey", tk.getRegistrationKey());
 					
-					String link = serverpath + "/dmz/registration/index.html?key=" + tk.getRegistrationKey() + "&language=" + i18nManager.getLocaleKey(ureq.getLocale());
+					String link = serverpath + "/dmz/registration/index.html?key=" + tk.getRegistrationKey() + "&language=" + i18nModule.getLocaleKey(ureq.getLocale());
 					String[] bodyAttrs = new String[]{
 						serverpath,										//0
 						tk.getRegistrationKey(),						//1
-						i18nManager.getLocaleKey(ureq.getLocale()),		//2
+						i18nModule.getLocaleKey(ureq.getLocale()),		//2
 						"<a href=\"" + link + "\">" + link + "</a>"		//3
 					};
 					
@@ -370,8 +372,8 @@ public class RegistrationController extends BasicController implements Activatea
 			if (event == Event.DONE_EVENT) {
 				String lang = registrationForm.getLangKey();
 				// change language if different then current language
-				if (! lang.equals(I18nManager.getInstance().getLocaleKey(ureq.getLocale()))) {
-					Locale loc = I18nManager.getInstance().getLocaleOrDefault(lang);
+				if (! lang.equals(i18nModule.getLocaleKey(ureq.getLocale()))) {
+					Locale loc = i18nManager.getLocaleOrDefault(lang);
 					ureq.getUserSession().setLocale(loc);
 					getTranslator().setLocale(loc);					
 				}
diff --git a/src/main/java/org/olat/registration/RegistrationForm2.java b/src/main/java/org/olat/registration/RegistrationForm2.java
index f4fed839d77..02bc13267e4 100644
--- a/src/main/java/org/olat/registration/RegistrationForm2.java
+++ b/src/main/java/org/olat/registration/RegistrationForm2.java
@@ -77,6 +77,8 @@ public class RegistrationForm2 extends FormBasicController {
 
 	@Autowired
 	private UserModule userModule;
+	@Autowired
+	private I18nManager i18nManager;
 	
 	/**
 	 * @param name
@@ -174,7 +176,7 @@ public class RegistrationForm2 extends FormBasicController {
 		
 		uifactory.addSpacerElement("lang", formLayout, true);
 		// second the user language
-		Map<String, String> languages = I18nManager.getInstance().getEnabledLanguagesTranslated();
+		Map<String, String> languages = i18nManager.getEnabledLanguagesTranslated();
 		lang = uifactory.addDropdownSingleselect("user.language", formLayout,
 				StringHelper.getMapKeysAsStringArray(languages),
 				StringHelper.getMapValuesAsStringArray(languages),
diff --git a/src/main/java/org/olat/registration/restapi/RegistrationWebService.java b/src/main/java/org/olat/registration/restapi/RegistrationWebService.java
index 14be04afef3..2305d8c1037 100644
--- a/src/main/java/org/olat/registration/restapi/RegistrationWebService.java
+++ b/src/main/java/org/olat/registration/restapi/RegistrationWebService.java
@@ -45,7 +45,7 @@ import org.olat.core.helpers.Settings;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.Util;
-import org.olat.core.util.i18n.I18nManager;
+import org.olat.core.util.i18n.I18nModule;
 import org.olat.core.util.mail.MailBundle;
 import org.olat.core.util.mail.MailManager;
 import org.olat.core.util.mail.MailerResult;
@@ -126,7 +126,7 @@ public class RegistrationWebService {
 			String[] bodyAttrs = new String[] {
 					serverpath,
 					tk.getRegistrationKey(),
-					I18nManager.getInstance().getLocaleKey(locale)
+					CoreSpringFactory.getImpl(I18nModule.class).getLocaleKey(locale)
 			};
 			String[] whereFromAttrs = new String [] { serverpath, today, ip };
 			String body = translator.translate("reg.body", bodyAttrs) + SEPARATOR + translator.translate("reg.wherefrom", whereFromAttrs);
diff --git a/src/main/java/org/olat/repository/_spring/repositoryContext.xml b/src/main/java/org/olat/repository/_spring/repositoryContext.xml
index 42418ac70ce..9c0dc8925cf 100644
--- a/src/main/java/org/olat/repository/_spring/repositoryContext.xml
+++ b/src/main/java/org/olat/repository/_spring/repositoryContext.xml
@@ -10,13 +10,13 @@
 
 	<context:component-scan base-package="org.olat.repository" />
 	
-	<bean id="automaticLifecycleTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="automaticLifecycleTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 	    <property name="jobDetail" ref="automaticLifecycleJob" />
 	    <property name="cronExpression" value="0 45 5 * * ?" />
 	    <property name="startDelay" value="55000" />
 	</bean>
 	
-	<bean id="automaticLifecycleJob" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="automaticLifecycleJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 		<property name="jobClass" value="org.olat.repository.manager.AutomaticLifecycleJob" />
 	</bean>
 	
diff --git a/src/main/java/org/olat/resource/accesscontrol/_spring/acContext.xml b/src/main/java/org/olat/resource/accesscontrol/_spring/acContext.xml
index 00e121ceeec..6b353d79936 100644
--- a/src/main/java/org/olat/resource/accesscontrol/_spring/acContext.xml
+++ b/src/main/java/org/olat/resource/accesscontrol/_spring/acContext.xml
@@ -73,14 +73,14 @@
 		<property name="order" value="7220" />
 	</bean>
 	
-	<bean id="acReservationCleanupJob" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
+	<bean id="acReservationCleanupJob" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
     	<property name="jobDetail" ref="acReservationCleanupJobDetail"/>
     	<!-- 60 seconds -->
   		<property name="repeatInterval" value="60000"/>
     	<property name="startDelay" value="30000" />
 	</bean>
 	
-	<bean id="acReservationCleanupJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
+	<bean id="acReservationCleanupJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
 		<property name="jobClass" value="org.olat.resource.accesscontrol.manager.ReservationsJob" />
 	</bean>
 	
diff --git a/src/main/java/org/olat/restapi/_spring/restApiContext.xml b/src/main/java/org/olat/restapi/_spring/restApiContext.xml
index 7836d4a86a0..74745c58a9b 100644
--- a/src/main/java/org/olat/restapi/_spring/restApiContext.xml
+++ b/src/main/java/org/olat/restapi/_spring/restApiContext.xml
@@ -51,7 +51,7 @@
 		</property>
 	</bean>
 	
-	<bean id="systemSamplerTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="systemSamplerTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 	    <property name="jobDetail" ref="systemSamplerJob" />
 	    <!-- adjust cron style syntax for your needs 
 	    A "Cron-Expression" is a string comprised of 6 or 7 fields separated by white space. The 6 mandatory and 1 optional fields are as follows:
@@ -71,32 +71,32 @@
 	    <property name="startDelay" value="60000" />
 	</bean>
 	
-	<bean id="systemSamplerJob" class="org.springframework.scheduling.quartz.JobDetailBean">
+	<bean id="systemSamplerJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
 	  <property name="jobClass" value="org.olat.restapi.system.SamplerJob" />
 	</bean>
 	
-	<bean id="procSamplerTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="procSamplerTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 	    <property name="jobDetail" ref="procSamplerJob" />
 	    <property name="cronExpression" value="5 3,8,13,18,23,28,33,38,43,48,53,58 * * * ?" />
 	    <property name="startDelay" value="30000" />
 	</bean>
 	
-	<bean id="procSamplerJob" class="org.springframework.scheduling.quartz.JobDetailBean">
+	<bean id="procSamplerJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
 	  <property name="jobClass" value="org.olat.restapi.system.ProcSamplerJob" />
 	</bean>
 	
 	
 	<!-- Deadline Job -->
-	<bean id="restTokenTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	<bean id="restTokenTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 		<property name="jobDetail" ref="restTokenJob.${cluster.singleton.services}" />
   	<!--  every day at 1:21 -->
 		<property name="cronExpression" value="0 21 1 * * ?" />
 		<property name="startDelay" value="60000" />
 	</bean>
-	<bean id="restTokenJob.enabled" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	<bean id="restTokenJob.enabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean" lazy-init="true">
 		<property name="jobClass" value="org.olat.restapi.security.RestTokenJob" />
 	</bean>
-	<bean id="restTokenJob.disabled" class="org.springframework.scheduling.quartz.JobDetailBean"  lazy-init="true">
+	<bean id="restTokenJob.disabled" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"  lazy-init="true">
 		<property name="jobClass" value="org.olat.core.commons.services.scheduler.DummyJob" />
 	</bean>
 
diff --git a/src/main/java/org/olat/restapi/i18n/I18nWebService.java b/src/main/java/org/olat/restapi/i18n/I18nWebService.java
index dedd11c75ba..20653689525 100644
--- a/src/main/java/org/olat/restapi/i18n/I18nWebService.java
+++ b/src/main/java/org/olat/restapi/i18n/I18nWebService.java
@@ -31,6 +31,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.i18n.I18nManager;
@@ -83,7 +84,8 @@ public class I18nWebService {
 	@Path("{package}/{key}")
 	@Produces(MediaType.TEXT_PLAIN)
 	public Response getTranslation(@PathParam("package") String packageName, @PathParam("key") String key, @QueryParam("locale") String localeKey, @Context HttpServletRequest request) {
-		I18nManager i18n = I18nManager.getInstance();
+		I18nManager i18n = CoreSpringFactory.getImpl(I18nManager.class);
+		I18nModule i18nModule = CoreSpringFactory.getImpl(I18nModule.class);
 		
 		Locale locale = null;
 		if(StringHelper.containsNonWhitespace(localeKey)) {
@@ -96,10 +98,10 @@ public class I18nWebService {
 		}
 		
 		if(locale == null) {
-			locale = I18nModule.getDefaultLocale();
+			locale = i18nModule.getDefaultLocale();
 		}
 		
-		boolean overlayEnabled = I18nModule.isOverlayEnabled();
+		boolean overlayEnabled = i18nModule.isOverlayEnabled();
 		String val = i18n.getLocalizedString(packageName, key, EMPTY_ARRAY, locale, overlayEnabled, true);
 		return Response.ok(val).build();
 	}
diff --git a/src/main/java/org/olat/restapi/system/NotificationsAdminWebService.java b/src/main/java/org/olat/restapi/system/NotificationsAdminWebService.java
index a75227d390b..d6eb54c5816 100644
--- a/src/main/java/org/olat/restapi/system/NotificationsAdminWebService.java
+++ b/src/main/java/org/olat/restapi/system/NotificationsAdminWebService.java
@@ -33,8 +33,8 @@ import org.olat.core.CoreSpringFactory;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.restapi.system.vo.NotificationsStatus;
-import org.quartz.JobDetail;
 import org.quartz.JobExecutionContext;
+import org.quartz.JobKey;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
 
@@ -46,6 +46,8 @@ public class NotificationsAdminWebService {
 	
 	private static final OLog log = Tracing.createLoggerFor(NotificationsAdminWebService.class);
 	
+	private final JobKey notificationsJobKey = new JobKey("org.olat.notifications.job.enabled", Scheduler.DEFAULT_GROUP);
+	
 	/**
 	 * Return the status of the notifications job: running, stopped
    * @response.representation.200.mediaType application/xml, application/json
@@ -77,10 +79,9 @@ public class NotificationsAdminWebService {
 	private String getJobStatus() {
 		try {
 			Scheduler scheduler = CoreSpringFactory.getImpl(Scheduler.class);
-			@SuppressWarnings("unchecked")
 			List<JobExecutionContext> jobs = scheduler.getCurrentlyExecutingJobs();
 			for(JobExecutionContext job:jobs) {
-				if("org.olat.notifications.job.enabled".equals(job.getJobDetail().getName())) {
+				if("org.olat.notifications.job.enabled".equals(job.getJobDetail().getKey().getName())) {
 					return "running";
 				}
 			}
@@ -103,9 +104,7 @@ public class NotificationsAdminWebService {
 	public Response setStatus(@FormParam("status") String status) {
 		if("running".equals(status)) {
 			try {
-				Scheduler scheduler = CoreSpringFactory.getImpl(Scheduler.class);
-				JobDetail detail = scheduler.getJobDetail("org.olat.notifications.job.enabled", Scheduler.DEFAULT_GROUP);
-				scheduler.triggerJob(detail.getName(), detail.getGroup());
+				CoreSpringFactory.getImpl(Scheduler.class).triggerJob(notificationsJobKey);
 			} catch (SchedulerException e) {
 				log.error("", e);
 			}
diff --git a/src/main/java/org/olat/search/service/SearchServiceImpl.java b/src/main/java/org/olat/search/service/SearchServiceImpl.java
index b1fe565851f..6d886142b7e 100644
--- a/src/main/java/org/olat/search/service/SearchServiceImpl.java
+++ b/src/main/java/org/olat/search/service/SearchServiceImpl.java
@@ -80,6 +80,7 @@ import org.olat.search.service.indexer.MainIndexer;
 import org.olat.search.service.searcher.JmsSearchProvider;
 import org.olat.search.service.spell.SearchSpellChecker;
 import org.quartz.JobDetail;
+import org.quartz.JobKey;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
 
@@ -90,6 +91,8 @@ import org.quartz.SchedulerException;
 public class SearchServiceImpl implements SearchService, GenericEventListener {
 	private static final OLog log = Tracing.createLoggerFor(SearchServiceImpl.class);
 	
+	private final JobKey indexerJobKey = new JobKey("org.olat.search.job.enabled", Scheduler.DEFAULT_GROUP);
+	
 	private Index indexer;	
 	private SearchModule searchModuleConfig;
 	private MainIndexer mainIndexer;
@@ -180,13 +183,13 @@ public class SearchServiceImpl implements SearchService, GenericEventListener {
 		if (indexer==null) throw new AssertException ("Try to call startIndexing() but indexer is null");
 		
 		try {
-			JobDetail detail = scheduler.getJobDetail("org.olat.search.job.enabled", Scheduler.DEFAULT_GROUP);
+			JobDetail detail = scheduler.getJobDetail(indexerJobKey);
 			if(detail == null) {
 				if("disabled".equals(indexerCron)) {
 					indexer.startFullIndex();
 				}
 			} else {
-				scheduler.triggerJob(detail.getName(), detail.getGroup());
+				scheduler.triggerJob(indexerJobKey);
 			}
 			log.info("startIndexing...");
 		} catch (SchedulerException e) {
@@ -202,13 +205,13 @@ public class SearchServiceImpl implements SearchService, GenericEventListener {
 		if (indexer==null) throw new AssertException ("Try to call stopIndexing() but indexer is null");
 
 		try {
-			JobDetail detail = scheduler.getJobDetail("org.olat.search.job.enabled", Scheduler.DEFAULT_GROUP);
+			JobDetail detail = scheduler.getJobDetail(indexerJobKey);
 			if(detail == null) {
 				if("disabled".equals(indexerCron)) {
 					indexer.stopFullIndex();
 				}
 			} else {
-				scheduler.interrupt(detail.getName(), detail.getGroup());
+				scheduler.interrupt(indexerJobKey);
 			}
 			log.info("stopIndexing.");
 		} catch (SchedulerException e) {
@@ -243,8 +246,7 @@ public class SearchServiceImpl implements SearchService, GenericEventListener {
 
 		if (startingFullIndexingAllowed()) {
 			try {
-				JobDetail detail = scheduler.getJobDetail("org.olat.search.job.enabled", Scheduler.DEFAULT_GROUP);
-				scheduler.triggerJob(detail.getName(), detail.getGroup());
+				scheduler.triggerJob(indexerJobKey);
 			} catch (SchedulerException e) {
 				log.error("", e);
 			}
diff --git a/src/main/java/org/olat/user/ChangePrefsController.java b/src/main/java/org/olat/user/ChangePrefsController.java
index f5c493e634e..0d1bd3f44c0 100644
--- a/src/main/java/org/olat/user/ChangePrefsController.java
+++ b/src/main/java/org/olat/user/ChangePrefsController.java
@@ -52,7 +52,7 @@ import org.olat.core.id.context.HistoryModule;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.UserSession;
 import org.olat.core.util.WebappHelper;
-import org.olat.core.util.i18n.I18nManager;
+import org.olat.core.util.i18n.I18nModule;
 import org.olat.core.util.prefs.Preferences;
 import org.olat.core.util.prefs.PreferencesFactory;
 import org.olat.core.util.session.UserSessionManager;
@@ -296,11 +296,13 @@ class UserPrefsResetForm extends FormBasicController {
 	private MultipleSelectionElement resetElements;
 	private String[] keys, values;
 
-	private final UserSessionManager sessionManager;
+	@Autowired
+	private I18nModule i18nModule;
+	@Autowired
+	private UserSessionManager sessionManager;
 	
 	public UserPrefsResetForm(UserRequest ureq, WindowControl wControl, Identity changeableIdentity) {
 		super(ureq, wControl);
-		sessionManager = CoreSpringFactory.getImpl(UserSessionManager.class);
 		tobeChangedIdentity = changeableIdentity;
 		initForm(ureq);
 	}
@@ -363,7 +365,7 @@ class UserPrefsResetForm extends FormBasicController {
 			
 			if(logout) {
 				//if logout, need a redirect to the login page
-				String lang = I18nManager.getInstance().getLocaleKey(ureq.getLocale());
+				String lang = i18nModule.getLocaleKey(ureq.getLocale());
 				ureq.getDispatchResult().setResultingMediaResource(
 						new RedirectMediaResource(WebappHelper.getServletContextPath() + "/dmz/?lang=" + lang + "&logout=true"));
 			}
diff --git a/src/main/java/org/olat/user/PreferencesFormController.java b/src/main/java/org/olat/user/PreferencesFormController.java
index 76ef2677b9f..981570a7e58 100644
--- a/src/main/java/org/olat/user/PreferencesFormController.java
+++ b/src/main/java/org/olat/user/PreferencesFormController.java
@@ -50,6 +50,7 @@ import org.olat.core.util.Util;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
 import org.olat.core.util.mail.MailModule;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * This form controller provides an interface to change the user's system
@@ -70,6 +71,9 @@ public class PreferencesFormController extends FormBasicController {
 	private Identity tobeChangedIdentity;
 	private SingleSelection language, fontsize, charset, notificationInterval, mailSystem;
 	private static final String[] mailIntern = new String[]{"intern.only","send.copy"};
+	
+	@Autowired
+	private I18nModule i18nModule;
 
 	/**
 	 * Constructor for the user preferences form
@@ -193,7 +197,7 @@ public class PreferencesFormController extends FormBasicController {
 		String langKey = prefs.getLanguage();
 		// Preselect the users language if available. Maye not anymore enabled on
 		// this server
-		if (prefs.getLanguage() != null && I18nModule.getEnabledLanguageKeys().contains(langKey)) {
+		if (prefs.getLanguage() != null && i18nModule.getEnabledLanguageKeys().contains(langKey)) {
 			language.select(prefs.getLanguage(), true);
 		} else {
 			language.select(I18nModule.getDefaultLocale().toString(), true);
diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_en.properties
index 86b7a6f281c..26632eae883 100644
--- a/src/main/java/org/olat/user/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/user/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Thu Sep 03 11:09:03 CEST 2015
+#Thu Aug 03 10:54:35 CEST 2017
 Failed=File upload failed.
 NoImage=This file format cannot be uploaded as image.
 ULLimitExceeded=Your image must not exceed {0} kByte.
@@ -65,7 +65,7 @@ interval.two-hourly=Every two hours
 interval.weekly=Weekly
 landing.pages=Landing page
 logo.header=Enterprise logo (Formats .jpg .jpeg .png .gif only)
-logo.select=$:ul.select
+logo.select=$\:ul.select
 mail.intern.only=Send e-mails to the OpenOLAT internal inbox
 mail.send.copy=Send e-mails to the OpenOLAT internal inbox and the address {0}
 mail.system=E-mail delivery
diff --git a/src/test/java/org/olat/core/commons/services/scheduler/SchedulerTest.java b/src/test/java/org/olat/core/commons/services/scheduler/SchedulerTest.java
index 33dbdb7d6c6..6d0a9d0ac8f 100644
--- a/src/test/java/org/olat/core/commons/services/scheduler/SchedulerTest.java
+++ b/src/test/java/org/olat/core/commons/services/scheduler/SchedulerTest.java
@@ -25,19 +25,22 @@
 */
 package org.olat.core.commons.services.scheduler;
 
-import static org.junit.Assert.assertEquals;
+import static org.quartz.JobBuilder.newJob;
 
 import java.text.ParseException;
 import java.util.Calendar;
 import java.util.Date;
 
+import org.junit.Assert;
 import org.junit.Test;
 import org.olat.test.OlatTestCase;
 import org.quartz.JobDetail;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
+import org.quartz.TriggerUtils;
+import org.quartz.spi.OperableTrigger;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.quartz.SimpleTriggerBean;
+import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;
 
 /**
  * Description:<br>
@@ -53,8 +56,11 @@ public class SchedulerTest extends OlatTestCase {
 	
 	@Test
 	public void testSimpleTrigger() throws SchedulerException, ParseException {
-		JobDetail job = new JobDetail("schedulerTestJobSimpleTrigger", Scheduler.DEFAULT_GROUP, SchedulerTestJob.class);
-		SimpleTriggerBean trigger = new SimpleTriggerBean();
+		JobDetail job = newJob(SchedulerTestJob.class)
+				.withIdentity("schedulerTestJobSimpleTrigger", Scheduler.DEFAULT_GROUP)
+				.build();
+
+		SimpleTriggerFactoryBean trigger = new SimpleTriggerFactoryBean();
 		trigger.setName("Test scheduler trigger");
 		trigger.setStartDelay(0);
 		trigger.setRepeatInterval(1000);
@@ -62,14 +68,17 @@ public class SchedulerTest extends OlatTestCase {
 		trigger.setJobDetail(job);
 		trigger.afterPropertiesSet();
 		// Schedule job now
-		scheduler.scheduleJob(job, trigger);
+		scheduler.scheduleJob(job, trigger.getObject());
+		
+		sleep(20);//because of cal.add(Calendar.MILLISECOND, 11);
 
-		//check next time
+		//check number of calls to the job
+		org.quartz.Calendar quartzCal = scheduler.getCalendar(trigger.getObject().getCalendarName());
 		Calendar cal = Calendar.getInstance();
 		Date start = cal.getTime();
 		cal.add(Calendar.SECOND, 5);
-		cal.add(Calendar.MILLISECOND, 011);
+		cal.add(Calendar.MILLISECOND, 11);
 		Date end = cal.getTime();
-		assertEquals(5, trigger.computeNumTimesFiredBetween(start, end));
+		Assert.assertEquals(5, TriggerUtils.computeFireTimesBetween((OperableTrigger)trigger.getObject(), quartzCal, start, end).size());
 	}
 }
diff --git a/src/test/java/org/olat/core/util/i18n/I18nTest.java b/src/test/java/org/olat/core/util/i18n/I18nTest.java
index e98b518ca21..1c3965a469a 100644
--- a/src/test/java/org/olat/core/util/i18n/I18nTest.java
+++ b/src/test/java/org/olat/core/util/i18n/I18nTest.java
@@ -77,6 +77,8 @@ public class I18nTest extends OlatTestCase {
 	@Autowired
 	private I18nManager i18nMgr;
 	@Autowired
+	private I18nModule i18nModule;
+	@Autowired
 	private TranslationDevManager tDMgr;
 	private static final String testSourceBundle =  "org.olat.core.util.i18n.junittestdata.devtools.source";
 	private static final String testTargetBundle =  "org.olat.core.util.i18n.junittestdata.devtools.target";
@@ -95,7 +97,7 @@ public class I18nTest extends OlatTestCase {
 	public void tearDown() throws Exception {
 		String testNewBundle =  "org.olat.core.util.i18n.junittestdata.new";
 		Locale testLocale = i18nMgr.getLocaleOrDefault("de");
-		File baseDir = I18nModule.getPropertyFilesBaseDir(testLocale, testNewBundle);
+		File baseDir = i18nModule.getPropertyFilesBaseDir(testLocale, testNewBundle);
 		// only delete files when basedir available
 		if (baseDir == null) return;
 		File testFile = i18nMgr.getPropertiesFile(testLocale, testNewBundle, baseDir);
@@ -129,17 +131,17 @@ public class I18nTest extends OlatTestCase {
 		Locale testLocale = i18nMgr.getLocaleOrDefault("de");
 		// cleanup devtools source/target files
 		// 1) source files
-		File baseDir = I18nModule.getPropertyFilesBaseDir(testLocale, testSourceBundle);
+		File baseDir = i18nModule.getPropertyFilesBaseDir(testLocale, testSourceBundle);
 		File testSFile = i18nMgr.getPropertiesFile(testLocale, testSourceBundle, baseDir);
 		File sourcePath = testSFile.getParentFile().getParentFile();
 		FileUtils.deleteDirsAndFiles(sourcePath, true, true);
 		// 2) target files
-		baseDir = I18nModule.getPropertyFilesBaseDir(testLocale, testTargetBundle);
+		baseDir = i18nModule.getPropertyFilesBaseDir(testLocale, testTargetBundle);
 		File testTFile = i18nMgr.getPropertiesFile(testLocale, testTargetBundle, baseDir);
 		File targetPath = testTFile.getParentFile().getParentFile();
 		FileUtils.deleteDirsAndFiles(targetPath, true, true);
 		// 3) move target files
-		baseDir = I18nModule.getPropertyFilesBaseDir(testLocale, testMoveTargetBundle);
+		baseDir = i18nModule.getPropertyFilesBaseDir(testLocale, testMoveTargetBundle);
 		File testMFile = i18nMgr.getPropertiesFile(testLocale, testMoveTargetBundle, baseDir);
 		File movePath = testMFile.getParentFile().getParentFile().getParentFile();
 		FileUtils.deleteDirsAndFiles(movePath, true, true);
@@ -150,7 +152,7 @@ public class I18nTest extends OlatTestCase {
 		// set languages that is used as reference: all keys there are the keys should not to be deleted
 		String[] referenceLanguages = new String[]{"de", "en"};
 		// set the languages that should be cleaned up
-		Set<String> targetLanguages = I18nModule.getTranslatableLanguageKeys();
+		Set<String> targetLanguages = i18nModule.getTranslatableLanguageKeys();
 		//Set<String> targetLanguages = new HashSet<String>();
 		//targetLanguages.add("en");
 		tDMgr.removeDeletedKeys(false, referenceLanguages, targetLanguages);		
@@ -158,7 +160,7 @@ public class I18nTest extends OlatTestCase {
 	
 
 	@Test public void testMoveKeyTask() {
-		if (I18nModule.isTransToolEnabled()) {
+		if (i18nModule.isTransToolEnabled()) {
 			prepareDevToolTests();
 			Locale testLocale = i18nMgr.getLocaleOrDefault("de");
 			String ktm = "key.to.move";
@@ -182,38 +184,35 @@ public class I18nTest extends OlatTestCase {
 			//check for changed references in value
 			//if correctly done, should still be resolvable
 			assertTrue(sourcePropResolved.getProperty("key.to.stay2").indexOf(matchString)!=-1);
-			tDMgr.logToFile("moveKey");
 		}
 	}
 	
 	@Test public void testMovePackageTask(){
-		if (I18nModule.isTransToolEnabled()) {
+		if (i18nModule.isTransToolEnabled()) {
 			prepareDevToolTests();
 			tDMgr.movePackageTask(testSourceBundle, testTargetBundle);
 			i18nMgr.clearCaches();
 			Properties sourceProp = i18nMgr.getPropertiesWithoutResolvingRecursively(null, testSourceBundle);
 			assertTrue(sourceProp.isEmpty());
 			Properties targetProp = i18nMgr.getPropertiesWithoutResolvingRecursively(null, testTargetBundle);
-			assertFalse(targetProp.isEmpty());		
-			tDMgr.logToFile("movePackage");
+			assertFalse(targetProp.isEmpty());
 		}
 	}
 	
 	@Test public void testMovePackageByMovingSingleKeysTask(){
-		if (I18nModule.isTransToolEnabled()) {
+		if (i18nModule.isTransToolEnabled()) {
 			prepareDevToolTests();
 			tDMgr.movePackageByMovingSingleKeysTask(testSourceBundle, testTargetBundle);
 			i18nMgr.clearCaches();
 			Properties sourceProp = i18nMgr.getPropertiesWithoutResolvingRecursively(null, testSourceBundle);
 			assertTrue(sourceProp.isEmpty());
 			Properties targetProp = i18nMgr.getPropertiesWithoutResolvingRecursively(null, testTargetBundle);
-			assertFalse(targetProp.isEmpty());		
-			tDMgr.logToFile("movePackageSingle");
+			assertFalse(targetProp.isEmpty());
 		}
 	}
 	
 	@Test public void testMergePackageTask(){
-		if (I18nModule.isTransToolEnabled()) {
+		if (i18nModule.isTransToolEnabled()) {
 			prepareDevToolTests();
 			tDMgr.mergePackageTask(testSourceBundle, testTargetBundle);
 			i18nMgr.clearCaches();
@@ -224,7 +223,7 @@ public class I18nTest extends OlatTestCase {
 	}
 	
 	@Test public void testRenameLanguageTask(){
-		if (I18nModule.isTransToolEnabled()) {
+		if (i18nModule.isTransToolEnabled()) {
 			prepareDevToolTests();
 			// create source
 			Locale xxLocale = new Locale("xx");		
@@ -256,9 +255,9 @@ public class I18nTest extends OlatTestCase {
 	}
 	
 	@Test public void testMoveLanguageTask(){
-		if (I18nModule.isTransToolEnabled()) {
+		if (i18nModule.isTransToolEnabled()) {
 			prepareDevToolTests();
-			String srcPath = I18nModule.getTransToolApplicationLanguagesSrcDir().getAbsolutePath() + "/../../test/java/org/olat/core/util/i18n/junittestdata/devtools";
+			String srcPath = i18nModule.getTransToolApplicationLanguagesSrcDir().getAbsolutePath() + "/../../test/java/org/olat/core/util/i18n/junittestdata/devtools";
 			String targetPath = srcPath + "/../movetarget";
 			//only copy: target should exist
 			Locale mvLocale = i18nMgr.getLocaleOrDefault("de");
@@ -287,30 +286,26 @@ public class I18nTest extends OlatTestCase {
 	//remove after execution!
 	@Test
 	public void testRemoveXKeyTask(){
-		tDMgr.removeXKeysTask(false);		
-		tDMgr.logToFile("XKeys");
+		tDMgr.removeXKeysTask(false);
 	}
 	
 	//remove after execution!
 	@Test
 	public void testRemoveTodoKeyTask(){
 		tDMgr.removeTodoKeysTask(false);
-		tDMgr.logToFile("todoKeys");
 	}
 	
 	//remove after execution!
 	@Test
 	public void testRemoveEmptyKeysTask(){
 		tDMgr.removeEmptyKeysTask(false);
-		tDMgr.logToFile("emptyKeys");
 	}
 	
 	//remove after execution!	
 	@Test
 	public void testRemoveReferenceLanguageCopiesTask(){
-		if (I18nModule.isTransToolEnabled()) {
-			tDMgr.removeReferenceLanguageCopiesTask(false);
-			tDMgr.logToFile("refLangCopied");			
+		if (i18nModule.isTransToolEnabled()) {
+			tDMgr.removeReferenceLanguageCopiesTask(false);		
 		}
 	}
 
@@ -318,11 +313,11 @@ public class I18nTest extends OlatTestCase {
 	 * Test method i18nManager.searchForAvailableLanguages()
 	 */
 	@Test public void testSearchForAvailableLanguages() {
-		if (I18nModule.isTransToolEnabled()) {
+		if (i18nModule.isTransToolEnabled()) {
 			// Try to load i18n files and a jar from the testdata dir
-			File testDataDir = new File(I18nModule.getTransToolApplicationLanguagesSrcDir(), "/../../test/java/org/olat/core/util/i18n/junittestdata/");
+			File testDataDir = new File(i18nModule.getTransToolApplicationLanguagesSrcDir(), "/../../test/java/org/olat/core/util/i18n/junittestdata/");
 			assertTrue(testDataDir.exists());
-			Set<String> foundLanguages = i18nMgr.searchForAvailableLanguages(testDataDir);
+			Set<String> foundLanguages = i18nModule.searchForAvailableLanguages(testDataDir);
 			// Set must contain some LocalStrings file:
 			assertTrue(foundLanguages.contains("de"));
 			assertTrue(foundLanguages.contains("en"));
@@ -333,7 +328,7 @@ public class I18nTest extends OlatTestCase {
 			// Final check
 			assertEquals(6, foundLanguages.size());
 		} else {
-			Set<String> foundLanguages = I18nModule.getAvailableLanguageKeys();
+			Set<String> foundLanguages = i18nModule.getAvailableLanguageKeys();
 			// Set must contain some LocaleStrings from the jar package
 			assertTrue(foundLanguages.contains("fr"));
 			assertTrue(foundLanguages.contains("zh_CN"));			
@@ -345,7 +340,7 @@ public class I18nTest extends OlatTestCase {
 	 */
 	@Test public void testSearchForBundleNamesContainingI18nFiles() {
 		long start = System.currentTimeMillis();
-		List<String> foundBundles = i18nMgr.searchForBundleNamesContainingI18nFiles();
+		List<String> foundBundles = i18nModule.searchForBundleNamesContainingI18nFiles();
 		long end = System.currentTimeMillis();
 		log.info("Searching for " + foundBundles.size() + " bundles on OLAT source path took me " + (end-start) + "ms", "testSearchForBundleNamesContainingI18nFiles");
 		// Must contain packages from core
@@ -361,7 +356,7 @@ public class I18nTest extends OlatTestCase {
 	 * Test method i18nManager.buildI18nFilename()
 	 */
 	@Test public void testBuildI18nFilename() {
-		String overlay = I18nModule.getOverlayName();
+		String overlay = i18nModule.getOverlayName();
 		String testFileName = i18nMgr.buildI18nFilename(new Locale("de"));
 		assertEquals("LocalStrings_de.properties", testFileName);
 		testFileName = i18nMgr.buildI18nFilename(new Locale("de","","__" + overlay));
@@ -386,9 +381,9 @@ public class I18nTest extends OlatTestCase {
 		locale = i18nMgr.getLocaleOrDefault("xy");
 		assertEquals(I18nModule.getDefaultLocale(), locale);		
 		// Test trying to get overlay via getLocale method which should not return the overlay
-		Locale overlay = i18nMgr.getLocaleOrDefault("de__" + I18nModule.getOverlayName());
+		Locale overlay = i18nMgr.getLocaleOrDefault("de__" + i18nModule.getOverlayName());
 		assertEquals(I18nModule.getDefaultLocale(), overlay);
-		overlay = i18nMgr.getLocaleOrDefault("zh_CN__" + I18nModule.getOverlayName());
+		overlay = i18nMgr.getLocaleOrDefault("zh_CN__" + i18nModule.getOverlayName());
 		assertEquals(I18nModule.getDefaultLocale(), overlay);
 	}
 
@@ -397,25 +392,25 @@ public class I18nTest extends OlatTestCase {
 	 */	
 	@Test public void testCreateLocale() {
 		// standard locale
-		Locale loc = i18nMgr.createLocale("de");
+		Locale loc = i18nModule.createLocale("de");
 		assertNotNull(loc);
 		assertEquals("de",loc.getLanguage());
 		assertEquals("",loc.getCountry());
 		assertEquals("",loc.getVariant());
 		// with country
-		loc = i18nMgr.createLocale("de_CH");
+		loc = i18nModule.createLocale("de_CH");
 		assertNotNull(loc);
 		assertEquals("de", loc.getLanguage());
 		assertEquals("CH", loc.getCountry());
 		assertEquals("", loc.getVariant());
 		// with variant
-		loc = i18nMgr.createLocale("de_CH_ZH");
+		loc = i18nModule.createLocale("de_CH_ZH");
 		assertNotNull(loc);
 		assertEquals("de", loc.getLanguage());
 		assertEquals("CH", loc.getCountry());
 		assertEquals("ZH", loc.getVariant());
 		// with variant but no country
-		loc = i18nMgr.createLocale("de__VENDOR");
+		loc = i18nModule.createLocale("de__VENDOR");
 		assertNotNull(loc);
 		assertEquals("de", loc.getLanguage());
 		assertEquals("", loc.getCountry());
@@ -423,21 +418,21 @@ public class I18nTest extends OlatTestCase {
 		//
 		// With overlay
 		// with language
-		String overlay = I18nModule.getOverlayName();
-		loc = i18nMgr.createLocale("de");
-		Locale over = i18nMgr.createOverlay(loc);
+		String overlay = i18nModule.getOverlayName();
+		loc = i18nModule.createLocale("de");
+		Locale over = i18nModule.createOverlay(loc);
 		assertEquals("de____" + overlay, over.toString()); 
-		assertEquals(i18nMgr.createOverlayKeyForLanguage(loc.toString()), i18nMgr.getLocaleKey(over)); 
+		assertEquals(i18nModule.createOverlayKeyForLanguage(loc.toString()), i18nModule.getLocaleKey(over)); 
 		// with country
-		loc = i18nMgr.createLocale("de_CH");
-		over = i18nMgr.createOverlay(loc);
+		loc = i18nModule.createLocale("de_CH");
+		over = i18nModule.createOverlay(loc);
 		assertEquals("de_CH___" + overlay, over.toString()); 
-		assertEquals(i18nMgr.createOverlayKeyForLanguage(loc.toString()), i18nMgr.getLocaleKey(over)); 
+		assertEquals(i18nModule.createOverlayKeyForLanguage(loc.toString()), i18nModule.getLocaleKey(over)); 
 		// with variant
-		loc = i18nMgr.createLocale("de_CH_ZH");
-		over = i18nMgr.createOverlay(loc);
+		loc = i18nModule.createLocale("de_CH_ZH");
+		over = i18nModule.createOverlay(loc);
 		assertEquals("de_CH_ZH__" + overlay, over.toString()); 
-		assertEquals(i18nMgr.createOverlayKeyForLanguage(loc.toString()), i18nMgr.getLocaleKey(over)); 
+		assertEquals(i18nModule.createOverlayKeyForLanguage(loc.toString()), i18nModule.getLocaleKey(over)); 
 	}
 	
 	/**
@@ -454,8 +449,8 @@ public class I18nTest extends OlatTestCase {
 	 * Test methods i18nManager.getLanguageTranslated() i18nManager.getLanguageInEnglish()
 	 */
 	@Test public void testGetPropertyFile() {
-		if (I18nModule.isTransToolEnabled()) {
-			File baseDir = I18nModule.getPropertyFilesBaseDir(i18nMgr.getLocaleOrDefault("de"), "org.olat.core");
+		if (i18nModule.isTransToolEnabled()) {
+			File baseDir = i18nModule.getPropertyFilesBaseDir(i18nMgr.getLocaleOrDefault("de"), "org.olat.core");
 			assertNotNull(baseDir);
 			File file = i18nMgr.getPropertiesFile(i18nMgr.getLocaleOrDefault("de"), "org.olat.core", baseDir);
 			assertTrue(file.exists());
@@ -486,7 +481,7 @@ public class I18nTest extends OlatTestCase {
 		// test with non existing files
 		String testNewBundle =  "org.olat.core.util.i18n.junittestdata.new";
 		Locale testLocale = i18nMgr.getLocaleOrDefault("de");
-		File baseDir = I18nModule.getPropertyFilesBaseDir(testLocale, testNewBundle);
+		File baseDir = i18nModule.getPropertyFilesBaseDir(testLocale, testNewBundle);
 		File testFile = i18nMgr.getPropertiesFile(testLocale, testNewBundle, baseDir);
 		// clean first existing files from previous broken testcase
 		if (testFile.exists()) {
@@ -580,11 +575,11 @@ public class I18nTest extends OlatTestCase {
 	 */
 	@Ignore
 	@Test public void testCountI18nItemsAndBundles() {
-		I18nModule.initBundleNames(); // remove dirty stuff from previous tests
-		int bundleCounter = I18nModule.getBundleNamesContainingI18nFiles().size();
+		i18nModule.initBundleNames(); // remove dirty stuff from previous tests
+		int bundleCounter = i18nModule.getBundleNamesContainingI18nFiles().size();
 		String testNewBundle =  "org.olat.core.util.i18n.junittestdata.new";
 		Locale testLocale = i18nMgr.getLocaleOrDefault("de");
-		File baseDir = I18nModule.getPropertyFilesBaseDir(testLocale, testNewBundle);
+		File baseDir = i18nModule.getPropertyFilesBaseDir(testLocale, testNewBundle);
 		File testFile = i18nMgr.getPropertiesFile(testLocale, testNewBundle, baseDir);
 		// clean first existing files from previous broken testcase
 		if (testFile.exists()) {
@@ -598,7 +593,7 @@ public class I18nTest extends OlatTestCase {
 		i18nMgr.saveOrUpdateProperties(props, testLocale, testNewBundle);
 		assertEquals(2, i18nMgr.countI18nItems(testLocale, testNewBundle, false));
 		assertEquals(0, i18nMgr.countI18nItems(i18nMgr.getLocaleOrDefault("en"), testNewBundle, false));
-		assertEquals(bundleCounter + 1, I18nModule.getBundleNamesContainingI18nFiles().size());
+		assertEquals(bundleCounter + 1, i18nModule.getBundleNamesContainingI18nFiles().size());
 		// test all bundles
 		int allCount = i18nMgr.countI18nItems(testLocale, null, true);
 		assertEquals(allCount, i18nMgr.countI18nItems(testLocale, null, false));
@@ -607,7 +602,7 @@ public class I18nTest extends OlatTestCase {
 		assertEquals(allCount-1, i18nMgr.countI18nItems(testLocale, null, false));
 		i18nMgr.deleteProperties(testLocale, testNewBundle);
 		assertEquals(allCount-2, i18nMgr.countI18nItems(testLocale, null, false));
-		assertEquals(bundleCounter, I18nModule.getBundleNamesContainingI18nFiles().size());
+		assertEquals(bundleCounter, i18nModule.getBundleNamesContainingI18nFiles().size());
 		// count bundles tests
 		assertEquals(0, i18nMgr.countBundles("org.olat.core.util.i18n.nonexisting", true));
 		assertEquals(1, i18nMgr.countBundles("org.olat.core.util.i18n.ui", true));
diff --git a/src/test/java/org/olat/resource/accesscontrol/ACReservationDAOTest.java b/src/test/java/org/olat/resource/accesscontrol/ACReservationDAOTest.java
index 312b24fe930..7058754d1c7 100644
--- a/src/test/java/org/olat/resource/accesscontrol/ACReservationDAOTest.java
+++ b/src/test/java/org/olat/resource/accesscontrol/ACReservationDAOTest.java
@@ -35,6 +35,7 @@ import org.olat.resource.OLATResource;
 import org.olat.resource.accesscontrol.manager.ACReservationDAO;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.OlatTestCase;
+import org.quartz.JobKey;
 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -57,7 +58,7 @@ public class ACReservationDAOTest extends OlatTestCase  {
 	@Before
 	public void interruptReservationJob() {	
 		try {
-			scheduler.pauseJob("acReservationCleanupJobDetail", Scheduler.DEFAULT_GROUP);
+			scheduler.pauseJob(new JobKey("acReservationCleanupJobDetail", Scheduler.DEFAULT_GROUP));
 		} catch (SchedulerException e) {
 			log.error("Cannot intterupt the reservation job.", e);
 		}
-- 
GitLab