diff --git a/app/controllers/admin/communication/websites/pages_controller.rb b/app/controllers/admin/communication/websites/pages_controller.rb
index 45850b219188009d841e15b1c59d54953a73c44b..3705053233afa7e1ec807a4bbad20d594d7cb112 100644
--- a/app/controllers/admin/communication/websites/pages_controller.rb
+++ b/app/controllers/admin/communication/websites/pages_controller.rb
@@ -4,8 +4,6 @@ class Admin::Communication::Websites::PagesController < Admin::Communication::We
 
   include Admin::Translatable
 
-  before_action :check_or_redirect_translatable_page, only: [:show, :edit, :update, :destroy]
-
   def index
     @homepage = @website.special_page(Communication::Website::Page::Home, language: current_website_language)
     @first_level_pages = @homepage.children.ordered
@@ -44,10 +42,6 @@ class Admin::Communication::Websites::PagesController < Admin::Communication::We
     render layout: 'admin/layouts/preview'
   end
 
-  def translate
-
-  end
-
   def new
     @page.website = @website
     breadcrumb
@@ -118,20 +112,4 @@ class Admin::Communication::Websites::PagesController < Admin::Communication::We
     )
   end
 
-  def check_or_redirect_translatable_page
-    # Early return if language is correct
-    return if @page.language_id == current_website_language.id
-    # Look up for translation from page
-    translation = @page.translation_for(current_website_language)
-    # If not found, duplicate the current page (with blocks and all) for given language
-    translation ||= @page.duplicate!(current_website_language)
-    # Redirect to the translation
-    if ['edit', 'update'].include?(action_name)
-      # Safety net on update action if called on wrong language
-      redirect_to [:edit, :admin, translation.becomes(translation.class.base_class)]
-    else
-      # Safety net on destroy action if called on wrong language
-      redirect_to [:admin, translation.becomes(translation.class.base_class)]
-    end
-  end
 end
diff --git a/app/controllers/admin/communication/websites/posts_controller.rb b/app/controllers/admin/communication/websites/posts_controller.rb
index a08c1e0c1bf0570922953cb0a70ec540fcd2e119..a03fc53b651184730075fedddcd64396e6bdc958 100644
--- a/app/controllers/admin/communication/websites/posts_controller.rb
+++ b/app/controllers/admin/communication/websites/posts_controller.rb
@@ -3,6 +3,8 @@ class Admin::Communication::Websites::PostsController < Admin::Communication::We
 
   load_and_authorize_resource class: Communication::Website::Post, through: :website
 
+  include Admin::Translatable
+
   before_action :load_filters, only: :index
 
   has_scope :for_search_term
@@ -11,7 +13,7 @@ class Admin::Communication::Websites::PostsController < Admin::Communication::We
   has_scope :for_pinned
 
   def index
-    @posts = apply_scopes(@posts).ordered.page params[:page]
+    @posts = apply_scopes(@posts).where(language_id: current_website_language.id).ordered.page params[:page]
     @authors =  @website.authors.accessible_by(current_ability)
                                 .ordered
                                 .page(params[:authors_page])
@@ -93,14 +95,15 @@ class Admin::Communication::Websites::PostsController < Admin::Communication::We
   end
 
   def post_params
-    params.require(:communication_website_post)
-          .permit(
-            :university_id, :website_id, :title, :meta_description, :summary, :text,
-            :published, :published_at, :slug, :pinned,
-            :featured_image, :featured_image_delete, :featured_image_infos, :featured_image_alt, :featured_image_credit,
-            :author_id, :language_id, category_ids: []
-          )
-          .merge(university_id: current_university.id)
+    translatable_params(
+      :communication_website_post,
+      [
+        :title, :meta_description, :summary, :text,
+        :published, :published_at, :slug, :pinned,
+        :featured_image, :featured_image_delete, :featured_image_infos, :featured_image_alt, :featured_image_credit,
+        :author_id, category_ids: []
+      ]
+    )
   end
 
   def load_filters
diff --git a/app/controllers/admin/communication/websites_controller.rb b/app/controllers/admin/communication/websites_controller.rb
index c32581fdc6ace8e0a8477153a291353d906481de..422c8b0c25b7e0771846c3d2c88fb7f3f9e8706f 100644
--- a/app/controllers/admin/communication/websites_controller.rb
+++ b/app/controllers/admin/communication/websites_controller.rb
@@ -10,7 +10,7 @@ class Admin::Communication::WebsitesController < Admin::Communication::Websites:
 
   def show
     @pages = @website.pages.accessible_by(current_ability).where(language_id: current_website_language.id).published.recent
