diff --git a/app/but/bulletin_but.py b/app/but/bulletin_but.py
index 481393c5ef404c42d5f48ef789dd3b11367dbc2a..eb71373f155401fc7dafd2e636204ccf46461bd9 100644
--- a/app/but/bulletin_but.py
+++ b/app/but/bulletin_but.py
@@ -484,6 +484,7 @@ class BulletinBUT:
         d["etudid"] = etud.id
         d["etud"] = d["etudiant"]
         d["etud"]["nomprenom"] = etud.nomprenom
+        d["etud"]["etat_civil"] = etud.etat_civil
         d.update(self.res.sem)
         etud_etat = self.res.get_etud_etat(etud.id)
         d["filigranne"] = sco_bulletins_pdf.get_filigranne(
diff --git a/app/models/etudiants.py b/app/models/etudiants.py
index e4b2e5bbb910468044f2752764b8cca094752045..fb98e98b1c56e194ef8a80bf5ee546da7cc73348 100644
--- a/app/models/etudiants.py
+++ b/app/models/etudiants.py
@@ -30,6 +30,7 @@ class Identite(db.Model):
         db.UniqueConstraint("dept_id", "code_nip"),
         db.UniqueConstraint("dept_id", "code_ine"),
         db.CheckConstraint("civilite IN ('M', 'F', 'X')"),
+        db.CheckConstraint("civilite_etat_civil IN ('M', 'F', 'X')"),
     )
 
     id = db.Column(db.Integer, primary_key=True)
@@ -41,6 +42,12 @@ class Identite(db.Model):
     nom_usuel = db.Column(db.Text())
     "optionnel (si present, affiché à la place du nom)"
     civilite = db.Column(db.String(1), nullable=False)
+
+    # données d'état-civil. Si présent remplace les données d'usage dans les documents officiels (bulletins, PV)
+    # cf nomprenom_etat_civil()
+    civilite_etat_civil = db.Column(db.String(1), nullable=False, server_default="X")
+    prenom_etat_civil = db.Column(db.Text(), nullable=True)
+
     date_naissance = db.Column(db.Date)
     lieu_naissance = db.Column(db.Text())
     dept_naissance = db.Column(db.Text())
