From 0d8c76cd035c8878ae861d2c590463e42bc65501 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Mon, 29 Dec 2025 16:32:05 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(backend)=20add=20a=20flexible=20JSON?= =?UTF-8?q?=20field=20to=20store=20recording=20options?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a JSON field allows iterating on recording data without running a new migration each time additional options or metadata need to be tracked. This comes with trade-offs, notably weaker data validation and less clarity on which data can be stored alongside a recording. In the long run, this JSON field can be refactored into dedicated columns once the feature and data model have stabilized. --- .../core/migrations/0016_recording_options.py | 18 +++++++ src/backend/core/models.py | 6 +++ .../recording/test_api_recordings_list.py | 1 + .../recording/test_api_recordings_retrieve.py | 4 ++ .../locale/de_DE/LC_MESSAGES/django.mo | Bin 10212 -> 10376 bytes .../locale/de_DE/LC_MESSAGES/django.po | 50 ++++++++++-------- .../locale/en_US/LC_MESSAGES/django.mo | Bin 9323 -> 9427 bytes .../locale/en_US/LC_MESSAGES/django.po | 50 ++++++++++-------- .../locale/fr_FR/LC_MESSAGES/django.mo | Bin 10375 -> 10544 bytes .../locale/fr_FR/LC_MESSAGES/django.po | 50 ++++++++++-------- .../locale/nl_NL/LC_MESSAGES/django.mo | Bin 9702 -> 9866 bytes .../locale/nl_NL/LC_MESSAGES/django.po | 50 ++++++++++-------- 12 files changed, 137 insertions(+), 92 deletions(-) create mode 100644 src/backend/core/migrations/0016_recording_options.py diff --git a/src/backend/core/migrations/0016_recording_options.py b/src/backend/core/migrations/0016_recording_options.py new file mode 100644 index 00000000..96fb1d46 --- /dev/null +++ b/src/backend/core/migrations/0016_recording_options.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.9 on 2025-12-29 15:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0015_application_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='recording', + name='options', + field=models.JSONField(blank=True, default=dict, help_text='Recording options', verbose_name='Recording options'), + ), + ] diff --git a/src/backend/core/models.py b/src/backend/core/models.py index b291f7c6..3d97963e 100644 --- a/src/backend/core/models.py +++ b/src/backend/core/models.py @@ -577,6 +577,12 @@ class Recording(BaseModel): verbose_name=_("Recording mode"), help_text=_("Defines the mode of recording being called."), ) + options = models.JSONField( + blank=True, + default=dict, + verbose_name=_("Recording options"), + help_text=_("Recording options"), + ) class Meta: db_table = "meet_recording" diff --git a/src/backend/core/tests/recording/test_api_recordings_list.py b/src/backend/core/tests/recording/test_api_recordings_list.py index f09a2594..2fc3e39d 100644 --- a/src/backend/core/tests/recording/test_api_recordings_list.py +++ b/src/backend/core/tests/recording/test_api_recordings_list.py @@ -82,6 +82,7 @@ def test_api_recordings_list_authenticated_direct(role, settings): "key": recording.key, "created_at": recording.created_at.isoformat().replace("+00:00", "Z"), "mode": recording.mode, + "options": {}, "room": { "access_level": str(room.access_level), "id": str(room.id), diff --git a/src/backend/core/tests/recording/test_api_recordings_retrieve.py b/src/backend/core/tests/recording/test_api_recordings_retrieve.py index 5196b700..827bdd09 100644 --- a/src/backend/core/tests/recording/test_api_recordings_retrieve.py +++ b/src/backend/core/tests/recording/test_api_recordings_retrieve.py @@ -95,6 +95,7 @@ def test_api_recording_retrieve_administrators(settings): "updated_at": recording.updated_at.isoformat().replace("+00:00", "Z"), "status": str(recording.status), "mode": str(recording.mode), + "options": {}, "expired_at": None, "is_expired": False, } @@ -130,6 +131,7 @@ def test_api_recording_retrieve_owners(settings): "updated_at": recording.updated_at.isoformat().replace("+00:00", "Z"), "status": str(recording.status), "mode": str(recording.mode), + "options": {}, "expired_at": None, "is_expired": False, } @@ -169,6 +171,7 @@ def test_api_recording_retrieve_compute_expiration_date_correctly(settings): "updated_at": "2023-01-15T12:00:00Z", "status": str(recording.status), "mode": str(recording.mode), + "options": {}, "expired_at": "2023-01-16T12:00:00Z", "is_expired": False, # Ensure the recording is still valid and hasn't expired } @@ -209,6 +212,7 @@ def test_api_recording_retrieve_expired(settings): "updated_at": "2023-01-15T12:00:00Z", "status": str(recording.status), "mode": str(recording.mode), + "options": {}, "expired_at": "2023-01-17T12:00:00Z", "is_expired": True, # Ensure the recording has expired } diff --git a/src/backend/locale/de_DE/LC_MESSAGES/django.mo b/src/backend/locale/de_DE/LC_MESSAGES/django.mo index 78b8a6c70fcc15030e451e6aa536d9846c1c65d8..fd9e4b59579e2c7b170531b155045c63ee1b7e0e 100644 GIT binary patch delta 2701 zcmYk+d2AGA7{~FKrO>THyM;ngjvY%W0z!+R)fR-dP$-8Sau!-#+G)GAo!##4pb~M3 zfk=#y=!Pq5NQ}Wm(5S@(qr@mg2_C_lKL}RDL_)$JiU^4szrUT)^i7}nyzg}8J)haj z%XY6wUmTXR&rn=q3~_p(F)w3RE*DB)o-sE5glloZZN`-1VVsJmF^a#TUfFoNF@v!c zhhiu4XP)3P40qvhJcuD<(&iYIA>25L@rVS5WP(Jf z37$lC*oRutRpiSwH~ss6p^hS#S?LIdVDSJxF?^EtWM&!1*Kj(Hy2JZA7U5&GpF-tS z`UaJ3lHKW@X%IEjk*G7ZkmEAbQCnSydT}L|V>9Zxy{Mf$jLNAmQ470>+JWF`?|uQ+ z&<^8+`u-zSwDK2GD}NPZ_$j`GmHaAkD&||?D>#$(KR5?xkPzCTBr3Uf;3C|OJMkOT z#MklTqJ_1ij;sem`u=xO(TetCExv-9&@ZS5uc1~L2zvt!N5(c5YQWj}0?tSEa~?I| zWn}T@cO)%LzU94NisZ4Gj-fP_c~p4Dtj4?0MRjlhb#_NkGe3_yic7cxucJDu=OyLJ zdQ@_@q9(o_l_Sq1>0WD5N$8T=oAS|Bf-5-luaMeWiUs+tw4Xt1+4#sy- zTlgLZ@C(#gp2I146?3tepF651jLMk>s3TgA193CzYiPqDZuL#$0NS&(jSGl+!X?z+ zM5t)RJZHKIty*WeoLEMz${flaonA<-f6-E6L{Gn)8>wrLItgt)*_iB~9AYw|qHNNB%_Y_mn+cUiGHx)O z)=#sJOXX2w2B8FRC3FfQB2KI)Y6u;%PC-RK1!O_Cq`1x|R(eg7@YM-COz5N1>FOkH zLb*#xn+;s`Av{Dxi1~y?tRXrGB`+yy+KK+9*>5PBmkoL#S&KBc3PuOyX7YBM6%jS z*gbAEVYgatJmy%DmX?_7q%alT8qr&sKMIy)wiGN6TCr>|$;?{?b9(DS$MWl!{on1W z4-!_yO(s)z2ff=?t?js}ZFZvCvJ;HiYA3p)EghB<;j%d9q+*dy`j6TP*J;n32+s;N o+Wg;kc)Tm(Zca_hTpQONs&U(#NJqEr4QxA^#_-DCfORSNU&Xy6sQ>@~ delta 2559 zcmYk-drXye9LMpW+ztrhIV7PHagv*I7cfakxq2z&5|R>Ri5%e=_e)tCk89N!t+{n( z`G>T^*|MG5gksB;IsS0dwL;gL#Byn_a*MSb|J5J8Kj%C)emmdi_4_?M&-1%{f6v2c z!<{pU@ZNcDJp54n8AGf1J%Kr*r0AKqMd=w*ou0GIEQV zMHa!_w7rXYv=>p&OXVirm&G9xOE8N5O%;^~u@=M7gPPf4Wb&pD)xj~_F;vH=kY}3- zOu+NF8n2)RavK|Q0W+|i^;XATbJw|~NT+JB-37Q#guhyyji zc;rte5!Yk3eZC1b;}%rMZK#xtq569VHNfv&tbZ<*IZkZBNOnj8R-$fv(e`~zqJ0@t z@D6I`k?f>0OhD3W_F)csPN416WSzx)CxG5b|tz{ zOWTCHu^TnBH<4$Vw^1|s5Y?d{^YI4ix+wCh=Q%M1*P>FL#9;##SyYsh{kRT0P!AkK z&FCcZMw$ux{70x%oJXZ#8WWcB+TtCEkJURH*q@nIB zLH4WJiTq3phez-z##&UysWhPVfBQ6V4-- z7*|SgPZT0qG;O#WM^LH!7Ax>p3hQ4+B{h|I5#v_8{u~%cvQ@i`u*ssD7@eTfrrYh%fXZbyX5kKW;2`od zM>%M(oIw}*F%&PN-hvtX@7HbTaT({;>2{)(7$P3kXLCQHq8Y2*PiVQ7vpS-dX!M