-    @posts = @website.posts.accessible_by(current_ability).published.recent
+    @posts = @website.posts.accessible_by(current_ability).where(language_id: current_website_language.id).published.recent
     breadcrumb
   end
 
diff --git a/app/controllers/concerns/admin/translatable.rb b/app/controllers/concerns/admin/translatable.rb
index 13a1e910a3cfe2ee02c5cc5f26b9761fb09b3206..00221bfc6abc420378c27c629af0430807c8fceb 100644
--- a/app/controllers/concerns/admin/translatable.rb
+++ b/app/controllers/concerns/admin/translatable.rb
@@ -2,19 +2,43 @@ module Admin::Translatable
   extend ActiveSupport::Concern
 
   included do
-
-    def translate
-      raise NotImplementedError
-    end
+    before_action :check_or_redirect_translatable_resource, only: [:show, :edit, :update, :destroy]
 
     protected
 
+    # If we don't have a website, it will not work
+
     def translatable_params(model_name, attribute_names)
       params.require(model_name).permit(attribute_names).merge(
         university_id: current_university.id,
         language_id: current_website_language.id
       )
     end
+
+    def check_or_redirect_translatable_resource
+      # Early return if language is correct
+      return if resource.language_id == current_website_language.id
+      # Look up for translation from resource
+      translation = resource.translation_for(current_website_language)
+      # If not found, translate the current resource (with blocks and all) for given language
+      translation ||= resource.translate!(current_website_language)
+      # Redirect to the translation
+      if ['edit', 'update'].include?(action_name)
+        # Safety net on update action if called on wrong language
+        redirect_to [:edit, :admin, translation.becomes(translation.class.base_class)]
+      else
+        # Safety net on destroy action if called on wrong language
+        redirect_to [:admin, translation.becomes(translation.class.base_class)]
+      end
+    end
+
+    def resource_name
+      self.class.to_s.remove("Controller").demodulize.singularize.underscore
+    end
+
+    def resource
+      instance_variable_get("@#{resource_name}")
+    end
   end
 
 end
diff --git a/app/models/communication/website/page.rb b/app/models/communication/website/page.rb
index 8f5f630a6a00990e345a50303bf8c7c6be425b8e..b30d3259c8a53adce65ae5854733498ca2be4ab1 100644
--- a/app/models/communication/website/page.rb
+++ b/app/models/communication/website/page.rb
@@ -59,6 +59,7 @@ class Communication::Website::Page < ApplicationRecord
   include WithPath
   include WithType
   include WithPermalink
+  include WithTranslations
 
   has_summernote :text
 
@@ -142,53 +143,6 @@ class Communication::Website::Page < ApplicationRecord
               .where.not(id: id)
   end
 
-  def translation_for(language)
-    # If current language is language, returns itself
-    return self if language_id == language.id
-    # Translations have the same original_id if set
-    original_id.present?  ? original.translation_for(language)
-                          : translations.find_by(language_id: language.id)
-  end
-
-  def duplicate!(language)
-    # Duplicate parent if needed
-    if parent_id.present?
-      parent_translation = parent.translation_for(language)
-      parent_translation ||= parent.duplicate!(language)
-    end
-
-    duplicate = self.dup
-    # Inherits from original_id or set it to itself
-    duplicate.assign_attributes(
-      original_id: original_object.id,
-      parent_id: parent_translation&.id,
-      github_path: nil,
-      published: false,
-      language_id: language.id
-    )
-    duplicate.featured_image.attach(
-      io: URI.open(featured_image.url),
-      filename: featured_image.filename.to_s,
-      content_type: featured_image.content_type
-    ) if featured_image.attached?
-    duplicate.save
-
-    blocks.ordered.each do |block|
-      block_duplicate = block.dup
-      block_duplicate.about = duplicate
-      block_duplicate.save
-    end
-    duplicate
-  end
-
-  def original_object
-    @original_object ||= (self.original || self)
-  end
-
-  def original_with_translations
-    original_object.translations + [original_object]
-  end
-
   protected
 
   def check_accessibility
