From 8c80cb9f0b23e952226db15494753de3062766fc Mon Sep 17 00:00:00 2001 From: Jonathan Gamble <101470903+schlawg@users.noreply.github.com> Date: Sat, 10 Feb 2024 12:40:44 -0600 Subject: [PATCH 01/39] don't forget tournament tab when browsing rounds --- ui/analyse/src/study/relay/relayTourView.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/analyse/src/study/relay/relayTourView.ts b/ui/analyse/src/study/relay/relayTourView.ts index 78b65f036792a..f10a7944f3bb4 100644 --- a/ui/analyse/src/study/relay/relayTourView.ts +++ b/ui/analyse/src/study/relay/relayTourView.ts @@ -200,13 +200,14 @@ const roundStateIcon = (round: RelayRound) => export function rounds(ctrl: StudyCtrl): VNode { const canContribute = ctrl.members.canContribute(); const relay = ctrl.relay!; + const fragment = relay.tab() === 'overview' ? '' : `#${relay.tab()}`; return h( 'div.study__relay__rounds', { hook: onInsert(el => scrollToInnerSelector(el, '.active')) }, relay.data.rounds .map(round => h('div', { key: round.id, class: { active: ctrl.data.id == round.id } }, [ - h('a.link', { attrs: { href: relay.roundPath(round) } }, round.name), + h('a.link', { attrs: { href: `${relay.roundPath(round)}${fragment}` } }, round.name), roundStateIcon(round), canContribute && h('a.act', { attrs: { ...dataIcon(licon.Gear), href: `/broadcast/round/${round.id}/edit` } }), From 6f292ebf66a064845aec7251f5b8634497d79ff8 Mon Sep 17 00:00:00 2001 From: Carbrex <95964955+Carbrex@users.noreply.github.com> Date: Sun, 11 Feb 2024 02:01:57 +0530 Subject: [PATCH 02/39] Update translation/source/broadcast.xml for consistent casing Co-authored-by: Trevor Fitzgerald --- translation/source/broadcast.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/translation/source/broadcast.xml b/translation/source/broadcast.xml index 249e862c91089..a86c9b78a3aaa 100644 --- a/translation/source/broadcast.xml +++ b/translation/source/broadcast.xml @@ -8,7 +8,7 @@ Live tournament broadcasts New live broadcast - Subscribed Broadcasts + Subscribed broadcasts About broadcasts No rounds yet. How to use Lichess Broadcasts. From 560686951bbc0b3806fd740c7d66a0dd78c747a9 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 11 Feb 2024 07:56:52 +0100 Subject: [PATCH 03/39] New Crowdin updates (#14648) * New translations: site.xml (Italian) * New translations: study.xml (Italian) * New translations: site.xml (Czech) * New translations: broadcast.xml (French) * New translations: ublog.xml (Czech) * New translations: timeago.xml (Czech) * New translations: onboarding.xml (Czech) * New translations: preferences.xml (Marathi) * New translations: ublog.xml (Czech) * New translations: patron.xml (Czech) * New translations: broadcast.xml (Czech) * New translations: tfa.xml (Czech) * New translations: faq.xml (Czech) * New translations: oauthscope.xml (Czech) * New translations: coordinates.xml (Marathi) * New translations: arena.xml (Swiss German) * New translations: site.xml (Japanese) * New translations: oauthscope.xml (Korean) * New translations: onboarding.xml (Korean) * New translations: site.xml (Korean) * New translations: study.xml (Korean) * New translations: dgt.xml (Korean) * New translations: challenge.xml (Afrikaans) * New translations: challenge.xml (Azerbaijani) * New translations: challenge.xml (Aragonese) --- translation/dest/arena/gsw-CH.xml | 10 ++++------ translation/dest/broadcast/cs-CZ.xml | 15 +++++++++++++++ translation/dest/broadcast/fr-FR.xml | 4 ++-- translation/dest/challenge/af-ZA.xml | 2 +- translation/dest/challenge/an-ES.xml | 2 +- translation/dest/challenge/az-AZ.xml | 2 +- translation/dest/coordinates/mr-IN.xml | 2 +- translation/dest/dgt/ko-KR.xml | 6 +++++- translation/dest/faq/cs-CZ.xml | 24 ++++++++++++++++++++++++ translation/dest/oauthScope/cs-CZ.xml | 7 +++++++ translation/dest/oauthScope/ko-KR.xml | 6 ++++++ translation/dest/onboarding/cs-CZ.xml | 17 ++++++++++++++++- translation/dest/onboarding/ko-KR.xml | 9 +++++++++ translation/dest/patron/cs-CZ.xml | 3 +++ translation/dest/preferences/mr-IN.xml | 2 +- translation/dest/site/cs-CZ.xml | 14 ++++++++++++++ translation/dest/site/it-IT.xml | 1 + translation/dest/site/ja-JP.xml | 1 + translation/dest/site/ko-KR.xml | 1 + translation/dest/study/it-IT.xml | 3 ++- translation/dest/study/ko-KR.xml | 3 ++- translation/dest/tfa/cs-CZ.xml | 3 +++ translation/dest/timeago/cs-CZ.xml | 13 +++++++++++++ translation/dest/ublog/cs-CZ.xml | 9 +++++++++ 24 files changed, 142 insertions(+), 17 deletions(-) diff --git a/translation/dest/arena/gsw-CH.xml b/translation/dest/arena/gsw-CH.xml index 1e856ba65a23f..01f9763ac60fb 100644 --- a/translation/dest/arena/gsw-CH.xml +++ b/translation/dest/arena/gsw-CH.xml @@ -2,8 +2,7 @@ Arena Turnier Isch es gwertet? - Du wirsch benachrichtiget, wänn\'s Turnier afangt. -Es isch also möglich, während de Wartezit ime andere Tab z\'schpille. + Du wirsch benachrichtiget, wänn\'s Turnier afangt. Es isch also möglich, während de Wartezit ime andere Tab z\'schpille. Das Turnier isch gwertet und wird dini Wertig beiflusse. Das Turnier isch *nöd* gwertet und wird dini Wertig *nöd* beiflusse. Einigi Turnier sind gwertet und werded dini Wertig beiflusse. @@ -33,8 +32,7 @@ Wer schnäll schpillt und sofort zrugg id Turnierübersicht gaht, hät meh Schpi Wie ändet es Turnier? Es Turnier hät e \"Countdown Uhr\" - isch d\'Turnierzit abgloffe, werded alli Räng fix und de Sieger wird bekannt geh. Schpiel wo no am laufe sind, müend fertig gschpillt werde, sie zelled aber nümme fürs Turnier. Anderi wichtigi Regle - Es lauft en \"Countdown\" für de 1. Zug... -Isch nach 12 Sekunde nöd zoge worde, gits es Forfait für de Gägner. + Es lauft en \"Countdown\" für de 1. Zug... Isch nach 12 Sekunde nöd zoge worde, gits es Forfait für de Gägner. Es Remis innerhalb vu de erschte %s Züg git für beidi Schpiller 0 Pünkt. Es Remis innerhalb vu %s Züg git für beidi Schpiller 0 Pünkt. @@ -46,7 +44,7 @@ Isch nach 12 Sekunde nöd zoge worde, gits es Forfait für de Gägner. Variante Minimali Schpieldur Arena Verlauf - + Zeig s\'Team Zeig all %s Teams @@ -59,7 +57,7 @@ Isch nach 12 Sekunde nöd zoge worde, gits es Forfait für de Gägner. Arena Sieges Serie Nach 2 Sieg in Serie gits 4 Pünkt anstatt 2. Berserk nöd möglich - Kei Arena-Serie + Kei Arena-Serie Durchschnittlichi Leischtig Durchschnittlichi Punktzahl Mini Turnier diff --git a/translation/dest/broadcast/cs-CZ.xml b/translation/dest/broadcast/cs-CZ.xml index 5298985e6b137..7aba71fc740ba 100644 --- a/translation/dest/broadcast/cs-CZ.xml +++ b/translation/dest/broadcast/cs-CZ.xml @@ -10,10 +10,15 @@ Živé přenosy turnajů Nový živý přenos + O vysílání + Zatím žádná kola. + Jak používat Lichess vysílání. + Nové kolo bude mít stejné členy a přispěvatele jako to předchozí. Přidat kolo Probíhající Chystané Dokončené + Lichess detekuje dokončení kola na základě zdrojových her. Tento přepínač použijte, pokud není k dispozici žádný zdroj. Číslo kola Číslo kola Název turnaje @@ -37,4 +42,14 @@ Upravit studie kola Smazat tento turnaj Opravdu smazat celý turnaj, všechna kola a hry. + Automatický žebříček + Vypočítejte a zobrazte jednoduchý žebříček na základě výsledků hry + Volitelné: nahraďte jména hráčů, hodnocení a tituly + Jeden řádek pro každého hráče a takto naformátovaný: +Původní jméno; Náhradní jméno; Nepovinné náhradní hodnocení; Nepovinný náhradní název +Příklad: +DrNykterstein;Magnus Carlsen;2863 +AnishGiri;Anish Giri;2764;GM + Doba v sekundách + Volitelné, jak dlouho se má čekat mezi jednotlivými požadavky. Min. 2s, max. 60s. Výchozí hodnota je automatická podle počtu diváků. diff --git a/translation/dest/broadcast/fr-FR.xml b/translation/dest/broadcast/fr-FR.xml index b7c473914acaf..d03157abf7dd0 100644 --- a/translation/dest/broadcast/fr-FR.xml +++ b/translation/dest/broadcast/fr-FR.xml @@ -9,8 +9,8 @@ Diffusions de tournois en direct Nouvelle diffusion en direct À propos des diffusions - Aucune ronde pour le moment - Comment utiliser les diffusions dans Lichess + Aucune ronde pour le moment. + Comment utiliser les diffusions dans Lichess. La nouvelle ronde aura les mêmes participants et contributeurs que la précédente. Ajouter une ronde En cours diff --git a/translation/dest/challenge/af-ZA.xml b/translation/dest/challenge/af-ZA.xml index 3a98538b7afec..3f775e90980cf 100644 --- a/translation/dest/challenge/af-ZA.xml +++ b/translation/dest/challenge/af-ZA.xml @@ -2,7 +2,7 @@ Uitdagings: %1$s Daag uit tot \'n spel - Uitdaging afgewys + Uitdaging afgewys. Uitdaging aanvaar! Uitdaging gekanselleer. Registreer om uitdagings te stuur. diff --git a/translation/dest/challenge/an-ES.xml b/translation/dest/challenge/an-ES.xml index 4ba55264fab4d..9c35453a85c4d 100644 --- a/translation/dest/challenge/an-ES.xml +++ b/translation/dest/challenge/an-ES.xml @@ -2,7 +2,7 @@ Desafíos: %1$s Desafiar a una partida - Desafío refusau + Desafío refusau. Desafío acceptau! Desafío cancelau. Has d\'estar rechistrau pa ninviar desafíos. diff --git a/translation/dest/challenge/az-AZ.xml b/translation/dest/challenge/az-AZ.xml index 03ec86dd3c51f..0fabed4693a72 100644 --- a/translation/dest/challenge/az-AZ.xml +++ b/translation/dest/challenge/az-AZ.xml @@ -1,7 +1,7 @@ Oyuna çağırış - Çağırış rədd edildi + Çağırış rədd edildi. Çağırış qəbul edildi! Çağırışdan imtina edildi. Çağırış göndərmək üçün lütfən qeydiyyatdan keçin. diff --git a/translation/dest/coordinates/mr-IN.xml b/translation/dest/coordinates/mr-IN.xml index 84f289c7ac69a..4ea00616fd51d 100644 --- a/translation/dest/coordinates/mr-IN.xml +++ b/translation/dest/coordinates/mr-IN.xml @@ -5,7 +5,7 @@ पांढऱ्या सोंगट्या खेळताना सरासरी गुण: %s काळ्या सोंगट्या खेळताना सरासरी गुण: %s बुद्धिबळ पटावरील सहनिर्देशक माहिती असणे हे एक महत्वाचे कौशल्य आहे: -  सर्व अभ्यास बिजगणितीय सहनिर्देशक वापरतात. + सर्व अभ्यास बिजगणितीय सहनिर्देशक वापरतात. सर्वांना \"बुद्धिबळाची भाषा\" माहिती असल्यास मित्रांशी बोलणे सोपे होते. सहनिर्देशक लगेच ओळखता आले तर खेळाचे विश्लेषण जास्त परिणामकारक होते. एक सहनिर्देशक पटावर दिसेल व तुम्हाला संबंधित घरावर क्लिक करावे लागेल. diff --git a/translation/dest/dgt/ko-KR.xml b/translation/dest/dgt/ko-KR.xml index ac0a05e2d2418..42cd7e1240a0e 100644 --- a/translation/dest/dgt/ko-KR.xml +++ b/translation/dest/dgt/ko-KR.xml @@ -4,16 +4,20 @@ 이 페이지에서는 DGT 보드를 Lichess에 연결하여 사용 할 수 있습니다. DGT 보드에 연결하려면 %s를 설치해야 합니다. 소프트웨어 다운로드가 가능합니다: %s. + 만약 %1$s가 이 컴퓨터에서 작동하고 있다면, %2$s하여 연결을 확인할 수 있습니다. + 이 링크를 클릭 + 만약 %1$s가 다른 장치나 포트에서 작동하고 있다면, %2$s에서 IP 주소를 설정하고 이곳으로 이식해야 합니다. 구성 섹션 이 보드는 이미 진행 중인 게임이나 시작하는 새로운 게임에 자동으로 연결됩니다. 어떤 게임을 할지 선택할 수 있는 기능이 곧 나올 예정입니다. 준비가 되셨으면 보드를 설치한 다음 %s를 클릭하세요. 움직임이 감지되지 않을 경우 DGT 보드에서 먼저 상대방이 말을 움직였는지 확인하고, 다시 시도해주세요. - 마지막 수단으로 보드를 Liches와 동일하게 설정한 다음 %s + 마지막 수단으로 보드를 Liches와 동일하게 설정한 다음 %s 이 페이지를 다시 로드하세요 Lichess 연결 알맞은 OAuth 토큰이 생성되지 않았습니다 DGT 보드 연결 + %2$s가 다른 장치나 포트에서 작동하는 것이 아니라면 \"%1$s\"를 사용하십시오. 텍스트 음성 변환 각 플레이어의 수에 음성 내레이션을 구성하여 보드에 더 집중 할 수 있게 만듭니다 합성 음성 활성화 diff --git a/translation/dest/faq/cs-CZ.xml b/translation/dest/faq/cs-CZ.xml index 6f188a6850935..7d4247c441d21 100644 --- a/translation/dest/faq/cs-CZ.xml +++ b/translation/dest/faq/cs-CZ.xml @@ -134,4 +134,28 @@ Je nejlepší myslet na hodnocení jako \"relativní\" údaje (na rozdíl od \"a Zobrazit vyskakovací okno s informacemi o webu Lichess vám také může posílat oznámení, například když jste na tahu či po obdržení soukromé zprávy. Klikněte na ikonu zámku vedle URL adresy ve Vašem prohlížeči, a poté vyberte zda zablokovat či povolit oznámení. + Povolit automatické přehrávání zvuků? + Většina prohlížečů může v zájmu ochrany uživatelů zabránit přehrávání zvuku na čerstvě načtené stránce. Představte si, že by vás každá webová stránka mohla okamžitě bombardovat zvukovou reklamou. + +Červená ikona ztlumení zvuku se zobrazí, když prohlížeč zabrání přehrávání zvuku na stránce lichess.org. Obvykle se toto omezení zruší, jakmile na něco kliknete. V některých mobilních prohlížečích se přetažení figurky dotykem nepočítá jako kliknutí. V takovém případě musíte na začátku každé hry klepnout na šachovnici, aby byl zvuk povolen. + +Zobrazujeme červenou ikonu, abychom vás upozornili, když k tomu dojde. Často můžete výslovně povolit, aby lichess.org přehrával zvuky. Zde jsou pokyny, jak to udělat v posledních verzích některých populárních prohlížečů. + počítač + 1. Jděte na lichess.org +2. Stiskněte klávesu Ctrl-i v systému Linux/Windows nebo cmd-i v systému MacOS. +3. Klikněte na kartu Oprávnění +4. Povolit zvuk a video na lichess.org + 1. Jděte na lichess.org +2. Klikněte na ikonu zámku v adresním řádku +3. Klikněte na možnost Nastavení webu +4. Povolit zvuk + 1. Jděte na lichess.org +2. Klikněte na Safari na liště nabídek +3. Klikněte na položku Nastavení pro lichess.org ... +4. Povolit veškeré automatické přehrávání + 1. Klikněte na tři tečky v pravém horním rohu. +2. Klikněte na možnost Nastavení +3. Klikněte na položku Cookies a oprávnění webu +4. Přejděte dolů a klikněte na možnost Automatické přehrávání médií +5. Přidejte lichess.org do Povolit diff --git a/translation/dest/oauthScope/cs-CZ.xml b/translation/dest/oauthScope/cs-CZ.xml index d05e20497be46..89c788db0e24d 100644 --- a/translation/dest/oauthScope/cs-CZ.xml +++ b/translation/dest/oauthScope/cs-CZ.xml @@ -36,12 +36,19 @@ tok kódu autorizace Místo, %s můžete přímo použít API žádosti. generovat osobní přístupový token + Pečlivě tyto žetony střežte! Jsou jako hesla. Výhodou používání tokenů oproti zadávání hesla do skriptu je, že tokeny lze odvolat a lze jich hodně vygenerovat. + Zde je %1$s a %2$s. + příklad aplikace osobního tokenu Dokumentace API Nový přístupový token + Přístupové API tokeny Vytvořeno %s Naposledy použito %s Již jsi hrál hry! Upozornění pouze pro vývojáře: Tento formulář lze předvyplnit úpravou parametrů dotazu URL. %s + zaškrtne rozsahy %1$s a %2$s a nastaví popis tokenu. + Kódy rozsahů naleznete v kódu HTML formuláře. + Poskytnutí těchto předvyplněných URL adres uživatelům jim pomůže získat správné rozsahy tokenů. diff --git a/translation/dest/oauthScope/ko-KR.xml b/translation/dest/oauthScope/ko-KR.xml index 04282feb0df7f..4420e012f1c39 100644 --- a/translation/dest/oauthScope/ko-KR.xml +++ b/translation/dest/oauthScope/ko-KR.xml @@ -33,4 +33,10 @@ 운영자 도구 사용(허용 범위 내에서) 개인 API 액세스 토큰 개인 접속 토큰을 생성합니다. + 개발자들을 위한 메모: + URL의 쿼리 파라미터를 변경하여 이 서식을 미리 채울 수 있습니다. + 예시: %s + 위 링크는 \'%1$s\'와 \'%2$s\' 스코프를 체크하고, 토큰의 설명을 설정합니다. + 스코프 코드는 서식의 HTML 코드에서 찾을 수 있습니다. + 이러한 미리 채워진 URL을 유저에게 제공하면 올바른 토큰 스코프를 갖도록 하는 데 도움이 될 것입니다. diff --git a/translation/dest/onboarding/cs-CZ.xml b/translation/dest/onboarding/cs-CZ.xml index 3ea04e700dfa8..3a455f6a4c2c4 100644 --- a/translation/dest/onboarding/cs-CZ.xml +++ b/translation/dest/onboarding/cs-CZ.xml @@ -1,2 +1,17 @@ - + + Vítejte! + Vítejte na lichess.org! + Toto je vaše profilová stránka. + Bude tento účet používat dítě? Možná budete chtít povolit %s. + Co teď? Zde je několik návrhů: + Naučte se pravidla šachu + Zlepšete se pomocí taktických šachových úloh. + Zahrajte si s umělou inteligencí. + Zahrajte si se soupeři z celého světa. + Sledujte své přátele na Lichess. + Zahrajte si v turnajích. + Učte se z %1$s a %2$s. + Nakonfigurujte Lichess podle svých představ. + Prozkoumejte stránku a bavte se :) + diff --git a/translation/dest/onboarding/ko-KR.xml b/translation/dest/onboarding/ko-KR.xml index 77433b371f8d2..9c66b59ea8084 100644 --- a/translation/dest/onboarding/ko-KR.xml +++ b/translation/dest/onboarding/ko-KR.xml @@ -4,5 +4,14 @@ lichess.org에 오신 것을 환영합니다! 여기는 프로필 페이지 입니다. 아이가 이 계정을 사용할까요? %s를 사용하도록 설정할 수 있습니다. + 이제 뭘 하죠? 여기 몇 가지 추천해 드릴게요: 체스 규칙 배우기 + 체스 전술 퍼즐로 실력을 향상시키세요. + 인공지능을 상대로 플레이하세요. + 전 세계의 상대들과 플레이하세요. + Lichess에 있는 친구들을 팔로우하세요. + 토너먼트에서 플레이하세요. + %1$s와 %2$s에서 배우세요. + 취향대로 Lichess를 설정하세요. + 사이트를 탐험하고 즐거운 시간을 보내세요 :) diff --git a/translation/dest/patron/cs-CZ.xml b/translation/dest/patron/cs-CZ.xml index dd57dffce7bc7..5861c6272b09a 100644 --- a/translation/dest/patron/cs-CZ.xml +++ b/translation/dest/patron/cs-CZ.xml @@ -84,4 +84,7 @@ Patroni se však blýsknou novou cool ikonou profilu. Nyní jste Lichess Patronem na jeden měsíc! Jeden měsíc Vám NEBUDE znovu účtován poplatek a váš Lichess účet bude ponížen na bezplatný. Změnit měnu + Detaily platby + Aktualizovat způsob platby + Spravujte své předplatné a stáhněte si své faktury a účtenky diff --git a/translation/dest/preferences/mr-IN.xml b/translation/dest/preferences/mr-IN.xml index defd1af50e0a7..9a1fd1ef41f13 100644 --- a/translation/dest/preferences/mr-IN.xml +++ b/translation/dest/preferences/mr-IN.xml @@ -12,7 +12,7 @@ खेळताना चालयादी चाल यादी सोंगट्यांचे चिन्ह -  अक्षर (K, Q, R, B, N) + अक्षर (K, Q, R, B, N) ध्यानग्र स्थिती गुणांकन दाखवा खेळाडूंचे फ्लेअर दाखवा diff --git a/translation/dest/site/cs-CZ.xml b/translation/dest/site/cs-CZ.xml index 33e929d581d47..49480fba2acc5 100644 --- a/translation/dest/site/cs-CZ.xml +++ b/translation/dest/site/cs-CZ.xml @@ -5,6 +5,7 @@ Pro pozvání někoho ke hře využijte tento odkaz Konec hry Čekání na soupeře + Nebo nechte soupeře naskenovat tento QR kód Čeká se Jste na tahu AI %1$s úrovně %2$s @@ -72,6 +73,7 @@ Povýšit na hlavní variantu Smazat odsud Zobrazit jako variantu + Zkopírovat PGN varianty Tah Prohra Výhra @@ -459,6 +461,7 @@ Importuj hru Vložení partie ve formátu PGN Vám umožní přehrání partie, získáte počítačovou analýzu, chat ke hře a URL ke sdílení hry. Varianty budou vymazány. Chcete-li je ponechat, importujte PGN prostřednictvím studie. + K této PGN má přístup kdokoli. Chcete-li hru naimportovat soukromě, použijte studii. %s importovaná %s importované @@ -473,6 +476,7 @@ Černý dá prvním tahem mat Zkusit znovu Připojování + Offline %s kamarád online %s kamarádi online @@ -570,6 +574,7 @@ Jméno Příjmení O mně + Země nebo region Děkujeme! Odkazy na sociální sítě Jedna URL na řádek. @@ -762,6 +767,10 @@ Další hrubá chyba Další chyba Další nepřesnost + Přepnout šipky variant + Přepnout poznámky glyfů + Šipky variant umožňují navigaci bez použití seznamu tahů. + zahrát vybraný tah Nový turnaj Šachové turnaje nabízejí různé časové možnosti a varianty Zahrajte si rychlý šachový turnaj! Připojte se k oficiálnímu plánovanému turnaji, nebo si vytvořte vlastní. Bullet, Blitz, Klasické, Chess960(Fisherovky), Král v centru, Tři šachy a další možnosti jsou k dispozici pro nekonečnou šachovou zábavu. @@ -806,6 +815,7 @@ S přáteli Se všemi Dětský režim + Dětský režim je povolen. To je pro bezpečnost. V dětském režimu je jakákoli komunikace zablokována. Zapněte to pro děti a studenty, pro ochranu před ostatními na Internetu. Když je zapnutý dětský režim, tak se u loga Lichess objeví ikona %s. Podle toho poznáte, že je Vaše dítě v bezpečí. Váš účet je spravován. Požádejte svého šachového učitele o zrušení dětského režimu. @@ -927,6 +937,8 @@ a uložit %s předtažených variant a uložit %s předtažených variant + Dostali jste soukromou zprávu od Lichess. + Pro přečtení klikněte zde Omlouváme se :( Museli jsme tě odpojit na chvíli. Proč? @@ -1045,6 +1057,8 @@ Nechte toto pole prázdné, pokud chcete začínat z běžného základního pos Prohodit strany Uzavřením vašeho účtu stáhnete vaše odvolání Naše tipy pro organizování akcí + Pokyny + Ukaž mi všechno Lichess je bezplatný a zcela svobodný/nezávislý softvér s otevřeným zdrojovým kódem. Veškeré provozní náklady, vývoj a obsah jsou financovány výhradně z příspěvků uživatelů. diff --git a/translation/dest/site/it-IT.xml b/translation/dest/site/it-IT.xml index b822f336120bc..3b350ce684c9c 100644 --- a/translation/dest/site/it-IT.xml +++ b/translation/dest/site/it-IT.xml @@ -419,6 +419,7 @@ analizzarla con il computer, commentarla in chat, e condividerla tramite un indi Il Nero dà matto in una mossa Riprova Riconnessione + Non in linea %s amico online %s amici online diff --git a/translation/dest/site/ja-JP.xml b/translation/dest/site/ja-JP.xml index f02b38c35eeb4..2096fb57d2008 100644 --- a/translation/dest/site/ja-JP.xml +++ b/translation/dest/site/ja-JP.xml @@ -390,6 +390,7 @@ 黒 1 手でチェックメイト もう一度 再接続 + オフライン %s 人の友達が接続中 diff --git a/translation/dest/site/ko-KR.xml b/translation/dest/site/ko-KR.xml index c25ff8cdb6194..7882b0e61dfd7 100644 --- a/translation/dest/site/ko-KR.xml +++ b/translation/dest/site/ko-KR.xml @@ -387,6 +387,7 @@ 흑이 한 수 만에 체크메이트하기 재시도 연결 재시도 중 + 오프라인 %s명의 친구들이 접속중 diff --git a/translation/dest/study/it-IT.xml b/translation/dest/study/it-IT.xml index c1e84dbdb0cc5..b13ed55e1ff6f 100644 --- a/translation/dest/study/it-IT.xml +++ b/translation/dest/study/it-IT.xml @@ -53,6 +53,7 @@ Tutti i membri in SYNC rimangono sulla stessa posizione Condividi le modifiche con gli spettatori e salvale sul server In corso + Barre di valutazione Primo Precedente Successivo @@ -84,7 +85,7 @@ Commento del capitolo Salva capitolo Cancella annotazioni - Elimina le varianti + Elimina le varianti Elimina capitolo Vuoi davvero eliminare questo capitolo? Sarà perso per sempre! Cancellare tutti i commenti, le annotazioni e i disegni in questo capitolo? diff --git a/translation/dest/study/ko-KR.xml b/translation/dest/study/ko-KR.xml index 7d5f0c003b338..10b9ee91ac3f7 100644 --- a/translation/dest/study/ko-KR.xml +++ b/translation/dest/study/ko-KR.xml @@ -50,6 +50,7 @@ 동기화된 모든 멤버들은 같은 포지션을 공유합니다 관전자와 변경 사항을 공유하고 서버에 저장 플레이중 + 평가 막대 처음 이전 다음 @@ -81,7 +82,7 @@ 챕터 댓글 고정하기 챕터 저장 주석 지우기 - 파생 초기화 + 파생 초기화 챕터 지우기 이 챕터를 지울까요? 되돌릴 수 없습니다! 이 챕터의 모든 코멘트와 기호를 지울까요? diff --git a/translation/dest/tfa/cs-CZ.xml b/translation/dest/tfa/cs-CZ.xml index 2c3c3e7c6b3f6..b39666b00be21 100644 --- a/translation/dest/tfa/cs-CZ.xml +++ b/translation/dest/tfa/cs-CZ.xml @@ -2,13 +2,16 @@ Dvoufázové ověření Dvoufázové ověření vašeho účtu přidává další vrstvu zabezpečení. + Pořiďte si aplikaci pro dvoufaktorové ověřování. Doporučujeme následující aplikace: Naskenujte QR kód pomocí aplikace. Zadejte své heslo a ověřovací kód vygenerovaný aplikací pro dokončení nastavení. Při každém přihlášení budete potřebovat nový ověřovací kód. Pokud nemůžete naskenovat kód, zadejte %s do vaší aplikace. Ověřovací kód + Poznámka: Pokud ztratíte přístup ke kódům dvoufaktorového ověřování, můžete provést %s prostřednictvím e-mailu. Povolit dvoufázové ověřování Zakázat dvoufázové ověření Dvoufázové ověřování zapnuto + K vypnutí dvoufaktorového ověřování potřebujete heslo a ověřovací kód z ověřovací aplikace. Otevřete aplikaci pro dvoufázové ověřování na vašem zařízení a najděte svůj ověřovací kód. Pro zabezpečení vašeho účtu si zapněte dvoufázové ověření na https://lichess.org/account/twofactor. Tuto zprávu jste obdrželi protože zastaváte speciální funkce jako je vedoucí týmu,coach, učitel nebo streamer diff --git a/translation/dest/timeago/cs-CZ.xml b/translation/dest/timeago/cs-CZ.xml index db01efe83ad7c..b825d03868812 100644 --- a/translation/dest/timeago/cs-CZ.xml +++ b/translation/dest/timeago/cs-CZ.xml @@ -80,4 +80,17 @@ před %s lety před %s lety + + Zbývá %s minuta + Zbývají %s minuty + Zbývá %s minut + Zbývá %s minut + + + Zbývá %s hodina + Zbývají %s hodiny + Zbývá %s hodin + Zbývá %s hodin + + dokončeno diff --git a/translation/dest/ublog/cs-CZ.xml b/translation/dest/ublog/cs-CZ.xml index 2b559e54f8b8f..766938f256e75 100644 --- a/translation/dest/ublog/cs-CZ.xml +++ b/translation/dest/ublog/cs-CZ.xml @@ -1,5 +1,13 @@ + Komunitní blogy + Blogy přátel + Oblíbené příspěvky blogu + Témata blogů + Oficiální blog Lichess + Pokračovat ve čtení tohoto příspěvku + Příspěvky blogu Lichess v %s + Předchozí příspěvky blogu Blog hráče %s Nový příspěvek Upravit svůj příspěvek na blogu @@ -49,4 +57,5 @@ Publikuje prosím jenom svůj vlastní a bezpečný obsah. Nekopírujte obsah někoho jiného. Cokoliv nevhodného může způsobit smazání vašeho účtu. Naše jednoduché rady, jak psát skvělé příspěvky do blogu + Diskutujte o tomto příspěvku blogu ve fóru From ff5fc69a4d5cded61cb8461d6eea7fe2f5dd69ae Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 11 Feb 2024 08:46:07 +0100 Subject: [PATCH 04/39] remove prismic dependency --- app/views/cms.scala | 2 +- app/views/site/page.scala | 1 - app/views/site/variant.scala | 5 +- build.sbt | 4 +- conf/base.conf | 6 - modules/api/src/main/Cli.scala | 9 +- modules/api/src/main/Env.scala | 3 - modules/api/src/main/PrismicExport.scala | 269 ------------------- modules/blog/src/main/BlogApi.scala | 154 ----------- modules/blog/src/main/BlogPost.scala | 15 -- modules/blog/src/main/BlogTransform.scala | 38 --- modules/blog/src/main/Env.scala | 14 +- modules/blog/src/main/Notifier.scala | 20 -- modules/blog/src/main/PrismicPaginator.scala | 16 -- modules/blog/src/main/Youtube.scala | 40 --- project/Dependencies.scala | 1 - 16 files changed, 6 insertions(+), 591 deletions(-) delete mode 100644 modules/api/src/main/PrismicExport.scala delete mode 100644 modules/blog/src/main/BlogApi.scala delete mode 100644 modules/blog/src/main/BlogPost.scala delete mode 100644 modules/blog/src/main/BlogTransform.scala delete mode 100644 modules/blog/src/main/Notifier.scala delete mode 100644 modules/blog/src/main/PrismicPaginator.scala delete mode 100644 modules/blog/src/main/Youtube.scala diff --git a/app/views/cms.scala b/app/views/cms.scala index 8270fc3d79171..c451395078619 100644 --- a/app/views/cms.scala +++ b/app/views/cms.scala @@ -22,7 +22,7 @@ object cms: rawHtml(page.html) ) - def editButton(p: CmsPage.Render)(using Context) = + private def editButton(p: CmsPage.Render)(using Context) = isGranted(_.Pages) option a( href := routes.Cms.edit(p.id), cls := "button button-empty text", diff --git a/app/views/site/page.scala b/app/views/site/page.scala index 112029b6794e1..65561cb3cee1d 100644 --- a/app/views/site/page.scala +++ b/app/views/site/page.scala @@ -4,7 +4,6 @@ import controllers.routes import lila.app.templating.Environment.{ given, * } import lila.app.ui.ScalatagsTemplate.{ *, given } -import io.prismic.{ Document, DocumentLinkResolver } import lila.cms.CmsPage object page: diff --git a/app/views/site/variant.scala b/app/views/site/variant.scala index ef13c16f96c1d..6aa7469730a84 100644 --- a/app/views/site/variant.scala +++ b/app/views/site/variant.scala @@ -20,10 +20,7 @@ object variant: )( boxTop(h1(cls := "text", dataIcon := perfType.icon)(variant.name)), h2(cls := "headline")(variant.title), - div(cls := "body expand-text")( - views.html.cms.editButton(p), - rawHtml(lila.blog.Youtube.augmentEmbeds(p.html)) - ) + div(cls := "body expand-text")(views.html.cms.render(p)) ) def home(using PageContext) = diff --git a/build.sbt b/build.sbt index d141a63a10333..c8c798cd43a5a 100644 --- a/build.sbt +++ b/build.sbt @@ -50,7 +50,7 @@ ThisBuild / libraryDependencySchemes ++= Seq( libraryDependencies ++= akka.bundle ++ playWs.bundle ++ macwire.bundle ++ Seq( play.json, play.server, play.netty, play.logback, chess, compression, scalalib, hasher, - reactivemongo.driver, /* reactivemongo.kamon, */ maxmind, prismic, scalatags, + reactivemongo.driver, /* reactivemongo.kamon, */ maxmind, scalatags, kamon.core, kamon.influxdb, kamon.metrics, kamon.prometheus, scaffeine, caffeine, lettuce, uaparser, nettyTransport, reactivemongo.shaded ) ++ tests.bundle @@ -137,7 +137,7 @@ lazy val coordinate = module("coordinate", lazy val blog = module("blog", Seq(timeline), - Seq(prismic) ++ tests.bundle ++ reactivemongo.bundle + Seq() ++ tests.bundle ++ reactivemongo.bundle ) lazy val ublog = module("ublog", diff --git a/conf/base.conf b/conf/base.conf index f519f7f0dec3e..deeeedc77d6b5 100644 --- a/conf/base.conf +++ b/conf/base.conf @@ -102,12 +102,6 @@ pagerDuty { serviceId = "" apiKey = "" } -prismic.api_url = "https://lichess-clone.cdn.prismic.io/api" -blog { - prismic = ${prismic} - collection = blog - last_post_cache.ttl = 5 minutes -} chat { collection { chat = chat diff --git a/modules/api/src/main/Cli.scala b/modules/api/src/main/Cli.scala index af23608bb76c9..35de28e8debfd 100644 --- a/modules/api/src/main/Cli.scala +++ b/modules/api/src/main/Cli.scala @@ -17,8 +17,7 @@ final private[api] class Cli( puzzle: lila.puzzle.Env, team: lila.team.Env, notify: lila.notify.Env, - accountClosure: AccountClosure, - prismicExport: PrismicExport + accountClosure: AccountClosure )(using Executor) extends lila.common.Cli: @@ -51,12 +50,6 @@ final private[api] class Cli( fuccess: val threads = ornicar.scalalib.Jvm.threadGroups() s"${threads.map(_.total).sum} threads\n\n${threads.mkString("\n")}" - case "blog" :: "to" :: "ublog" :: Nil => - prismicExport.blogPosts() - fuccess("Converting blogs to ublogs in the background, it can take a minute or two. Check the logs.") - case "prismic" :: "to" :: "pages" :: Nil => - prismicExport.pages() - fuccess("Converting docs to pages in the background, it can take a minute or two. Check the logs.") private def run(args: List[String]): Fu[String] = { (processors lift args) | fufail("Unknown command: " + args.mkString(" ")) diff --git a/modules/api/src/main/Env.scala b/modules/api/src/main/Env.scala index 9278167b21877..cc12ee59220af 100644 --- a/modules/api/src/main/Env.scala +++ b/modules/api/src/main/Env.scala @@ -57,7 +57,6 @@ final class Env( modLogApi: lila.mod.ModlogApi, activityWriteApi: lila.activity.ActivityWriteApi, ublogApi: lila.ublog.UblogApi, - blogApi: lila.blog.BlogApi, picfitUrl: lila.memo.PicfitUrl, picfitApi: lila.memo.PicfitApi, cmsApi: lila.cms.CmsApi, @@ -117,8 +116,6 @@ final class Env( private lazy val pagerDuty = wire[PagerDuty] - private lazy val prismicExport = wire[PrismicExport] - import lila.cms.CmsPage def cmsRender(key: CmsPage.Key)(using ctx: Context): Fu[Option[CmsPage.Render]] = cmsApi.render(key)(ctx.req, ctx.user.flatMap(_.lang)) diff --git a/modules/api/src/main/PrismicExport.scala b/modules/api/src/main/PrismicExport.scala deleted file mode 100644 index eae6b391cbecb..0000000000000 --- a/modules/api/src/main/PrismicExport.scala +++ /dev/null @@ -1,269 +0,0 @@ -package lila.api - -import io.prismic.{ Api as PrismicApi, * } -import io.prismic.DocumentLinkResolver -import io.prismic.Fragment.StructuredText -import play.api.libs.ws.JsonBodyWritables.* -import play.api.libs.ws.{ StandaloneWSClient, StandaloneWSResponse } -import play.api.mvc.MultipartFormData -import akka.stream.scaladsl.* -import akka.util.ByteString - -import lila.common.config.MaxPerPage -import lila.blog.BlogPost -import lila.ublog.{ UblogPost, UblogBlog, UblogImage, UblogPostId } -import lila.memo.{ PicfitApi, PicfitUrl, PicfitImage } -import lila.user.User.lichessId -import lila.db.dsl.* -import lila.cms.CmsPage -import chess.variant.Variant - -final private class PrismicExport( - ublogApi: lila.ublog.UblogApi, - blogApi: lila.blog.BlogApi, - cmsApi: lila.cms.CmsApi, - picfitApi: PicfitApi, - picfitUrl: PicfitUrl, - ws: StandaloneWSClient -)(using Executor, akka.stream.Materializer): - - private given StandaloneWSClient = ws - - def blogPosts(): Funit = for - ctx <- blogApi.context - prismic <- blogApi.prismicApi - _ <- - blogApi - .recentStream(ctx) - .zipWithIndex - .map: (p, i) => - logger.info(s"$i ${p.date.so(_.toString)} ${~p.title}") - p - .mapAsync(1)(convert(ctx.api)) - .runWith(Sink.ignore) - yield () - - def pages(): Funit = for - _ <- variants() - prismic <- blogApi.prismicApi - bookmarks = prismic.bookmarks.toVector - _ <- Source(bookmarks).zipWithIndex - .map: (bm, i) => - logger.info(s"${i + 1}/${bookmarks.size} $bm") - bm - .mapAsync(1)(convertBookmark(prismic)) - .runWith(Sink.ignore) - .void - yield () - - private def variants(): Funit = for - prismic <- blogApi.prismicApi - _ <- Source(Variant.list.all.filter(_.exotic)).zipWithIndex - .map: (v, i) => - logger.info(s"${i + 1} ${v.name}") - v - .mapAsync(1)(convertVariant(prismic)) - .runWith(Sink.ignore) - .void - yield () - - private def convertVariant(prismic: PrismicApi)(variant: Variant): Fu[Boolean] = - val key = CmsPage.Key(s"variant-${variant.key}") - val language = lila.i18n.defaultLanguage - val pageId = CmsPage.Id.random - val video = variant.key.value match - case "racingKings" => "https://www.youtube.com/watch?v=GBUylnvSRYo\n" - case "crazyhouse" => "https://www.youtube.com/watch?v=VhZEc73HaYw\n" - case "chess960" => "https://www.youtube.com/watch?v=fUypgJQy7O8\n" - case _ => "" - cmsApi - .get(key, language) - .flatMap: page => - !page.isDefined so - prismic - .forms("variant") - .query(s"""[[:d = at(my.variant.key, "${variant.key}")]]""") - .ref(prismic.master.ref) - .submit() - .map(_.results.headOption) - .flatMap: - case None => - logger.error(s"Can't find prismic document for variant ${variant.key}") - fuccess(true) - case Some(doc) => - transferMarkdownImages(doc, pageId).flatMap: doc => - cmsApi create CmsPage( - id = pageId, - key = key, - title = doc.getText("variant.title") | pageId.value, - markdown = htmlToMarkdown: - val html = ~doc.getHtml("variant.content", linkResolver(prismic)) - lila.blog.BlogTransform.markdown: - Html(video + html) - , - language = language, - live = true, - canonicalPath = s"/variant/${variant.key}".some, - by = lichessId, - at = nowInstant - ) inject true - - private val bookmarksPaths = Map( - "tos" -> "/terms-of-service", - "how-to-cheat" -> "/how-to-cheat", - "help" -> "/help/contribute", - "master" -> "/help/master", - "source" -> "/source" - ) - - private def convertBookmark(prismic: PrismicApi)(bm: (String, String)): Fu[Boolean] = - val key = CmsPage.Key(bm._1) - val language = lila.i18n.defaultLanguage - val pageId = CmsPage.Id.random - cmsApi - .get(key, language) - .flatMap: page => - !page.isDefined so prismic - .forms("everything") - .query(s"""[[:d = at(document.id, "${bm._2}")]]""") - .ref(prismic.master.ref) - .submit() - .dmap(_.results.headOption) - .flatMap: - case None => - logger.error(s"Can't find prismic document ${bm._2} for bookmark ${bm._1}") - fuccess(true) - case Some(doc) => - transferMarkdownImages(doc, pageId).flatMap: doc => - cmsApi create CmsPage( - id = pageId, - key = key, - title = doc.getText("doc.title") | pageId.value, - markdown = htmlToMarkdown: - lila.blog.BlogTransform.markdown: - Html(~doc.getHtml("doc.content", linkResolver(prismic))) - , - language = language, - live = true, - canonicalPath = bookmarksPaths.get(key.value), - by = lichessId, - at = nowInstant - ) inject true - - import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter - private val htmlConverter: FlexmarkHtmlConverter = FlexmarkHtmlConverter.builder.build - - private def htmlToMarkdown(html: Html) = Markdown: - htmlConverter - .convert(html.value) - .replace("""
""", "") - .replaceAllIn("""<(https?://[^>]+)>""".r, "$1") - - private def uPostId(p: BlogPost) = UblogPostId(p.id take 8) - - private def uploadImage(fullUrl: String, rel: String): Fu[Option[PicfitImage]] = - val url = - if fullUrl.contains("images.prismic.io") - then fullUrl.replaceAllIn("""^([^\?]+).*$""".r, "$1") - else fullUrl - ws.url(url).stream() flatMap: - case res if res.status != 200 => - logger.error: - s"Can't download image $url for $rel: ${res.status} ${res.statusText}" - fuccess(none) - case res => - val source: Source[ByteString, ?] = res.bodyAsSource - val filename = url.split('/').last.takeWhile(_ != '?') - val part = MultipartFormData.FilePart( - key = "image", - filename = filename, - contentType = Option(if filename.endsWith(".png") then "image/png" else "image/jpeg"), - ref = source - ) - logger.debug(s"$rel $url > $filename") - picfitApi.uploadSource(rel, part, lichessId).map(_.some) - - private def transferMainImage(post: BlogPost): Fu[Option[UblogImage]] = - post - .copy(imgSize = "main") - .imageObj - .so: img => - uploadImage(img.url, s"ublog:${uPostId(post)}") map2: pfi => - UblogImage(id = pfi.id, alt = img.alt, credit = none) - - private def transferMarkdownImages(doc: Document, pageId: CmsPage.Id): Fu[Document] = - doc.get("doc.content") match - case Some(StructuredText(blocks)) => - blocks - .traverse: - case i: StructuredText.Block.Image => - uploadImage(i.url, s"cmsPage:$pageId:${ornicar.scalalib.ThreadLocalRandom.nextString(12)}") - .map: - _.fold(i): pfi => - i.copy(view = i.view.copy(url = picfitUrl.resize(pfi.id, picfitApi.bodyImage.sizePx))) - case b => fuccess(b) - .map: blocks => - doc.copy(fragments = doc.fragments + ("doc.content" -> StructuredText(blocks))) - case _ => fuccess(doc) - - private def transferMarkdownImages(post: BlogPost): Fu[BlogPost] = post.get("blog.body") match - case Some(StructuredText(blocks)) => - blocks - .traverse: - case i: StructuredText.Block.Image => - uploadImage(i.url, s"ublog:${uPostId(post)}:${ornicar.scalalib.ThreadLocalRandom.nextString(12)}") - .map: - _.fold(i): pfi => - i.copy(view = i.view.copy(url = picfitUrl.resize(pfi.id, picfitApi.bodyImage.sizePx))) - case b => fuccess(b) - .map: blocks => - post.copy(doc = post.doc.copy(fragments = post.fragments + ("blog.body" -> StructuredText(blocks)))) - case _ => fuccess(post) - - private def convert(prismic: PrismicApi)(p: BlogPost): Funit = for - prev <- ublogApi.getByPrismicId(p.id) - _ <- prev.so(ublogApi.delete) - mainImage <- transferMainImage(p) - post <- transferMarkdownImages(p) - html = Html - .from(post.getHtml("blog.body", linkResolver(prismic))) - .map(lila.blog.Youtube.augmentEmbeds) - .map(lila.blog.BlogTransform.removeProtocol) - .map(lila.blog.BlogTransform.markdown.apply) - .map(blogApi.expand) - created = post.date match - case Some(d) => d.atStartOfDay.instant - case None => - logger.error(s"Blog post ${post.id} ${~post.title} has no date") - nowInstant - upost = UblogPost( - id = uPostId(p), - blog = UblogBlog.Id.User(lichessId), - title = ~post.title, - intro = post.shortlede, - markdown = html.fold(Markdown(""))(htmlToMarkdown), - language = lila.i18n.defaultLanguage, - topics = Nil, - image = mainImage, - live = true, - discuss = Option(false), - created = UblogPost.Recorded(lichessId, created), - updated = none, - lived = UblogPost.Recorded(lichessId, created).some, - likes = UblogPost.Likes(1), - views = UblogPost.Views(0), - rankAdjustDays = none, - pinned = none - ) - extra = $doc( - "author" -> post.author, - "category" -> post.category, - "forKids" -> post.forKids - ) - _ <- ublogApi.migrateFromBlog(upost, p.id, extra) - yield () - - private type MakeLinkResolver = PrismicApi => DocumentLinkResolver - private given linkResolver: MakeLinkResolver = prismicApi => - DocumentLinkResolver(prismicApi): (link, _) => - s"/blog/${link.id}/${link.slug}" diff --git a/modules/blog/src/main/BlogApi.scala b/modules/blog/src/main/BlogApi.scala deleted file mode 100644 index e997532bbfd14..0000000000000 --- a/modules/blog/src/main/BlogApi.scala +++ /dev/null @@ -1,154 +0,0 @@ -package lila.blog - -import scala.util.Try -import io.prismic.* -import play.api.mvc.RequestHeader -import play.api.libs.ws.StandaloneWSClient -import java.util.regex.{ Pattern, Matcher } - -import lila.common.{ Bus, LpvEmbed } -import lila.common.config.{ BaseUrl, MaxPerPage } -import lila.common.paginator.* -import lila.hub.actorApi.lpv.AllPgnsFromText -import chess.format.pgn.PgnStr -import akka.stream.Materializer - -final class BlogApi( - config: BlogConfig, - baseUrl: BaseUrl, - cacheApi: lila.memo.CacheApi -)(using Executor, Scheduler, StandaloneWSClient, Materializer): - - import BlogApi.looksLikePrismicId - import config.collection - - def recent( - api: Api, - page: Int, - maxPerPage: MaxPerPage, - ref: Option[String] - ): Fu[Option[Paginator[BlogPost]]] = Future.fromTry { - Try { - api - .forms(collection) - .ref(ref | api.master.ref) - .orderings(s"[my.$collection.date desc]") - .pageSize(maxPerPage.value) - .page(page) - .submit() - .fold(_ => none, some) - .map2 { PrismicPaginator(_, page, maxPerPage) } - .map2 { _.mapResults(BlogPost(_)) } - }.recover { case _: NoSuchElementException => - fuccess(none) - } - }.flatten - - def recent( - prismic: BlogApi.Context, - page: Int, - maxPerPage: MaxPerPage - ): Fu[Option[Paginator[BlogPost]]] = - recent(prismic.api, page, maxPerPage, prismic.ref.some) - - def recentStream(prismic: BlogApi.Context): akka.stream.scaladsl.Source[BlogPost, ?] = - Paginator.stream: page => - recent(prismic, page, MaxPerPage(20)).map(_ | Paginator.empty) - - def one(api: Api, ref: Option[String], id: String): Fu[Option[BlogPost]] = - looksLikePrismicId(id) so api - .forms(collection) - .query(s"""[[:d = at(document.id, "$id")]]""") - .ref(ref | api.master.ref) - .submit() - .map(_.results.headOption.map(BlogPost(_))) - - def one(prismic: BlogApi.Context, id: String): Fu[Option[BlogPost]] = - one(prismic.api, prismic.ref.some, id).flatMapz { doc => - doc.getHtml("blog.body", prismic.linkResolver) match - case Some(html) => - Bus - .ask("lpv")(AllPgnsFromText(html, _)) - .map(pgnCache.putAll) inject doc.some - case _ => fuccess(doc.some) - } - - def context(using linkResolver: Api => DocumentLinkResolver): Fu[BlogApi.Context] = - prismicApi map { api => - val ref = resolveRef(api)(none) - BlogApi.Context(api, api.master.ref, linkResolver(api)) - } - - def masterContext(using - linkResolver: Api => DocumentLinkResolver - ): Fu[BlogApi.Context] = - prismicApi.map: api => - BlogApi.Context(api, api.master.ref, linkResolver(api)) - - def expand(html: Html) = html.map(expandGames).map(expandChapters) - - private def expandGames(html: String) = expandGameRegex.replaceAllIn( - html, - m => - pgnCache.getIfPresent(m.group(1)) match - case Some(LpvEmbed.PublicPgn(pgn)) => - val esc = Matcher.quoteReplacement: - lila.common.base.StringUtils.escapeHtmlRaw(pgn.value) - val color = Option(m.group(2)).getOrElse("white") - val ply = Option(m.group(3)).getOrElse("last") - s"""
""" - case _ => m.matched - ) - - private def expandChapters(html: String) = expandChapterRegex.replaceAllIn( - html, - m => - pgnCache.getIfPresent(m.group(1)) match - case Some(LpvEmbed.PublicPgn(pgn)) => - val esc = Matcher.quoteReplacement: - lila.common.base.StringUtils.escapeHtmlRaw(pgn.value) - val ply = Option(m.group(2)).getOrElse("last") - s"""
""" - case _ => m.matched - ) - - // match the entire tag with scheme & domain. href value should be identical to inner text - private val expandGameRegex = - val quotedBaseUrl = Pattern.quote(baseUrl.value) - val gameUrlRegex = quotedBaseUrl + """/(\w{8})(?:/(white|black)|\w{4}|)(?:#(last|\d+))?""" - ("" + gameUrlRegex + "").r - private val expandChapterRegex = - val quotedBaseUrl = Pattern.quote(baseUrl.value) - val chapterUrlRegex = quotedBaseUrl + """/study/(?:embed/)?(?:\w{8})/(\w{8})(?:#(last|\d+))?""" - ("" + chapterUrlRegex + "").r - - private val pgnCache = cacheApi.notLoadingSync[String, LpvEmbed](256, "prisblog.markup.pgn"): - _.expireAfterWrite(10.seconds).build() - - private def resolveRef(api: Api)(ref: Option[String]) = - ref.map(_.trim).filterNot(_.isEmpty) map { reqRef => - api.refs.values.collectFirst { - case r if r.label == reqRef => r.ref - } getOrElse reqRef - } - - def prismicApi = (new Prismic).get(config.apiUrl) - -object BlogApi: - - def extract(body: Fragment.StructuredText): String = - body.blocks - .takeWhile(_.isInstanceOf[Fragment.StructuredText.Block.Paragraph]) - .take(2) - .map { - case Fragment.StructuredText.Block.Paragraph(text, _, _) => s"

$text

" - case _ => "" - } - .mkString - - case class Context(api: Api, ref: String, linkResolver: DocumentLinkResolver): - def maybeRef = Option(ref).filterNot(_ == api.master.ref) - - private val idRegex = """^[\w-]{16}$""".r - - def looksLikePrismicId(id: String) = idRegex.matches(id) diff --git a/modules/blog/src/main/BlogPost.scala b/modules/blog/src/main/BlogPost.scala deleted file mode 100644 index 40e1edb29a880..0000000000000 --- a/modules/blog/src/main/BlogPost.scala +++ /dev/null @@ -1,15 +0,0 @@ -package lila.blog - -import java.time.LocalDate -import io.prismic.Fragment.Image.View - -case class BlogPost(doc: io.prismic.Document, coll: String = "blog", imgSize: String = "wide"): - export doc.* - def title: Option[String] = getText(s"$coll.title") - def shortlede: String = ~getText(s"$coll.shortlede") - def date: Option[LocalDate] = getDate(s"$coll.date").map(_.value) - def imageObj: Option[View] = getImage(s"$coll.image", imgSize) - def image: Option[String] = imageObj.map(_.url) - def forKids: Boolean = getText(s"$coll.kidsafe").forall(_ == "true") - def author: Option[String] = getText(s"$coll.author") - def category: Option[String] = getText(s"$coll.category") diff --git a/modules/blog/src/main/BlogTransform.scala b/modules/blog/src/main/BlogTransform.scala deleted file mode 100644 index 34b22ae5e2cd9..0000000000000 --- a/modules/blog/src/main/BlogTransform.scala +++ /dev/null @@ -1,38 +0,0 @@ -package lila.blog - -import scala.util.matching.Regex - -import lila.common.{ Markdown, MarkdownRender } - -object BlogTransform: - - private val RemoveRegex = """http://(\w{2}\.)?+lichess\.org""".r - def removeProtocol(html: Html) = Html(RemoveRegex.replaceAllIn(html.value, _ => "//lichess.org")) - - private val AddRegex = """(https?+:)?+(//)?+(\w{2}\.)?+lichess\.org""".r - def addProtocol(html: Html) = Html(AddRegex.replaceAllIn(html.value, _ => "https://lichess.org")) - - object markdown: - - private val renderer = MarkdownRender(table = true) - - // hash code collisions can't be a vector of attack here, - // since only lichess team members can write these blog posts - private val cache = lila.memo.CacheApi.scaffeineNoScheduler - .expireAfterAccess(20 minutes) - .maximumSize(64) - .build[Int, Html]() - - private val PreRegex = """
markdown(.+)
""".r - - def apply(html: Html): Html = Html: - PreRegex.replaceAllIn( - html.value, - m => - val markdown = m group 1 - val markup = cache.get( - markdown.hashCode, - _ => renderer("prismic")(Markdown(markdown.replace("
", "\n"))) - ) - Regex.quoteReplacement(markup.value) - ) diff --git a/modules/blog/src/main/Env.scala b/modules/blog/src/main/Env.scala index 5fbe1428c4225..0801129538eb1 100644 --- a/modules/blog/src/main/Env.scala +++ b/modules/blog/src/main/Env.scala @@ -5,12 +5,6 @@ import lila.common.autoconfig.* import play.api.Configuration import lila.common.config.CollName -private class BlogConfig( - @ConfigName("prismic.api_url") val apiUrl: String, - val collection: String, - @ConfigName("last_post_cache.ttl") val lastPostTtl: FiniteDuration -) - @Module final class Env( appConfig: Configuration, @@ -18,13 +12,7 @@ final class Env( cacheApi: lila.memo.CacheApi, baseUrl: lila.common.config.BaseUrl, db: lila.db.Db -)(using Executor, Scheduler, play.api.libs.ws.StandaloneWSClient, akka.stream.Materializer): - - private val config = appConfig.get[BlogConfig]("blog")(AutoConfig.loader) - - lazy val api = wire[BlogApi] - - private lazy val notifier = wire[Notifier] +)(using Executor, Scheduler): private val feedColl = db(CollName("daily_feed")) val dailyFeed = wire[DailyFeed] diff --git a/modules/blog/src/main/Notifier.scala b/modules/blog/src/main/Notifier.scala deleted file mode 100644 index 741d9d24f8676..0000000000000 --- a/modules/blog/src/main/Notifier.scala +++ /dev/null @@ -1,20 +0,0 @@ -package lila.blog - -import lila.timeline.EntryApi - -final private[blog] class Notifier( - blogApi: BlogApi, - timelineApi: EntryApi -)(using Executor): - - def apply(id: String): Funit = - blogApi.prismicApi flatMap { prismicApi => - blogApi.one(prismicApi, none, id) orFail - s"No such document: $id" flatMap doSend - } - - private def doSend(post: BlogPost): Funit = - post.getText("blog.title") so { title => - timelineApi.broadcast.insert: - lila.hub.actorApi.timeline.BlogPost(id = post.id, slug = post.slug, title = title) - } diff --git a/modules/blog/src/main/PrismicPaginator.scala b/modules/blog/src/main/PrismicPaginator.scala deleted file mode 100644 index 69f3ccb0f8419..0000000000000 --- a/modules/blog/src/main/PrismicPaginator.scala +++ /dev/null @@ -1,16 +0,0 @@ -package lila.blog - -import io.prismic.* - -import lila.common.config.MaxPerPage -import lila.common.paginator.* - -private object PrismicPaginator: - - def apply(response: Response, page: Int, maxPerPage: MaxPerPage): Paginator[Document] = - Paginator.fromResults( - currentPageResults = response.results, - nbResults = response.totalResultsSize, - currentPage = page, - maxPerPage = maxPerPage - ) diff --git a/modules/blog/src/main/Youtube.scala b/modules/blog/src/main/Youtube.scala deleted file mode 100644 index 38716ccc1981f..0000000000000 --- a/modules/blog/src/main/Youtube.scala +++ /dev/null @@ -1,40 +0,0 @@ -package lila.blog - -object Youtube: - - def augmentEmbeds(html: Html): Html = - addCredentialless(fixStartTimes(html)) - - private val IframeRegex = """(]*)>""".r - private def addCredentialless(html: Html) = Html: - IframeRegex.replaceAllIn(html.value, """$1 credentialless>""") - - private val TimeMarkerRegex = """youtube\.com/watch\?v=[\w-]++\#t=([^"]++)[^?]++\?feature=oembed""".r - private val HourMinSecRegex = """(\d++)h(\d++)m(\d++)s""".r - private val MinSecRegex = """(\d++)m(\d++)s""".r - private val SecRegex = """(\d++)s""".r - /*
- *
- */ - private def fixStartTimes(html: Html) = Html: - TimeMarkerRegex.replaceAllIn( - html.value, - m => - val orig = m group 0 - parseSeconds(m group 1).fold(orig)(seconds => s"$orig&start=$seconds") - ) - - private def parseSeconds(text: String) = text match - case HourMinSecRegex(hourS, minS, secS) => - for - hour <- hourS.toIntOption - min <- minS.toIntOption - sec <- secS.toIntOption - yield 3600 * hour + 60 * min + sec - case MinSecRegex(minS, secS) => - for - min <- minS.toIntOption - sec <- secS.toIntOption - yield 60 * min + sec - case SecRegex(secS) => secS.toIntOption - case _ => None diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 08ba4ee3355a3..8c2aabff5c6ce 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -20,7 +20,6 @@ object Dependencies { val chess = "org.lichess" %% "scalachess" % "15.7.7" val compression = "org.lichess" %% "compression" % "1.10" val maxmind = "com.maxmind.geoip2" % "geoip2" % "4.0.1" - val prismic = "io.prismic" %% "scala-kit" % "1.2.19_lila-3.2" val caffeine = "com.github.ben-manes.caffeine" % "caffeine" % "3.1.8" % "compile" val scaffeine = "com.github.blemale" %% "scaffeine" % "5.2.1" % "compile" val googleOAuth = "com.google.auth" % "google-auth-library-oauth2-http" % "1.22.0" From 0155f35ba9578397e7e5125cc238062abd4c1a4c Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 11 Feb 2024 09:12:29 +0100 Subject: [PATCH 05/39] give the feed its own module, remove blog module --- app/Env.scala | 4 +- app/LilaComponents.scala | 2 +- app/controllers/DailyFeed.scala | 63 ------------------- app/controllers/Feed.scala | 61 ++++++++++++++++++ app/mashup/Preload.scala | 4 +- app/views/base/layout.scala | 2 +- app/views/{dailyFeed.scala => feed.scala} | 32 +++++----- app/views/lobby/home.scala | 2 +- app/views/site/page.scala | 2 +- build.sbt | 8 +-- conf/routes | 14 ++--- modules/blog/src/main/Env.scala | 21 ------- modules/blog/src/main/package.scala | 9 --- modules/feed/src/main/Env.scala | 15 +++++ .../src/main/Feed.scala} | 16 +++-- modules/feed/src/main/package.scala | 3 + modules/security/src/main/Permission.scala | 6 +- 17 files changed, 124 insertions(+), 140 deletions(-) delete mode 100644 app/controllers/DailyFeed.scala create mode 100644 app/controllers/Feed.scala rename app/views/{dailyFeed.scala => feed.scala} (86%) delete mode 100644 modules/blog/src/main/Env.scala delete mode 100644 modules/blog/src/main/package.scala create mode 100644 modules/feed/src/main/Env.scala rename modules/{blog/src/main/DailyFeed.scala => feed/src/main/Feed.scala} (91%) create mode 100644 modules/feed/src/main/package.scala diff --git a/app/Env.scala b/app/Env.scala index 95c093429ed1b..39cedb2dbd8c1 100644 --- a/app/Env.scala +++ b/app/Env.scala @@ -47,7 +47,7 @@ final class Env( val puzzle: lila.puzzle.Env, val coordinate: lila.coordinate.Env, val tv: lila.tv.Env, - val blog: lila.blog.Env, + val feed: lila.feed.Env, val history: lila.history.Env, val video: lila.video.Env, val playban: lila.playban.Env, @@ -211,7 +211,7 @@ final class EnvBoot( lazy val puzzle: lila.puzzle.Env = wire[lila.puzzle.Env] lazy val coordinate: lila.coordinate.Env = wire[lila.coordinate.Env] lazy val tv: lila.tv.Env = wire[lila.tv.Env] - lazy val blog: lila.blog.Env = wire[lila.blog.Env] + lazy val feed: lila.feed.Env = wire[lila.feed.Env] lazy val history: lila.history.Env = wire[lila.history.Env] lazy val video: lila.video.Env = wire[lila.video.Env] lazy val playban: lila.playban.Env = wire[lila.playban.Env] diff --git a/app/LilaComponents.scala b/app/LilaComponents.scala index 3d3a4d7e8bc35..9110f5387826c 100644 --- a/app/LilaComponents.scala +++ b/app/LilaComponents.scala @@ -99,7 +99,7 @@ final class LilaComponents( lazy val api: Api = wire[Api] lazy val appealC: appeal.Appeal = wire[appeal.Appeal] lazy val auth: Auth = wire[Auth] - lazy val dailyFeed: DailyFeed = wire[DailyFeed] + lazy val feed: Feed = wire[Feed] lazy val playApi: PlayApi = wire[PlayApi] lazy val challenge: Challenge = wire[Challenge] lazy val coach: Coach = wire[Coach] diff --git a/app/controllers/DailyFeed.scala b/app/controllers/DailyFeed.scala deleted file mode 100644 index 1c9c87156c733..0000000000000 --- a/app/controllers/DailyFeed.scala +++ /dev/null @@ -1,63 +0,0 @@ -package controllers - -import play.api.mvc.* -import views.* -import java.time.LocalDate - -import lila.app.{ given, * } -import lila.common.config.Max -import lila.blog.DailyFeed.Update - -final class DailyFeed(env: Env) extends LilaController(env): - - def api = env.blog.dailyFeed - def paginator = env.blog.dailyFeedPaginator - - def index(page: Int) = Open: ctx ?=> - Reasonable(page): - for - updates <- paginator.recent(isGrantedOpt(_.DailyFeed), page) - renderedPage <- renderPage(html.dailyFeed.index(updates)) - yield Ok(renderedPage) - - def createForm = Secure(_.DailyFeed) { _ ?=> _ ?=> - Ok.pageAsync(html.dailyFeed.create(api.form(none))) - } - - def create = SecureBody(_.DailyFeed) { _ ?=> _ ?=> - api - .form(none) - .bindFromRequest() - .fold( - err => BadRequest.pageAsync(html.dailyFeed.create(err)), - data => - val up = data toUpdate none - api.set(up) inject Redirect(routes.DailyFeed.edit(up.id)).flashSuccess - ) - } - - def edit(id: String) = Secure(_.DailyFeed) { _ ?=> _ ?=> - Found(api.get(id)): up => - Ok.pageAsync(html.dailyFeed.edit(api.form(up.some), up)) - } - - def update(id: String) = SecureBody(_.DailyFeed) { _ ?=> _ ?=> - Found(api.get(id)): from => - api - .form(from.some) - .bindFromRequest() - .fold( - err => BadRequest.pageAsync(html.dailyFeed.edit(err, from)), - data => - api.set(data toUpdate from.id.some) inject Redirect(routes.DailyFeed.edit(from.id)).flashSuccess - ) - } - - def delete(id: String) = Secure(_.DailyFeed) { _ ?=> _ ?=> - Found(api.get(id)): up => - api.delete(up.id) inject Redirect(routes.DailyFeed.index(1)).flashSuccess - } - - def atom = Anon: - api.recentPublished map: ups => - Ok(html.dailyFeed.atom(ups)) as XML diff --git a/app/controllers/Feed.scala b/app/controllers/Feed.scala new file mode 100644 index 0000000000000..d27ccf12d9fbe --- /dev/null +++ b/app/controllers/Feed.scala @@ -0,0 +1,61 @@ +package controllers + +import play.api.mvc.* +import views.* +import java.time.LocalDate + +import lila.app.{ given, * } +import lila.common.config.Max +import lila.feed.Feed.Update + +final class Feed(env: Env) extends LilaController(env): + + def api = env.feed.api + + def index(page: Int) = Open: ctx ?=> + Reasonable(page): + for + updates <- env.feed.paginator.recent(isGrantedOpt(_.Feed), page) + renderedPage <- renderPage(html.feed.index(updates)) + yield Ok(renderedPage) + + def createForm = Secure(_.Feed) { _ ?=> _ ?=> + Ok.pageAsync(html.feed.create(api.form(none))) + } + + def create = SecureBody(_.Feed) { _ ?=> _ ?=> + api + .form(none) + .bindFromRequest() + .fold( + err => BadRequest.pageAsync(html.feed.create(err)), + data => + val up = data toUpdate none + api.set(up) inject Redirect(routes.Feed.edit(up.id)).flashSuccess + ) + } + + def edit(id: String) = Secure(_.Feed) { _ ?=> _ ?=> + Found(api.get(id)): up => + Ok.pageAsync(html.feed.edit(api.form(up.some), up)) + } + + def update(id: String) = SecureBody(_.Feed) { _ ?=> _ ?=> + Found(api.get(id)): from => + api + .form(from.some) + .bindFromRequest() + .fold( + err => BadRequest.pageAsync(html.feed.edit(err, from)), + data => api.set(data toUpdate from.id.some) inject Redirect(routes.Feed.edit(from.id)).flashSuccess + ) + } + + def delete(id: String) = Secure(_.Feed) { _ ?=> _ ?=> + Found(api.get(id)): up => + api.delete(up.id) inject Redirect(routes.Feed.index(1)).flashSuccess + } + + def atom = Anon: + api.recentPublished map: ups => + Ok(html.feed.atom(ups)) as XML diff --git a/app/mashup/Preload.scala b/app/mashup/Preload.scala index 9e78cc53055ea..26d1662940286 100644 --- a/app/mashup/Preload.scala +++ b/app/mashup/Preload.scala @@ -30,7 +30,7 @@ final class Preload( lightUserApi: LightUserApi, roundProxy: lila.round.GameProxyRepo, simulIsFeaturable: SimulIsFeaturable, - getLastUpdates: lila.blog.DailyFeed.GetLastUpdates, + getLastUpdates: lila.feed.Feed.GetLastUpdates, lastPostsCache: AsyncLoadingCache[Unit, List[UblogPost.PreviewPost]], msgApi: lila.msg.MsgApi, relayListing: lila.relay.RelayListing, @@ -148,7 +148,7 @@ object Preload: currentGame: Option[Preload.CurrentGame], isFeaturable: Simul => Boolean, blindGames: List[Pov], - lastUpdates: List[lila.blog.DailyFeed.Update], + lastUpdates: List[lila.feed.Feed.Update], ublogPosts: List[UblogPost.PreviewPost], me: Option[User.WithPerfs], hasUnreadLichessMessage: Boolean diff --git a/app/views/base/layout.scala b/app/views/base/layout.scala index 8b3c66f1db680..7369b356fa3e5 100644 --- a/app/views/base/layout.scala +++ b/app/views/base/layout.scala @@ -207,7 +207,7 @@ object layout: private def spaceless(html: String) = raw(spaceRegex.replaceAllIn(html.replace("\\n", ""), "")) private val dailyNewsAtom = link( - href := routes.DailyFeed.atom, + href := routes.Feed.atom, st.title := "Lichess Updates Feed", tpe := "application/atom+xml", rel := "alternate" diff --git a/app/views/dailyFeed.scala b/app/views/feed.scala similarity index 86% rename from app/views/dailyFeed.scala rename to app/views/feed.scala index 472c908c36fc0..64c17b0ee6cbb 100644 --- a/app/views/dailyFeed.scala +++ b/app/views/feed.scala @@ -4,12 +4,12 @@ import controllers.routes import lila.app.templating.Environment.{ given, * } import lila.app.ui.ScalatagsTemplate.{ *, given } -import lila.blog.DailyFeed.Update +import lila.feed.Feed.Update import play.api.data.Form import play.api.i18n.Lang import lila.common.paginator.Paginator -object dailyFeed: +object feed: private def layout(title: String, edit: Boolean = false)(using PageContext) = views.html.site.page.layout( @@ -25,16 +25,16 @@ object dailyFeed: boxTop( h1("Lichess updates"), div(cls := "box__top__actions")( - isGranted(_.DailyFeed) option a( - href := routes.DailyFeed.createForm, + isGranted(_.Feed) option a( + href := routes.Feed.createForm, cls := "button button-green", dataIcon := licon.PlusButton ), - views.html.site.bits.atomLink(routes.DailyFeed.atom) + views.html.site.bits.atomLink(routes.Feed.atom) ) ), standardFlash, - updates(ups, editor = isGranted(_.DailyFeed)) + updates(ups, editor = isGranted(_.Feed)) ) def updates(ups: Paginator[Update], editor: Boolean)(using Context) = @@ -49,7 +49,7 @@ object dailyFeed: h2(a(href := s"#${update.id}")(absClientInstant(update.at))), editor option frag( a( - href := routes.DailyFeed.edit(update.id), + href := routes.Feed.edit(update.id), cls := "button button-green button-empty button-thin text", dataIcon := licon.Pencil ), @@ -60,7 +60,7 @@ object dailyFeed: div(cls := "daily-feed__update__markup")(rawHtml(update.rendered)) ) ), - pagerNext(ups, np => routes.DailyFeed.index(np).url) + pagerNext(ups, np => routes.Feed.index(np).url) ) val lobbyUpdates = renderCache[List[Update]](1 minute): ups => @@ -88,12 +88,12 @@ object dailyFeed: main(cls := "daily-feed page-small box box-pad")( boxTop( h1( - a(href := routes.DailyFeed.index(1))("Daily Feed"), + a(href := routes.Feed.index(1))("Daily Feed"), " • ", "New update!" ) ), - postForm(cls := "content_box_content form3", action := routes.DailyFeed.create): + postForm(cls := "content_box_content form3", action := routes.Feed.create): inForm(form) ) @@ -103,16 +103,16 @@ object dailyFeed: div(cls := "box box-pad")( boxTop( h1( - a(href := routes.DailyFeed.index(1))("Lichess update"), + a(href := routes.Feed.index(1))("Lichess update"), " • ", semanticDate(update.at) ) ), standardFlash, - postForm(cls := "content_box_content form3", action := routes.DailyFeed.update(update.id)): + postForm(cls := "content_box_content form3", action := routes.Feed.update(update.id)): inForm(form) , - postForm(action := routes.DailyFeed.delete(update.id))(cls := "daily-feed__delete"): + postForm(action := routes.Feed.delete(update.id))(cls := "daily-feed__delete"): submitButton(cls := "button button-red button-empty confirm")("Delete") ) ) @@ -152,8 +152,8 @@ object dailyFeed: import views.html.base.atom.{ atomDate, category } views.html.base.atom( elems = ups, - htmlCall = routes.DailyFeed.index(1), - atomCall = routes.DailyFeed.atom, + htmlCall = routes.Feed.index(1), + atomCall = routes.Feed.atom, title = "Lichess updates feed", updated = ups.headOption.map(_.at) ): up => @@ -163,7 +163,7 @@ object dailyFeed: link( rel := "alternate", tpe := "text/html", - href := s"$netBaseUrl${routes.DailyFeed.index(1)}#${up.id}" + href := s"$netBaseUrl${routes.Feed.index(1)}#${up.id}" ), tag("title")(up.title), tag("content")(tpe := "html")(convertToAbsoluteHrefs(up.rendered)) diff --git a/app/views/lobby/home.scala b/app/views/lobby/home.scala index da227444e27a1..525a809e295e4 100644 --- a/app/views/lobby/home.scala +++ b/app/views/lobby/home.scala @@ -122,7 +122,7 @@ object home: , ctx.noBot option bits.underboards(tours, simuls, leaderboard, tournamentWinners), div(cls := "lobby__feed"): - views.html.dailyFeed.lobbyUpdates(lastUpdates) + views.html.feed.lobbyUpdates(lastUpdates) , div(cls := "lobby__support")( a(href := routes.Plan.index)( diff --git a/app/views/site/page.scala b/app/views/site/page.scala index 65561cb3cee1d..330c2c9389339 100644 --- a/app/views/site/page.scala +++ b/app/views/site/page.scala @@ -206,7 +206,7 @@ $('#asset-version-message').text(lichess.info.message);""" main(cls := "page-menu")( views.html.site.bits.pageMenuSubnav( a(activeCls("about"), href := "/about")(trans.aboutX("lichess.org")), - a(activeCls("news"), href := routes.DailyFeed.index(1))("Lichess updates"), + a(activeCls("news"), href := routes.Feed.index(1))("Lichess updates"), a(activeCls("faq"), href := routes.Main.faq)(trans.faq.faqAbbreviation()), a(activeCls("contact"), href := routes.Main.contact)(trans.contact.contact()), a(activeCls("tos"), href := routes.Cms.tos)(trans.termsOfService()), diff --git a/build.sbt b/build.sbt index c8c798cd43a5a..bda9b88384b65 100644 --- a/build.sbt +++ b/build.sbt @@ -61,7 +61,7 @@ lazy val modules = Seq( gameSearch, timeline, forum, forumSearch, team, teamSearch, analyse, mod, round, pool, lobby, setup, importer, gathering, tournament, simul, relation, report, pref, - evaluation, chat, puzzle, tv, coordinate, blog, + evaluation, chat, puzzle, tv, coordinate, feed, history, video, shutup, push, appeal, mailer, playban, insight, perfStat, irc, challenge, study, studySearch, fishnet, explorer, learn, plan, @@ -135,9 +135,9 @@ lazy val coordinate = module("coordinate", reactivemongo.bundle ++ macwire.bundle ) -lazy val blog = module("blog", - Seq(timeline), - Seq() ++ tests.bundle ++ reactivemongo.bundle +lazy val feed = module("feed", + Seq(user), + reactivemongo.bundle ) lazy val ublog = module("ublog", diff --git a/conf/routes b/conf/routes index 18238ac5fc493..30b181854ebe8 100644 --- a/conf/routes +++ b/conf/routes @@ -120,13 +120,13 @@ GET /blog/community.atom controllers.Ublog.communityAtom(lang = "a GET /blog/community/$lang<[\w-]{2,6}>.atom controllers.Ublog.communityAtom(lang) GET /blog/:id/:slug controllers.Ublog.historicalBlogPost(id, slug) -GET /feed controllers.DailyFeed.index(page: Int ?= 1) -GET /feed/new controllers.DailyFeed.createForm -POST /feed/new controllers.DailyFeed.create -GET /feed/:id/edit controllers.DailyFeed.edit(id) -POST /feed/:id/edit controllers.DailyFeed.update(id) -POST /feed/:id/delete controllers.DailyFeed.delete(id) -GET /feed.atom controllers.DailyFeed.atom +GET /feed controllers.Feed.index(page: Int ?= 1) +GET /feed/new controllers.Feed.createForm +POST /feed/new controllers.Feed.create +GET /feed/:id/edit controllers.Feed.edit(id) +POST /feed/:id/edit controllers.Feed.update(id) +POST /feed/:id/delete controllers.Feed.delete(id) +GET /feed.atom controllers.Feed.atom GET /opening controllers.Opening.index(q: Option[String] ?= None) POST /opening/config/:key controllers.Opening.config(key) diff --git a/modules/blog/src/main/Env.scala b/modules/blog/src/main/Env.scala deleted file mode 100644 index 0801129538eb1..0000000000000 --- a/modules/blog/src/main/Env.scala +++ /dev/null @@ -1,21 +0,0 @@ -package lila.blog - -import com.softwaremill.macwire.* -import lila.common.autoconfig.* -import play.api.Configuration -import lila.common.config.CollName - -@Module -final class Env( - appConfig: Configuration, - timelineApi: lila.timeline.EntryApi, - cacheApi: lila.memo.CacheApi, - baseUrl: lila.common.config.BaseUrl, - db: lila.db.Db -)(using Executor, Scheduler): - - private val feedColl = db(CollName("daily_feed")) - val dailyFeed = wire[DailyFeed] - val dailyFeedPaginator = wire[DailyFeedPaginatorBuilder] - - export dailyFeed.lastUpdate diff --git a/modules/blog/src/main/package.scala b/modules/blog/src/main/package.scala deleted file mode 100644 index 42ec9ccd7229b..0000000000000 --- a/modules/blog/src/main/package.scala +++ /dev/null @@ -1,9 +0,0 @@ -package lila.blog - -export lila.Lila.{ *, given } - -private val logger = lila.log("blog") - -lazy val thisYear = nowDateTime.getYear - -lazy val allYears = (thisYear to 2014 by -1).toList diff --git a/modules/feed/src/main/Env.scala b/modules/feed/src/main/Env.scala new file mode 100644 index 0000000000000..cb3cacfe6f225 --- /dev/null +++ b/modules/feed/src/main/Env.scala @@ -0,0 +1,15 @@ +package lila.feed + +import com.softwaremill.macwire.* +import lila.common.autoconfig.* +import play.api.Configuration +import lila.common.config.CollName + +@Module +final class Env(cacheApi: lila.memo.CacheApi, db: lila.db.Db)(using Executor): + + private val feedColl = db(CollName("daily_feed")) + val api = wire[FeedApi] + val paginator = wire[FeedPaginatorBuilder] + + export api.lastUpdate diff --git a/modules/blog/src/main/DailyFeed.scala b/modules/feed/src/main/Feed.scala similarity index 91% rename from modules/blog/src/main/DailyFeed.scala rename to modules/feed/src/main/Feed.scala index b1ac1f7435edd..8a013bf9ef3cd 100644 --- a/modules/blog/src/main/DailyFeed.scala +++ b/modules/feed/src/main/Feed.scala @@ -1,4 +1,4 @@ -package lila.blog +package lila.feed import reactivemongo.api.bson.* import reactivemongo.api.bson.Macros.Annotations.Key @@ -11,7 +11,7 @@ import lila.common.config.{ Max, MaxPerPage } import play.api.data.Form import lila.user.Me -object DailyFeed: +object Feed: type ID = String @@ -37,9 +37,9 @@ object DailyFeed: import ornicar.scalalib.ThreadLocalRandom def makeId = ThreadLocalRandom nextString 6 -final class DailyFeed(coll: Coll, cacheApi: CacheApi)(using Executor): +final class FeedApi(coll: Coll, cacheApi: CacheApi)(using Executor): - import DailyFeed.* + import Feed.* private val max = Max(50) @@ -57,7 +57,7 @@ final class DailyFeed(coll: Coll, cacheApi: CacheApi)(using Executor): def clear() = store.underlying.synchronous.invalidateAll() store.get({}) // populate lastUpdate - def lastUpdate: DailyFeed.GetLastUpdates = () => mutableLastUpdates + def lastUpdate: Feed.GetLastUpdates = () => mutableLastUpdates store.get({}) // populate lastUpdate export cache.lastUpdate @@ -88,10 +88,8 @@ final class DailyFeed(coll: Coll, cacheApi: CacheApi)(using Executor): )(UpdateData.apply)(unapply) from.fold(form)(u => form.fill(UpdateData(u.content, u.public, u.at, u.flair))) -final class DailyFeedPaginatorBuilder( - coll: Coll -)(using Executor): - import DailyFeed.* +final class FeedPaginatorBuilder(coll: Coll)(using Executor): + import Feed.* def recent(includeAll: Boolean, page: Int): Fu[Paginator[Update]] = Paginator( diff --git a/modules/feed/src/main/package.scala b/modules/feed/src/main/package.scala new file mode 100644 index 0000000000000..190e8ea85a5d5 --- /dev/null +++ b/modules/feed/src/main/package.scala @@ -0,0 +1,3 @@ +package lila.feed + +export lila.Lila.{ *, given } diff --git a/modules/security/src/main/Permission.scala b/modules/security/src/main/Permission.scala index 2e7ae504f109b..3803480e03c69 100644 --- a/modules/security/src/main/Permission.scala +++ b/modules/security/src/main/Permission.scala @@ -71,7 +71,7 @@ object Permission: case object Streamers extends Permission("STREAMERS", "Manage streamers") case object Verified extends Permission("VERIFIED", "Verified badge") case object Pages extends Permission("PAGES", "Lichess pages") - case object DailyFeed extends Permission("DAILY_FEED", "Feed updates") + case object Feed extends Permission("DAILY_FEED", "Feed updates") case object MonitoredCheatMod extends Permission("MONITORED_MOD_CHEAT", "Monitored mod: cheat") case object MonitoredBoostMod extends Permission("MONITORED_MOD_BOOST", "Monitored mod: boost") case object MonitoredCommMod extends Permission("MONITORED_MOD_COMM", "Monitored mod: comms") @@ -203,7 +203,7 @@ object Permission: StudyAdmin, BroadcastTimeout, ApiChallengeAdmin, - DailyFeed + Feed ), "Admin" ) @@ -279,7 +279,7 @@ object Permission: PuzzleCurator, OpeningWiki, Presets, - DailyFeed + Feed ), "Dev" -> List( Cli, From db1289e65346a35f88add413d3fb96e4e94ce42e Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 11 Feb 2024 09:24:13 +0100 Subject: [PATCH 06/39] remove unneeded feed package file --- modules/feed/src/main/Env.scala | 1 + modules/feed/src/main/Feed.scala | 1 + modules/feed/src/main/package.scala | 3 --- 3 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 modules/feed/src/main/package.scala diff --git a/modules/feed/src/main/Env.scala b/modules/feed/src/main/Env.scala index cb3cacfe6f225..9e479453a5823 100644 --- a/modules/feed/src/main/Env.scala +++ b/modules/feed/src/main/Env.scala @@ -1,5 +1,6 @@ package lila.feed +import lila.Lila.{ *, given } import com.softwaremill.macwire.* import lila.common.autoconfig.* import play.api.Configuration diff --git a/modules/feed/src/main/Feed.scala b/modules/feed/src/main/Feed.scala index 8a013bf9ef3cd..6a627590d0c2f 100644 --- a/modules/feed/src/main/Feed.scala +++ b/modules/feed/src/main/Feed.scala @@ -1,5 +1,6 @@ package lila.feed +import lila.Lila.{ *, given } import reactivemongo.api.bson.* import reactivemongo.api.bson.Macros.Annotations.Key import java.time.format.{ DateTimeFormatter, FormatStyle } diff --git a/modules/feed/src/main/package.scala b/modules/feed/src/main/package.scala deleted file mode 100644 index 190e8ea85a5d5..0000000000000 --- a/modules/feed/src/main/package.scala +++ /dev/null @@ -1,3 +0,0 @@ -package lila.feed - -export lila.Lila.{ *, given } From 44406106db7a0bd49083553512339962c36d13a4 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 11 Feb 2024 10:57:14 +0100 Subject: [PATCH 07/39] picfit now handles webp --- app/templating/FormHelper.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templating/FormHelper.scala b/app/templating/FormHelper.scala index 9cf7c51cb236a..ee9232006b02e 100644 --- a/app/templating/FormHelper.scala +++ b/app/templating/FormHelper.scala @@ -293,6 +293,6 @@ trait FormHelper: object file: def image(name: String): Frag = - st.input(tpe := "file", st.name := name, accept := "image/png, image/jpeg") + st.input(tpe := "file", st.name := name, accept := "image/png, image/jpeg, image/webp") def pgn(name: String): Frag = st.input(tpe := "file", st.name := name, accept := ".pgn") def selectImage = button(cls := "button select-image")("select image") From b8f2975be80cbe0fa516b88524c63b6421bc068e Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 11 Feb 2024 13:18:55 +0100 Subject: [PATCH 08/39] list up to 100 ongoing broadcasts --- modules/relay/src/main/RelayListing.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/relay/src/main/RelayListing.scala b/modules/relay/src/main/RelayListing.scala index 7e46d21857623..f5ebde5a90cf9 100644 --- a/modules/relay/src/main/RelayListing.scala +++ b/modules/relay/src/main/RelayListing.scala @@ -21,7 +21,7 @@ final class RelayListing( _.refreshAfterWrite(5 seconds).buildAsyncFuture: _ => for upcoming <- upcoming.get({}) - max = 64 + max = 100 docs <- tourRepo.coll .aggregateList(max): framework => import framework.* From 4f9dcf9941aa70b70ce64b4902a998f296910833 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 11 Feb 2024 13:19:11 +0100 Subject: [PATCH 09/39] LCC uses chess960 position 518 for standard chess --- modules/relay/src/main/RelayFetch.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/relay/src/main/RelayFetch.scala b/modules/relay/src/main/RelayFetch.scala index f39ebf93fa627..b0ff326591b7f 100644 --- a/modules/relay/src/main/RelayFetch.scala +++ b/modules/relay/src/main/RelayFetch.scala @@ -244,7 +244,10 @@ private object RelayFetch: case class GameJson(moves: List[String], result: Option[String], chess960: Option[Int] = none): def outcome = result.flatMap(Outcome.fromResult) def toPgn(extraTags: Tags = Tags.empty): PgnStr = - val fenTag = chess960.flatMap(chess.variant.Chess960.positionToFen).map(pos => Tag(_.FEN, pos.value)) + val fenTag = chess960 + .filter(_ != 518) // LCC sends 518 for standard chess + .flatMap(chess.variant.Chess960.positionToFen) + .map(pos => Tag(_.FEN, pos.value)) val outcomeTag = outcome.map(o => Tag(_.Result, Outcome.showResult(o.some))) val tags = extraTags ++ Tags(List(fenTag, outcomeTag).flatten) val strMoves = moves From f1eeda8eb5d27766214a1d35d8f064d9b5025216 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 11 Feb 2024 13:50:58 +0100 Subject: [PATCH 10/39] tweak team chat modding --- app/controllers/Team.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/Team.scala b/app/controllers/Team.scala index 324d4722e5110..d59c0399f666b 100644 --- a/app/controllers/Team.scala +++ b/app/controllers/Team.scala @@ -77,7 +77,7 @@ final class Team(env: Env, apiC: => Api) extends LilaController(env): team.enabled && !team.isChatFor(_.NONE) && ctx.kid.no && HTTPRequest.isHuman(ctx.req) && { (team.isChatFor(_.LEADERS) && info.ledByMe) || (team.isChatFor(_.MEMBERS) && info.mine) || - (isGrantedOpt(_.Shusher) && requestModView) + ((isGrantedOpt(_.Shusher) || isGrantedOpt(_.ManageTeam)) && requestModView) } private def canHaveForum(team: TeamModel, asMod: Boolean)(member: Option[TeamMember])(using From 6e60a320f1544b4423df58de2df71a0eb5e23307 Mon Sep 17 00:00:00 2001 From: Jonathan Gamble Date: Sun, 11 Feb 2024 06:58:19 -0600 Subject: [PATCH 11/39] hotfix snab dialogs clobbering body overflow --- ui/analyse/src/study/chapterEditForm.ts | 22 +++++++----- ui/analyse/src/study/chapterNewForm.ts | 5 ++- ui/analyse/src/study/inviteForm.ts | 1 + ui/analyse/src/study/studyForm.ts | 48 ++++++++++++++----------- ui/analyse/src/study/topics.ts | 20 +++++++---- 5 files changed, 59 insertions(+), 37 deletions(-) diff --git a/ui/analyse/src/study/chapterEditForm.ts b/ui/analyse/src/study/chapterEditForm.ts index c10cb9dad8e78..3c00782d582aa 100644 --- a/ui/analyse/src/study/chapterEditForm.ts +++ b/ui/analyse/src/study/chapterEditForm.ts @@ -74,14 +74,20 @@ export function view(ctrl: StudyChapterEditForm): VNode | undefined { h( 'form.form3', { - hook: bindSubmit(e => { - ctrl.submit({ - name: chapterForm.fieldValue(e, 'name'), - mode: chapterForm.fieldValue(e, 'mode') as ChapterMode, - orientation: chapterForm.fieldValue(e, 'orientation') as Orientation, - description: chapterForm.fieldValue(e, 'description'), - }); - }, ctrl.redraw), + hook: bindSubmit( + e => { + ctrl.submit({ + name: chapterForm.fieldValue(e, 'name'), + mode: chapterForm.fieldValue(e, 'mode') as ChapterMode, + orientation: chapterForm.fieldValue(e, 'orientation') as Orientation, + description: chapterForm.fieldValue(e, 'description'), + }); + }, + () => { + document.body.style.overflowY = 'scroll'; + ctrl.redraw(); + }, + ), }, [ h('div.form-group', [ diff --git a/ui/analyse/src/study/chapterNewForm.ts b/ui/analyse/src/study/chapterNewForm.ts index 3273f68f17845..79734a0be6de8 100644 --- a/ui/analyse/src/study/chapterNewForm.ts +++ b/ui/analyse/src/study/chapterNewForm.ts @@ -153,7 +153,10 @@ export function view(ctrl: StudyChapterNewForm): VNode { fen: fieldValue(e, 'fen') || (ctrl.tab() === 'edit' ? ctrl.editorFen() : null), isDefaultName: ctrl.isDefaultName(), }), - ctrl.redraw, + () => { + document.body.style.overflowY = 'scroll'; + ctrl.redraw(); + }, ), }, [ diff --git a/ui/analyse/src/study/inviteForm.ts b/ui/analyse/src/study/inviteForm.ts index 407104df92c70..1d06ae21dca15 100644 --- a/ui/analyse/src/study/inviteForm.ts +++ b/ui/analyse/src/study/inviteForm.ts @@ -83,6 +83,7 @@ export function view(ctrl: ReturnType): VNode { onSelect(v) { input.value = ''; ctrl.invite(v.name); + document.body.style.overflowY = 'scroll'; ctrl.redraw(); }, }) diff --git a/ui/analyse/src/study/studyForm.ts b/ui/analyse/src/study/studyForm.ts index fc56997387983..aaaaf045a6d6b 100644 --- a/ui/analyse/src/study/studyForm.ts +++ b/ui/analyse/src/study/studyForm.ts @@ -91,27 +91,33 @@ export function view(ctrl: StudyForm): VNode { h( 'form.form3', { - hook: bindSubmit(e => { - const getVal = (name: string): string => { - const el = (e.target as HTMLElement).querySelector('#study-' + name) as HTMLInputElement; - if (el) return el.value; - else throw `Missing form input: ${name}`; - }; - ctrl.save( - { - name: getVal('name'), - visibility: getVal('visibility'), - computer: getVal('computer'), - explorer: getVal('explorer'), - cloneable: getVal('cloneable'), - shareable: getVal('shareable'), - chat: getVal('chat'), - sticky: getVal('sticky') as 'true' | 'false', - description: getVal('description') as 'true' | 'false', - }, - isNew, - ); - }, ctrl.redraw), + hook: bindSubmit( + e => { + const getVal = (name: string): string => { + const el = (e.target as HTMLElement).querySelector('#study-' + name) as HTMLInputElement; + if (el) return el.value; + else throw `Missing form input: ${name}`; + }; + ctrl.save( + { + name: getVal('name'), + visibility: getVal('visibility'), + computer: getVal('computer'), + explorer: getVal('explorer'), + cloneable: getVal('cloneable'), + shareable: getVal('shareable'), + chat: getVal('chat'), + sticky: getVal('sticky') as 'true' | 'false', + description: getVal('description') as 'true' | 'false', + }, + isNew, + ); + }, + () => { + document.body.style.overflowY = 'scroll'; + ctrl.redraw(); + }, + ), }, [ h('div.form-group' + (ctrl.relay ? '.none' : ''), [ diff --git a/ui/analyse/src/study/topics.ts b/ui/analyse/src/study/topics.ts index 867c6fa00b376..53c5152797770 100644 --- a/ui/analyse/src/study/topics.ts +++ b/ui/analyse/src/study/topics.ts @@ -48,13 +48,19 @@ export const formView = (ctrl: TopicsCtrl, userId?: string): VNode => h( 'form', { - hook: bindSubmit(_ => { - const tags = tagify?.value; - if (tags) { - ctrl.save(tags.map(t => t.value)); - ctrl.open(false); - } - }, ctrl.redraw), + hook: bindSubmit( + _ => { + const tags = tagify?.value; + if (tags) { + ctrl.save(tags.map(t => t.value)); + ctrl.open(false); + } + }, + () => { + document.body.style.overflowY = 'scroll'; + ctrl.redraw(); + }, + ), }, [ h( From 456485d960be349d65dcf8c0baeb7b776aa12ebb Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 11 Feb 2024 14:24:17 +0100 Subject: [PATCH 12/39] show team chat is mod is shusher but not team manager --- app/controllers/Team.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/Team.scala b/app/controllers/Team.scala index d59c0399f666b..7ff86faebd15a 100644 --- a/app/controllers/Team.scala +++ b/app/controllers/Team.scala @@ -77,7 +77,8 @@ final class Team(env: Env, apiC: => Api) extends LilaController(env): team.enabled && !team.isChatFor(_.NONE) && ctx.kid.no && HTTPRequest.isHuman(ctx.req) && { (team.isChatFor(_.LEADERS) && info.ledByMe) || (team.isChatFor(_.MEMBERS) && info.mine) || - ((isGrantedOpt(_.Shusher) || isGrantedOpt(_.ManageTeam)) && requestModView) + isGrantedOpt(_.Shusher) || + (isGrantedOpt(_.ManageTeam) && requestModView) } private def canHaveForum(team: TeamModel, asMod: Boolean)(member: Option[TeamMember])(using From cc59bc71c60331d1dd2476c9297b6bf52fb97a1f Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 11 Feb 2024 14:33:35 +0100 Subject: [PATCH 13/39] maket it possible for shusher to enter team mod view but without most of the associated perks --- app/controllers/Team.scala | 10 ++++++---- app/views/team/show.scala | 17 +++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/controllers/Team.scala b/app/controllers/Team.scala index 7ff86faebd15a..7ce254d99a82f 100644 --- a/app/controllers/Team.scala +++ b/app/controllers/Team.scala @@ -32,7 +32,7 @@ final class Team(env: Env, apiC: => Api) extends LilaController(env): def show(id: TeamId, page: Int, mod: Boolean) = Open: Reasonable(page): - Found(api team id) { renderTeam(_, page, mod && isGrantedOpt(_.ManageTeam)) } + Found(api team id) { renderTeam(_, page, mod && canEnterModView) } def members(id: TeamId, page: Int) = Open: Reasonable(page, config.Max(50)): @@ -61,7 +61,7 @@ final class Team(env: Env, apiC: => Api) extends LilaController(env): team <- api.withLeaders(team) info <- env.teamInfo(team, ctx.me, withForum = canHaveForum(team.team, asMod)) members <- paginator.teamMembers(team.team, page) - log <- asMod.so(env.mod.logApi.teamLog(team.id)) + log <- (asMod && isGrantedOpt(_.ManageTeam)).so(env.mod.logApi.teamLog(team.id)) hasChat = canHaveChat(info, asMod) chat <- hasChat soFu env.chat.api.userChat.cached.findMine(ChatId(team.id)) _ <- env.user.lightUserApi.preloadMany: @@ -70,6 +70,9 @@ final class Team(env: Env, apiC: => Api) extends LilaController(env): page <- renderPage(html.team.show(team, members, info, chat, version, asMod, log)) yield Ok(page).withCanonical(routes.Team.show(team.id)) + private def canEnterModView(using Context) = + isGrantedOpt(_.Shusher) || isGrantedOpt(_.ManageTeam) + private def canHaveChat(info: lila.app.mashup.TeamInfo, requestModView: Boolean)(using ctx: Context ): Boolean = @@ -77,8 +80,7 @@ final class Team(env: Env, apiC: => Api) extends LilaController(env): team.enabled && !team.isChatFor(_.NONE) && ctx.kid.no && HTTPRequest.isHuman(ctx.req) && { (team.isChatFor(_.LEADERS) && info.ledByMe) || (team.isChatFor(_.MEMBERS) && info.mine) || - isGrantedOpt(_.Shusher) || - (isGrantedOpt(_.ManageTeam) && requestModView) + (canEnterModView && requestModView) } private def canHaveForum(team: TeamModel, asMod: Boolean)(member: Option[TeamMember])(using diff --git a/app/views/team/show.scala b/app/views/team/show.scala index d707743186423..1a1434ed193d7 100644 --- a/app/views/team/show.scala +++ b/app/views/team/show.scala @@ -54,7 +54,8 @@ object show: )) ) ): - val canSeeMembers = asMod || (t.enabled && (t.publicMembers || info.mine)) + val canManage = asMod && isGranted(_.ManageTeam) + val canSeeMembers = canManage || (t.enabled && (t.publicMembers || info.mine)) main( cls := "team-show box", socketVersion.map: v => @@ -70,7 +71,7 @@ object show: ), div(cls := "team-show__content")( div(cls := "team-show__content__col1")( - (t.enabled || info.ledByMe || asMod) option st.section(cls := "team-show__meta")( + (t.enabled || info.ledByMe || canManage) option st.section(cls := "team-show__meta")( t.publicLeaders.nonEmpty option p( teamLeaders.pluralSame(t.publicLeaders.size), ": ", @@ -100,7 +101,7 @@ object show: postForm(action := teamRoutes.quit(t.id)): submitButton(cls := "button button-red button-empty confirm")(trans.cancel()) ) - else ctx.isAuth option joinButton(t.team) + else (ctx.isAuth && !asMod) option joinButton(t.team) ), t.enabled && info.mine option postForm( @@ -158,7 +159,7 @@ object show: em(messageAllMembersOverview()) ) ), - ((t.enabled && info.havePerm(_.Settings)) || asMod) option + ((t.enabled && info.havePerm(_.Settings)) || canManage) option a( href := teamRoutes.edit(t.id), cls := "button button-empty text", @@ -166,19 +167,19 @@ object show: )( trans.settings.settings() ), - ((t.enabled && info.havePerm(_.Admin)) || asMod) option + ((t.enabled && info.havePerm(_.Admin)) || canManage) option a( cls := "button button-empty text", href := teamRoutes.leaders(t.id), dataIcon := licon.Group )(teamLeaders()), - ((t.enabled && info.havePerm(_.Kick)) || asMod) option + ((t.enabled && info.havePerm(_.Kick)) || canManage) option a( cls := "button button-empty text", href := teamRoutes.kick(t.id), dataIcon := licon.InternalArrow )(kickSomeone()), - ((t.enabled && info.havePerm(_.Request)) || asMod) option + ((t.enabled && info.havePerm(_.Request)) || canManage) option a( cls := "button button-empty text", href := teamRoutes.declinedRequests(t.id), @@ -211,7 +212,7 @@ object show: a(href := teamRoutes.edit(t.id))("Give your team a short introduction text!") ), log.nonEmpty option renderLog(log), - (t.enabled || asMod) option st.section(cls := "team-show__desc")( + (t.enabled || canManage) option st.section(cls := "team-show__desc")( bits.markdown(t.team, t.descPrivate.ifTrue(info.mine) | t.description) ), t.enabled && info.hasRequests option div(cls := "team-show__requests")( From ea141f4e8917098472ddaff560dad5fbdf002ad2 Mon Sep 17 00:00:00 2001 From: Jonathan Gamble Date: Sun, 11 Feb 2024 07:57:32 -0600 Subject: [PATCH 14/39] force call DialogWrapper.onClose when externally removed from DOM --- ui/analyse/src/study/chapterEditForm.ts | 22 +++++------- ui/analyse/src/study/chapterNewForm.ts | 5 +-- ui/analyse/src/study/inviteForm.ts | 1 - ui/analyse/src/study/studyForm.ts | 48 +++++++++++-------------- ui/analyse/src/study/topics.ts | 20 ++++------- ui/site/src/component/dialog.ts | 19 ++++++++-- 6 files changed, 53 insertions(+), 62 deletions(-) diff --git a/ui/analyse/src/study/chapterEditForm.ts b/ui/analyse/src/study/chapterEditForm.ts index 3c00782d582aa..c10cb9dad8e78 100644 --- a/ui/analyse/src/study/chapterEditForm.ts +++ b/ui/analyse/src/study/chapterEditForm.ts @@ -74,20 +74,14 @@ export function view(ctrl: StudyChapterEditForm): VNode | undefined { h( 'form.form3', { - hook: bindSubmit( - e => { - ctrl.submit({ - name: chapterForm.fieldValue(e, 'name'), - mode: chapterForm.fieldValue(e, 'mode') as ChapterMode, - orientation: chapterForm.fieldValue(e, 'orientation') as Orientation, - description: chapterForm.fieldValue(e, 'description'), - }); - }, - () => { - document.body.style.overflowY = 'scroll'; - ctrl.redraw(); - }, - ), + hook: bindSubmit(e => { + ctrl.submit({ + name: chapterForm.fieldValue(e, 'name'), + mode: chapterForm.fieldValue(e, 'mode') as ChapterMode, + orientation: chapterForm.fieldValue(e, 'orientation') as Orientation, + description: chapterForm.fieldValue(e, 'description'), + }); + }, ctrl.redraw), }, [ h('div.form-group', [ diff --git a/ui/analyse/src/study/chapterNewForm.ts b/ui/analyse/src/study/chapterNewForm.ts index 79734a0be6de8..3273f68f17845 100644 --- a/ui/analyse/src/study/chapterNewForm.ts +++ b/ui/analyse/src/study/chapterNewForm.ts @@ -153,10 +153,7 @@ export function view(ctrl: StudyChapterNewForm): VNode { fen: fieldValue(e, 'fen') || (ctrl.tab() === 'edit' ? ctrl.editorFen() : null), isDefaultName: ctrl.isDefaultName(), }), - () => { - document.body.style.overflowY = 'scroll'; - ctrl.redraw(); - }, + ctrl.redraw, ), }, [ diff --git a/ui/analyse/src/study/inviteForm.ts b/ui/analyse/src/study/inviteForm.ts index 1d06ae21dca15..407104df92c70 100644 --- a/ui/analyse/src/study/inviteForm.ts +++ b/ui/analyse/src/study/inviteForm.ts @@ -83,7 +83,6 @@ export function view(ctrl: ReturnType): VNode { onSelect(v) { input.value = ''; ctrl.invite(v.name); - document.body.style.overflowY = 'scroll'; ctrl.redraw(); }, }) diff --git a/ui/analyse/src/study/studyForm.ts b/ui/analyse/src/study/studyForm.ts index aaaaf045a6d6b..fc56997387983 100644 --- a/ui/analyse/src/study/studyForm.ts +++ b/ui/analyse/src/study/studyForm.ts @@ -91,33 +91,27 @@ export function view(ctrl: StudyForm): VNode { h( 'form.form3', { - hook: bindSubmit( - e => { - const getVal = (name: string): string => { - const el = (e.target as HTMLElement).querySelector('#study-' + name) as HTMLInputElement; - if (el) return el.value; - else throw `Missing form input: ${name}`; - }; - ctrl.save( - { - name: getVal('name'), - visibility: getVal('visibility'), - computer: getVal('computer'), - explorer: getVal('explorer'), - cloneable: getVal('cloneable'), - shareable: getVal('shareable'), - chat: getVal('chat'), - sticky: getVal('sticky') as 'true' | 'false', - description: getVal('description') as 'true' | 'false', - }, - isNew, - ); - }, - () => { - document.body.style.overflowY = 'scroll'; - ctrl.redraw(); - }, - ), + hook: bindSubmit(e => { + const getVal = (name: string): string => { + const el = (e.target as HTMLElement).querySelector('#study-' + name) as HTMLInputElement; + if (el) return el.value; + else throw `Missing form input: ${name}`; + }; + ctrl.save( + { + name: getVal('name'), + visibility: getVal('visibility'), + computer: getVal('computer'), + explorer: getVal('explorer'), + cloneable: getVal('cloneable'), + shareable: getVal('shareable'), + chat: getVal('chat'), + sticky: getVal('sticky') as 'true' | 'false', + description: getVal('description') as 'true' | 'false', + }, + isNew, + ); + }, ctrl.redraw), }, [ h('div.form-group' + (ctrl.relay ? '.none' : ''), [ diff --git a/ui/analyse/src/study/topics.ts b/ui/analyse/src/study/topics.ts index 53c5152797770..867c6fa00b376 100644 --- a/ui/analyse/src/study/topics.ts +++ b/ui/analyse/src/study/topics.ts @@ -48,19 +48,13 @@ export const formView = (ctrl: TopicsCtrl, userId?: string): VNode => h( 'form', { - hook: bindSubmit( - _ => { - const tags = tagify?.value; - if (tags) { - ctrl.save(tags.map(t => t.value)); - ctrl.open(false); - } - }, - () => { - document.body.style.overflowY = 'scroll'; - ctrl.redraw(); - }, - ), + hook: bindSubmit(_ => { + const tags = tagify?.value; + if (tags) { + ctrl.save(tags.map(t => t.value)); + ctrl.open(false); + } + }, ctrl.redraw), }, [ h( diff --git a/ui/site/src/component/dialog.ts b/ui/site/src/component/dialog.ts index cba80d8bc8973..0840e3f6bccc1 100644 --- a/ui/site/src/component/dialog.ts +++ b/ui/site/src/component/dialog.ts @@ -94,8 +94,18 @@ export function snabDialog(o: SnabDialogOpts): VNode { } class DialogWrapper implements Dialog { - restore?: { focus: HTMLElement; overflow: string }; - resolve?: (dialog: Dialog) => void; + private restore?: { focus: HTMLElement; overflow: string }; + private resolve?: (dialog: Dialog) => void; + private observer: MutationObserver = new MutationObserver(list => { + for (const m of list) + if (m.type === 'childList') + for (const n of m.removedNodes) { + if (n === this.dialog) { + this.onClose(); + return; + } + } + }); constructor( readonly dialog: HTMLDialogElement, @@ -107,6 +117,7 @@ class DialogWrapper implements Dialog { const justThen = Date.now(); const cancelOnInterval = () => Date.now() - justThen > 200 && this.close('cancel'); + this.observer?.observe(document.body, { childList: true, subtree: true }); view.parentElement?.style.setProperty('--vh', `${window.innerHeight}px`); view.addEventListener('click', e => e.stopPropagation()); @@ -150,6 +161,7 @@ class DialogWrapper implements Dialog { focus: document.activeElement as HTMLElement, overflow: document.body.style.overflow, }; + $(focusQuery, this.view)[1]?.focus(); document.body.style.overflow = 'hidden'; @@ -164,7 +176,8 @@ class DialogWrapper implements Dialog { this.dialog.close(this.returnValue || v || 'ok'); }; - onClose = () => { + private onClose = () => { + this.observer.disconnect(); if (!this.dialog.returnValue) this.dialog.returnValue = 'cancel'; this.restore?.focus.focus(); // one modal at a time please if (this.restore?.overflow !== undefined) document.body.style.overflow = this.restore.overflow; From a70dd291a2e1dabaee4e49794bc0f7811b4b09dc Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 11 Feb 2024 15:42:58 +0100 Subject: [PATCH 15/39] don't reset a broadcast board on initial fen change, if moves were played might fix an issue with LCC 960 broadcasts random board resets --- modules/relay/src/main/RelaySync.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/relay/src/main/RelaySync.scala b/modules/relay/src/main/RelaySync.scala index 0bb94776db6cf..8c200c1cd70d5 100644 --- a/modules/relay/src/main/RelaySync.scala +++ b/modules/relay/src/main/RelaySync.scala @@ -77,7 +77,7 @@ final private class RelaySync( yield SyncResult.ChapterResult(chapter.id, tagUpdate, nbMoves) private def updateInitialPosition(studyId: StudyId, chapter: Chapter, game: RelayGame): Fu[Chapter] = - if game.root.fen == chapter.root.fen + if game.root.mainline.sizeIs > 1 || game.root.fen == chapter.root.fen then fuccess(chapter) else studyApi From 4c91f0027f47acd99c4c862bbd7ccde9cdee8ad0 Mon Sep 17 00:00:00 2001 From: Jonathan Gamble <101470903+schlawg@users.noreply.github.com> Date: Sun, 11 Feb 2024 09:20:43 -0600 Subject: [PATCH 16/39] private onClose renamed onRemove --- ui/site/src/component/dialog.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/site/src/component/dialog.ts b/ui/site/src/component/dialog.ts index 0840e3f6bccc1..908ead676b0bd 100644 --- a/ui/site/src/component/dialog.ts +++ b/ui/site/src/component/dialog.ts @@ -101,7 +101,7 @@ class DialogWrapper implements Dialog { if (m.type === 'childList') for (const n of m.removedNodes) { if (n === this.dialog) { - this.onClose(); + this.onRemove(); return; } } @@ -122,7 +122,7 @@ class DialogWrapper implements Dialog { view.addEventListener('click', e => e.stopPropagation()); dialog.addEventListener('cancel', () => !this.returnValue && (this.returnValue = 'cancel')); - dialog.addEventListener('close', this.onClose); + dialog.addEventListener('close', this.onRemove); dialog.querySelector('.close-button-anchor > .close-button')?.addEventListener('click', cancelOnInterval); if (!o.noClickAway) setTimeout(() => dialog.addEventListener('click', cancelOnInterval)); @@ -176,7 +176,7 @@ class DialogWrapper implements Dialog { this.dialog.close(this.returnValue || v || 'ok'); }; - private onClose = () => { + private onRemove = () => { this.observer.disconnect(); if (!this.dialog.returnValue) this.dialog.returnValue = 'cancel'; this.restore?.focus.focus(); // one modal at a time please From 44d71f4b54142ba36eb1c7bf6df61a3373cd0952 Mon Sep 17 00:00:00 2001 From: Jonathan Gamble <101470903+schlawg@users.noreply.github.com> Date: Sun, 11 Feb 2024 19:28:50 -0600 Subject: [PATCH 17/39] remove prismic url from config --- modules/api/src/main/ApiConfig.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/api/src/main/ApiConfig.scala b/modules/api/src/main/ApiConfig.scala index d2b489aaab070..b9d485ee03bc4 100644 --- a/modules/api/src/main/ApiConfig.scala +++ b/modules/api/src/main/ApiConfig.scala @@ -8,7 +8,6 @@ final class ApiConfig( val apiToken: Secret, val influxEventEndpoint: String, val influxEventEnv: String, - val prismicApiUrl: String, val pagerDuty: ApiConfig.PagerDuty ) @@ -31,7 +30,6 @@ object ApiConfig: c.get[Secret]("api.token"), c.get[String]("api.influx_event.endpoint"), c.get[String]("api.influx_event.env"), - c.get[String]("prismic.api_url"), new PagerDuty( c.get[String]("pagerDuty.serviceId"), c.get[Secret]("pagerDuty.apiKey") From b5d0b421289e65e1326d3d757ded68918532a3a6 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Sun, 11 Feb 2024 23:42:54 +0100 Subject: [PATCH 18/39] Make position evaluation glyphs available via shortcuts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using lichess to analyze openings or solve chess studies, one needs to frequently select a position evaluation annotation like `=` (equal) or `+-` (white is winning) – much more frequent than _Zugzwang_ or similar symbols; more times than the existing move annotation glyphs (`?!` `?` `!!` etc.). Use Shift+1 to Shift+8 for these, analogous to 1 to 6 for the move annotations. Likely, the help text for move annotations should be changed (no chess player knows what a _glyph annotation_ is, but a _move annotation_ is widely known), but as I am unfamiliar with the i18n system, I'll leave that for a future PR. --- app/views/site/help.scala | 3 ++- modules/i18n/src/main/I18nKeys.scala | 1 + translation/source/site.xml | 1 + ui/analyse/src/keyboard.ts | 5 +++++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/views/site/help.scala b/app/views/site/help.scala index 38431c21a97cc..5f3bc891ab188 100644 --- a/app/views/site/help.scala +++ b/app/views/site/help.scala @@ -103,7 +103,8 @@ object help: row(kbd("g"), trans.study.annotateWithGlyphs()), row(kbd("n"), trans.study.nextChapter()), row(kbd("p"), trans.study.prevChapter()), - row(frag((1 to 6).map(kbd(_))), trans.toggleGlyphAnnotations()) + row(frag((1 to 6).map(kbd(_))), trans.toggleGlyphAnnotations()), + row(frag(kbd("shift"), (1 to 8).map(kbd(_))), trans.togglePositionAnnotations()) ), header(trans.mouseTricks()), tr( diff --git a/modules/i18n/src/main/I18nKeys.scala b/modules/i18n/src/main/I18nKeys.scala index 7c80219e58cf3..e699d379c8ab3 100644 --- a/modules/i18n/src/main/I18nKeys.scala +++ b/modules/i18n/src/main/I18nKeys.scala @@ -560,6 +560,7 @@ object I18nKeys: val `toggleVariationArrows` = I18nKey("toggleVariationArrows") val `cyclePreviousOrNextVariation` = I18nKey("cyclePreviousOrNextVariation") val `toggleGlyphAnnotations` = I18nKey("toggleGlyphAnnotations") + val `togglePositionAnnotations` = I18nKey("togglePositionAnnotations") val `variationArrowsInfo` = I18nKey("variationArrowsInfo") val `playSelectedMove` = I18nKey("playSelectedMove") val `newTournament` = I18nKey("newTournament") diff --git a/translation/source/site.xml b/translation/source/site.xml index bccf3cd990d88..9d7f57ecae898 100644 --- a/translation/source/site.xml +++ b/translation/source/site.xml @@ -705,6 +705,7 @@ Toggle variation arrows Cycle previous/next variation Toggle glyph annotations + Toggle position annotations Variation arrows let you navigate without using the move list. play selected move New tournament diff --git a/ui/analyse/src/keyboard.ts b/ui/analyse/src/keyboard.ts index f19fbe4603dbc..a033b74f8e36d 100644 --- a/ui/analyse/src/keyboard.ts +++ b/ui/analyse/src/keyboard.ts @@ -126,7 +126,12 @@ export const bind = (ctrl: AnalyseCtrl) => { // navigation for next and prev chapters kbd.bind('p', ctrl.study.goToPrevChapter); kbd.bind('n', ctrl.study.goToNextChapter); + // ! ? !! ?? !? ?! for (let i = 1; i < 7; i++) kbd.bind(i.toString(), () => ctrl.study?.glyphForm.toggleGlyph(i)); + // = (equality) + kbd.bind('shift+1', () => ctrl.study?.glyphForm.toggleGlyph(10)); + // ∞ ⩲ ⩱ ± ∓ +- -+ + for (let i = 2; i < 9; i++) kbd.bind(`shift+${i}`, () => ctrl.study?.glyphForm.toggleGlyph(11 + i)); } }; From f28aa80eadd0775fef11f2443df7771bbd23ea98 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 12 Feb 2024 09:30:06 +0100 Subject: [PATCH 19/39] TS code golf --- ui/analyse/src/keyboard.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ui/analyse/src/keyboard.ts b/ui/analyse/src/keyboard.ts index a033b74f8e36d..2a5497add3005 100644 --- a/ui/analyse/src/keyboard.ts +++ b/ui/analyse/src/keyboard.ts @@ -128,10 +128,9 @@ export const bind = (ctrl: AnalyseCtrl) => { kbd.bind('n', ctrl.study.goToNextChapter); // ! ? !! ?? !? ?! for (let i = 1; i < 7; i++) kbd.bind(i.toString(), () => ctrl.study?.glyphForm.toggleGlyph(i)); - // = (equality) - kbd.bind('shift+1', () => ctrl.study?.glyphForm.toggleGlyph(10)); - // ∞ ⩲ ⩱ ± ∓ +- -+ - for (let i = 2; i < 9; i++) kbd.bind(`shift+${i}`, () => ctrl.study?.glyphForm.toggleGlyph(11 + i)); + // = ∞ ⩲ ⩱ ± ∓ +- -+ + for (let i = 1; i < 9; i++) + kbd.bind(`shift+${i}`, () => ctrl.study?.glyphForm.toggleGlyph(i == 1 ? 10 : 11 + i)); } }; From 3b6de69638f6cff8719c276da75f375a8efebbe9 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 12 Feb 2024 09:30:12 +0100 Subject: [PATCH 20/39] tweak move annotation wording --- translation/source/site.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/translation/source/site.xml b/translation/source/site.xml index 9d7f57ecae898..68f67e94bf31e 100644 --- a/translation/source/site.xml +++ b/translation/source/site.xml @@ -704,7 +704,7 @@ Next branch Toggle variation arrows Cycle previous/next variation - Toggle glyph annotations + Toggle move annotations Toggle position annotations Variation arrows let you navigate without using the move list. play selected move From 88cc3b5a1a1906a806b4d02c06bc2c0dfccd23a8 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 12 Feb 2024 09:53:40 +0100 Subject: [PATCH 21/39] select the broadcast games tab if there are games --- ui/analyse/src/study/relay/relayCtrl.ts | 4 +++- ui/analyse/src/study/studyCtrl.ts | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/analyse/src/study/relay/relayCtrl.ts b/ui/analyse/src/study/relay/relayCtrl.ts index 591fe668a73f7..853508ceea0ab 100644 --- a/ui/analyse/src/study/relay/relayCtrl.ts +++ b/ui/analyse/src/study/relay/relayCtrl.ts @@ -22,11 +22,13 @@ export default class RelayCtrl { readonly redraw: () => void, readonly members: StudyMemberCtrl, chapter: StudyChapter, + hasBoards: boolean, ) { this.applyChapterRelay(chapter, chapter.relay); this.tourShow = toggle((location.pathname.match(/\//g) || []).length < 5); const locationTab = location.hash.replace(/^#/, '') as RelayTab; - this.tab = prop(relayTabs.includes(locationTab) ? locationTab : 'overview'); + const initialTab = relayTabs.includes(locationTab) ? locationTab : hasBoards ? 'games' : 'overview'; + this.tab = prop(initialTab); } setSync = (v: boolean) => { diff --git a/ui/analyse/src/study/studyCtrl.ts b/ui/analyse/src/study/studyCtrl.ts index a1e815889a04e..e5f30a4435251 100644 --- a/ui/analyse/src/study/studyCtrl.ts +++ b/ui/analyse/src/study/studyCtrl.ts @@ -157,6 +157,7 @@ export default class StudyCtrl { this.redrawAndUpdateAddressBar, this.members, this.data.chapter, + !this.looksNew(), ); this.multiBoard = new MultiBoardCtrl( this.data.id, From cb6bbfe8ce276bf6551da39dd0fa6043c3261410 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 12 Feb 2024 10:03:31 +0100 Subject: [PATCH 22/39] cms page ids no longer change --- modules/cms/src/main/CmsApi.scala | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/cms/src/main/CmsApi.scala b/modules/cms/src/main/CmsApi.scala index b65959ac223ae..b0af791569b8b 100644 --- a/modules/cms/src/main/CmsApi.scala +++ b/modules/cms/src/main/CmsApi.scala @@ -38,11 +38,7 @@ final class CmsApi(coll: Coll, markup: CmsMarkup)(using Executor): def update(prev: CmsPage, data: CmsForm.CmsPageData)(using me: Me): Fu[CmsPage] = val page = data update me - val idChange: Funit = (prev.id != page.id).so: - coll.exists($id(page.id)) flatMap: - case true => fufail(s"A page with the ID ${page.id} already exists") - case false => coll.delete.one($id(prev.id)).void - idChange >> coll.update.one($id(page.id), page, upsert = true) inject page + coll.update.one($id(page.id), page) inject page def delete(id: Id): Funit = coll.delete.one($id(id)).void From c61cb30932a1aeed491ff721e7a136e2490a416d Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 12 Feb 2024 11:12:48 +0100 Subject: [PATCH 23/39] finish removing prismic --- COPYING.md | 1 - README.md | 1 - modules/common/src/main/MarkdownRender.scala | 1 - modules/ublog/src/main/UblogApi.scala | 10 ---------- 4 files changed, 13 deletions(-) diff --git a/COPYING.md b/COPYING.md index 0f3770ce81865..5d5f621db4f0b 100644 --- a/COPYING.md +++ b/COPYING.md @@ -99,7 +99,6 @@ public/images/staunton/piece/Staunton | [Eden Murs](https://userstyles.org/style Lichess as deployed on https://lichess.org/ also uses these external services: - [Cloudflare](https://www.cloudflare.com/) to serve static assets, DNS lookups for email validation -- [prismic.io](https://prismic.io/) for help/documentation pages and the blog - [twitch](https://www.twitch.tv/) for featured livestreams - [YouTube](https://www.youtube.com) for featured livestreams and the [Video library](https://lichess.org/video) - [stripe](https://stripe.com/) and [PayPal](https://www.paypal.com) for [Patron donations](https://lichess.org/patron) diff --git a/README.md b/README.md index 06c737a33165a..dc7eb66786d5b 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,6 @@ Lichess talks to [Stockfish](https://stockfishchess.org/) deployed in an [AI clu It uses [MongoDB](https://www.mongodb.com) to store more than 4.7 billion games, which are indexed by [elasticsearch](https://github.com/elastic/elasticsearch). HTTP requests and WebSocket connections can be proxied by [nginx](https://nginx.org). The web client is written in [TypeScript](https://www.typescriptlang.org/) and [snabbdom](https://github.com/snabbdom/snabbdom), using [Sass](https://sass-lang.com/) to generate CSS. -The [blog](https://lichess.org/blog) uses a free open content plan from [prismic.io](https://prismic.io). All rated games are published in a [free PGN database](https://database.lichess.org). Browser testing done with [Browserstack](https://www.browserstack.com). Proxy detection done with [IP2Proxy database](https://www.ip2location.com/database/ip2proxy). diff --git a/modules/common/src/main/MarkdownRender.scala b/modules/common/src/main/MarkdownRender.scala index 3169ef510af58..1b21a2436d6d1 100644 --- a/modules/common/src/main/MarkdownRender.scala +++ b/modules/common/src/main/MarkdownRender.scala @@ -129,7 +129,6 @@ object MarkdownRender: "i.ibb.co", "i.postimg.cc", "xkcd.com", - "images.prismic.io", "image.lichess1.org", "127.0.0.1" ) diff --git a/modules/ublog/src/main/UblogApi.scala b/modules/ublog/src/main/UblogApi.scala index b7b51d05235da..be2b351b5a9dd 100644 --- a/modules/ublog/src/main/UblogApi.scala +++ b/modules/ublog/src/main/UblogApi.scala @@ -28,16 +28,6 @@ final class UblogApi( bsonWriteObjTry[UblogPost](post).get ++ $doc("likers" -> List(author.id)) ) inject post - def migrateFromBlog(post: UblogPost, prismicId: String, prismicData: Bdoc) = - colls.post.insert - .one: - bsonWriteObjTry[UblogPost](post).get ++ $doc( - "likers" -> List(post.created.by), - "prismicId" -> prismicId, - "prismicData" -> prismicData - ) - .void - def getByPrismicId(id: String): Fu[Option[UblogPost]] = colls.post.one[UblogPost]($doc("prismicId" -> id)) def update(data: UblogForm.UblogPostData, prev: UblogPost)(using me: Me): Fu[UblogPost] = From e2b9e5edbf8e48aaefc964e706d54433166163d8 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 12 Feb 2024 11:13:15 +0100 Subject: [PATCH 24/39] New Crowdin updates (#14655) * New translations: broadcast.xml (Chinese Simplified) * New translations: broadcast.xml (Vietnamese) * New translations: broadcast.xml (Marathi) * New translations: broadcast.xml (French) * New translations: broadcast.xml (Czech) * New translations: broadcast.xml (Romanian) * New translations: broadcast.xml (Spanish) * New translations: broadcast.xml (Arabic) * New translations: broadcast.xml (Catalan) * New translations: broadcast.xml (Danish) * New translations: broadcast.xml (German) * New translations: broadcast.xml (Basque) * New translations: broadcast.xml (Finnish) * New translations: broadcast.xml (Hebrew) * New translations: broadcast.xml (Italian) * New translations: broadcast.xml (Japanese) * New translations: broadcast.xml (Dutch) * New translations: broadcast.xml (Polish) * New translations: broadcast.xml (Portuguese) * New translations: broadcast.xml (Russian) * New translations: broadcast.xml (Slovenian) * New translations: broadcast.xml (Albanian) * New translations: broadcast.xml (Swedish) * New translations: broadcast.xml (Ukrainian) * New translations: broadcast.xml (Galician) * New translations: broadcast.xml (Portuguese, Brazilian) * New translations: broadcast.xml (Persian) * New translations: broadcast.xml (Thai) * New translations: broadcast.xml (Norwegian Nynorsk) * New translations: broadcast.xml (English, United States) * New translations: broadcast.xml (Esperanto) * New translations: broadcast.xml (Norwegian Bokmal) * New translations: broadcast.xml (Sorani (Kurdish)) * New translations: broadcast.xml (Swiss German) * New translations: broadcast.xml (Spanish) * New translations: broadcast.xml (Persian) * New translations: broadcast.xml (Norwegian Nynorsk) * New translations: broadcast.xml (Vietnamese) * New translations: site.xml (Vietnamese) * New translations: broadcast.xml (Catalan) * New translations: broadcast.xml (German) * New translations: broadcast.xml (Armenian) * New translations: broadcast.xml (Polish) * New translations: broadcast.xml (Galician) * New translations: dgt.xml (Persian) * New translations: broadcast.xml (Portuguese) * New translations: broadcast.xml (Slovenian) * New translations: site.xml (Vietnamese) * New translations: broadcast.xml (French) * New translations: broadcast.xml (Hebrew) * New translations: broadcast.xml (Ukrainian) * New translations: broadcast.xml (English, United States) * New translations: site.xml (Vietnamese) * New translations: site.xml (Albanian) * New translations: broadcast.xml (Italian) * New translations: broadcast.xml (Slovak) * New translations: broadcast.xml (Albanian) * New translations: patron.xml (Vietnamese) * New translations: broadcast.xml (Sorani (Kurdish)) * New translations: broadcast.xml (Danish) * New translations: broadcast.xml (Swiss German) * New translations: tfa.xml (Hungarian) * New translations: faq.xml (Hungarian) * New translations: timeago.xml (Hungarian) * New translations: oauthscope.xml (Hungarian) * New translations: site.xml (Dutch) * New translations: broadcast.xml (Arabic) * New translations: site.xml (Tamil) * New translations: broadcast.xml (Basque) * New translations: broadcast.xml (Chinese Simplified) * New translations: site.xml (Russian) * New translations: site.xml (Chinese Simplified) * New translations: broadcast.xml (Russian) --- translation/dest/broadcast/ar-SA.xml | 7 ++++--- translation/dest/broadcast/ca-ES.xml | 5 +++-- translation/dest/broadcast/ckb-IR.xml | 3 ++- translation/dest/broadcast/cs-CZ.xml | 4 ++-- translation/dest/broadcast/da-DK.xml | 5 +++-- translation/dest/broadcast/de-DE.xml | 5 +++-- translation/dest/broadcast/en-US.xml | 5 +++-- translation/dest/broadcast/eo-UY.xml | 4 ++-- translation/dest/broadcast/es-ES.xml | 5 +++-- translation/dest/broadcast/eu-ES.xml | 5 +++-- translation/dest/broadcast/fa-IR.xml | 5 +++-- translation/dest/broadcast/fi-FI.xml | 4 ++-- translation/dest/broadcast/fr-FR.xml | 5 +++-- translation/dest/broadcast/gl-ES.xml | 5 +++-- translation/dest/broadcast/gsw-CH.xml | 5 +++-- translation/dest/broadcast/he-IL.xml | 5 +++-- translation/dest/broadcast/hy-AM.xml | 1 + translation/dest/broadcast/it-IT.xml | 5 +++-- translation/dest/broadcast/ja-JP.xml | 4 ++-- translation/dest/broadcast/mr-IN.xml | 4 ++-- translation/dest/broadcast/nb-NO.xml | 4 ++-- translation/dest/broadcast/nl-NL.xml | 4 ++-- translation/dest/broadcast/nn-NO.xml | 5 +++-- translation/dest/broadcast/pl-PL.xml | 5 +++-- translation/dest/broadcast/pt-BR.xml | 4 ++-- translation/dest/broadcast/pt-PT.xml | 5 +++-- translation/dest/broadcast/ro-RO.xml | 4 ++-- translation/dest/broadcast/ru-RU.xml | 5 +++-- translation/dest/broadcast/sk-SK.xml | 1 + translation/dest/broadcast/sl-SI.xml | 5 +++-- translation/dest/broadcast/sq-AL.xml | 5 +++-- translation/dest/broadcast/sv-SE.xml | 4 ++-- translation/dest/broadcast/th-TH.xml | 4 ++-- translation/dest/broadcast/uk-UA.xml | 5 +++-- translation/dest/broadcast/vi-VN.xml | 5 +++-- translation/dest/broadcast/zh-CN.xml | 5 +++-- translation/dest/dgt/fa-IR.xml | 2 ++ translation/dest/faq/hu-HU.xml | 1 + translation/dest/oauthScope/hu-HU.xml | 2 +- translation/dest/patron/vi-VN.xml | 2 +- translation/dest/site/nl-NL.xml | 1 + translation/dest/site/ru-RU.xml | 1 + translation/dest/site/sq-AL.xml | 1 + translation/dest/site/ta-IN.xml | 8 ++++---- translation/dest/site/vi-VN.xml | 18 +++++++++--------- translation/dest/site/zh-CN.xml | 1 + translation/dest/tfa/hu-HU.xml | 2 +- translation/dest/timeago/hu-HU.xml | 9 +++++++++ 48 files changed, 125 insertions(+), 84 deletions(-) diff --git a/translation/dest/broadcast/ar-SA.xml b/translation/dest/broadcast/ar-SA.xml index 3753cf47350ca..d7f16dd2dd8d1 100644 --- a/translation/dest/broadcast/ar-SA.xml +++ b/translation/dest/broadcast/ar-SA.xml @@ -12,7 +12,8 @@
بث البطولة المباشرة بث مباشر جديد - حول البث + البث المُشترك به + حول البثوث لا جولات بعد. كيفية استخدام بث ليتشيس. ستضم الجولة الجديدة الأعضاء والمساهمين عينهم الذين اشتركوا في الجولة السابق. @@ -44,8 +45,8 @@ تعديل دراسة الجولة حذف هذه المسابقة قم بحذف البطولة جميعها و جميع جولاتها و جميع ألعابها. - لوحة متصدرين تلقائية - حساب النتائج وعرض لوحة متصدرين بسيطة بناء على تلك النتائج + لوحة متصدرين تلقائية + حساب النتائج وعرض لوحة متصدرين بسيطة بناء على تلك النتائج اختياري: استبدال أسماء اللاعبين وتقييماتهم وألقابهم سطر واحد لكل لاعب، على النحو التالي: الاسم الأصلي؛ الاسم البديل؛ التقييم البديل (اختياري)؛ لقب بديل (اختياري) diff --git a/translation/dest/broadcast/ca-ES.xml b/translation/dest/broadcast/ca-ES.xml index 07234977c1625..19edbe5f2a861 100644 --- a/translation/dest/broadcast/ca-ES.xml +++ b/translation/dest/broadcast/ca-ES.xml @@ -8,6 +8,7 @@ Retransmissions de tornejos en directe Nova retransmissió en directe + Emissions que segueixo Sobre les retransmissions Cap ronda encara. Com utilitzar les retransmissions de Lichess. @@ -40,8 +41,8 @@ Edita l\'estudi de la ronda Elimina aquest torneig Elimina el torneig de forma definitiva, amb totes les seves rondes i les seves partides. - Taula de classificació automàtica - Calcula i mostra una taula de classificació simple basada en els resultats de les partides + Taula de classificació automàtica + Calcula i mostra una taula de classificació simple basada en els resultats de les partides Opcional: Reemplaça noms dels jugadors, puntuacions i títols Una línia per jugador, seguint el següent format: Nom Original; Nom a mostrar; (Opcional) Puntuació opcional a mostrar; (Opcional) Títol a mostrar diff --git a/translation/dest/broadcast/ckb-IR.xml b/translation/dest/broadcast/ckb-IR.xml index e4261f4a244dd..614907a455cef 100644 --- a/translation/dest/broadcast/ckb-IR.xml +++ b/translation/dest/broadcast/ckb-IR.xml @@ -3,10 +3,11 @@ پەخشەکان. %s پەخش دەکرێت - %s پەخش دەکرێت + %s پەخش دەکرێت پەخشی ڕاستەوخۆی پاڵەوانییەتیەکان پەخشێکی تازە + پەخشی بەشداربووان دەربارەی پەخش هێشتا هیچ خولێک نییە. چۆنیەتی بەکارهێنانی پەخشی لیچێس. diff --git a/translation/dest/broadcast/cs-CZ.xml b/translation/dest/broadcast/cs-CZ.xml index 7aba71fc740ba..e6124704f3d50 100644 --- a/translation/dest/broadcast/cs-CZ.xml +++ b/translation/dest/broadcast/cs-CZ.xml @@ -42,8 +42,8 @@ Upravit studie kola Smazat tento turnaj Opravdu smazat celý turnaj, všechna kola a hry. - Automatický žebříček - Vypočítejte a zobrazte jednoduchý žebříček na základě výsledků hry + Automatický žebříček + Vypočítejte a zobrazte jednoduchý žebříček na základě výsledků hry Volitelné: nahraďte jména hráčů, hodnocení a tituly Jeden řádek pro každého hráče a takto naformátovaný: Původní jméno; Náhradní jméno; Nepovinné náhradní hodnocení; Nepovinný náhradní název diff --git a/translation/dest/broadcast/da-DK.xml b/translation/dest/broadcast/da-DK.xml index b62069698761b..520a0e5c59f4e 100644 --- a/translation/dest/broadcast/da-DK.xml +++ b/translation/dest/broadcast/da-DK.xml @@ -8,6 +8,7 @@ Live turnerings-udsendelser Ny live-udsendelse + Udsendelser, du abonnerer på Om udsendelse Ingen runder endnu. Sådan bruges Lichess-udsendelser. @@ -40,8 +41,8 @@ Rediger rundestudie Slet denne turnering Slet hele turneringen, alle dens runder og alle dens partier. - Automatisk rangliste - Beregn og vis en simpel rangliste baseret på resultater af partier + Automatisk rangliste + Beregn og vis en simpel rangliste baseret på resultater af partier Valgfrit: udskift spillernavne, ratings og titler En linje pr. spiller, formateret således: Oprindeligt navn; Erstatningsnavn; Valgfri erstatnings-rating; Valgfri oprindelige erstatningstitel diff --git a/translation/dest/broadcast/de-DE.xml b/translation/dest/broadcast/de-DE.xml index a1f303bea7863..f474cc4bb9e13 100644 --- a/translation/dest/broadcast/de-DE.xml +++ b/translation/dest/broadcast/de-DE.xml @@ -8,6 +8,7 @@ Live-Turnierübertragungen Neue Liveübertragung + Abonnierte Übertragungen Über Übertragungen Noch keine Runden. Wie man Lichess-Übertragungen benutzt. @@ -40,8 +41,8 @@ Rundenstudie bearbeiten Dieses Turnier löschen Lösche definitiv das gesamte Turnier, alle seine Runden und Partien. - Automatische Rangliste - Berechne und zeige eine einfache Rangliste basierend auf den Spielergebnissen + Automatische Rangliste + Berechne und zeige eine einfache Rangliste basierend auf den Spielergebnissen Optional: Spielernamen, Wertungen und Titel ersetzen Eine Zeile pro Spieler, wie folgt formatiert: Originalname; Ersatzname; optional Ersatzwertung; optional Ersatztitel diff --git a/translation/dest/broadcast/en-US.xml b/translation/dest/broadcast/en-US.xml index 7580d5152ed79..10de1ced03bc8 100644 --- a/translation/dest/broadcast/en-US.xml +++ b/translation/dest/broadcast/en-US.xml @@ -8,6 +8,7 @@ Live tournament broadcasts New live broadcast + Subscribed broadcasts About broadcasts No rounds yet. How to use Lichess Broadcasts. @@ -40,8 +41,8 @@ Edit round study Delete this tournament Definitively delete the entire tournament, all its rounds and all its games. - Automatic leaderboard - Compute and display a simple leaderboard based on game results + Automatic leaderboard + Compute and display a simple leaderboard based on game results Optional: replace player names, ratings and titles One line per player, formatted as such: Original name; Replacement name; Optional replacement rating; Optional replacement title diff --git a/translation/dest/broadcast/eo-UY.xml b/translation/dest/broadcast/eo-UY.xml index 74e3f38f35786..ad79112fdb230 100644 --- a/translation/dest/broadcast/eo-UY.xml +++ b/translation/dest/broadcast/eo-UY.xml @@ -40,8 +40,8 @@ Redakti raŭndan studon Forigi ĉi tiun turniron Sendube forigi la tuta turniro, kaj ĝiajn raŭndojn kaj ĉiujn ĝiajn ludojn. - Aŭtomata ĉampionejo - Komputi kaj montri simplan ĉampionejon baze sur la ludrezultoj + Aŭtomata ĉampionejo + Komputi kaj montri simplan ĉampionejon baze sur la ludrezultoj Laŭvola: anstataŭi ludantaj nomoj, atingoj, kaj titoloj Po unu lino por unu ludanto, aranĝita tiel: Origna namo; Anstataŭa namo; Laŭvola anstataŭa atingo; Laŭvola anstataŭa titolo diff --git a/translation/dest/broadcast/es-ES.xml b/translation/dest/broadcast/es-ES.xml index 859a2d5490c72..809a742f18a8a 100644 --- a/translation/dest/broadcast/es-ES.xml +++ b/translation/dest/broadcast/es-ES.xml @@ -8,6 +8,7 @@ Emisiones de torneos en directo Nueva emisión en directo + Transmisiones suscritas Acerca de las transmisiones Aún no hay rondas. Como utilizar las transmisiones de Lichess. @@ -40,8 +41,8 @@ Editar estudio de ronda Elimina este torneo Elimina definitivamente todo el torneo, rondas y partidas incluidas. - Tabla de clasificación automática - Calcula y muestra una tabla de clasificación simple según los resultados de la partida + Tabla de clasificación automática + Calcula y muestra una tabla de clasificación simple según los resultados de la partida Opcional: reemplazar nombres de jugadores, puntuaciones y títulos Una línea por jugador, con este formato: Nombre original; Nombre de reemplazo; Puntuación opcional de reemplazo; Título opcional de reemplazo diff --git a/translation/dest/broadcast/eu-ES.xml b/translation/dest/broadcast/eu-ES.xml index 83644dd129c11..789e3042ae245 100644 --- a/translation/dest/broadcast/eu-ES.xml +++ b/translation/dest/broadcast/eu-ES.xml @@ -8,6 +8,7 @@ Txapelketen zuzeneko emanaldiak Zuzeneko emanaldi berria + Harpidetutako emanaldiak Zuzeneko emanaldiei buruz Ez dago txandarik. Nola erabili Lichessen Zuzenekoak. @@ -40,8 +41,8 @@ Editatu txandako azterlana Ezabatu txapelketa hau Txapelketa behin betiko ezabatu, bere txanda eta partida guztiak barne. - Sailkapen automatikoa - Partiden emaitzetan oinarritutako sailkapen sinplea kalkulatu eta erakutsi + Sailkapen automatikoa + Partiden emaitzetan oinarritutako sailkapen sinplea kalkulatu eta erakutsi Hautazkoa: aldatu jokalarien izen, puntuazio eta tituluak Lerro bat jokalari bakotizeko, horrela formateatuta: Jatorrizko izena; Ordezko izena; Ordezko puntuazioa (hautazkoa); Ordezko titulua (hautazkoa) diff --git a/translation/dest/broadcast/fa-IR.xml b/translation/dest/broadcast/fa-IR.xml index bbb9067c910e5..3b00ef5da635c 100644 --- a/translation/dest/broadcast/fa-IR.xml +++ b/translation/dest/broadcast/fa-IR.xml @@ -8,6 +8,7 @@ پخش زنده مسابقات پخش زنده جدید + پخش‌های دنبال‌شده درباره پخش‌های همگانی هنوز هیچ دوری وجود ندارد. نحوه استفاده از پخش همگانی Lichess. @@ -40,8 +41,8 @@ ویرایش مطالعه دور حذف این مسابقات کل مسابقات، شامل همه دورها و بازی‌هایش را به طور کامل حذف کن. - جدول رده‌بندی خودکار - یک جدول رده‌بندی ساده را بر اساس نتایج بازی‌ها حساب کن و نمایش بده + جدول رده‌بندی خودکار + یک جدول رده‌بندی ساده را بر اساس نتایج بازی‌ها حساب کن و نمایش بده اختیاری: عوض کردن نام، درجه‌بندی و عنوان بازیکنان یک خط برای هر بازیکن، به این صورت قالب‌بندی شده: نام اصلی؛ نام جایگزین؛ اختیاری-درجه‌بندی جایگزین؛ اختیاری-عنوان جایگزین diff --git a/translation/dest/broadcast/fi-FI.xml b/translation/dest/broadcast/fi-FI.xml index 039172fbc0a3f..feefe1496dff3 100644 --- a/translation/dest/broadcast/fi-FI.xml +++ b/translation/dest/broadcast/fi-FI.xml @@ -40,8 +40,8 @@ Kierrostutkielman muokkaus Poista tämä turnaus Poista lopullisesti koko turnaus, sen kaikki kierrokset ja kaikki pelit. - Automaattinen tulostaulukko - Laske ja näytä yksinkertainen tulostaulukko pelien tulosten pohjalta + Automaattinen tulostaulukko + Laske ja näytä yksinkertainen tulostaulukko pelien tulosten pohjalta Valinnainen: korvaa pelaajien nimet, vahvuusluvut ja arvonimet Yksi rivi pelaajaa kohden tässä muodossa: Alkuperäinen nimi; Korvaava nimi; Haluttaessa korvaava vahvuusluku; Haluttaessa korvaava arvonimi diff --git a/translation/dest/broadcast/fr-FR.xml b/translation/dest/broadcast/fr-FR.xml index d03157abf7dd0..b59448417aee6 100644 --- a/translation/dest/broadcast/fr-FR.xml +++ b/translation/dest/broadcast/fr-FR.xml @@ -8,6 +8,7 @@ Diffusions de tournois en direct Nouvelle diffusion en direct + Diffusions suivies À propos des diffusions Aucune ronde pour le moment. Comment utiliser les diffusions dans Lichess. @@ -40,8 +41,8 @@ Modifier l\'étude de la ronde Supprimer ce tournoi Supprimer définitivement le tournoi, toutes ses rondes et toutes ses parties. - Classement automatique - Calculer et afficher un échiquier principal simplifié basé sur les résultats de parties + Classement automatique + Calculer et afficher un échiquier principal simplifié basé sur les résultats de parties Facultatif : remplacer les noms des joueurs, les cotes et les titres Une ligne par joueur, formatée comme suit : Nom d\'origine; Nom de remplacement; Cote de remplacement facultative; Titre de remplacement facultatif diff --git a/translation/dest/broadcast/gl-ES.xml b/translation/dest/broadcast/gl-ES.xml index 24471643cd054..3475ff7ad67b1 100644 --- a/translation/dest/broadcast/gl-ES.xml +++ b/translation/dest/broadcast/gl-ES.xml @@ -8,6 +8,7 @@ Emisións de torneos en directo Nova emisión en directo + Retransmisións subscritas Sobre as retransmisións Aínda non hai roldas. Como usar as Retransmisións de Lichess. @@ -40,8 +41,8 @@ Editar o estudo da rolda Eliminar este torneo Eliminar o torneo de forma definitiva, con todas as súas roldas e partidas. - Listaxe de líderes automática - Calcula e amosa unha listaxe de líderes simple baseada nos resultados das partidas + Listaxe de líderes automática + Calcula e amosa unha listaxe de líderes simple baseada nos resultados das partidas Opcional: substitúe os nomes dos xogadores, as puntuacións e os títulos Unha liña por xogador, con este formato: Nome orixinal; Nome alternativo; Puntuación alternativa (opcional); Título alternativo (opcional) diff --git a/translation/dest/broadcast/gsw-CH.xml b/translation/dest/broadcast/gsw-CH.xml index f873490ef2114..48721c5eec3a5 100644 --- a/translation/dest/broadcast/gsw-CH.xml +++ b/translation/dest/broadcast/gsw-CH.xml @@ -8,6 +8,7 @@ Live Turnier-Überträgige Neui Live-Überträgige + Abonnierti Überträgige Über Überträgige No kei Rundene. Wie mer Lichess-Überträgige benutzt. @@ -40,8 +41,8 @@ Schtudie Rundi bearbeite Lösch das Turnier Das ganze Turnier, alli Runde und alli Partie definitiv lösche. - Automatischi Ranglischte - Eifachi Ranglischte, uf Grund vu Schpielergäbnis berächnet, azeige + Automatischi Ranglischte + Eifachi Ranglischte, uf Grund vu Schpielergäbnis berächnet, azeige Optional: Spielernäme, Bewertinge und Titel usblände 1 Zile pro Schpiller, formatiert wie folgt: Ursprüngliche Name; Ersatzname; Optionali Ersatzbewertig; Optionale Ersatzbezeichnig diff --git a/translation/dest/broadcast/he-IL.xml b/translation/dest/broadcast/he-IL.xml index 85494ca147486..e1d7a00228bbf 100644 --- a/translation/dest/broadcast/he-IL.xml +++ b/translation/dest/broadcast/he-IL.xml @@ -10,6 +10,7 @@ צפייה ישירה בטורנירים הקרנה ישירה חדשה + הקרנות שנרשמת אליהן הסבר על הקרנות טרם נוצרו סבבים. איך להשתמש בהקרנות ב-Lichess. @@ -42,8 +43,8 @@ עריכת לוח הלמידה של הסבב מחיקת הטורניר הזה מחיקה לצמיתות של הטורניר הזה, על כל סבביו והמשחקים שבו. - טבלה אוטומטית - הצגת טבלה פשוטה שמתבססת על תוצאות המשחקים + טבלה אוטומטית + הצגת טבלה פשוטה שמתבססת על תוצאות המשחקים אופציונאלי: החלפת השמות, הדירוגים והתארים של השחקנים שחקן אחד בכל שורה, על פי התבנית הבאה: שם מקורי; שם רצוי; דירוג להצגה; תואר להצגה diff --git a/translation/dest/broadcast/hy-AM.xml b/translation/dest/broadcast/hy-AM.xml index ae1bdb921c62e..16be2356bdea2 100644 --- a/translation/dest/broadcast/hy-AM.xml +++ b/translation/dest/broadcast/hy-AM.xml @@ -4,6 +4,7 @@ Իմ հեռարձակումները Մրցաշարի ուղիղ հեռարձակումներ Նոր ուղիղ հեռարձակում + Բաժանորդագրված հեռարձակումներ Ավելացնել խաղափուլ Ընթացիկ Առաջիկայում սպասվող diff --git a/translation/dest/broadcast/it-IT.xml b/translation/dest/broadcast/it-IT.xml index 13b559c9b1f64..6abf28b891312 100644 --- a/translation/dest/broadcast/it-IT.xml +++ b/translation/dest/broadcast/it-IT.xml @@ -8,6 +8,7 @@ Tornei in diretta Nuova diretta + Trasmissioni abbonate Informazioni sulle trasmissioni Ancora nessun turno. Istruzioni delle trasmissioni Lichess. @@ -40,8 +41,8 @@ Modifica lo studio del turno Elimina questo torneo Elimina definitivamente l\'intero torneo, tutti i turni e tutte le partite. - Classifica automatica - Calcola e mostra una semplice classifica basata sui risultati delle partite + Classifica automatica + Calcola e mostra una semplice classifica basata sui risultati delle partite Facoltativo: sostituisci i nomi dei giocatori, i punteggi e i titoli Una riga per giocatore, formattata come segue: Nome; Nome sostitutivo; Punteggio sostitutivo (facoltativo); Titolo sostitutivo (facoltativo) diff --git a/translation/dest/broadcast/ja-JP.xml b/translation/dest/broadcast/ja-JP.xml index 83de37def824d..23e9c8277f892 100644 --- a/translation/dest/broadcast/ja-JP.xml +++ b/translation/dest/broadcast/ja-JP.xml @@ -39,8 +39,8 @@ ラウンドの研究を編集 このトーナメントを削除 トーナメント全体(全ラウンド、全ゲーム)を削除する。 - 自動ランキング - ゲーム結果から簡単なランキングを計算して表示する + 自動ランキング + ゲーム結果から簡単なランキングを計算して表示する オプション:プレイヤーの名前、レーティング、タイトルの変更 1 人 1 行、次の形式で: 元の名前;変更後の名前;変更後のレーティング(オプション);変更後のタイトル(オプション) diff --git a/translation/dest/broadcast/mr-IN.xml b/translation/dest/broadcast/mr-IN.xml index cbd33cb1940cc..1074843f30081 100644 --- a/translation/dest/broadcast/mr-IN.xml +++ b/translation/dest/broadcast/mr-IN.xml @@ -40,8 +40,8 @@ फेरीचा अभ्यास संपादित करा ही स्पर्धा हटवा संपूर्ण टूर्नामेंट, त्याच्या सर्व फेऱ्या आणि त्याचे सर्व गेम निश्चितपणे हटवा. - स्वयंचलित लीडरबोर्ड - गेम परिणामांवर आधारित एक साधा लीडरबोर्ड कम्प्युट करा आणि प्रदर्शित करा + स्वयंचलित लीडरबोर्ड + गेम परिणामांवर आधारित एक साधा लीडरबोर्ड कम्प्युट करा आणि प्रदर्शित करा पर्यायी: खेळाडूंची नावे, रेटिंग आणि शीर्षके बदला प्रति खेळाडू एक ओळ, असे स्वरूपित: मूळ नाव; बदलण्याचे नाव; पर्यायी बदली रेटिंग; पर्यायी बदली शीर्षक diff --git a/translation/dest/broadcast/nb-NO.xml b/translation/dest/broadcast/nb-NO.xml index ca81bb9e8ed4c..a8b2c2a3751a5 100644 --- a/translation/dest/broadcast/nb-NO.xml +++ b/translation/dest/broadcast/nb-NO.xml @@ -40,8 +40,8 @@ Rediger rundestudie Slett denne turneringen Slett hele turneringen for godt, sammen med alle rundene og alle partiene. - Automatisk ledertabell - Beregn og vis en enkel ledertabell basert på resultatene av partiene + Automatisk ledertabell + Beregn og vis en enkel ledertabell basert på resultatene av partiene Valgfritt: erstatt spillernavn, ratinger og titler Én linje per spiller, formatert slik: Originalt navn; Erstattet navn; Valgfri erstattet rating; Valgfri erstattet tittel diff --git a/translation/dest/broadcast/nl-NL.xml b/translation/dest/broadcast/nl-NL.xml index c0aaad83d6ede..f2254f3300290 100644 --- a/translation/dest/broadcast/nl-NL.xml +++ b/translation/dest/broadcast/nl-NL.xml @@ -40,8 +40,8 @@ Studieronde bewerken Verwijder dit toernooi Verwijder definitief het hele toernooi, inclusief alle rondes en partijen. - Automatisch scorebord - Bereken en toon een eenvoudig scorebord gebaseerd op de uitslagen + Automatisch scorebord + Bereken en toon een eenvoudig scorebord gebaseerd op de uitslagen Optioneel: vervang spelersnamen, ratings en titels Eén regel per speler, geformatteerd zoals hieronder: Oorspronkelijke naam; Nieuwe naam; Nieuwe rating (optioneel); Nieuwe titel (optioneel) diff --git a/translation/dest/broadcast/nn-NO.xml b/translation/dest/broadcast/nn-NO.xml index 3112b1e770667..a6d381f83bba6 100644 --- a/translation/dest/broadcast/nn-NO.xml +++ b/translation/dest/broadcast/nn-NO.xml @@ -8,6 +8,7 @@ Direktesende turneringar Ny direktesending + Sendingar du abonnerar på Om sending Så langt ingen rundar. Korleis bruke Lichess-sendingar. @@ -40,8 +41,8 @@ Rediger rundestudie Slett denne turneringa Slett heile turneringa med alle rundene og alle partia. - Automatisk rangliste - Berekne og vise ei enkel rangliste baseret på resultatar frå partia + Automatisk rangliste + Berekne og vise ei enkel rangliste baseret på resultatar frå partia Valfritt: erstatt spelaramn, rangeringar og titlar Ei linje per spelar, formattert slik: Opphavleg namn; valfritt alternativt namn; valfri alternativ rating; valfri alternativ tittel diff --git a/translation/dest/broadcast/pl-PL.xml b/translation/dest/broadcast/pl-PL.xml index 23dcc7c0b1bf0..79fd46c1c6312 100644 --- a/translation/dest/broadcast/pl-PL.xml +++ b/translation/dest/broadcast/pl-PL.xml @@ -10,6 +10,7 @@ Transmisje turniejów na żywo Nowa transmisja na żywo + Subskrybowane transmisje O transmisji Nie ma jeszcze rund. Jak korzystać z transmisji na Lichess. @@ -42,8 +43,8 @@ Edytuj opracowanie rundy Usuń ten turniej Ostatecznie usuń cały turniej, jego wszystkie rundy i partie. - Automatyczna tablica wyników - Oblicz i wyświetl prostą tablicę wyników w oparciu o wyniki partii + Automatyczna tablica wyników + Oblicz i wyświetl prostą tablicę wyników w oparciu o wyniki partii Opcjonalnie: zastąp nazwy, rankingi i tytuły graczy Jeden wiersz na gracza, w następującym formacie: oryginalna nazwa; nowa nazwa; nowy ranking (opcjonalnie); nowy tytuł (opcjonalnie) diff --git a/translation/dest/broadcast/pt-BR.xml b/translation/dest/broadcast/pt-BR.xml index 29c0d0aaaa430..5a71bd57c7e76 100644 --- a/translation/dest/broadcast/pt-BR.xml +++ b/translation/dest/broadcast/pt-BR.xml @@ -40,8 +40,8 @@ Editar estudo da rodada Excluir este torneio Excluir permanentemente todo o torneio, incluindo todas as rodadas e jogos. - Placar automático - Calcula e exibe um placar simples baseado nos resultados dos jogos + Placar automático + Calcula e exibe um placar simples baseado nos resultados dos jogos Opcional: nomes de jogador, classificações e títulos alternativos Uma linha por jogador, no seguinte formato: Nome original; Nome alternativo; Classificação alternativa opcional; Título alternativo opcional diff --git a/translation/dest/broadcast/pt-PT.xml b/translation/dest/broadcast/pt-PT.xml index 9ba3aed2e9ee4..79aedd734f364 100644 --- a/translation/dest/broadcast/pt-PT.xml +++ b/translation/dest/broadcast/pt-PT.xml @@ -8,6 +8,7 @@ Transmissões do torneio em direto Nova transmissão em direto + Transmissões subscritas Sobre Transmissões Sem rondas ainda. Como usar as Transmissões do Lichess. @@ -40,8 +41,8 @@ Editar estudo da ronda Eliminar este torneio Excluir definitivamente todo o torneio, todas as rondas e todos os jogos. - Tabela de classificação automática - Calcula e exibe uma tabela de classificação simples baseada nos resultados dos jogos + Tabela de classificação automática + Calcula e exibe uma tabela de classificação simples baseada nos resultados dos jogos Opcional: substituir nomes de jogadores, ratings e títulos Uma linha por jogador, formatada da seguinte forma: Nome original; Nome substituto; Opcional: Ranting de substituição; Opcional: Título de substituição diff --git a/translation/dest/broadcast/ro-RO.xml b/translation/dest/broadcast/ro-RO.xml index dc75925a89a6a..f111eccf14a5e 100644 --- a/translation/dest/broadcast/ro-RO.xml +++ b/translation/dest/broadcast/ro-RO.xml @@ -41,8 +41,8 @@ Editare rundă de studiu Șterge acest turneu Sigur doresc să ștergeți întregul turneu, toate rundele și toate jocurile sale. - Clasament automat - Calculează și afișează un clasament simplu bazat pe rezultatele jocului + Clasament automat + Calculează și afișează un clasament simplu bazat pe rezultatele jocului Opțional: înlocuiește numele jucătorilor, evaluări și titluri O singură linie per jucător, formatată ca such: Nume original; Nume de înlocuire; Clasificare de înlocuire opțională; Titlu de înlocuire opțională diff --git a/translation/dest/broadcast/ru-RU.xml b/translation/dest/broadcast/ru-RU.xml index 8da69c0cbe35a..f5fdb76ebc568 100644 --- a/translation/dest/broadcast/ru-RU.xml +++ b/translation/dest/broadcast/ru-RU.xml @@ -10,6 +10,7 @@ Прямые трансляции турнира Новая прямая трансляция + Подписанные рассылки О трансляции Пока нет туров. Как пользоваться трансляциями Lichess. @@ -42,8 +43,8 @@ Редактировать студию тура Удалить этот турнир Окончательно удалить весь турнир, его туры и партии. - Автоматическая таблица лидеров - Вычислять и отображать простую таблицу лидеров на основе результатов партий + Автоматическая таблица лидеров + Вычислять и отображать простую таблицу лидеров на основе результатов партий Необязательно: заменять имена игроков, рейтинги и звания По одной строке на каждого игрока, форматирование по образцу: Имя в системе; Имя для замены; Рейтинг для замены (необязательно); Звание для замены (необязательно) diff --git a/translation/dest/broadcast/sk-SK.xml b/translation/dest/broadcast/sk-SK.xml index 0d3c335fbeed7..01bdd20339fb0 100644 --- a/translation/dest/broadcast/sk-SK.xml +++ b/translation/dest/broadcast/sk-SK.xml @@ -10,6 +10,7 @@ Živé vysielanie turnaja Nové živé vysielanie + Odoberané vysielania Pridať kolo Prebiehajúci Nasledujúce diff --git a/translation/dest/broadcast/sl-SI.xml b/translation/dest/broadcast/sl-SI.xml index 76a1c352e0eee..c472ba78ab1a2 100644 --- a/translation/dest/broadcast/sl-SI.xml +++ b/translation/dest/broadcast/sl-SI.xml @@ -10,6 +10,7 @@ Prenos turnirjev v živo Nov prenos v živo + Naročene oddaje O oddaji Ni še krogov. Kako uporabljati Lichess Broadcasts. @@ -42,8 +43,8 @@ Uredi krog študije Zbrišite ta turnir Dokončno izbrišite celoten turnir, vse njegove kroge in vse njegove igre. - Samodejna lestvica najboljših - Izračunajte in prikažite preprosto lestvico najboljših na podlagi rezultatov igre + Samodejna lestvica najboljših + Izračunajte in prikažite preprosto lestvico najboljših na podlagi rezultatov igre Izbirno: zamenjajte imena igralcev, rejtinge in nazive Ena vrstica na igralca, oblikovana tako: izvirno ime; Nadomestno ime; Izbirno rejting zamenjave; Izbirno nadomestni naslov diff --git a/translation/dest/broadcast/sq-AL.xml b/translation/dest/broadcast/sq-AL.xml index 0946a1d811acd..0fca2e36a7557 100644 --- a/translation/dest/broadcast/sq-AL.xml +++ b/translation/dest/broadcast/sq-AL.xml @@ -8,6 +8,7 @@ Transmetime të drejtpërdrejta turnesh Transmetim i ri i drejtpërdrejtë + Transmetime me pajtim Rreth transmetimeve Ende pa raunde. Si të përdoren Transmetimet Lichess. @@ -39,8 +40,8 @@ Përpunoni analizë raundi Fshije këtë turne Fshihe përfundimisht krejt turneun, krejt raundet e tij dhe krejt lojërat në të. - Tabelë automatike - Harto dhe shfaq një tabelë të thjeshtë bazuar në përfundime lojërash + Tabelë automatike + Harto dhe shfaq një tabelë të thjeshtë bazuar në përfundime lojërash Opsionale: zëvendësoni emra lojëtarësh, vlerësime dhe tituj Një rresht për lojtar, formatuar kështu: Emri origjinal name; Emri zëvendësim; Vlerësim opsional zëvendësim; Titull opsional zëvendësim diff --git a/translation/dest/broadcast/sv-SE.xml b/translation/dest/broadcast/sv-SE.xml index b15c53e612daf..2187e62f1605e 100644 --- a/translation/dest/broadcast/sv-SE.xml +++ b/translation/dest/broadcast/sv-SE.xml @@ -40,8 +40,8 @@ Redigera studie för ronden Radera turnering Definitivt radera turnering. - Automatisk topplista - Beräkna och visa en enkel topplista baserat på spelresultat + Automatisk topplista + Beräkna och visa en enkel topplista baserat på spelresultat Valfritt: byt ut spelarnamn, ranking och titlar En rad per spelare, formaterad som sådan: Originalnamn; Ersättningsnamn; Valfritt ersättningsranking; Valfri ersättningstitel diff --git a/translation/dest/broadcast/th-TH.xml b/translation/dest/broadcast/th-TH.xml index 46fe416b3247f..df4c23117fbfa 100644 --- a/translation/dest/broadcast/th-TH.xml +++ b/translation/dest/broadcast/th-TH.xml @@ -24,7 +24,7 @@ URL การถ่ายทอดสด URL รอบปัจจุบัน URL เกมปัจจุบัน - ตารางผู้นำอัตโนมัติ - คำนวณและแสดงกระดานผู้นำอย่างง่ายตามผลลัพธ์ของเกม + ตารางผู้นำอัตโนมัติ + คำนวณและแสดงกระดานผู้นำอย่างง่ายตามผลลัพธ์ของเกม ตัวเลือก: แทนที่ชื่อผู้เล่น, เรดติ้ง และ ตำแหน่ง diff --git a/translation/dest/broadcast/uk-UA.xml b/translation/dest/broadcast/uk-UA.xml index eb47c0ddc2889..bb5b2a9a4e69e 100644 --- a/translation/dest/broadcast/uk-UA.xml +++ b/translation/dest/broadcast/uk-UA.xml @@ -10,6 +10,7 @@ Онлайн трансляції турнірів Нова трансляція + Обрані трансляції Про трансляцію Поки що немає раундів. Як користуватися Lichess трансляціями. @@ -42,8 +43,8 @@ Редагувати дослідження туру Видалити турнір Остаточно видалити весь турнір, всі його раунди та всі його ігри. - Автоматична таблиця лідерів - Розрахунки та показ простої таблиці лідерів на основі результатів гри + Автоматична таблиця лідерів + Розрахунки та показ простої таблиці лідерів на основі результатів гри Опціонально: замінити імена гравців, рейтинги та заголовки Один рядок на одного гравця, приклад форматування нижче: Справжнє ім\'я; ім\'я на заміну; замінити рейтинг (опціонально); замінити звання (опціонально) diff --git a/translation/dest/broadcast/vi-VN.xml b/translation/dest/broadcast/vi-VN.xml index 8088e8a5bf7e9..f88149b106ad7 100644 --- a/translation/dest/broadcast/vi-VN.xml +++ b/translation/dest/broadcast/vi-VN.xml @@ -7,6 +7,7 @@ Các giải đấu phát sóng trực tiếp Phát sóng trực tiếp mới + Các phát sóng đã đăng ký theo dõi Giới thiệu về phát sóng Chưa có vòng nào. Cách sử dụng Phát sóng của Lichess. @@ -39,8 +40,8 @@ Chỉnh sửa vòng nghiên cứu Xóa giải đấu này Xóa dứt khoát toàn bộ giải đấu, tất cả các vòng và tất cả ván cờ trong đó. - Bảng xếp hạng tự động - Tính toán và hiển thị bảng xếp hạng đơn giản dựa trên kết quả ván đấu + Bảng xếp hạng tự động + Tính toán và hiển thị bảng xếp hạng đơn giản dựa trên kết quả ván đấu Tùy chọn: biệt danh, hệ số Elo và danh hiệu Một dòng cho mỗi người chơi, được định dạng như sau: Tên khai sinh; Tên thay thế; Hệ số Elo thay thế tùy chọn; Danh hiệu thay thế tùy chọn diff --git a/translation/dest/broadcast/zh-CN.xml b/translation/dest/broadcast/zh-CN.xml index 62f08619c739e..6804de2081bf8 100644 --- a/translation/dest/broadcast/zh-CN.xml +++ b/translation/dest/broadcast/zh-CN.xml @@ -7,6 +7,7 @@ 赛事转播 新实况转播 + 已订阅的转播 关于转播 尚未有任何棋局 如何使用Lichess转播 @@ -37,8 +38,8 @@ 编辑该轮次的棋局研究 删除该锦标赛 确定删除整个锦标赛、所有轮次和其中所有比赛。 - 自动生成排行榜 - 根据对局结果计算并显示一个简单的排行榜 + 自动生成排行榜 + 根据对局结果计算并显示一个简单的排行榜 可选:替换选手的姓名,等级分和头衔 每行一位选手,格式如下: 原始的名字; 替换的名字; 可选的替换的等级分; 可选的替换的头衔 diff --git a/translation/dest/dgt/fa-IR.xml b/translation/dest/dgt/fa-IR.xml index 467cb4cd3657c..a169c88e8686f 100644 --- a/translation/dest/dgt/fa-IR.xml +++ b/translation/dest/dgt/fa-IR.xml @@ -1,4 +1,6 @@ بارگذاری مجدد صفحه + اتصال به لیچس + متن به گفتار diff --git a/translation/dest/faq/hu-HU.xml b/translation/dest/faq/hu-HU.xml index ebe041b28f75b..779b846f73e88 100644 --- a/translation/dest/faq/hu-HU.xml +++ b/translation/dest/faq/hu-HU.xml @@ -143,4 +143,5 @@ Jobb csak relatív összehasonlítási alapként tekinteni ezekre a számokra: a Kattints a lakat ikonra a böngésző címsorában, a lichess.org mellett. Utána válaszd ki, hogy engedélyezed vagy tiltod az Lichess értesítéseit. + Engedélyezed hangok automatikus lejátszását? diff --git a/translation/dest/oauthScope/hu-HU.xml b/translation/dest/oauthScope/hu-HU.xml index d9a1e1ec8abb1..da66f6bf007b9 100644 --- a/translation/dest/oauthScope/hu-HU.xml +++ b/translation/dest/oauthScope/hu-HU.xml @@ -21,7 +21,7 @@ Feladvány-aktivitási adatok olvasása Privát csapatinformációk Csatlakozás és kilépés csapatokból - Csapatműveletek: PMek küldése, tagok eltávolítása + Csapatműveletek: privát üzenetek küldése, tagok eltávolítása Követett játékosok megtekintése Játékosok követése Privát üzenete küldése játékosoknak diff --git a/translation/dest/patron/vi-VN.xml b/translation/dest/patron/vi-VN.xml index c8d6c6abd1441..59fd989527648 100644 --- a/translation/dest/patron/vi-VN.xml +++ b/translation/dest/patron/vi-VN.xml @@ -56,7 +56,7 @@ Tuy nhiên, Patron được quyền khoe khoang với những đôi cánh Ngư Cảm ơn sự giúp đỡ của bạn rất nhiều. Bạn thật tuyệt vời! Trạng thái hiện tại Lần thanh toán tiếp theo - Bạn sẽ trả %1$s vào ngày %2$s. + Bạn sẽ bị tính phí %1$s vào ngày %2$s. Ủng hộ thêm ngay bây giờ Tặng đôi cánh Người bảo trợ Tặng đôi cánh Người bảo trợ cho kỳ thủ diff --git a/translation/dest/site/nl-NL.xml b/translation/dest/site/nl-NL.xml index d70f17ea730ff..c274ced055941 100644 --- a/translation/dest/site/nl-NL.xml +++ b/translation/dest/site/nl-NL.xml @@ -418,6 +418,7 @@ Zwart zet schaakmat in één zet Probeer het opnieuw Opnieuw aan het verbinden + Offline %s vriend online %s vrienden online diff --git a/translation/dest/site/ru-RU.xml b/translation/dest/site/ru-RU.xml index 5ae53c020ce9e..518b4b81d3896 100644 --- a/translation/dest/site/ru-RU.xml +++ b/translation/dest/site/ru-RU.xml @@ -476,6 +476,7 @@ Чёрные ставят мат в один ход Повторить Переподключение + Офлайн %s друг онлайн %s друга онлайн diff --git a/translation/dest/site/sq-AL.xml b/translation/dest/site/sq-AL.xml index c217e01322887..8b4995f6c2c55 100644 --- a/translation/dest/site/sq-AL.xml +++ b/translation/dest/site/sq-AL.xml @@ -419,6 +419,7 @@ loje dhe URL për ta ndarë me të tjerë. I ziu në shah-mat me një lëvizje Riprovoni Po rilidhet + Jashtë linje %s shok në linjë %s shokë në linjë diff --git a/translation/dest/site/ta-IN.xml b/translation/dest/site/ta-IN.xml index cd171df462e73..4998c18c0974c 100644 --- a/translation/dest/site/ta-IN.xml +++ b/translation/dest/site/ta-IN.xml @@ -13,7 +13,7 @@ உரையாடலை மாற்று உரையாடு விலகு - முழுத்தடை + நிகர்தடை நகர்த்த வாய்ப்பின்மை வெள்ளை கருப்பு @@ -403,9 +403,9 @@ இது ஒரு சதுரங்கமுறை மாந்தத்தேர்வு (CAPTCHA) பலகையிலே சொடுக்கி நகர்த்துங்கள், நீங்கள் மாந்தரென்று நிறுவுங்கள் சதுரங்க புதிரை தீர்க்கவும். - முழுத்தடையன்று - வெள்ளையின் அடுத்த நகர்வில் இறுதி முற்றுகை - கறுப்பின் அடுத்த நகர்வில் இறுதி முற்றுக்கை + நிகர்தடையன்று + வெள்ளையின் அடுத்த நகர்வில் நிகர்தடை + கறுப்பின் அடுத்த நகர்வில் நிகர்தடை மீள்முயற்சி மீண்டும் இணைகிறது பிடித்தமான எதிராளிகள் diff --git a/translation/dest/site/vi-VN.xml b/translation/dest/site/vi-VN.xml index caec92a019904..67c02d711be7a 100644 --- a/translation/dest/site/vi-VN.xml +++ b/translation/dest/site/vi-VN.xml @@ -130,7 +130,7 @@ %s sai lầm nghiêm trọng - %s nước đi sai + %s sai lầm %s nước đi không chính xác @@ -337,7 +337,7 @@ ≥ %s ván xếp hạng - ≥ %1$s ván %2$s xếp hạng + Đã chơi ≥ %1$s ván %2$s xếp hạng Bạn cần chơi thêm %1$s ván %2$s xếp hạng @@ -347,8 +347,8 @@ Hệ số %s của bạn là tạm thời Hệ số %1$s (%2$s) của bạn quá cao - Hệ số %1$s theo tuần của bạn quá cao (%2$s) - Hệ số %1$s của bạn quá thấp (%2$s) + Hệ số %1$s hàng tuần của bạn quá cao (%2$s) + Hệ số %1$s (%2$s) của bạn quá thấp Hệ số %2$s ≥ %1$s Xếp hạng %2$s tuần trước ≤ %1$s Phải ở trong đội %s @@ -404,7 +404,7 @@ trò chuyện trong ván đấu và có một URL có thể chia sẻ công khai Đã chặn Bỏ chặn Theo dõi bạn - %1$s bắt đầu theo dõi %2$s + %1$s đã bắt đầu theo dõi %2$s %s người theo dõi @@ -646,7 +646,7 @@ trò chuyện trong ván đấu và có một URL có thể chia sẻ công khai Thiết lập Đồng hồ Fischer. Bạn càng chơi với nhiều người thì càng có thể cần nhiều thời gian. Bạn có thể thêm thời gian ban đầu cho đồng hồ của mình để đấu cờ đồng loạt dễ hơn. Thời gian thêm ban đầu cho người chủ trì - Thêm thời gian ban đầu vào đồng hồ của bạn cho mỗi người chơi tham gia cờ đồng loạt. + Thêm thời gian ban đầu vào đồng hồ của bạn cho mỗi người chơi tham gia sự kiện đồng loạt. Thời gian thêm cho mỗi người tham gia Các giải đấu của Lichess Các câu hỏi hay gặp về giải đấu Đấu trường @@ -658,7 +658,7 @@ trò chuyện trong ván đấu và có một URL có thể chia sẻ công khai chuyển đến nước đi đầu/cuối Biến được chọn theo chu kỳ hiện/ẩn bình luận - vào/thoát thế cờ + vào/thoát biến Yêu cầu máy tính phân tích, Học từ sai lầm của bạn Tiếp theo (Học từ sai lầm của bạn) Nước đi sai nghiêm trọng tiếp theo @@ -869,8 +869,8 @@ trò chuyện trong ván đấu và có một URL có thể chia sẻ công khai Gia nhập %1$s để đăng trong diễn đàn này Đội %1$s Bạn chưa thể đăng bài lên diễn đàn bây giờ. Hãy chơi vài ván đã! - Đăng kí - Hủy đăng ký + Đăng ký theo dõi + Hủy đăng ký theo dõi đã nhắc đến bạn trong \"%1$s\". %1$s đã nhắc đến bạn trong \"%2$s\". đã mời bạn tham gia \"%1$s\". diff --git a/translation/dest/site/zh-CN.xml b/translation/dest/site/zh-CN.xml index ff9a19c6746d4..fffb5f9dc777c 100644 --- a/translation/dest/site/zh-CN.xml +++ b/translation/dest/site/zh-CN.xml @@ -389,6 +389,7 @@ 黑方一步将死 重试 重新连接中 + 离线 在线好友:%s diff --git a/translation/dest/tfa/hu-HU.xml b/translation/dest/tfa/hu-HU.xml index 2add4f78bed39..6bced8e3d4ed4 100644 --- a/translation/dest/tfa/hu-HU.xml +++ b/translation/dest/tfa/hu-HU.xml @@ -2,7 +2,7 @@ Kétlépcsős azonosítás Kétlépcsős azonosítás használatával a fiók biztonsága tovább növelhető. - A kétfaktoros anozosítás használatához az alábbi alkalmazásokat ajánljuk: + A kétfaktoros azonosítás használatához az alábbi alkalmazásokat ajánljuk: Olvasd be a QR kódot az app-al. Add meg a jelszót és az hitelesítő kódot amit az alkalmazás generált a beállítás befejezéséhez. Minden bejelentkezéskor szükséged lesz hitelesítő kódra. Ha nem sikerül beolvasni a kódot, írd be ezt a jelszót %s az alkalmazásban. diff --git a/translation/dest/timeago/hu-HU.xml b/translation/dest/timeago/hu-HU.xml index b956a941035c2..526ca2e60334a 100644 --- a/translation/dest/timeago/hu-HU.xml +++ b/translation/dest/timeago/hu-HU.xml @@ -54,4 +54,13 @@ %s éve %s éve + + %s perc van hátra + %s perc van hátra + + + %s óra van hátra + %s óra van hátra + + befejeződött From 8995231ba243c719ed88c8a5a2fe2760181e2db0 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 12 Feb 2024 12:29:35 +0100 Subject: [PATCH 25/39] this.observer is always defined --- ui/site/src/component/dialog.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/site/src/component/dialog.ts b/ui/site/src/component/dialog.ts index 908ead676b0bd..10dfc378799f1 100644 --- a/ui/site/src/component/dialog.ts +++ b/ui/site/src/component/dialog.ts @@ -117,7 +117,7 @@ class DialogWrapper implements Dialog { const justThen = Date.now(); const cancelOnInterval = () => Date.now() - justThen > 200 && this.close('cancel'); - this.observer?.observe(document.body, { childList: true, subtree: true }); + this.observer.observe(document.body, { childList: true, subtree: true }); view.parentElement?.style.setProperty('--vh', `${window.innerHeight}px`); view.addEventListener('click', e => e.stopPropagation()); From 1d31234664057265d86682c7beef82e479f89b7b Mon Sep 17 00:00:00 2001 From: Jonathan Gamble <101470903+schlawg@users.noreply.github.com> Date: Mon, 12 Feb 2024 21:51:08 -0600 Subject: [PATCH 26/39] don't link to unavailable games tab fix #14667 --- ui/analyse/src/study/relay/relayTourView.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ui/analyse/src/study/relay/relayTourView.ts b/ui/analyse/src/study/relay/relayTourView.ts index f10a7944f3bb4..28a2b07240cd8 100644 --- a/ui/analyse/src/study/relay/relayTourView.ts +++ b/ui/analyse/src/study/relay/relayTourView.ts @@ -200,19 +200,20 @@ const roundStateIcon = (round: RelayRound) => export function rounds(ctrl: StudyCtrl): VNode { const canContribute = ctrl.members.canContribute(); const relay = ctrl.relay!; - const fragment = relay.tab() === 'overview' ? '' : `#${relay.tab()}`; + const currentFrag = relay.tab() === 'overview' ? '' : `#${relay.tab()}`; return h( 'div.study__relay__rounds', { hook: onInsert(el => scrollToInnerSelector(el, '.active')) }, relay.data.rounds - .map(round => - h('div', { key: round.id, class: { active: ctrl.data.id == round.id } }, [ - h('a.link', { attrs: { href: `${relay.roundPath(round)}${fragment}` } }, round.name), + .map(round => { + const roundFrag = !round.finished && !round.ongoing && currentFrag === '#games' ? '' : currentFrag; + return h('div', { key: round.id, class: { active: ctrl.data.id == round.id } }, [ + h('a.link', { attrs: { href: `${relay.roundPath(round)}${roundFrag}` } }, round.name), roundStateIcon(round), canContribute && h('a.act', { attrs: { ...dataIcon(licon.Gear), href: `/broadcast/round/${round.id}/edit` } }), - ]), - ) + ]); + }) .concat( canContribute ? [ From 351bb651d4a95b163ae963a0ded60bda27bc08bc Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 13 Feb 2024 08:04:21 +0100 Subject: [PATCH 27/39] New Crowdin updates (#14662) * New translations: site.xml (Catalan) * New translations: site.xml (Persian) * New translations: site.xml (Vietnamese) * New translations: site.xml (German) * New translations: site.xml (Spanish) * New translations: site.xml (Danish) * New translations: site.xml (Hebrew) * New translations: site.xml (Italian) * New translations: site.xml (Dutch) * New translations: site.xml (Portuguese) * New translations: site.xml (Esperanto) * New translations: broadcast.xml (Esperanto) * New translations: preferences.xml (Danish) * New translations: onboarding.xml (Hindi) * New translations: puzzletheme.xml (Serbian (Cyrillic)) * New translations: site.xml (Polish) * New translations: site.xml (Slovenian) * New translations: site.xml (Norwegian Nynorsk) * New translations: puzzletheme.xml (Serbian (Cyrillic)) * New translations: timeago.xml (Serbian (Cyrillic)) * New translations: onboarding.xml (Serbian (Cyrillic)) * New translations: puzzletheme.xml (Vietnamese) * New translations: site.xml (Portuguese, Brazilian) * New translations: site.xml (Swiss German) * New translations: broadcast.xml (Portuguese, Brazilian) * New translations: voicecommands.xml (Portuguese, Brazilian) * New translations: puzzle.xml (Swiss German) * New translations: oauthscope.xml (Swiss German) * New translations: site.xml (French) * New translations: broadcast.xml (Japanese) --- translation/dest/broadcast/eo-UY.xml | 1 + translation/dest/broadcast/ja-JP.xml | 1 + translation/dest/broadcast/pt-BR.xml | 1 + translation/dest/oauthScope/gsw-CH.xml | 2 +- translation/dest/onboarding/hi-IN.xml | 3 +++ translation/dest/onboarding/sr-SP.xml | 17 ++++++++++++++++- translation/dest/preferences/da-DK.xml | 2 +- translation/dest/puzzle/gsw-CH.xml | 12 ++++++------ translation/dest/puzzleTheme/sr-SP.xml | 19 +++++++++++++++++++ translation/dest/puzzleTheme/vi-VN.xml | 2 +- translation/dest/site/ca-ES.xml | 2 +- translation/dest/site/da-DK.xml | 3 ++- translation/dest/site/de-DE.xml | 1 + translation/dest/site/eo-UY.xml | 1 + translation/dest/site/es-ES.xml | 1 + translation/dest/site/fa-IR.xml | 1 + translation/dest/site/fr-FR.xml | 1 + translation/dest/site/gsw-CH.xml | 1 + translation/dest/site/he-IL.xml | 1 + translation/dest/site/it-IT.xml | 1 + translation/dest/site/nl-NL.xml | 1 + translation/dest/site/nn-NO.xml | 1 + translation/dest/site/pl-PL.xml | 1 + translation/dest/site/pt-BR.xml | 5 +++-- translation/dest/site/pt-PT.xml | 1 + translation/dest/site/sl-SI.xml | 1 + translation/dest/site/vi-VN.xml | 3 ++- translation/dest/timeago/sr-SP.xml | 7 +++++++ translation/dest/voiceCommands/pt-BR.xml | 5 +++++ 29 files changed, 83 insertions(+), 15 deletions(-) diff --git a/translation/dest/broadcast/eo-UY.xml b/translation/dest/broadcast/eo-UY.xml index ad79112fdb230..68324ab508342 100644 --- a/translation/dest/broadcast/eo-UY.xml +++ b/translation/dest/broadcast/eo-UY.xml @@ -8,6 +8,7 @@ Vivaj turniraj elsendoj Nova viva elsendo + Abonitaj elsendoj Pri elsendoj Ankoraŭ neniom raŭndojn. Kiel uzi Lichess Elsendojn. diff --git a/translation/dest/broadcast/ja-JP.xml b/translation/dest/broadcast/ja-JP.xml index 23e9c8277f892..f3c264ff31191 100644 --- a/translation/dest/broadcast/ja-JP.xml +++ b/translation/dest/broadcast/ja-JP.xml @@ -7,6 +7,7 @@ 実戦トーナメントのライブ中継 新しいライブ中継 + 登録した配信 中継について まだラウンドはありません。 Lichess 中継の使い方。 diff --git a/translation/dest/broadcast/pt-BR.xml b/translation/dest/broadcast/pt-BR.xml index 5a71bd57c7e76..d63625f985ff8 100644 --- a/translation/dest/broadcast/pt-BR.xml +++ b/translation/dest/broadcast/pt-BR.xml @@ -8,6 +8,7 @@ Transmissões ao vivo do torneio Nova transmissão ao vivo + Transmissões em que você se inscreveu Sobre as transmissões Sem rodadas ainda. Como usar as transmissões do Lichess. diff --git a/translation/dest/oauthScope/gsw-CH.xml b/translation/dest/oauthScope/gsw-CH.xml index 70228495606a3..20130d1abbba2 100644 --- a/translation/dest/oauthScope/gsw-CH.xml +++ b/translation/dest/oauthScope/gsw-CH.xml @@ -17,7 +17,7 @@ Privati Schtudie und Überträgige läse Erschtell, aktualisier, lösch Schtudie und Überträgige Turnier erschtelle, aktualisiere und biträte - Puzzle Racer Ränne erschtelle und biträte + Ufgabe Ränne erschtelle und biträte Ufgabe Aktivitäte läse Privati Team Infos läse Tritt bi, verlah, und organisier es Team diff --git a/translation/dest/onboarding/hi-IN.xml b/translation/dest/onboarding/hi-IN.xml index 1b0e2e7c46a81..4e741ddd10449 100644 --- a/translation/dest/onboarding/hi-IN.xml +++ b/translation/dest/onboarding/hi-IN.xml @@ -11,4 +11,7 @@ दुनिया भर के विरोधियों से खेलें। Lichess पर अपने दोस्तों का अनुसरण करें। टूर्नामेंट में खेलें। + %1$s और %2$s से सीखें। + Lichess को अपने अनुसार सेट करें। + साइट में घूमें और मजा करें :) diff --git a/translation/dest/onboarding/sr-SP.xml b/translation/dest/onboarding/sr-SP.xml index 3ea04e700dfa8..40a3e08b02706 100644 --- a/translation/dest/onboarding/sr-SP.xml +++ b/translation/dest/onboarding/sr-SP.xml @@ -1,2 +1,17 @@ - + + Добродошли! + Добродошли на Lichess.org! + Ово је страница са твојим профилом. + Да ли ће овај налог користити дете? Можда ћете желети да омогућите %s. + Шта даље? Ево неколико сугестија: + Научи шаховска правила + Учи кроз шаховске тактичке проблеме. + Играј против вештачке интелгенције. + Играј против противника широм света. + Прати своје пријатеље на Lichessu. + Играј на турнирима. + Учи од %1$s и %2$s. + Конфигуриши Lichess онако како желиш. + Истражи сајт и забави се :) + diff --git a/translation/dest/preferences/da-DK.xml b/translation/dest/preferences/da-DK.xml index bb6554ecb40b2..d9aa316a7b817 100644 --- a/translation/dest/preferences/da-DK.xml +++ b/translation/dest/preferences/da-DK.xml @@ -49,7 +49,7 @@ Flyt kongen over på tårn Lav træk med tastaturet Angiv træk med din stemme - Marker lovlige træk med pile + Markér lovlige træk med pile Sig \"Good game, well played\" (Godt parti, godt spillet) ved nederlag eller remis Dine præferencer er blevet gemt. Brug musens scrollhjul på brættet for at afspille træk diff --git a/translation/dest/puzzle/gsw-CH.xml b/translation/dest/puzzle/gsw-CH.xml index 180c66002a335..87fc448f80445 100644 --- a/translation/dest/puzzle/gsw-CH.xml +++ b/translation/dest/puzzle/gsw-CH.xml @@ -15,7 +15,7 @@ Stimm ab, um die Nächscht z\'lade! Die Ufgab positiv bewerte Die Ufgab negativ bewerte - Dini Ufgabe Wertig änderet sich nöd. Die Ufgabe sind kein Wettbewerb. Dini Wertig hilft nur, um so Ufgabe uszwähle, wo zu dinere aktuelle Stärchi passed. + Dini Ufgabe-Wertig veränderet sich nöd. Eusi Ufgabe sind kein Wettbewerb. Dini Wertig hilft nur Ufgabe z\'wähle, wo zu dinere aktuelle Schpielstärchi passed. Find de bescht Zug für Wiss. Find de bescht Zug für Schwarz. Für personalisierti Ufgabe muesch: @@ -48,14 +48,14 @@ Eifacher Am eifachschte - 1 Punkt under dinere Ufgabe Wertig - %s Pünkt under dinere Ufgabe Wertig + 1 Punkt under dinere Ufgabe-Wertig + %s Pünkt under dinere Ufgabe-Wertig Schwieriger Am schwierigschte - 1 Punkt über dinere Ufgabe Wertig - %s Pünkt über diinere Ufgabe Wertig + 1 Punkt über dinere Ufgabe-Wertig + %s Pünkt über dinere Ufgabe-Wertig Bischpil Es witers Motiv zuefüege @@ -90,7 +90,7 @@ Schpill schnälli und klassischi Partie, so erhöht sich d\'Chance, dass au Ufga %s widerhole %s glöst - Es git no nüt zum Zeige, lös zerscht es paar Ugabe! + Es git no nüt zum Zeige, lös zerscht es paar Ufgabe! Trainier mit dene Ufgabe und optimier din Fortschritt! Dini Leischtig isch am beschte i dene Theme diff --git a/translation/dest/puzzleTheme/sr-SP.xml b/translation/dest/puzzleTheme/sr-SP.xml index 18679f54d4d31..0276683929cef 100644 --- a/translation/dest/puzzleTheme/sr-SP.xml +++ b/translation/dest/puzzleTheme/sr-SP.xml @@ -50,14 +50,19 @@ Виљушка Потез где померена фигура напада две противничке фигуре од једном. Висећа фигура + Тактика где је противникова фигура небрањена или недовољно брањена и могуће ју је узети. Кука-мат + Мат топом, коњем и пешаком, при чему један противнички пешак онемогућава бег противничком краљу. Сметња + Постављање фигуре између две противничке фигуре, тако да су једна или обе од нјих небрањене, као што је на пример скакач на брањеном пољу између два топа. Интермецо + Уместо играња очекиваног потеза, прво убаци потез који је непосредна претња на коју противник мора да одговори. Такође знано као \"Zwischenzug\" или \"међупотез\". Скакачка завршница Завршница са само скакачима и пешацима. Дугачак проблем Три потеза до добитка. Партије мајстора + Проблеми из партија играних између два играча са титулама. Партије Мајстор против Мајстора Проблеми из партија између два играча са титулама. Мат @@ -71,6 +76,7 @@ Мат у 4 Матирајте у четири потеза. Мат у 5 или више + Пронађи дугу матну комбинацију. Средишњица Тактика у току друге фазе партије. Једнопотезни проблем @@ -90,19 +96,32 @@ Напад на даминој страни Напад на противничког краља, након што су се рокадирали на краљичиној страни. Тихи потез + Потез који којим се нити даје шах, нити узима фигура, а није ни непосреднја претња узимања фигуре, али којим се припрема скривена претња каснијег узимања фигуре. Топовска завршница Завршница са само топовима и пешацима. Жртва + Тактика која укључује привремено жртвовање материјала, како би се после форсираног низа потеза поново стекла предност. Кратак проблем Два потеза до добитка. + Линијски напад + Мотив који укључује напад на фигуру веће вредности, а када се она помери, омогућује се узимање фигуре мање вредности која је била иза ње или напад на ту фигуру; обрнуто од везивања. Угушени мат + Мат скакачем, при чему матирани краљ није у стању да се помери зато што је окружен (или угушен) својим фигурама. + Проблеми из партија које су одиграли најбољи светски велемајстори + Проблем из партија које су одиграли најбољи играчи на свету. Заробљена фигура + Фигура не може да избегне да буде узета, зато што јој је ограничено кретање. Слаба промоција Промоција на коња, ловца или топа. Врло дугачак проблем Четири или више потеза за победу. Икс Реј напад + Фигура напада или брани поље, захваљујући противничкој фигури. Цугцванг + Противник има ограничен избор потеза и сваким потезом погоршава своју позицију. Здрава мешавина Свега по мало. Не знаш шта да очекујеш, па остајеш спреман за све! Баш као у правим партијама. + Играчеве партије + Потражи проблеме створене на основу твојих партија или партија других грача. + Ови проблеми су у јавном власништву и могуће их је презузети са %s. diff --git a/translation/dest/puzzleTheme/vi-VN.xml b/translation/dest/puzzleTheme/vi-VN.xml index 971826dafebda..c868eff22d73f 100644 --- a/translation/dest/puzzleTheme/vi-VN.xml +++ b/translation/dest/puzzleTheme/vi-VN.xml @@ -123,5 +123,5 @@ Mỗi thứ một chút. Bạn không biết được thứ gì đang chờ mình, vậy nên bạn cần phải sẵn sàng cho mọi thứ! Như một ván cờ thật vậy! Các ván đấu của người chơi Những câu đố từ những ván cờ của bạn hoặc từ các ván cờ của những người chơi khác. - Những câu đố này nằm ở máy chủ công khai, bạn có thể tải xuống ở %s. + Những câu đố này thuộc phạm vi công khai và có thể tải về từ %s. diff --git a/translation/dest/site/ca-ES.xml b/translation/dest/site/ca-ES.xml index efeec9db2d8d0..0e411e0f4d615 100644 --- a/translation/dest/site/ca-ES.xml +++ b/translation/dest/site/ca-ES.xml @@ -418,7 +418,7 @@ Les negres fan escac i mat en una jugada Reintentar S\'està reconnectant - Fora de línia + Desconnectat %s amic connectat %s amics connectats diff --git a/translation/dest/site/da-DK.xml b/translation/dest/site/da-DK.xml index c53bd211e0fb3..b398fbc712dbf 100644 --- a/translation/dest/site/da-DK.xml +++ b/translation/dest/site/da-DK.xml @@ -704,7 +704,8 @@ Næste gren Slå variantpile til/fra Gennemgå forrige/næste variant - Slå glyf-annotationer til/fra + Slå træk-annotationer til/fra + Slå positionsannotationer til/fra Variantpile lader dig navigere uden at bruge træklisten. spil valgte træk Ny turnering diff --git a/translation/dest/site/de-DE.xml b/translation/dest/site/de-DE.xml index c5e12a94ee60f..310e5579f93d1 100644 --- a/translation/dest/site/de-DE.xml +++ b/translation/dest/site/de-DE.xml @@ -705,6 +705,7 @@ Variantenpfeile ein-/auschalten Durch vorherige/nächste Variante schalten Schalten der Zeichen-Anmerkungen + Positionsanmerkungen umschalten Mit Variantenpfeilen navigierst du durch die Zugliste. den ausgewählten Zug ausführen Neues Turnier diff --git a/translation/dest/site/eo-UY.xml b/translation/dest/site/eo-UY.xml index bd22d2c630358..89051f0e3aea7 100644 --- a/translation/dest/site/eo-UY.xml +++ b/translation/dest/site/eo-UY.xml @@ -418,6 +418,7 @@ La nigra ludanto devas matigi per unu movo Reprovi Rekonektante + Nekonektita %s amiko enreta %s amikoj enretaj diff --git a/translation/dest/site/es-ES.xml b/translation/dest/site/es-ES.xml index 89df31e15d098..15849f8c31183 100644 --- a/translation/dest/site/es-ES.xml +++ b/translation/dest/site/es-ES.xml @@ -705,6 +705,7 @@ Activar/Desactivar flechas de variantes Alterna entre la variante siguiente y la anterior Activa o desactiva la anotación de figurines + Alternar anotaciones de posición Las flechas de variantes te permiten navegar sin usar la lista de movimientos. hacer movimiento seleccionado Nuevo torneo diff --git a/translation/dest/site/fa-IR.xml b/translation/dest/site/fa-IR.xml index 5e7493546739c..dbceb617e5cb9 100644 --- a/translation/dest/site/fa-IR.xml +++ b/translation/dest/site/fa-IR.xml @@ -705,6 +705,7 @@ کلید پیکان‌های شاخه اصلی چرخه قبلی/بعدی شاخه اصلی کلید علائم حرکت‌نویسی + تغییر علائم حرکت‌نویسی پیکان های شاخه اصلی به شما امکان می‌دهد بدون استفاده از فهرست حرکت، پیمایش کنید. حرکت انتخاب شده را بازی کن مسابقه جدید diff --git a/translation/dest/site/fr-FR.xml b/translation/dest/site/fr-FR.xml index 47addbea9602b..e99819848c6c0 100644 --- a/translation/dest/site/fr-FR.xml +++ b/translation/dest/site/fr-FR.xml @@ -705,6 +705,7 @@ Activer/désactiver les flèches de variantes Variante précédente/suivante Activer/désactiver les annotations en symboles + Activer/désactiver les annotations de positions Les flèches de variantes vous permettent de naviguer sans utiliser la liste des coups. jouer le coup sélectionné Nouveau tournoi diff --git a/translation/dest/site/gsw-CH.xml b/translation/dest/site/gsw-CH.xml index 6865aa78b1599..5e4c65a0aab8b 100644 --- a/translation/dest/site/gsw-CH.xml +++ b/translation/dest/site/gsw-CH.xml @@ -714,6 +714,7 @@ gits nöd und es isch immer ungwertet. Variatione-Pfil umschalte Zyklus vorherigi/nächschti Variante Glyph-Amerkige ischalte und usschalte (...was immer das glyph isch?!) + Positionsamerkige umschalte Mit de Variationspfil chasch ohni d\'Zugslischte navigiere. spill de gwählti zug Neus Turnier diff --git a/translation/dest/site/he-IL.xml b/translation/dest/site/he-IL.xml index 5683ecf0e9851..2d9868a7ee49f 100644 --- a/translation/dest/site/he-IL.xml +++ b/translation/dest/site/he-IL.xml @@ -779,6 +779,7 @@ הפעלת חצי הווריאנטים מחזור הוריאנט הקודם/הבא הפעלת סמלי ההערות + הפעלת הערות עמדתיות חצי הווריאנטים מאפשרים ניווט קל ללא צורך ברשימת המסעים. שחקו את המהלך שנבחר טורניר חדש diff --git a/translation/dest/site/it-IT.xml b/translation/dest/site/it-IT.xml index 3b350ce684c9c..b1bb7fd830899 100644 --- a/translation/dest/site/it-IT.xml +++ b/translation/dest/site/it-IT.xml @@ -706,6 +706,7 @@ analizzarla con il computer, commentarla in chat, e condividerla tramite un indi Mostra le frecce delle varianti Vai alla variante precedente/successiva Mostra i simboli delle annotazioni + Mostra le annotazioni della posizione Le frecce delle varianti ti permettono di esplorare le mosse senza usare la lista. gioca la mossa selezionata Nuovo torneo diff --git a/translation/dest/site/nl-NL.xml b/translation/dest/site/nl-NL.xml index c274ced055941..e75d3cb638745 100644 --- a/translation/dest/site/nl-NL.xml +++ b/translation/dest/site/nl-NL.xml @@ -705,6 +705,7 @@ Schakel variatiepijlen in/uit Bekijk vorige/volgende variant Zet glyph-aantekeningen aan of uit + Zet stellingsaantekeningen aan of uit Met de variantpijlen kunt u navigeren zonder de zettenlijst te gebruiken. speel geselecteerde zet Nieuw toernooi diff --git a/translation/dest/site/nn-NO.xml b/translation/dest/site/nn-NO.xml index 5b5eaf8e07838..10976b4026de9 100644 --- a/translation/dest/site/nn-NO.xml +++ b/translation/dest/site/nn-NO.xml @@ -706,6 +706,7 @@ få en computeranalyse, chatte eller dele ein URL. Slå variantpilar på/av Gå gjennom førre/neste variant Slå symbol-merknadar på/av + Slå merknader for stillingar på/av Med hjelp av variantpiler kan du navigere utan å bruka trekklista. spel valde trekk Ny turnering diff --git a/translation/dest/site/pl-PL.xml b/translation/dest/site/pl-PL.xml index d9cd228297456..cd461a5da69ef 100644 --- a/translation/dest/site/pl-PL.xml +++ b/translation/dest/site/pl-PL.xml @@ -779,6 +779,7 @@ Pokaż strzałki wariantów Powtarzaj poprzedni/następny wariant Przełącz adnotacje symbolami + Przełącz adnotacje pozycji Strzałki wariantów pozwalają nawigować bez użycia listy posunięć. wykonaj wybrane posunięcie Nowy turniej diff --git a/translation/dest/site/pt-BR.xml b/translation/dest/site/pt-BR.xml index 33dff1fe0acc8..af84db7f491b9 100644 --- a/translation/dest/site/pt-BR.xml +++ b/translation/dest/site/pt-BR.xml @@ -32,7 +32,7 @@ Três xeques Corrida terminada Fim da variante - Novo adversário + Novo oponente Seu oponente quer jogar uma nova partida contra você Entrar no jogo Brancas jogam @@ -41,7 +41,7 @@ O seu adversário deixou a partida. Você pode reivindicar vitória em %s segundo. O seu adversário deixou a partida. Você pode reivindicar vitória em %s segundos. - O seu adversário deixou a partida. Você pode reivindicar vitória, declarar empate ou aguardar. + O seu oponente deixou a partida. Você pode reivindicar vitória, declarar empate ou aguardar. Reivindicar vitória Reivindicar empate Por favor, seja gentil no chat! @@ -705,6 +705,7 @@ Ativar/desativar setas Variante seguinte/anterior Ativar/desativar anotações + Ativar/desativar anotações de posição Setas de variação permitem navegar sem usar a lista de movimentos. jogar movimento selecionado Novo torneio diff --git a/translation/dest/site/pt-PT.xml b/translation/dest/site/pt-PT.xml index 41bcd1a4c306c..436948e2cb6e3 100644 --- a/translation/dest/site/pt-PT.xml +++ b/translation/dest/site/pt-PT.xml @@ -706,6 +706,7 @@ análise de computador, sala de chat do jogo e link de partilha. Ativar/desactivar seta da variante Ciclo anterior/próxima variante Ativar/desativar anotações com símbolos + Ativar/desativar anotações de posição Setas de variação permitem navegar sem usar a lista de movimentos. jogar o movimento selecionado Novo torneio diff --git a/translation/dest/site/sl-SI.xml b/translation/dest/site/sl-SI.xml index e9fdc1e74d173..8725bcd0ae6e3 100644 --- a/translation/dest/site/sl-SI.xml +++ b/translation/dest/site/sl-SI.xml @@ -772,6 +772,7 @@ Naslednji spodrsljaj Naslednja napaka Naslednja nepravilnost + Preklop opomb o položaju Nov turnir Turnir z možnostjo različnih variant in različnih igralnih časov Igraj turnirje z hitrim tempom! Pridruži se uradnemu turnirju ali ustvari svoj turnir. Hitropotezno, Pospešeno, Klasično, Šah960, Trojni šah in ostale možnosti so na voljo za neskončno šahovsko zabavo. diff --git a/translation/dest/site/vi-VN.xml b/translation/dest/site/vi-VN.xml index 67c02d711be7a..5f0125d1fd052 100644 --- a/translation/dest/site/vi-VN.xml +++ b/translation/dest/site/vi-VN.xml @@ -668,7 +668,8 @@ trò chuyện trong ván đấu và có một URL có thể chia sẻ công khai Nhánh tiếp theo Đổi mũi tên của từng biến Chu kì của biến trước/tiếp theo - Đổi chú thích bằng dấu + Đổi chú thích nước cờ + Chuyển đổi chú thích thế cờ Mũi tên của biến cho phép bạn điều hướng mà không cần sử dụng danh sách nước đi. chơi nước đi đã chọn Giải đấu mới diff --git a/translation/dest/timeago/sr-SP.xml b/translation/dest/timeago/sr-SP.xml index af1987e37d869..a9829b6c4b75e 100644 --- a/translation/dest/timeago/sr-SP.xml +++ b/translation/dest/timeago/sr-SP.xml @@ -1,4 +1,11 @@ + управо сада + + за %s секунди + за %s сати + за %s дана + управо сад + завршено diff --git a/translation/dest/voiceCommands/pt-BR.xml b/translation/dest/voiceCommands/pt-BR.xml index c5300cc74b1bc..3ac988a5a4bea 100644 --- a/translation/dest/voiceCommands/pt-BR.xml +++ b/translation/dest/voiceCommands/pt-BR.xml @@ -4,6 +4,10 @@ Assista ao tutorial Use o botão %1$s para ativar/desativar o reconhecimento de voz, o botão %2$s para ver esta aba de ajuda, e o menu %3$s para mudar as configurações de fala. Setas de vários movimentos são mostradas quando há incerteza. Diga uma cor ou um número para escolher uma seta. + Se uma seta mostrar um radar varrendo uma área, esse lance será jogado qujando o círculo estiver completo. Durante esse tempo, você pode dizer %1$s para jogar o lance imediatamente, %2$s para cancelar, ou falar a cor/número de uma seta diferente. Esse timer pode ser ajustado ou desativado nas configurações. + Ative %s em ambientes barulhentos. Mantenha a tecla shift enquanto fala comandos com isso ativado. + Use o alfabeto fonético para melhorar o reconhecimento das colunas do tabuleiro de xadrez. + %s explica as configurações de movimentação via comando de voz em detalhes. Esta postagem Mover para e4 ou selecionar a peça em e4 Selecionar ou tomar um bispo @@ -12,6 +16,7 @@ O alfabeto fonético é melhor Cancelar relógio ou negar um pedido Fazer lance preferido ou confirmar algo + Dormir (se a palavra-chave estiver ativada) Desligar o reconhecimento de voz Mostrar solução do quebra-cabeça From 2817ca1784ca39e932e49b1ad969c53ce688c50f Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 13 Feb 2024 08:55:52 +0100 Subject: [PATCH 28/39] localize perf stats numbers --- app/views/user/perfStat.scala | 49 ++++++++++++++--------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/app/views/user/perfStat.scala b/app/views/user/perfStat.scala index 5f0069b747a71..30d3d69446cf8 100644 --- a/app/views/user/perfStat.scala +++ b/app/views/user/perfStat.scala @@ -145,22 +145,22 @@ object perfStat: tbody( tr( th(totalGames()), - td(count.all), + td(count.all.localize), td ), tr(cls := "full")( th(ratedGames()), - td(count.rated), + td(count.rated.localize), td(pct(count.rated, count.all)) ), tr(cls := "full")( th(tournamentGames()), - td(count.tour), + td(count.tour.localize), td(pct(count.tour, count.all)) ), tr(cls := "full")( th(berserkedGames()), - td(count.berserk), + td(count.berserk.localize), td(pct(count.berserk, count.tour)) ), count.seconds > 0 option tr(cls := "full")( @@ -180,23 +180,23 @@ object perfStat: ), tr(cls := "full")( th(victories()), - td(tag("green")(count.win)), + td(tag("green")(count.win.localize)), td(tag("green")(pct(count.win, count.all))) ), tr(cls := "full")( th(trans.draws()), - td(count.draw), + td(count.draw.localize), td(pct(count.draw, count.all)) ), tr(cls := "full")( th(defeats()), - td(tag("red")(count.loss)), + td(tag("red")(count.loss.localize)), td(tag("red")(pct(count.loss, count.all))) ), tr(cls := "full")( th(disconnections()), - td(if count.disconnects > count.all * 100 / 15 then tag("red") else emptyFrag)( - count.disconnects + td(count.disconnects > count.all * 100 / 15 option tag("red"))( + count.disconnects.localize ), td(pct(count.disconnects, count.all)) ) @@ -244,7 +244,7 @@ object perfStat: div(cls := "streak")( h3( title( - if s.v > 0 then tag(color)(trans.nbGames.plural(s.v, strong(s.v))) + if s.v > 0 then tag(color)(trans.nbGames.plural(s.v, strong(s.v.localize))) else "-" ) ), @@ -266,30 +266,21 @@ object perfStat: resultStreakSide(streak.loss, losingStreak(), "red") ) - private def resultTable(results: lila.perfStat.Results, title: Frag, user: User)(using - Lang - ): Frag = - div( + private def resultTable(results: lila.perfStat.Results, title: Frag, user: User)(using Lang) = + div: table( - thead( - tr( - th(colspan := 2)(h2(title)) - ) - ), - tbody( - results.results map { r => + thead: + tr(th(colspan := 2)(h2(title))) + , + tbody: + results.results map: r => tr( td(userIdLink(r.opId.some, withOnline = false), " (", r.opRating, ")"), - td( - a(cls := "glpt", href := s"${routes.Round.watcher(r.gameId, "white")}?pov=${user.username}")( + td: + a(cls := "glpt", href := s"${routes.Round.watcher(r.gameId, "white")}?pov=${user.username}"): absClientInstant(r.at) - ) - ) ) - } - ) ) - ) private def result(stat: PerfStat, user: User)(using Lang): Frag = st.section(cls := "result split")( @@ -302,7 +293,7 @@ object perfStat: div(cls := "streak")( h3( title( - if s.v > 0 then trans.nbGames.plural(s.v, strong(s.v)) + if s.v > 0 then trans.nbGames.plural(s.v, strong(s.v.localize)) else "-" ) ), From 3dc9b88697f62a3b5b65e9466b384bc394a84eb3 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 13 Feb 2024 09:24:34 +0100 Subject: [PATCH 29/39] scala tweaks --- app/controllers/User.scala | 15 +++++---------- modules/perfStat/src/main/JsonView.scala | 19 +++++++++---------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/app/controllers/User.scala b/app/controllers/User.scala index 5b43471e46edc..f8f0e92a9a2e7 100644 --- a/app/controllers/User.scala +++ b/app/controllers/User.scala @@ -510,12 +510,10 @@ final class User( relateds <- ops .zip(followables) - .map { case ((u, nb), followable) => - relationApi.fetchRelation(user.id, u.id) map { + .traverse { case ((u, nb), followable) => + relationApi.fetchRelation(user.id, u.id) map: lila.relation.Related(u, nb.some, followable, _) - } } - .parallel page <- renderPage(html.relation.bits.opponents(user, relateds)) yield Ok(page) } @@ -524,9 +522,8 @@ final class User( Found(env.perfStat.api.data(username, perfKey)): data => negotiate( Ok.pageAsync: - env.history.ratingChartApi(data.user.user) map { + env.history.ratingChartApi(data.user.user) map: html.user.perfStat(data, _) - } , JsonOk: getBool("graph") @@ -597,8 +594,6 @@ final class User( } def tryRedirect(username: UserStr)(using Context): Fu[Option[Result]] = - env.user.repo byId username map { - _.filter(_.enabled.yes || isGrantedOpt(_.SeeReport)) map { user => + env.user.repo byId username map: + _.filter(_.enabled.yes || isGrantedOpt(_.SeeReport)) map: user => Redirect(routes.User.show(user.username)) - } - } diff --git a/modules/perfStat/src/main/JsonView.scala b/modules/perfStat/src/main/JsonView.scala index bb701c4f3d3c4..f563974052596 100644 --- a/modules/perfStat/src/main/JsonView.scala +++ b/modules/perfStat/src/main/JsonView.scala @@ -45,21 +45,20 @@ object JsonView: import lila.rating.Glicko.given - private given Writes[Instant] = Writes { d => + private given Writes[Instant] = Writes: d => JsString(isoDateTimeFormatter print d) - } - given OWrites[User] = OWrites { u => + + given OWrites[User] = OWrites: u => Json.obj("name" -> u.username) - } - given OWrites[Perf] = OWrites { p => + + given OWrites[Perf] = OWrites: p => Json.obj("glicko" -> p.glicko, "nb" -> p.nb, "progress" -> p.progress) - } - private given Writes[Avg] = Writes { a => + + private given Writes[Avg] = Writes: a => JsNumber(lila.common.Maths.roundDownAt(a.avg, 2)) - } - given (using lang: Lang): OWrites[PerfType] = OWrites { pt => + + given (using lang: Lang): OWrites[PerfType] = OWrites: pt => Json.obj( "key" -> pt.key, "name" -> pt.trans ) - } From ba6359d4f70a381a7a4c621c9d4193e619997f83 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 13 Feb 2024 09:24:48 +0100 Subject: [PATCH 30/39] remove worst losses section in user perf stats --- app/views/user/perfStat.scala | 2 +- modules/i18n/src/main/I18nKeys.scala | 1 - modules/perfStat/src/main/PerfStat.scala | 5 +---- modules/perfStat/src/main/PerfStatStorage.scala | 9 +-------- translation/source/perfStat.xml | 1 - 5 files changed, 3 insertions(+), 15 deletions(-) diff --git a/app/views/user/perfStat.scala b/app/views/user/perfStat.scala index 30d3d69446cf8..414f3c922f6a6 100644 --- a/app/views/user/perfStat.scala +++ b/app/views/user/perfStat.scala @@ -285,7 +285,7 @@ object perfStat: private def result(stat: PerfStat, user: User)(using Lang): Frag = st.section(cls := "result split")( resultTable(stat.bestWins, bestRated(), user), - resultTable(stat.worstLosses, worstRated(), user) + div ) private def playStreakNbStreak(s: lila.perfStat.Streak, title: Frag => Frag)(using Lang): Frag = diff --git a/modules/i18n/src/main/I18nKeys.scala b/modules/i18n/src/main/I18nKeys.scala index e699d379c8ab3..a3554df99e6a0 100644 --- a/modules/i18n/src/main/I18nKeys.scala +++ b/modules/i18n/src/main/I18nKeys.scala @@ -1840,7 +1840,6 @@ object I18nKeys: val `longestStreak` = I18nKey("perfStat:longestStreak") val `currentStreak` = I18nKey("perfStat:currentStreak") val `bestRated` = I18nKey("perfStat:bestRated") - val `worstRated` = I18nKey("perfStat:worstRated") val `gamesInARow` = I18nKey("perfStat:gamesInARow") val `lessThanOneHour` = I18nKey("perfStat:lessThanOneHour") val `maxTimePlaying` = I18nKey("perfStat:maxTimePlaying") diff --git a/modules/perfStat/src/main/PerfStat.scala b/modules/perfStat/src/main/PerfStat.scala index 6d4188a9bcd2e..91d61d483f6bb 100644 --- a/modules/perfStat/src/main/PerfStat.scala +++ b/modules/perfStat/src/main/PerfStat.scala @@ -12,7 +12,6 @@ case class PerfStat( highest: Option[RatingAt], lowest: Option[RatingAt], bestWins: Results, - worstLosses: Results, count: Count, resultStreak: ResultStreak, playStreak: PlayStreak @@ -28,13 +27,12 @@ case class PerfStat( highest = RatingAt.agg(highest, pov, 1), lowest = if thisYear then RatingAt.agg(lowest, pov, -1) else lowest, bestWins = if ~pov.win then bestWins.agg(pov, 1) else bestWins, - worstLosses = if thisYear && ~pov.loss then worstLosses.agg(pov, -1) else worstLosses, count = count(pov), resultStreak = resultStreak agg pov, playStreak = playStreak agg pov ) - def userIds = bestWins.userIds ::: worstLosses.userIds + def userIds = bestWins.userIds object PerfStat: @@ -50,7 +48,6 @@ object PerfStat: highest = none, lowest = none, bestWins = Results(Nil), - worstLosses = Results(Nil), count = Count.init, resultStreak = ResultStreak(win = Streaks.init, loss = Streaks.init), playStreak = PlayStreak(nb = Streaks.init, time = Streaks.init, lastDate = none) diff --git a/modules/perfStat/src/main/PerfStatStorage.scala b/modules/perfStat/src/main/PerfStatStorage.scala index 5179c9f0bf29f..89d1a5d2bc408 100644 --- a/modules/perfStat/src/main/PerfStatStorage.scala +++ b/modules/perfStat/src/main/PerfStatStorage.scala @@ -34,12 +34,6 @@ final class PerfStatStorage(coll: AsyncCollFailingSilently)(using Executor): resultsDiff(a, b)(_.bestWins).map { set => "bestWins" -> set }, - resultsDiff(a, b)(_.worstLosses).map { set => - "worstLosses" -> set - }, - (a.worstLosses != b.worstLosses).so(resultsHandler.writeOpt(b.worstLosses)) map { worstLosses => - "worstLosses" -> worstLosses - }, streakDiff(a, b)(_.resultStreak.win.cur).map { set => "resultStreak.win.cur" -> set }, @@ -92,9 +86,8 @@ final class PerfStatStorage(coll: AsyncCollFailingSilently)(using Executor): private def docDiff[T: BSONDocumentWriter](a: T, b: T): Map[String, BSONValue] = val (am, bm) = (docMap(a), docMap(b)) - bm collect { + bm.collect: case (field, v) if am.get(field).forall(_ != v) => field -> v - } private def docMap[T](a: T)(using writer: BSONDocumentWriter[T]) = writer.writeTry(a).get.toMap diff --git a/translation/source/perfStat.xml b/translation/source/perfStat.xml index 5b0b21ae9a731..8376facbdc1da 100644 --- a/translation/source/perfStat.xml +++ b/translation/source/perfStat.xml @@ -25,7 +25,6 @@ Longest streak: %s Current streak: %s Best rated victories - Worst rated defeats Games played in a row Less than one hour between games Max time spent playing From a373ad222c0c04a1559c44978f1188a575a63b68 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 13 Feb 2024 10:50:37 +0100 Subject: [PATCH 31/39] relay fetch quick start --- modules/relay/src/main/RelayFetch.scala | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/modules/relay/src/main/RelayFetch.scala b/modules/relay/src/main/RelayFetch.scala index b0ff326591b7f..00542544ef78b 100644 --- a/modules/relay/src/main/RelayFetch.scala +++ b/modules/relay/src/main/RelayFetch.scala @@ -31,10 +31,22 @@ final private class RelayFetch( import RelayFetch.* - LilaScheduler("RelayFetch.official", _.Every(500 millis), _.AtMost(15 seconds), _.Delay(15 seconds)): + private val quickStart = false // for dev + + LilaScheduler( + "RelayFetch.official", + _.Every(500 millis), + _.AtMost(15 seconds), + _.Delay(if quickStart then 1.milli else 15 seconds) + ): syncRelays(official = true) - LilaScheduler("RelayFetch.user", _.Every(750 millis), _.AtMost(10 seconds), _.Delay(33 seconds)): + LilaScheduler( + "RelayFetch.user", + _.Every(750 millis), + _.AtMost(10 seconds), + _.Delay(if quickStart then 1.milli else 33 seconds) + ): syncRelays(official = false) private val maxRelaysToSync = Max(50) @@ -199,7 +211,8 @@ final private class RelayFetch( MultiPgn(results.sortBy(_._1).map(_._2)) } flatMap { multiPgnToGames(_).toFuture } - private def httpGetPgn(url: URL)(using CanProxy): Fu[PgnStr] = PgnStr from formatApi.httpGet(url) + private def httpGetPgn(url: URL)(using CanProxy): Fu[PgnStr] = + PgnStr from formatApi.httpGetAndGuessCharset(url) private def httpGetJson[A: Reads](url: URL)(using CanProxy): Fu[A] = for str <- formatApi.httpGet(url) From e73bb4b940b7ca0e41f6bf4e10e3848155504f64 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 13 Feb 2024 10:57:13 +0100 Subject: [PATCH 32/39] guess broadcast source charset and decode it - closes #14664 --- modules/common/src/main/String.scala | 14 ++++++++++++++ modules/relay/src/main/RelayFormat.scala | 10 +++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/common/src/main/String.scala b/modules/common/src/main/String.scala index a5d23537ee4f2..2504803a357d2 100644 --- a/modules/common/src/main/String.scala +++ b/modules/common/src/main/String.scala @@ -184,3 +184,17 @@ object String: .mkString("{", ",", "}") def underscoreFen(fen: chess.format.Fen.Epd) = fen.value.replace(" ", "_") + + object charset: + import akka.util.ByteString + import com.ibm.icu.text.CharsetDetector + + def guessAndDecode(str: ByteString): String = + str.decodeString(guess(str) | "UTF-8").ppAs(_.take(100), ~guess(str)) + + def guess(str: ByteString): Option[String] = + Option: + val cd = new CharsetDetector + cd.setText(str.take(10_000).toArray) + cd.detect() + .map(_.getName) diff --git a/modules/relay/src/main/RelayFormat.scala b/modules/relay/src/main/RelayFormat.scala index 3d100e6d5ce1d..f43619bcc99ad 100644 --- a/modules/relay/src/main/RelayFormat.scala +++ b/modules/relay/src/main/RelayFormat.scala @@ -12,6 +12,7 @@ import lila.study.MultiPgn import lila.memo.CacheApi.* import lila.memo.{ CacheApi, SettingStore } import lila.common.config.{ Max, Credentials, HostPort } +import play.api.libs.ws.StandaloneWSResponse final private class RelayFormatApi( ws: StandaloneWSClient, @@ -77,6 +78,13 @@ final private class RelayFormatApi( } private[relay] def httpGet(url: URL)(using CanProxy): Fu[String] = + httpGetResponse(url).map(_.body) + + private[relay] def httpGetAndGuessCharset(url: URL)(using CanProxy): Fu[String] = + httpGetResponse(url).map: res => + lila.common.String.charset.guessAndDecode(res.bodyAsBytes) + + private def httpGetResponse(url: URL)(using CanProxy): Future[StandaloneWSResponse] = val (req, proxy) = addProxy(url): ws.url(url.toString) .withRequestTimeout(4.seconds) @@ -84,7 +92,7 @@ final private class RelayFormatApi( req .get() .flatMap: res => - if res.status == 200 then fuccess(res.body) + if res.status == 200 then fuccess(res) else fufail(s"[${res.status}] $url") .monSuccess(_.relay.httpGet(url.host.toString, proxy)) From 46760e95132ded20e381037c4421806c50bbefc3 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 13 Feb 2024 11:06:54 +0100 Subject: [PATCH 33/39] skip guessing the charset when the response header exists - for #14664 --- modules/common/src/main/String.scala | 2 +- modules/relay/src/main/RelayFormat.scala | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/common/src/main/String.scala b/modules/common/src/main/String.scala index 2504803a357d2..d80d0b6792446 100644 --- a/modules/common/src/main/String.scala +++ b/modules/common/src/main/String.scala @@ -190,7 +190,7 @@ object String: import com.ibm.icu.text.CharsetDetector def guessAndDecode(str: ByteString): String = - str.decodeString(guess(str) | "UTF-8").ppAs(_.take(100), ~guess(str)) + str.decodeString(guess(str) | "UTF-8") def guess(str: ByteString): Option[String] = Option: diff --git a/modules/relay/src/main/RelayFormat.scala b/modules/relay/src/main/RelayFormat.scala index f43619bcc99ad..6764d267ae773 100644 --- a/modules/relay/src/main/RelayFormat.scala +++ b/modules/relay/src/main/RelayFormat.scala @@ -82,7 +82,14 @@ final private class RelayFormatApi( private[relay] def httpGetAndGuessCharset(url: URL)(using CanProxy): Fu[String] = httpGetResponse(url).map: res => - lila.common.String.charset.guessAndDecode(res.bodyAsBytes) + responseHeaderCharset(res) match + case None => lila.common.String.charset.guessAndDecode(res.bodyAsBytes) + case Some(known) => res.bodyAsBytes.decodeString(known) + + private def responseHeaderCharset(res: StandaloneWSResponse): Option[java.nio.charset.Charset] = + import play.shaded.ahc.org.asynchttpclient.util.HttpUtils + Option(HttpUtils.extractContentTypeCharsetAttribute(res.contentType)).orElse: + res.contentType.startsWith("text/") option java.nio.charset.StandardCharsets.ISO_8859_1 private def httpGetResponse(url: URL)(using CanProxy): Future[StandaloneWSResponse] = val (req, proxy) = addProxy(url): From cea920582146b6cc335b82375cf5a60f492e8c84 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 13 Feb 2024 11:19:22 +0100 Subject: [PATCH 34/39] rewrite imports --- modules/relay/src/main/RelayFormat.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/relay/src/main/RelayFormat.scala b/modules/relay/src/main/RelayFormat.scala index 6764d267ae773..71841a90dbaf0 100644 --- a/modules/relay/src/main/RelayFormat.scala +++ b/modules/relay/src/main/RelayFormat.scala @@ -4,7 +4,12 @@ import io.mola.galimatias.URL import com.softwaremill.tagging.* import scala.util.matching.Regex import play.api.libs.json.* -import play.api.libs.ws.{ StandaloneWSClient, StandaloneWSRequest, DefaultWSProxyServer } +import play.api.libs.ws.{ + StandaloneWSClient, + StandaloneWSRequest, + StandaloneWSResponse, + DefaultWSProxyServer +} import play.api.libs.ws.DefaultBodyReadables.* import chess.format.pgn.PgnStr @@ -12,7 +17,6 @@ import lila.study.MultiPgn import lila.memo.CacheApi.* import lila.memo.{ CacheApi, SettingStore } import lila.common.config.{ Max, Credentials, HostPort } -import play.api.libs.ws.StandaloneWSResponse final private class RelayFormatApi( ws: StandaloneWSClient, From 108e9d7664f1fff16091b38a26da5a20ed12722d Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 13 Feb 2024 11:24:40 +0100 Subject: [PATCH 35/39] Revert "remove worst losses section in user perf stats" This reverts commit ba6359d4f70a381a7a4c621c9d4193e619997f83. Because it's impossible to ever remove any feature. Ever. --- app/views/user/perfStat.scala | 2 +- modules/i18n/src/main/I18nKeys.scala | 1 + modules/perfStat/src/main/PerfStat.scala | 5 ++++- modules/perfStat/src/main/PerfStatStorage.scala | 9 ++++++++- translation/source/perfStat.xml | 1 + 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/views/user/perfStat.scala b/app/views/user/perfStat.scala index 414f3c922f6a6..30d3d69446cf8 100644 --- a/app/views/user/perfStat.scala +++ b/app/views/user/perfStat.scala @@ -285,7 +285,7 @@ object perfStat: private def result(stat: PerfStat, user: User)(using Lang): Frag = st.section(cls := "result split")( resultTable(stat.bestWins, bestRated(), user), - div + resultTable(stat.worstLosses, worstRated(), user) ) private def playStreakNbStreak(s: lila.perfStat.Streak, title: Frag => Frag)(using Lang): Frag = diff --git a/modules/i18n/src/main/I18nKeys.scala b/modules/i18n/src/main/I18nKeys.scala index a3554df99e6a0..e699d379c8ab3 100644 --- a/modules/i18n/src/main/I18nKeys.scala +++ b/modules/i18n/src/main/I18nKeys.scala @@ -1840,6 +1840,7 @@ object I18nKeys: val `longestStreak` = I18nKey("perfStat:longestStreak") val `currentStreak` = I18nKey("perfStat:currentStreak") val `bestRated` = I18nKey("perfStat:bestRated") + val `worstRated` = I18nKey("perfStat:worstRated") val `gamesInARow` = I18nKey("perfStat:gamesInARow") val `lessThanOneHour` = I18nKey("perfStat:lessThanOneHour") val `maxTimePlaying` = I18nKey("perfStat:maxTimePlaying") diff --git a/modules/perfStat/src/main/PerfStat.scala b/modules/perfStat/src/main/PerfStat.scala index 91d61d483f6bb..6d4188a9bcd2e 100644 --- a/modules/perfStat/src/main/PerfStat.scala +++ b/modules/perfStat/src/main/PerfStat.scala @@ -12,6 +12,7 @@ case class PerfStat( highest: Option[RatingAt], lowest: Option[RatingAt], bestWins: Results, + worstLosses: Results, count: Count, resultStreak: ResultStreak, playStreak: PlayStreak @@ -27,12 +28,13 @@ case class PerfStat( highest = RatingAt.agg(highest, pov, 1), lowest = if thisYear then RatingAt.agg(lowest, pov, -1) else lowest, bestWins = if ~pov.win then bestWins.agg(pov, 1) else bestWins, + worstLosses = if thisYear && ~pov.loss then worstLosses.agg(pov, -1) else worstLosses, count = count(pov), resultStreak = resultStreak agg pov, playStreak = playStreak agg pov ) - def userIds = bestWins.userIds + def userIds = bestWins.userIds ::: worstLosses.userIds object PerfStat: @@ -48,6 +50,7 @@ object PerfStat: highest = none, lowest = none, bestWins = Results(Nil), + worstLosses = Results(Nil), count = Count.init, resultStreak = ResultStreak(win = Streaks.init, loss = Streaks.init), playStreak = PlayStreak(nb = Streaks.init, time = Streaks.init, lastDate = none) diff --git a/modules/perfStat/src/main/PerfStatStorage.scala b/modules/perfStat/src/main/PerfStatStorage.scala index 89d1a5d2bc408..5179c9f0bf29f 100644 --- a/modules/perfStat/src/main/PerfStatStorage.scala +++ b/modules/perfStat/src/main/PerfStatStorage.scala @@ -34,6 +34,12 @@ final class PerfStatStorage(coll: AsyncCollFailingSilently)(using Executor): resultsDiff(a, b)(_.bestWins).map { set => "bestWins" -> set }, + resultsDiff(a, b)(_.worstLosses).map { set => + "worstLosses" -> set + }, + (a.worstLosses != b.worstLosses).so(resultsHandler.writeOpt(b.worstLosses)) map { worstLosses => + "worstLosses" -> worstLosses + }, streakDiff(a, b)(_.resultStreak.win.cur).map { set => "resultStreak.win.cur" -> set }, @@ -86,8 +92,9 @@ final class PerfStatStorage(coll: AsyncCollFailingSilently)(using Executor): private def docDiff[T: BSONDocumentWriter](a: T, b: T): Map[String, BSONValue] = val (am, bm) = (docMap(a), docMap(b)) - bm.collect: + bm collect { case (field, v) if am.get(field).forall(_ != v) => field -> v + } private def docMap[T](a: T)(using writer: BSONDocumentWriter[T]) = writer.writeTry(a).get.toMap diff --git a/translation/source/perfStat.xml b/translation/source/perfStat.xml index 8376facbdc1da..5b0b21ae9a731 100644 --- a/translation/source/perfStat.xml +++ b/translation/source/perfStat.xml @@ -25,6 +25,7 @@ Longest streak: %s Current streak: %s Best rated victories + Worst rated defeats Games played in a row Less than one hour between games Max time spent playing From fa9cbe44878bac665f7571fd6e4d7b22f0df28b3 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Tue, 13 Feb 2024 11:27:57 +0100 Subject: [PATCH 36/39] hide worst defeats stats because they're a troll magnet. it can't be fully removed (one can dream) as mods sometimes use it --- app/views/user/perfStat.scala | 8 ++++++-- translation/source/perfStat.xml | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/views/user/perfStat.scala b/app/views/user/perfStat.scala index 30d3d69446cf8..890f2c3c14b73 100644 --- a/app/views/user/perfStat.scala +++ b/app/views/user/perfStat.scala @@ -282,10 +282,14 @@ object perfStat: ) ) - private def result(stat: PerfStat, user: User)(using Lang): Frag = + private def result(stat: PerfStat, user: User)(using Context): Frag = st.section(cls := "result split")( resultTable(stat.bestWins, bestRated(), user), - resultTable(stat.worstLosses, worstRated(), user) + isGranted(_.BoostHunter) || isGranted(_.CheatHunter) option resultTable( + stat.worstLosses, + "Worst rated defeats", + user + ) ) private def playStreakNbStreak(s: lila.perfStat.Streak, title: Frag => Frag)(using Lang): Frag = diff --git a/translation/source/perfStat.xml b/translation/source/perfStat.xml index 5b0b21ae9a731..8376facbdc1da 100644 --- a/translation/source/perfStat.xml +++ b/translation/source/perfStat.xml @@ -25,7 +25,6 @@ Longest streak: %s Current streak: %s Best rated victories - Worst rated defeats Games played in a row Less than one hour between games Max time spent playing From 4d0d67431fbf8d3fa9a466a6d16a073d8b4b663b Mon Sep 17 00:00:00 2001 From: Jonathan Gamble <101470903+schlawg@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:43:29 -0600 Subject: [PATCH 37/39] only use lichess.trans on lichess pages - fix #14666 --- ui/site/src/component/socket.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/site/src/component/socket.ts b/ui/site/src/component/socket.ts index c43dec857ff65..099beb88201a7 100644 --- a/ui/site/src/component/socket.ts +++ b/ui/site/src/component/socket.ts @@ -120,7 +120,7 @@ export default class StrongSocket { if (!navigator.onLine) { document.body.classList.remove('online'); document.body.classList.add('offline'); - $('#network-status').text(siteTrans('noNetwork')); + $('#network-status').text(lichess ? siteTrans('noNetwork') : 'Offline'); this.scheduleConnect(1000); return; } @@ -203,7 +203,7 @@ export default class StrongSocket { this.connectSchedule = setTimeout(() => { document.body.classList.add('offline'); document.body.classList.remove('online'); - $('#network-status').text(siteTrans('reconnecting')); + $('#network-status').text(lichess ? siteTrans('reconnecting') : 'Reconnecting'); if (!this.tryOtherUrl && navigator.onLine) { // if this was set earlier, we've already logged the error this.tryOtherUrl = true; From f286f084b028f669fabbd6c0bdeafee1f404e7f7 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Wed, 14 Feb 2024 07:56:40 +0100 Subject: [PATCH 38/39] New Crowdin updates (#14669) * New translations: site.xml (Serbian (Cyrillic)) * New translations: perfstat.xml (Romanian) * New translations: perfstat.xml (French) * New translations: perfstat.xml (Spanish) * New translations: perfstat.xml (Afrikaans) * New translations: perfstat.xml (Arabic) * New translations: perfstat.xml (Belarusian) * New translations: perfstat.xml (Bulgarian) * New translations: perfstat.xml (Catalan) * New translations: perfstat.xml (Czech) * New translations: perfstat.xml (Danish) * New translations: perfstat.xml (German) * New translations: perfstat.xml (Greek) * New translations: perfstat.xml (Basque) * New translations: perfstat.xml (Finnish) * New translations: perfstat.xml (Irish) * New translations: perfstat.xml (Hebrew) * New translations: perfstat.xml (Hungarian) * New translations: perfstat.xml (Armenian) * New translations: perfstat.xml (Italian) * New translations: perfstat.xml (Japanese) * New translations: perfstat.xml (Korean) * New translations: perfstat.xml (Lithuanian) * New translations: perfstat.xml (Macedonian) * New translations: perfstat.xml (Dutch) * New translations: perfstat.xml (Polish) * New translations: perfstat.xml (Portuguese) * New translations: perfstat.xml (Russian) * New translations: perfstat.xml (Slovak) * New translations: perfstat.xml (Slovenian) * New translations: perfstat.xml (Albanian) * New translations: perfstat.xml (Serbian (Cyrillic)) * New translations: perfstat.xml (Swedish) * New translations: perfstat.xml (Turkish) * New translations: perfstat.xml (Ukrainian) * New translations: perfstat.xml (Chinese Simplified) * New translations: perfstat.xml (Chinese Traditional) * New translations: perfstat.xml (Vietnamese) * New translations: perfstat.xml (Galician) * New translations: perfstat.xml (Portuguese, Brazilian) * New translations: perfstat.xml (Indonesian) * New translations: perfstat.xml (Persian) * New translations: perfstat.xml (Marathi) * New translations: perfstat.xml (Thai) * New translations: perfstat.xml (Croatian) * New translations: perfstat.xml (Norwegian Nynorsk) * New translations: perfstat.xml (Kazakh) * New translations: perfstat.xml (Estonian) * New translations: perfstat.xml (Latvian) * New translations: perfstat.xml (Azerbaijani) * New translations: perfstat.xml (Hindi) * New translations: perfstat.xml (English, United States) * New translations: perfstat.xml (Esperanto) * New translations: perfstat.xml (Luxembourgish) * New translations: perfstat.xml (Tatar) * New translations: perfstat.xml (Breton) * New translations: perfstat.xml (Bosnian) * New translations: perfstat.xml (Kannada) * New translations: perfstat.xml (Aragonese) * New translations: perfstat.xml (Norwegian Bokmal) * New translations: perfstat.xml (Sorani (Kurdish)) * New translations: perfstat.xml (Corsican) * New translations: perfstat.xml (Swiss German) * New translations: site.xml (Vietnamese) * New translations: site.xml (Serbian (Cyrillic)) * New translations: site.xml (English, United States) * New translations: onboarding.xml (Chinese Simplified) * New translations: site.xml (Chinese Simplified) * New translations: site.xml (Norwegian Bokmal) * New translations: broadcast.xml (Norwegian Bokmal) * New translations: patron.xml (Chinese Simplified) * New translations: preferences.xml (Chinese Simplified) * New translations: faq.xml (Chinese Simplified) * New translations: timeago.xml (Chinese Simplified) * New translations: dgt.xml (Chinese Simplified) * New translations: study.xml (French) --- translation/dest/broadcast/nb-NO.xml | 1 + translation/dest/dgt/zh-CN.xml | 8 +- translation/dest/faq/zh-CN.xml | 2 +- translation/dest/onboarding/zh-CN.xml | 20 ++--- translation/dest/patron/zh-CN.xml | 3 + translation/dest/perfStat/af-ZA.xml | 3 +- translation/dest/perfStat/an-ES.xml | 3 +- translation/dest/perfStat/ar-SA.xml | 3 +- translation/dest/perfStat/az-AZ.xml | 3 +- translation/dest/perfStat/be-BY.xml | 3 +- translation/dest/perfStat/bg-BG.xml | 3 +- translation/dest/perfStat/br-FR.xml | 3 +- translation/dest/perfStat/bs-BA.xml | 3 +- translation/dest/perfStat/ca-ES.xml | 3 +- translation/dest/perfStat/ckb-IR.xml | 3 +- translation/dest/perfStat/co-FR.xml | 3 +- translation/dest/perfStat/cs-CZ.xml | 3 +- translation/dest/perfStat/da-DK.xml | 3 +- translation/dest/perfStat/de-DE.xml | 3 +- translation/dest/perfStat/el-GR.xml | 3 +- translation/dest/perfStat/en-US.xml | 3 +- translation/dest/perfStat/eo-UY.xml | 3 +- translation/dest/perfStat/es-ES.xml | 3 +- translation/dest/perfStat/et-EE.xml | 3 +- translation/dest/perfStat/eu-ES.xml | 3 +- translation/dest/perfStat/fa-IR.xml | 3 +- translation/dest/perfStat/fi-FI.xml | 3 +- translation/dest/perfStat/fr-FR.xml | 3 +- translation/dest/perfStat/ga-IE.xml | 3 +- translation/dest/perfStat/gl-ES.xml | 3 +- translation/dest/perfStat/gsw-CH.xml | 3 +- translation/dest/perfStat/he-IL.xml | 3 +- translation/dest/perfStat/hi-IN.xml | 3 +- translation/dest/perfStat/hr-HR.xml | 3 +- translation/dest/perfStat/hu-HU.xml | 3 +- translation/dest/perfStat/hy-AM.xml | 3 +- translation/dest/perfStat/id-ID.xml | 3 +- translation/dest/perfStat/it-IT.xml | 3 +- translation/dest/perfStat/ja-JP.xml | 3 +- translation/dest/perfStat/kk-KZ.xml | 3 +- translation/dest/perfStat/kn-IN.xml | 3 +- translation/dest/perfStat/ko-KR.xml | 3 +- translation/dest/perfStat/lb-LU.xml | 3 +- translation/dest/perfStat/lt-LT.xml | 3 +- translation/dest/perfStat/lv-LV.xml | 3 +- translation/dest/perfStat/mk-MK.xml | 3 +- translation/dest/perfStat/mr-IN.xml | 3 +- translation/dest/perfStat/nb-NO.xml | 3 +- translation/dest/perfStat/nl-NL.xml | 3 +- translation/dest/perfStat/nn-NO.xml | 3 +- translation/dest/perfStat/pl-PL.xml | 3 +- translation/dest/perfStat/pt-BR.xml | 3 +- translation/dest/perfStat/pt-PT.xml | 3 +- translation/dest/perfStat/ro-RO.xml | 3 +- translation/dest/perfStat/ru-RU.xml | 3 +- translation/dest/perfStat/sk-SK.xml | 3 +- translation/dest/perfStat/sl-SI.xml | 3 +- translation/dest/perfStat/sq-AL.xml | 3 +- translation/dest/perfStat/sr-SP.xml | 3 +- translation/dest/perfStat/sv-SE.xml | 3 +- translation/dest/perfStat/th-TH.xml | 3 +- translation/dest/perfStat/tr-TR.xml | 3 +- translation/dest/perfStat/tt-RU.xml | 3 +- translation/dest/perfStat/uk-UA.xml | 3 +- translation/dest/perfStat/vi-VN.xml | 3 +- translation/dest/perfStat/zh-CN.xml | 3 +- translation/dest/perfStat/zh-TW.xml | 3 +- translation/dest/preferences/zh-CN.xml | 2 +- translation/dest/site/en-US.xml | 3 +- translation/dest/site/nb-NO.xml | 2 + translation/dest/site/sr-SP.xml | 113 +++++++++++++++++++++++++ translation/dest/site/vi-VN.xml | 2 +- translation/dest/site/zh-CN.xml | 23 ++--- translation/dest/study/fr-FR.xml | 4 +- translation/dest/timeago/zh-CN.xml | 6 +- 75 files changed, 217 insertions(+), 158 deletions(-) diff --git a/translation/dest/broadcast/nb-NO.xml b/translation/dest/broadcast/nb-NO.xml index a8b2c2a3751a5..f192c371a5db9 100644 --- a/translation/dest/broadcast/nb-NO.xml +++ b/translation/dest/broadcast/nb-NO.xml @@ -8,6 +8,7 @@ Direkteoverføringer av turneringer Ny direkteoverføring + Overføringer som du abonnerer på Om overføringer Ingen runder ennå. Hvordan bruke overføringer hos Lichess. diff --git a/translation/dest/dgt/zh-CN.xml b/translation/dest/dgt/zh-CN.xml index d4ad5076290a9..18fed6de60021 100644 --- a/translation/dest/dgt/zh-CN.xml +++ b/translation/dest/dgt/zh-CN.xml @@ -1,12 +1,12 @@ DGT 棋盘 - Lichess 与 DGT + 在 Lichess 中使用 DGT DGT 棋盘需求 DGT 棋盘限制 此页面说明如何将 DGT 棋盘连接至 Lichess,并将其投入使用。 为了连接 DGT 电子棋盘,你需要安装 %s。 - 您可以在此下载软件:%s。 + 你可以在此下载软件:%s。 如果 %1$s 已在电脑上运行,你可以%2$s以检查是否连接。 点击这里 如果 %1$s 运行在其他设备或不同的端口,则需要在%2$s设置 IP 地址和端口。 @@ -17,8 +17,8 @@ 排位对局时限:慢棋、通讯棋以及部分快棋时限,包括 15+10 和 20+0 准备就绪后,摆好你的棋盘然后点击%s。 如果你的着法未被检测到 - 先确保你在 DGT 棋盘上摆放了对手走的着法。复原你走的着法,再走一次。 - 作为最后的手段,对照 Lichess 重新摆放棋子,然后%s + 先确认你在 DGT 棋盘上放置了对手走的着法。然后退回你走的着法,再走一次。 + 作为最后的手段,对照 Lichess 重新摆放棋子,然后%s 重新加载此页面 DGT - 配置 Lichess 连接状态 diff --git a/translation/dest/faq/zh-CN.xml b/translation/dest/faq/zh-CN.xml index 4b5acf47a0b7d..93db9826ce82b 100644 --- a/translation/dest/faq/zh-CN.xml +++ b/translation/dest/faq/zh-CN.xml @@ -25,7 +25,7 @@ 对没有认输就离开的玩家怎么处理? 如果你的对手频繁中止或离开游戏,他们会被 “禁止游戏”,这意味着他们被暂时禁止参加对局。 这在他们的个人资料中不会说明。 如果这种行为继续下去,禁止游戏的期限就会延长――长期被禁止可能会导致账户的关闭。 如何成为仲裁人? - 无法申请成为仲裁人。 如果我们看到我们认为会成为很好的仲裁人的人,我们将直接与他们联系。 + 你没有办法主动申请成为管理员。 如果有我们认为有能力担任管理员的人,我们会直接与他们联系。 通讯棋是否不同于常规棋? 欲了解更多信息,请阅读我们的 %s 公平对弈页面 diff --git a/translation/dest/onboarding/zh-CN.xml b/translation/dest/onboarding/zh-CN.xml index beca0bba6ac8e..f911da0f69328 100644 --- a/translation/dest/onboarding/zh-CN.xml +++ b/translation/dest/onboarding/zh-CN.xml @@ -1,17 +1,17 @@ 欢迎! - 欢迎来到 lichess.org。 + 欢迎来到 Lichess! 这是你的个人资料页面。 - 未成年人会使用此帐户吗?您可能想要启用 %s。 + 如果此账户是为儿童创建的,那你可能会想启用 %s。 现在做什么?以下是一些建议: - 学习国际象棋规则 - 练习谜题以提高战术技巧 - 和人工智能对战 - 和世界各地的对手对战 - 在Lichess上关注你的朋友们 + 学习国际象棋的规则 + 练习谜题以提升技能 + 和电脑对战 + 和世界各地的棋手对战 + 在 Lichess 上关注你的朋友们 参与锦标赛 - 从%1$s与%2$s中学习 - 根据您的喜好配置lichess - 探索这个网站,好好玩吧:) + 从%1$s和%2$s中学习 + 根据你的偏好配置 Lichess + 探索网站,愉快地玩 :) diff --git a/translation/dest/patron/zh-CN.xml b/translation/dest/patron/zh-CN.xml index 4b8edf715d988..8f4360834a653 100644 --- a/translation/dest/patron/zh-CN.xml +++ b/translation/dest/patron/zh-CN.xml @@ -78,4 +78,7 @@ 你是一个月的 Lichess 的赞助者! 在一个月内,你不会再次被收取费用,且你的 Lichess 账户将变回普通。 更改币种 + 付款详情 + 更新付款方式 + 管理你的订阅并下载发票和收据信息 diff --git a/translation/dest/perfStat/af-ZA.xml b/translation/dest/perfStat/af-ZA.xml index 628d2a1804f50..ca84caba8f14a 100644 --- a/translation/dest/perfStat/af-ZA.xml +++ b/translation/dest/perfStat/af-ZA.xml @@ -22,10 +22,9 @@ vanaf %1$s tot %2$s Weghol-wen reeks Verloor reeks - Langste reeks: %s + Langste reeks: %s Huidige reeks: %s Hoogste gegradeerde oorwinnings - Laagste gegradeerde nederlaag Spelle gespeel in \'n ry Minder as een uur tussen spelle Maks tyd spandeer op speel diff --git a/translation/dest/perfStat/an-ES.xml b/translation/dest/perfStat/an-ES.xml index a560df195fedb..b2b15730da00d 100644 --- a/translation/dest/perfStat/an-ES.xml +++ b/translation/dest/perfStat/an-ES.xml @@ -22,10 +22,9 @@ dende %1$s dica %2$s Tongada de victorias Tongada de redotas - Tongada mas larga: %s + Tongada mas larga: %s Tongada actual: %s Millors victorias per puntos - Piors redotas per puntos Partidas chugadas seguidas Menos d\'una hora entre partidas Tiempo maximo chugando diff --git a/translation/dest/perfStat/ar-SA.xml b/translation/dest/perfStat/ar-SA.xml index 998ca4f8684e5..b9acd582d146d 100644 --- a/translation/dest/perfStat/ar-SA.xml +++ b/translation/dest/perfStat/ar-SA.xml @@ -22,10 +22,9 @@ من %1$s الى %2$s سلسلة الانتصارات سلسلة الهزائم - اطول سلسلة: %s + اطول سلسلة: %s السلسلة الحالية: %s افضل الانتصارات المقيّمة - اسوء الهزائم المقيّمة مباريات لُعبت على التوالي اقل من ساعة واحدة بين المباريات اقصى وقت مقضي في اللعب diff --git a/translation/dest/perfStat/az-AZ.xml b/translation/dest/perfStat/az-AZ.xml index 8a64547f36f67..28d724635f384 100644 --- a/translation/dest/perfStat/az-AZ.xml +++ b/translation/dest/perfStat/az-AZ.xml @@ -22,10 +22,9 @@ %1$s tarixindən %2$s tarixinə qədər Qalibiyyət seriyası Məğlubiyyət seriyası - Ən uzun seriya: %s + Ən uzun seriya: %s Hazırkı seriya: %s Ən yüksək reytinqli qələbələr - Ən pis xallı məğlubiyyətlər Ardıcıl oynanılan oyunlar Oyunlar arasında bir saatdan az ara olmalıdır Oyun üçün xərclənən ən uzun vaxt diff --git a/translation/dest/perfStat/be-BY.xml b/translation/dest/perfStat/be-BY.xml index 202df789068bf..23e66ad92c04c 100644 --- a/translation/dest/perfStat/be-BY.xml +++ b/translation/dest/perfStat/be-BY.xml @@ -22,10 +22,9 @@ ад %1$s да %2$s Перамог запар Паразаў запар - Найдаўжэйшая серыя: %s + Найдаўжэйшая серыя: %s Бягучая серыя: %s Найлепшыя рэйтынгавыя перамогі - Горшыя рэйтынгавыя паразы Гульняў сыграна запар Менш за гадзіну паміж гульнямі Максімальны час за гульнёй diff --git a/translation/dest/perfStat/bg-BG.xml b/translation/dest/perfStat/bg-BG.xml index 49a48d5911b1b..860b9acd732ef 100644 --- a/translation/dest/perfStat/bg-BG.xml +++ b/translation/dest/perfStat/bg-BG.xml @@ -22,10 +22,9 @@ от %1$s до %2$s Печеливша поредица Губеща поредица - Най-дълга поредица: %s + Най-дълга поредица: %s Текуща поредица: %s Най-добри победи в игри с рейтинг - Най-тежки загуби в игри с рейтинг Изиграни игри подред По-малко от час между игри Най-дълго време прекарано в игра diff --git a/translation/dest/perfStat/br-FR.xml b/translation/dest/perfStat/br-FR.xml index 3dc5f9cf5c16b..d213ec73dafc9 100644 --- a/translation/dest/perfStat/br-FR.xml +++ b/translation/dest/perfStat/br-FR.xml @@ -21,10 +21,9 @@ etre %1$s ha %2$s Krogadoù gounezet da-heul Krogadoù kollet da-heul - Brasañ niver da heul: %s + Brasañ niver da heul: %s Niver a grogadoù da heul evit poent: %s Gwellañ trec\'hioù renket - Gwashañ lammoù renket Krogadoù c\'hoariet hep troc\'h Nebeutoc\'h evit un eur etre daou grogad Ar muiañ a amzer o c\'hoari dizehan diff --git a/translation/dest/perfStat/bs-BA.xml b/translation/dest/perfStat/bs-BA.xml index 81d08b82562ae..c73f618180949 100644 --- a/translation/dest/perfStat/bs-BA.xml +++ b/translation/dest/perfStat/bs-BA.xml @@ -22,10 +22,9 @@ od %1$s do %2$s Pobjednički Niz Gubitnički Niz - Najduži niz: %s + Najduži niz: %s Trenutni niz: %s Pobjede protiv protivnika visokog rejtinga - Porazi protiv protivnika nižeg rejtinga Broj odigranih partija u nizu Manje od jednog sata između partija Maksimalno vrijeme provedeno igrajući diff --git a/translation/dest/perfStat/ca-ES.xml b/translation/dest/perfStat/ca-ES.xml index e214c2a3b787f..82e89ae0f8076 100644 --- a/translation/dest/perfStat/ca-ES.xml +++ b/translation/dest/perfStat/ca-ES.xml @@ -22,10 +22,9 @@ des de %1$s fins a %2$s Ratxa de victòries Ratxa de derrotes - Ratxa més llarga: %s + Ratxa més llarga: %s Ratxa actual: %s Millors victòries puntuables - Pitjors derrotes puntuables Partides jugades seguides Menys d\'una hora entre partida i partida Temps màxim jugant diff --git a/translation/dest/perfStat/ckb-IR.xml b/translation/dest/perfStat/ckb-IR.xml index 727c2a563a93e..074047823b2f1 100644 --- a/translation/dest/perfStat/ckb-IR.xml +++ b/translation/dest/perfStat/ckb-IR.xml @@ -22,10 +22,9 @@ لە %1$s بۆ %2$s بردنەوەی یەک لە دوای یەک دۆڕانی یەک بە دوای یەک - درێژترین ماوەی یەک بە دوای یەک: %s + درێژترین ماوەی یەک بە دوای یەک: %s بردنەوەی یەکبەدوای یەکی ئێستات:%s باشترین سەرکەوتنەکانی پلەبەندی - خراپترین شکستەکانی پلەبەندی یارییەکان لەسەریەک ئەنجامدراون کەمتر لە کاتژمێرێک لە نێوان یارییەکاندا زۆرترین کات بەسەربردن بە یاریکردن diff --git a/translation/dest/perfStat/co-FR.xml b/translation/dest/perfStat/co-FR.xml index 64d964a256357..82e4493afc91b 100644 --- a/translation/dest/perfStat/co-FR.xml +++ b/translation/dest/perfStat/co-FR.xml @@ -21,10 +21,9 @@ trà u %1$s è u %2$s Seria di vittorie Seria di scunfitte - A più longa seria:%s + A più longa seria:%s Seria attuale: %s E vittorie contru à i ghjucadori cù a classifica a più alta - E scunfitte contru à i ghjucadori cù a classifica a più bassa Partite ghjucate à a fila Menu d\' una ora trà e partite Tempu massimu passatu à ghjucà diff --git a/translation/dest/perfStat/cs-CZ.xml b/translation/dest/perfStat/cs-CZ.xml index 0e954173fc2e5..eb4e4f9b058e1 100644 --- a/translation/dest/perfStat/cs-CZ.xml +++ b/translation/dest/perfStat/cs-CZ.xml @@ -22,10 +22,9 @@ od %1$s do %2$s Série výher Série proher - Nejdelší série: %s + Nejdelší série: %s Aktuální série: %s Nejlépe hodnocená vítězství - Nejhůře hodnocené prohry Hry odehrané v řadě Méně než jedna hodina mezi hrami Maximální čas strávený hraním diff --git a/translation/dest/perfStat/da-DK.xml b/translation/dest/perfStat/da-DK.xml index 05d6f75ba096f..771c6242acb32 100644 --- a/translation/dest/perfStat/da-DK.xml +++ b/translation/dest/perfStat/da-DK.xml @@ -22,10 +22,9 @@ fra %1$s til %2$s Sejrsstime Tabsstime - Længste stime: %s + Længste stime: %s Aktuel stime: %s Bedst ratede sejre - Værst ratede nederlag Partier spillet i træk Mindre end en time mellem partier Maks tid brugt på at spille diff --git a/translation/dest/perfStat/de-DE.xml b/translation/dest/perfStat/de-DE.xml index eb3ac31d120b8..54efd45c00709 100644 --- a/translation/dest/perfStat/de-DE.xml +++ b/translation/dest/perfStat/de-DE.xml @@ -22,10 +22,9 @@ von %1$s zu %2$s Siegesserie Niederlagenserie - Längste Serie: %s + Längste Serie: %s Aktuelle Serie: %s Beste gewertete Siege - Schlimmste gewertete Niederlagen In Folge gespielte Spiele Weniger als eine Stunde zwischen den Spielen Maximale Spielzeit diff --git a/translation/dest/perfStat/el-GR.xml b/translation/dest/perfStat/el-GR.xml index 64ede3b150248..ab5566d87cd3a 100644 --- a/translation/dest/perfStat/el-GR.xml +++ b/translation/dest/perfStat/el-GR.xml @@ -22,10 +22,9 @@ από %1$s έως %2$s Συνεχόμενες νίκες Συνεχόμενες ήττες - Μεγαλύτερο Σερί: %s + Μεγαλύτερο Σερί: %s Τρέχον σερί: %s Καλύτερες αξιολογήσιμες νίκες - Χειρότερες αξιολογήσιμες ήττες Συνεχόμενες παρτίδες Διάστημα λιγότερο από μία ώρα μεταξύ των παρτίδων Μέγιστος χρόνος που διατέθηκε παίζοντας diff --git a/translation/dest/perfStat/en-US.xml b/translation/dest/perfStat/en-US.xml index 357f038bcc565..8376facbdc1da 100644 --- a/translation/dest/perfStat/en-US.xml +++ b/translation/dest/perfStat/en-US.xml @@ -22,10 +22,9 @@ from %1$s to %2$s Winning streak Losing streak - Longest streak: %s + Longest streak: %s Current streak: %s Best rated victories - Worst rated defeats Games played in a row Less than one hour between games Max time spent playing diff --git a/translation/dest/perfStat/eo-UY.xml b/translation/dest/perfStat/eo-UY.xml index 2cfe781025e6a..3b5cb2d00a8b3 100644 --- a/translation/dest/perfStat/eo-UY.xml +++ b/translation/dest/perfStat/eo-UY.xml @@ -22,10 +22,9 @@ de %1$s al %2$s Sinsekva gajnado Sinsekva perdado - Plej longa sinsekva rezulto: %s + Plej longa sinsekva rezulto: %s Nuntempa sinsekva rezulto: %s Plej bonaj venkoj laŭ kontraŭula rango - Plej malbonaj malvenkoj laŭ kontraŭula rango Ludoj sinsekve luditaj Malpli ol unu horo inter ludoj Maksimuma tempo pasita ludante diff --git a/translation/dest/perfStat/es-ES.xml b/translation/dest/perfStat/es-ES.xml index aef2d05a8a00b..17ed9e6afda8c 100644 --- a/translation/dest/perfStat/es-ES.xml +++ b/translation/dest/perfStat/es-ES.xml @@ -22,10 +22,9 @@ desde %1$s hasta %2$s Racha de victorias Racha de derrotas - Racha más larga: %s + Racha más larga: %s Racha actual: %s Mejores victorias por puntos - Peores derrotas por puntos Partidas jugadas seguidas Menos de una hora entre partidas Tiempo máximo jugando diff --git a/translation/dest/perfStat/et-EE.xml b/translation/dest/perfStat/et-EE.xml index ddfe8913fc416..4e91b7d5d83f9 100644 --- a/translation/dest/perfStat/et-EE.xml +++ b/translation/dest/perfStat/et-EE.xml @@ -22,10 +22,9 @@ ajavahemikus %1$s - %2$s Võitude seeria Kaotuste seeria - Pikim seeria: %s + Pikim seeria: %s Praegune seeria: %s Parimad reitinguga võidud - Halvimad reitinguga kaotused Järjestikusi mänge Mängude vahel vähem kui tund Pikim aeg mängimas diff --git a/translation/dest/perfStat/eu-ES.xml b/translation/dest/perfStat/eu-ES.xml index 839a0d2bf1e00..b85c1ac7d7032 100644 --- a/translation/dest/perfStat/eu-ES.xml +++ b/translation/dest/perfStat/eu-ES.xml @@ -22,10 +22,9 @@ %1$s - %2$s Garaipenen segida Porroten segida - Segida luzeena: %s + Segida luzeena: %s Uneko segida: %s Garaipen onenak - Porrot txarrenak Jarraian jokatutako partida kopurua Partiden artean ordubete baino gutxiago Jokatzen emandako denbora gehiena diff --git a/translation/dest/perfStat/fa-IR.xml b/translation/dest/perfStat/fa-IR.xml index 0fd1b5f9512d8..0d7ee9a17bde0 100644 --- a/translation/dest/perfStat/fa-IR.xml +++ b/translation/dest/perfStat/fa-IR.xml @@ -22,10 +22,9 @@ از %1$s تا %2$s بردهای متوالی باخت‌های متوالی - طولانی‌ترین توالی: %s + طولانی‌ترین توالی: %s استمرار فعلی: %s بهترین پیروزی های رسمی - بدترین باخت های رسمی بازی های متوالی انجام شده کمتر از یک ساعت بین بازی‌ها بیشترین زمانی که صرف بازی شده است diff --git a/translation/dest/perfStat/fi-FI.xml b/translation/dest/perfStat/fi-FI.xml index d068b806a55ba..b456c2167826d 100644 --- a/translation/dest/perfStat/fi-FI.xml +++ b/translation/dest/perfStat/fi-FI.xml @@ -22,10 +22,9 @@ aikavälillä %1$s–%2$s Voittoputki Tappioputki - Pisin putki: %s + Pisin putki: %s Nykyinen putki: %s Korkeimman vahvuusluvun voitot - Alimman vahvuusluvun tappiot Peräjälkeen pelattuja pelejä Alle tunti pelien välissä Pisin yhtäjaksoinen peliaika diff --git a/translation/dest/perfStat/fr-FR.xml b/translation/dest/perfStat/fr-FR.xml index 6b6d5d8875b45..7f1e50a3b54b5 100644 --- a/translation/dest/perfStat/fr-FR.xml +++ b/translation/dest/perfStat/fr-FR.xml @@ -22,10 +22,9 @@ de %1$s à %2$s Victoires consécutives Défaites consécutives - Série la plus longue : %s + Série la plus longue : %s Série actuelle : %s Meilleures victoires classées - Pires défaites classées Parties jouées à la suite Moins d\'une heure entre les parties Temps maximal à jouer en continu diff --git a/translation/dest/perfStat/ga-IE.xml b/translation/dest/perfStat/ga-IE.xml index c98a0480da17a..b09dffd62a880 100644 --- a/translation/dest/perfStat/ga-IE.xml +++ b/translation/dest/perfStat/ga-IE.xml @@ -22,10 +22,9 @@ ó %1$s go %2$s Stríoc bua Stríoc caillte - Stríoc is faide: %s + Stríoc is faide: %s Stríoc reatha: %s Bua ar an rátáil is fearr - Cailleadh cluichí ar an rátáil is measa Cluichí a imrítear i ndiaidh a chéile Níos lú ná uair an chloig idir cluichí Uasmhéid ama caite ag imirt diff --git a/translation/dest/perfStat/gl-ES.xml b/translation/dest/perfStat/gl-ES.xml index 9dcd9bdbac3cd..3b37473ed76b3 100644 --- a/translation/dest/perfStat/gl-ES.xml +++ b/translation/dest/perfStat/gl-ES.xml @@ -22,10 +22,9 @@ de %1$s a %2$s Vitorias consecutivas Derrotas consecutivas - Secuencia máis longa: %s + Secuencia máis longa: %s Secuencia actual: %s Mellores vitorias puntuadas - Peores derrotas puntuadas Partidas xogadas seguidas Menos dunha hora entre partidas Tempo máximo xogando diff --git a/translation/dest/perfStat/gsw-CH.xml b/translation/dest/perfStat/gsw-CH.xml index 733810dae59af..16241e1af800c 100644 --- a/translation/dest/perfStat/gsw-CH.xml +++ b/translation/dest/perfStat/gsw-CH.xml @@ -22,10 +22,9 @@ vu %1$s bis %2$s Sieges Serie Niderlage Serie - Längschti Serie: %s + Längschti Serie: %s Aktuelli Serie: %s die beschte Sieg - schlimmschti Niederlage In Serie gschpillti Partie Weniger als 1 Schtund zwüsche de Schpil Maximali Schpillzit diff --git a/translation/dest/perfStat/he-IL.xml b/translation/dest/perfStat/he-IL.xml index 83b21503c1b5e..5c37ed7c60906 100644 --- a/translation/dest/perfStat/he-IL.xml +++ b/translation/dest/perfStat/he-IL.xml @@ -22,10 +22,9 @@ מ - %1$s עד %2$s רצף ניצחונות רצף הפסדים - הרצף הארוך ביותר: %s + הרצף הארוך ביותר: %s רצף נוכחי: %s ניצחונות בדירוג הגבוה ביותר - הפסדים בדירוג הנמוך ביותר משחקים ששוחקו ברצף פחות משעה בין משחקים הכי הרבה זמן במשחק diff --git a/translation/dest/perfStat/hi-IN.xml b/translation/dest/perfStat/hi-IN.xml index 55363259ece5b..48743aaf97c9a 100644 --- a/translation/dest/perfStat/hi-IN.xml +++ b/translation/dest/perfStat/hi-IN.xml @@ -22,10 +22,9 @@ %1$s से %2$s तक लगातार जीत की संख्या लगातार हार की संख्या - सबसे लंबी स्ट्रीक: %s + सबसे लंबी स्ट्रीक: %s वर्तमान स्ट्रीक: %s सर्वश्रेष्ठ रेटेड जीत - सबसे खराब रेटेड हार लगातार खेले गए खेल वो खेल जिन के बीच एक घंटे से कम फासला हो खेलने में बिताया गया अधिकतम समय diff --git a/translation/dest/perfStat/hr-HR.xml b/translation/dest/perfStat/hr-HR.xml index 73eb8584700e6..761a08aab0c0a 100644 --- a/translation/dest/perfStat/hr-HR.xml +++ b/translation/dest/perfStat/hr-HR.xml @@ -22,10 +22,9 @@ od %1$s do %2$s Pobjednički niz Gubitnički niz - Najduži niz: %s + Najduži niz: %s Trenutni niz: %s Najbolje rangirane pobjede - Najgore rangirani porazi Igre odigrane za redom Manje od jednog sata između igara Vrijeme provedeno igrajući diff --git a/translation/dest/perfStat/hu-HU.xml b/translation/dest/perfStat/hu-HU.xml index 3ec14de6d03f7..caaf08c69d93a 100644 --- a/translation/dest/perfStat/hu-HU.xml +++ b/translation/dest/perfStat/hu-HU.xml @@ -22,10 +22,9 @@ %1$s-tól %2$s-ig Győztes sorozat Vesztes sorozat - Leghosszabb sorozat: %s + Leghosszabb sorozat: %s Jelenlegi sorozat: %s Legjobb győzelmek - Legrosszabb vereségek Egymás után játszott partik Kevesebb, mint egy óra játszmák között Legtöbb játékkal töltött idő diff --git a/translation/dest/perfStat/hy-AM.xml b/translation/dest/perfStat/hy-AM.xml index c9cdbff486fe4..d525331a61815 100644 --- a/translation/dest/perfStat/hy-AM.xml +++ b/translation/dest/perfStat/hy-AM.xml @@ -22,10 +22,9 @@ %1$s-ից %2$s Անընդմեջ հաղթանակներ Անընդմեջ պարտություններ - Ամենաերկար շարքը` %s + Ամենաերկար շարքը` %s Ընթացիկ շարքը` %s Հաղթանակներ ամենաբարձր վարկանիշ ունեցողների նկատմամբ - Պարտություններ ամենացածր վարկանիշ ունեցողներից Անընդմեջ խաղացված պարտիաներ Պարտիաների միջև դադարը` մեկ ժամից պակաս Առավելագույն խաղաժամանակ diff --git a/translation/dest/perfStat/id-ID.xml b/translation/dest/perfStat/id-ID.xml index 1ea12d7fc162d..1fbd4cfbb0b4f 100644 --- a/translation/dest/perfStat/id-ID.xml +++ b/translation/dest/perfStat/id-ID.xml @@ -22,10 +22,9 @@ dari %1$s ke %2$s Kemenangan beruntun Kekalahan beruntun - Beruntun terpanjang: %s + Beruntun terpanjang: %s Beruntun saat ini: %s Kemenangan dirating terbaik - Kekalahan dirating terburuk Permainan yang dimainkan berturut-turut Kurang dari satu jam antar permainan Maksimal waktu bermain diff --git a/translation/dest/perfStat/it-IT.xml b/translation/dest/perfStat/it-IT.xml index b76480eee0189..eb07da5c5ed86 100644 --- a/translation/dest/perfStat/it-IT.xml +++ b/translation/dest/perfStat/it-IT.xml @@ -22,10 +22,9 @@ da %1$s a %2$s Serie di vittorie Serie di sconfitte - Serie più lunga: %s + Serie più lunga: %s Serie attuale: %s Migliori vittorie classificate - Peggiori sconfitte classificate Partite giocate di fila Meno di un\'ora tra partite Tempo massimo trascorso giocando diff --git a/translation/dest/perfStat/ja-JP.xml b/translation/dest/perfStat/ja-JP.xml index 73dcf55c6174c..8df6f716f84a0 100644 --- a/translation/dest/perfStat/ja-JP.xml +++ b/translation/dest/perfStat/ja-JP.xml @@ -22,10 +22,9 @@ %1$s から %2$s まで 連勝 連敗 - 最長:%s + 最長:%s 現在:%s 勝った相手の最高 - 負けた相手の最低 連続対局数 ゲーム間隔 1 時間以内 最長連続プレイ時間 diff --git a/translation/dest/perfStat/kk-KZ.xml b/translation/dest/perfStat/kk-KZ.xml index 0a54e68c53795..519159e5ac06d 100644 --- a/translation/dest/perfStat/kk-KZ.xml +++ b/translation/dest/perfStat/kk-KZ.xml @@ -22,10 +22,9 @@ %1$s - %2$s аралығында Жеңістер тізбегі Жеңілістер тізбегі - Ең ұзақ тізбек: %s + Ең ұзақ тізбек: %s Қазіргі тізбек: %s Ең бағалы жеңістер - Ең ауыр жеңілістер Қатарынан ойналған ойындар Ойындар арасы бір сағаттан кем Ойынмен өткен ең ұзақ уақыт diff --git a/translation/dest/perfStat/kn-IN.xml b/translation/dest/perfStat/kn-IN.xml index b261e3416f447..ae8e23965e146 100644 --- a/translation/dest/perfStat/kn-IN.xml +++ b/translation/dest/perfStat/kn-IN.xml @@ -22,10 +22,9 @@ %1$s ರಿಂದ %2$s ವರೆಗೆ ಗೆಲುವಿನ ಸರಮಾಲೆ ಸೋತ ಸರಣಿ - ಅತಿ ಉದ್ದದ ಸ್ಟ್ರೀಕ್ ಗೆಲುವುಗಳು: %s + ಅತಿ ಉದ್ದದ ಸ್ಟ್ರೀಕ್ ಗೆಲುವುಗಳು: %s ಪ್ರಸ್ತುತ ಸರಣಿ: %s ಅತ್ಯುತ್ತಮ ರೇಟ್ ಮಾಡಿದ ವಿಜಯಗಳು - ಕೆಟ್ಟ ರೇಟಿಂಗ್ ಸೋಲುಗಳು ಆಟಗಳನ್ನು ಸತತವಾಗಿ ಆಡಲಾಗುತ್ತದೆ ಆಟಗಳ ನಡುವೆ ಒಂದು ಗಂಟೆಗಿಂತ ಕಡಿಮೆ ಆಟವಾಡಿದ ಗರಿಷ್ಠ ಸಮಯ diff --git a/translation/dest/perfStat/ko-KR.xml b/translation/dest/perfStat/ko-KR.xml index 5bef00ac7f164..05bfde2b29dd7 100644 --- a/translation/dest/perfStat/ko-KR.xml +++ b/translation/dest/perfStat/ko-KR.xml @@ -22,10 +22,9 @@ %1$s에서 %2$s 연승 연패 - 최고 기록: %s + 최고 기록: %s 현재 기록: %s 승리한 최고 레이팅 - 패배한 최저 레이팅 연속 게임 플레이 게임 사이가 1시간 미만인 경우 게임을 한 최대 시간 diff --git a/translation/dest/perfStat/lb-LU.xml b/translation/dest/perfStat/lb-LU.xml index 1001d1eb80a47..107479458c7ff 100644 --- a/translation/dest/perfStat/lb-LU.xml +++ b/translation/dest/perfStat/lb-LU.xml @@ -22,10 +22,9 @@ Vun %1$s bis %2$s Erfollegsserie Verloschserie - Längsten Erfollegserie: %s + Längsten Erfollegserie: %s Aktuell Erfollegserie: %s Bescht gewäert Victoirë - Schlëmmst gewäert Defaiten Partien hannerteneen gespillt Manner wéi eng Stonn zwëschen den Partien Maximal Spillzäit diff --git a/translation/dest/perfStat/lt-LT.xml b/translation/dest/perfStat/lt-LT.xml index 14307168fa63f..5839a345fa217 100644 --- a/translation/dest/perfStat/lt-LT.xml +++ b/translation/dest/perfStat/lt-LT.xml @@ -22,10 +22,9 @@ nuo %1$s iki %2$s Pergalių iš eilės Pralaimėjimų iš eilės - Daugiausia iš eilės: %s + Daugiausia iš eilės: %s Kol kas iš eilės: %s Geriausios reitinguotos pergalės - Blogiausia reitinguoti pralaimėjimai Partijų žaista iš eilės Mažiau negu valanda tarp partijų Daugiausia laiko praleista žaidžiant diff --git a/translation/dest/perfStat/lv-LV.xml b/translation/dest/perfStat/lv-LV.xml index 12b6ee027b0bb..aaf50ed71d56e 100644 --- a/translation/dest/perfStat/lv-LV.xml +++ b/translation/dest/perfStat/lv-LV.xml @@ -22,10 +22,9 @@ no %1$s līdz %2$s Uzvaras pēc kārtas Zaudējumi pēc kārtas - Garākā sērija: %s + Garākā sērija: %s Pašreizējā sērija: %s Labākās vērtētās uzvaras - Smagākie vērtētie zaudējumi Pēc kārtas spēlētās spēles Mazāk par stundu starp spēlēm Ilgākais spēlējot pavadītais laiks diff --git a/translation/dest/perfStat/mk-MK.xml b/translation/dest/perfStat/mk-MK.xml index a58bbc567c6c7..744a3c156e0af 100644 --- a/translation/dest/perfStat/mk-MK.xml +++ b/translation/dest/perfStat/mk-MK.xml @@ -22,10 +22,9 @@ од %1$s до %2$s Победничка низа Губитничка низа - Најдолга низа: %s + Најдолга низа: %s Сегашна низа: %s Најдобро рангирани победи - Најлошо рангирани порази Број одиграни партии во низа Помалку од еден час меѓу партии Макс. време поминато во играње diff --git a/translation/dest/perfStat/mr-IN.xml b/translation/dest/perfStat/mr-IN.xml index cf258d08e2a21..dfc9684e089f2 100644 --- a/translation/dest/perfStat/mr-IN.xml +++ b/translation/dest/perfStat/mr-IN.xml @@ -22,10 +22,9 @@ %1$s पासून %2$s पर्यंत विजयाची मालिका पराभवांची मािलका - सर्वात लांब मालिका: %s + सर्वात लांब मालिका: %s सद्य मालिका: %s गुणांनुसार सर्वोच्च विजय - गुणांनुसार सर्वात वाईट पराभव सलग खेळ दोन डावांमध्ये एका तासापेक्षा कमी वेळ खेळण्यात घालवलेला सर्वाधिक वेळ diff --git a/translation/dest/perfStat/nb-NO.xml b/translation/dest/perfStat/nb-NO.xml index d9662ca51fb0b..f8920adf30783 100644 --- a/translation/dest/perfStat/nb-NO.xml +++ b/translation/dest/perfStat/nb-NO.xml @@ -22,10 +22,9 @@ fra %1$s til %2$s Seiersrekke Tapsrekke - Lengste rekke: %s + Lengste rekke: %s Nåværende rekke: %s Beste seire - Verste tap Partier spilt på rad Mindre enn én time mellom partiene Maks tid brukt på å spille diff --git a/translation/dest/perfStat/nl-NL.xml b/translation/dest/perfStat/nl-NL.xml index ed52bbfe49016..cacd54342a832 100644 --- a/translation/dest/perfStat/nl-NL.xml +++ b/translation/dest/perfStat/nl-NL.xml @@ -22,10 +22,9 @@ van %1$s tot %2$s Overwinningsreeks Verliesreeks - Langste reeks: %s + Langste reeks: %s Huidige reeks: %s Grootste overwinningen - Grootste nederlagen Aaneengesloten partijen Minder dan een uur tussen de partijen Langste schaakpartij diff --git a/translation/dest/perfStat/nn-NO.xml b/translation/dest/perfStat/nn-NO.xml index 811d019a305a9..dd2aaa1e8c70b 100644 --- a/translation/dest/perfStat/nn-NO.xml +++ b/translation/dest/perfStat/nn-NO.xml @@ -22,10 +22,9 @@ frå %1$s til %2$s Vinstrekkje Tapsrekke - Lengste rekke: %s + Lengste rekke: %s Noverande rekke: %s Beste sigrar - Verste tap Parti spela på rad Mindre enn ein time mellom partia Lengste speletid diff --git a/translation/dest/perfStat/pl-PL.xml b/translation/dest/perfStat/pl-PL.xml index 8407f9e6f453e..a373db883d634 100644 --- a/translation/dest/perfStat/pl-PL.xml +++ b/translation/dest/perfStat/pl-PL.xml @@ -22,10 +22,9 @@ od %1$s do %2$s Seria zwycięstw Seria porażek - Najdłuższa seria: %s + Najdłuższa seria: %s Bieżąca seria: %s Najlepsze zwycięstwa - Najgorsze porażki Gry rozegrane z rzędu Mniej niż jedna godzina pomiędzy grami Maksymalny czas spędzony na grze diff --git a/translation/dest/perfStat/pt-BR.xml b/translation/dest/perfStat/pt-BR.xml index e8db4e5fdfd4b..657f00eee698c 100644 --- a/translation/dest/perfStat/pt-BR.xml +++ b/translation/dest/perfStat/pt-BR.xml @@ -22,10 +22,9 @@ de %1$s para %2$s Série de Vitórias Série de derrotas - Sequência mais longa: %s + Sequência mais longa: %s Sequência atual: %s Melhores vitórias valendo pontuação - Piores derrotas valendo pontuação Partidas jogadas seguidas Menos de uma hora entre partidas Tempo máximo jogando diff --git a/translation/dest/perfStat/pt-PT.xml b/translation/dest/perfStat/pt-PT.xml index 3962411dd14be..3515f86baaba4 100644 --- a/translation/dest/perfStat/pt-PT.xml +++ b/translation/dest/perfStat/pt-PT.xml @@ -22,10 +22,9 @@ de %1$s a %2$s Vitórias consecutivas Derrotas consecutivas - Sequência mais longa: %s + Sequência mais longa: %s Sequência atual: %s Melhores vitórias a pontuar - Piores derrotas a pontuar Partidas jogadas de seguida Menos de uma hora entre partidas Tempo máximo passado a jogar diff --git a/translation/dest/perfStat/ro-RO.xml b/translation/dest/perfStat/ro-RO.xml index 1043d9b3137ff..8e17b34033619 100644 --- a/translation/dest/perfStat/ro-RO.xml +++ b/translation/dest/perfStat/ro-RO.xml @@ -22,10 +22,9 @@ de la %1$s la %2$s Victorii consecutive Înfrângeri consecutive - Cea mai lungă secvență: %s + Cea mai lungă secvență: %s Secvența curentă: %s Cele mai bune victorii oficiale - Cele mai rele înfrângeri oficiale Meciuri jucate consecutiv Mai puțin de o oră între meciuri Cel mai mult timp petrecut jucând diff --git a/translation/dest/perfStat/ru-RU.xml b/translation/dest/perfStat/ru-RU.xml index 9ed6592935205..16aa33c5841c7 100644 --- a/translation/dest/perfStat/ru-RU.xml +++ b/translation/dest/perfStat/ru-RU.xml @@ -22,10 +22,9 @@ от %1$s до %2$s Побед подряд Поражений подряд - Рекордная серия: %s + Рекордная серия: %s Текущая серия: %s Победы против лучших по рейтингу - Поражения худшим по рейтингу Сыгранные подряд игры Перерыв между играми менее часа Максимальное время за игрой diff --git a/translation/dest/perfStat/sk-SK.xml b/translation/dest/perfStat/sk-SK.xml index 0bd65e9432564..bb2433a836d66 100644 --- a/translation/dest/perfStat/sk-SK.xml +++ b/translation/dest/perfStat/sk-SK.xml @@ -22,10 +22,9 @@ od %1$s do %2$s Séria výhier Séria prehier - Najdlhšia séria: %s + Najdlhšia séria: %s Súčasná séria: %s Najlepšie hodnotené víťazstvá - Najhoršie hodnotené víťazstvá Hry hrané v rade Menej ako hodina medzi hrami Max čas strávený hraním diff --git a/translation/dest/perfStat/sl-SI.xml b/translation/dest/perfStat/sl-SI.xml index b33ff7ee0500e..2f34ae6f11156 100644 --- a/translation/dest/perfStat/sl-SI.xml +++ b/translation/dest/perfStat/sl-SI.xml @@ -22,10 +22,9 @@ od %1$s do %2$s Zmagovalni niz Niz porazov - Najdaljši niz: %s + Najdaljši niz: %s Trenutni niz: %s Najbolj rangirane zmage - Najslabše rangirani porazi Odigrane partije v vrsti Manj kot 1 ura med partijami Najdaljši čas igranja diff --git a/translation/dest/perfStat/sq-AL.xml b/translation/dest/perfStat/sq-AL.xml index e8d864a5deb9d..eb3950b5820b9 100644 --- a/translation/dest/perfStat/sq-AL.xml +++ b/translation/dest/perfStat/sq-AL.xml @@ -22,10 +22,9 @@ nga %1$s deri %2$s Fitore radhazi Humbje radhazi - Vijimësia më e gjatë: %s + Vijimësia më e gjatë: %s Vijimësi aktuale: %s Fitoret më të mira - Humbjet më të dobëta Lojëra radhazi Më pak se një orë mes lojërave Maksimum kohe shpenzuar në lojë diff --git a/translation/dest/perfStat/sr-SP.xml b/translation/dest/perfStat/sr-SP.xml index 35196061e1f8d..7331f5bbfaa13 100644 --- a/translation/dest/perfStat/sr-SP.xml +++ b/translation/dest/perfStat/sr-SP.xml @@ -21,10 +21,9 @@ од %1$s до %2$s Низ победа Низ пораза - Најдужи низ: %s + Најдужи низ: %s Тренутни низ: %s Најбоље рангиране победе - Најлошије рангирани порази Узастопно одиграних партија Мање од један сат између партија Највише времена проведено у игри diff --git a/translation/dest/perfStat/sv-SE.xml b/translation/dest/perfStat/sv-SE.xml index 29a8de328486b..7628592dc7c2b 100644 --- a/translation/dest/perfStat/sv-SE.xml +++ b/translation/dest/perfStat/sv-SE.xml @@ -22,10 +22,9 @@ från %1$s till %2$s Vinster i rad Förluster i rad - Längsta serie: %s + Längsta serie: %s Nuvarande serie: %s Högst rankade segrar - Lägst rankade förluster Partier som spelats i rad Mindre än en timme mellan partierna Längsta speltid diff --git a/translation/dest/perfStat/th-TH.xml b/translation/dest/perfStat/th-TH.xml index c00365253a8c4..b6243ea65484f 100644 --- a/translation/dest/perfStat/th-TH.xml +++ b/translation/dest/perfStat/th-TH.xml @@ -22,10 +22,9 @@ จาก %1$s ถึง %2$s การชนะต่อเนื่อง การแพ้ต่อเนื่อง - ค่าต่อเนื่องสูงสุด: %s + ค่าต่อเนื่องสูงสุด: %s ค่าต่อเนื่องปัจจุบัน: %s ชนะระดับคะแนนที่ดีที่สุด - แพ้ระดับคะแนนที่แย่ที่สุด เกมที่เล่นติดต่อกัน น้อยกว่าหนึ่งชั่วโมงระหว่างเกม เวลาที่ใช้เล่นสูงสุด diff --git a/translation/dest/perfStat/tr-TR.xml b/translation/dest/perfStat/tr-TR.xml index c638ea7876a90..de9a6672c4b49 100644 --- a/translation/dest/perfStat/tr-TR.xml +++ b/translation/dest/perfStat/tr-TR.xml @@ -22,10 +22,9 @@ %1$s tarihinden %2$s tarihine kadar Kazanma serisi Yenilgi serisi - En uzun seri: %s + En uzun seri: %s Mevcut seri: %s Destansı zaferler - Vahim yenilgiler Üst üste yapılan maçlar Maçlar arasında bir saatten az bir boşluk olmalı Oyun için harcanan en uzun süre diff --git a/translation/dest/perfStat/tt-RU.xml b/translation/dest/perfStat/tt-RU.xml index 020ecfbde42fa..4bd50a4e6857a 100644 --- a/translation/dest/perfStat/tt-RU.xml +++ b/translation/dest/perfStat/tt-RU.xml @@ -21,10 +21,9 @@ %1$s дан %2$s га Бер-артлы җиңүләр Бер-артлы җиңүлеләр - Иң озын бер-артлы: %s + Иң озын бер-артлы: %s Хәзерге бер-артлы: %s Иң яхшы рейтинглы җиңүләр - Иң начар рейтинглы җиңелүләр Уеннар рәттән уйналды Уеннар арасында бер сәгатьтән дә азрак Бер-артлы уйнаган максималь вакыт diff --git a/translation/dest/perfStat/uk-UA.xml b/translation/dest/perfStat/uk-UA.xml index 0f24ab789eb44..4bdfdf6053bdd 100644 --- a/translation/dest/perfStat/uk-UA.xml +++ b/translation/dest/perfStat/uk-UA.xml @@ -22,10 +22,9 @@ від %1$s до %2$s Серія перемог Серія поразок - Найдовша серія: %s + Найдовша серія: %s Поточна серія: %s Найкращі перемоги в рейтингових іграх - Найгірші поразки в рейтингових іграх Зіграно ігор поспіль Менше години між іграми Максимальний час, проведений у грі diff --git a/translation/dest/perfStat/vi-VN.xml b/translation/dest/perfStat/vi-VN.xml index 1f1b5ec45ad55..36076a4a1a911 100644 --- a/translation/dest/perfStat/vi-VN.xml +++ b/translation/dest/perfStat/vi-VN.xml @@ -22,10 +22,9 @@ từ %1$s đến %2$s Chuỗi thắng Chuỗi thua - Chuỗi dài nhất: %s + Chuỗi dài nhất: %s Chuỗi hiện tại: %s Ván thắng được cộng Elo nhiều nhất - Ván thua mất Elo tệ nhất Số ván cờ được chơi liên tục Ít hơn một giờ giữa các ván cờ Thời gian dài nhất đã chơi diff --git a/translation/dest/perfStat/zh-CN.xml b/translation/dest/perfStat/zh-CN.xml index 751e388a5506b..cebb87c439020 100644 --- a/translation/dest/perfStat/zh-CN.xml +++ b/translation/dest/perfStat/zh-CN.xml @@ -22,10 +22,9 @@ 自 %1$s 至 %2$s 连胜 连败 - 最长纪录: %s + 最长纪录: %s 当前纪录: %s 最佳胜利 - 最差负败 连续对局 棋局间隔一个小时以内 最长连续对局时间 diff --git a/translation/dest/perfStat/zh-TW.xml b/translation/dest/perfStat/zh-TW.xml index aba4cfb81984e..54d3636844e97 100644 --- a/translation/dest/perfStat/zh-TW.xml +++ b/translation/dest/perfStat/zh-TW.xml @@ -23,10 +23,9 @@ 從%1$s到%2$s 連勝場數 連敗場數 - 最長紀錄:%s + 最長紀錄:%s 目前記錄:%s 積分賽勝場之最強對手 - 積分賽敗場之最弱對手 連續奕棋場數 兩場間距不到一小時 最高奕棋時間 diff --git a/translation/dest/preferences/zh-CN.xml b/translation/dest/preferences/zh-CN.xml index d01e42a0673ff..fe6f98c78762c 100644 --- a/translation/dest/preferences/zh-CN.xml +++ b/translation/dest/preferences/zh-CN.xml @@ -49,7 +49,7 @@ 将王移到车上 用键盘输入棋步 用语音输入着法 - 吸附箭头到有效着 + 将箭头吸附到有效着法上 输棋、和棋后自动发送:“厉害,玩得不错!” 你的设置已保存。 在棋盘上滚动鼠标滚轮以回退 diff --git a/translation/dest/site/en-US.xml b/translation/dest/site/en-US.xml index 8151c15d6a524..ba9c722e6fd25 100644 --- a/translation/dest/site/en-US.xml +++ b/translation/dest/site/en-US.xml @@ -705,7 +705,8 @@ computer analysis, game chat and shareable URL. Next branch Toggle variation arrows Cycle previous/next variation - Toggle glyph annotations + Toggle move annotations + Toggle position annotations Variation arrows let you navigate without using the move list. play selected move New tournament diff --git a/translation/dest/site/nb-NO.xml b/translation/dest/site/nb-NO.xml index 56b482c23b3be..9ef0e6de1127b 100644 --- a/translation/dest/site/nb-NO.xml +++ b/translation/dest/site/nb-NO.xml @@ -418,6 +418,7 @@ Svart setter matt i ett trekk Prøv igjen Gjenoppretter forbindelsen + Frakoblet %s venn online %s venner online @@ -704,6 +705,7 @@ Skru variantpiler av eller på Endre til forrige/neste variant Skru symboler i kommentarer av eller på + Skru kommentarer for stillinger av eller på Variantpiler lar deg navigere uten å bruke notasjonslisten. spill valgt trekk Ny turnering diff --git a/translation/dest/site/sr-SP.xml b/translation/dest/site/sr-SP.xml index 328e1d753486a..3cd16c2a3124f 100644 --- a/translation/dest/site/sr-SP.xml +++ b/translation/dest/site/sr-SP.xml @@ -5,6 +5,7 @@ Да позовете неког да игра, дајте овaј линк Партија Завршена Чека се противник + Или допусти свом противнику да копира овај QR код Чека се Ваш потез %1$s ниво %2$s @@ -55,10 +56,13 @@ Тражи рачунарску анализу Компјутерска анализа Рачунарска анализа је доступна + Онемогућена компјутерска анализа Табла за анализирање Дубина %s Анализа помоћу сервера Рачунар се учитава... + Израчунавам потезе... + Грешка при учитавању машине Анализа у облаку Иди дубље Прикажи претњу @@ -68,6 +72,7 @@ Направи као главну линију Избриши одавде Промакни варијацију + Ископирај ПГН варијације Потез Губитак из варијанте Победа из варијанте @@ -90,13 +95,20 @@ Мат у %s полу-потеза Мат у %s полу-потеза + Заокружен DTZ50, на основу броја полупотеза до следећег узимања фигуре или потеза пешаком Партија није нађена + Достигнут максимални број потеза! Можда укључите више партија у менију за подешавања? Отваранја Претраживач отварања + Претраживач отварања/завршница %s претаживач отварања + Одиграј први потез који сугерише претраживач отварања/завршница Добитак спречен правилом о 50 потеза Пораз спречен правилом о 50 потеза + Победа или 50 потеза на основу претходне грешке + Пораз или 50 потеза на основу претходне грешке + Победа/пораз су гарантовани једино ако се после последњег узимања фигуре или потеза пешаком следи препоручена основна табела и то због могућег заокруживања DTZ вредности у Syzygy osnovnim tabelama. Све је спремно! Унеси PGN Обриши @@ -107,12 +119,14 @@ Отвори проуку Укључи Стрелица за најбољи потез + Прикажи стрелице за варијацију Линија за процену Више стрелица Процесори Меморија Бесконачна анализа Уклања ограничење дубине и греје рачунар + Менаџер машине Груба грешка Грешка Непрецизност @@ -143,6 +157,7 @@ Погледај у пуној величини Одјави се Пријави се + Остани пријављен Треба вам налог да бисте то урадили Региструјте се Игра уз асистенцију рачунара није дозвољена. Молимо Вас да не користите шаховске програме, базе података, и помоћ других играча. Отварање вишеструких налога такође није пожељно док ће прекомерно отварање налога резултирати бановањем. @@ -186,15 +201,38 @@ Промените корисничко име Само се величина слова може променити. На пример \"johndoe\" у \"JohnDoe\". Промените ваше корисничко име. Можете променити ваше корисничко име само једном и то само величину слова. + Постарај се да одабереш пристојно корисничко име. Касније га нећеш моћи променити, а налози са непристојним корисничким именима биће затворени! + Биће коришћено само аз ресетовање лозинке. Лозинка Промените лозинку Промени е-пошту Е-пошта Мењање лозинке Заборавили сте лозинку? + Ова лозинка је изузетно честа и сувише лака да се погоди. Не користите своје корисничко име као шифру. + Користио си исту лозинку на другом сајту и тај сајт је био хакован. Да бисмо обезбедили сигурност твог Lichess налога, неопходно је да поставимо нову лозинку. Хвала на разумевању. Напуштате Личесс + Никада немој користити своју Lichess лозинку на неком другом сајту! Настаби до %s + Немој користити лозинку коју ти је предложио неко други. Он ће је искористити да преузме твој налог. + Немој користити мејл адресу коју ти је предложио неко други. Он ће је искористити да преузме твој налог. + Помоћ око потврђивања мејл адресе + Ниси примио потврду на мејл пошто си се регистровао? + Које корисничко име си користио приликом регистрације? + Не можемо да пронађемо ниједног корисника са тим именом: %s. + Можеш користи то корисничко име за отварање новог налога + Послали смо мејл на %s. + Треба мало времена док не стигне. + Сачекај 5 минута и освежи своје поштанско сандуче. + Такође провери фасциклу са спам порукама, можда је тамо. Ако је ту, обележи поруку тако да није спам. + Ако ништа од овога не помаже, онда нам пошаљи овај мејл: + Ископирај горњи текст и пошаљи га на %s + Ускоро ћемо те контактирати како бисмо ти помогли да завршиш своју регистрацију. + Корисник %s је потврђен. + Можеш се сада пријавити као %s. + Није ти потребан мејл потврде. + Налог %s је затворен. Налог %s је регистрован без Е-поште. Ранг Ранг: %s @@ -316,6 +354,7 @@ Погледај турнир Повратак у турнир + Не можеш ремизирати пре 30. потеза на турниру играном према швајцарском систему. Тематски ≥ %s рангирана игра @@ -349,6 +388,7 @@ Бесплатни интернет шах. Играј сада у чистом окружењу. Без регистрације, реклама, захтеваних података. Играј шах ротив рачунара, пријатеља или насумичних противника. %1$s придружио/ла се тиму %2$s %1$s креирао/ла тим %2$s + стриминг започет %s је почео са приказивањем Просечан рејтинг Локација @@ -357,15 +397,19 @@ Примени Сачувај Табела + Сними тренутну позицију Партију као ГИФ Убаци FEN текст овде Убаци PGN текст овде + Или учитај PGN фајл Од позиције Настави одавде Проучи Увези игру Кад прекопирате партију у PGN-у, отвори се табла за поновно проигравање, рачунарска анализа, прозор за ћаскање и адреса странице коју можете поделити. + Варијације ће бити избрисане. Ако желиш да их сачуваш, увези PGN путем студије. + Овај PGN је јавно доступан. Ако желиш да партију увезеш као приватну, користи студију. %s увезена игра %s увезене игре @@ -379,6 +423,7 @@ Црни матирау једном потезу Покушај поново Поновно повезивање + Ван мреже %s пријатељ на мрежи %s пријатеља на мрежи @@ -388,6 +433,8 @@ Прати Праћен Не прати + Прати %s + Престани да пратиш %s Блокирај Блокиран Одблокирај @@ -449,12 +496,15 @@ Одиграно потеза Победе као бели Победе као црни + Проценат ремија Ремија Следећи %s турнир: Просечан противник Уређивач табле Постави таблу Популарна отварања + Позиције у завршници + Почетна позиција за шах960: %s Почетна позиција Уклони фигуре Учитај позицију @@ -467,11 +517,17 @@ Уредите профил Име Презиме + Постави своју значку + Значка + Постоји подешавање којим се сакривају све корисникове значке на читавом сајту. Биографија + Земља или регион Хвала! Линкови за социјалне медије Један УРЛ по линији. Нотација у реду + Како би сачувао и делио, размисли о томе да направиш студију. + Уклони потезе Претходно на Личес ТВ Играчи на мрежи Активни играчи @@ -510,14 +566,18 @@ Варање Увреда Трол + Манипулација рејтингом Остало Залијепите везу до игре и објасните шта није у реду са понашањем корисника. Немојте само рећи \"варао\", али реците како сте дошли до тог закључка. Ваша пријава ће бити обрађена брже ако је напишете на енглеском језику. Наведите барем једну везу игре у којој је играч варао. од %s + Увезао %s Ова тема је сада затворена Блог Белешке Овде напишите приватне белешке + Направи приватну белешку о овом кориснику + Још нема никаквих белешки Неисправно корисничко име или лозинка погрешна лозинка Неважећи аутентикациони код @@ -576,11 +636,18 @@ Заједница Алати додатак + Неправилна вредност Ово поље морате попунити Ова Е-пошта адреса је погрешна + Ова мејл адреса је неодговарајућа. Молим те провери и пробај поново. + Мејл адреса је погрешна или већ заузета + Ово је већ твоја мејл адреса + Мора имати барем %s знакова + Мора имати највише %s знакова Мора бити најманје %s Мора бити манје или једнако %s Ако je рејтинг ± %s + Само регистровани Само постојећи разговори Само пријатељи Опције @@ -610,8 +677,10 @@ Симултанке Домаћин Боја приређивача: %s + Незавршене симултанке Недавно креиране симултанке Покрени нову симултанку + Пријави се да би организовао или учествовао у симултанци Симултанка није пронађена Симултанка не постоји Врати се на почетну страну @@ -626,6 +695,8 @@ Фишерово подешавање сата. Што више играча примиш, више времена ће ти бити потребно. Можеш додати додатно време на свој сат да ти помогне савладати симултанку. Додатно време домаћина + Додај почетно време на свом сату за сваког играча који учествује у симултанци. + Додатно време домаћину за сваког играча против којег игра Личес турнири Најчешће постављена питања за арена турнире Време пре него турнир започне. @@ -634,6 +705,7 @@ Скраћенице на тастатури иди назад/напред иди на почетак/крај + Излистај одабрану варијанту покажи/сакриј коментаре отвори/затвори варијанту Нови турнир @@ -839,4 +911,45 @@ Враћено: %1$s %2$s рејтингових поена. Време ускоро изтиче! Преузми + Које фигуре има домаћин за сваку партију + Очекивано време почетка + Прикажи на %s + Покажи своју симултанку свима на %s. Онемогући за приватне симултанке. + Опис симултанке + Желиш ли нешто да саопштиш учесницима? + %s је на располагању за напреднију синтаксу. + Убаци URL партије или поглавља студије. + Према твојој локалној временској зони + Чет на турниру + Нема чета + Само за вође тимова + Само за чланове тимова + Кретање кроз листу потеза + Покрети мишем + Одабери анализу на свом компјутеру + Одабери анализу на свом компјутеру и на Lichess серверима + Одиграј најбољи потез који сугерише компјутер + Опције при анализи + Пређи на чет + Прикажи овај прозор за помоћ + Поново отвори свој налог + Ако си затворио налог, али си се после предомислио, имаш једну прилику да повратиш свој налог. + Ово ће радити само једном. + Ако си затворио налог по други пут, не постоји начин да га повратиш. + Мејл адреса повезана са налогом + Послали смо ти мејл са линком. + Код за приступ турниру + Сачекај! + Твоја партија са %s је у току. + Прекину партију + Предај партију + Не можеш започети нову партију све док ову не завршиш. + Од + До + Бодоване партије одигране на Lichess + Промени страну + Ако затвриш налог, твоја жалба ће бити поништена + Наши савети за организовање догађаја + Инструкције + Прикажи све diff --git a/translation/dest/site/vi-VN.xml b/translation/dest/site/vi-VN.xml index 5f0125d1fd052..5c806c48b951e 100644 --- a/translation/dest/site/vi-VN.xml +++ b/translation/dest/site/vi-VN.xml @@ -866,7 +866,7 @@ trò chuyện trong ván đấu và có một URL có thể chia sẻ công khai hãy thử trang trợ giúp Hãy chắc rằng bạn đã đọc %1$s quy tắc diễn đàn - Đề tài này đã bị đóng nên bạn không thể bình luận nữa. + Chủ đề này đã được lưu trữ và không thể trả lời được nữa. Gia nhập %1$s để đăng trong diễn đàn này Đội %1$s Bạn chưa thể đăng bài lên diễn đàn bây giờ. Hãy chơi vài ván đã! diff --git a/translation/dest/site/zh-CN.xml b/translation/dest/site/zh-CN.xml index fffb5f9dc777c..3e458cb984114 100644 --- a/translation/dest/site/zh-CN.xml +++ b/translation/dest/site/zh-CN.xml @@ -70,7 +70,7 @@ 做为主线 从此处开始删除 强制作为变着 - 复制变体的 PGN + 复制带变着的 PGN 着法 变体输了 变体胜利 @@ -114,7 +114,7 @@ 按厘兵损失 进入研讨室 启用 - 箭头指示最佳着 + 箭头指示最佳着法 显示变着箭头 显示局面评分 多线搜索 @@ -376,7 +376,7 @@ 研讨 导入棋局 粘贴PGN棋谱后可重放棋局、使用电脑分析、使用对局聊天室以及获得通往本局的链接。 - 变着分支将被删除。若要保存这些变着,请通过导入PGN棋谱创建一个研究。 + 变着分支将被删除。若要保存这些变着,请通过研讨导入 PGN。 该PGN(用以记录棋类游戏棋谱的文件格式)可被公众访问。私人导入游戏请用研究研究 %s盘导入的棋局 @@ -484,7 +484,7 @@ 社交媒体链接 每行一个URL。 紧凑显示棋谱 - 这便于保管和分享,以及考虑创建一项研讨。 + 如果要保管和分享,请考虑创建一项研讨。 清除着法储存 过去的 Lichess TV 在线棋手 @@ -655,9 +655,9 @@ 快捷键 后退/前进 跳到开始/结束 - 经历选定的变化 + 选择变着 显示/隐藏评论 - 进入/退出变着 + 进入或退出变着 请求电脑分析,并从你的失误中学习 下一个 (从你的失误中学习) 下一个漏着 @@ -665,9 +665,10 @@ 下一个失准着 上一个分支 下一个分行 - 切换变化箭头 - 循环切换上一个/下一个变化 - 切换符号标注 + 切换变着箭头 + 切换上一个或下一个变着 + 开启着法注释 + 开启局面注释 走已选的棋步 新锦标赛 国际象棋锦标赛均设有不同的时间限制和变体 @@ -696,12 +697,12 @@ 阅读我们的 %s 你和 Lichess 之间的网络延迟 Lichess 服务器上处理一步的时间 - 下载有注释的PGN + 下载有注释的 PGN 下载无注释的PGN 下载导入的棋局 比分表 你也可以用鼠标滚轮浏览棋局。 - 将鼠标移到电脑给出的变着上进行预览 + 移到电脑给出的变着上进行预览 按shift+左键单击或右键单击在棋盘上绘制圆圈和箭头。 允许其他人给您发私信 在论坛中被提及时接收通知 diff --git a/translation/dest/study/fr-FR.xml b/translation/dest/study/fr-FR.xml index 2c3cd5579de3c..95d1e18dfc9dd 100644 --- a/translation/dest/study/fr-FR.xml +++ b/translation/dest/study/fr-FR.xml @@ -53,7 +53,7 @@ Tous les membres SYNC demeurent sur la même position Partager les changements avec les spectateurs et les enregistrer sur le serveur En cours - Barres d’évaluation + Barre d’évaluation Premier Précédent Suivant @@ -85,7 +85,7 @@ Commentaire du chapitre épinglé Enregistrer le chapitre Effacer les annotations - Supprimer les variantes + Supprimer les variantes Supprimer le chapitre Supprimer ce chapitre ? Cette action est irréversible ! Effacer tous les commentaires et annotations dans ce chapitre ? diff --git a/translation/dest/timeago/zh-CN.xml b/translation/dest/timeago/zh-CN.xml index 653d8781cb3b7..e05588b9dacc3 100644 --- a/translation/dest/timeago/zh-CN.xml +++ b/translation/dest/timeago/zh-CN.xml @@ -24,10 +24,10 @@ 刚刚 - %s分钟前 + %s 分钟前 - %s小时前 + %s 小时前 %s 天前 @@ -39,7 +39,7 @@ %s 月前 - %s年前 + %s 年前 还剩 %s 分钟 From aea0cd7b76be36e944374b003fe2b390463d11f3 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Wed, 14 Feb 2024 08:42:23 +0100 Subject: [PATCH 39/39] fix cms page update --- modules/cms/src/main/CmsApi.scala | 2 +- modules/cms/src/main/CmsForm.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/cms/src/main/CmsApi.scala b/modules/cms/src/main/CmsApi.scala index b0af791569b8b..8fa1758a97765 100644 --- a/modules/cms/src/main/CmsApi.scala +++ b/modules/cms/src/main/CmsApi.scala @@ -37,7 +37,7 @@ final class CmsApi(coll: Coll, markup: CmsMarkup)(using Executor): def create(page: CmsPage): Funit = coll.insert.one(page).void def update(prev: CmsPage, data: CmsForm.CmsPageData)(using me: Me): Fu[CmsPage] = - val page = data update me + val page = data.update(prev, me) coll.update.one($id(page.id), page) inject page def delete(id: Id): Funit = coll.delete.one($id(id)).void diff --git a/modules/cms/src/main/CmsForm.scala b/modules/cms/src/main/CmsForm.scala index d312788587f6e..336ebb770e0cf 100644 --- a/modules/cms/src/main/CmsForm.scala +++ b/modules/cms/src/main/CmsForm.scala @@ -51,4 +51,4 @@ object CmsForm: by = user.id ) - def update(user: User) = create(user) + def update(prev: CmsPage, user: User) = create(user).copy(id = prev.id)