diff --git a/Gemfile.lock b/Gemfile.lock
index 15786cb000edefde9fd50846e1fd44775b57a36b..811b94e607e94e976fb46b49e72c27aab6e8d593 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -100,10 +100,10 @@ GEM
       activerecord (>= 3.2, < 8.0)
       rake (>= 10.4, < 14.0)
     ast (2.4.2)
-    autoprefixer-rails (10.4.13.0)
+    autoprefixer-rails (10.4.15.0)
       execjs (~> 2)
     aws-eventstream (1.2.0)
-    aws-partitions (1.809.0)
+    aws-partitions (1.819.0)
     aws-sdk-core (3.181.0)
       aws-eventstream (~> 1, >= 1.0.2)
       aws-partitions (~> 1, >= 1.651.0)
@@ -112,7 +112,7 @@ GEM
     aws-sdk-kms (1.71.0)
       aws-sdk-core (~> 3, >= 3.177.0)
       aws-sigv4 (~> 1.1)
-    aws-sdk-s3 (1.133.0)
+    aws-sdk-s3 (1.134.0)
       aws-sdk-core (~> 3, >= 3.181.0)
       aws-sdk-kms (~> 1)
       aws-sigv4 (~> 1.6)
@@ -172,9 +172,9 @@ GEM
       rexml
     csl-styles (2.0.1)
       csl (~> 2.0)
-    curation (1.10)
+    curation (1.11)
       htmlentities
-      metainspector (~> 5.12)
+      metainspector
       nokogiri
     date (3.3.3)
     delayed_job (4.1.11)
@@ -255,8 +255,8 @@ GEM
     gitlab (4.19.0)
       httparty (~> 0.20)
       terminal-table (>= 1.5.1)
-    globalid (1.1.0)
-      activesupport (>= 5.0)
+    globalid (1.2.1)
+      activesupport (>= 6.1)
     hal_openscience (0.1.0)
       json
       net-http
@@ -370,7 +370,7 @@ GEM
       rack (>= 1.2, < 4)
       snaky_hash (~> 2.0)
       version_gem (~> 1.1)
-    octokit (7.0.0)
+    octokit (7.1.0)
       faraday (>= 1, < 3)
       sawyer (~> 0.9)
     omniauth (2.1.1)
@@ -393,7 +393,7 @@ GEM
       racc
     pexels (0.5.0)
       requests (~> 1.0.2)
-    pg (1.5.3)
+    pg (1.5.4)
     popper_js (2.11.8)
     public_suffix (5.0.3)
     puma (6.3.1)
@@ -454,7 +454,7 @@ GEM
     roo (2.10.0)
       nokogiri (~> 1)
       rubyzip (>= 1.3.0, < 3.0.0)
-    rotp (6.2.2)
+    rotp (6.3.0)
     ruby-saml (1.15.0)
       nokogiri (>= 1.13.10)
       rexml
@@ -513,7 +513,7 @@ GEM
       hashie
       version_gem (~> 1.1, >= 1.1.1)
     spring (4.1.1)
-    sprockets (4.2.0)
+    sprockets (4.2.1)
       concurrent-ruby (~> 1.0)
       rack (>= 2.2.4, < 4)
     sprockets-rails (3.4.2)
@@ -550,7 +550,7 @@ GEM
     version_gem (1.1.3)
     warden (1.2.9)
       rack (>= 2.0.9)
-    web-console (4.2.0)
+    web-console (4.2.1)
       actionview (>= 6.0.0)
       activemodel (>= 6.0.0)
       bindex (>= 0.4.0)
@@ -559,7 +559,7 @@ GEM
       nokogiri (~> 1.6)
       rubyzip (>= 1.3.0)
       selenium-webdriver (~> 4.0, < 4.11)
-    webmock (3.18.1)
+    webmock (3.19.1)
       addressable (>= 2.8.0)
       crack (>= 0.3.2)
       hashdiff (>= 0.4.0, < 2.0.0)
diff --git a/app/models/communication/block.rb b/app/models/communication/block.rb
index 293d4d1388b3622b6fdf15a715aaf845a36fcf8a..bc8c2442744c3d38dd7c8141d1b264a6850eda7f 100644
--- a/app/models/communication/block.rb
+++ b/app/models/communication/block.rb
@@ -146,6 +146,10 @@ class Communication::Block < ApplicationRecord
     translation.save
   end
 
+  def full_text
+    template.full_text
+  end
+
   def to_s
     title.blank?  ? "#{Communication::Block.model_name.human} #{position}"
                   : "#{title}"
diff --git a/app/models/communication/block/component/base.rb b/app/models/communication/block/component/base.rb
index d6e26f46371c2a50736af186c3c3379256d12bf0..cf987455a0baefd501d0841f0e56950f353e6d4d 100644
--- a/app/models/communication/block/component/base.rb
+++ b/app/models/communication/block/component/base.rb
@@ -34,6 +34,10 @@ class Communication::Block::Component::Base
     # By default, does nothing. Specific cases are handled in their own definitions. (example: post)
   end
 
+  def full_text
+    ''
+  end
+
   def to_s
     self.class.to_s.demodulize
   end
diff --git a/app/models/communication/block/component/rich_text.rb b/app/models/communication/block/component/rich_text.rb
index 428b4bff02e81b87946183a2c1ef97f4c25add04..1f2e7f1afe5c2b4f91894b9d0dd1b0a802ecbaed 100644
--- a/app/models/communication/block/component/rich_text.rb
+++ b/app/models/communication/block/component/rich_text.rb
@@ -6,4 +6,8 @@ class Communication::Block::Component::RichText < Communication::Block::Componen
     @data = value
   end
 