diff --git a/app/models/communication/website/post.rb b/app/models/communication/website/post.rb
index e81056ab8e7f3ef8cb8ed10b115401719048f1db..8b72d41e7c18640ea6fade5107f9c3ff14ebfc58 100644
--- a/app/models/communication/website/post.rb
+++ b/app/models/communication/website/post.rb
@@ -18,7 +18,8 @@
 #  updated_at               :datetime         not null
 #  author_id                :uuid             indexed
 #  communication_website_id :uuid             not null, indexed
-#  language_id              :uuid             indexed
+#  language_id              :uuid             not null, indexed
+#  original_id              :uuid             indexed
 #  university_id            :uuid             not null, indexed
 #
 # Indexes
@@ -26,11 +27,13 @@
 #  index_communication_website_posts_on_author_id                 (author_id)
 #  index_communication_website_posts_on_communication_website_id  (communication_website_id)
 #  index_communication_website_posts_on_language_id               (language_id)
+#  index_communication_website_posts_on_original_id               (original_id)
 #  index_communication_website_posts_on_university_id             (university_id)
 #
 # Foreign Keys
 #
 #  fk_rails_1e0d058a25  (university_id => universities.id)
+#  fk_rails_bbbef3b1e9  (original_id => communication_website_posts.id)
 #  fk_rails_d1c1a10946  (communication_website_id => communication_websites.id)
 #  fk_rails_e0eec447b0  (author_id => university_people.id)
 #
@@ -44,6 +47,7 @@ class Communication::Website::Post < ApplicationRecord
   include WithMenuItemTarget
   include WithPermalink
   include WithSlug # We override slug_unavailable? method
+  include WithTranslations # TODO: Must handle categories
 
   has_summernote :text
 
@@ -56,7 +60,6 @@ class Communication::Website::Post < ApplicationRecord
   belongs_to :author,
              class_name: 'University::Person',
              optional: true
-  belongs_to :language, optional: true
   has_and_belongs_to_many :categories,
                           class_name: 'Communication::Website::Category',
                           join_table: 'communication_website_categories_posts',
diff --git a/app/models/communication/website/with_special_pages.rb b/app/models/communication/website/with_special_pages.rb
index 3e7628192aaa032d363bbe35750cb3edab5fbd39..9c33dbbde7e2dd34851297d7a05799f37b9496ed 100644
--- a/app/models/communication/website/with_special_pages.rb
+++ b/app/models/communication/website/with_special_pages.rb
@@ -10,7 +10,7 @@ module Communication::Website::WithSpecialPages
     special_page = pages.where(type: type.to_s, language_id: language.id).first
     special_page ||= begin
       original_special_page = pages.where(type: type.to_s, language_id: default_language_id).first
-      original_special_page.duplicate!(language) if original_special_page.present?
+      original_special_page.translate!(language) if original_special_page.present?
     end
     special_page
   end
