diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 803eb5f..db12be0 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -37,6 +37,83 @@ class ApplicationController < ActionController::Base
   end
   
   before_filter :user_setup, :check_if_login_required, :set_localization
+
+  before_filter :maybe_return_cached_page
+
+  # return 0 if the page is not cacheable, 
+  # the cache refresh rate otherwise
+  def page_cache_refresh
+    if User.current.logged?
+      return 0
+    else
+      cache_refresh = Setting.cache_refresh_rate_in_minutes.to_i
+      if cache_refresh.nil?
+        return 0
+      else
+        return cache_refresh.to_i
+      end
+    end
+  end
+ 
+  # return the two keys to use for retrieving in the cache 
+  # the page content and page timestamp.
+  def request_cache_key
+    l = "page__" + I18n.locale.to_s + "__"
+    return l  + request.path, l + "t__" + request.path
+  end
+  
+  # return the cached page
+  def maybe_return_cached_page 
+    cache_refresh = page_cache_refresh
+    if cache_refresh > 0
+      cache = ActionController::Base.cache_store
+      key, key_t = request_cache_key
+      cache_timestamp = cache.read(key_t)
+      if ! cache_timestamp.nil?
+        now_timestamp = Time.now.to_i
+        if (now_timestamp - cache_timestamp) < (cache_refresh * 60)
+          logger.info('Return cached '  + key + ' with time stamp ' + cache_timestamp.to_s() + ".")
+          t = cache.read(key)
+          if ! t.nil?
+            render :text => t
+          end
+        end
+      end
+    end
+  end
+
+  after_filter :maybe_write_page_inside_cache
+
+  # cache the page
+  def maybe_write_page_inside_cache
+    cache_refresh = page_cache_refresh
+    if cache_refresh > 0
+      c = response.body
+      if page_can_be_cached(c)
+        cache = ActionController::Base.cache_store      
+        key, key_t = request_cache_key
+        cache.write(key, c)
+        cache.write(key_t, Time.now.to_i)
+        logger.info('Wrote ' + key + " in the cache, using " + cache.class.name + " cache method.")
+      end
+    end
+  end
+
+  # return false if it can not be cached. 
+  # For example forms with authenticity_token can not be cached
+  # because they must be uniquely generated for each request. 
+  def page_can_be_cached(c)
+    i = c.index('<form')    
+    if ! i.nil?
+      i = c.index('<input name="authenticity_token"', i)
+      if ! i.nil?
+        return false
+      end
+    end
+    return true
+  end
+
+
   filter_parameter_logging :password
   protect_from_forgery
   
diff --git a/app/views/settings/_general.rhtml b/app/views/settings/_general.rhtml
index a384693..f575f0a 100644
--- a/app/views/settings/_general.rhtml
+++ b/app/views/settings/_general.rhtml
@@ -22,6 +22,9 @@
 
 <p><%= setting_check_box :cache_formatted_text %></p>
 
+<p><%= setting_text_field :cache_refresh_rate_in_minutes, :size => 3 %> <%= l(:label_minute_plural) %><br/>
+<em><%= l(:text_cache_refresh_rate_in_minutes) %></em></p>
+
 <p><%= setting_select :wiki_compression, [['Gzip', 'gzip']], :blank => :label_none %></p>
 
 <p><%= setting_text_field :feeds_limit, :size => 6 %></p>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 727ad65..8d30bd8 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -362,6 +362,7 @@ en:
   setting_commit_logtime_enabled: Enable time logging
   setting_commit_logtime_activity_id: Activity for logged time
   setting_gantt_items_limit: Maximum number of items displayed on the gantt chart
+  setting_cache_refresh_rate_in_minutes: Refresh cached pages after
   
   permission_add_project: Create project
   permission_add_subprojects: Create subprojects
@@ -793,6 +794,7 @@ en:
   label_project_copy_notifications: Send email notifications during the project copy
   label_principal_search: "Search for user or group:"
   label_user_search: "Search for user:"
+  label_minute_plural: "minutes"
   
   button_login: Login
   button_submit: Submit
@@ -908,6 +910,7 @@ en:
   text_own_membership_delete_confirmation: "You are about to remove some or all of your permissions and may no longer be able to edit this project after that.\nAre you sure you want to continue?"
   text_zoom_in: Zoom in
   text_zoom_out: Zoom out
+  text_cache_refresh_rate_in_minutes: "Enable caching of pages, only for anonymous users. 0 for no caching. It uses the cache method specified in environment configuration." 
   
   default_role_manager: Manager
   default_role_developer: Developer
diff --git a/config/settings.yml b/config/settings.yml
index 6a9676a..bb3c505 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -196,3 +196,6 @@ default_notification_option:
   default: 'only_my_events'
 emails_header:
   default: ''
+cache_refresh_rate_in_minutes:
+  format: int
+  default: 0
\ No newline at end of file
