From bd52c075a5fd7e34282af333015d839ddb37f8ec Mon Sep 17 00:00:00 2001 From: KrZ <124951513+KrZ-W@users.noreply.github.com> Date: Thu, 15 Jan 2026 22:21:02 -0500 Subject: [PATCH] New: Add regional translation support (fr-CA, en-CA, es-MX, pt-BR) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the ability to fetch regional translation titles from TMDb and use them in indexer searches. This addresses requests for supporting regional language variants like French Canadian (fr-CA) which have different movie titles than the base language (fr). Changes: - Add config settings: FetchRegionalTranslations, RegionalTranslationVariants, and RegionalTranslationRateLimit in Media Management - Add UI settings in Media Management page for configuring regional variants - Extend TranslationResource to parse TMDb API format (iso_639_1, iso_3166_1) - Implement FetchRegionalTranslationsFromTMDb in SkyHookProxy - Fix MovieTranslationService to use DistinctBy(CleanTitle) instead of DistinctBy(Language) allowing multiple translations for the same language with different titles (e.g., fr 'À nous quatre' and fr-CA 'L'attrape-parents') Closes #10482 Related: #7788, #4612, #2644 --- .../MediaManagement/MediaManagement.tsx | 118 +++++++++++++++++ .../src/typings/Settings/MediaManagement.ts | 3 + global.json | 4 +- package.json | 3 +- radarr-title-search-walkthrough.pdf | Bin 0 -> 56267 bytes .../Configuration/ConfigServiceFixture.cs | 18 +++ .../ParserTests/IsoLanguagesFixture.cs | 79 +++++++++++- .../Configuration/ConfigService.cs | 18 +++ .../Configuration/IConfigService.cs | 3 + src/NzbDrone.Core/Localization/Core/en.json | 8 ++ .../Resource/TMDbTranslationsResponse.cs | 8 ++ .../SkyHook/Resource/TranslationResource.cs | 21 +++ .../MetadataSource/SkyHook/SkyHookProxy.cs | 122 ++++++++++++++++++ .../Translations/MovieTranslationService.cs | 6 +- src/NzbDrone.Core/Parser/IsoLanguages.cs | 6 + .../Config/MediaManagementConfigResource.cs | 8 +- 16 files changed, 418 insertions(+), 7 deletions(-) create mode 100644 radarr-title-search-walkthrough.pdf create mode 100644 src/NzbDrone.Core/MetadataSource/SkyHook/Resource/TMDbTranslationsResponse.cs diff --git a/frontend/src/Settings/MediaManagement/MediaManagement.tsx b/frontend/src/Settings/MediaManagement/MediaManagement.tsx index 6547415336..e516104a6a 100644 --- a/frontend/src/Settings/MediaManagement/MediaManagement.tsx +++ b/frontend/src/Settings/MediaManagement/MediaManagement.tsx @@ -461,6 +461,124 @@ function MediaManagement() { +
+ + {translate('FetchRegionalTranslations')} + + + + + {settings.fetchRegionalTranslations.value ? ( + <> + + {translate('RegionalTranslationVariants')} + + + + + + {translate('RegionalTranslationRateLimit')} + + + + + ) : null} +
+ +
+ + {translate('FetchRegionalTranslations')} + + + + + {settings.fetchRegionalTranslations.value ? ( + <> + + {translate('RegionalTranslationVariants')} + + + + + + {translate('RegionalTranslationRateLimit')} + + + + + ) : null} +
+ {showAdvancedSettings && !isWindows ? (
shvK+qP}nwr$(CZF|2bIXjuzGe5q6o$jQ%lde=>)pr%C z{6A4zMmkm~(&PJ^cPK_q0tNy*LrW+g9(qv=YiAQjdQocwXOn*>Ms~&~^wK7_X3pjW zOe~B{e0)$&&W!b^GuTV4c`?R4H&3kvb_^$UBOh?y9-khe2F0H4chM_ibl(zqkdx3I`Ut zz-jEsJh5vGLGSF1Fuc>9Bp5uzbuE`OM^>8H`H2$T`>X>{Rnuac6ZgMAzi$_IcP|2x z?loP&oWwAnjs#%(CZb?S0;42_2)VS*01l6X*bKBhq%HB~cJdGay2!H*D3cHbf2WVP z2g3L#DFMz5?ZtA#^nUZDZV3e64W&Tc#R&pvpW;>fng*ZuWVsh%_%2RZChsV05VBlh zjF4LprPj8lbpHPp1Ez}{DQ*sn(MPq^?K0dHcqS8cHi-&>MHn=I`ft(sbwlcyJy=Rq99+nz zV7L)E2HNCTZK*L$D%8srwej^0MtBb6RV;O})0N(;6m?I*%@aauHvl!u9sc52G-ZQS z6re+hTpH;V45I{Ym|CJJA+4aDfN53-onz~f(KK#mB+z2w7=WLmiC~oP9eKA4!G9(j ziOfZ@4t`uXLlT}el{i`hmdvi&?#CV9D>4)}A;fCsrOYyzLN@QGsQYOd=m>9$&d_MD zY6CCHaVkB&djp~C5u%^7Obnh7`orW|;(=A}rV{r&Q8MF^1K3?SS71&rbw|5ju2nmkbKszTkF`$L-@;5I^6x$XOq zYukN@o9-9!N??yeWhNE+?26dapaV`h2Yx(!m31!Os01BuvB@Q%0I&#*2gql&hA>XI z)I|0$ zrv)Vse<>k5#@R>w+nYo+=oGI^%O;d_emZf;+|i{dO?Y5(>=n{c%NI)$2&--`)5ros zBmE*N={r;{*@Kc=$F7}lQ^zDIKunX*&E!(WYUojRT^fhEY9tj?783Mo!vmoKIrNVc zMOcIss}GK0fx_&Y{uIP?W`C^EJ1^KOdNn%L0Y~SXU2qz?v?<1f*uCJ)>`)&#RBc`> zk%sh@aVfV(rpr5#?b?u|D7I2;1`tY%6laCs@j2{qo@tBTQ8j}Uo?zwP$BLZq$O^L>}?k2_TtVzpk9Vdau4uyNY2rU@Fgjt-u5wJbVes@Q@4)3fAJMfQQV?28*A6OShaORYf8W%qxH|yn?02P_X!I{ z6RnnSs8^gNT`Vt<89-EnW{(2{S%s7{Wk%bg*(+cl+-ONGWhCjy>&b`cZJ_@-g2^zbGdU(2Ussf~eUbUmCWl}cbk!R!iIfpk(y8kiWcdb2`-KW) zeGKOUrj2zvnvhN~(GW(0SrRy5i9a5+gJ<-Z((9K8;vrl0J4Tpd;xt8;G7s6v@WU1o zP3o+)T<|CRm+iaTDrFo#!=~K#d%YS)6nxNilSQS2ec95}x-OdKWT*jMbmk`fd_Q*{ zN@3$~lctl<)u3cpb3})7tU>A_PTSdvB@tMoQyHqgn!zyjTfwBw6^v#}aJ0A)*a2LH zA=nM`N_3|x6mXB*+JKg)4d(>+&|u``na%P4{`;)?)!%; z)%O^8p?MGtmaKQ!xT-`*$UwX8t^_CCl`!XN=($g3=4#X1S21qi{yy4?b6b!8SZwFk zo7}jA98A7ldohph*>;}~)LQ#0N614sy$WRqJy)MdVn&(@Hu1jAx)-K%KQTUVW(dC? zfcpT%>Uehh>37jxFttOC&)xJ|ox-7CJ0pRaA-eG#S&I^gC#mYhR2L!ArQ0*tLDgbY z$Oyc$#+gd#EaM~liF~%cN88e~YZK2sL^0c|m$q|$s_Rup*Gy*6;um^6S6i`V)ZM<` zd+AN)N+TUP?HJdg@)19!FbdHO>|B*O>e4Y<<|T*t$Yei6Y5SG3DOz9rV1VAc|4JvN zZP{Q(sFbOZH@Lmou`Jxz1omrgq)q2UH(u>Vxq5xywW4>5@t?=w=MJMgU!wv1BJ?5@ z$}?mlJ8fQs%bT;`&nEZzXu?C_^Td$;?!=jr=9t%@?}v}I;N)TVT{>Ld48z5FQ8QYb z>W+SO%k{kK+D!(;0eaT5-@LX@W$__)UCMOv%D$E2KFg2U)L~l9>?a;ko&TyHEV#C3 z^SpvDed%llUW##VrG4+6=}9fkYpk2o_8%p^>u6b{fB!-W^O?2&Ow2MLj|T$UB2<)N zI2wQ1j1F0EJ*fJB^3$4t!ncWl1u3j$;R5mho%{t#qWyz1u{HkxW7mJ9{~xF^G5?Q< zje~*Ve+K37SZX^0;7aaPLNK36xazU7+wN zWV3UlADq?UhH)c9w(hvMrOvAwR#41>DRKo4-B|?)f1+oMLSJ#Le6;h=kXI*N1TyI5 zbBfWH@>8{zI+CC4adjaS%jD|W(fRERP`qS_M(|kIe9}hTUbcu5f;W_z^OAc2-kH+^ z?|3xvC3-YwuZs;->quYGm4M|Eu4V%NDR^(=z^56HN+$0e|X zc{%F@zO}J-cj3Wx*c5@TP+sxI0f;^B6%())g?Ul0g23B}#;yd@X!KR-GV7bd@3+<*gbRcc-thgY!&%wEHG`^*@^*@M43 zmstF9Ik+0C_nz!NU}h6pS3&PEx(QB9yv{#-GB-!O)84V&aUE)t9ZxN)54*a*)knD+ z#YZFXH^oP!2He4K;uo~;-%Izs$6UBAu50euNrkfi!iJ9~q3TKxncD&%WJtL~GR<3? zM7UvG7G`~6RMIpfB|241h6XXxN||zSbL*II3~+^I;wM$8-b^sMZJR>n{co+65o|)( zB6AwESf$z9<}D4&O$Cn+O(+>vO(w>}3amYR7r=DIu>GenSFR8`p78pqkfjniA-*rn ztY2*+BX}>!j=lw>8x>eIbM+X`C1_t@Zd0x*%I_>PV4C&l2j5>BzC>F zcTP_{AS;iCoQOsC&P=W6mUPf-1ATg8;MlreN3l-3@J00u(}p6 zaL!^_Irm!{8(}c&R2~f!mF5(_$Z!a`F}4lQKdi{4>GqN?eq6#yiK(PI0Iv$e)7(z3klsxih_=aV28?$xAy*Yx z#)Wh|pSw!#3Pm$&E~_i?0D@zy4=%M#kZhEf0MvLD!Nob07}HWT0j#B@D>#$aTpb*_ z7#Pr#PvGh#A^f?@x!7!qi zbA>T4>unn5rbgm53x@o1sv?QcYA->Bi1#cMDOuxpr1_Ya!VTEn++?$#5+_BG{tjy3 zE3M@Xx(~djRZ9!9{v>=;rsIAflgOXG(tMY`7P39-u zOL4*Y$3)M4FdTTw?ipa(=-4JBqV#E7%r7ol^1CePr&m_cwLBaxSTG=M->JZ-d6LFb zVme^+AO#zotTH*tZj!qk0;!bv*3uj9g?Q72{zAx+Z`ttM%_x7Gmv8EpM}ivyimdJS zBys(qiRa2!VVg*ob`>uH54n+<`KXGY8m7WEN^5W6fmEW?o(0Y#l%g&gh8uK7s#c~ z$G0GuZkJLmgRHe~V3j$}yNp&F;^21)rHuXALYiSs+UBwu!n*x2T&T4%jyn_kq;Khl zuS(XS`R?Vis}O|%{>XLh_Y4Pw^iQ0708u$sbwi*{PsQl0bBqQs&KO@96fAO(Z2m1T zyuLXuJz{hwMQoKt9)k8MEbON(ZLU3(K}g^|!;$RgfJ&1QM;5hJ4ti%5nO4a8_Qp@)}Mf}TB{xQ79`d(C>Rn(Q+E z;0=?)orc& z)ZFSr#ad52rKe}O^922uyLV?u?UQ)xFNPe{uwPlg{5JMUC8(7UGhNmgfK(u~*9*4i z%{pZzrcF4J%?;d>3#{{db(h47-un7c9cQ%WwxV%roLeh(P39G`ip8KwvIl26f!ZHu zYIXoVQJi9+b-`LuoOH;oBCk7s4S_=uS196|5ub^6n#X=muE!o$&^_g0Ec2I!KikDz z297Zx?6Yuee$1DkRKy0Q;!%QxQFi}Ug65x>r+T1HCNofh@s2NtXGZda4@O&L?W%Xq zQU}7-+{LmOmeL1?Is{=JdwCo`2SNZ63!j~Q*W-pTo&cL5q=%0tbkK|tR_o^zbbc4N zB7R=|k22%5f!X2%R!491s-c}pB%U$rjTSz00R3pr-0X3cFN%}BI{kuhF+cTU?k?6c zGp@Wt>U)t2>r0-e;98>PvE7|o=8@7%N8E7OJePWwoK1f1oXI+82KA!52BgnHK*s@q zG#64C9$q^35BHu#C25l7X^`g$!?brmy8^ee(1>Tq$hs^=t^rfQ{gvJ?JmOpG{r`oU z+5bn>%)-p^zf$vvHfP**JL2pQ^)q-TS=0!$y0m`3ZvVz+5+mo=8No za`I>Vzt_VaPEDk%-gk-2gEm3f#NUbmz@N0CwYujEv(L}D%QHQ`F#f+8SV0hI*Y|I{ zZq(I`14BU$tI)ZvKHtPeNlI36NVQL1@d#Z>Gk&^FOs*(rFuSD<_tDY4zNN@J_Y_*S zn$_Yf99jOF={2qN*z&pver^8d!XvJl`um5wxxS=lPr@EYO^h;$776%lf5`40N>~8>c4FE{MB7_TRRW8QTriV_N&BM`wAMu`^Ui{MBwI^uo3~i zlc_`dDP)qT%ikr)Jua5aiOI=1$?=NBi1PY;YlR-#1oiJN-}mz8A+fLRAqnI!57q>$ z2%-ZVkNbxB!}L}MtWZH~;!B{+iMS!_4Ls<1rbGV>pVQDi$#F1i3h`AU@a|i{mvMeR+@-a6J;_KpwoODQ z=jqW+I zZpV6jFy5qUuk!aF+Xol;!X3iVAP&l;>*hNew6iX1n)HB6_{%rG)-;T>CqYxNQDj#{ zNcAAA%2(j2En}^+q!H#!o8oLcV_$rUr6YRYEQ#eS03rW^Q@>tGec_*K=YOkC$1(VO6j3;2??Q0iy{tD(C|Ngfx&|YfUKe>C9YO9 z30hORHk~eu$m@S#k*4$8HkLJq)iPtYD8y(D^+t0TKENZWghHOb3SwaeF zX?@XXEQcnctsHY(XycaX$VeZ%Fb)enPsd-mg!bD!0s3>Xtl^w21|ecw@+VrigAi0MrIfpS zX5`|ThcRmle7-ZUuy<72xNWsB4^pWhj$_|zlZ+AVGC3u;1iGG~YQ@Z*xS;HBsz7hG ziWkCEwqA_7K8?4hnPJoQ9&SZK;&O6_5Zu(TEL-yAT~EF%X1tekKFKR}e6~b{Z^J@m zO&p@WST9YqU_KmHJR9XmUNvqSG_I}6ugFvXjVZ25pD{Vv|Gi7}McZ)dvgfge!_aNO1t^ zG)aFkj}oK=s6Ty>j4J>#@2OC8#pN=M!jR%dTWMvXlmx{u5~zduIY=ik-9TmZo~57DK%()X$&r}Ym(U`m{^dQ2-ddWeC2k_sxZyV(_-44 z7YoY=aqme1nPdLCHV)Lp=zE>r$RSN!vRKu;Fg{$1)imo7u-enT!q_@(iKTwY)f{8p zRJvN91Z%1NZ<89M<-c~#HQ@>ED~y}i|EAzdR%;UTXRV3xZ-_mY2SIXFBe%d#?D0x0 zoFeCKl1-PNln9T2X)W1Qaq4n5x_9j5yA*3XT^lyAHxUM%golo!3*C=cr57a?73k0sG*cq)H#=TLTC z21af#-u`jjNlW1d&g5^tg$uMIx&uN)d8KUTI6M04`zQI5vO8rzrT73K&Khka9Z4in z8JVXuQy1-;b}Z!iDgy>b!{$A?yG+B%avXJOwoB)v{9(`NU{%;xm!D<0CijB+L#@V_ zJV!YY^&e*jNAPez+Vh>@Y+Fn`8EbC*S))&a1|fwHp5Nwlfos?ZP%Lp)VaD+?kn3%r zpMs!>j;%LRBs<4^dHAMAD%rt1rCN@)xSKT9lnbqUo;<_o2Yp?ez#Tp7^=zfyd8>N9 z_{JL6a_|-wUQcnp)T;Zd67aMGBP!y#T%r(SDfq+WSm)qJRtEdAv&iF-To#f5y#RL= z?&9DI6yHQR_B4-|A8^rj5*LUrlC74fn98*Nm5gw3^Nr0{j4)i@ZT+5|xlrG@^3+eM zv2FaGm1$BHY<4UvDJbuhf{OOc-S$2E)J_EL{1rg5&J(8TsR6E`C<)9DdiBIme!E9g zCU?HymsF4z+TVp#TvR99FaTI04O;C11Me5V=>vG1g90qX-G&_XEt!cMZ&H%(!0<0K8BBXXiZG z9*NtMl3mqoH3`PQT|c+6k!ZOZm^H(l)MPCnNKCW15^ zFQ?ej1Xffw+!hMEkVngUUVgv3!V9$Z8QxmmajS%UK}GB>y(wvWa{|}|0*3*eN&*Q~ zm9eflkBch}ok5|k(GD$TU>3Wtr;zf>q3@5VXIoTG%z>H~D=!^I-@T$G3)FU=7?nSr zx*oqOaeS?`tZpV-xBe=ECe$;trcNIGEsGZ;KhhHg`sU-qZ3i!;VH|s_oWtdPlws|n zUXI~4*73qR)>@9{CR^;M2y4@=V7@WVgU!DGp)fVa%NuZCiYvFjUT-7iy%yxkY|6vj zi$EPMQQ0o~dku>P%r{mINasBGJFD`c^ZKyQl-|G2pf9>VFql$)ZDggB*(U=T1|6fE zd2>(w&g^GA>9o4*pkI4D8^)ceX6!NnF77B1n zwKnm2dC5OjJS$qT!RYc;ABxuaq>E-|1)-tb>0^?slI@)il5^iBQ z-1hx1Ck4ZxC2uze!tTbw&(U6;;^zHp-kTo`fA3tsWWQgsRQw@ChEEe5579hYyPD#q zT(^KE`O+L|qYsZdbzvhdd@E>|_Ia}WC@b_#4c)dxnA+e3S~i>ef5Dd29gxwvh%~Ss zfo{?2d2kD~W)A`Iab4E!0DUw*H`gwpC-{E;U+MR2y6+!EyNf3 z{z(jc3lybf@fHiO8Kgi5dOKv{j_E%&Bq#xYQEE|V@yPv-#1G4*xVbZ&e>uUG*4_o% z;_a5^W&qN{z)yQY0TQCdpwoRmEk=0|+lQeRgF1R-|2(Gunz1%ytNigea|LFw{L>of zWLNr!dj^Y^K6Jd{^-&rVq#TURI}6hWk}V>OP80@h!g1dIX&nv#8TsGL8ZH~KJ(6%| zuV^WXq*exBYhsgZDG*nNT|3uJCql4F!NFLmRo7Vl7q{MyZjAICb()oSXwl6zGt9eF zcIZ>nkk$I&ldV&P_JkdpqfhRUeJ_rVS(K$Ej3I*hpxzStv_Vy3(qf7x2$HHJhaI^A zmq#jdWizH3_90Np@{`MMjbiK4zm(DNC4^;}0LcR2;3`dSI9?5pSc+Z>g!D7K0%#0FUEZ&l5x{VLzd)LTS*u@`g5*2 zr6LAsGxsra{@S_eiupFmmT1`JwfM)Jt!%h24e2XU!Iaz~xp;=MP@0{RXPyHIZI2Jr zn=2AQU^lJY!H6%_osg>Y5i=u{g-$Z}6MvO?o*NDP%w2xotlRjb_-ODMsAcU6^% zCq{Qk4ben`;TqzcQv@6L)Vk&f_X)S>YZBJ0(dd-Klw=+k&&AZdgb$26n5deBXb|#L zM0TaD7(J6pTxg_NNf%z&ocz0fsd;`d=ciZCEr2K+`{7aCsSN=y)O<{rG2`b_lv3(qTdhhJn3dhpueVdE`B`@hYY; zr{r2vr9eCxtRpcb{6_kw-4ePOAB}BSa<;=0(lJq_iuDFbI5V!nC3bHv3OMyV9cUTR z3*1H#6AK+&Q#M$5fJgrIwIdyfS3w+UAaq&n$@8d3lTr!y)pMHz0#f(e^2U?4lp~Zm zO1sx;k{%8+P3z8tBPi9<2dZhGbXikFme5v&IW~!aT}o=#)#MCZ<`wAmM@LBUmX)R_ zhL0Y}OxGDWXdJNLC+TPEGomiaz&j7>x!Q~=Emk`>NAYV#PQ?pWM&j6-Vt4g3tZC{p zIm>*FSk($U=Om87+&`Zu@u@>DB9AD#lJOiH%$Bs>ka0Iw9Y{s2;TJ1cjTynz3E&@esVT0)|fSSXl0`gug{lhuE0pF17YLk{k9q{#L zbZ;|iRgt1<-)a78g}r0nx)&BSfZ^Q27AUI~0$-sabf~m8)9v*0TDcri;NGyRmPF0# z&@#UkFI_DYtdSH-bP@ssT5?N5x=#?b$|PvU+N#amEK6qfIk$N&0zP5k3`!n&R}ohc zW)9L64vzx3HJ*SkXRkXIcx;@HKBtpg9E3cUs$j}3w724OH|y>#Bb@-YVu5jDBv!yq zDbfPoe|@2~-a~9|cbp*yTjsrNpi__M{`>W!Zg(}U{F5bgNzYzElJ?3ODYy}@t=aIE zKXqbLV>3Br$+%+?XU4~Ujk)Z|Q0ZN3je+AT68l)TsSw^BCy+M!k=jW(*glD~J}DU> zhK&dc4GI3dpo%N|I;TV zR+^oT-(Uy9d1)yWByJ$83r)b;>giFhpZP$eH_H*NmOH=jrWzsBVdEMjUmblo%CUgc z?CYqh$h$Q?sExf{d+T^r(Nw{ijH0+XVWoXh!`b`DOr=tUbBi-uY!47_Kg*Q*Ieht< zl1cq>vClDg%4Ay|ke7XLZrm05a2Lq84O`*yc2>nMh5&%hQ70xpO zzy9we4@tU)tfD)~q?+^>F5*?5yseA_6}CQLChSJZ5REW?xsOLIFOST|7((jy-d@!ut8vPlVu#D9U(n5I0~b7cV5;10n(lS8 z>zqOLs)KJW4qWq754Mbti*Ju1ehmr0WXOAq%U#Si`S{Y`;CiG5&J#2L?Ce;g-^$rv zmhlpfwwH+c5;ix99kY8xIhRLR=BGwQ=+FnN>-l`%3(&l9_Ckl?6;7~X0m?p;0OhBym;fIKTtpEUaCE;wj$n|bd``7>!^ABNi;{1%v_Rh`azK6W2 z(=>09{w%W(>*vP$9>M6sycE8vPw>Z92!B1QMZBTil)kB(VoXm`zC4w#k2v0j`EIS$ z#I7iRZ%WqF2?908-xkenNJqK5lI!liI;&U}FkJco_*{!;J!zeNLZVx7o5+3VtrFsz zV0-eH1ioC7-M#cpcW+M|amZxmPtUI725`QcV6szp{n7%2_nstW`_^o*;M}@xht&8= zsOGtPkh_+p;Nc5|zuEL>Zimq6n2@7QBT&3rztvWpxklyR=+P%`)B1k!<1^C;{x7`9 z`aj}Dc8>q8#&HB^D)FfOCbw=Lo<%tDuCju!m};YPn=M0&D(uxgTk5smYhzDO-a9Z+ zvr%MbRl04f6~f;=2wu8R*6{FMP8#i=Kd<*E@XmKI?~hjZ@73k=ivRjJgI&M0E^Y$C zG$v~oX1^-8clYlp#EFulEz;>B#>wSK`)F_S;Ozc)ukP<3L}NfciP9|5GY494PamZ} zy*3X?toMGLyB{!mZ)Z=?h?)sP_W(TanA>S+T;;dyE)bUYDW2ZLLI%vylGiwevHvi# zU?-ut{a8D4NFjhwls{h)oVc1P5h`%i6i3Yx2D-xBwm_pZp$}@0^R(AHN*5He_EE{R zw39GJI8L-9hj>8aH22&0_g=Aph9_$ep2m^*WihkoSLMVbUuc3J4-#9x`89KYRFDMG9T@sl%<()Jg&Eamy~TP1!*`v>pz zDM&2yPpp||6{h1TWGXDG4Y|`OaCngE)e^2g?_L#g!42VhUak?@*Cp!b=v9 ziwdcpkAxs6>G5-2-uTvDBKNBm zml0r#fC;p6!tlnUc5CnMqp5xk{(bC(h9Crk3G$KIDLR34N}hn((`y^*JP@sV;mK?L z51j%K%911JBk^N<<#koE#ccEvueXOD2h}Jc#2|<~Um#gtwU8JfqzT%5lL9zl0UZzt z`&DJ4S)Jldh2rBf3?Ru9bc1EjlqW#kuwD^@zqJ^|7u3K)irCK?qODICoEq~zv!z_aleEFnX;!rFnB|A9A z6Jk00^klZg`nCT@Z`OVyCZQ+9Kzn5^o2VQ2(RAb#L3{CLSz|jelVkZdD47J7b{w!$ zJ|P?|>)IvgbG$0<{!^4|s737o^v3K)EhbyjC1<&{w&eC|&#uN?0~ayzm^!k)iP1Nt z5fOmnAdAyJ9;?f11-(_}qO`$=zyi(8`9!vOK0(j@LG7CdNA z9vC1v&7x-p+*F`sd0An*Uuja7Ci%k)Q_e($ag<52-Bg7sG`Di2Q{-znt3qwX(cq8- zKS8v?Vx}#d=d^XTK;6c`t|U)dq_YZ><-A+KcGklrM@;BaOczO~lx@aqYtg*5m+8fQ zTEc-^BJ2mrk$~SO9WEtUH+!l-fRrXI*T!qLwT0rrmg0hta{u?vclH#q+hPRolgOg8 z#&pNLKVR!GrfomSCp?orSJ48PbiQ9JNHRK}S(~2^$!^9A zc|&@1HwTsy6+N@DCC_mD+CSvs2JIs~)Hx>=X*ScaxPifRAC}W|$yex1!^W%m(2h_= z4@90KZDC!Wf_Z*D&+$-~RrNvHHAh2mYY~0klg|LvoZ2M_o{Csn?!r`V$fI(~j(*g~ z+7F-rJlEZQhs_TYbWuwD_H1KV-~u!@w-HB0m&6=TTkeUpRPTWy9Ezla4V4hBt;J+> z(EZIsPkus4?%H@a?KDA#yVXnhPU1DqFR3mIMX-$zSN51So|+9Lp6+;2!dMN-$qYsC zukqB(F%LSi*eyjV1OGw%){@l57P!wmRRoi=O^ca?K#Gnz=w@IVv)u}x8+TVf+Adb8 zx5S^8!`0Vkb55im*tMtxqqntW_}OCgukst#3LIor*j+tgY6J6M@>URvVEaLRSzIM5 zn7HfExm!qio+CC;itQVn0CcOKW+#D$;G=(BAB6rou|1tLd5Xf3U*Y(PP`sCh#UFST zU&rmsQN0t8$tyx=MM!nsZL1cSW#D~=)({Uw|Gt)}p+?x}A#-0~S0HE^Zbj>I9LKT) z@j4SJjY3*9pDv0?%kWUf0*XOXmcyDtosSbB zXM_a69~7Sg1!Z8^;;>e7jaf9;8PNw$Ng()#^@A&tuj7Y z(gpcOCakQ+R{Wezx7MKZ&QvMUE^W@9&5o$Z*4=px^w67S}nzCV5<2`*~z_QvW*}O!4g&tZJ#C^Rq^GE!x^qsrf(I+df1=)$Idp||UFQHw^0=rOjxzVr^ENRIJhIH&*DgBq_+?W{J^iv< zM~oq~DxD)BsR*@q6#L+8_`1+vIA1G)8}zs-%FHa`3McYRJY69hkVf>EvrFN^mz|XK z^Yh5754UP% zz0U*GD(XnvzV)vCDZ(O$#;-F1mMn~8t_5|fi z|3p;sV_p&1K;#rM)Eeuk_*SmlY8|9PMY-e;7j@@2ND6-@VOYG+J$)RK^cw8-Ii`}G z1Zbs2O3mj`;3!vIdI_%l26~t{GIE(MCs1gp^xeXQ%w{vVmyWkUS*yQv)!P&au!%qY1wjj?utld ztjrKk)sAKSutP9a<%8$ed!5(U$U>`}H7)-EzHCzEq%>sRo8oF=cPQYFnWO&_AwOx> zTZ2Ztn0I%i30#E|rs}j8;s!(Qo`wwbX>MOCG3@w33@r~c_6>Bq!$%c66N(nw{^_g< z_FYVgzdcM2bON4)g^!pI!|6GmoaVP*bb_3;+< zj#y%Lgqa`IAK=1?Ls$r8jCxoOEqA7&fY=0NyZVIx#Bo)XBx{#9@kgw#L2;f-Zx@G8 zwhW0QerA#WKhI9@5xu^{v%0Q6{vJ90-@~$MM}LN%y;2aW;|m0Vk^Qo_D}1qRsoNk(n{^|8ZAizH=kXN5 zF~>sqj;Zw)X<6urxr|#vPdS_};#mBn zmiXYn23qB8h%tphTimEaiZeI$F~)qu^Ni->fUX0-a2Is9f7A_ltJQ&l`*z`1Bx?TA zVG7UZ+)5uAGa(K2(1WZ=b{EZ*0tPDKET<#+SEuxc%P_8~ILpx5AkJrKQqbVrSk<`J zCL=PS-Mg-m5$WjJhc`{K8ZwGo#;Vd@n@lyF$aJI!No8WpsQi66SH9$FXnnng{ab!a z`)9_tuo%;+fO%EDS*B3jn4R_R1JZ;(=-D<&8jQ$i@S7T@bGo){Lvwd-xO;699of^* zbH>`ky7bcE*oBSj)V?{@6O&%%QhsuMa(d-bEXWn`B{DEzUqiuXjcOD>**_i6gNss* zT8CK$=v=ZAA-_}cH)VIOfFC0ht2oZ##S3hNha!kfn4J^!=(b+x+P?4i7~^Iua61H= z%(Nlqjb!c*pxS{BSh)XIX`heHhTZ-c1oyy#LX|~hVXQW&cIN)4(tU~RQ%qTdj1AE< zd9f)2=h-`VHnr35q@N^sDw3!&%OxXjoJ0e*-en-xPl2c&e1CfbaKWKEX_gS*%;f5N zdcjEolh#Jgx{SNOeySqD)Gx8I>&lSClUmLA<6)#H?#C9K^K2%JwS+IRSY^XfZhS){ zS+mx;`svj`NIhRbN))e<0|M27Uaste)Iads9)+6yz$k~otj^hzQJ$?qB>C=ENd z!8-!Pqg#ceb(@skRP;HpvaQ}Y`99nas-8thSk1$%%#ogra(v=XNomin!A+AeGyOeJ z*zZt+S)5G)P-?01#Fm4phmHr1@h_PbvVYMD0Glq&Kq=6;_F!eh*umOD4Q0%BV<6qZ z@RW*F_V!xd$^I$QbbVPfr3rVqrLI~Rqpjh~V z`TOA)SHD)E-vftftFEWkv0q_gO0H+wm(BfsUj>MICb?iD zWMEzf4Jq2Dkm4p}d3QslcoRDw?e{ko);*Oo!};s$!L^h z2@ZbT=&@ncd0@sTl*TQ+P#pdzL_} zkQUdg!89kpn(DrmOsm->sN+oNH{)pl%Q|WPYrqoq8i&f)<7o>14=BMTf$9GY`7HmV zk|;*j|Go9IMq?rthaINpjQSE>GvQy2KoLA(B0vXbhF1L0vNKoO@xGETKM84Nv8E^H zmTM7u1k#5%U*gHdl`&b2-wX=v@6ys(-}{Z4_m9u}@6y)u5j}%RN)YVQmQ7@SW6%Xk zb>x7Y-5UR_rr+>Xo?V{|e_xDaLz0wW$hn&1Zz-#KjSkhFf*#QR-6^nNm!*x_XU-g6 zi~Td=eW_#YPkVMYv4mNrF)wH5BOXid^$CbTS7Fb(_*+)vAyADv7bG2d)~rgnt_R{^ z%r|uH?y=h4C1Nud`pShDOk>b%R5nIu`J!~s%hv^n1|%v0Uq|jqO!W;=-&y@RO6QM> z--{svms&?*M2Mvq5;eX4to7fjjcyU0hrO0$rhNJoWVDS7`o`K;^uU1ZkUxiq-7SHZ z>P`3fR>$P7amuS>{Pa(R%;;;`#-&fZeb1!tW3M~U@;gC~0UD>~g|Ihg&I6~4xa?^8 zH7WhDGdnwLu8Wf_6!MV?`pR;Us}b;<~*^zqIMH0mqOEY_aajq4`;D&9*SB zr^zAJIZGSnF}$?$T*_Pf7^&hpqO~(`vz$nf>nGex`qL3XSp3@WX&3%ymYc(R(pllQ z+uj$cA+Mb%AQ+moWLrzJ8yE(CtI6H zR@f7e;NDjJ*oPPEddYh{&jpWVCBd5cng^M+ATi4LP zoxU0P-M{r%&bA)>8WGK*E4b2RrdY+ybxZ4O@hVxu?k?$aA%>sqfl=Jq{9c)I7#Rx| zz3idMp00U7p8v#Jms##+D<9Q?5t${G0IHB2p2N3JQOotr^3^L&@!dYzbs%!)pD+;? zLqEj$8waAM37J1x{l-B;+mDO9i?<7@3;P-6Zu2j+HN(9Vf^Cm>gRNn`O3<%Za>(48 zn^I~I)8i)2au9e^uXW5%(E&4`z1-OAXT|A%PIW)0jzKZm4;DUONI@Op8jGC&YvLeLHjwy z``}e~QGvj6s)${acV-0A5QMQk)FPehUg>4tLj|fe1T$Zt7l`s`^^1T%dXVO*`LOG@ zv>zv7e}KafA;tgaYr)9E@;}KCnAsWs*91W)QO+tz0Ab|LH}+g~u|;X7!n$53wG)=ePPydL{Emynq0pMB zMlE?|DNe?8pLNu3W0LTK9||qx*V(;Kv|Qa?n9&;Aj5mrUHxZL2e z?2->7jEWiMod|~J;QF|vCx*)~_3O%8A^NA?vRZNWODeQ85_ay7o;$ncM63`ak%R^( z1+5JgmS+)(PI0X_)Hp1X=j> z)zD&Kp`2bb3V&H9!LuS{z{*tV@)0q;(yDX}WXpu}L}NK;iAM5Hl8q!tw=}J%@Ndm0 zr&;0m?19JH7Zwy##hLb*qy-93IH$drrb%zVCe#7A|J%j=kK_+l_W!M4P$zl8_Wz;m zoq|LQmTl3tZQHhO+qP}HS9`T>+qP}nwynGF-`OvAyg2t`M%34wQIT0WD>KI!Ss;KS zu=^hAd1bZ;0W-BUlty83VAgrP@&b$?mRbZP=yP|AezLVzM3#Y*mhOF%eVJ|A>9e{N zoYDPa+wLCBwIaLRDeZkNT?%)j!Y+tXSwRO*_^X{0MVDqeEBac>!OiMD?%(~h{q^28F-7b^f9G6pMemIaW4-tNHDBnH3r8{{G{Jx#hWvqus0lA~ii?`)qn!hZ(pYUI&a8MYvD5{2Iv+=?US4>J zS!igHTH?TT?vF2IlPP`?@lG*X339zCrv4|@x9pwrn zZ@iIhNZpDG!?4%Z9;7ujNplGjCFc+l;APqwUAhH{c1WRfsg z#%DhfvI!RBqD@!q$iv3#VcrAqQf!~4)^bee>{`uriSExQez%}-%761ew*O7wU}a|g zkHC>6ZGXUk68id%s^`X1@o-m}tU!{Hgt)+<4C}I}D*=OC&Jhm@{qs%2C$0;FB!OS= z+w0B1UfuG%@|q~IJ1}>%O(NHQ8`KHcI>+Vca=JtAN!ZboEpgx2&0?IO)@k;&tdk|d z4~PF8+j`6I-q{cD`SLcJZJ#Ua;lpp^M9k$ra4_iWQb1sT`Tfn+KDm+$R0`A zsb8#Nd!nAsvHShHg|_C#)9jyFM>DH`a;#bMz@&sa9(N%T8li%sp&3A;mf%979SCy< zY9h#bMwxKZXpWFuttc2|U?#zkXpJzfaf|wiViD|1kbamBmJcqh#DTm_>P0cvDFP4G zE&XI5@zg}%m0&=oFUaBzG!Ik6v?S~*I%|%=D>?+z*-3WCZ53z-AePGMpzF{YKU z23*+)j?|!bCYVnQyilixjZg&(xq<{~r7??5L})E-v?3u?7zVU$rGZ`rEAz1n`X)i$w>qV?ZcA9+{3TZ!;e|*~8o3o)GqMtCk;4 z!LE%G1qBetN*>muGkPT@%{`9h*tQABltU$YIYbRLpJ?hb+<mG5WEko5vmrN0x|X zFhzoze>A`n!sBxg5(!l1i_C|d6k;$WO2R1-P*@~EC-Uf6<*ep}3C0s+308{GfeX-) zmhpj(AyKFhx_N@mLP6-?(M$wLA@o=xE~+G5kv`J-gQ2EJI9U?H>P(t`iw2%WN?7)U6jP6?Bfpx#}B zJu<6^%L=>7Oetg!)ee8b+=TQ;PgN+`uX6Xw*|y(wtzHi6uRdFAZ&toeeuQMhMYZ23 z++MA2$R9SDh3@*lGktvhH-GqF)iIfw{?i{86s?095CHbv{YCNE#pc&mng|A#ARFAU z8~@25v2k+elM$A{f4?s3oDBjY_IRY?q=ty?SQK{Y#Sy?4=C1yd>T)rusSp_j6Xs+J`qM`a~Igu0S>01a}L24|^JY$X~lPo4hX zhjEo^H?iIFQFpgCLq8^6>lQDhbE*BeJLEHSUTRj;?gxu1DF2%y~pLfQ@ zX}f>c2)X46jjgVLVpy{)rce^Xf-FDBKhN(*Y?O>g3dV67+eGK7#ES%37~SA*w6@nt zs$6Ie4&U`Lr^XuUag8Z;cE3*<`U_Vbr9_#r0w=R?E$@myJX~_4e}NqF_Ic^6O?#We zo;l-c>7)<$T;KefyZP^E3VT;=>vH$$wU*_}RrkYj#jcX~Pa<^VEe z7<7Fq|9K$@Rfp6;UhT+*7#E4QzzoiqPZu0+2BNEVYt*W0GpgSczD!X75+Mi-5!G31 zJwk}n6^W}JL&7g$(z;%*p!Ky=t)0C7)a`C*=Ch(-QK$7Ad>8_#k+ z`Re_B{Y{Bitf@(oA;WIwy5m)@n&B|NvGG@yX?t8?vJ7HDEa!+QB+(;-93-Jfw~VIN zD{yKraKa5A)I~;NCTkm+Bv(qJu}pgOxgf>J&k*s8;VREK=yFgwmYpA@z$`8jQ?im0 z<}DHsFc2G|96K&f`Gmwx-zdSr;_m7~Y8@36LmO?oBc%SxO_wVyn!%u}dO`&94Ph-YaatyjVaE(*@J*s46JijBApCe1DiF1AfrvL#Hp(*n6N`Xk zS_d&s=G-LEGyQ?lJyQUWjuf-+)fk6RjGj^r4TlIMGXi4Rybs(xUx02liv|*qdelQ?mOX)WGj?})#^VY|nU z+SLL0#F4eW-*UoUW+z16K|MN;M-a`L`YPlKw0 zpp?Kd5^MznO|Ly`M0ZqO%y?|53+6Zal2j%U(?VEaM?T6U)p`U%)>R7G(S@Tnc=uEcN3&tC zesX$pT5Oe2(c=GRsA`KF_RPGTso3Z9m$LYz&>G)2q{jCV7HVxO__B|}Rb@$w=dbaO z_oZ!oztcmU3I217Kl0JXCOWRCC_~3LewmW`a9K|!zugo7u zx&;k+#7?R1J*tJ3F-wWjixNU_l3LO-?|N#@je88&dfnLg=3ts_u{bG^qg96CLp%@T zW91Ua4c=h^OSEa9$X%y_3p|wD=YHGTe6yE5QWM*wbVux>+@(<%+mE_4+kL|@Bd*wH z?!OK<=O)-FhGblgvx~Zal&(XnIdUwoi$ld85}(-hPU9 zIb`3yNn`Pn*Sq<0EzkP|oF24DgK~owh-%?=^XGp{<jL}j}@_mX77nl6HvOcP{YMXqo8C8sDY^U7>Inu;JMBU<|z zK%H^ued0H3e&s7nYl5z3(xbvIk0?E`L?5JEZABB$4a$PX+zki>%mx(WVvf!qa2zuFe?N9@8)P-1cQ;32g^4UWX5{f4En+Vkldwwe1l zI)iUxW?B5S)=m0}FGt|2KW}??MkC|<#Fja(pFsAe*X)(5tmelY6oj0P=5&2aydb_h zz9HcG>&~BhB7wAD2h1e`PoxX>Cs>`?gR%MB|6K8QmP%&ZZc?t<5!=Z)LFTIBir%Z? zEla+^-f$uxq-D_Yu2oM@d51NR|Q))koILp)1IkEy% zP?JQ#a;Y%9ozEgdo->&NIw)kax<7r+W=KK`_lykrOjt4t^R^<;qX9=NH?OyNB-vDb zVflFdZ(1Wf!S)OhqEM_*pW=EbIKorjWnk12Y~~U?Fus8%au|8bcpr9tFx}suB zYq@0mdt+z$P`01?#|H#HFDKkw)4LPJ6|{ zcBFE~aS<$b$mcV`1`hSa*6{Ihsrl&%b)_ugaJ&soPDI@)2}br> z%H$~J<*R-}Dh2{6fg&wjy!Khl@A*X^DL>aCs{vKadvUoN}l+~K^of2vE z>9#FN@iuw+9lyjR<77Hqt90e^c+u{gX9f|b`B*0k0X6kER7ssX*v+A)7U<9h;mW$# zRKm?~@*m1#=({>5qibR$+a`$qaXkJYnN?8Y&NRJoSg}g}`OpPwqZr290(vYC4iIG# z9?&4yCfkpZ^To&HO^J@S;7t@gcVxRQF2A1@de~iqW}o=KLRsf$o}H&s%y2k&LgJU_ zqS`AoI$5hOe~m}_cP&efR|_$pn&_ivvF!7?iPY~pf;45MR9zETl#?XYN$i^&y|fiE zKIz>W3flSDu?el|%JT*tIn@RU-#HZxWi=uXG!C^)Vo#gVEj`TpgnPQDayI+aQa9j} z?(eX^Xm-_=RJ`I{Q^i!to}mkDf+~ysY1%ncG>^snO)dW%eV0QQ!y);m6Ay!OExS>ETyyyjlJUs3zS~&`s5tUqVY) zM0wt&y40BnkneJO)Vs+m+CsupF2p`$AbI~|3U#}Vt^A}AYR8lxxfzxRXG7_}FiMf0 zoS5Dv-s#B*mwqWX6q1H(aEH##%c7fIOVUoLpq(UXJF$9NM%`)22wv}1g_xSCJ&Bpb z9*>Kp@!loy6c>dHl$D8qOTF`zoewTQ3^hOzoqh})U^}hATy++~BQ6^Q4&(78#Cz1re?lI1Bok2`8nHa?g2LEjn5#9@Mx7)BYw%d54 zm7E8ZUhiU2$(q@O)}rQSg_G8`i6$MdJ8!#r>@>H>yZ=Y0;{P>YWM^mok19g87q|w>>BbAqeN-2e0%Px-;KLkfToraP+*_g_Q!O7{|zB?iTwK2H8reLECar7f6Sg(&<~5aF%I#b z4Q-pEkX;ig)~dcoUax5@E*FPTkzc3?F{4ZzTbzF@26r0pxA^04O!F=Oh>wBEZ+%)a zC|Tc!VQ`({n#2|33w)r)-0y5?idU$YNA1f4T*O0c!gLmw@5hyCzF`A|zkV;pX8L03 zY=(_ruDvz;vRh22xq*d?NnUTYcX;Y`MtRF+>4qId%t`FW=3jW&`sceBXZVMD*ynoJ zryVoun5VztP0uk9$$v!U(yT7ePVp_Vaj_6BCVyk@;2zv!pI#c0|9E(cuZg{TZq~Rs zIW*}aVj-D!&g?F7lPqkyO`vFRO4!?L_m-8_fi9MaO8S=m5qpz++^>zuLR<1yJYsn~ zEvc&8-QzIbzA(+TadJ53h4us7|?7tDj_!TxJep`zk z*%=)%My`ukBe7v(1I>(-9W*mwuGd_{xe~UaV}s9(rS0PzKr@!ED^A00fzke3-KS<$ zS;xAjWrN#-w;5nN#AcYu2tI}AJkVmWS%ORte2cyCs+R6Xoff&c9kSS5+Q63f9++z?u|QG^=BCF5~IiZ z&D9A`Q}h}uFqVUT!SP7X3&l6svZ1-Lo5yN|B1};~T8~!?9=l3*JRo#a(@wpq?}#rc zdH>~J6V?d~G+m@1h{aV62enjbsFZQ6@zZ>rZI)LqV_)#C)+@YHgr3dKlJfp?_up?W8vZAtLcxf zR!RMdh90l$Rn@A@2>5Qvhe$KsnpK4VkeYfz9K8pQV|n9uUp!Mr-J?vcBfpTU4$W7J zAbxfn!p8XIm#&)!3m*UW3h1f%!b%AfCG_T+b=49;6fB#q?kBw|hClm&wAjJ9q%r}! z*uVj@D$%=6HC;61z-A01qNHUx7V06#ylL@fN(d220I@Eio$JK_`mRgDwWIFjD!nVt zaZY=cBN?x6!I-JKM;bEc=S)ZGZZ`kgoXn;^C%${q$H~IFHy4>umqIgJU#QcDmytig zqTfRw`gN-o7c~~XMRf=5o*1N~dXHEC)tCdVh~mDH&E(YK}hoI=MYQJIvFF!`%#N2P;)^OrFfQ#dvuS;5|27`&g+9D#>=gWISM zNzuGU86x{x!{0fFxU{zWw);U^8Ptmenq4k`m>96A>}5?@n5sY6jsp*tn@g(EtnNy7 zZEIk&*m?4q(~~pHx(chJIQvqDaUe*@IYjqF?B<#{u(byk(K;w0`qOgT{Vu;2Lz#TY zqNvTbzmY-Te%?T&Q#{o};0f<{o?zU5`(=9~ADC=KGyb2LYPc=p3A zz_tKR`2t~@4uD$}?LuHJ&1uV{s-PevqG2G*BdaPaD=G@-WhZ-an8Pf_?arQ*0MxNV=2WTA!)>0Q5<^47 zQbSl#QO!=x7gE;hcFaua2H2{llalOHib0B54_kkg| zqA56lX@9);G{g6WBnIyth#&hENTTasw*|vQ?RQxIVy#Be+wt!J_nRNg)<~r08o=32 zr8kCO31(#R4h}5xtgPj+Ve|Q!W{0q=vnCDmOOA7mIP~s|+;cMs3wkJrYd0f@e*Db| zAPM(i!i(gFyRBqrs&q7hOwyPL(87~OrsWRSEwW3BvVZ=OAnQ_fZArFS(JkYaX+-@; z22_l(_14iKqem+vMm*qr$cuP_N&Dy+BQfGA9zkRrj#k8hDlWKzwg*}WD+CK8p6z0U+pD7((_&MZvZE6i(*2zfRN##7;O^@;`~uCz3M zbANb^KnPn2%dd;pgbkBcNWhRA>$2Vw?;aCPLWh@4ZdzfPqp;xCbHu6m3*D~kkY6O} zx7Hc+w>*4O*Sqgx^29jTEg{w{C;O*As94#QE0xWhi@u(70K>YO(&X=;htpDRrC(S< zZs$*4>YzSpX1CkM=e)(7?R-u5gfHpQ@TBc(jk}Gmn7WHJiFB$>Hoy70x$fx&ch8|P zqeFZd+lj;-SOfSl(3wRBktGB*EIfQ7=p5}fx2Sj1Mv@Pedah!Dsn*<6Z_wrjOQifX zB3jF%tm6>yEO;xP2*&=WSV8({@FwMXg#D-fAvIak$4F*gsMR-MSq26h06CjH7-$U4 z($=8=xNl;6yCh)Z87G6XjLg}zu0Lazg^Pd-qcQ9(a0+t0!^^f!Fo2dDUk7~%*`k1C zqx@isJl_^mq}ba)p7t5o4H0;y$4-b*_gNoe9#>yo=Y8=-7a5oz>@dv*aP{47EFNzW zJy5x*OMy}ff}j|x`05gBvidylc_5lRnQQ+w*qh!exxA3IJNDB&+i32M-`&14g{J@v z<`8GUF4CI)4|B-1OVs0I@xEGCU4=ptd(n!r!`?DJ6q71uIm|pbFjZVhL1Ll1NNoWG z^pvx@S}1d3fjW=?(&s37U=jxy?w~0_F@tpJtW0UtV}`u1w6E0`>7-etuZ!NMB)sq`9rTeb)1ShTcS`X)uk+%-K^kZI$zq?Xhz9MYvWKd7zBrevO# zFLu-Co0D3Qic#6YM|hR&GSB>IGE=FHJ>Z1JGL7$q?a+EudzHJd$x?0SXh@wl2l&Tkd?YydvZIr zk=!*k=~cUR5HN7sx}kEROY_-uJj1KKdST+J2lzoW9h)yVYz=EuFv}_3%p_-rbB= zv4CzYFs{8<0PH1^)FJRB`+}2>jn5HAtT!DQ9zS;m3Quh!BHktz`TWYGJqF;_{a#(} zMMuh6OXiq^-F7h(*jvF*=O7*psu0&XJtw$iy93Q%{8~@TAz;ET_9WO*^a_tY2UU+m zzFRci=}1*S=s@=4W`wivv^=Y?lpj{f@+0VT2Ryr&*0=GNV>AU;rjtJ=bhmkI6dsn3 z+xXC2ki;Ne=9S5qv@qmD5shOjR|Cg5pz>UQT2D03L}OyCruqJ0oQ(0NE{Ujue?D?i zS26kA_B?12!^iWK0}4o!TTrq(bZTa*S+t{R@%4(^oOa2!m|aP!5WQ*&+)jhA?#l}V z;V)iC%WvM)g_4O;s|7jtz%ZUHeswR)<{#(7)azW}-%cPHoU?v{_v-b2xZ+h$gLU|l zv?AKmf~0zs@W*b!4(~e0^X7Q)aovwz$Q_uUHR=wGJF=`_4aVR&W7#;S9&uVP76=G( z=qBmuX$Y%LP6!K|&hKl_hU9#IH2%f6FbcP9I^JzFxv~x2H^b?=`s!#bPCPqkc(-_$ z=$EtyLv$#XD3qRDN<3esJ2G2Lm1{buYEq-AfszEsPrCKWX3NPPoMdT#0Ab?dVF@Q)Xf&t9o5Jb@wtrndt%mO z2C-&BLg(D-74BWdlS4j!yyU~k*zFFt9(4;G%D)I(m4;FKkPXK}Q7g*pQ9clH`RiRp ziTb)1BA(q25Rxsz%;LRmjQlE})%Nh(0__RWn{kI#-O^lFhDPQ~?L&$)A$EXYsc)>7 z>K{<_*-(c{^3B3oJ%{xw6#=C^?a-w+qzANKnudo=x zs7&dPtf==W)9YdCNxOpEjNPSh`mW=FHp|7VWz~WH3Y+8AZRO|h3g8q`YwMbI`+Kuc zqPG3{lVU!fm)|{lA7}KrUUXrqPCW&`W?@YJ+^C@IL4i|DNqD)6B`c$e`+6^g4rESz z$#M~O+xT{D80m=xtELL!7?p9Gu?H;2L(t8&_w7(b+2^Y4t*u7Q7yh8qYpo7jERbyM zjhY@)khsGi$KLspYr|n-jx)mhD-!t?T9MY~{Yvrm$JADjaiq4vl7@C9;P;&2TuH$>$q&pmDATXvyJjs)H`7F`LF2q)7 z9VjD{>Ag3`2NVvac^UlLb^SSsX7;zvB!&>w6#TRvJ9JC5&E*nLF=oKd9)ygpePT!# z;Y1I}Ca`J|pc<<=#DvKDAF>Nm@IBvB%67PSEn3K@2K*k3RY`!L4nE%y1sbIev;1V4k(En!Eh}~!aw%_T=)FoMW4!ozL)Qi ztQX&awibH>;ON8oWm2+)9!$PoEl6VYepI3ETi+th)4%mI?e9x=44HI727eGfUoe@? z%9!_5@p6LzLKqyZv1dlGZT0j5hjoYYRwujlwpFoY z-4E~$EuYId7X6FPLLTVFQcnWt+Cqi>b7Tm1LCO*qt@s=LfesA1 zaquo)Ow#4*B-0uZ;W1BaCh_4R&f}t<7JZf^1@nE-uPaAN>E|C+?shPTZ``ed-A5%j za1J3vdX#Ik?O7s}Nm8LuWs@dTiTCE7#n-Y0!+c*9%n<8ykP!maM5yNzQ(IyB0tY<4 zKw3w_``fD<1>$(QU)+F-e_FcQjBFTv%=Rv#+01k9=R?DChA|=9w@}hZ#z8$FOk|}J z{CfE&k>491V6`wZm;TMsQQ^22k9^bkvBt#l z3&I?hE)tEfSSk~J!nEAGk6CIVV2`Z}!l=%0q!LeAHKc)r&bw}nwID+Bh7q3yRbyXUZQZGJY$4iu!`4Fu))+)V+Q5Gsy$@ewjeV>WHw2du^U)V=<=aNE41 z<=H5FYYz=2hrL_W>k38}u8Lq%UVBZDiAyB_A1}x9Y9EkC6TFt-yf@}abkJU@FYK?k zc{{AgM7K}qCAimp0*vAFFC`0)YgL_hnVu3}^;%lXtQZU7(Axt0!cPD0A+SJg2lHt0 zS{#DhU0ICmUYbteZiY#4Y9yg1LeINrK^pLJBpqWvv(&Z2r6|P{k|xEP1h*W@bo*|2 zJmwup8EorM_{ig8=iXJdyJu-)U^hRx&3M!&-BiiK_-(rGXV>J)o1dqWbur?=)T$p< zu$ro6M+T-B=QG?ldLe>FUxJ!(@!0`fb%o$0-6HU8`Iy;q!h$svy^QLT%OF_}I zGZA>yVX_QGqj)F-ic=iv)8$1XQ7x2|DgI`Qx(MRcGFS4Mp2A|iE!v)DAd~kby0@~C zz1UgO!mo_H+X?`1dVeu>7DhA2*%Y$pD!!Ow(LA)t21o^^ZU%QMK`l+Odj$J4T#OLi=ru)+E(6kDh$9^qMs4HusUvy+)755DAW+G(!M zc~nisAa^qf6K@r3yXwok<3J?S>90b`~u)jVRGF)(O=8a zBsQ@Wwo26#-AYu0o#cLy62JMygFgMt`>6|~o3~Iz-reG&5nGI@WvhuH(CRSHb(| zpU5^Xx=!qjurNX>2?b8FaOE*S(~u>_*E=~!bb5aB709NsujS{SuBGBq#~!pOl$aaH z79FYm3ct6;7TikXKVIfq%b?BZrJ2VcZ~3wHOd%4_an1)1Q>BDRG5+sGxug_;1pvxf z$r);y+3DrQyHa(x0vJBxfKwBEya#NzLE5Ukafn9zKAXch#FFAIHpysDaga#kxTILr zEM<))0CL6RWr6HT6^cNf$fL;x{Gr$q-sz7|^*Oob-n04LoHq-FwppHxl;D8{7p+uv z;0X$jateTHN|sl*l{Z*|FAhP=Cuqd~^NHQ2NSa0e-Q9 z9@{l&+8b|9K2e{tGo01!55zYhR}WpK6a%D8V}Ugk#EW`f8no||063cQrt zsFAxC^-=Td7m7qGl*>_ME65^}%ma}=;{MflCm=0`A`#SENl8z?(?(cU>T+$MsNo}E zqTRE94y`BxR`|c}tY`5?Vn*5bB6o8e*+%{SAGqHFJ%%|2x%I@0KubHwuIr^FbzzH8 zv`GElg+NM$KL*OpNl<3nVyfaT&YRNVMgx0_7<-$w)UHztz_3t#+aFXOIWNM3p--5H zj$>QsU3BD$#Zd?nCIh(=jvN>bU%lX;D4^kch#Oa*WU_d<^AHY(1fTkIzpX*}yicV% z+b4)~7exHuaOIj_a=IZ^m@!!p^+8Go$IaoE{nW%~`yxnrB93lOO6r4{==8=+pLlQ- z#X~I$%GOU5J2Vr~QH9AWlchL$(M*Y@HRzR40$c>tS_70a@H;@M6w^x8(5I-|q|YPs zfWZC=Dxl<+OH=1TEjT-QuHWNzr7LSX)hTmteW(KJ56Q1Vv_v#h`l3qOco(0gZ!h-? zW*9&{GuOVim+%n$Q7Kbeg2Ix$dJ$-B2Z<-s%}y7*;RUaF7gg<{_N0uhnpQ`CoKXYV z^%=Q?H0nq#;LOtbrzF_$~*-LQzbWM%7o(CugU1Fuu(T&r;{}Dn)}4Q`XG4SetPet zN?>0N`yq^yn=ii)Tro*AWsoyiqOaH}k+b70v5S1jcelB4Xd_6BZ`??5yIv1gCCgVz zs-goJi)K`qD5H)(On^kU-Rb{ZUvaT-qij8o*odGW25vo2zDLVt3uKRHsGUC}7fyVb zfV6<}^dTCR6P4f`NS8=MH9@($AOdJlP=a*rcH`^krdnCgKfoi3WbU2kw!`DII1_WR z{q5w9UuhQc${O9onum;J25 zp&dmxG)xw?wX$0($CtW7L&m`x1e0W;oOIDBA*}p2SUi(@c8;7HdvL=q=tQAuU+q5v zWhW>iw&>r5IaF)P12HWWiWtMSCmUf#OEG&@{tq-^f&!Io))a|@u2o-v1DwbFK_+b^GyKc=f+M(z_k zbUqc}$ZbTn^WsMdPngwF=b+%V;`oJfzRLHHge5;xBh%VPT|VPTbxJ)cIbG(?bFKv$8h%cu>Df@a%cB{%d<9noH?k^vHsB}0h)DF*O&EjxXx*uduO-N*>;%lZjC)**eTdxfiH z!**|4AROtJ&rssUs=@Ak^ztOWo^}FfU)V@RlNa%=V^g202RcDD}%!(@|&q_c4_Wu+bur4}vxKH&Dc zz1(__eN>ILET%VOKqPo9nBYqtXma5XTxJKW+4TrBO%$`lssWFR%^p zQ>$I$+TT9Hs16E*gH3x7J5A}}8e-s>*hO*N*)(1%h=l&h@4do8Cs6{K;sI)#GR^}| zSZKy6AtGabX9Q0P+5p#+aBUIz^^Osz~cMn(};Xuw4J{>|{pL|Eug3JwpZ-l-t{f77>LO@6!6oEjL1VKCy0U;zPf}|Ld zpn%9ILKAN=EE?s_i9F-8RTV*U;1BvL{vO@IaM7b$w`_cwzS3F6j|!Au%AoI&yCu1U zNQ+Jy$%jUdsQ%Z_GWr_hm9cfSBPIsRd&?{`X6t0tG5xToE_ux>rWN~lKBOHvgB*&C zOKwTt#|+)5b@#^H3aHsX;k(FZTuE~Kh&2&bnM~HxTxvV%^kx0!mwVa#qPe_RBDhHX ze8@7flV^$HgftRPQ@g(1T8SA3L{PC(9x#*E>El) zx{x@*AmC5`AsAMO73$Qa(LzJRf^yM*bsgB3%nIA!-x&^!A(n69@RWF2<`6+g2AVF+ z6(;^f*6O<8e*1!IBpZ3ZNIv8ZGfWLPLQmot~=cL8-xK#sUoD(URMY1Tle4_O!`b8j z#~3RfO5SmH)*;zj(f+Ar23I#A0;(ino`W!6g}XoS^1iFVW@t<;mS8S}0c6-$8_^#- z(K~d7()3*(g{$90&D=4vhWha?VuK_MxiV@4cXehOgCaf14J-@H#r?NVTb}pwy?s%# zO2SvEw*V74Yc1>EFEvK5VCrPVhrzI(T8=(02|lGs9cOJHL!0_Jyj!ky$V2M*+aHkM zmY=8OuapGQ6HyapK28V931@u)hsRhY`JF!=mXoASeLaaqLk$&ZJEnKqk|IKLZ0>PB zYTkCSNnAoc3mY44{QliwM=;Te9$;Xmm6o?pliuCUGf6DiR*$ztm=gTr~I4u70>(L0$7A2_4_Iha(6jfc_Ns8{a=j0hB0F z0Fs*ioAoQ1`$o}rSaEX%Z}Z_#V$^Jyp^|fNqW<2Vo$f*!3<7ioGgS))b#5jVv0zUo zIMLTT@R!;FxBG<|bXbsnUx13yi$|Q7IxF3jz5YmB2)bWKTgREXRk}bnid(GIE?g21 zKFwt~Zj;9fIZ!{%T1imH+uL=WIBPwI0;TV*0K?eizLQ|K@lDjOSOKM|eZbjDO)5(X z-fM-xIF{ubrPheV-ipvXDs|vERo%I}vX__7(>M@FD~5s-2O?sbpskce(4vA2oD`5G z;I@kuXH{)gXLn|{l#3OjL0ezbMqNTEaNVExDlv|Q=Cnt^=rE+Ur;f=zI- z6SJ47g~$ZgHL{}!E&q} zuVikh>CO+BqqmI_aF`0BwubI4l1=nkWERT|MDRRlokg4QyA953&s?82y7fQlb=TSp z5+rHHaqjl6v?MgDS ztv2kZ0(RE!d3kIZTReG?*9pyjcdanA!^w!uSrh}@@*>pEs8_TWkaw`K@?ieq=)y0! z))v+w??f+mvkz|%Z_`afb6O-|I{BaO)kDL;ny6pTqg>yI2|N$~7A@g8df5rNWwEqV z)t6kJK3br-X9lWbgSf|(r8uhranTD(rxdK-s|0-iK`M&0#8DWH#v$ZKl5LMQv7k)F z_jm&L;7J{G)_6ung7m&up)s4{`Q*$Ebt^;VnLV27#*WUnOmPyOS8 zxc+Y(Z+Fy45T`TaumY&ZK=7*nHE%;}H>`r4pn@;N7D1)9$6r?g|9FM%n;rYE=Na$S z&s?2Ouj>g)cX&Tuije>x7&o04c}72zEyE%|O7hSg=~scR(J{_qZj)q*KX}!L)B4vbL#zWjTfnnUnHJcfrvBE}tPn8eyfvskKR_ zK52bDp+p!r6_QSG1UN{{_WN`L>nXFCAU7ADZ(XF|nK)S2I`DYxpFiY>_0DF8_b|)B zw*DERBx65A!Dx4I8Fc-wM==vo=r!}^pGmbz3@sLu&7G?tHbmCs=Ws_^;kgMH0u-sY z!N)KkF*Lj2otQkU9o!%#K>w6eux_wze@bwq)#K zclQ0WVk|Mv%;NNvHYp}!s>tG5jrIb#MuE6t@msq=LUSw+@P!O9ohk;1Kz==Zz!_tV zL6!HT-fC6M-g-`!q%vCXD>I~h&Mjjsg3#>!@@@7j5?Kn&n!~Js*@_J5>7gHS)u4}S zIRw2QFm3@^3ESJxvddcqZ3|s%0e>+;z+=jirNd;B#tT_7_v(pRoI{3I%JsN;&QU87 z1I-FO^?$!BZzic^mKY-5KbBU|JxJKNX*n=m#=a|kENvd4O6r;2zQJ=MNBn$>3d?gM z0v%6=3snnF$Z{GT2S}Sv4xv-$E~NKUuQvE2*zK4Ko=3{$oucu5gk%Xcc&+IzBX75| zPKsf7Aj=p7egend&r38vdEsX|>AEZnrsq&b}tM32YmPn@l9Q+~6 zm;5&l2)c~5Atz)}`!(nQWp^a>iHnIC^u(NDT(gcTIlrW|Sk($Uzlou@p$_E;6-Onz z0DtGLAU7Y4)6HT7c~d~x)7dao4yW9Hf~MFyV`3At3s3w1PryZ`>#ZG>T`JEY3>a zl~lRhSrhrf*>mmqhFWG)V%;kLb_nY#zdCl!J#E;Hq;#o`n+5Emuu)Dey~NJVuryVjcw2u>bh!^6*p zBh5mPng_#6k@;+)U8nxF^vjVs*+leUmxo-Nc(haA%;Lzk2C80{&6Xt-L9WI^ zB%TO>*CK&s%pVONc@SLU7|jl5&)X>2H@A*S4%p#)tG_s}&6s|0j_L|-hmUI-|4KS7 zQ-HpAZdH8rk~)}ltrc|W!RK^zrP`qGk(XPQ3yY&@+tH%Zf|O4|=hndqlvq z@Xx_bP?(`PC1>JB2S4BZ`O7%68>J@II zVR|qY&}Dxd(VBVvk0t?)1;g|GaRJg?$}^&a{AoRD14l1+I#2bNm!$4wE=w#ZoZ~nA zD=`iAsZ$qaFOOtW)r!N(E!_*cRiiuFK3J+5&=W2kf)y2XGpVzSu1C_u#1w4#ropS@ zUF~k2*81VpslIO^oSqzUlXg1vSW^AuGsSX@sAbf^ z0h4D!z!IVczm;66`+rPCZ6R>6YGWhJ%DHhp92o-OSce(_@eCaDC@5SJMqXzW4s!?c z-9(oweul{5*j33o0jkkP;2*|o(80dL2!#cGm!pilIyT35*~Z>YrB_ufB(En=pHkYr9J{g$~U8s;f!*sg|Zi4gEbHmZ8Ij8QG*t=NsRHi@T{$m2T$}#!a3eouV z-95M#4k*j$s&Vy3kQtwcbXcHbJ`Nxof#pV!!eU~rS8ckV&p)fw>--!?Oam%R+gJ&- zYZInUZ{4t`+dyq#C)#ixG%G4L2n;q-o8NdG6WQ402~}6k)K_p<@p-_&)MyZ5l3NB5 z-#V}qYAYO09OG0PViU!!@eC0AEBUWH5=?^22NS5trxM;qgT%9m?zc}^z`LXW_>tz} zxI7+nVU+;RoJki^Mvp~Hm=$0D>ZT~mZ~dhL)}x8E^}`b6f1Fe0GBqz)T63s!+@-0Q zq>-TjcOTSuE36pT`nV=AihuG_&{fmXAl*sQ#YYWrGxX949K+LJ?}4r6b(`wRu%oTq z8%kLN&IbApp{}#Io&|qg+7B%=wr8pN=Y^M`o1&RCoyXQt2ubUdFb6jRTY?t&<0Hn|%TY5_wwBih@sS14cgQHIZ zLyA7yk|S@6tdLijhP}uN8xU-jft~8o#6LM#l3McyS^-*AVJiQsiGwb(g zIFoc5%f$fLB>vW7Us(4fE8Dsc9;+)-%)`I4v@&ogPqQfIs9^zyqcvs%fx*r=ZP*p!OxbOddta&vPKuR7F@9U|&_e!YSqLY*f*WB8v@U0M{xR+F)oA zb|5*Ev;e)~M$-5;xr)~G*n0@PLSAGjlh+k7s{S2(A}GzLsq$6$TF)AmcXl;$2Rnb+ z(z%s2rXEwBTE%z!AN60*L7R8kTEP6>C!DyqxBl-#-FAvg}rB;j#FkkAPp9u86Kv<|zpXAcS^p zPxC1OY1!a3RW#$)W6w}js=1;B7c86oS24FxTw^Eyt;)$H`qFr`bXONpNG8%yB<2TI zVgny0HxF<6vyvfMYMVYvewM&mZwj0@m%2>0HaucNR%QbDHPe?JoFS=|PAFS0Rc%jG zTR9K>G~+~W=-2{xn*g_ZI2R4y;g_^)&_vtJE*olM63k#NI&}GtlgX98Ym^XXO(Vil z27FDM;)*7}0)%H4)o!yFeNEC*FNjwdBMXAvlC`M%qA-< zZD0Eh6IDOcc_T+id+EuyN8Kdl1TA2G=At3w=gT$D&7+BjITS2L`8V)!IO|WMVQ{iO z28WzdiTqskZ~x4WOTe$TDS2UfVWE-FcfEwh(-F8%67R`YSe%S1OWKeJzY-R4v$)d&3`kXF!Y02_{)|YvR*3apPvL0#babvDngWo{5~n z{V)TK!y_DKLxR4ir4eWgwnf7RED~Su3KAjulEBcJtsw5Kg}kLcdV}UgbA@S@!}K#H zhH*8uhybI#5Ronyx1rp__&cR#s)#6o|D_wMeTr5SsI9S@f;%oBT54M#ypW&|vkYCa^;l@8A(ys1^r2Lm|HdOl z$wRW55VCvb7)U2yO=A}_;_ShEO=r|=a1~^>RYnX^o*-(IW?)bp69(25yhr#XxPbzpObUW#GtP?xrQVachHc5hi?@z?2HaC2 zN|hf{QONRXh`9W2lNt=P6cq`|vD9F#+vA1t;b4lr@1L?1B`FQ|X$9<4P*V~NqnpBp%vhVztkI0Iy#G+7 zhq}TKp`I97H(_7HhFUpwPhb6t8ID%RMSjv>@UhQ+(ErjrVfzoojF_d3v*{mtF&jf? zQ;~n-CKFS78B;rRXA1(R|KXPVha<)_{^r^Le9!geGvb{$E=& ztpCes7orKNfxNbv3o(%oDiUfjvo9k8%AVZWyrLzF(r~M)vYekUB4DzINC+_yj~sZN zf1L#(VS;EntW_hOLTA-e^RrXi(z<%Gy18k8?~wP)KTz`gvio`Fksj=1_CEXBv*)!- zpP-PMnk+(u*=h5Bd9UzWzqYNzJLm?M9@Z@)?ugQODiVw25mAmq65EP^OViNQG6HHn z^+V!4sCar}fk}lcs+ibbaC&rOXkdOL!WYA1$-ByP-}1~6i6GCa+iv5l3D$F!^v`I9YQ^@SC%haX+ith*Eqq0!vu7m`qW*ykgmUnZ=6ind_O1H7ZlKM|7rWyW%|= z{6x}2F{*-eS;-2sC0k3hN4lnTRbe+7z9m6PQJaE)GH+9=qJn@beN!+*p+E%$RZ>)u zQ3a=EDiA&J`@35Rj!_Ad25C`<(sk`J}*-%IX3*C8=)D>$5MFi|#R&M%$vG6Z{ z@r0J{2M?PZY0!X}3v3F-pGf(@7?esA^!g^}MkzC!uBguSSZ#^5$)l@y z!ZApuc)_G)wJ!l{C{%+JLI>6j_I?8h0L&sJ`PE5lB?YLqL4PSL6a*o^zI$RGL)O+E zZXaoDAz@{wl?7o)(@q<@SA(X4^zZH!KRkRH`sIUeUia+41sR~O;VFHn9Puj7Q6KWh z?-XvrDjKmCo)=K9*=Cu{Or(>hnr93JhMK41gr*yA`Bd+15Ys>q9RrYTF!Crq+Uoed ztanJ?5`W;z!y@Q4RQ}mFq`Bh{^a}sWUp!?hMgg#_?ZYBV2tkdeq{}f-@yLqF+a66k0g%2>$tq@!8kF7p=mLLxi1Q(#{ifhITY2Xi! zlQ6sB@0)Or z7GXZv90V9@P(yk_hSRu=P+(KiZbi)^K59~AZ8U$B1L31QKBdwH>)z8x)!dKelMJD{eIcqJ-M7e@NW%BvkCzp30O`%;s?OeB@VX+jM0N|q?Oh}Y)-q`WcOMEM`jOS_h~-gvOwnWdRNHz ztS6VYL!b&lCvx+-jP;3_tSb^Ru>_2k>^HS)TGwr4H5@M848 z9hstk??r5Nk^2(NwgrtQSV&53o^!{Hv_aU^3vR z73#^U{{&_LwL?q*{Vk?Pz&fVFJT)3BJ2;`qg{d(&d4>8u{R@PnHgS6QkTvchOemAe zn8VPt3%rH154s^YFZD~wD0~kakUyt43e$*c-GW{^n*PYRcc^}&6tD_G;}D=6seTO+8eTT`Q392f+_#tNhYZ?Xkh z3dJB*f9@r$L&aX#^qY2eMPl`YfNSg}5a>MS4%npNl-R3&4^-tGxB^xVRsv(TIz1Bf ziah9BdhvmPV_1E`w$3`Xl?N&cK+y|Mej2O+)%z#^Y^#>ml;Gm%sU-Nfv~+)?M2Ji2S+ zUeSfU2LZYbZja5Lre7|n`J`R-jY{`j8$XxFcP?t(o_h|&NHlocKq_%Tf~ho!qi{D! zFK9-{x*P~L$!kc&Ax$TtwZ40{US9U(f&Rx{LS;VkKaM<-t@Ybr_2>@li36c^oG}qF zP+Dn=JQfRZ73wg)?1N!}CWxI-k#4>-ACto0#|?_9_C%FoHA7Co5Rg&lk4gBy4H}$H z4~JsAcQTVJ_$UUN9=8(kZjDDD30~KCzjYefe>D`^b4NURP`mbR-I1e*lncsF6kkS? zyhWBm#(7#%Qm)Si(#Whwddbqg?GJj+y%NakyW39m@+s?=@E+|6>jm0y${|8MDRL3T zr>qmTe3Dc<^J#IE@fEYr^;z>qjC=N8wzWE1I78v#7jMIrNzQDpAr6$B@f@d6_{_Hj zL37z>^*NJ$EguYHHBlWMW~5jmVxB}pWqhS`OKWr#)0_C&^Ng#B3%mBFDvb@VGqBZz z%TtemzY2g=H$=gzs;8@YwLqCkh$?9sdV8x2Q-=tXPO=sbFL0dbjJQ6I-yEMNYP2mL z%Pi!C@Qox#2fXbpC$zr)*gkRKcj5mA=7cU54YA6Xjn_{3kNHSKW;gj) z?GyIJ&B>CS)A<&p$e|TZIRH+DUr$J!w#fB)W@;(Dsxi92|&@M{$cy4^V-&=l2O7Md! zx|?+%jMgig;*6g>!g|AH5+J3mpoy@APR)AxAu!%He*SR49kXy=(4@$YQA!{*-qKv2W$G*{o3=zQ zv=}94oQTgE55s&8wF;rYuqeOsBQU)@gpOp6TA%#-2Ib^oiAoQz^&mX;O25sQOI>jO z33euH9IEwA{U~F3_WL;7AAjQUxT4g=e|L^`(e4{yPwYbGUnw^;uiovZ2?mce>m9uH zyN*Tw9o)L}q{FL?&HD^&`!$W+f4&6J+lvR@z=kw(NW#JB>J9UOQKT2EP_85U7+L?U z!{2wror$KTUoubm8^aaEr?$W!aO;K?R2(heAZ8zK?0Be*^UEBG>6hPrO^QNo$=LLZ zO{tutWigL$fUO`1OYbYEjtv7IgJW!7JtGFb5rFiI>~Q*F=UvgeR`U{ZJk6l{d<I z(*5bXgmaVR0z>iU?a*?5<&S?-j~oX~juV2+7&mrwvTuO%=Ctn8x9xPt z@++D>W;VCpa!nN%q;GTLrX$nmsk~tQ_1Pfb0ng1}!9Dk)2j^E7WUrmcye2J3lA*zA z)=w>f#}R)6K6sp;{(;aJu;+{&CT`TFO?Qtr{eDXbb5bvy;0-p2V#W~U|8dLVS$ECg zR(xoo3h(uFUYl>#ONHTKuLN^#Rj77Onx#e6Ed&E`(4*8Xrd~8CA&WM-K2(#-jW*Ko zP${($z#JO+*V~Vh49kG$1>?D%H*SWz%T^y)kfRUTGxvkvf?2o#P5Feu;%o20rq=KD z??>`?72a_WIV_Kc4_J`LHJ3MGW)wN1H4Jb6qybT8TR+W$dk#R6tV0q2&_m|R|4JQ65=1qt{ZM&=T=c8tev4jP{Ie`ax0GtPdbsbSue4Zz_~tPyeknyxm}+A99>^vKh)*zXIN&oj*Mnhp`;IyA7_@& zPeZJ77j?83G!&lf8_qOJ9gcI2Tls|pBd@b&KrDp0K&sC?MIrI0AY1oA*p7Wono6_d zZm6zptL#v|rI=v0M}Ev6+P#Pi`&&tW)V{ghi7FvHuj}$^Yt4GW(zR*BF`PxqjLH{Jk)I1 z*AZZZ@T#Ye2@uxrfVNJ%JBC#PVW7=$Z6T_Ii2N#6Oid+!N#OL>!MO#e*Q1P&c#7H>hV;`}Hq zxZEGk>GQ#i#Pt&lS(^ev( zpxYHh&1(zsxI0RO4V^Z3^yNf2-K9xJ=uZ&=JFznsen1Hpx2cLQmpSAP+-zQR)6Qtl zE2~y&mltg)BCc~O`BRdSVe#6uP6FI;Vp{aAic?fYpA_nxCzN7?EF-x8)m-N+a=c>$4^LD_zt;oXd)Qm!*8Kc1C2EdoTKgiuUHE9~3wiyYa`IWzWM$ z1;yLE%Sawwfg}S));DUuu-V7m$f+KOCNA`c#9t>L&~2J z$VtB$ocsNg3V)NDgzHOpS$jy3m;+iwWVPI)XKM7}$VDw6I7R;mEaS0jy-FX4-zx^& zzY ziMFpay!FUsMtru0cGG$vt`%>}-l&g}ZYQB|jCj=Iy+%{>L#9VHlaD&4-Hlt;h>+?m zo$WF``Y9aQTg75Kef*g-jO~FI)WszS>XgNWr`R&ePa$~D`c*wJ+c+7;UH9`H+(`%# zCa8&_Q&FuJ2vFzsLQ)`l^n?$o101=&xs!aXIPc34K-5(dsojkdPNTp`r|tKr?j$?qFOgm zf*I5B`{`*<+(Iur{G3ECHxzVJf%}Usi0Dy?-#@6sGj)zDuA{Sa3Fqr+aoSGnUG2-OdMMD>+ET?4lFD!jDn>PgXBtdVD>Ex;ZEBNCYc*~7xgoH4b%AMgaAA>Q zfB6YfP%}&O`LV3D_ZDQ4<#D~o5B3FxUHT3&sK%Alm(Ku>3GAUV%egG$w(mPka{R4K zq?4MRye770ijpUODk!WSj^|^oho@coi?VGxe#ZnSLsv5d4#ECqqrdRxiU4yi?A_X6 z%wj#jAPjlhoaeJMuMh#bGR}-VLy_Wq!P=RtMsJM!0Ei|C?E)MGBt!1X!&MKg_FK4E(qqnudg=)C+nB;PI!Yfa zxZz%7a+-c4Ey*vJ6qAVQS0Y{|3Y})SE({vlk_Vh^zyO1emUd$1GZgi_qO;+YJQ>a0 z6y>j%WL%Tm9d>P<9DvrQAW;3nfuP9;l`K}9sXK^k0vQQtp=|N*`@&ne1~M0;p+23E zi2nO0L4crpJBt7*u(cEMJGENIu+#B@K+;c!uVBLY{27WMkd&%PsZnP08_e<-G{4$Q zTCG{~66f%b4P9B~aEPy}XTFdII zu3RBycW6D;x4afv-Sj{aRjkYMbL}vyqeN0i?LVy?B*J7LUgX~PWN7pi#QHZ05aYrEKMP94WF_seNf`MRd^zE z=|mClHLKn%MBxF2kisP;fFwbZfs7W%98U-e$69!6Y%$LJH=gUS)2XxtU`qlz|+Rgal$*>${fHPq)iP92uQwE?2 zH^WUb@y_5nktV!ZY++V2Y6HGD(p%l-P8W$e~z;emA-=$^Cm* z;S-u8tl!Mr>aa|a_8r&V+*+AF;M?JBCenn=6`R?Q^Y3O+2tp9_hi|iITMj3j2OS=5 z&L%_IxrQ9#dfjimMi4n!E;c(-J-n?oBfQYSDEYLGSi1@1U$DO)O`;4Cv)CT%a@E06 zqSJ~`nJ0($`VR+FoQf{NeH)-Twdizs(QcoM+UI`@>D5!Pi}p6!V2WvwF_KM{EYm6y z-1|9*6^{gySdL(<1*tdPLmT07ilaqHoQ3$8H%Bt9CjaHda8H{fm2?UU9!e`gTU=OP zkbYv^a6_XwM+}ZU`A4nWx);5Ebti0S;q&C@1d3U`eqM%+k`4IFn9Q`4Z;LLBiWOyz zau*SCkC9F)1Cd&~vVi@))X{tPyBZic&)&>lx%p>ncib@Oug-y&Lx-uR?mSl0w6@da zk(V;Er~6Qs?jEcZcITWt{`}4{{O2^cd^KJmA0EIcx0Fo)&qV9Yp~7y zV2I_ft5U10k!p)$MvLKZU*qFdEM0>|f93a2P1vO-IY3$&_LRnd!aM>SP>B@rtfM~x zvhhVhLIklZ*b9Kw=ci0`=kpq8N5gZ8+M*5ddoYsJOMuO{6xzvZtEGw+jaw}}JvFyH z1Gsu=O)nB{9Z8$ZMMC*aTpGY_pI3CWO}caiXs3ZP!W$8-UCagmM)U^;}dKh2OWv9ad{RT8!= zeSO-?kHJmuVXu>t>TdzM9^B~_6jzqrmFq7D=^zufRI6`ZG6B_>?ZnM=?%Lw#nD;hX zl>Dtq3UT6M=ABEE;PMMQo@IfPq-mH@QOb*T;%JOH7`aK!ar}WBi~R)`uhYAy^D+Qc zw~|Y#pC^aOI|vJ9z(9U;r+fSK&5e$Y=b{mJFc7xYiiJB+7z zsa4b@Bd)KFmQzN?FwS-?SDb)?wnnV~NU86JRYZaA_IuDrr~uH&UNy6^Z)0`!3b}8W zK7ndK2^`Z|cjZC_i_l|mvdvI6a3tpcZ10>!i%w|0UA13Fd{7NiQx`n1fcggTO|@!4 zWZ#g?{mOHa>ES*$<%2m>89h`1ULFzArM&1r0Nl>yg^O}mNCi>dnQMh!f=GZA&1>Plt zk8*MtaeA->G96F=RLja?g(!1w+dQ(II(l0TeDzCluT+_IGu_7=HXpAzk;8pkU_Wp? z?c5mBGuz0#G32Vqr#lrp8>E64|Hns9Cl9VPz{)&P@p>?GUC1=Bq6t|bYQN-3MsamE zxscF!!wn3FmDUG9dR2`*EAyVQxgrUR;H##Ch22=@Nn4pWt`J90&z;7CVhJDW^BwJJ zg>hc;(Mh=wHH2?kxA(Ys#%4&qO&RzZ;Td+O6znT$a`Z*&5DMqaja~f(@n_eIGzJ>I z=~ci4){R^R9A$N(>T3V8bCL^X`cYa5(mXSyNwPa$nwIV;rmeMP6+{Bz>GO1|AF4%xFcJczpl#xafQkY@fSN)=FTA*( zl6O0jp0bs%a(6k!O)f}_kOB1|C=L?>Qv{F@h0H~VOqaN0jyNfG_3d*#E0F2i8IHa? zQn_-SxpkGZuf1p8XS_Q&B#ej$4jfMZev8X#u5pZUmrr=s!6=qfgrKI-31+)H>=48l+UH6RBnN+Arf& zzAZ8eS~^6BwEC^rZSW)ddHcM1vtE?!ecAMgscDaYs-WEIOa8JI|7Ck5z1~pT74k); zud63%D-0i_KQu+NJBtVj0V1r^=tozF_Dh6D;4M12754ir+fvkYPQ&I9Oub|uzV$j}a`2M^c| z+K!_ULLGk@^OHw2AVIE@r+nNDxK9iBcSw+uD+rj|lT6q13(Blvsg)fwK`=2IU z2^LJrcHUZrqb~}oF-i!LN{XrJK#k4`9Sq<9Y$nDck`Ii2jDx|FB>*oF-oZ8ox5PWC zR0+CR>;w&x(9*`Oo#qi=$Ip!c& zkpfFP|G7TxQ$OR5Pg$!NDK%i|o^siyjRVJ>Jx?jfSw>ehrJ?I3fp{J26j?=EPICF} zOJh_t9YoPpokYXY{<^uhWZfa$;9kC2 z)rjc`?`FJ);e3^qU{9#kJVjDr3Fv?>NK>FkG^IgfM)F_i^(^`?tlf99rcv5jRRvbA zf9#qb1vPmt#n;i;y(YxIRXP(>d|PfZ3(Mt0CEg_BlV)emK3e~4>_B53(s}LF_CHij zv1%zRT7Zo5h4=>;p(0$bgGyMMA$6& z?e2jZ6y%fFlhLg?sRI}@HiIcf7O3f$Yh|2? zl3n>cm5injGEaKQfcU}RELGHJ>`nU%wNPx--v#VhgS;sg|U=xTTivAjp~!)cl%@r|D|24d6f z5ddvxp8*xd9-KcSaYf3pMSb56DP(%FD_W{@AXqx^ zQephg(#@an4Px`$fdvfWwJnyA3698{3QXL%qR4nzV{`99Jnvu-#B&OTGL=%5i5P=w z&ItU$P!&Hgxy4*N`T7SyT*}5<~KTFIa_53SiP*K zE*%*QEL~n$qr2Bcb6pl!obc_|TS;{QtoC0JD$c4S`QJzu7-N}BSSZ%YaxRwnWigLuoRR%Oj^#L8AEq*YKZ_`bdGyFPfZ{njNDVW zWQ7+0j$livio`^~N#Q~1^tL>#_Ku(_{bHeK4HKFhV6E>dFcmD~b&@&yI+A25^Qxu3 zJyf#KpLIttSU61_!ms7rZ|yUCGqYq%+r(YDE^Y(xJ2xEI7NnV7E{~pu-UX3bgGYs+ z&Ell}t=QD=hi{1N4e&*G&L{g0-9`U)EgA&L@55V%;tuv*I1Ab;xRh!Z2>Vb11`8E2 zg`%|TUEy;#tvDTo!O1%hJa>fxvdVw!o@ zTgqaRf8IvLCZHuHB=#*L9rz+mwx;T^e9!3uJ%A)by)(ke#rKaLv*-+uBA}G-&#vK5 zDQL9ttaub3=9qe@UYB9k!H-yqHT}C3ZU2GlGOc?!b!`WX=I#~O7ZASGwVW)~=C)?2 zV3MwgAPojw9jbDRY$v;_}j?W=I?3QTsY z1+i;XtvEQWmSruY$ih%EmR4`2E#J&!N=`8I#guYPZYSZm$QrW~!oippj|v|f;FCo` z=RMl!(HP+GagD)bE9D6ogR;s}4ViOUxVAZ5$JWH!mm-E|*ss?RVQi;IQ&G|V^2Tvu z5~-Kf-ii`)d*2;sty*XAO*gg+ z1NZ%7$ifwE{nVVPX_eDN&kRA$AoJ%`I6vM52jtMps@H?IG-M0TV}~OA+_2lY`zmgp zX&Ey?Us!r@l{)Pq7T&-*j#{%7Bp7x-KM<3+KjAT z=50}W+@Q#Pf!VKnRvX>s+5MX4z7_}bbz{_B~N%2M8Qt$@GcUC))o_0$K63!*c`6p3AS}7iw~AzM~KCFFIoI7~h+- zA=@~_e|oHTpf^Ij0r7EAPPUdu=m7fFMJA_KwXVn^*gm*+33Ls;nx$K?Lc^4TrCz!R zP%j)x!UjZ<2ThFX1=SV8p7stZgNXPBMiInCcb)rL_p`0)z)Nz}$Htsy)adx-ESUg$ z4axTa;}0Kvs~>=+19B3~AGd-#mi^NShjEUYFqN^ruff^?dF0slE($wu49Pv7`kZ54 z`}~vTx0k8jrDlVLfoRXEASQC9NZGQ3Egz3Wk0-?)O?RVCi3JFG{}y} z)6WXRv3Z1XLzb-(>&;!kChbU#$WQt)7xE;kX6#+|VX|zmy6cA=bgLKKmb!$+ssTW6 zrP$0Y+C}b@QK28(k7@wX0y}f!*PqWm0n*+UoyF^(*g%F2Ft`Jplzsc8FvYG|%CNe+ zU&IUQVnyO`rn25AH1mCE)KOg8m4FSG5GswjEcW?WatUeIQPraYUOePcMlF~v9$YD2 zxr7eA&o3=f(p37rG;)_WZvMn|dZKk8S#$Zae*^=t}uivHm^@O*p*?;uolijh&T zV)w_6{oM^;t&%O((m{)F1IyZ$l@r*itrO3&>l$*hHtU*wS8wu#C#x)>YA!yOTvkC3 zBj2sp%EGaQL-0lqag(j@u!PE@F2j0z5QDz^QWvg``;=%;n3)KKhIIa($t7Z0ooFVg zA|q!HQ&{Eb#I@lC8Q&9z|9B1-kkPoJ7#_18iEN|zZluz6@!<(VFHi=1gl|C4@OAzy z$lhz}MJ#n5`vk6z8d$_Q3yQj5PtU1&;$JYjO-Y+$TuKki)9#jDDZadJ>=1@?sQr#g zT?=mj9^us1_s$#`7m`txO;LAI_Wc9Vwb@wl254qCP?@q=WEa_}Noyhe}+9{O`%u|05$%59?9#ReU?%G&kx zmS|F{TaK}#QrMWT1rMKd$)lYUa@HGn7c&UtCyt!1QIJl5^1ii7r;<)S9*P?<+jk$| zR(SY5;Y)QYZ^E?Sj7d12cC(p~(yPoM#>ji|38cIp`pILng3M^oS5-Gy1&61cPo$so zY`@!=X_slE70^6}R7c-)s;oiyoL;BZFpgQj;G)ocwO8hviXY>zhES{7qmw%3c@Duh&oxFK zwT*k(aLMV_TPIk3m}W%e)5!GKS-6sIaoZZJGsrA~ru@z0fjz3rS=kxmcBXrb+m^Q= zHV5+MIUKTFmR=F#>cxr40nfxzAL9d~h0+ zKHgH?K-lPFZ)wpzn41E-3RMy%2}()Z3SiZ0_2N;Zx7mHKjH$C9u393yP>lw?tQ53$N#-K&+ZXlW(5F|B zu&#mmv5PLZquu^Z!i#qF&xN)7ewC!$E7l4X@ObGw6m6jWu^+T}C& z9URz@EDZ%;&!Sl6RSVQed$DI|wfWpN-t;tmaySTqmhLGX@o9}Ihle8zFS&YC3&or?rGUGE1c?&zX`H2!v$*d!#F43-kzc%&G}D8%6}I3o@^!wRN_*20307zS7n7NO~?c4kxBn z(`J7llQph}5CuzIKt2>$1w5o|glnUrns2R{@yKETljDd==CeCSHk|RTixF-I6#vN6 zW#BSm;ND}w)t8e{x#LTyk*U1if`+z+Z%-UOk$^iCziU2nj2{6d1BMlgK;fK{xInFo zmx+m>5;7Tas*RQ^?f(^aR#8!SdmE->Bqc?8 zc7LZ^ZsZo`4I|FqR&8H2H`_{tDGV|0U1^OsqB^q0HlCXR>$8p-r6Ne(M2sG}%qJ$U z3N0RyUsujhyRwe|jck~1{^9v9|IOjQF~@(Tjs6GE{EsXX5wALdan0`PmfQzjK@^nN zAZ)q+GW{RJ|0Un%(Xg=9c6Z=Wr{@y@{q=CWy1CQy0R@5oL&+_`FC_5KcjslJMc2iF z2LExrTuwq_^(e_z9*&f9u2*C1mgC??7%N{dc6uoEhi0gZH0`0^qd{w{QZTcm3jeQC zF!v3QayAYM3&O)r#XAr)7n;~28_w({6PHFnRIO-DUesJm2EWMg z2`fh!5p}bSi^i>Y0p!B98M4CytG&s)rs4tS-7hedF*5lTKTBrydNI)~OBMy^W#)Ch z#lVGgl=FXVOwYw7S57gwWT7Ku} z+fZV->l73}DOUt_1T|*!yKXlz>qLCWfqKC!MEe+#J_@;zR9K-R&J^arn_whMO>)U@ z&CDwqd(=`cVqE)6@-yOj0VSy>YRM4BQ{H#rllEd4L^y5b8+^uoNsxLnAJ(*71X-H8 z5O9ivgE3RHxEsrjSC*aixz;*^G4K;0iaBBkm$^uEP>=LoT%t0bO~KD#Bg!7qcQuHR zI&<-jz7T!@>RLG3_Iq}sJ4_~n^E;7odEA7M%CGrV~e0wSvL z2ier1XS}S_FXoYh+HWlfU@zMGqpu55LCI^Nt>lXzxL-26>bEc^QvxRecOibrz0LUo zh3$-1LY+Hkv;D&P)p2WbcJ|zG&hUk`V70DgIP(DOHfY=Gj+8JC$dQw~czBM`OSyd0 zT1GLGGgRldy7X?_UCW>IFl=q{Onx$KC-3#)!f&a`mA;yz3Dsm2F|&1gS+LY zj#hoa;WF=qin4RLi`uH$?L;}F%H-+BKl<&Zi*g!Dd`7#mbSc$k1|mBP6rTkohtR43 zeE?1T!G3Z@szhY$hZ{loZHu9Q1*|;=PzngoR+Z?UA_+(HP!iO+fubLjmwzA$`i9~(@nFcH`U5Y8 z#=7%EOobpk=ADb^S|Irs`H@^qmiMZIVZ47(+DQ~W&K?eM!4cWllH+NXCqBCDyPkV| zI+UIR?Z1gmI`P`|W)RjU-$oC((b#A9n#~sS`fOuJ3g&Z&fGg*_HbY_T-Pl27lfA9!UPcs1YX6W2z`kOp;W(Hd}<|Mn?M0&T^ zUK*Tpwu;$f<3+6x0=67d(T?dp4Peb&H=4kGJ8_eq;|$yRodtphT*ijO+Rdh4osQ)* zCILcrj^bQpjZ~E~-U@mjcT%!+WR~#`K@hRBl!E$f4>MpF*IvF^>x9rfKIyZcnWqCugWdYQOIR1&C z7RkqJ8#9sh(u_P*At@CEo*pIhMuaN3P%1xZJ2&!Ibyo5#9TzE_97*90XC2P8+jO;3 zS?O(7g~71j%AMRv#gDXuOBFrH(!}LBZw@5O#@fZ%fz6=KFl-YNv^ir{PHt8*p3S~& z_kK_2t6*!l(;Iw>H(BPVWP_PwbsBs77PHuCL;HAs8bxFK0)Ev4TkhNe(rR-rR}1=g z+_O8_rnlYmJM^~PgtaAfNo0T-+`EDal7cN&$upeM_hu`r(F-?MaDnQ$`(%-2HsMKB zQI3_7c>M+QPkrXQmmZipw1A@C+i{G`pUIMh_vvAjQmb{LcE;_Yr~01HEoa}xE4kF2 zb2ltnNF<~7ou58=t02!X6H3l#Unbc5wCbzE4=elM9>})$%#P-iP&9&BvIo_@{t70O zez^x^9E6EifQVwnkhy-5WO<@_W&l(3(VEf}g?k%1UgOu4jnCjsf4bT>;oP>ikMN4g~&z!DLk@1u)08Mz^f-ik5=1ErPR_T1$ zoa5WiCFVMdO#}M>h#6k}IGxO|ej>h)q3FqS)>!Cif>^xQEg`9u>L-S$zW8Z7v~IX7 zf?foZG(bc?1%yfnsa-fnUJcw)%(R#woMwAjg^u=Y)Zy+rCMJAEXSLyc;E@W&8*#Bk zq|K|RlpQr~Q}-0ydYbI28X&>yL<0UQM25QK_;`k?wu*>M98cKA$vUpu6OMm?r(qQU zBWak+0FwQ77@DEJiE~Jx=6_kI=W(o-%Hq2n*uL>>e%Q-DTFrBOx*=a&MtqN!&a|p5 zcHQ?bM#i>_q1jDwxG;_lwl~khG$@sFpyhZqHi&YKMVgq|DlA9JZ(n~zRf+vcm!?1> z#Fkwn2E(#E!ufq79)5&&7B%oE{>zFMEJ8fC(o;yy(S&(O#R0h12If`&b1H^T-g1Cg z;wa)o*aDlHkLHh8G*d4qe1KqALu*JOrZ?v`(eKO;5tct+6TpQ&Z>_Lk__Lwu(G*m9 zvOD3`g^gO! zZaYD=Y^fNk?HR(|hmx5wG8~KEiQjaz6{@y|E*qko1}VQ4L#RZJ(vqII^@e&OmC)#8 z5^=h$GY3$yTDYO;U+c*;(j*M*Jxh}+7Gp41t(J28JiSG4NwCh;|B(N3<9y1YZc-r8 zIj~HmE&GrHZTa!UIX1<|6*A`Wb=Fh>3ZjDVeqaNA3BXPG$s_hXAd`T=TR0>F=JVrJ zr@_%t@2hPVOVavqVaoKOZMl3Iv-SK`=_NQS>$_9t?7Bne`+o4wf=simV%2=g%ej{{ z&7QC3E(bkslI#e#JhktOZiKs;36=@ifPC}T`ED4!a8>2rA|!LC(_88}k;IK1jsYEi z*HQoN1N7#H^{W00m3gt<1N{wbF0GBOzZ%kCV5;~&@=Ia&rtkdRWQ1xuW`Rkq#oQi5 z<}7qa9$SV*EoS)C9u1`q)H1-VO*us&U9};KnYQd~P)^TH6&BOj{is)}hTcrQgKh@1 z_{SGA#XhRVcwd*-eqD|b=oaX?_&m7Ij5xt&4vwZDEFU2O9v2+Hchk(Jd57mEE=0>@ zY@1UXXXg8IG_5Fi)87O=$*VpE)k;Yop|6!5) zfTae9t$cmk()Jt23bX*{C;3v~`m~LRiNG9$xwTf;Gyi+)3Myin#0n|D7in#I^pVXl z`t?_mW8}g>WPIM(d*=bz^Q-LXQ5Cel`>aAkF7~QUN!m`u(vfqP2+GNq zL*5v_euVOuxCF1nBHIZ^!4#G>E5kyJAujCB?|AdX+GrNf#zclIJV=z}g@sMh*~67n zCXtN4IpBjIF6`ggqupJqQwy_O*?uwva0^G)6orYTzo3PWxujh;ktrv75KNK9Ep z_!dSKn{Kqfcekl^H<%`r7$sSlrMXZT$30t|WLNR=d$Dd0u{gPLvg!Bm?6aUU=0GS` z+ZrwIe3DO{z=nKhyg8$JAesy&u|x|%NPP^J9uP|(R5{T-O5e55M=G6v10_YdpqxUP z224m}_*xPP7;Df0dagaIciiXz13S7Od$UQ78ymuN5>$-aVug|F$}UoLn1x1BxtD@i z1DoDDgsyM;3op2W?QnG!ItM4R={+d>M z+dpf*^)A|@!m48KQToJ3Rg^t({z-$2?j>)uvZQ&OBGgpG9V&&6Z$<(QjrCw9Z{@o> z%k$ho4NicVzhuufGo3)0lQmXv#PEw#*KdaE0+Xmx~dS4(idF4ysfqV4EMoE78 z0fw#0Ep$A&owQIKe%c?=h@7<+Bd7ay(D4vG=F_0D8SRzxq0bT}?efzk7pi(18 zQ`h%E-k2&?_kOz-+MR91ya&>V3gG|Vhhi{7uW^Z+jkhuPC2FNO${$51d`sf<>+96l z_v`jPzju!N%uIXIDMst=>Yy&zP`)EmXt%Ph0y%>$ok7WH4A&=*!C;73!V*-s-)!~D ztuK2mif)Vpeb1wG2Y_kR3SW?cPKgWv~ z7qUyc#}v#T-!Ok{HGAt)m-wzp4Ju{BR=Q@xTguK%Cf}J|w7O}*C$35s5X{+|W`)wt zt#|addmg=Mis!K#x^Ga^WX6a2xas6%nsZubEPMVeu8)@6vGVpqT999QkTL!6I-bBr znfa76Pu7a6{KMR+{G+5N*zzW&=~_x<$#kD^M|Hf;s(0xLy`e`L>%ZU@kN`a|y_1D4 zKvb0H-@HZtt(7&8lB|&^NDv4HL9B#$Ex`gpyjB(vegP0fh#zRh2j%A#QEuhK&pgH_+K>vg}EK>%c87<1d zUytdrc#+g;RHSTBz+ix^JaF^}>yg#Fn-DnUgu{4urU)2f)=$<%iAm8`iIRc!n;tP7#snynGcT zbw;+BJ@#Nu`M`4U4u*P0fX4ExdMwx+&wc|uX~63jXWYuo)5V4pq=^&a+=N5?ma+oD zBZUj5f9@#5StvzX*lYP$2*vQSjvhO|o4_lNGMxbnm`6<8O;!?YTN0#S5++=N07oET z&e-YnsM#_cThfeMQsPS?<(eorc|=v+9_+zDcEn3fRKhg|<{%QzZcI=fDsYWsDHy64 zL{1qP@IFl48`bfBNXi5O%><_Z1iskBvublR(_WmmFa~eJg0&!*TlQ_t*_;Y+qcfa~ zlaR|;fm~4LFL5q()U;DxvNBx#{-|JQ*k)rmyshA4oWepG%6cQ8!u&~H!$OHZlGD{Yv literal 0 HcmV?d00001 diff --git a/src/NzbDrone.Core.Test/Configuration/ConfigServiceFixture.cs b/src/NzbDrone.Core.Test/Configuration/ConfigServiceFixture.cs index 17d1d72bf1..7966eda8d6 100644 --- a/src/NzbDrone.Core.Test/Configuration/ConfigServiceFixture.cs +++ b/src/NzbDrone.Core.Test/Configuration/ConfigServiceFixture.cs @@ -121,5 +121,23 @@ public void should_ignore_null_properties() Mocker.GetMock().Verify(c => c.Upsert("downloadedepisodesfolder", It.IsAny()), Times.Never()); } + + [Test] + public void FetchRegionalTranslations_should_default_to_true() + { + Subject.FetchRegionalTranslations.Should().BeTrue(); + } + + [Test] + public void RegionalTranslationVariants_should_have_default_value() + { + Subject.RegionalTranslationVariants.Should().Be("fr-CA,en-CA,es-MX,pt-BR"); + } + + [Test] + public void RegionalTranslationRateLimit_should_default_to_500() + { + Subject.RegionalTranslationRateLimit.Should().Be(500); + } } } diff --git a/src/NzbDrone.Core.Test/ParserTests/IsoLanguagesFixture.cs b/src/NzbDrone.Core.Test/ParserTests/IsoLanguagesFixture.cs index 0d398a771a..c37d6b8605 100644 --- a/src/NzbDrone.Core.Test/ParserTests/IsoLanguagesFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/IsoLanguagesFixture.cs @@ -22,7 +22,6 @@ public void should_return_iso_language_for_English(string isoCode) [TestCase("enus")] [TestCase("enusa")] [TestCase("wo")] - [TestCase("fr-CA")] public void unknown_or_invalid_code_should_return_null(string isoCode) { var result = IsoLanguages.Find(isoCode); @@ -129,5 +128,83 @@ public void should_return_georgian(string isoCode) var result = IsoLanguages.Find(isoCode); result.Language.Should().Be(Language.Georgian); } + + [TestCase("fr-CA")] + [TestCase("fr-ca")] + [TestCase("FR-CA")] + public void should_return_french_for_french_canadian(string isoCode) + { + var result = IsoLanguages.Find(isoCode); + result.Should().NotBeNull(); + result.Language.Should().Be(Language.French); + } + + [TestCase("en-CA")] + [TestCase("en-ca")] + [TestCase("EN-CA")] + public void should_return_english_for_english_canadian(string isoCode) + { + var result = IsoLanguages.Find(isoCode); + result.Should().NotBeNull(); + result.Language.Should().Be(Language.English); + } + + [Test] + public void french_canadian_should_map_to_same_language_as_french() + { + var frCA = IsoLanguages.Find("fr-CA"); + var fr = IsoLanguages.Find("fr"); + + frCA.Should().NotBeNull(); + fr.Should().NotBeNull(); + frCA.Language.Should().Be(fr.Language); + } + + [Test] + public void english_canadian_should_map_to_same_language_as_english() + { + var enCA = IsoLanguages.Find("en-CA"); + var en = IsoLanguages.Find("en"); + + enCA.Should().NotBeNull(); + en.Should().NotBeNull(); + enCA.Language.Should().Be(en.Language); + } + + [TestCase("de-AT")] + [TestCase("de-at")] + public void should_return_german_for_german_austria(string isoCode) + { + var result = IsoLanguages.Find(isoCode); + result.Should().NotBeNull(); + result.Language.Should().Be(Language.German); + } + + [TestCase("de-CH")] + [TestCase("de-ch")] + public void should_return_german_for_german_switzerland(string isoCode) + { + var result = IsoLanguages.Find(isoCode); + result.Should().NotBeNull(); + result.Language.Should().Be(Language.German); + } + + [TestCase("zh-TW")] + [TestCase("zh-tw")] + public void should_return_chinese_for_chinese_taiwan(string isoCode) + { + var result = IsoLanguages.Find(isoCode); + result.Should().NotBeNull(); + result.Language.Should().Be(Language.Chinese); + } + + [TestCase("zh-HK")] + [TestCase("zh-hk")] + public void should_return_chinese_for_chinese_hong_kong(string isoCode) + { + var result = IsoLanguages.Find(isoCode); + result.Should().NotBeNull(); + result.Language.Should().Be(Language.Chinese); + } } } diff --git a/src/NzbDrone.Core/Configuration/ConfigService.cs b/src/NzbDrone.Core/Configuration/ConfigService.cs index 361d997eb0..eae0ea5b9d 100644 --- a/src/NzbDrone.Core/Configuration/ConfigService.cs +++ b/src/NzbDrone.Core/Configuration/ConfigService.cs @@ -135,6 +135,24 @@ public TMDbCountryCode CertificationCountry set { SetValue("CertificationCountry", value); } } + public bool FetchRegionalTranslations + { + get { return GetValueBoolean("FetchRegionalTranslations", false); } + set { SetValue("FetchRegionalTranslations", value); } + } + + public string RegionalTranslationVariants + { + get { return GetValue("RegionalTranslationVariants", "fr-CA,en-CA,es-MX,pt-BR"); } + set { SetValue("RegionalTranslationVariants", value); } + } + + public int RegionalTranslationRateLimit + { + get { return GetValueInt("RegionalTranslationRateLimit", 500); } + set { SetValue("RegionalTranslationRateLimit", value); } + } + public int MaximumSize { get { return GetValueInt("MaximumSize", 0); } diff --git a/src/NzbDrone.Core/Configuration/IConfigService.cs b/src/NzbDrone.Core/Configuration/IConfigService.cs index f425f540e7..9b37376e45 100644 --- a/src/NzbDrone.Core/Configuration/IConfigService.cs +++ b/src/NzbDrone.Core/Configuration/IConfigService.cs @@ -65,6 +65,9 @@ public interface IConfigService // Metadata Provider TMDbCountryCode CertificationCountry { get; set; } + bool FetchRegionalTranslations { get; set; } + string RegionalTranslationVariants { get; set; } + int RegionalTranslationRateLimit { get; set; } // UI int FirstDayOfWeek { get; set; } diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 23a3b71ab8..88b60363ba 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -1150,6 +1150,14 @@ "MovieInfoLanguage": "Movie Info Language", "MovieInfoLanguageHelpText": "Language that {appName} will use for Movie Information in UI", "MovieInfoLanguageHelpTextWarning": "Browser Reload Required", + "MovieInfo": "Movie Info", + "FetchRegionalTranslations": "Fetch Regional Translations", + "FetchRegionalTranslationsHelpText": "Automatically fetch regional language variants (fr-CA, en-CA, etc.) from TMDb to include in indexer searches. Regional variants map to their base language (fr-CA → French, en-CA → English).", + "RegionalTranslationVariants": "Regional Translation Variants", + "RegionalTranslationVariantsHelpText": "Comma-separated list of regional language variants to fetch from TMDb (e.g., fr-CA, en-CA, es-MX, pt-BR). These will be included in searches when the base language is selected in quality profiles.", + "RegionalTranslationVariantsHelpTextExamples": "Examples: 'fr-CA,en-CA' or 'fr-CA, en-CA, es-MX, pt-BR'", + "RegionalTranslationRateLimit": "Regional Translation Rate Limit", + "RegionalTranslationRateLimitHelpText": "Delay in milliseconds between regional translation requests to TMDb API. This coordinates with all other TMDb requests to prevent rate limiting. Default: 500ms.", "MovieInvalidFormat": "Movie: Invalid Format", "MovieIsDownloading": "Movie is downloading", "MovieIsMonitored": "Movie is monitored", diff --git a/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/TMDbTranslationsResponse.cs b/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/TMDbTranslationsResponse.cs new file mode 100644 index 0000000000..4a0304e220 --- /dev/null +++ b/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/TMDbTranslationsResponse.cs @@ -0,0 +1,8 @@ +namespace NzbDrone.Core.MetadataSource.SkyHook.Resource +{ + public class TMDbTranslationsResponse + { + public int Id { get; set; } + public TranslationResource[] Translations { get; set; } + } +} diff --git a/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/TranslationResource.cs b/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/TranslationResource.cs index 686cd3c29c..9b81c7e19a 100644 --- a/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/TranslationResource.cs +++ b/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/TranslationResource.cs @@ -1,3 +1,5 @@ +using Newtonsoft.Json; + namespace NzbDrone.Core.MetadataSource.SkyHook.Resource { public class TranslationResource @@ -5,5 +7,24 @@ public class TranslationResource public string Title { get; set; } public string Overview { get; set; } public string Language { get; set; } + + // For TMDb direct API response (iso codes + nested data) + [JsonProperty("iso_639_1")] + public string Iso6391 { get; set; } + + [JsonProperty("iso_3166_1")] + public string Iso31661 { get; set; } + + [JsonProperty("data")] + public TranslationDataResource Data { get; set; } + } + + public class TranslationDataResource + { + [JsonProperty("title")] + public string Title { get; set; } + + [JsonProperty("overview")] + public string Overview { get; set; } } } diff --git a/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs b/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs index 6afb732698..3f6a1d05b5 100644 --- a/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs +++ b/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs @@ -29,6 +29,7 @@ public class SkyHookProxy : IProvideMovieInfo, ISearchForNewMovie private readonly Logger _logger; private readonly IHttpRequestBuilderFactory _radarrMetadata; + private readonly IHttpRequestBuilderFactory _tmdb; private readonly IConfigService _configService; private readonly IMovieService _movieService; private readonly IMovieMetadataService _movieMetadataService; @@ -44,6 +45,7 @@ public SkyHookProxy(IHttpClient httpClient, { _httpClient = httpClient; _radarrMetadata = requestBuilder.RadarrMetadata; + _tmdb = requestBuilder.TMDB; _configService = configService; _movieService = movieService; _movieMetadataService = movieMetadataService; @@ -241,6 +243,11 @@ public MovieMetadata MapMovie(MovieResource resource) movie.Translations.AddRange(resource.Translations.Select(MapTranslation)); + // Fetch additional regional translations from TMDb (fr-CA, en-CA, etc.) + // Add these as Translations so they are used for indexer searches + var regionalTranslations = FetchRegionalTranslationsFromTMDb(resource.TmdbId); + movie.Translations.AddRange(regionalTranslations); + movie.OriginalLanguage = IsoLanguages.Find(resource.OriginalLanguage.ToLower())?.Language ?? Language.English; movie.Website = resource.Homepage; @@ -638,6 +645,121 @@ private static MovieTranslation MapTranslation(TranslationResource arg) return newAlternativeTitle; } + private List FetchRegionalTranslationsFromTMDb(int tmdbId) + { + // Check if feature is enabled + if (!_configService.FetchRegionalTranslations) + { + return new List(); + } + + // Parse configured variants + var wantedVariants = _configService.RegionalTranslationVariants + .Split(',') + .Select(v => v.Trim().ToLower()) + .Where(v => !string.IsNullOrEmpty(v)) + .ToHashSet(); + + if (!wantedVariants.Any()) + { + _logger.Debug("No regional translation variants configured, skipping fetch"); + return new List(); + } + + try + { + var request = _tmdb.Create() + .SetSegment("api", "3") + .SetSegment("route", "movie") + .SetSegment("id", tmdbId.ToString()) + .SetSegment("secondaryRoute", "/translations") + .Build(); + + // Use configured rate limit with coordination across all TMDb requests + request.RateLimit = TimeSpan.FromMilliseconds(_configService.RegionalTranslationRateLimit); + request.RateLimitKey = "regional-translations"; + + _logger.Info("Fetching regional translations for TMDb ID {0}", tmdbId); + + var response = _httpClient.Get(request); + + // Filter for configured regional variants and create MovieTranslations + var regionalTranslations = new List(); + _logger.Info("TMDb returned {0} translations, wanted variants: {1}", response.Resource.Translations?.Length ?? 0, string.Join(",", wantedVariants)); + foreach (var translation in response.Resource.Translations) + { + // Build full regional code from iso_639_1 (language) and iso_3166_1 (country) + // e.g., "fr" + "CA" = "fr-ca" + var languageCode = translation.Iso6391?.ToLower(); + var countryCode = translation.Iso31661?.ToLower(); + + if (string.IsNullOrEmpty(languageCode)) + { + continue; + } + + // Create regional variant code (e.g., "fr-ca") + var regionalCode = !string.IsNullOrEmpty(countryCode) + ? $"{languageCode}-{countryCode}" + : languageCode; + + // Check if this is a wanted regional variant + if (wantedVariants.Contains(regionalCode)) + { + // Get title and overview from nested data object (TMDb API format) + var title = translation.Data?.Title ?? translation.Title; + var overview = translation.Data?.Overview ?? translation.Overview; + + if (string.IsNullOrEmpty(title)) + { + _logger.Info("Matched {0} but title is empty, skipping", regionalCode); + continue; + } + + // Map the language code to Radarr's Language enum + var language = IsoLanguages.Find(languageCode)?.Language; + if (language == null) + { + _logger.Info("Could not map language code {0} to Radarr language for regional translation", languageCode); + continue; + } + + // Create a MovieTranslation so it's used in indexer searches + var movieTranslation = new MovieTranslation + { + Title = title, + Overview = overview, + CleanTitle = title.CleanMovieTitle(), + Language = language + }; + + regionalTranslations.Add(movieTranslation); + _logger.Info("Added regional translation {0} ({1}) for movie {2}", regionalCode, title, tmdbId); + } + } + + _logger.Info("Fetched {0} regional translations for TMDb ID {1}", regionalTranslations.Count, tmdbId); + return regionalTranslations; + } + catch (TooManyRequestsException ex) + { + _logger.Warn("Rate limit hit fetching regional translations for TMDb ID {0}. Will retry on next refresh. Retry after: {1}", tmdbId, ex.RetryAfter); + return new List(); + } + catch (HttpException ex) + { + _logger.Debug(ex, "HTTP error fetching regional translations for TMDb ID {0}", tmdbId); + return new List(); + } + catch (Exception ex) + { + _logger.Error(ex, "Unexpected error fetching regional translations for TMDb ID {0}", tmdbId); + return new List(); + } + } + + + private static Ratings MapRatings(RatingResource ratings) { if (ratings == null) diff --git a/src/NzbDrone.Core/Movies/Translations/MovieTranslationService.cs b/src/NzbDrone.Core/Movies/Translations/MovieTranslationService.cs index 41f7434238..4b30cb832b 100644 --- a/src/NzbDrone.Core/Movies/Translations/MovieTranslationService.cs +++ b/src/NzbDrone.Core/Movies/Translations/MovieTranslationService.cs @@ -51,8 +51,10 @@ public List UpdateTranslations(List translat // Then throw out any we don't have languages for translations = translations.Where(t => t.Language != null).ToList(); - // Then make sure they are all distinct languages - translations = translations.DistinctBy(t => t.Language).ToList(); + // Make sure translations are distinct by their CleanTitle + // This allows multiple translations for the same language with different titles + // (e.g., fr="À nous quatre" and fr-CA="L'attrape-parents" both map to Language.French) + translations = translations.DistinctBy(t => t.CleanTitle).ToList(); // Now find translations to delete, update and insert var existingTranslations = _translationRepo.FindByMovieMetadataId(movieMetadataId); diff --git a/src/NzbDrone.Core/Parser/IsoLanguages.cs b/src/NzbDrone.Core/Parser/IsoLanguages.cs index be75aeb92d..74896c18d6 100644 --- a/src/NzbDrone.Core/Parser/IsoLanguages.cs +++ b/src/NzbDrone.Core/Parser/IsoLanguages.cs @@ -11,15 +11,21 @@ public static class IsoLanguages private static readonly HashSet All = new HashSet { new IsoLanguage("en", "", "eng", "English", Language.English), + new IsoLanguage("en", "ca", "eng", "English (Canada)", Language.English), new IsoLanguage("fr", "fr", "fra", "French", Language.French), + new IsoLanguage("fr", "ca", "fra", "French (Canada)", Language.French), new IsoLanguage("es", "", "spa", "Spanish", Language.Spanish), new IsoLanguage("de", "de", "deu", "German", Language.German), + new IsoLanguage("de", "at", "deu", "German (Austria)", Language.German), + new IsoLanguage("de", "ch", "deu", "German (Switzerland)", Language.German), new IsoLanguage("it", "", "ita", "Italian", Language.Italian), new IsoLanguage("da", "", "dan", "Danish", Language.Danish), new IsoLanguage("nl", "", "nld", "Dutch", Language.Dutch), new IsoLanguage("ja", "", "jpn", "Japanese", Language.Japanese), new IsoLanguage("is", "", "isl", "Icelandic", Language.Icelandic), new IsoLanguage("zh", "cn", "zho", "Chinese", Language.Chinese), + new IsoLanguage("zh", "tw", "zho", "Chinese (Taiwan)", Language.Chinese), + new IsoLanguage("zh", "hk", "zho", "Chinese (Hong Kong)", Language.Chinese), new IsoLanguage("ru", "", "rus", "Russian", Language.Russian), new IsoLanguage("pl", "", "pol", "Polish", Language.Polish), new IsoLanguage("vi", "", "vie", "Vietnamese", Language.Vietnamese), diff --git a/src/Radarr.Api.V3/Config/MediaManagementConfigResource.cs b/src/Radarr.Api.V3/Config/MediaManagementConfigResource.cs index 37db584089..659f327151 100644 --- a/src/Radarr.Api.V3/Config/MediaManagementConfigResource.cs +++ b/src/Radarr.Api.V3/Config/MediaManagementConfigResource.cs @@ -30,6 +30,9 @@ public class MediaManagementConfigResource : RestResource public bool ImportExtraFiles { get; set; } public string ExtraFileExtensions { get; set; } public bool EnableMediaInfo { get; set; } + public bool FetchRegionalTranslations { get; set; } + public string RegionalTranslationVariants { get; set; } + public int RegionalTranslationRateLimit { get; set; } } public static class MediaManagementConfigResourceMapper @@ -59,7 +62,10 @@ public static MediaManagementConfigResource ToResource(IConfigService model) ScriptImportPath = model.ScriptImportPath, ImportExtraFiles = model.ImportExtraFiles, ExtraFileExtensions = model.ExtraFileExtensions, - EnableMediaInfo = model.EnableMediaInfo + EnableMediaInfo = model.EnableMediaInfo, + FetchRegionalTranslations = model.FetchRegionalTranslations, + RegionalTranslationVariants = model.RegionalTranslationVariants, + RegionalTranslationRateLimit = model.RegionalTranslationRateLimit }; } }