diff --git a/app/models/concerns/with_translations.rb b/app/models/concerns/with_translations.rb
new file mode 100644
index 0000000000000000000000000000000000000000..37cd33af14e54d05ab5cf7c28053552b41fec2fd
--- /dev/null
+++ b/app/models/concerns/with_translations.rb
@@ -0,0 +1,70 @@
+module WithTranslations
+  extend ActiveSupport::Concern
+
+  included do
+    belongs_to  :language
+    belongs_to  :original, class_name: base_class.to_s, optional: true
+    has_many    :translations, class_name: base_class.to_s, foreign_key: :original_id, dependent: :nullify
+  end
+
+  def translation_for(language)
+    # If current language is language, returns itself
+    return self if language_id == language.id
+    # Translations have the same original_id if set
+    original_id.present?  ? original.translation_for(language)
+                          : translations.find_by(language_id: language.id)
+  end
+
+  def original_object
+    @original_object ||= (self.original || self)
+  end
+
+  def original_with_translations
+    original_object.translations + [original_object]
+  end
+
+  def translate!(language)
+    translation = self.dup
+
+    # Translate parent if needed
+    if respond_to?(:parent_id) && parent_id.present?
+      parent_translation = parent.translation_for(language)
+      parent_translation ||= parent.translate!(language)
+      translation.parent_id = parent_translation&.id
+    end
+
+    # Inherits from original_id or set it to itself
+    translation.assign_attributes(
+      original_id: original_object.id,
+      language_id: language.id
+    )
+
+    # Handle publication
+    translation.published = false if respond_to?(:published)
+    # Handle featured image if object has one
+    translate_featured_image(translation) if respond_to?(:featured_image) && featured_image.attached?
+    translation.save
+    # Handle blocks if object has any
+    translate_blocks!(translation) if respond_to?(:blocks)
+
+    translation
+  end
+
+  protected
+
+  def translate_featured_image(translation)
+    translation.featured_image.attach(
+      io: URI.open(featured_image.url),
+      filename: featured_image.filename.to_s,
+      content_type: featured_image.content_type
+    )
+  end
+
+  def translate_blocks!(translation)
+    blocks.ordered.each do |block|
+      block_duplicate = block.dup
+      block_duplicate.about = translation
+      block_duplicate.save
+    end
+  end
+end
\ No newline at end of file
diff --git a/app/models/university/person.rb b/app/models/university/person.rb
index b96f64957dee83814daa09f1b6c209befe379112..547438c54b3d856aed08410a988bfabbe1d80a2b 100644
--- a/app/models/university/person.rb
+++ b/app/models/university/person.rb
@@ -2,39 +2,40 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  mastodon           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #
diff --git a/app/models/university/person/administrator.rb b/app/models/university/person/administrator.rb
index bac4deebe718a2416d90e51c40693d7e3c8c8339..c69d82a9a0d532d48f9c53adeabdcf027b589d74 100644
--- a/app/models/university/person/administrator.rb
+++ b/app/models/university/person/administrator.rb
@@ -2,39 +2,40 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  mastodon           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #
diff --git a/app/models/university/person/alumnus.rb b/app/models/university/person/alumnus.rb
index cecc421cd2f061798f2cfc03a20c9fa04c20ef6b..ba7b52692aa3511a37355bc6fb6c16c065643e40 100644
--- a/app/models/university/person/alumnus.rb
+++ b/app/models/university/person/alumnus.rb
@@ -2,39 +2,40 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  mastodon           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #
diff --git a/app/models/university/person/author.rb b/app/models/university/person/author.rb
index ce3bad531fb8019ade2136e103b17bdf299d4128..dc57d751ad51f4c83925ca24bd42bdbd825f3816 100644
--- a/app/models/university/person/author.rb
+++ b/app/models/university/person/author.rb
@@ -2,39 +2,40 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  mastodon           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #
diff --git a/app/models/university/person/researcher.rb b/app/models/university/person/researcher.rb
index aa2415f64931c64dab1857e259cff3b0d4e75ed1..b6b7464afba46fa1af7e1da007c1838c335d9e70 100644
--- a/app/models/university/person/researcher.rb
+++ b/app/models/university/person/researcher.rb
@@ -2,39 +2,40 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  mastodon           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #
diff --git a/app/models/university/person/teacher.rb b/app/models/university/person/teacher.rb
index 66d8f2af271b6524093d1648bd4710861269a039..f02acc6005dd6a3a7b1b0b1a64a67a3d778ed1b6 100644
--- a/app/models/university/person/teacher.rb
+++ b/app/models/university/person/teacher.rb
@@ -2,39 +2,40 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  mastodon           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #
diff --git a/app/views/admin/communication/websites/posts/_form.html.erb b/app/views/admin/communication/websites/posts/_form.html.erb
index 1cfe0a7deda6e65ce393b71880cbf9b78e4ab665..6e5599e6c5a7ae62b3825fdaae069af5f89f0d61 100644
--- a/app/views/admin/communication/websites/posts/_form.html.erb
+++ b/app/views/admin/communication/websites/posts/_form.html.erb
@@ -52,11 +52,6 @@
             </div>
             <%= f.input :published_at, html5: true %>
           <% end %>
-          <% if @website.languages.many? %>
-            <%= f.input :language_id, collection: @website.languages, include_blank: false %>
-          <% elsif @website.languages.any? %>
-            <%= f.input :language_id, as: :hidden, input_html: { value: @website.languages.first.id }, wrapper: false %>
-          <% end %>
           <% if current_user.author? || current_user.contributor? %>
             <%= f.input :author_id,
                         as: :hidden,
diff --git a/app/views/admin/communication/websites/posts/show.html.erb b/app/views/admin/communication/websites/posts/show.html.erb
index e37dba9adefcc5743eba08bb64d3ec4b8523c5f5..8fa71739335c80a5b5c89f12f1bcb0ca7aa43df6 100644
--- a/app/views/admin/communication/websites/posts/show.html.erb
+++ b/app/views/admin/communication/websites/posts/show.html.erb
@@ -7,6 +7,7 @@
       <%= render 'admin/communication/blocks/list', about: @post %>
     </div>
     <div class="col-md-4">
