From c2baec5ebcc483690998ca27b91b49024a044b7d Mon Sep 17 00:00:00 2001 From: Christopher Serr Date: Thu, 5 Feb 2026 19:58:53 +0100 Subject: [PATCH] Implement Localization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements localization throughout `livesplit-core`. The following languages are supported: - English / English / en - Dutch / Nederlands / nl - French / Français / fr - German / Deutsch / de - Italian / Italiano / it - Portuguese / Português / pt - Polish / Polski / pl - Russian / Русский / ru - Spanish / Español / es - Brazilian Portuguese / Português (Brasil) / pt-BR - Chinese (Simplified) / 简体中文 / zh-Hans - Chinese (Traditional) / 繁體中文 / zh-Hant - Japanese / 日本語 / ja - Korean / 한국어 / ko The main thing that is not localized are the comparison names, which may be a little problematic as we match them by value in various places. Changelog (en): LiveSplit One is now available in multiple languages! You can change the language in the settings. Changelog (de): LiveSplit One ist jetzt in mehreren Sprachen verfügbar! Du kannst die Sprache in den Einstellungen ändern. Changelog (es): ¡LiveSplit One ya está disponible en varios idiomas! Puedes cambiar el idioma en la configuración. Changelog (fr): LiveSplit One est désormais disponible en plusieurs langues ! Vous pouvez changer la langue dans les paramètres. Changelog (it): LiveSplit One è ora disponibile in più lingue! Puoi cambiare la lingua nelle impostazioni. Changelog (ja): LiveSplit Oneは複数の言語で利用可能になりました! 設定で言語を変更できます。 Changelog (ko): LiveSplit One이 여러 언어로 제공됩니다! 설정에서 언어를 변경할 수 있습니다. Changelog (nl): LiveSplit One is nu beschikbaar in meerdere talen! Je kunt de taal wijzigen in de instellingen. Changelog (pl): LiveSplit One jest teraz dostępny w wielu językach! Możesz zmienić język w ustawieniach. Changelog (pt): LiveSplit One agora está disponível em vários idiomas! Você pode alterar o idioma nas configurações. Changelog (ru): LiveSplit One теперь доступен на нескольких языках! Вы можете изменить язык в настройках. Changelog (pt-BR): LiveSplit One agora está disponível em vários idiomas! Você pode alterar o idioma nas configurações. Changelog (zh-Hans): LiveSplit One现已支持多种语言! 您可以在设置中更改语言。 Changelog (zh-Hant): LiveSplit One現已支援多種語言! 您可以在設定中更改語言。 --- README.md | 18 +- livesplit-core | 2 +- package-lock.json | 8 +- package.json | 2 +- src/css/timer.woff | Bin 33904 -> 33924 bytes src/index.tsx | 13 +- src/localization/chinese-simplified.ts | 310 ++++++++++ src/localization/chinese-traditional.ts | 107 ++++ src/localization/dutch.ts | 310 ++++++++++ src/localization/english.ts | 310 ++++++++++ src/localization/french.ts | 310 ++++++++++ src/localization/german.ts | 310 ++++++++++ src/localization/index.ts | 403 +++++++++++++ src/localization/italian.ts | 310 ++++++++++ src/localization/japanese.ts | 310 ++++++++++ src/localization/korean.ts | 310 ++++++++++ src/localization/polish.ts | 310 ++++++++++ src/localization/portuguese-brazil.ts | 310 ++++++++++ src/localization/portuguese.ts | 310 ++++++++++ src/localization/russian.ts | 310 ++++++++++ src/localization/spanish.ts | 310 ++++++++++ src/platform/Hotkeys.ts | 9 +- src/storage/index.ts | 25 +- src/type-definitions/webpack-globals.d.ts | 1 + src/ui/LiveSplit.tsx | 176 ++++-- src/ui/components/ContextMenu.tsx | 4 + src/ui/components/Leaderboard.tsx | 97 ++- src/ui/components/Settings/Accuracy.tsx | 22 +- src/ui/components/Settings/Alignment.tsx | 18 +- src/ui/components/Settings/Column.tsx | 75 ++- src/ui/components/Settings/DigitsFormat.tsx | 5 +- src/ui/components/Settings/Font.tsx | 25 +- src/ui/components/Settings/Gradient.tsx | 67 ++- src/ui/components/Settings/HotkeyButton.tsx | 17 +- .../components/Settings/LayoutBackground.tsx | 33 +- .../components/Settings/LayoutDirection.tsx | 14 +- .../Settings/ServerConnectionButton.tsx | 26 +- src/ui/components/Settings/String.tsx | 19 +- src/ui/components/Settings/TimingMethod.tsx | 15 +- src/ui/components/Settings/index.tsx | 68 ++- src/ui/views/About.tsx | 87 ++- src/ui/views/LayoutEditor.tsx | 240 ++++---- src/ui/views/LayoutView.tsx | 24 +- src/ui/views/MainSettings.tsx | 188 ++++-- src/ui/views/RunEditor.tsx | 564 +++++++++++------- src/ui/views/SplitsSelection.tsx | 126 ++-- src/ui/views/TimerView.tsx | 67 ++- src/util/LSOCommandSink.ts | 32 +- src/util/OptionUtil.tsx | 45 +- src/util/TimeUtil.ts | 11 +- tsconfig.json | 7 +- webpack.config.js | 49 +- 52 files changed, 6038 insertions(+), 701 deletions(-) create mode 100644 src/localization/chinese-simplified.ts create mode 100644 src/localization/chinese-traditional.ts create mode 100644 src/localization/dutch.ts create mode 100644 src/localization/english.ts create mode 100644 src/localization/french.ts create mode 100644 src/localization/german.ts create mode 100644 src/localization/index.ts create mode 100644 src/localization/italian.ts create mode 100644 src/localization/japanese.ts create mode 100644 src/localization/korean.ts create mode 100644 src/localization/polish.ts create mode 100644 src/localization/portuguese-brazil.ts create mode 100644 src/localization/portuguese.ts create mode 100644 src/localization/russian.ts create mode 100644 src/localization/spanish.ts diff --git a/README.md b/README.md index 01dd25b3b..91ce00822 100644 --- a/README.md +++ b/README.md @@ -59,14 +59,14 @@ npm run serve | Browser | Compatibility | Known Issues | | ----------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Chrome | ≥112 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Chromium.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3A"Chromium") | -| Firefox | ≥121 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Firefox.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3AFirefox) | -| Edge | ≥112 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Chromium.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3A"Chromium") | -| Safari | ≥18.2 | | -| Opera | ≥98 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Chromium.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3A"Chromium") | -| iOS | ≥18.2 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/iOS.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3AiOS) | -| Android WebView | ≥112 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Android.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3AAndroid) | -| Chrome Android | ≥112 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Android.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3AAndroid) | -| Firefox Android | ≥121 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Android.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3AAndroid) | +| Chrome | ≥122 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Chromium.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3A"Chromium") | +| Firefox | ≥131 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Firefox.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3AFirefox) | +| Edge | ≥122 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Chromium.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3A"Chromium") | +| Safari | ≥18.4 | | +| Opera | ≥108 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Chromium.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3A"Chromium") | +| iOS | ≥18.4 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/iOS.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3AiOS) | +| Android WebView | ≥122 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Android.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3AAndroid) | +| Chrome Android | ≥122 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Android.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3AAndroid) | +| Firefox Android | ≥131 | [![GitHub issues by-label](https://img.shields.io/github/issues/LiveSplit/LiveSplitOne/Android.svg)](https://github.com/LiveSplit/LiveSplitOne/issues?q=is%3Aissue+is%3Aopen+label%3AAndroid) | | Internet Explorer | Unsupported | | | Opera Mini | Unsupported | | diff --git a/livesplit-core b/livesplit-core index 6b840f0d6..856bf312c 160000 --- a/livesplit-core +++ b/livesplit-core @@ -1 +1 @@ -Subproject commit 6b840f0d647b8e2d1175143030fd3477c9f2768b +Subproject commit 856bf312c59c05ba777acc5e58727eb05514c6b9 diff --git a/package-lock.json b/package-lock.json index 413a7ae92..b981b0fb4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "sass-loader": "^16.0.4", "style-loader": "^4.0.0", "ts-loader": "^9.4.2", - "typescript": "^5.7.3", + "typescript": "^5.9.3", "typescript-eslint": "^8.24.0", "webpack": "^5.91.0", "webpack-cli": "^6.0.1", @@ -10922,9 +10922,9 @@ } }, "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 6e82e7d5f..ecd57ccf1 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "sass-loader": "^16.0.4", "style-loader": "^4.0.0", "ts-loader": "^9.4.2", - "typescript": "^5.7.3", + "typescript": "^5.9.3", "typescript-eslint": "^8.24.0", "webpack": "^5.91.0", "webpack-cli": "^6.0.1", diff --git a/src/css/timer.woff b/src/css/timer.woff index 5ca4f422c622a606c5e451f776eb01529a7b3777..aa1899424b0e7bedba53cac2e7fa79d0202b475d 100644 GIT binary patch delta 24662 zcmafaQ;;S;^ySx{>7KT2+qP}n)3))oJ#E{zZQHhObASJ>ec0NUP1UJXPEK-fQprP7 z_uhtq28DwH-Q>l@03d+>N>C60>Awnu+yDRq7X3fW|69bwRAm3t{r!)}`5&acFT9D1 zh>8IKp6>s(+5ZC{q~tF-aRqs00KiuR0Dy!A0RA*n3Ste4E2|3qr>g}3z={9>sKrg3 z6D@gV`Zyp0(B9a_&>jGQ0ROM=KM%m=u;(#0ja{7y0020a|K{ZR4@M~8obP7#<~9Jp zFO2`R@c;mfeN=p`rn#Zhe`7uW1K`*H0fM=;hZz8X;An`6?ysq#$$yJW z{7=L7KfrzDPX7BJ2>>L(fnXw*{%2R>FvNzz+Rpet4$eM-1B6^K^*`k|002raDtGpdrvF)nt^7|H@*m>Z0?aP|_ilomKK=b9=T684K>

(Q zOAir9^sN4HOPsrz}e&J&Y!RbQL=NRa91w8xGhG7H4V&A$Rn|qLU?%T1OE4^Dn*W zyluLdGQ1!`M?^#nA$M33=Ved4r!y9;xCd;RJu?Vh*-?aPf22^x z$s9kQfusP20%(BkD~(Gw*tea|LO?Hn2zPTjXX`=N@`v5mk`<5IZO(UezO6t8#GEtZCJ&? z%my44KmJ=M6?GTQ$nUx_>VutGt6hcx3FWo2ZOmo6nY&cHVN&3{KFtMm0qV?qM}A)If}dCK?(zBY>y` zjZo62K&P~C4U8xaj@XA#ERawMD;9)+Xlg`>9TlZ)ETXmPTNi?<@`F#0eLW7GOMMpb z2F|hnqfdW!%i$!qG|J~rYx;ERsXu?S^A524tGx9xUG(| zu3y8Ul5#m2`7jYukAWr((nFBP-E#Bj4yXxqpT^XVvNW{}${$}ckyZ9bvj~=In$zfB zmfw~zew+Vbo0>nGz(0h4Qh&Gl96xP7rLUtgrhJVo8q^2@FAz$0A&ks)Qr{wV>vQRN z*j?AD_*l$xrL7)gZ3nZhitLz^`^xxOc`<)!dc-A(>dr?XRu9#;@EcqnEFKIA0(t^( zXm50v7ScB_%1+n*?EF0IHpmX{+)@1Cztn|=((qev$qga@l&=YCrtUyHn8(L&+h^`Z zL@0}ZgiY5KN=q$U^<qMlDc%vbh=ULRJlG2!BPH6T?U7vv90Zo!9o7NLO z2NP)xVXY{S7?+lGugfI4E_~q3+_fJ&2FNw1 z+36{Sl8tvxJ#^-IPT19FNx}ywF7l|Xp_B-tx0VXXTB;SuktM0%YO7RXvEH)XWGwI* zpm&tz#ydXO?QA!t2;&?R@UQ1^My9anGOG-#O)blye*b<^+Qe`8hJu4fF`nx6QeYof zyZw!wnVrH94Wgf$nm~Y#0S3Zz+rW*U0tPIi>kKtMbAOJ#3m_rVE{bAVqQ?X?-fw2W z9P1n-ar`-)W&rIRYXGsq3L&^Jl!wX$oY_OkMv>>zPjZQZlQl^c-(Ha&@tDXI+xtGp_)UawNPubv+QF)qy;- zbX&zN{Uw@VJV!oLdSC{fWDTk!7!CPJ+~F%D&^>4&yRd=)P#t)XuA}~Ja>NOUqg%hG zJc&9Z!Oc<(mY8#NqkaUPWoI4y~#2go3a74jUnApEob$uDnF~O z=mqYT?oB`}@tCbMyIht^CjsZ%8t||%fn5zLGeH-8^O1McO_d$aVASZo6!vPm4&fMF z%I)MZlI+lt$-$VGc=J}|SYF)#@RT(};Z1E{Q#>eVXL486!q=CR8;4(={UWxuB7KL* zbLXV;2G{=E1!t|jwzbjW!5=ImMdi;x4xgIln+EF4zCM3gws7EW+5`FB5O5#WwCU7B z#T|0#a*+0QHp9HQHKy5)ODR5#xjYgYs3`jgvGKxnd!)L1=RORHH2|5B@-H6N6J6EC zAS!|)?O-N-{&elC2>Wi5Z<&w< zaeMVm~E_EDatt6uGVrDH070dx)PXKYOH0l46z z4rb*ywVBUcXM3oPC-`*LX7ko&_xX`R#z`hF`4zI3^eN49mxAyHpX^PwBB9ki*yZ@X zw~)JBwT^xKu_c<_(QtsY;XYU+dDz!Oh+Z-590a_Kw&v9wc+YG~&Q58>b3i@@25tL~ zgpbl?#gB&F2K6}f0tcY(Q|~ZxoJa zkZ~d1qO*KQ0Ke=x7X*PMX}FgR#!8*UW2T%kVgj$@OMJykCPM%6lUOef9_u{uhU|}O zeKu|}z27{XfJC|(c+1NW#^i`{#5Bp#e*~$)Hi9^Y!fsfwXkWv87_!+TZBf#WU}MLX zX@@neWmvUot&f#-Drg?Gmrcb8n)QP@`M|kep^q`Jq_megu5n`riA}BF#!iRPJZ69( z&-Sq1^ugC{ph=Yv3yST~QVs|LWz+yA&|ajwq|`!YprqJmj3HCzGYQyw2v;vfGJD`e z>qdrgO9TGa0jC^!<96#LO#P40rKT_Tqy_w?3zw37@Tgo3s3R|IX;_@OMDs|#o@ot) zZBvOX-f}~jHX%q29r$_{ppiT5FG>~-!meO*c;+Hm`7r*TW9|aZYY%qHK}>s%PM>y- zj;x3-@Y3fH`39yH^xwye{_`UOCBeocEWiqLi28^DgNYeHMbr$_Y5u@F8r^fpLms%U z`ZI|9bRh`memk@4MijiLt?$$b*}{ObJkT!Wx71%)-lYR^$|0DNAU`Gj`>2Sz_o0TD zNM&Yhz zXpN0P6<3J}I0BQ>d#~O9zQZFxagV zpvMII`|iks!0_}N6n*0sD%zv_)1{STt8g;o%Ydg{0oTk3F&`&!Ml-ShK3u}k-atfD zXB`AirKh`K4?ou9H1X{hc$#gQm$^DgWSTo@ko8T7-HXnMijen4XP82zIeK>#zld>M zuWZU_hn3aFF6vPaI|{Egp=0PMcJR|YkOJR6!#IT4IQ@5qF-{6{)T*_V@bDgEslCB~pU(mjAiVS@aK1d7+!Yu zcn9-m_C?Pz>m?@t5%2~mwf{R5^NKEw<9SV2<%ktzL}6B{oW6P z(puMLvC1o;3R$7tjqDPvVpLgBucAKOU-C7Hp;s4a7^xbSDRvBRV*}f2rK!Xdcbi;L zv9Y$qpm*$)RuoUQ&%Nhyj2MUm>^r$raDi5k_p1WCL!YR=168%Bm#W)_sORCe3qL7O zLeIW(w9fzilR>@w^lI@Bi|;nG`t&dkZiG071E+O*Z}!RWV9`s}6T+n8+eQ(yesZ4O1&!&E@ zG%nhjjA27G?Zo)i5(9Nt9?l)g)|bb?p`L`&A2TTVVa9>8-B?9D5In49td8X|M}HNn zDOEhX8C!ebdE^qKLjlwXsHz zgad!0@x#~~b1mAL-{dg#Um1V{^ z27Ne_dp%Ad2Ao0i!j8m_R#^d0oFbYGq(on4qfWqc?>qYfZ>+U6eol#DVWm^< z|L}QYZQeIi#WK+Q!SOS$SXp=USS+oJF<~2J2edI6+OS0A1#x~|#2*z1W}7GvWV!BX z_SL`PGvJN$+)bImbT+B)=tvL7+`JjLDoC&(+(?xdGOMY1Ay~4xLnUSB zu;axEyWL+YZk82uSQg=s(`lNYXXyOVS@s)x@-TSvy|XcG74 zi2OZYD1m}&3dHh}xM6Z`c1<_Z%N3^X2yNqFi`k8D^9ylT_4V(^fTu6UclmSOh~)*I zSK_Rx;KR=w&~(_ic<||&aG~O+LKi~%T1b<6g4Aw3L_Nndz?!_$i>z__xgiqIgV#4NbL$<0HqeIogcxNA(NB=>u@4%x>aIPx;jGz?PE^M7~no z4eyd_A4M@IsnszIPh&K&p+{3&yW^SeGkFng^&;*SIJM|RN7s)po!B(W5!@Qyfj^8X zb0&bg!w_4F!vg|R9KKsQ^3QZfjff0*6-U=af4g98txEkFxV=Q{AqAhsGWZlB0d(VS z(MZ-!@(bkZ^EBsjG+@cK60zoGBWb?;(8^BqgJ+{~Z{*4`*apaNO*~gv3)* z0BK|ZJW#Ed0m7m=!XD>-i}=SlIL=x1?%ft_P%G-?wj+2eZ`JtoiB&w4u$#yWvH!Z{ z?F~;I(RTGdzjR76V)%>_SrbO?)GuR?0pC==tghNV zD1haWIF7l{7QM!J;pWwUiOjr<|>0j#YJVx+xvx;gBqhAdB1ax z_u>1%k?6t~(&jRf%jYq^-j*f2GGKL|cc)b><7kmiXl~{wUqocWhNwtSyRsmB;$RMA zpYS3QnVavI)uz}=rq}7wnhzY`?-7^7`FEX$#tI#TKa zjSt#v4He=TiTN#tafDKK$nF`JxT)F(k_WF%3NV{CgF{ETYYm{H+Inu7+|Y(e5b68+ z#sq0aKMzm*B&WvaNPET&WS=T>NLngLVD|lux`Crz7S48Y2P=tRIC+?!FICfz@U2{q-!|iN(g-vS#H;K5$`dk z!7!=2k6TP6(S^t>l2MqPy%&Mi-+vLl@dd+#OXfPvDxStsK{TgY0ms;pDYp{_-R?V> z7?)O^z$DvlF4pA__=DPtv}E&JCQMWFe**@jT~L>!!RM`k_e{SoxdE;~-YC&aE2L9Z z%pefrjFpVu;SYquYt6ABxjh~N*U&*+&kfuD{Ks;VE@SpQX#u8snr;Z|EwWk{=C5ZL z=-FQg+!|=NMEZ*FiM|320R7%b9(K1564S)gaqzrJm3TtQ5-RO~qIJVY##W@P110-X zecm+$%PqMjO;^D#o}Y=<;4l0ypL#k3RwL1=8QQ5LMTLrD%0TiJ=6+E7YFt zb?jA#z&}F7mL@t$QwjyX70{ef^^|X4qba~$LSSjmyrIC&A9e+dyOM$;66EnDfNV@; zf}SH50-NN(%;T5Q-?)^UVjqTU(>+|7N$W25kg@bv#Me(QW#*lJPE08w1CY|{z2iTM z&gTy~!u{6kyYr5_u_iz;jcGYk9v#ET!)b0Wy|&FCrjH|uPjyUJ=tqB(6Y{iEVP#cy zSS}=48}=-(iJSp~14;fF!Tu4`ECAD5-K^EX(q=tQ+ve}h1{H%YvS*R2LNIwQ>~7+?plmPA%u2@$Q! z3DxNin~BJf&R~@_bD|lP;snmdc3DMl*~w=bkEL&qvdh!UW*tjGuCHsMwK#@mTvu!j6I4+%po{Tc}S7o-pXPYLz-h-fY2DzWT@K8(6@Wb~EYVS}= za*x@Su4GfWNT5c;l}QHV!2MS36^@00e?;FESDXV9)R)jg=8qX~U6#btS4!nP{e!#F zCQ&q~5AtM}*lrP|mW}^=`BT-+^&Qn6hbin72_DEtV>Wb>{_r5yn$=BPEXm!j($^Q^ z@n$Sucjoy$>4D5=p9`a(Y1=Y`$h32lI>+MlkUhmblcDfwCGnH=H}tC7>+?Ax;*562 zPKOD&<)p5?Ql>3aT6NK&J!!r56kPLdv(zOyz)mV{r8u{^d4}1NY-c6*DeMJ@i!RQS zL4n#@vgKrDHhfq<^}~7={a6m#QLr05d44xwXwG+((I)SbWzaHGaplTq(D$P*Eh{Sx zt0j{2dVH>3{8{g5xksO9?ikJeEBq4(I)x2P&0}#D2Ti=4;C`62kn7SE*Ii&~%G!%x z2=Ie%+i(Eg4zZktU>T?oPx^U<+V)7JZCZuCIQ}-=5N4L5O};B0BuVLLT%_I1M2Qqp z`8Sf zD!@LFwy;^##wM1VjDpy6=&EpTBq9K$h_qPCm)DpvhdW-easDUL06g zw~Q{b5CB1@-NC@|43@B3^^`X$eia1_ZKGEhe|7n2WActn zc7c`Ps~TrfhdD&J_eV&-T3^3(L+}~ij@;`ktHRp&3=3wSf6YutcrK-Q>*5(muOo3O z?n}NJb7goN*mbJ=`}ShJ$o9AIFT0pSthS|gc2xYtb2K4Wt{n%IUu=&aH`Tgb9doGx zzmcJb_R`G+GCi`xKhu=ym7AD z2~H2>4fPmuLUfMcUl04k0r%}Ux6kAw9U(FDviSPTxfiL7oGs<~dA0Vsf}Y#Ai<_H_ zl9HrN495?fOmed}raIj`l%f;I9Z%3$f7&7v(RD36tX=lD63UOa_1SN`udz+#`TR4Pta&2sl@0);wB@c-18%t<+h`OoIeku6VT=e;VJ4}B|* zjR<6%n@}Iqt!;m>PVa^cRDk;>k#zdmlYCl(4f+4^Bpl2x4*BnCZoZT)w#fl;q?)em1t3CDrtGYfx0wL@%X3WB_P zIT(zzf^uD%+`rIKQ}u!$Ht}dqrr&_?t2fmB=eb=F%yh%$F_oR`!mgXKdWE%g72b5i^R4jC?H%(2EuK2|5e z%?$D77Recy2^%X;$ElSL%@I@?nTh{M7EDsfpygCDS`971qh8q7g?Wrt@WtX|Vw^t> z8(8Z~M8Zl2KS|3#To#%jG%0OAPV)9hiVZF*LLdeM3=F-5Z=z}qDxEb6FJ{iInn@Mu z&*y&>85U=L4QCoEK8*L4g_3s7`elc_+E$rR_{%ciLWoc7YM?$I@R7mpN_ZQ); zTVGMPA-~BBB0>^{MsnaFco2VH*udz+FWH$k7hjj;gUMjx^+e4SXADy~msCl$otw7_t5ejj+t)hq(kP3r>SWB*Akuj z#85F?{w0fRd@NwDzFr|%e!G`gW5tkCD};#1^pe2Fm!mqV5|xWSjxkMTyS2b9a7rN@ zh^CIs=1jUzY4)ZOHJ zYWY}?Ze8wDt)Z3=Cz_%A>MIM9ga%YPCBx))s8Yolp{AK2NA2q4fvx#XT%x<0c4cJRig$cncL^xVWh>*gfB%gIY2m4KKO`gmS;-sSkRus z9;$JzF_kn-`n&qxubJoYxJ;dO9?RF8FyqkshtR7j(canKqv01h%Rfw((oMtwtH+!X z8)m1)mCcwNnHKw#Ryn5T_tCSBKRAz7H#=Ec(^MM+N)_h6tkEJh8BN|?jM z9zX4fj$6azXvZuAmFuDGJ;VEdId*nwC47Vat&ZhG#`JwwS#{!8=JIQH0ajOj^-Y%1{^I z7$p<&A$d>DfQNyH9lv*m0q&u_nPSM|sPJVo#E~1bq^&HImve)qEiIE5cg2YXkZmt{ zFfjFh)lItTpp%cVC;kyjH{yq&EQ@rEhT2##teccZ;Nr6B_ZB?8MA;n!F0Z8#Od^9f zHwrgSHEnQniPmY7{7_6I56QW+%cGoTcjji~5}TuyE!Nj-O2{#dbxOJw$q+)|-X>=* z&NK50iVP;^Qp=08WpCAH(bVL*205%A#T}QEH^-~4B$r?yS4TIxr{f8s*8Sd6pH04| zp15mf(X}M@HKyka0-EIj>GBcj+4DDh2-wfje2I!ZJ=?WbjjdzcE_#0I?Sk3UQhdnM z;Uzr&ij?9a5^^JKRV$HgCdR4=CMlIgWU^pz*~Q`_8tPr2SQ76Wt#P91a zhF;mb8)8(ccY9PnpYbw3Zj9@7ohP;RJ=)_7$rE_gF)|L@q7DDTh604Cp%O((U*)M6 z0+}VnS}l%X*$t0?8LvEidcXCAj~3)@-v>0@8K0Rft8Kh{=ZNzb>E#L3xxI!P56+Z< zN$rK)*HzSx&XP5WpN%FV=2RGtc9}e0_BZK2U?0>cWj5fQ#S8@j2cYfW4d1iPq`6e# z{henIhL^>EDg8cmNW~barKk)zcm%n(_<0C|k}*Pke39pXxqm%W+{?c{@Ojx80SUb( zNYvuYAq)t+nL?EoJ!8vRyUMjNCmGh4%8Ge9h$!;zu7FlA^itN)w9A&^(sUV(>^(ci6kbb{09 zx_ldVcMJfx8N_%wk3z5PIDANamdOwBq20#&HbecN-#9ru|Oz1z}*in+bFZ?Xv_dyZ4$^c{X4-!x2!TmX-V-myqTn;4XJAp*7+ z0Ra`V%)?0r((1@ZD1(Nc=Zfesc1`bD0{BR2t4KN0}XrmG;@68G9pOEAk=GRmBBw@fKFO^yA`o3G-L*8*` z@fCXEa{Q0AxBvVvG^5S-ZUzC3FRtWnNItPE0)t=Ckc7k6Q80}V=j)rYciSm2Q@@zI zuTZgks^ILGAtbOz654JDg(5Ev(wk4++ZnQuLG^wW&&A7w8iA}8 z*;Gx9IJD~7Ik~FI!vV)A(V{VU(Mi?gLmkuLY9%2a)~iWV(s|Gj;!)wmlDJ`<+}&-e ztEl5!k0q2UUV3$h1SC@s>A5n_suqTnbq(6pZB=X!0qU-^_1QaUYrgG&&dDesmAIB5 zk@$0dBvEB{g(AZX;xc@0$@ubTL#WHA(_g{9ayajlWcootuNUATHYtAB)7P+ZWf9hns> zizF<1Xi}sr6f%E#ExW-Q7A1>x)m7$d&cj>9X&mItHI-^edUk6{Nzs?e$EWAqEQOl! zzS=iPqMrN?H3!5YH}98KYizffaP+bnb_?@+hbORK3o#e$TLYt^o106+j6d{7k{Yvl zgH5!GkO<|9r=VozRiu0=nk%I;Fm;Eb!dpz}wKe9(LkWNRT(-%4Oihl;PeuEP8Yr8~ z*<~=UhURVGXfBG~bSYZT1Vr61E1tYOsELCI!+ zGbEVuSs@)PR}wB&noqHxzYoBlfy5$%bo(ki)yMCg@t+aCWgX-jR@46Cm|3TIJvhWe zmXZVCt9(?r^_vo@Qj_JTT=s?<88nePZN_AMXFnq^>+?`+NJCzEndr7^_e#X_OltgH zmM^cym;uyUx9>?5@^*mo654BSB^B#Xzi}EHn79DzEG}>O`621)hisg`j*%=a7YH;$ zlJd_{lL2jXQIs$Ti83VCn9sV4uNe?vJGF8?XyhW>J564em`}$p3D`%>ds9`@UkNXL zQ`PP@xvK`>FpW_YOE9YZTgYTF$OiT-#UIzU2M2`eSll~3=O-&!rQQw+%i~Z>l25`S zQ7#~LvB^Wal1V(ItSY3GLrrmpl%72mRCZ0s3{v2{r7&qcB{q8APisuk3hDV~mY5U2 zu2fT^#Kux>6(|_e5<@+G_5n@t{CO;nxZPw;w&*Wv%n_x!`atM33uOHTd4xhBfCdilE-Sp4(zKKK@uc zz61=9>)1R0(EXTnSQUTWTAsYMb*G{NM_nxEehb2 z-Cp`o%j{P2CPwI#O>-Q!aVS!M*@v-KjUF7heJ2$o)^^?utb|~X#Z{OYrdiin<^h)F z=j~ko%Qlr|jt1skb5`ss0V6Q`O%}Faz*FAx^`;?z6kloRtG+M*X*zR$uJ9-&Pwr{^P!-Z zMT#*6Z0P?+dFVj6tJ_xvm|eAYB?Sm`;NIPU2CNuJ%FF{zni6C`!D zDs`XY-1EJl{&t4EbaG3p9AK%iKE+fjkM<~IX2D3G?S+Gmr@ZY%BhPH|*o(J@9{(<3 zr!4Yp^ftHNS#bKAKKtUUK_6-tdpVxS@)be-_1~~n(xn9~l5&k=B!f6FG1KQ2Rw|J& zu?s@h4SF78mxOz^pm7mAEf=*IZcOySrMWQk-E33m0we5pY(f8cVpXEJzz0xHB#fdrUvFg=u-FCRXAl0$ zpMYtw_pn}W=r<047%&3fKN}mQy*S7+D+?}^eM-#f{pk(7Z&HSX{c6t~`|Zn@Jxr=R_1Rjc(lNNbq?QsfwtKKiV!h zJl2)G0OtB{SS#=-!|cY?yB~Ps=Zby29c16ehJBpkHM><=@7cJ5L&L@5HBSk-H#i<5 zv2|wa911{O_43!!)55brA>wG_cU91U;O-DjzzQG^1+JU&Q>Dkwc(W3xej$vQYxPZ1 zYpEa|BGX5TP=+z?TS}2@LMO$But$W;$s~QUOu=n2B3*MzdF8gGC9H}V$BSZJN9ZTu zR;>Kpu)%RWej`5GK7e9u=<_9HVV)OfgiOF$LkO?gjb81W9o6?8 z$cO4E1m4GK{F4hQ?z_P!KOXgYik!3A>&#a~My-u!rM7C-4|MdxN!&OLLzSo>!>)Uj zAQqQkH4nle+^IxnZE!rqBrZ94wF)=U7dX?$;>eLw%TcvJGxU*BViIJE8yORVc3_D`y3}xG49w>Zf!UXZr&1TTLRoX?R9uo+in8j715tLIfwUp;U4jL1*^syQ6AP;Ub9<)eBJM+GZk{<*?zRKdO{TUsPg_fuZz#FSx(2@zL;7AkvEAeH3n zhyQjhLhM#H5dO6qLhV{!`i+L2uPcklDEAC* zN^>nUOQ)DdLmLzH6}9IaYQl9l*C-&*(l}iMDYj`{lIe!9+d?P|m)ea_kraw!x3}sa z=jk^Mp|n(-MbB9KJh`>Sw(z}*p&hH*Qv)1_kHc+sCOC{q{qTPt)1_bsepF!)_5MNB zN@^3Lm#o{lw$go0z?pBS;XR#B{N*$Gsa_WQ4dlppj={rD#Ud!5ru=Ou7m@^O)Vyu{`JNjfCyx=t^Fyv3 zz=0g%x8Gw7eJQv5obBZTz+0K0Z^&Wz_E14%ZEcdWp_cU6ugXNdq+26}^NL+jQv<;$ zG2PDbga{4v9!0*}-Qr->eCkltIO^E}#}P2h`Y%&)_=2?ZO5;GFn31zWK)EYlW9PI{ z5u85ft4o=DAo0qc{yh1-^P)>R&XUJp?O*9^sqhhXCU)9Lc%<#J4$Dpnz-cmqi(qtMX& zl7|02u*-ahx(Y9WNr^p1@`-8?-7cj$gm4vsH{h z3W&Yd?-1jj!pGT-%*%M1l@U8+{uFM2_i1wWvPp-79R|Nf6V{3zu(=2VD)^38&oB7e z4_a#;{`STQCoCC=<+2V&4JS3K2h^NUTK$>=iGb-KxIDcEE(i2qnnqHc^S`p4rq?>X zIxiPG{=6M!LZf4O&|Xe6n6XVtUQ4x7N+mZucm1~ZsPeXK*F1O!Um81m_c9Mz86S0v zQpDxtGpZT~RO1O-XyL}a;qspg)yJBJ%shMXV)n}4*yT2B_1ubgEc^H3pLU%xbF=~B zF6%>QsWQKT)&IRJ&=C{yvexZG*|8*_4${;h#~7`jeWs#`2~QVox%111;;u-p@EG=r zD6Lb};5nPggk0n#kW+7wQ04lZMtiG2_j#d_%MCva<3X&WNhxeQd|F-00en*BY16C1_yvbq(l`nDhU7 zBx3!S`!(?*^3bSOl_ZAgafMybiwps~m9962B3lXG5!2D{Ana(P-Fnfk{?}Wxo15p* zh;{w|nBf|PW@=in`6NJ-$#YFj*vDdPX}C@-hJrYu-ZJZ5J+#ONP-E zIj!)&>bnFxQpoNTqZc~#Hww04RzoB&2!hn5E|@aQdeARN;^9B65ewbP4LZWnchw?Q zW6*G@Ah@5hUhLLYp4E4*8r35cmER50QVk)2mqxc0w>Vv17-4C|>_a%OAE1EGtPjBK~+1$1Pl<-G#!%xaXdRZa8iu`O`@cJ{%y zTBGQXH>Ezwl|&-45Ru&HpMr+cMl-1$NK?jW0DIu`lC*4O#Ox`Wj0JvZ9AD2#OiAK9 zwMAjWaMAZxt@JMV6feCNEW&D7b(eU+A6nEh(%4bAEQAQTM&+k+Woh+Cb2e` z4>{Hk{nrtVbR4TQnsZ$Gf%;Qg?#o^#&jsoZA4%e7Ui{x5pPB{~Ecv$2n^K#~3z6lH z@HJ=O=M~qip-y+v+gK(#;q?mKwuK*eJx=Cu=iK1U=jsgbV~pd(jF$OE2}wB2>IAN` zh2h+xKwi|Y_2u9gWJSRcV#FV)@dkxTzN0D08C%iNuls;s@H`doz#nm+t+W)7=$|~_ zHu{wHoQtyL34#QEMf23cgtSAiJr#?rdX^AQllI)F4FUASO_2r#?QU2GUQIav1#DOr z=>~P&2?5q#Yb0Il4Xoc0wa$jiw z|D+}PVvgn}i;FZi@1c%@@^a+8l(5c%PD!T?;Ywg(o$a+UKiGQ}LGaCL_k6cUyV$zA z3CTgvjsucZGt~>v@d5&KlNd!^5j12hO}kMEvTR6RwPsP~g0@MLGb0jI zOc_g!%U)VV!w!trh-xD`OEj&1@e`VgUc3!n zeSA9VgwXWAgec1?v*vrHK1kRYxtYsu$wdQd6%i&b;@(y>pOo5%jFvqvy^ zNdEzs{iJ%UX2$^wdlO2g4AUc%3Px|4e5e&*A6gi%iZgC=jCQX>vRg>Tk1IC5Sor}` zCgT*JNAc6+lUGYkQ_p!J}#lG-2Hu-vmsm-vY$SHpwaoclk=L*i0 z(AV{kDiHA|B|DReNBl8P?S%A-2eAPP<1$Ki)BayMM|35TJOAYzJt}~fS+WzW*lO+J zR*Do@{;vSUA3NYPtX|W5l+Bh%Y=Fd=fc^&&4?(9HOp0{xL}HYC6a28oYr`50qaV*c zQ5etxLuDHqK*|gx=A#h#|D24>E-L(W?I8Sr2ETH)qqkm>{Q;Y1cqE%feLa6uv_3N$ zHjKXwkt*jTUfV+s_KAZXVM<$6$HVun)PvGc=KROe)V8i&OI0%*NgvU@L+MA(QKrjx z`R*^K@7zjWw|t+Z*_NzyQ{iqxqfryyh>zSvc5E{K7;i*PXw+m{wfWfO$y@jAVT<8m z>rFZdzkoAvI}q6n)QC=?`^bMQ&wRGI8((?pC1mOLu9JC)_PCMhS7ZWczuiU(i05}SaAW>|4E$q9Z5{|794FS{ufK0xaPlBSZwx+-8pJc?nLi>ksV7?&F8`vBKFz6=n!zs7YD2Qm4uF6E85q~0rg438 zivKJ;;LOaUsUVh;az^7ob(#v-yy0AXUwTxoP{v>F?coT&5@zJ9ts!?D`gvUqFFeASBm3s*SNn3ItP%0xd)CjSM#T?)Ap%@YA066AQBcG7oddia z3b)^U-WREzRQPwV-+q5P2Z&%p%{R&t5-teXZ+)de!;OJEQT?Wy6>K&lx74=2OU|DL z-=mB!VWS5n;0vtDSAXoex?uxMNEd+%u4tT;#58+2Y7U7tmNLd_RB0AMF=}EtZ7UJD>R5 zNL&VXY1hb49^bh-0VI^=fNlq_@IHqtj|t)qkV@!xkAW?=Y;&_<+bIf185Vc;o!7_u zV!^(;7tR$#U~WrL_0LF<`@87W-{Z#75Bappys>B_GIn3RN^}9tE31KOr1PFuRLqy4 z;LC3`s}uvv+zNlVtX1j*RFv(KIbZ3=8c&W33Q!zBh3e!=e1eF&OdFcIZX>dL^z~1y zxo5rqCR;p4NJZbczk2Zm(&29a!Dyu%r=jOoJVSd|X?CvC=#3ZoC`t)DMC_%=GSgsB zn{;o3eo6PyJ!v#cLl5R;&@66NM`jWO(J)Z2s}7T1numY4FV^#kr@?gk>9q&5F0yz< zN8u=T{-XL7%kQacZRJ@|N5%M~wx58aVA0|X`~jLYbybVUv+jYJPi;8#H1Tcj0Nl>t zF2lTbx?-ASN{t=r+?Z3x(p&2%BTl*C#LBIyYxbP*UL+T3i#t!@%PV?%^9u&8n0s6C z>|Qoje58MJ<64rKzY+iAf#MBGc3hX9kvif9kbRe6!uMbcw5PrKo?G_Aw%TdMFJfX;cjbHRK6tT%^@{ zC#WDOv{w^x{B(V=w(QU<`}|xDUni*UUiYt9qZNN9n(%>H(sc2ZRcY3~En3;`kFOnpwE=gMU%#vkf zesWRp9e^93KSOsL$-Lo51yAnK>5=dXlih!lL|!3yrSKg)#`}&yi$uV59ZzBp@|ZLy zGpaA6ITgD|vw7)g4FELqF~fkN_P}_6XECfXDQy2kcAI~Y?Dk1<2-)o(I;G~ek_pt? z2zsNhuZRDm50AcLoG@SJNpiG|w|)Dr&y(>X@i^`}e42VPz$#?CZlGBP#&fF2<0yad zoWH7HHap$?S%;&?`H?XJUr#W81U%_LX|`BYgr>&YlnKyoTqKHUAD&L37rjmFMq`>oj0)_luA68!UL5^zhHU%NuP>mdyqi4}P%M2#5CtZX?=PHf!Wg*ge zasbYFO*n($^CQ(S;7D)Q7PZb{GX;uuzd@jJxsbPDQ~}^Xc0M zaS71g8*{<>+K0w8p*=ulVy()#R+4Aea$z@ zV+QCyG*N+aLJ1KD3txNZs-wp-qjB{tr;k%BSAKaKxd2fo>)KvGb7g;@_Br6tL>2$L z0&uzm&u-oW=C=%I5B*gJrC?^sP{O0^KTZZ)Vjhg?3amdrS94tYth<9I+}v=eh7UnR zUnqNZhh@}GF+a(D#PbnBRw zF{f!>&*OlLn_x`ROC^8VH>zJp_*Ira&S6EH<2D% zm~0+lun8sMV`zULzkWT6_i@A+{DxUHq1&sc4v&E(g?#y)P7Dym;n#n;^hdH`_Z5fmlvc%zdE^)NLGXCm z&K}mRnDMi8zjZ_M9X>&KWoz7IQ=+~mdwhf{p}=L?5#;Q2w3ok!?WXxMsxGB`5lBW) z20+;@?UUe#{H+=OcB{tUw!+`u=nDE<)WsEXtnO8kkEX;Dl@7OT^Ca3m@K{+XPy5f_ z)kJ@r{L$|e!gu!3?}X*B`Eoz^HThcCDtV>wJ-mlwQFhetq3ot#1$qg}`2G@LJW63q z424n`^bY-g(jE8SM#j1wJ*B+7JsA9;rO>epVeEa%*g;Sw2j>c}4Z!$ygk=UTnPpDE zdQZ~z_BVE0VC7GyLPv=?QTO=ZR8pJs+arD^Zx@lRqmA&RoxzwBfP%Lcdgu>&=-lmOXNbI3EgEG z@T|TbeG$k*1MQ+FfyL)$CIP}o#w);=Dx!3HiXopsDS5DTZNu7tkm={sfsEbNt+!dnInA@#nrUtl{}>&ze! zb9|xasd{d?uDzEW_<_H_r|-Ou*X^Jke@N*0eF~GV5L%j_+Le^8f> z)FcEz&sPEqd8%ZiJeq4n7h>ZVyjf6+id{VK@)ocUOyB(5M9Vshxfox4;RAehk|eFm za9;!&zDub1N%Ka#Wu?XTwr3w2sw;%AuovAFSc*$0i&jmF9t-P*N$jIMp~Ek^uLqY=d!Z-GAoqrmve>w5j` zufRt$jL2~Dq8^b@_0Rh}{GA|=bYO`j$@gr=$GPHMxjLX2xfa0RH#VQ}f4Qh|SMFHf z{nWr{pO)owXFMD3;g;P}`in``bADPjr+QL#Nk*nS*)^sztFSO@%%n-W&EAXXP$^5u z&(m5lt~f1oM)3^z$xNS?`}3)plg4B_OHYo^%$Sf@lTToq0IY5?S9nuueR1ua+p|l@Wsc8^y+vOkWlhN~o2eh*GGU#QVV(1+PLQb7DkCJ1|hHGg#(6<1=>Fkw10q!qcJHP4TUke zV=eiJM&aW9fo>c3fBU`o#K}|m#P!$l4;DL!t%qw?EPZ*!GH&gc$4=mLDCxwT$e4`s z1@UQ1!j1A}H6;99vrLYw9>FdA8U204@8-se$vM7u#IpOHJ6ht8fmZ$;oNcG$l%y{q zF_;QT((nGEOd>h>J@EZk;QL96jhUVdq7Eeo%uNyxC(%NFe>1UA-(pkEX74F(GBH6H zOR;Ra_hhW3Z*+VCGZct6??mY|7z37g_8@z}5)T#u$kvb0N$xEBvTVl&?u_N$lCOtl z_bQjclJ)!nx99|b$EKV^$ldnn--Gmu2h{QZOdag~N}q@^I8fJ)OA?x&q`!>b(5wIke@}>CFfC?)4rmZJIje!II)%{DK=>{EO;oC9?{rJjl&?{rSyr zzOoO!xp~uTFTad!lPfExRF5zCMb*Ud)l+{~IhpF1e|@-x>w&cq4<}HwYz?YariX&0 zMER^>qb17k?VLYZ5X^axjeKv%LVXb_Lmm?28bA34t1e3BF)c`DnQhEzeh}CSNg&lo zH4R~IxtzuZv(P2VSq_s?eAItMf0(|u*`1nij2&{j$giI>eNFS2)B>YEzARB^db}~( zKXR?*f90umi*4~T`aFEmV!XHfKSl&TNm}$U!N*6iIcNE0a&4-?Et7`QI6w(eEBA#Y z)6l?Bxw@Ns>%-9=rxSNI8Hc?!BDV1nr}NWMxYy}Kwe|Fq+WAg)61n;@`%C)Y@1 zN)rECOssjAF!+Q0Msb(Rgvw*AD=kC3D>T)RZ${tt}SUFKNNP0CCxQw{c5HO-Z$ zf0>9PviX=NEg!tsL^K$2Y+?+`jETX=V-oSsMDk4DC+_(6+snFk(OWB6y?2Qs`#ZtP zc8E6|tQA1H1Uz{g)1kXxx0vRSkYUqh88!%hbw3vbPp&9-*K-%Rjf_+)^{*FZm(_pORzX{?!$~MO2@sno-9eh3qT!UkLCo%qo>utyi}-?0#3`5Z|1W)wh%1RCzM@|_+uh7)o(h^km!f9_;~ z4~GW41A%VDTm>F`ovvqqtKt5riPET$1Kt`z-<9$#*i*EVEbxv&pO&r^6p~`fG_a8k z#IUj?)Bf410vOi0dNBU^>_jwd=AY9S?d#mN^R;CQEV17u^7iv4D{DbJ4u9=k*RbMO zmL;`SS54OLWY+Bd>B{z}*R4*re~H7J>n$kGgsKi6!k-o9mf!h;%NB1TdXbaip|PE8 zxwDQs!vABSL;q5DDYo=pRV+6OZ^3m8XgUn1P^`(uD-Yc#I{D;eM_)X6lS z)&VXgfP3FMw0mOws7*K>Rz6EwWfTo?9YMwSp1J=|=qRu!;hm0t&pe;$n8r z0M`=Ss_928hF8`i$A$ArZ&S^4%pbRyE;%;5kT$ug8sHlKZ);Zr)7Eu`eebi)Pbqcm z2ab7hY(v2DQbHWd7zeNsVy;tJ9r74u%yUUbJ>oKGN@&)2F0&ZbDw2g}D{CWEA)2)r zs=BH_Q7T1Qt0Y5RhN87Ye<`WjZcAIVH2aITiV*y=d+&R;pUv|hnS_uck^AmB_nvd_ zJ?DJiNsSP%*5tjnVsn+c`OZ+yIG6*B0*2i{N}ugv@_Q| zm*Z@C-o{mTu9HQ6ob4li+>B3X;>Yg+r67q0A`h?LVsF8nEf0EUf3)Sfxp#SCQ(e5> z<@9cKP0st8!?Euo%*kn(4D<7yKHpCw4|PT&-O9~c6|L2Rb2+MgE!p9%nf!gu1@vZj zN_I;ms!Ah9v5`O&PR=B7@p*clB^nfl_W0(_7()Mb8py*B+XAf})vk?l1-cyOCfp@$ zaPXK-0Wi|uw!J~Ie`?6tcKvL>)Qk3(k>6ctdWvd2*;3paos@Z#J9rge_gYy%s}r$V z3jJ}F0ZC3%6*H63FImHIHwg8ymyZ14e2Gd|VFc0nklzeGwD5u9hXC}m??FE}`tu?5 zlKwPcY7dOH48C~kGkX8<5*LmT ziJr)+I}ii*iB+~%=O*aS;m>s#f8=v+xL1*9s4}Hw3-Q}W^aUL&$T`}+I4!@ z0Q&ADNaiNOJAXtXbOJcBMF1zRx22$o71Z|@*?)a;bh%BTdR9aC9P1kzdRkYt1opR$ zdzH+y^aj_p$eZXe53>x_8{)^-~vJ*jT8ACmFO1 z*Y7Hc$A3dF#^RyMSU?oXhLbBG5f6pGI=jqX{%DcCd>Wji)w3EE`-(q2aymRhT`;g; zy~~9}Kll_HHL7RS^r~DC5CxJSAzj*$yb3;k$W;LHiSr7bJi1h@`Ddw04&IA?uH!+& z%DbhbB#n;FsBSdRPP8XfXf0~cSo$r<}e8@s_BRt7#?Q7M7;;>>zt_ zr2ok0VEBu}!5>G@hrF;O)Bzh_8-Ak0`vkMH5SgZVrqiqgt49e6&fWy3k+;Jm-|>f$ zQGZ@V%84!#<$wkQD1PTM&_=gm4Ixe8*h1v?Dpd!Wcs?741vpR%j*@FRZZY()8raoy z@L-QG6!JB;w>LUH9>`2Q#ta=jI)r|;^mQ}c`@ZjEd;tl7-UY22fUDf!FHmJ?sroIxzv&?0M(Z6bKE@W0{Ym`IV#p!+&JX zxxmlMrqlx!`1dR_r0w(P)(8~(*sFK65_AH%V_K(G`50_UchC@@$u$> zPCz9x9Pq>O5?3&IxW8OwlMkC}?M`F0vl*%{1YGVwz-@5q+=VmjO}n|y;qdck&C5vE zB7QANPK7GMX%e!U3$5gi3Z~E=!hgEQcCs}^|Cur_u=D<|rmjbEQmCnuB!#x@;F3ZP z2V}BkRv>r@eY_a$qYcN(O<@&tzl94e&40*Hm5^MN^Fqq; z1@IhcMy^YSV7(35*#oHi1s%HB*D_NH2o!QA3#|as3*i7DbE`|%OF=G-0L!E?n6xyRv4W8Avs*w10d937+h`kVo4tGM_B;*w+OuM!}OAS+NDcnv9$T6pu6dfXpcw zm14|{hKD7>>G-mvizefQmeI#EqYy}X78n%QWKtZ-mI+&r-W@>z|}N0;fbCtqBY@C4u4}vzNtZ4u1)p$*${`= z{l}Z%UP+HW6!asMXT%{A>>!`7NcMF(APK=uLB8}p6LmV@}_(R^8Y!&w|vOScoj7KH2Lcc1luN7*6bk9Jp}0axP-;YxoR4K_0<}%6R^$ zAx7L{_hXou|7QWb-~ffwQK&-;mr%opa2YM^gadlMg)3;QP&hd*KS+a1;*FQLn-cG*yBTEH+4yV1I>-?78oR?}AzmjO->&R+;sB zVizfecWmj&F{5t)$IKVStx!fRc06TgHnBZ>)8(e+=|0002xrdj?&9Rp1O delta 24667 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 | HotkeyConfig; + config(lang: Language | undefined): Promise | HotkeyConfig; setConfig(config: HotkeyConfig): void; activate(): void; deactivate(): void; @@ -13,12 +13,13 @@ export interface HotkeyImplementation { class GlobalHotkeys implements HotkeyImplementation { constructor(private hotkeySystem?: HotkeySystem) { } - public async config(): Promise { + public async config(lang: Language | undefined): Promise { return expect( HotkeyConfig.parseJson( await window.__TAURI__!.core.invoke("get_hotkey_config"), ), "Couldn't parse the hotkey config.", + lang, ); } @@ -67,6 +68,7 @@ class GlobalHotkeys implements HotkeyImplementation { export function createHotkeys( commandSink: CommandSinkRef, configJson: unknown, + lang: Language | undefined, ): HotkeyImplementation { let hotkeySystem: HotkeySystem | null = null; @@ -86,6 +88,7 @@ export function createHotkeys( hotkeySystem = expect( HotkeySystem.new(commandSink), "Couldn't initialize the hotkeys", + lang, ); } } diff --git a/src/storage/index.ts b/src/storage/index.ts index 11bd2086f..2e54c19ec 100644 --- a/src/storage/index.ts +++ b/src/storage/index.ts @@ -1,11 +1,12 @@ import { openDB, IDBPDatabase } from "idb"; import { Option, assert } from "../util/OptionUtil"; -import { RunRef, Run, TimingMethod } from "../livesplit-core"; +import { RunRef, Run, TimingMethod, Language } from "../livesplit-core"; import { GeneralSettings, MANUAL_GAME_TIME_SETTINGS_DEFAULT, } from "../ui/views/MainSettings"; import { FRAME_RATE_AUTOMATIC } from "../util/FrameRate"; +import { fromLocaleOpt, getLocaleOpt, setHtmlLang } from "../localization"; export type HotkeyConfigSettings = unknown; export type LayoutSettings = unknown; @@ -114,15 +115,16 @@ function getDb(): Promise> { export async function storeRunWithoutDisposing( run: RunRef, key: number | undefined, + lang: Language | undefined, ) { await storeSplits((callback) => { callback(run, run.saveAsLssBytes()); - }, key); + }, key, lang); } -export async function storeRunAndDispose(run: Run, key: number | undefined) { +export async function storeRunAndDispose(run: Run, key: number | undefined, lang: Language | undefined) { try { - await storeRunWithoutDisposing(run, key); + await storeRunWithoutDisposing(run, key, lang); } finally { run[Symbol.dispose](); } @@ -131,6 +133,7 @@ export async function storeRunAndDispose(run: Run, key: number | undefined) { export async function storeSplits( callback: (callback: (run: RunRef, lssBytes: Uint8Array) => void) => void, key: number | undefined, + lang: Language | undefined, ): Promise { const db = await getDb(); @@ -146,7 +149,7 @@ export async function storeSplits( await tx.done; - assert(promise !== null, "Callback needs to actually run"); + assert(promise !== null, "Callback needs to actually run", lang); return promise; } @@ -245,7 +248,12 @@ export async function loadSplitsKey(): Promise { export async function storeGeneralSettings(generalSettings: GeneralSettings) { const db = await getDb(); - await db.put("settings", generalSettings, "generalSettings"); + const storedSettings = { + ...generalSettings, + lang: getLocaleOpt(generalSettings.lang), + }; + + await db.put("settings", storedSettings, "generalSettings"); } export async function loadGeneralSettings(): Promise { @@ -259,6 +267,10 @@ export async function loadGeneralSettings(): Promise { generalSettings.showManualGameTime = MANUAL_GAME_TIME_SETTINGS_DEFAULT; } + const lang = fromLocaleOpt(generalSettings.lang); + + setHtmlLang(lang); + return { frameRate: generalSettings.frameRate ?? FRAME_RATE_AUTOMATIC, showControlButtons: generalSettings.showControlButtons ?? !isTauri, @@ -268,6 +280,7 @@ export async function loadGeneralSettings(): Promise { serverUrl: generalSettings.serverUrl, alwaysOnTop: generalSettings.alwaysOnTop ?? (isTauri ? true : undefined), + lang, }; } diff --git a/src/type-definitions/webpack-globals.d.ts b/src/type-definitions/webpack-globals.d.ts index bcfec398e..01b663f0a 100644 --- a/src/type-definitions/webpack-globals.d.ts +++ b/src/type-definitions/webpack-globals.d.ts @@ -11,5 +11,6 @@ declare interface Contributor { declare interface ChangelogEntry { id: string; message: string; + messages?: Record; date: string; } diff --git a/src/ui/LiveSplit.tsx b/src/ui/LiveSplit.tsx index f3abb424d..0d71439ef 100644 --- a/src/ui/LiveSplit.tsx +++ b/src/ui/LiveSplit.tsx @@ -14,6 +14,7 @@ import { TimerPhase, Event, LayoutRefMut, + Language, } from "../livesplit-core"; import { Layout as ShowLayout } from "./components/Layout"; import { @@ -65,6 +66,7 @@ import "react-toastify/dist/ReactToastify.css"; import * as classes from "../css/LiveSplit.module.scss"; import * as sidebarClasses from "../css/Sidebar.module.scss"; import * as toastClasses from "../css/Toast.module.scss"; +import { Label, orAutoLang, resolve, setHtmlLang } from "../localization"; const buttonHeight = parseFloat(variables.buttonHeight); const largeMargin = parseFloat(variables.largeMargin); @@ -183,6 +185,7 @@ export class LiveSplit extends React.Component { const timer = expect( Timer.new(run), "The Default Run should be a valid Run", + props.generalSettings.lang, ); const commandSink = new LSOCommandSink(timer, this); @@ -190,6 +193,7 @@ export class LiveSplit extends React.Component { hotkeySystem = createHotkeys( commandSink.getCommandSink(), props.hotkeys, + props.generalSettings.lang, ); if (props.splits !== undefined) { @@ -215,7 +219,9 @@ export class LiveSplit extends React.Component { /* Looks like the storage has no valid data */ } if (layout === null) { - layout = Layout.defaultLayout(); + layout = Layout.defaultLayout( + orAutoLang(props.generalSettings.lang), + ); } const isDesktop = this.isDesktopQuery.matches; @@ -270,12 +276,16 @@ export class LiveSplit extends React.Component { this.mediaQueryChanged = this.mediaQueryChanged.bind(this); } - private notifyAboutUpdate(this: void) { + public getLang(): Language | undefined { + return this.state.generalSettings.lang; + } + + private notifyAboutUpdate() { const { serviceWorker } = navigator; if (serviceWorker && serviceWorker.controller) { // Don't prompt for update when service worker gets removed toast.warn( - "A new version of LiveSplit One is available! Click here to reload.", + resolve(Label.UpdateAvailable, this.state.generalSettings.lang), { closeOnClick: true, onClick: () => window.location.reload(), @@ -296,7 +306,10 @@ export class LiveSplit extends React.Component { window.onbeforeunload = () => { if (this.state.splitsModified || this.state.layoutModified) { - return "There are unsaved changes. Do you really want to close LiveSplit One?"; + return resolve( + Label.UnsavedChangesBeforeUnload, + this.state.generalSettings.lang, + ); } else { return; } @@ -311,9 +324,8 @@ export class LiveSplit extends React.Component { const { serviceWorker } = navigator; if (serviceWorker && serviceWorker.controller) { // Don't prompt for update when there was no service worker previously installed - serviceWorker.addEventListener( - "controllerchange", - this.notifyAboutUpdate, + serviceWorker.addEventListener("controllerchange", () => + this.notifyAboutUpdate(), ); } } @@ -325,15 +337,27 @@ export class LiveSplit extends React.Component { public componentWillUnmount() { window.removeEventListener( "wheel", - expect(this.scrollEvent, "A Scroll Event should exist"), + expect( + this.scrollEvent, + "A Scroll Event should exist", + this.state.generalSettings.lang, + ), ); window.removeEventListener( "contextmenu", - expect(this.rightClickEvent, "A Right Click Event should exist"), + expect( + this.rightClickEvent, + "A Right Click Event should exist", + this.state.generalSettings.lang, + ), ); window.removeEventListener( "resize", - expect(this.resizeEvent, "A Resize Event should exist"), + expect( + this.resizeEvent, + "A Resize Event should exist", + this.state.generalSettings.lang, + ), ); this.state.commandSink[Symbol.dispose](); this.state.layout[Symbol.dispose](); @@ -348,15 +372,15 @@ export class LiveSplit extends React.Component { const { serviceWorker } = navigator; if (serviceWorker) { - serviceWorker.removeEventListener( - "controllerchange", - this.notifyAboutUpdate, + serviceWorker.removeEventListener("controllerchange", () => + this.notifyAboutUpdate(), ); } } public render() { let view: React.JSX.Element | undefined; + if (this.state.menu.kind === MenuKind.RunEditor) { view = ( { /> ); } else if (this.state.menu.kind === MenuKind.About) { - view = ; + view = ( + + ); } else if (this.state.menu.kind === MenuKind.Splits) { view = ( { > {!this.state.isDesktop && !this.state.sidebarOpen && (