+  def full_text
+    ActionController::Base.helpers.strip_tags data
+  end
+
 end
diff --git a/app/models/communication/block/component/string.rb b/app/models/communication/block/component/string.rb
index 2d4302f3a600742d583a8c77b18016c25680b929..6509381f276ccb452e6e56d5e03a845886911ab8 100644
--- a/app/models/communication/block/component/string.rb
+++ b/app/models/communication/block/component/string.rb
@@ -4,4 +4,8 @@ class Communication::Block::Component::String < Communication::Block::Component:
     @data = Osuny::Sanitizer.sanitize value, 'string'
   end
 
+  def full_text
+    data
+  end
+
 end
diff --git a/app/models/communication/block/component/text.rb b/app/models/communication/block/component/text.rb
index a5fdf576725700081e139019a11d568226790147..66db4f641734a098b436b30206d305c58e94d5a1 100644
--- a/app/models/communication/block/component/text.rb
+++ b/app/models/communication/block/component/text.rb
@@ -4,4 +4,8 @@ class Communication::Block::Component::Text < Communication::Block::Component::B
     @data = Osuny::Sanitizer.sanitize value, 'string'
   end
 
+  def full_text
+    data
+  end
+
 end
diff --git a/app/models/communication/block/heading.rb b/app/models/communication/block/heading.rb
index cbf44bb4f99c80d350c1f8b8ca74bbb853a9559e..770c78932f39ae8b87e8f21b892cb4ebaf59e542 100644
--- a/app/models/communication/block/heading.rb
+++ b/app/models/communication/block/heading.rb
@@ -75,6 +75,10 @@ class Communication::Block::Heading < ApplicationRecord
     end
   end
 
+  def full_text
+    to_s
+  end
+
   def to_s
     "#{title}"
   end
diff --git a/app/models/communication/block/template/base.rb b/app/models/communication/block/template/base.rb
index cd828e2b1e6a246f2816f3819a6a8cc188e304d6..b241d11b2582396184500e9e6d555370d5577f0d 100644
--- a/app/models/communication/block/template/base.rb
+++ b/app/models/communication/block/template/base.rb
@@ -126,6 +126,21 @@ class Communication::Block::Template::Base
     hash
   end
 
+  def full_text
+    unless @full_text
+      @full_text = ''
+      components.each do |component|
+        @full_text += "#{component.full_text}\r"
+      end
+      if has_element_class?
+        elements.each do |element|
+          @full_text += "#{element.full_text}\r"
+        end
+      end
+    end
+    @full_text
+  end
+
   def to_s
     self.class.to_s.demodulize
   end
diff --git a/app/models/concerns/with_blocks.rb b/app/models/concerns/with_blocks.rb
index 13778ae89d02bd85ed6ac86e03bb6fd9db45457c..4788d0812029145a4cd3fa83005c32a184dbfc39 100644
--- a/app/models/concerns/with_blocks.rb
+++ b/app/models/concerns/with_blocks.rb
@@ -14,11 +14,16 @@ module WithBlocks
       end
       headings.ordered.each do |heading|
         @contents << heading
+        @contents.concat heading.blocks
       end
     end
     @contents
   end
 
+  def contents_full_text
+    @contents_full_text ||= contents.collect(&:full_text).join("\r")
+  end
+
   # Basic rule is: TOC if 2 titles or more
   def show_toc?
     headings.many?
diff --git a/app/views/admin/communication/blocks/content/_static.html.erb b/app/views/admin/communication/blocks/content/_static.html.erb
index c6c34bcdedb28349592e0cf4d8b23e2ba99dc44e..8a05c6e6b4aa0e64472f2cd033632622f30d8b2e 100644
--- a/app/views/admin/communication/blocks/content/_static.html.erb
+++ b/app/views/admin/communication/blocks/content/_static.html.erb
@@ -1,6 +1,11 @@
 <%
 @university = about.university
+I18n.locale = about.language.iso_code if about.respond_to?(:language)
 %>
+contents_reading_time:
+  seconds: <%= about.contents_full_text.reading_time %>
+  text: >-
+    <%= distance_of_time_in_words(0, about.contents_full_text.reading_time) %>
 contents:
 <% about.blocks.without_heading.published.ordered.each do |block| %>
 <%= render 'admin/communication/blocks/static', block: block %>
diff --git a/app/views/admin/communication/blocks/content/_static.json.jbuilder b/app/views/admin/communication/blocks/content/_static.json.jbuilder
index 33c49fb9a21cb801cab0169a81a56dfccf411939..a965c87f5f3d6b28a062efe9eba13e050116d4a1 100644
--- a/app/views/admin/communication/blocks/content/_static.json.jbuilder
+++ b/app/views/admin/communication/blocks/content/_static.json.jbuilder
@@ -2,5 +2,6 @@ json.contents about.contents do |block_or_heading|
   if block_or_heading.is_a? Communication::Block
     json.partial! 'admin/communication/blocks/static', block: block_or_heading
   else
+    # TODO
   end
 end
\ No newline at end of file
diff --git a/config/initializers/string.rb b/config/initializers/string.rb
new file mode 100644
index 0000000000000000000000000000000000000000..bfa4450fc4bf1a126479c2e837c37a75aeba1287
--- /dev/null
+++ b/config/initializers/string.rb
@@ -0,0 +1,15 @@
+# encoding: utf-8
+String.class_eval do
+
+  # Time in seconds
+  # 
+  def reading_time
+    # https://www.sciencedirect.com/science/article/abs/pii/S0749596X19300786
+    words_per_minute = 238
+    (60.0 * words / words_per_minute).round
+  end
+
+  def words
+    self.scan(/(\w|-)+/).size
+  end
+end
\ No newline at end of file