+      <%= render 'admin/application/i18n/widget', about: @post if @website.languages.many? %>
       <div class="card flex-fill w-100">
         <div class="card-header">
           <div class="float-end">
diff --git a/app/views/admin/communication/websites/show/_posts.html.erb b/app/views/admin/communication/websites/show/_posts.html.erb
index 186639df5c50374b68e5d37548f49a848c959084..4001a9ad257b01dfbc8d9d15a8f275120159be33 100644
--- a/app/views/admin/communication/websites/show/_posts.html.erb
+++ b/app/views/admin/communication/websites/show/_posts.html.erb
@@ -13,7 +13,7 @@
         <%= t('communication.website.last_posts') %>
         <small>
           -
-          <%= t('communication.website.see_all', number: @website.posts.accessible_by(current_ability).count) %>
+          <%= t('communication.website.see_all', number: @website.posts.accessible_by(current_ability).where(language_id: current_website_language.id).count) %>
         </small>
       <% end %>
     </h2>
diff --git a/db/migrate/20230123150502_set_language_on_communication_website_posts.rb b/db/migrate/20230123150502_set_language_on_communication_website_posts.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ebee8b281180a0c6cf44da6a16590cef7b1082cf
--- /dev/null
+++ b/db/migrate/20230123150502_set_language_on_communication_website_posts.rb
@@ -0,0 +1,11 @@
+class SetLanguageOnCommunicationWebsitePosts < ActiveRecord::Migration[7.0]
+  def change
+    add_reference :communication_website_posts, :original, foreign_key: {to_table: :communication_website_posts}, type: :uuid
+
+    Communication::Website.find_each do |website|
+      website.posts.where(language_id: nil).update_all(language_id: website.default_language_id)
+    end
+
+    change_column_null :communication_website_posts, :language_id, false
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 7081f66780991bdf69d60efa8d886c1e7fbc1782..dadd362decce6e8541242e835bb9aed1a3010148 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,13 +10,13 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
+ActiveRecord::Schema[7.0].define(version: 2023_01_23_150502) do
   # These are extensions that must be enabled in order to support this database
   enable_extension "pgcrypto"
   enable_extension "plpgsql"
   enable_extension "unaccent"
 
-  create_table "action_text_rich_texts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "action_text_rich_texts", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.string "name", null: false
     t.text "body"
     t.string "record_type", null: false
@@ -26,7 +26,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["record_type", "record_id", "name"], name: "index_action_text_rich_texts_uniqueness", unique: true
   end
 
-  create_table "active_storage_attachments", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "active_storage_attachments", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.string "name", null: false
     t.string "record_type", null: false
     t.uuid "record_id", null: false
@@ -36,7 +36,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
   end
 
-  create_table "active_storage_blobs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "active_storage_blobs", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.string "key", null: false
     t.string "filename", null: false
     t.string "content_type"
@@ -50,13 +50,13 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_active_storage_blobs_on_university_id"
   end
 
-  create_table "active_storage_variant_records", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "active_storage_variant_records", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "blob_id", null: false
     t.string "variation_digest", null: false
     t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
   end
 
-  create_table "administration_qualiopi_criterions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "administration_qualiopi_criterions", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.integer "number"
     t.text "name"
     t.text "description"
@@ -64,7 +64,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.datetime "updated_at", null: false
   end
 
-  create_table "administration_qualiopi_indicators", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "administration_qualiopi_indicators", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "criterion_id", null: false
     t.integer "number"
     t.text "name"
@@ -78,7 +78,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["criterion_id"], name: "index_administration_qualiopi_indicators_on_criterion_id"
   end
 
-  create_table "communication_blocks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_blocks", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.string "about_type"
     t.uuid "about_id"
@@ -93,7 +93,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_communication_blocks_on_university_id"
   end
 
-  create_table "communication_extranets", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_extranets", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.string "name"
     t.uuid "university_id", null: false
     t.string "host"
@@ -117,7 +117,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_communication_extranets_on_university_id"
   end
 
-  create_table "communication_website_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_categories", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "communication_website_id", null: false
     t.string "name"
@@ -147,7 +147,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["communication_website_post_id", "communication_website_category_id"], name: "post_category"
   end
 
-  create_table "communication_website_git_files", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_git_files", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.string "previous_path"
     t.string "about_type", null: false
     t.uuid "about_id", null: false