m~LP zWyI5jvY=8(knKPjzNHy_FG!GTBaSB`8+lQ?CvGIPpADMYsvQg&jmL z!Im?Jh^6IOyHSHr65T|ReeOQH?1~3t2z^}HZl;=0Sr^!WR8|L?{2Rt(yWWXA?YiES z9HM#ZTGS`uzEEeKuid#RqJP*s;A!_wudJDR&-q!b??!T0RE6giucvdkr^9#Lo!}dG oZ;YuPIMh4P?iuLv9_;kJm0Y@F(A(4QrhQ\n" "Language-Team: LANGUAGE \n" @@ -315,92 +315,96 @@ msgstr "Aufzeichnungsmodus" msgid "Defines the mode of recording being called." msgstr "Definiert den aufgerufenen Aufzeichnungsmodus." -#: core/models.py:584 +#: core/models.py:583 core/models.py:584 +msgid "Recording options" +msgstr "Aufnahmeoptionen" + +#: core/models.py:590 msgid "Recording" msgstr "Aufzeichnung" -#: core/models.py:585 +#: core/models.py:591 msgid "Recordings" msgstr "Aufzeichnungen" -#: core/models.py:693 +#: core/models.py:699 msgid "Recording/user relation" msgstr "Beziehung Aufzeichnung/Benutzer" -#: core/models.py:694 +#: core/models.py:700 msgid "Recording/user relations" msgstr "Beziehungen Aufzeichnung/Benutzer" -#: core/models.py:700 +#: core/models.py:706 msgid "This user is already in this recording." msgstr "Dieser Benutzer ist bereits Teil dieser Aufzeichnung." -#: core/models.py:706 +#: core/models.py:712 msgid "This team is already in this recording." msgstr "Dieses Team ist bereits Teil dieser Aufzeichnung." -#: core/models.py:712 +#: core/models.py:718 msgid "Either user or team must be set, not both." msgstr "Entweder Benutzer oder Team muss festgelegt werden, nicht beides." -#: core/models.py:729 +#: core/models.py:735 msgid "Create rooms" msgstr "Räume erstellen" -#: core/models.py:730 +#: core/models.py:736 msgid "List rooms" msgstr "Räume auflisten" -#: core/models.py:731 +#: core/models.py:737 msgid "Retrieve room details" msgstr "Raumdetails abrufen" -#: core/models.py:732 +#: core/models.py:738 msgid "Update rooms" msgstr "Räume aktualisieren" -#: core/models.py:733 +#: core/models.py:739 msgid "Delete rooms" msgstr "Räume löschen" -#: core/models.py:746 +#: core/models.py:752 msgid "Application name" msgstr "Anwendungsname" -#: core/models.py:747 +#: core/models.py:753 msgid "Descriptive name for this application." msgstr "Beschreibender Name für diese Anwendung." -#: core/models.py:757 +#: core/models.py:763 msgid "Hashed on Save. Copy it now if this is a new secret." msgstr "" "Beim Speichern gehasht. Jetzt kopieren, wenn dies ein neues Geheimnis ist." -#: core/models.py:768 +#: core/models.py:774 msgid "Application" msgstr "Anwendung" -#: core/models.py:769 +#: core/models.py:775 msgid "Applications" msgstr "Anwendungen" -#: core/models.py:792 +#: core/models.py:798 msgid "Enter a valid domain" msgstr "Geben Sie eine gültige Domain ein" -#: core/models.py:795 +#: core/models.py:801 msgid "Domain" msgstr "Domain" -#: core/models.py:796 +#: core/models.py:802 msgid "Email domain this application can act on behalf of." msgstr "E-Mail-Domain, im Namen der diese Anwendung handeln kann." -#: core/models.py:808 +#: core/models.py:814 msgid "Application domain" msgstr "Anwendungsdomain" -#: core/models.py:809 +#: core/models.py:815 msgid "Application domains" msgstr "Anwendungsdomains" diff --git a/src/backend/locale/en_US/LC_MESSAGES/django.mo b/src/backend/locale/en_US/LC_MESSAGES/django.mo index cdf08bd5c113856ad04e9bbd5309ad1368b8ee7e..cdd88d170a1420d061c8efb8a74cd34022d98b3c 100644 GIT binary patch delta 2578 zcmZwHeN5F=9LMp)gK(h$HH8YnOMq9Ngo{KWASh%QU=%_^4@hvOtG9cB3x&@4Tjs20 zZLOPZR7EJPpPf@3(JZp@2RZsx%RX5$eo!Y`fY*Krx`SiYo=3veEmVIfxHO6)~V zU_UOx3GBxAaST(KO&adSR2;{A#y4+KDdWLcr~&?RjN@Asw3D$5>rfrMh9turM!ssM zkj0x*jx$(F`#V&BiM*uuQu%OUHtKy3rZc|rQi;bVd=6VtEBqE&yt#xL=!)ZYR0nb7 zk1iBo39mm7Pv=^f$ScIBL z8ES&7k*}IYT#g;i^IfQw??DZ`54AN@sPT@YCid$B^1p&gEGJ_Xda)b>s2AUG`~tIR zU&UNZ;RI>rUaZG@EWu|`XXiaE$4l6VsT>Gpq#ZS00E_X!BJ!_8GR*_6JeTD*Uwql1xFya zc2LnFdmhQIc@?$7w^4h095taC)b;!xwc_8L=Xtl=*VBvYcoS-ZJy?i7T!}BE&cJ6# zvds*3>;C^pWsCo^8(a?Whb|XldZRRJ1ooQ3HO2O4%={>+(0Q!eY05tp-rk2HuX4F=UB4e9fs16UJ zZo|76ho3mlPhdRlX;kXZVhk#q>xg@ZFmV_0D50Y9JevJBqKeR7-cM{G+9TT&Gp&26 z%`M8!lSF9FL*-{H;U~CC(TxDJk+_?ZP|iM51I$$#Yu`;mQH z?{l6iX>LNNLF-knR7we*pgN+H*i5KA80l~=wY=0aqitgzL+yPV@i?L19F-uUAFz5t zrO+n&+d(p;Wth(z;sLv91|4--T8UIb+sjXr=_6JX6f64sp#85UdWc4XGi^GEErbqd zF5x5QmPedM3pNu0Lcck4%X+8Lk2)GDL_SeTsN_VGLq!KxWr*PBM#})7O-@}0x0u*8 zbuejSUiILJKNRc@xVMCc-GjbhzdtzO9u513!`1F#-_WRk*w^nK9SjBCy?uS5(clP< s_@C<4TajZ~Es@%^HkUgT?Ij!uWYtamlNCsq+MPa`5ILE)@&Et*FIm_6egFUf delta 2487 zcmZA1drZ}39LMpmhzb@Ugy*OTauQIv8ka&qBDo}H0wO68YL}DX1@df>YvymGuvz*? zJJBXfms(pb+hne?)zXz)YwPBmxkYPkEOXWRqyBJnBYJ<%@3FC-@%_D?=kff0&+Yqo zx%v0C-p^_ABSwi3i;2@S&5mKs93GT2iDqFO!_63+YnFopScI=(AAXK{rSJ~3*;tNA zSdIKyGmkXvz`L*)=b3r7pURzd9KkFc#RB};_5Xr-wEseVcp*QYh1r;od02*Rs0j>X zIv&9;Jc;{o5>s%HSta8^%w>EVp|X;WPf!E=;rtuRY2U(5Ea5GE;1IGIb`<$1JB2LX z#+;vG3GFXY-@A!=?;lLSWEy%uhylj85S4hWM6GN!vRJD}4bbB3LA|&O`IbF{L3|Mx z;2Wrke1PqE0heJq`>cU$kS=S)YV1HSmCCDB^x;#e_WL*=&!Z-G1vQZ$Q4_p@{Mny8 zmgAJ`U(U-~aWQJ(3e=JGpau-1CU^pi@pLNtUqxk{j#3PeA$qadxfe5OAH}8k5o+b* zScku15f+e91=xwDIE)Q=4z)9rr~v~cMjy8hj$ zBX}0I_4_e6!)yq{v`3k(uBB$116xo#@;vt8d#EFrztEpxCh912P&ww6QehXZ7PZ1Q z)Y*nn6BMsFlYp@+X*x`Lt88469HR=tnl!2C)lY!F{^_*QqEg zw`KTeJAk>g51_X8Ez|&4oIhbX?FsC}1^ln2_amsSA40A0FluKQAyg3 z%AJ=`zdMKe-g%6}uTV$)^-|BjmlJd-2a>o$jAa4T2UnqPK?BajHrL;Q@wB(2wmytA zP`lPhXb};jf_Rir(SX{;0pdPFN4Y_RK1^(k9-5Qk?W8unXm55C{nI*?^L?(p2z3xD zO09bd-3^sGVhypKc#I&sV@m|xf-Mnd`gFT32}j zl^RJzF3~`!gkmF8QNpS`O>h%q\n" "Language-Team: LANGUAGE \n" @@ -309,95 +309,99 @@ msgstr "Recording mode" msgid "Defines the mode of recording being called." msgstr "Defines the mode of recording being called." -#: core/models.py:584 +#: core/models.py:583 core/models.py:584 +msgid "Recording options" +msgstr "Recording options" + +#: core/models.py:590 msgid "Recording" msgstr "Recording" -#: core/models.py:585 +#: core/models.py:591 msgid "Recordings" msgstr "Recordings" -#: core/models.py:693 +#: core/models.py:699 msgid "Recording/user relation" msgstr "Recording/user relation" -#: core/models.py:694 +#: core/models.py:700 msgid "Recording/user relations" msgstr "Recording/user relations" -#: core/models.py:700 +#: core/models.py:706 msgid "This user is already in this recording." msgstr "This user is already in this recording." -#: core/models.py:706 +#: core/models.py:712 msgid "This team is already in this recording." msgstr "This team is already in this recording." -#: core/models.py:712 +#: core/models.py:718 msgid "Either user or team must be set, not both." msgstr "Either user or team must be set, not both." -#: core/models.py:729 +#: core/models.py:735 #, fuzzy #| msgid "created on" msgid "Create rooms" msgstr "Create rooms" -#: core/models.py:730 +#: core/models.py:736 msgid "List rooms" msgstr "List rooms" -#: core/models.py:731 +#: core/models.py:737 msgid "Retrieve room details" msgstr "Retrieve room details" -#: core/models.py:732 +#: core/models.py:738 #, fuzzy #| msgid "updated on" msgid "Update rooms" msgstr "Update rooms" -#: core/models.py:733 +#: core/models.py:739 msgid "Delete rooms" msgstr "Delete rooms" -#: core/models.py:746 +#: core/models.py:752 msgid "Application name" msgstr "Application name" -#: core/models.py:747 +#: core/models.py:753 msgid "Descriptive name for this application." msgstr "Descriptive name for this application." -#: core/models.py:757 +#: core/models.py:763 msgid "Hashed on Save. Copy it now if this is a new secret." msgstr "Hashed on Save. Copy it now if this is a new secret." -#: core/models.py:768 +#: core/models.py:774 msgid "Application" msgstr "Application" -#: core/models.py:769 +#: core/models.py:775 msgid "Applications" msgstr "Applications" -#: core/models.py:792 +#: core/models.py:798 msgid "Enter a valid domain" msgstr "Enter a valid domain" -#: core/models.py:795 +#: core/models.py:801 msgid "Domain" msgstr "Domain" -#: core/models.py:796 +#: core/models.py:802 msgid "Email domain this application can act on behalf of." msgstr "Email domain this application can act on behalf of." -#: core/models.py:808 +#: core/models.py:814 msgid "Application domain" msgstr "Application domain" -#: core/models.py:809 +#: core/models.py:815 msgid "Application domains" msgstr "Application domains" diff --git a/src/backend/locale/fr_FR/LC_MESSAGES/django.mo b/src/backend/locale/fr_FR/LC_MESSAGES/django.mo index 61e6f0b6848f3038fe745523b7e166b2048a6c26..c76470df2be646bf8d833467a95ee452481c1c01 100644 GIT binary patch delta 2753 zcmYk;TWl0n9LMoPDRhfK3lu4G=}=0`wOgTpwkj(v1>}wh6lm+ZozkUy>+TGK39bPJ zL(~U128c1f87Ky-#e`spk)kn#Cliei1}Z9ns7Q#)B|P~3?QFCs{mCU z*oFL51~fmc+Q_T0s zBW3{E1am9ree~1L=fmo+7WG^`7ay*|LdG|ns62|Tn2#gXa-Q@-5A6EYi1Q>Mm74e4qI_P9z#8NIp<$E zh4y4JXgb!RR^EyMj3UQuPT@TK9F;>iQT>f4AsTT7YG>XqVgEJoN8Ff;-=UHvkL79y zTCf3kqPFxT>cM{0%6>%pHb0{lau+pV9_Lwu)u_+4q5A8OcLE ziaIEG%-hOQsAQXrTJcQOiUY`)rWrM%1kT2N$Z?wEx%N3^6V0z!fe%n;UN*^lt_pPo zwHVO*zn6+Wa1Qw~7r4an3TALE-%9H68gl&REq$EN_RWp`Ne7(lnJOD$3?I)RrAUy_UyO$#fRA!e3Ai-oka5&%vs_3AKP- zsMpX%^>+|;v^}T=^r9yG73#Umm|jHX8WqiWBAKTT%s}nLT-27fVH0+uR(Klg@jM3b zJ}$#LMtvM#!v**$D!H$tj;xr~>1|nwtFWbl^Vb%g;Kno9kF}UL!|QM{YT$jS_xU0& z!8`aQ&aX5ki4jy%Ud1i=J928KvC0?=LpTgyM^3{WM(t=%75lG_&T!)eyoFkE<4kWy z)?gm(W+ai#4%7-?#^HDZ7h*4}!|SLO-o~Mr&+_#JLcRME9VZJE%v9E<*2@_C-a@)zXy!Docq* zBBTa|*Cx9as<#jg1hf9H?D8J*Qc0(&Qb>?Y+3d(ieM6||yRd)=5L=0t2$knEuCFYu zT;r|ImKV7ycQz31gmzO&ogkWtX9*qg9709uLN;WJ!}V!mqu0!)hN?xxT0$qGQ`1S> zgi?u;Hru)CSe1i8Vi{o(n~6?BeP~43<=!AC%^;G8XqScvQMeBW5Jljhu(_6Hpuc7$V==8em zjhG#=5^*{Ze&H`_8sZ3K@S6`8}$M-Kir#A%v delta 2608 zcmY+`drZ}39LMp8>j5clp(bejlACcm#5F?-xtWQAToM8$E(biuor9~!I-AWhR=GTL z)vOlATo>Cw7;dcP%8lmM44PY6i^{cDF8|2&NB`CPbIz|u&-ngc&-0w$@A*B~pUyPA zu;05HA9~u5Jj7<=;}B!s!gdE2(sHCRE?mI_ShCKTR6L0}IFD|;fqJAi%9wC$!aK1I z`7>@V@i>lm;R%d2#%tara|ab4;XSx$m#p1>eHe-^)X0t?gEzyd7fjerqF($u(zZE^ z8*vuz#w)0f+`vY>g&DY$`PPfwNR=7Y{FjnBMkWqFK{dQ=m%qjJlz&HcESQ_r5eKS+ z>ye*K5^lq6yS^DU;x^QayHHCqiF)5DR0prdG5@(_u2b$_V!6!}K7jM6hHjyzHlK~58Qg(~uo_2j8r8uKd{oqt zZK!gdZ3V8=`EMelP11o{vs0*%zk%w&1=I*WN0!xGL)~{1bsGLa&D`I}WSOYsKz$l& zW(!cyRiHL+3u=ZYFvd$}ip)WrMQx%OD=@NB)PvPnhi!KGL)0Gm6m|T*KsEe5YE6S! zcy-)?>gZ-vJ1JO<+ff}JMz3y|Afp+04mFhvSc8{PBMfI}mSO^yV?9>mt9U>@iJ;j ziqixCC{-e}Z_c2Fix`IAA(Lu;LhY3xJ}PP_3Y)Py!y6d!87ed-(-@31$VN4Ds1aVp zaMWk62pp&e%TOcSg(296TJsK6dxNNsK7&E1S*#)22@g?By?@t&|JbQKLTLJQ?6mIt zh(_Q0jwEkCxwXkjVUQSJQ`tuTNxRGu^3RKkO+*Qy?knviDv2(lo8Y+k7azvy4p(Bd5+Itir)-|>iKuV$3f>rWkAwfE`?EsbVV zn_8cO7NVSZjL0ICw9i<5e;VVugV-M^{&$Tbx0ldLXw|fmJ%sig$?N~r=aDNTo*=3S zi_o6vBXSA0py?&nCY@5HT4E0|KxqH2O}p)a3$^q*KhUea)Xu#YI}`2uA-T`jVYMEt>*{y+ zb$W*QHP^~7DzdseM?1Scm){$8jaftE*1(W^a4grVb$LA0WLw>b-Mzi~&E@&ut>w;K bXO=U^*4<*-Sm6I= diff --git a/src/backend/locale/fr_FR/LC_MESSAGES/django.po b/src/backend/locale/fr_FR/LC_MESSAGES/django.po index 6d61f7b3..5f8c16b2 100644 --- a/src/backend/locale/fr_FR/LC_MESSAGES/django.po +++ b/src/backend/locale/fr_FR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-12-17 15:12+0000\n" +"POT-Creation-Date: 2025-12-29 15:15+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: antoine.lebaud@mail.numerique.gouv.fr\n" "Language-Team: LANGUAGE \n" @@ -315,93 +315,97 @@ msgstr "Mode d'enregistrement" msgid "Defines the mode of recording being called." msgstr "Définit le mode d'enregistrement appelé." -#: core/models.py:584 +#: core/models.py:583 core/models.py:584 +msgid "Recording options" +msgstr "Options d'enregistrement" + +#: core/models.py:590 msgid "Recording" msgstr "Enregistrement" -#: core/models.py:585 +#: core/models.py:591 msgid "Recordings" msgstr "Enregistrements" -#: core/models.py:693 +#: core/models.py:699 msgid "Recording/user relation" msgstr "Relation enregistrement/utilisateur" -#: core/models.py:694 +#: core/models.py:700 msgid "Recording/user relations" msgstr "Relations enregistrement/utilisateur" -#: core/models.py:700 +#: core/models.py:706 msgid "This user is already in this recording." msgstr "Cet utilisateur est déjà dans cet enregistrement." -#: core/models.py:706 +#: core/models.py:712 msgid "This team is already in this recording." msgstr "Cette équipe est déjà dans cet enregistrement." -#: core/models.py:712 +#: core/models.py:718 msgid "Either user or team must be set, not both." msgstr "Soit l'utilisateur, soit l'équipe doit être défini, pas les deux." -#: core/models.py:729 +#: core/models.py:735 msgid "Create rooms" msgstr "Créer des salles" -#: core/models.py:730 +#: core/models.py:736 msgid "List rooms" msgstr "Lister les salles" -#: core/models.py:731 +#: core/models.py:737 msgid "Retrieve room details" msgstr "Afficher les détails d’une salle" -#: core/models.py:732 +#: core/models.py:738 msgid "Update rooms" msgstr "Mettre à jour les salles" -#: core/models.py:733 +#: core/models.py:739 msgid "Delete rooms" msgstr "Supprimer les salles" -#: core/models.py:746 +#: core/models.py:752 msgid "Application name" msgstr "Nom de l’application" -#: core/models.py:747 +#: core/models.py:753 msgid "Descriptive name for this application." msgstr "Nom descriptif de cette application." -#: core/models.py:757 +#: core/models.py:763 msgid "Hashed on Save. Copy it now if this is a new secret." msgstr "" "Haché lors de l’enregistrement. Copiez-le maintenant s’il s’agit d’un " "nouveau secret." -#: core/models.py:768 +#: core/models.py:774 msgid "Application" msgstr "Application" -#: core/models.py:769 +#: core/models.py:775 msgid "Applications" msgstr "Applications" -#: core/models.py:792 +#: core/models.py:798 msgid "Enter a valid domain" msgstr "Saisissez un domaine valide" -#: core/models.py:795 +#: core/models.py:801 msgid "Domain" msgstr "Domaine" -#: core/models.py:796 +#: core/models.py:802 msgid "Email domain this application can act on behalf of." msgstr "Domaine de messagerie au nom duquel cette application peut agir." -#: core/models.py:808 +#: core/models.py:814 msgid "Application domain" msgstr "Domaine d’application" -#: core/models.py:809 +#: core/models.py:815 msgid "Application domains" msgstr "Domaines d’application" diff --git a/src/backend/locale/nl_NL/LC_MESSAGES/django.mo b/src/backend/locale/nl_NL/LC_MESSAGES/django.mo index 66894f7ba0373e8b75bfcc5e4bcc95fb0422aa34..afea428accc4b28a94bbcaa18f07b7546d507a7a 100644 GIT binary patch delta 2707 zcmYk;ZEO@p9LMpYl(sze3Kl2=?b-*BLfhk^fIX3?YRf|fvGP<}yk58EdhK0%4;6{w z5))!VkQbarn_zr{z5q3nnusxoQZ%NRn2>-bpp+Puh6EEswZ@0|{oO7}C;jhdX1hBx z`=8luf7yDhA^GFX%-0PiLChyEPc-H&?8@dq8J=v6jkj?()=e>{6yL@Qyo^Eo9d*n8 zsm5es8&1a%@?&1)FcXjBL-;1<8Iv^cQJKbx3s{IlZhHim(Eh`17jw}<+Eu6lcHty! z#&Qhc3Os?D$R*6jA>4$ui#J$VbR$8Kbq%?DV4pQ85A2&%tXY=~N{M`h;KeDbe>-{r(oyoTB= z89c5s(2Sd~1C`RVs2c}SPj(aO+x&!jkUvoaX0V=KtVCUR0M%bRW?&EUV`52;i>Vw# zt;t7Nj2BQH4x^svF7jrYG57pGsHMneR$78-IA;Q{7#^fu&MZ4Ih04T#sBxCgbzaw9 zsQ#0mQ_&2spk{d0{l!hxn*NGp-Hah)nyC*vo3R+R1eK`kc49RKP#Nh*?S=PI{a;57 z_ygA99bB#Vzhs_sK@&2DX~hZWu*n=3mrx)sHy4dp&9* zy>9z7YT#>Fiuc|2T-HnNHK>d>V?Fj1lYhPi<`Yh6fGem8O=M^JunHf;5Gq6Opcg+w zUH=<);v#z2<~@m9@f2#HJE#o(je0Oone!o=jmp5%vZV8kuHnQwPIRKy@C@q1GJqL) z3AOvbL{01_W@5oY=e1gZ%1j-m-v*pWJAfLf12w?}>bfLOz{l5cs3V>t5`@|Z2$ea6 zUZHM6uZ$+JgV;_qruwtzC6&bSrHV#`=pA=*KlLsmMDQx57YNLAgmSw|4a!EMmI$ap z;Vnp~LiJ{16QM82gF@bQi<3|#T}98xqNj7D{FDaFrNQl&(3S>dkIluW$viZ{Ul`XD0c2;=xGR-(|H&qE?R`ZVQGxtVGO?#(Y-P z?o9-vcAJ&xiG(eGAP`A};}{S2`E^%n)Uz$s>DiHEMbf>*QXhKO4Q$H0J-vB*`h;zF zS$z>Y?yy^a(MEFc!C3gPjjXNDp8~`E{k$;6D`XPIOz# utE;WJ9kRo*N^3)E$GoyB5xc{V#r^(pWvZmGagt_Wry_-G2gVBTW&ICeq$Q#N delta 2555 zcmYk-e@xVM9LMnwzwV9{IS4`_xRcIsI9hGa>&GOc zIVUICmes=6s!^L!Y`Myn&G*|xET(jnEE8ALs_=kV=eBFI*e8&48pU>yM-|y%1 zd4E3NW31_FL*#O1@`Ry;i93lelZ<%_yPSMb=2DHZa30&S`Zi;Hco@s@GYsMt)GdvR zjB(&rOv6s(&jk6%#1Xt552D+ch&fJWF&!Uc0iLqk7qFD}RlA+ZMSj{I)BqbX1)H!0 zTX7BUM@{5Y%)(RnIR1#wVF|NJ#}l}O@y#@q6?A-q6?hFbz_KNAy;w!N2s^L~^?(^9 zDP|VA#mpf|Fqdurz*V&WMLo~QO}ej?4;R*AD&w1aDtBNrCZmN~Ss$`^vllhMKHD+W zz;7VWHj|ixCvho$kDAC8Y{kE@2se;#4ID(eOi1~!rScM$4E!4P;5oZ}5wmIkiJDj< z7il6+)C9AUuS^~m<4U`~4YlG<)WEw?TQY_kZyYtjA2P^)Ih6}^tVI_mq!Q~;H$H3o zHs;fw#k=r#)XH6)r1hACY_HjlWoV(!P82KgG}hxks0>weFf?vU7WrREB|?V|$rLIB zPL^GV8K~5@p>7;Nt!xx|mN|r4$-Aflr?3LgqpnM3U-djUCSopXtMmD|8>=Ezv?twI zh`p!>j-ggGfxMAs((ZpBwG}5(TQGw;3B0!WH0^WDwhz}aTV>({)IdLD5Y4jq^ZQT} zjEqpx4ENbzjH34R2$E$pi9FkUjyjBIP+M>wb=^%2U|McGBXy{=(2g451=NCG!L>M! z)p!>9K4MbxVv{n9v70aaIF1KUr*tX5O0pQ0p&Hc6I#C&T)%GxMqCJ5F_$z7w%^VyZ zzMZJ83?j$PyoihR{zs{3M(?0f{R`^GOPGe&Q7gZR91r8-S4u0(M{S)CH9#3^fB-5p zO{nX-QTJP@Gc<%G&5WT_@Be#L8gL4=vKy#9_Iu(tmSQFCYSf|YLk+keHP9$>i#diG za0WHeuTatd=|Ek01S{}3Y9eRtwpkt@cs2Uy zZ?W4WcKawQlV9K?cm|dFZ1z#lFDfMen$ZqAYVkF^7r#TLDuI)xfpbweG+-aTj5@T} zQJK4e8mOLGC`0Y2h4mwEq6wiga1dAF>-Yf9`Xcc?bgYQ~prm6WUlgED{c_aAYA_kY zsMqOvRAx?~8$ZD$JdGOYThs*SQP*9<1k|%O5?w@?xJR!_H=&}#qxKL{LudkSa~gK-3Yth^GinckDPrEXNO`mU^oM zjZs%Tp_}Ypt&vTQz1hl7iQWG&>Le-2?Zi$(<+11imnX8C8gFN;?BG*ps)f+jYx|VZ zJ;ZimJ+Y0@F;Q7Vkjz*a=JP&cOT792XF9beLjNLk4EU)rJ;eP4B@+9oub{S$c#^0m zyhIz(OXz=tkJwEtEKk^tM%1|*Agb)XTRdu4EYvT!j)R|gh)^kvoj@u&;3^@)6RX94 z!u6)8=oKy_I;Q7SKT3%vxi?39+yTeXNHApeL}$_)r;oXRON%-^t\n" "Language-Team: LANGUAGE \n" @@ -311,92 +311,96 @@ msgstr "Opnamemodus" msgid "Defines the mode of recording being called." msgstr "Definieert de modus van opname die wordt aangeroepen." -#: core/models.py:584 +#: core/models.py:583 core/models.py:584 +msgid "Recording options" +msgstr "Opnameopties" + +#: core/models.py:590 msgid "Recording" msgstr "Opname" -#: core/models.py:585 +#: core/models.py:591 msgid "Recordings" msgstr "Opnames" -#: core/models.py:693 +#: core/models.py:699 msgid "Recording/user relation" msgstr "Opname/gebruiker-relatie" -#: core/models.py:694 +#: core/models.py:700 msgid "Recording/user relations" msgstr "Opname/gebruiker-relaties" -#: core/models.py:700 +#: core/models.py:706 msgid "This user is already in this recording." msgstr "Deze gebruiker is al in deze opname." -#: core/models.py:706 +#: core/models.py:712 msgid "This team is already in this recording." msgstr "Dit team is al in deze opname." -#: core/models.py:712 +#: core/models.py:718 msgid "Either user or team must be set, not both." msgstr "Ofwel gebruiker of team moet worden ingesteld, niet beide." -#: core/models.py:729 +#: core/models.py:735 msgid "Create rooms" msgstr "Ruimtes aanmaken" -#: core/models.py:730 +#: core/models.py:736 msgid "List rooms" msgstr "Ruimtes weergeven" -#: core/models.py:731 +#: core/models.py:737 msgid "Retrieve room details" msgstr "Details van een ruimte ophalen" -#: core/models.py:732 +#: core/models.py:738 msgid "Update rooms" msgstr "Ruimtes bijwerken" -#: core/models.py:733 +#: core/models.py:739 msgid "Delete rooms" msgstr "Ruimtes verwijderen" -#: core/models.py:746 +#: core/models.py:752 msgid "Application name" msgstr "Naam van de applicatie" -#: core/models.py:747 +#: core/models.py:753 msgid "Descriptive name for this application." msgstr "Beschrijvende naam voor deze applicatie." -#: core/models.py:757 +#: core/models.py:763 msgid "Hashed on Save. Copy it now if this is a new secret." msgstr "" "Wordt gehasht bij het opslaan. Kopieer het nu als dit een nieuw geheim is." -#: core/models.py:768 +#: core/models.py:774 msgid "Application" msgstr "Applicatie" -#: core/models.py:769 +#: core/models.py:775 msgid "Applications" msgstr "Applicaties" -#: core/models.py:792 +#: core/models.py:798 msgid "Enter a valid domain" msgstr "Voer een geldig domein in" -#: core/models.py:795 +#: core/models.py:801 msgid "Domain" msgstr "Domein" -#: core/models.py:796 +#: core/models.py:802 msgid "Email domain this application can act on behalf of." msgstr "E-maildomein namens welke deze applicatie kan handelen." -#: core/models.py:808 +#: core/models.py:814 msgid "Application domain" msgstr "Applicatiedomein" -#: core/models.py:809 +#: core/models.py:815 msgid "Application domains" msgstr "Applicatiedomeinen"