@@ -104,6 +111,13 @@ class Identite(db.Model):
         """
         return {"M": "M.", "F": "Mme", "X": ""}[self.civilite]
 
+    @property
+    def civilite_etat_civil_str(self):
+        """returns 'M.' ou 'Mme' ou '' (pour le genre neutre,
+        personnes ne souhaitant pas d'affichage).
+        """
+        return {"M": "M.", "F": "Mme", "X": ""}[self.civilite_etat_civil]
+
     def sex_nom(self, no_accents=False) -> str:
         "'M. DUPONTÉ', ou si no_accents, 'M. DUPONTE'"
         s = f"{self.civilite_str} {(self.nom_usuel or self.nom).upper()}"
@@ -150,6 +164,14 @@ class Identite(db.Model):
             r.append("-".join([x.lower().capitalize() for x in fields]))
         return " ".join(r)
 
+    @property
+    def etat_civil(self):
+        if self.prenom_etat_civil:
+            civ = {"M": "M.", "F": "Mme", "X": ""}[self.civilite_etat_civil]
+            return f"{civ} {self.prenom_etat_civil} {self.nom}"
+        else:
+            return self.nomprenom
+
     @property
     def nom_short(self):
         "Nom et début du prénom pour table recap: 'DUPONT Pi.'"
@@ -191,6 +213,8 @@ class Identite(db.Model):
             "nom_usuel": self.nom_usuel,
             "prenom": self.prenom,
             "sort_key": self.sort_key,
+            "civilite_etat_civil": self.civilite_etat_civil,
+            "prenom_etat_civil": self.prenom_etat_civil,
         }
 
     def to_dict_scodoc7(self) -> dict:
@@ -234,6 +258,8 @@ class Identite(db.Model):
             "dept_naissance": self.dept_naissance or "",
             "nationalite": self.nationalite or "",
             "boursier": self.boursier or "",
+            "civilite_etat_civil": self.civilite_etat_civil,
+            "prenom_etat_civil": self.prenom_etat_civil,
         }
         if include_urls and has_request_context():
             # test request context so we can use this func in tests under the flask shell
@@ -450,10 +476,10 @@ class Identite(db.Model):
             M. Pierre Dupont
         """
         if with_paragraph:
-            return f"""{self.nomprenom}{line_sep}n°{self.code_nip or ""}{line_sep}né{self.e} le {
+            return f"""{self.etat_civil}{line_sep}n°{self.code_nip or ""}{line_sep}né{self.e} le {
                 self.date_naissance.strftime("%d/%m/%Y") if self.date_naissance else ""}{
                 line_sep}à {self.lieu_naissance or ""}"""
-        return self.nomprenom
+        return self.etat_civil
 
     def photo_html(self, title=None, size="small") -> str:
         """HTML img tag for the photo, either in small size (h90)
diff --git a/app/scodoc/sco_bulletins_generator.py b/app/scodoc/sco_bulletins_generator.py
index ec5d258a7a23a1ec63b03684f25f17a7a9eb4204..b122d7a46b255b326c655115996a072e753b7db9 100644
--- a/app/scodoc/sco_bulletins_generator.py
+++ b/app/scodoc/sco_bulletins_generator.py
@@ -167,8 +167,9 @@ class BulletinGenerator:
 
         formsemestre_id = self.bul_dict["formsemestre_id"]
         nomprenom = self.bul_dict["etud"]["nomprenom"]
+        etat_civil = self.bul_dict["etud"]["etat_civil"]
         marque_debut_bulletin = sco_pdf.DebutBulletin(
-            nomprenom,
+            self.bul_dict["etat_civil"],
             filigranne=self.bul_dict["filigranne"],
             footer_content=f"""ScoDoc - Bulletin de {nomprenom} - {time.strftime("%d/%m/%Y %H:%M")}""",
         )
@@ -211,7 +212,7 @@ class BulletinGenerator:
                     document,
                     author="%s %s (E. Viennet) [%s]"
                     % (sco_version.SCONAME, sco_version.SCOVERSION, self.description),
-                    title=f"""Bulletin {sem["titremois"]} de {nomprenom}""",
+                    title=f"""Bulletin {sem["titremois"]} de {etat_civil}""",
                     subject="Bulletin de note",
                     margins=self.margins,
                     server_name=self.server_name,
diff --git a/app/scodoc/sco_etud.py b/app/scodoc/sco_etud.py
index 5a2313fae1036968dec66443fb151f2e2fac0e7f..70b7b16366717a3db42656ed4fbef966d159255c 100644
--- a/app/scodoc/sco_etud.py
+++ b/app/scodoc/sco_etud.py
@@ -57,7 +57,12 @@ def format_etud_ident(etud):
     else:
         etud["nom_usuel"] = ""
     etud["prenom"] = format_prenom(etud["prenom"])
+    if "prenom_etat_civil" in etud:
+        etud["prenom_etat_civil"] = format_prenom(etud["prenom_etat_civil"])
+    else:
+        etud["prenom_etat_civil"] = ""
     etud["civilite_str"] = format_civilite(etud["civilite"])
+    etud["civilite_etat_civil_str"] = format_civilite(etud["civilite_etat_civil"])
     # Nom à afficher:
     if etud["nom_usuel"]:
         etud["nom_disp"] = etud["nom_usuel"]
@@ -225,7 +230,12 @@ _identiteEditor = ndb.EditableTable(
         "nom",
         "nom_usuel",
         "prenom",
+        "prenom_etat_civil",
+        "cas_id",
+        "cas_allow_login",
+        "cas_allow_scodoc_login",
         "civilite",  # 'M", "F", or "X"
+        "civilite_etat_civil",
         "date_naissance",
         "lieu_naissance",
         "dept_naissance",
@@ -242,7 +252,9 @@ _identiteEditor = ndb.EditableTable(
     input_formators={
         "nom": force_uppercase,
         "prenom": force_uppercase,
+        "prenom_etat_civil": force_uppercase,
         "civilite": input_civilite,
+        "civilite_etat_civil": input_civilite,
         "date_naissance": ndb.DateDMYtoISO,
         "boursier": bool,
     },
@@ -263,6 +275,7 @@ def identite_list(cnx, *a, **kw):
         else:
             o["annee_naissance"] = o["date_naissance"]
         o["civilite_str"] = format_civilite(o["civilite"])
+        o["civilite_etat_civil_str"] = format_civilite(o["civilite_etat_civil"])
     return objs
 
 
diff --git a/app/scodoc/sco_import_etuds.py b/app/scodoc/sco_import_etuds.py
index 110d95d8899b52d0558b2b8f338361bb270064da..2d67c08cdec919e6f07720cb85eddce31351d2c4 100644
--- a/app/scodoc/sco_import_etuds.py
+++ b/app/scodoc/sco_import_etuds.py
@@ -71,6 +71,8 @@ FORMAT_FILE = "format_import_etudiants.txt"
 ADMISSION_MODIFIABLE_FIELDS = (
     "code_nip",
     "code_ine",
+    "prenom_etat_civil",
+    "civilite_etat_civil",
     "date_naissance",
     "lieu_naissance",
     "bac",
diff --git a/app/scodoc/sco_page_etud.py b/app/scodoc/sco_page_etud.py
index 6ac2b4bc0db2704178d9cfa109b82f4ff73d9a5f..b6a3592d676480eefd160f65bd40f09ee4dd7e3c 100644
--- a/app/scodoc/sco_page_etud.py
+++ b/app/scodoc/sco_page_etud.py
@@ -176,6 +176,18 @@ def ficheEtud(etudid=None):
     sco_etud.fill_etuds_info([etud_])
     #
     info = etud_
+    if etud.prenom_etat_civil:
+        info["etat_civil"] = (
+            "<h3>Etat-civil: "
+            + etud.civilite_etat_civil_str
+            + " "
+            + etud.prenom_etat_civil
+            + " "
+            + etud.nom
+            + "</h3>"
+        )
+    else:
+        info["etat_civil"] = ""
     info["ScoURL"] = scu.ScoURL()
     info["authuser"] = authuser
     info["info_naissance"] = info["date_naissance"]
@@ -325,18 +337,17 @@ def ficheEtud(etudid=None):
         if not sco_permissions_check.can_suppress_annotation(a["id"]):
             a["dellink"] = ""
         else:
-            a["dellink"] = (
-                '<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&annotation_id=%s">%s</a></td>'
-                % (
-                    etudid,
-                    a["id"],
-                    scu.icontag(
-                        "delete_img",
-                        border="0",
-                        alt="suppress",
-                        title="Supprimer cette annotation",
-                    ),
-                )
+            a[
+                "dellink"
+            ] = '<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&annotation_id=%s">%s</a></td>' % (
+                etudid,
+                a["id"],
+                scu.icontag(
+                    "delete_img",
+                    border="0",
+                    alt="suppress",
+                    title="Supprimer cette annotation",
+                ),
             )
         author = sco_users.user_info(a["author"])
         alist.append(
@@ -473,7 +484,7 @@ def ficheEtud(etudid=None):
 <div class="ficheEtud" id="ficheEtud"><table>
 <tr><td>
 <h2>%(nomprenom)s (%(inscription)s)</h2>
-
+%(etat_civil)s
 <span>%(emaillink)s</span> 
 </td><td class="photocell">
 <a href="etud_photo_orig_page?etudid=%(etudid)s">%(etudfoto)s</a>
diff --git a/app/views/scolar.py b/app/views/scolar.py
index 6268c7e20b551ece084dca69617d8ae6077fa4f1..3a4e89d3554d888c00a7492d4b99864bf337d37e 100644
--- a/app/views/scolar.py
+++ b/app/views/scolar.py
@@ -557,6 +557,7 @@ def etud_info(etudid=None, format="xml"):
         "nom_usuel",
         "prenom",
         "nomprenom",
+        "prenom_etat_civil",
         "email",
         "emailperso",
         "domicile",
@@ -577,6 +578,9 @@ def etud_info(etudid=None, format="xml"):
     ):
         d[a] = etud[a]  # ne pas quoter car ElementTree.tostring quote déjà
     d["civilite"] = etud["civilite_str"]  # exception: ne sort pas la civilite brute
+    d["civilite_etat_civil"] = etud[
+        "civilite_etat_civil_str"
+    ]  # exception: ne sort pas la civilite brute
     d["sexe"] = d["civilite"]  # backward compat pour anciens clients
     d["photo_url"] = sco_photos.etud_photo_url(etud)
 
@@ -1442,6 +1446,25 @@ def _etudident_create_or_edit_form(edit):
                 "title": "Civilité",
             },
         ),
+        (
+            "prenom_etat_civil",
+            {
+                "size": 25,
+                "title": "Prénom (état-civil)",
+                "allow_null": True,
+                "explanation": "Si précisé, remplace le prénom d'usage dans les documents officiels",
+            },
+        ),
+        (
+            "civilite_etat_civil",
+            {
+                "input_type": "menu",
+                "labels": ["Homme", "Femme", "Autre/neutre"],
+                "allowed_values": ["M", "F", "X"],
+                "title": "Civilité (état-civil)",
+                "explanation": "Si précisé: remplace la civilité d'usage dans les documents officiels",
+            },
+        ),
         (
             "date_naissance",
             {
diff --git a/migrations/versions/cf29790ca6f6_ajout_prenom_civilite__etat_civil.py b/migrations/versions/cf29790ca6f6_ajout_prenom_civilite__etat_civil.py
new file mode 100644
index 0000000000000000000000000000000000000000..8b13136ad3dffaabf0e1f75884ed8c5138c30f04
--- /dev/null
+++ b/migrations/versions/cf29790ca6f6_ajout_prenom_civilite__etat_civil.py
@@ -0,0 +1,33 @@
+"""ajout (prenom,civilite)_etat_civil
+
+Revision ID: cf29790ca6f6
+Revises: 6520faf67508
+Create Date: 2023-02-25 10:55:42.831526
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "cf29790ca6f6"
+down_revision = "6520faf67508"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    # ### commands auto generated by Alembic - checked ###
+    op.add_column(
+        "identite",
+        sa.Column("civilite_etat_civil", sa.Text(), nullable=True, server_default="X"),
+    )
+    op.add_column("identite", sa.Column("prenom_etat_civil", sa.Text(), nullable=True))
+    # ### end Alembic commands ###
+
+
+def downgrade():
+    # ### commands auto generated by Alembic - checked ###
+    op.drop_column("identite", "prenom_etat_civil")
+    op.drop_column("identite", "civilite_etat_civil")
+    # ### end Alembic commands ###
diff --git a/tools/format_import_etudiants.txt b/tools/format_import_etudiants.txt
index 3ba04f50bb48f2a3539ed5e5b5ca26a54adc9887..ad18c2750f43e7c529bdebe5af675ea524787b86 100644
--- a/tools/format_import_etudiants.txt
+++ b/tools/format_import_etudiants.txt
@@ -9,6 +9,8 @@ nom;          text;     identite;   0;  nom de l'etudiant;
 nom_usuel; text;    identite;   1;  nom usuel (si different);
 prenom;       text;     identite;   0;  prenom de l'etudiant
 civilite;         text;     identite;   1;  sexe ('M', 'F', 'X');sexe;genre
+prenom_etat_civil;  text;   identite; 1; prenom à l'état-civil (si différent);prenom_etat_civil
+civilite_etat_civil;    text; identite; 1; sexe ('M', 'F', 'X') à l'état civil;civilite_etat_civil
 date_naissance;text;identite;   1;  date de naissance (jj/mm/aaaa)
 lieu_naissance;text;identite; 1; lieu de naissance
 nationalite;  text;     identite;   1;  nationalite