@@ -159,7 +159,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["website_id"], name: "index_communication_website_git_files_on_website_id"
   end
 
-  create_table "communication_website_imported_authors", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_imported_authors", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "website_id", null: false
     t.uuid "author_id"
@@ -175,7 +175,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["website_id"], name: "idx_communication_website_imported_auth_on_website"
   end
 
-  create_table "communication_website_imported_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_imported_categories", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "website_id", null: false
     t.uuid "category_id"
@@ -193,7 +193,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["website_id"], name: "idx_communication_website_imported_cat_on_website"
   end
 
-  create_table "communication_website_imported_media", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_imported_media", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.string "identifier"
     t.jsonb "data"
     t.text "file_url"
@@ -208,7 +208,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["website_id"], name: "index_communication_website_imported_media_on_website_id"
   end
 
-  create_table "communication_website_imported_pages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_imported_pages", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "website_id", null: false
     t.uuid "page_id"
@@ -232,7 +232,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["website_id"], name: "index_communication_website_imported_pages_on_website_id"
   end
 
-  create_table "communication_website_imported_posts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_imported_posts", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "website_id", null: false
     t.uuid "post_id"
@@ -257,7 +257,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["website_id"], name: "index_communication_website_imported_posts_on_website_id"
   end
 
-  create_table "communication_website_imported_websites", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_imported_websites", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "website_id", null: false
     t.integer "status", default: 0
@@ -267,7 +267,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["website_id"], name: "index_communication_website_imported_websites_on_website_id"
   end
 
-  create_table "communication_website_menu_items", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_menu_items", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "website_id", null: false
     t.uuid "menu_id", null: false
@@ -287,7 +287,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["website_id"], name: "index_communication_website_menu_items_on_website_id"
   end
 
-  create_table "communication_website_menus", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_menus", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "communication_website_id", null: false
     t.string "title"
@@ -299,7 +299,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_communication_website_menus_on_university_id"
   end
 
-  create_table "communication_website_pages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_pages", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "communication_website_id", null: false
     t.string "title"
@@ -314,10 +314,10 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.text "github_path"
     t.string "featured_image_alt"
     t.text "text"
+    t.text "summary"
     t.string "breadcrumb_title"
     t.text "header_text"
     t.integer "kind"
-    t.text "summary"
     t.string "bodyclass"
     t.uuid "language_id", null: false
     t.text "featured_image_credit"
@@ -345,7 +345,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["website_id"], name: "index_communication_website_permalinks_on_website_id"
   end
 
-  create_table "communication_website_posts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_website_posts", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "communication_website_id", null: false
     t.string "title"
@@ -361,15 +361,17 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.string "featured_image_alt"
     t.text "text"
     t.text "summary"
-    t.uuid "language_id"
+    t.uuid "language_id", null: false
     t.text "featured_image_credit"
+    t.uuid "original_id"
     t.index ["author_id"], name: "index_communication_website_posts_on_author_id"
     t.index ["communication_website_id"], name: "index_communication_website_posts_on_communication_website_id"
     t.index ["language_id"], name: "index_communication_website_posts_on_language_id"
+    t.index ["original_id"], name: "index_communication_website_posts_on_original_id"
     t.index ["university_id"], name: "index_communication_website_posts_on_university_id"
   end
 
-  create_table "communication_websites", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "communication_websites", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.string "name"
     t.string "url"
@@ -421,7 +423,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["priority", "run_at"], name: "delayed_jobs_priority"
   end
 
-  create_table "education_academic_years", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "education_academic_years", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.integer "year"
     t.datetime "created_at", null: false
@@ -436,7 +438,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_person_id", "education_academic_year_id"], name: "index_person_academic_year"
   end
 
-  create_table "education_cohorts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "education_cohorts", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "program_id", null: false
     t.uuid "academic_year_id", null: false
@@ -457,7 +459,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_person_id", "education_cohort_id"], name: "index_person_cohort"
   end
 
-  create_table "education_diplomas", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "education_diplomas", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.string "name"
     t.string "short_name"
     t.integer "level", default: 0
@@ -471,7 +473,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_education_diplomas_on_university_id"
   end
 
-  create_table "education_programs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "education_programs", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.string "name"
     t.integer "capacity"
@@ -531,7 +533,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["education_program_id", "user_id"], name: "index_education_programs_users_on_program_id_and_user_id"
   end
 
-  create_table "education_schools", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "education_schools", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.string "name"
     t.string "address"
@@ -546,7 +548,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_education_schools_on_university_id"
   end
 
-  create_table "imports", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "imports", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.integer "number_of_lines"
     t.jsonb "processing_errors"
     t.integer "kind"
@@ -559,7 +561,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["user_id"], name: "index_imports_on_user_id"
   end
 
-  create_table "languages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "languages", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.string "name"
     t.string "iso_code"
     t.datetime "created_at", null: false
@@ -567,6 +569,20 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.string "summernote_locale"
   end
 
+  create_table "research_documents", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+    t.uuid "university_id", null: false
+    t.uuid "university_person_id", null: false
+    t.string "docid"
+    t.jsonb "data"
+    t.string "title"
+    t.string "url"
+    t.string "ref"
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["university_id"], name: "index_research_documents_on_university_id"
+    t.index ["university_person_id"], name: "index_research_documents_on_university_person_id"
+  end
+
   create_table "research_journal_paper_kinds", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "journal_id", null: false
@@ -578,7 +594,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_research_journal_paper_kinds_on_university_id"
   end
 
-  create_table "research_journal_papers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "research_journal_papers", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.string "title"
     t.datetime "published_at", precision: nil
     t.uuid "university_id", null: false
@@ -611,7 +627,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["researcher_id"], name: "index_research_journal_papers_researchers_on_researcher_id"
   end
 
-  create_table "research_journal_volumes", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "research_journal_volumes", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "research_journal_id", null: false
     t.string "title"
@@ -631,7 +647,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_research_journal_volumes_on_university_id"
   end
 
-  create_table "research_journals", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "research_journals", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.string "title"
     t.text "meta_description"
@@ -642,7 +658,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_research_journals_on_university_id"
   end
 
-  create_table "research_laboratories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "research_laboratories", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.string "name"
     t.string "address"
@@ -654,7 +670,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_research_laboratories_on_university_id"
   end
 
-  create_table "research_laboratory_axes", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "research_laboratory_axes", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "research_laboratory_id", null: false
     t.string "name"
@@ -668,7 +684,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_research_laboratory_axes_on_university_id"
   end
 
-  create_table "research_theses", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "research_theses", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "research_laboratory_id", null: false
     t.uuid "author_id", null: false
@@ -686,7 +702,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_research_theses_on_university_id"
   end
 
-  create_table "universities", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "universities", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.string "name"
     t.string "identifier"
     t.string "address"
@@ -711,7 +727,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.string "sso_button_label"
   end
 
-  create_table "university_organizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "university_organizations", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.string "name"
     t.string "long_name"
@@ -738,7 +754,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_university_organizations_on_university_id"
   end
 
-  create_table "university_people", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "university_people", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "user_id"
     t.string "last_name"
@@ -770,12 +786,13 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.string "zipcode"
     t.string "city"
     t.string "country"
+    t.string "hal_person_identifier"
     t.string "mastodon"
     t.index ["university_id"], name: "index_university_people_on_university_id"
     t.index ["user_id"], name: "index_university_people_on_user_id"
   end
 
-  create_table "university_person_experiences", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "university_person_experiences", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "person_id", null: false
     t.uuid "organization_id", null: false
@@ -789,7 +806,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_university_person_experiences_on_university_id"
   end
 
-  create_table "university_person_involvements", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "university_person_involvements", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.uuid "person_id", null: false
     t.integer "kind"
@@ -804,7 +821,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_university_person_involvements_on_university_id"
   end
 
-  create_table "university_roles", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "university_roles", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.string "target_type"
     t.uuid "target_id"
@@ -816,7 +833,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
     t.index ["university_id"], name: "index_university_roles_on_university_id"
   end
 
-  create_table "users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+  create_table "users", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t|
     t.uuid "university_id", null: false
     t.string "first_name"
     t.string "last_name"
@@ -902,6 +919,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
   add_foreign_key "communication_website_pages", "universities"
   add_foreign_key "communication_website_permalinks", "communication_websites", column: "website_id"
   add_foreign_key "communication_website_permalinks", "universities"
+  add_foreign_key "communication_website_posts", "communication_website_posts", column: "original_id"
   add_foreign_key "communication_website_posts", "communication_websites"
   add_foreign_key "communication_website_posts", "universities"
   add_foreign_key "communication_website_posts", "university_people", column: "author_id"
@@ -918,6 +936,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_19_164205) do
   add_foreign_key "education_schools", "universities"
   add_foreign_key "imports", "universities"
   add_foreign_key "imports", "users"
+  add_foreign_key "research_documents", "universities"
+  add_foreign_key "research_documents", "university_people"
   add_foreign_key "research_journal_paper_kinds", "research_journals", column: "journal_id"
   add_foreign_key "research_journal_paper_kinds", "universities"
   add_foreign_key "research_journal_papers", "research_journal_paper_kinds", column: "kind_id"
diff --git a/test/fixtures/communication/website/posts.yml b/test/fixtures/communication/website/posts.yml
index 8a2cbd33b616566e8787a71c542a9dacb2e2fa01..0ae2a17728e0c747c6fc7f89debccd981725666b 100644
--- a/test/fixtures/communication/website/posts.yml
+++ b/test/fixtures/communication/website/posts.yml
@@ -18,7 +18,8 @@
 #  updated_at               :datetime         not null
 #  author_id                :uuid             indexed
 #  communication_website_id :uuid             not null, indexed
-#  language_id              :uuid             indexed
+#  language_id              :uuid             not null, indexed
+#  original_id              :uuid             indexed
 #  university_id            :uuid             not null, indexed
 #
 # Indexes
@@ -26,11 +27,13 @@
 #  index_communication_website_posts_on_author_id                 (author_id)
 #  index_communication_website_posts_on_communication_website_id  (communication_website_id)
 #  index_communication_website_posts_on_language_id               (language_id)
+#  index_communication_website_posts_on_original_id               (original_id)
 #  index_communication_website_posts_on_university_id             (university_id)
 #
 # Foreign Keys
 #
 #  fk_rails_1e0d058a25  (university_id => universities.id)
+#  fk_rails_bbbef3b1e9  (original_id => communication_website_posts.id)
 #  fk_rails_d1c1a10946  (communication_website_id => communication_websites.id)
 #  fk_rails_e0eec447b0  (author_id => university_people.id)
 #
diff --git a/test/fixtures/university/people.yml b/test/fixtures/university/people.yml
index 49c568d5195415d1b2944fba5c22dc17997a8f7f..8fbe739520b3b9d7a0b72d1aa75753cd316ba1c1 100644
--- a/test/fixtures/university/people.yml
+++ b/test/fixtures/university/people.yml
@@ -2,39 +2,40 @@
 #
 # Table name: university_people
 #
-#  id                 :uuid             not null, primary key
-#  address            :string
-#  biography          :text
-#  birthdate          :date
-#  city               :string
-#  country            :string
-#  email              :string
-#  first_name         :string
-#  gender             :integer
-#  habilitation       :boolean          default(FALSE)
-#  is_administration  :boolean
-#  is_alumnus         :boolean          default(FALSE)
-#  is_author          :boolean
-#  is_researcher      :boolean
-#  is_teacher         :boolean
-#  last_name          :string
-#  linkedin           :string
-#  mastodon           :string
-#  meta_description   :text
-#  name               :string
-#  phone_mobile       :string
-#  phone_personal     :string
-#  phone_professional :string
-#  slug               :string
-#  summary            :text
-#  tenure             :boolean          default(FALSE)
-#  twitter            :string
-#  url                :string
-#  zipcode            :string
-#  created_at         :datetime         not null
-#  updated_at         :datetime         not null
-#  university_id      :uuid             not null, indexed
-#  user_id            :uuid             indexed
+#  id                    :uuid             not null, primary key
+#  address               :string
+#  biography             :text
+#  birthdate             :date
+#  city                  :string
+#  country               :string
+#  email                 :string
+#  first_name            :string
+#  gender                :integer
+#  habilitation          :boolean          default(FALSE)
+#  hal_person_identifier :string
+#  is_administration     :boolean
+#  is_alumnus            :boolean          default(FALSE)
+#  is_author             :boolean
+#  is_researcher         :boolean
+#  is_teacher            :boolean
+#  last_name             :string
+#  linkedin              :string
+#  mastodon              :string
+#  meta_description      :text
+#  name                  :string
+#  phone_mobile          :string
+#  phone_personal        :string
+#  phone_professional    :string
+#  slug                  :string
+#  summary               :text
+#  tenure                :boolean          default(FALSE)
+#  twitter               :string
+#  url                   :string
+#  zipcode               :string
+#  created_at            :datetime         not null
+#  updated_at            :datetime         not null
+#  university_id         :uuid             not null, indexed
+#  user_id               :uuid             indexed
 #
 # Indexes
 #